I’m trying to use Graphics.DrawMeshInstancedIndirect with a structured buffer in the shader. I just wanted to understand the argsOffset and if it works like i think it should.
Basically I have lets say 32 meshes, and those meshes will be called individually by Graphics.DrawMeshInstancedIndirect. I’ve built the visible list of meshes up into the structured buffer within the shader to modify their position and other attributes, i.e. no material property block.
So I wanted to confirm say i have a structured buffer of 3200 in length as an example, with each mesh having 100 visible instances of it, 32 * 100. If i were to draw the second mesh, would the startIndex of 100 for the argsOffset flow thru to the shader as the uint instanceID : SV_InstanceID variable?
Maybe it doesn’t work like i think it does? If anyone knows that would be great
Thanks Richard! So I suppose this won’t solve my problem. Do you or anyone else have a suggestion how to overcome my problem though?
I have a procedural tree generation program which can create many meshes
I cull and determine which meshes are visible and arrange them in a way so i know how many times i have to draw each mesh (by the way using ECS)
Now I know what I need to draw but I don’t want to limit myself with instancing using material property blocks i.e. 1023
I currently set the compute buffer array once with all meshes ordered in the array, so position 0 might have 10 trees, at index 10 we start a different mesh and render 200 trees etc.
So what would be the best way to draw this? I’m looking into material property blocks set buffer and seeing if that can help. What I was trying to do was set the compute buffer once, and for each mesh know exactly where to start in the compute buffer array by trying to offset the instance index per mesh draw call somehow if that makes sense.
I have many meshes and one material / shader. Really appreciate any suggestions anyone can provide.
The 5th argument of the args buffer is called “start instance location” and ought to be what you need. However, the way this value is interpreted on some platforms means it doesn’t adjust the instance ID like you would expect (eg DX11 uses it in a different way, and we can’t fix this within Unity because it’s how DX11 decided to use that parameter.
So, what i’m trying to say is, if you only care about a certain platform, you could try to use it and see if it works (eg i think it works on Metal).
But, the cross platform way to do this is to provide a value to the shader to add to the instance ID. To do this, call MyShader.SetInt(“InstanceOffset”, myOffset) before each draw call. (directly on the shader, or via a Material Property Block).
So simple hey… thanks very much. I’ll try it out, I thought I couldn’t do this because of how DrawMeshInstancedIndirect is apparently delayed so overwriting any shader values would mess things up. If that doesn’t work I’ll try the Material Property Block.
Oh and I should say I did try the “start instance location” before but didn’t work as I expected on Windows, weird stuff happening on the screen, flickering etc.
im currently experiencing strange behavior with Graphics.DrawMeshInstancedIndirect Indirect, the DrawMeshInstancedIndirect still rendering DrawCalls with 0 sets the number of instances.
this is what the Args buffer looks like [600,0,0,0,0,2034,14,0,0,0] and I pass (i * 5 * 4) to argsOffset.
I saw in your comment that the number of instances is set to the first index of the args buffer, which is not what the documentation says, am I missing something?
Thank you!
this is what the DrawMeshInstancedIndirect API displays on different devices:
On a Samsung Galaxy S10, S10+, and unity Editor
On Oneplus 2: (As you can see the Plane is visible when it’s instance count is set to 0 )
more details:
i just upgraded the Device to Android 8.1 (OpenGles 3.2) and the DrawMeshInstancedIndirect is still rendering objects with 0 value as instance count in the args buffer.
i found out that it draws 1 element of any drawcall request with 0 instance count.