DrawProcedual備忘録

はじめに

DrawProcedualを使用するモチベーションとしては,VertexShaderを用いたインスタンシングである.

ステップ

  • ComputeBufferを作成
 Vector3[] vertices = instancingTargetMesh.triangles
            .Select(i => instancingTargetMesh.vertices[i]).ToArray();


        this.vertexBuffer = new ComputeBuffer
            (this.instancingTargetMesh.triangles.Length, Marshal.SizeOf(typeof(Vector3)));
        this.vertexBuffer.SetData(vertices);
  • Materialにbufferを送信
  • DrawProcedualをする.

ここで頂点数とインスタンシングする数をしてしてあげる.

 Graphics.DrawProceduralNow(MeshTopology.Triangles,
                                this.instancingTargetMesh.triangles.Length,
                                this.numOfInstances);
  • shaderCode
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/Unlit/SimpleInstancing"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }

    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
        }

        LOD 100

        Pass
        {
            CGPROGRAM

            #pragma vertex vertexShader
            #pragma fragment fragmentShader
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct vertexOutput
            {
                float2 uv : TEXCOORD0;
                half4 color : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST; // need to use TRANSFORM_TEX

            StructuredBuffer<float3> _VertexBuffer;
            
            vertexOutput vertexShader (appdata input,
                                       uint vertexID : SV_VertexID,
                                       uint instanceID : SV_InstanceID)
            {
               
                input.vertex.xyz += _VertexBuffer[vertexID];
                input.vertex.x += (instanceID % 10) + (instanceID % 10) * 0.5;
                input.vertex.y += (instanceID / 10) + (instanceID / 10) * 0.5;

                vertexOutput output;
                output.vertex = UnityObjectToClipPos(input.vertex);
                output.uv = TRANSFORM_TEX(input.uv, _MainTex);
                output.color = half4(1, 0, 0, 1);

                return output;
            }

            fixed4 fragmentShader (vertexOutput input,
                                   uint primitiveID : SV_PrimitiveID) : SV_Target
            {  
                return input.color;
            }

            ENDCG
        }
    }
}