DrawMeshInstancedIndirect
Add a "draw mesh with indirect instancing" command.
Read time 16 minutesLast updated 5 days ago
Definition
- Type: Method
- Namespace: UnityEngine.Rendering
- Assembly: UnityEngine.CoreModule
DrawMeshInstancedIndirect(Mesh, int, Material, int, ComputeBuffer, int, MaterialPropertyBlock)
Add a "draw mesh with indirect instancing" command.
public void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, int shaderPass, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties)
Parameters
Which submesh of the mesh to draw. This only applies to meshes that are composed of several submeshes.
Which pass of the shader to use, or -1 which renders all passes.
A GPU buffer that provides rendering command arguments (See GraphicsBuffer.IndirectDrawIndexedArgs).
The offset into the buffer in bytes, where the draw arguments start.
Additional Material properties to apply onto the Material just before this Mesh is drawn. See MaterialPropertyBlock.
Remarks
This function renders multiple instances of the same Mesh, similar to Graphics.DrawMeshInstanced, but takes the rendering command arguments from .
bufferWithArgsYou can set up these command arguments with either the CPU or the GPU.
Use GraphicsBuffer.IndirectDrawIndexedArgs to set up the graphics buffer (instead of plain ints) as the layout of this structure can change depending on the platform. The should contain a single GraphicsBuffer.IndirectDrawIndexedArgs struct at the .
argsWithBufferargsOffsetThis function only works on platforms that support compute shaders.
The example script below will render a specified mesh 10 times using when attached to a camera.
DrawMeshInstancedIndirectusing UnityEngine;using UnityEngine.Rendering;[RequireComponent(typeof(Camera))]public class ExampleClass : MonoBehaviour{ public Material material; public Mesh mesh; private GraphicsBuffer bufferWithArgs; private GraphicsBuffer.IndirectDrawIndexedArgs[] bufferWithArgsData; private CommandBuffer cmd; void Start() { // Initialize the GPU-side argument buffer, as well as a CPU-side array to populate it. bufferWithArgs = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, GraphicsBuffer.IndirectDrawIndexedArgs.size); bufferWithArgsData = new GraphicsBuffer.IndirectDrawIndexedArgs[1]; // Create a material property block with an additional property that's fed to the shader. var matProps = new MaterialPropertyBlock(); matProps.SetMatrix("_ObjectToWorld", Matrix4x4.Translate(new Vector3(-4.5f, 0, 0))); // Populate the GPU-side argument buffer with draw command arguments. // This command will render 10 instances of the specified mesh. bufferWithArgsData[0] = new GraphicsBuffer.IndirectDrawIndexedArgs { indexCountPerInstance = mesh.GetIndexCount(0), instanceCount = 10, baseVertexIndex = 0, startIndex = 0, startInstance = 0, }; bufferWithArgs.SetData(bufferWithArgsData); // Record the indirect draw command onto a command buffer, and add it to the camera. // The command buffer is executed whenever the camera renders. cmd = new CommandBuffer(); cmd.DrawMeshInstancedIndirect(mesh, 0, material, 0, bufferWithArgs, 0, matProps); GetComponent<Camera>().AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmd); } void OnDestroy() { bufferWithArgs?.Release(); cmd?.Dispose(); }}
Use the example script with a material that uses the following shader:
Shader "ExampleShader"{ SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct v2f { float4 pos : SV_POSITION; float4 color : COLOR; }; float4x4 _ObjectToWorld; v2f vert(float4 vertex : POSITION, uint instanceID : SV_InstanceID) { v2f o; // Base the position of each instance on the instance ID, // so all the instances don't just render at the same position. float4 wpos = mul(_ObjectToWorld, vertex + float4(instanceID, 0, 0, 0)); o.pos = mul(UNITY_MATRIX_VP, wpos); // Base the color of each instance on the instance ID as well. // Instances will alternate between black and white color. o.color = instanceID & 1; return o; } float4 frag(v2f i) : SV_Target { return i.color; } ENDCG } }}
DrawMeshInstancedIndirect(Mesh, int, Material, int, ComputeBuffer, int)
Add a "draw mesh with indirect instancing" command.
public void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, int shaderPass, ComputeBuffer bufferWithArgs, int argsOffset)
Parameters
Which submesh of the mesh to draw. This only applies to meshes that are composed of several submeshes.
Which pass of the shader to use, or -1 which renders all passes.
A GPU buffer that provides rendering command arguments (See GraphicsBuffer.IndirectDrawIndexedArgs).
The offset into the buffer in bytes, where the draw arguments start.
Remarks
This function renders multiple instances of the same Mesh, similar to Graphics.DrawMeshInstanced, but takes the rendering command arguments from .
bufferWithArgsYou can set up these command arguments with either the CPU or the GPU.
Use GraphicsBuffer.IndirectDrawIndexedArgs to set up the graphics buffer (instead of plain ints) as the layout of this structure can change depending on the platform. The should contain a single GraphicsBuffer.IndirectDrawIndexedArgs struct at the .
argsWithBufferargsOffsetThis function only works on platforms that support compute shaders.
The example script below will render a specified mesh 10 times using when attached to a camera.
DrawMeshInstancedIndirectusing UnityEngine;using UnityEngine.Rendering;[RequireComponent(typeof(Camera))]public class ExampleClass : MonoBehaviour{ public Material material; public Mesh mesh; private GraphicsBuffer bufferWithArgs; private GraphicsBuffer.IndirectDrawIndexedArgs[] bufferWithArgsData; private CommandBuffer cmd; void Start() { // Initialize the GPU-side argument buffer, as well as a CPU-side array to populate it. bufferWithArgs = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, GraphicsBuffer.IndirectDrawIndexedArgs.size); bufferWithArgsData = new GraphicsBuffer.IndirectDrawIndexedArgs[1]; // Create a material property block with an additional property that's fed to the shader. var matProps = new MaterialPropertyBlock(); matProps.SetMatrix("_ObjectToWorld", Matrix4x4.Translate(new Vector3(-4.5f, 0, 0))); // Populate the GPU-side argument buffer with draw command arguments. // This command will render 10 instances of the specified mesh. bufferWithArgsData[0] = new GraphicsBuffer.IndirectDrawIndexedArgs { indexCountPerInstance = mesh.GetIndexCount(0), instanceCount = 10, baseVertexIndex = 0, startIndex = 0, startInstance = 0, }; bufferWithArgs.SetData(bufferWithArgsData); // Record the indirect draw command onto a command buffer, and add it to the camera. // The command buffer is executed whenever the camera renders. cmd = new CommandBuffer(); cmd.DrawMeshInstancedIndirect(mesh, 0, material, 0, bufferWithArgs, 0, matProps); GetComponent<Camera>().AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmd); } void OnDestroy() { bufferWithArgs?.Release(); cmd?.Dispose(); }}
Use the example script with a material that uses the following shader:
Shader "ExampleShader"{ SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct v2f { float4 pos : SV_POSITION; float4 color : COLOR; }; float4x4 _ObjectToWorld; v2f vert(float4 vertex : POSITION, uint instanceID : SV_InstanceID) { v2f o; // Base the position of each instance on the instance ID, // so all the instances don't just render at the same position. float4 wpos = mul(_ObjectToWorld, vertex + float4(instanceID, 0, 0, 0)); o.pos = mul(UNITY_MATRIX_VP, wpos); // Base the color of each instance on the instance ID as well. // Instances will alternate between black and white color. o.color = instanceID & 1; return o; } float4 frag(v2f i) : SV_Target { return i.color; } ENDCG } }}
DrawMeshInstancedIndirect(Mesh, int, Material, int, ComputeBuffer)
Add a "draw mesh with indirect instancing" command.
public void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, int shaderPass, ComputeBuffer bufferWithArgs)
Parameters
Which submesh of the mesh to draw. This only applies to meshes that are composed of several submeshes.
Which pass of the shader to use, or -1 which renders all passes.
A GPU buffer that provides rendering command arguments (See GraphicsBuffer.IndirectDrawIndexedArgs).
Remarks
This function renders multiple instances of the same Mesh, similar to Graphics.DrawMeshInstanced, but takes the rendering command arguments from .
bufferWithArgsYou can set up these command arguments with either the CPU or the GPU.
Use GraphicsBuffer.IndirectDrawIndexedArgs to set up the graphics buffer (instead of plain ints) as the layout of this structure can change depending on the platform. The should contain a single GraphicsBuffer.IndirectDrawIndexedArgs struct at the .
argsWithBufferargsOffsetThis function only works on platforms that support compute shaders.
The example script below will render a specified mesh 10 times using when attached to a camera.
DrawMeshInstancedIndirectusing UnityEngine;using UnityEngine.Rendering;[RequireComponent(typeof(Camera))]public class ExampleClass : MonoBehaviour{ public Material material; public Mesh mesh; private GraphicsBuffer bufferWithArgs; private GraphicsBuffer.IndirectDrawIndexedArgs[] bufferWithArgsData; private CommandBuffer cmd; void Start() { // Initialize the GPU-side argument buffer, as well as a CPU-side array to populate it. bufferWithArgs = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, GraphicsBuffer.IndirectDrawIndexedArgs.size); bufferWithArgsData = new GraphicsBuffer.IndirectDrawIndexedArgs[1]; // Create a material property block with an additional property that's fed to the shader. var matProps = new MaterialPropertyBlock(); matProps.SetMatrix("_ObjectToWorld", Matrix4x4.Translate(new Vector3(-4.5f, 0, 0))); // Populate the GPU-side argument buffer with draw command arguments. // This command will render 10 instances of the specified mesh. bufferWithArgsData[0] = new GraphicsBuffer.IndirectDrawIndexedArgs { indexCountPerInstance = mesh.GetIndexCount(0), instanceCount = 10, baseVertexIndex = 0, startIndex = 0, startInstance = 0, }; bufferWithArgs.SetData(bufferWithArgsData); // Record the indirect draw command onto a command buffer, and add it to the camera. // The command buffer is executed whenever the camera renders. cmd = new CommandBuffer(); cmd.DrawMeshInstancedIndirect(mesh, 0, material, 0, bufferWithArgs, 0, matProps); GetComponent<Camera>().AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmd); } void OnDestroy() { bufferWithArgs?.Release(); cmd?.Dispose(); }}
Use the example script with a material that uses the following shader:
Shader "ExampleShader"{ SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct v2f { float4 pos : SV_POSITION; float4 color : COLOR; }; float4x4 _ObjectToWorld; v2f vert(float4 vertex : POSITION, uint instanceID : SV_InstanceID) { v2f o; // Base the position of each instance on the instance ID, // so all the instances don't just render at the same position. float4 wpos = mul(_ObjectToWorld, vertex + float4(instanceID, 0, 0, 0)); o.pos = mul(UNITY_MATRIX_VP, wpos); // Base the color of each instance on the instance ID as well. // Instances will alternate between black and white color. o.color = instanceID & 1; return o; } float4 frag(v2f i) : SV_Target { return i.color; } ENDCG } }}
DrawMeshInstancedIndirect(Mesh, int, Material, int, GraphicsBuffer, int, MaterialPropertyBlock)
Add a "draw mesh with indirect instancing" command.
public void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, int shaderPass, GraphicsBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties)
Parameters
Which submesh of the mesh to draw. This only applies to meshes that are composed of several submeshes.
Which pass of the shader to use, or -1 which renders all passes.
A GPU buffer that provides rendering command arguments (See GraphicsBuffer.IndirectDrawIndexedArgs).
The offset into the buffer in bytes, where the draw arguments start.
Additional Material properties to apply onto the Material just before this Mesh is drawn. See MaterialPropertyBlock.
Remarks
This function renders multiple instances of the same Mesh, similar to Graphics.DrawMeshInstanced, but takes the rendering command arguments from .
bufferWithArgsYou can set up these command arguments with either the CPU or the GPU.
Use GraphicsBuffer.IndirectDrawIndexedArgs to set up the graphics buffer (instead of plain ints) as the layout of this structure can change depending on the platform. The should contain a single GraphicsBuffer.IndirectDrawIndexedArgs struct at the .
argsWithBufferargsOffsetThis function only works on platforms that support compute shaders.
The example script below will render a specified mesh 10 times using when attached to a camera.
DrawMeshInstancedIndirectusing UnityEngine;using UnityEngine.Rendering;[RequireComponent(typeof(Camera))]public class ExampleClass : MonoBehaviour{ public Material material; public Mesh mesh; private GraphicsBuffer bufferWithArgs; private GraphicsBuffer.IndirectDrawIndexedArgs[] bufferWithArgsData; private CommandBuffer cmd; void Start() { // Initialize the GPU-side argument buffer, as well as a CPU-side array to populate it. bufferWithArgs = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, GraphicsBuffer.IndirectDrawIndexedArgs.size); bufferWithArgsData = new GraphicsBuffer.IndirectDrawIndexedArgs[1]; // Create a material property block with an additional property that's fed to the shader. var matProps = new MaterialPropertyBlock(); matProps.SetMatrix("_ObjectToWorld", Matrix4x4.Translate(new Vector3(-4.5f, 0, 0))); // Populate the GPU-side argument buffer with draw command arguments. // This command will render 10 instances of the specified mesh. bufferWithArgsData[0] = new GraphicsBuffer.IndirectDrawIndexedArgs { indexCountPerInstance = mesh.GetIndexCount(0), instanceCount = 10, baseVertexIndex = 0, startIndex = 0, startInstance = 0, }; bufferWithArgs.SetData(bufferWithArgsData); // Record the indirect draw command onto a command buffer, and add it to the camera. // The command buffer is executed whenever the camera renders. cmd = new CommandBuffer(); cmd.DrawMeshInstancedIndirect(mesh, 0, material, 0, bufferWithArgs, 0, matProps); GetComponent<Camera>().AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmd); } void OnDestroy() { bufferWithArgs?.Release(); cmd?.Dispose(); }}
Use the example script with a material that uses the following shader:
Shader "ExampleShader"{ SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct v2f { float4 pos : SV_POSITION; float4 color : COLOR; }; float4x4 _ObjectToWorld; v2f vert(float4 vertex : POSITION, uint instanceID : SV_InstanceID) { v2f o; // Base the position of each instance on the instance ID, // so all the instances don't just render at the same position. float4 wpos = mul(_ObjectToWorld, vertex + float4(instanceID, 0, 0, 0)); o.pos = mul(UNITY_MATRIX_VP, wpos); // Base the color of each instance on the instance ID as well. // Instances will alternate between black and white color. o.color = instanceID & 1; return o; } float4 frag(v2f i) : SV_Target { return i.color; } ENDCG } }}
DrawMeshInstancedIndirect(Mesh, int, Material, int, GraphicsBuffer, int)
Add a "draw mesh with indirect instancing" command.
public void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, int shaderPass, GraphicsBuffer bufferWithArgs, int argsOffset)
Parameters
Which submesh of the mesh to draw. This only applies to meshes that are composed of several submeshes.
Which pass of the shader to use, or -1 which renders all passes.
A GPU buffer that provides rendering command arguments (See GraphicsBuffer.IndirectDrawIndexedArgs).
The offset into the buffer in bytes, where the draw arguments start.
Remarks
This function renders multiple instances of the same Mesh, similar to Graphics.DrawMeshInstanced, but takes the rendering command arguments from .
bufferWithArgsYou can set up these command arguments with either the CPU or the GPU.
Use GraphicsBuffer.IndirectDrawIndexedArgs to set up the graphics buffer (instead of plain ints) as the layout of this structure can change depending on the platform. The should contain a single GraphicsBuffer.IndirectDrawIndexedArgs struct at the .
argsWithBufferargsOffsetThis function only works on platforms that support compute shaders.
The example script below will render a specified mesh 10 times using when attached to a camera.
DrawMeshInstancedIndirectusing UnityEngine;using UnityEngine.Rendering;[RequireComponent(typeof(Camera))]public class ExampleClass : MonoBehaviour{ public Material material; public Mesh mesh; private GraphicsBuffer bufferWithArgs; private GraphicsBuffer.IndirectDrawIndexedArgs[] bufferWithArgsData; private CommandBuffer cmd; void Start() { // Initialize the GPU-side argument buffer, as well as a CPU-side array to populate it. bufferWithArgs = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, GraphicsBuffer.IndirectDrawIndexedArgs.size); bufferWithArgsData = new GraphicsBuffer.IndirectDrawIndexedArgs[1]; // Create a material property block with an additional property that's fed to the shader. var matProps = new MaterialPropertyBlock(); matProps.SetMatrix("_ObjectToWorld", Matrix4x4.Translate(new Vector3(-4.5f, 0, 0))); // Populate the GPU-side argument buffer with draw command arguments. // This command will render 10 instances of the specified mesh. bufferWithArgsData[0] = new GraphicsBuffer.IndirectDrawIndexedArgs { indexCountPerInstance = mesh.GetIndexCount(0), instanceCount = 10, baseVertexIndex = 0, startIndex = 0, startInstance = 0, }; bufferWithArgs.SetData(bufferWithArgsData); // Record the indirect draw command onto a command buffer, and add it to the camera. // The command buffer is executed whenever the camera renders. cmd = new CommandBuffer(); cmd.DrawMeshInstancedIndirect(mesh, 0, material, 0, bufferWithArgs, 0, matProps); GetComponent<Camera>().AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmd); } void OnDestroy() { bufferWithArgs?.Release(); cmd?.Dispose(); }}
Use the example script with a material that uses the following shader:
Shader "ExampleShader"{ SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct v2f { float4 pos : SV_POSITION; float4 color : COLOR; }; float4x4 _ObjectToWorld; v2f vert(float4 vertex : POSITION, uint instanceID : SV_InstanceID) { v2f o; // Base the position of each instance on the instance ID, // so all the instances don't just render at the same position. float4 wpos = mul(_ObjectToWorld, vertex + float4(instanceID, 0, 0, 0)); o.pos = mul(UNITY_MATRIX_VP, wpos); // Base the color of each instance on the instance ID as well. // Instances will alternate between black and white color. o.color = instanceID & 1; return o; } float4 frag(v2f i) : SV_Target { return i.color; } ENDCG } }}
DrawMeshInstancedIndirect(Mesh, int, Material, int, GraphicsBuffer)
Add a "draw mesh with indirect instancing" command.
public void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, int shaderPass, GraphicsBuffer bufferWithArgs)
Parameters
Which submesh of the mesh to draw. This only applies to meshes that are composed of several submeshes.
Which pass of the shader to use, or -1 which renders all passes.
A GPU buffer that provides rendering command arguments (See GraphicsBuffer.IndirectDrawIndexedArgs).
Remarks
This function renders multiple instances of the same Mesh, similar to Graphics.DrawMeshInstanced, but takes the rendering command arguments from .
bufferWithArgsYou can set up these command arguments with either the CPU or the GPU.
Use GraphicsBuffer.IndirectDrawIndexedArgs to set up the graphics buffer (instead of plain ints) as the layout of this structure can change depending on the platform. The should contain a single GraphicsBuffer.IndirectDrawIndexedArgs struct at the .
argsWithBufferargsOffsetThis function only works on platforms that support compute shaders.
The example script below will render a specified mesh 10 times using when attached to a camera.
DrawMeshInstancedIndirectusing UnityEngine;using UnityEngine.Rendering;[RequireComponent(typeof(Camera))]public class ExampleClass : MonoBehaviour{ public Material material; public Mesh mesh; private GraphicsBuffer bufferWithArgs; private GraphicsBuffer.IndirectDrawIndexedArgs[] bufferWithArgsData; private CommandBuffer cmd; void Start() { // Initialize the GPU-side argument buffer, as well as a CPU-side array to populate it. bufferWithArgs = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, GraphicsBuffer.IndirectDrawIndexedArgs.size); bufferWithArgsData = new GraphicsBuffer.IndirectDrawIndexedArgs[1]; // Create a material property block with an additional property that's fed to the shader. var matProps = new MaterialPropertyBlock(); matProps.SetMatrix("_ObjectToWorld", Matrix4x4.Translate(new Vector3(-4.5f, 0, 0))); // Populate the GPU-side argument buffer with draw command arguments. // This command will render 10 instances of the specified mesh. bufferWithArgsData[0] = new GraphicsBuffer.IndirectDrawIndexedArgs { indexCountPerInstance = mesh.GetIndexCount(0), instanceCount = 10, baseVertexIndex = 0, startIndex = 0, startInstance = 0, }; bufferWithArgs.SetData(bufferWithArgsData); // Record the indirect draw command onto a command buffer, and add it to the camera. // The command buffer is executed whenever the camera renders. cmd = new CommandBuffer(); cmd.DrawMeshInstancedIndirect(mesh, 0, material, 0, bufferWithArgs, 0, matProps); GetComponent<Camera>().AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmd); } void OnDestroy() { bufferWithArgs?.Release(); cmd?.Dispose(); }}
Use the example script with a material that uses the following shader:
Shader "ExampleShader"{ SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct v2f { float4 pos : SV_POSITION; float4 color : COLOR; }; float4x4 _ObjectToWorld; v2f vert(float4 vertex : POSITION, uint instanceID : SV_InstanceID) { v2f o; // Base the position of each instance on the instance ID, // so all the instances don't just render at the same position. float4 wpos = mul(_ObjectToWorld, vertex + float4(instanceID, 0, 0, 0)); o.pos = mul(UNITY_MATRIX_VP, wpos); // Base the color of each instance on the instance ID as well. // Instances will alternate between black and white color. o.color = instanceID & 1; return o; } float4 frag(v2f i) : SV_Target { return i.color; } ENDCG } }}