Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Graphics.DrawMeshiInstancedIndirect Only Rendering 1 instance

Discussion in 'Shaders' started by RMLEVERTON, Jun 17, 2022.

  1. RMLEVERTON

    RMLEVERTON

    Joined:
    Dec 13, 2015
    Posts:
    1
    I am trying to use append buffers to control a dynamic list of locations for spawning grass meshes (and later other type of foliage). I have had a lot of trouble trying to get the append buffers working.

    I think I am on the right track with the code below, but only 1 mesh is being rendered at a time, flicking around which obviously isn't very helpful, but otherwise generally seeming to be following the sine wave threshold. I'm v new to shaders and have been trying to follow the Ned Makes Games and Acerola tutorials, and can see that this problem is solved when they do frustum culling, but I haven't yet been able to work out how to rework this for my purpose.

    The code is adapted from this forum post: https://forum.unity.com/threads/app...er-how-to-transfer-to-geometry-shader.664927/

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class AppendBuffer : MonoBehaviour
    4. {
    5.     public Material material;
    6.     public ComputeShader shader;
    7.     public int size = 8;
    8.  
    9.     public Mesh grassMesh;
    10.  
    11.     ComputeBuffer meshTriangles;
    12.     ComputeBuffer meshPositions;
    13.  
    14.     ComputeBuffer buffer, argBuffer;
    15.     Bounds bounds;
    16.  
    17.     Vector3[] buf;
    18.  
    19.     void Start()
    20.     {
    21.         int[] triangles = grassMesh.triangles;
    22.         meshTriangles = new ComputeBuffer(triangles.Length, sizeof(int));
    23.         meshTriangles.SetData(triangles);
    24.  
    25.         Vector3[] positions = grassMesh.vertices;
    26.         meshPositions = new ComputeBuffer(positions.Length, sizeof(float) * 3);
    27.         meshPositions.SetData(positions);
    28.  
    29.         material.SetBuffer("Triangles", meshTriangles);
    30.         material.SetBuffer("Positions", meshPositions);
    31.  
    32.         buffer = new ComputeBuffer(size * size * size, sizeof(float) * 3, ComputeBufferType.Append);
    33.         argBuffer = new ComputeBuffer(1, 5*sizeof(int), ComputeBufferType.IndirectArguments);
    34.         shader.SetBuffer(0, "buffer", buffer);
    35.         shader.SetFloat("size", size);
    36.         shader.SetFloat("time", Time.time);
    37.         shader.Dispatch(0, size / 8, size / 8, size / 8);
    38.         int[] args = new int[] { 0, 1, 0, 0, 0 };
    39.         argBuffer.SetData(args);
    40.         ComputeBuffer.CopyCount(buffer, argBuffer, 0);
    41.         argBuffer.GetData(args);
    42.         Debug.Log(args[0]+ "," + args[1]+ "," + args[2]+ "," + args[3]);
    43.         bounds = new Bounds(Vector3.zero, new Vector3(-1000, 100, 1000));
    44.     }
    45.     void Update()
    46.     {
    47.  
    48.         buffer.Release();
    49.         argBuffer.Release();
    50.  
    51.         buffer = new ComputeBuffer(size * size * size, sizeof(float) * 3, ComputeBufferType.Append);
    52.         buffer.SetCounterValue(0);
    53.         argBuffer = new ComputeBuffer(1, 5*sizeof(int), ComputeBufferType.IndirectArguments);
    54.  
    55.         shader.SetBuffer(0, "buffer", buffer);
    56.         shader.SetFloat("size", size);
    57.         shader.SetFloat("time", Time.time);
    58.  
    59.         shader.Dispatch(0, size / 8, size / 8, size / 8);
    60.         int[] args = new int[] { 0, 1, 0, 0, 0 };
    61.         argBuffer.SetData(args);
    62.         ComputeBuffer.CopyCount(buffer, argBuffer, 0);
    63.         buf = new Vector3[buffer.count];
    64.         buffer.GetData(buf);
    65.         Debug.Log(buf[0] + ", " + buf[1]);
    66.         argBuffer.GetData(args);
    67.         Debug.Log(args[0] + "," + args[1] + "," + args[2] + "," + args[3]);
    68.  
    69.         material.SetPass(0);
    70.         material.SetBuffer("buffer", buffer);
    71.         //Graphics.DrawProceduralIndirect(material, bounds, MeshTopology.Triangles, argBuffer);
    72.         Graphics.DrawMeshInstancedIndirect(grassMesh, 0, material, bounds, argBuffer);
    73.     }
    74.  
    75.  
    76.     void OnDestroy()
    77.     {
    78.         buffer.Release();
    79.         argBuffer.Release();
    80.     }
    81. }
    82.  
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "AppendBuffer"
    4. {
    5.     SubShader
    6.     {
    7.         Cull Off
    8.         Pass
    9.         {
    10.             CGPROGRAM
    11.             #pragma vertex VSMain
    12.             //#pragma geometry GSMain
    13.             #pragma fragment PSMain
    14.             #pragma target 5.0
    15.  
    16.             StructuredBuffer<float3> buffer;
    17.             StructuredBuffer<int> Triangles;
    18.             StructuredBuffer<float3> Positions;
    19.  
    20.             struct Structure
    21.             {
    22.                 float4 position : SV_Position;
    23.                 uint id : custom;
    24.             };
    25.  
    26.             Structure VSMain(uint id : SV_VertexID)
    27.             {
    28.                 Structure VS;
    29.  
    30.                 VS.position = UnityObjectToClipPos(float4(buffer[id], 1.0));
    31.                 VS.id = id;
    32.  
    33.                 return VS;
    34.             }
    35.  
    36.             float Sign(int x)
    37.             {
    38.                 return (x > 0) ? 1 : -1;
    39.             }
    40.  
    41.  
    42.             float4 PSMain(Structure PS) : SV_Target
    43.             {
    44.                
    45.                 return float4(1.0, 0, 0, 1.0);
    46.             }
    47.  
    48.             ENDCG
    49.         }
    50.     }
    51. }
    52.  
    Code (CSharp):
    1. #pragma kernel CSMain
    2.  
    3. AppendStructuredBuffer<float3> buffer;
    4. float size;
    5. uniform float time;
    6.  
    7. [numthreads(8, 8, 8)]
    8. void CSMain(uint3 id : SV_DispatchThreadID)
    9. {
    10.     if (sin(id.x + id.z + time) > 0.5) {
    11.         float3 center = float3(id.x, 0, id.z);
    12.         buffer.Append(center);
    13.     }
    14.  
    15. }
    16.