Search Unity

Resolved How to draw triangles using StructuredBuffers and Graphics.DrawProceduralNow?

Discussion in 'Universal Render Pipeline' started by TheGabelle, Feb 25, 2021.

  1. TheGabelle

    TheGabelle

    Joined:
    Aug 23, 2013
    Posts:
    242
    I am very new to writing shaders and attempting to draw an arbitrary set of triangles from rapidly updated procedural data. I want to use the shader like this:

    Code (CSharp):
    1. void Render()
    2. {
    3.       // set whatever buffer data is needed
    4.       _triangleMaterial.SetPass(0);
    5.       Graphics.DrawProceduralNow(MeshTopology.Triangles, _triangleCount * 3);
    6. }
    I'm struggling to create the shader. Instead of modifying a mesh, I'd like to write the data to structured buffers. For each triangle I want to pass three vertex positions, three vertex normals, three vertex colors, and three vertex uvs.
    Code (CSharp):
    1. StructuredBuffer<float3> positionsBuffer;
    2. StructuredBuffer<float3> normalsBuffer;
    3. StructuredBuffer<float2> uvsBuffer;
    4. StructuredBuffer<float4> colorsBuffer;
    What do I need to do within the shader to make it work?
     
  2. TheGabelle

    TheGabelle

    Joined:
    Aug 23, 2013
    Posts:
    242
    I got it to work. I forgot I needed to add the script specifically to the Camera GO instead of an empty GO.
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Rendering;
    6. public class TrianglesTest : MonoBehaviour
    7. {
    8.  
    9.     // Vertices Buffer
    10.     ComputeBuffer _verticesBuffer;
    11.  
    12.     static readonly int verticesBuffer = Shader.PropertyToID("verticesBuffer");
    13.  
    14.     public Vector4[] vertices;
    15.     public Material triangleMaterial;
    16.  
    17.     void Awake()
    18.     {
    19.         RenderPipelineManager.endFrameRendering += (arg1, arg2) => Render();
    20.     }
    21.  
    22.     void OnPostRender()
    23.     {
    24.         Render();
    25.     }
    26.  
    27.  
    28.     void OnDrawGizmos()
    29.     {
    30.         Render();
    31.     }
    32.  
    33.  
    34.     void CopyFromCpuToGpu()
    35.     {
    36.         if (_verticesBuffer == null || _verticesBuffer.count != vertices.Length)
    37.         {
    38.             if (_verticesBuffer != null)
    39.             {
    40.                 _verticesBuffer.Release();
    41.                 _verticesBuffer = null;
    42.             }
    43.  
    44.             _verticesBuffer = new ComputeBuffer(vertices.Length, 4*4);
    45.             triangleMaterial.SetBuffer(verticesBuffer, _verticesBuffer);
    46.         }
    47.  
    48.         _verticesBuffer.SetData(vertices, 0, 0, vertices.Length);
    49.     }
    50.  
    51.     internal void Render()
    52.     {
    53.         CopyFromCpuToGpu();
    54.         triangleMaterial.SetPass(0);
    55.         Graphics.DrawProceduralNow(MeshTopology.Triangles, vertices.Length);
    56.     }
    57. }
    Code (CSharp):
    1. Shader "BurstDrawTrianglesShader" {
    2.     Properties
    3.     {
    4.     }
    5.     SubShader
    6.     {
    7.         Tags {"RenderType" = "Opaque" "IgnoreProjector" = "True" "RenderPipeline" = "UniversalPipeline" "ShaderModel"="2.0"}
    8.         Cull Off
    9.  
    10.         Pass
    11.         {
    12.             Name "Unlit"
    13.  
    14.             HLSLPROGRAM
    15.             #pragma exclude_renderers gles gles3 glcore
    16.             #pragma target 4.5
    17.  
    18.             #pragma vertex vert
    19.             #pragma fragment frag
    20.  
    21.  
    22.             #include "UnityCG.cginc"
    23.  
    24.             uniform StructuredBuffer<float4> verticesBuffer;
    25.  
    26.             struct vtf
    27.             {
    28.                 float4 vertex : SV_POSITION;
    29.                    float4 color : TEXCOORD0;
    30.             };
    31.  
    32.             // color packed into float4.w (1 byte per RGBA channel)
    33.             float4 unpack(float i)
    34.             {
    35.                 return float4(i / 262144.0, i / 4096.0, i / 64.0, i) % 64.0 / 63;
    36.             }
    37.  
    38.             vtf vert(uint vid : SV_VertexID)
    39.             {
    40.                 vtf output;
    41.                 float4 pos = verticesBuffer[vid];
    42.                 output.vertex = mul(UNITY_MATRIX_VP, float4(pos.xyz, 1));
    43.                 output.color = unpack(pos.w);
    44.                 return output;
    45.             }
    46.  
    47.             half4 frag(vtf input) : SV_Target
    48.             {
    49.                 return input.color;
    50.             }
    51.             ENDHLSL
    52.         }
    53.     }
    54.     SubShader
    55.     {
    56.         Pass
    57.         {
    58.             CGPROGRAM
    59.  
    60.             #pragma vertex vert
    61.             #pragma fragment frag
    62.             #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
    63.             #pragma target 4.5
    64.  
    65.             #include "UnityCG.cginc"
    66.  
    67.             StructuredBuffer<float4> verticesBuffer;
    68.  
    69.             struct v2f
    70.             {
    71.                 float4 pos : SV_POSITION;
    72.                 float4 color : TEXCOORD0;
    73.             };
    74.  
    75.             float4 unpack(float i)
    76.             {
    77.                 return float4(i / 262144.0, i / 4096.0, i / 64.0, i) % 64.0 / 63;
    78.             }
    79.  
    80.             v2f vert(uint vid : SV_VertexID)
    81.             {
    82.                 v2f o;
    83.                 float4 pos = verticesBuffer[vid];
    84.                 o.pos = mul(UNITY_MATRIX_VP, float4(pos.xyz, 1));
    85.                 o.color = unpack(pos.w);
    86.                 return o;
    87.             }
    88.  
    89.             fixed4 frag(v2f i) : SV_Target
    90.             {
    91.                 return i.color;
    92.             }
    93.  
    94.             ENDCG
    95.         }
    96.     }
    97. }