Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    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.