Graphics.DrawProceduralで好きな形状のポリゴンを描画

Graphics.DrawProceduralを使って、
Meshではないポリゴンを描画するサンプルです。
Meshじゃないので変形が楽。indexの数指定出来るので、OpenGL直叩きしてた頃のように可変数のポリゴン描ける。自前でライン描画したい時とかに使えそう。

一応影にも対応させておいた。

ただし現状WebGLでは使えない。StructuredBufferが未対応のため。Graphics.RenderPrimitiveも同様の理由で使えない。

自分用備忘録なので細かい説明は省略します。

```Test.cs
///
/// @file   Test.cs
/// @author Kyosei Yukimoto <kochiyukimoto@gmail.com>
/// @date   
///
/// @brief　プリミティブ描画実験
///
using UnityEngine;

namespace ProjectMain
{
    public class Test : MonoBehaviour
    {
        // inspector
        [SerializeField] string LayerName = "Default";
        [SerializeField] Material Material;
        [SerializeField] float BoundsSize = 1000;

        // material
        MaterialPropertyBlock MaterialProps;

        // data
        GraphicsBuffer Triangles;
        ComputeBuffer Positions;
        ComputeBuffer UVs;
        int Layer;

        // OnDestroy
        void OnDestroy()
        {
            // dispose
            UVs?.Dispose();
            UVs = null;
            Positions?.Dispose();
            Positions = null;
            Triangles?.Dispose();
            Triangles = null;
            MaterialProps = null;
        }

        // Start
        void Start()
        {
            // material
            MaterialProps = new MaterialPropertyBlock();

            // レイヤー
            Layer = LayerMask.NameToLayer(LayerName);

            // IndexBuffer
            int[] indices =
            {
                0, 2, 1,
            };
            Triangles = new GraphicsBuffer(GraphicsBuffer.Target.Structured, indices.Length, sizeof(int));
            Triangles.SetData(indices);

            // vertices
            Vector3[] vertices =
            {
                new Vector3(-1, 0, 0),
                new Vector3( 1, 0, 0),
                new Vector3( 1, 1, 0),
            };
            Positions = new ComputeBuffer(vertices.Length, sizeof(float) * 3, ComputeBufferType.Default, ComputeBufferMode.SubUpdates);
            Positions.SetData(vertices);
            MaterialProps.SetBuffer("_Positions", Positions);

            // uvs
            Vector2[] uvs =
            {
                new Vector2(0, 0),
                new Vector2(1, 0),
                new Vector2(1, 1),
            };
            UVs = new ComputeBuffer(uvs.Length, sizeof(float) * 2);
            UVs.SetData(uvs);
            MaterialProps.SetBuffer("_UVs", UVs);
        }


        // Update
        void Update()
        {
            // 変形実験
            if (Input.GetKeyDown(KeyCode.UpArrow)) {
                var vertices = Positions.BeginWrite<Vector3>(0, Positions.count);
                vertices[2] += Vector3.up;
                Positions.EndWrite<Vector3>(Positions.count);
            }

            // 描画
            var bounds = new Bounds(ThisTransform.position, Vector3.one * BoundsSize);
            MaterialProps.SetMatrix("_ObjectToWorld", Matrix4x4.TRS(transform.position, transform.rotation, transform.lossyScale));
            Graphics.DrawProcedural(Material, bounds, MeshTopology.Triangles, Triangles, Triangles.count, 1, Main.MainCamera, MaterialProps, UnityEngine.Rendering.ShadowCastingMode.On, true, Layer);
        }
    }
}
```
```Test.shader
Shader "ProjectMain/Test"
{
    Properties
    {
        [MainTexture] _BaseMap ("BaseMap", 2D) = "white" {}
        [MainColor] _BaseColor("BaseColor", Color) = (1, 1, 1, 1)
        _ShadowAlpha("ShadowAlpha", float) = 1
    }
    SubShader
    {
        Tags {
            "RenderType"="Opaque"
            "RenderPipeline"="UniversalPipeline" // Unity2021では "RenderPipeline"="UniversalRenderPipeline" だったような
            "Queue"="Geometry"
        }
        
        Pass
        {
            Tags { "LightMode"="UniversalForward" }

            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
            #pragma multi_compile _ _SHADOWS_SOFT

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 posWS : TEXCOORD0;
                float fogFactor: TEXCOORD1;
                float2 uv : TEXCOORD2;
            };

            StructuredBuffer<float3> _Positions;
            StructuredBuffer<float2> _UVs;
            float4x4 _ObjectToWorld;
            float4 _BaseColor;
            float _ShadowAlpha;
            sampler2D _BaseMap;
            float4 _BaseMap_ST;

            v2f vert(uint vertexID: SV_VertexID, uint instanceID : SV_InstanceID)
            {
                v2f o;
                float3 pos = _Positions[vertexID];
                float2 uv = _UVs[vertexID];
                o.posWS = mul(_ObjectToWorld, float4(pos, 1)).xyz;
                o.vertex = TransformWorldToHClip(o.posWS);
                o.fogFactor = ComputeFogFactor(o.vertex.z);
                o.uv = TRANSFORM_TEX(uv, _BaseMap);
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {
                float4 shadowCoord = TransformWorldToShadowCoord(i.posWS);
                Light mainLight = GetMainLight(shadowCoord);
                half shadow = mainLight.shadowAttenuation;
                Light addLight0 = GetAdditionalLight(0, i.posWS);
                shadow *= addLight0.shadowAttenuation;
                float4 col = tex2D(_BaseMap, i.uv) * _BaseColor;
                shadow = 1 - (1 - shadow) * _ShadowAlpha;
                col.rgb *= shadow;
                col.rgb = MixFog(col.rgb, i.fogFactor);
                return col;
            }
            ENDHLSL
        }

        Pass
        {
            Tags { "LightMode"="ShadowCaster" }

            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_shadowcaster

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            StructuredBuffer<float3> _Positions;
            float4x4 _ObjectToWorld;

            v2f vert(uint vertexID: SV_VertexID, uint instanceID : SV_InstanceID)
            {
                v2f o;
                float3 pos = _Positions[vertexID];
                float3 posWS = mul(_ObjectToWorld, float4(pos, 1)).xyz;
                o.vertex = TransformWorldToHClip(posWS);
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {
                return float4(0, 0, 0, 1);
            }
            ENDHLSL
        }

        // Used for rendering shadowmaps
        UsePass "Universal Render Pipeline/Lit/ShadowCaster"
    }
}

```