rparams | Unity 用于渲染网格的参数。 |
mesh | 要渲染的网格。 |
commandBuffer | 提供渲染命令参数的命令缓冲区(参见 IndirectDrawIndexedArgs)。 |
commandCount | 在 commandBuffer 中要执行的渲染命令数量。 |
startCommand | 在 commandBuffer 中要执行的第一个命令。 |
使用 GPU 实例化和来自 commandBuffer
的渲染命令参数来渲染网格的多个实例。
此函数渲染相同网格的多个实例,类似于 Graphics.RenderMeshInstanced,但从 commandBuffer
获取渲染命令参数。您可以使用 CPU 或 GPU 设置这些命令参数。 commandBuffer
可以包含多个渲染命令,您可以在一次调用此方法时执行这些命令。在受支持的平台上,Unity 可以通过将单个多绘制渲染命令提交到低级 API 来进一步优化多命令调用的 CPU 性能。使用 IndirectDrawIndexedArgs 设置命令缓冲区(而不是简单的整数),因为此结构的布局可能会根据平台而有所不同。
此函数仅在支持 计算着色器 的平台上有效。
使用此函数使用自定义着色器和 GPU 控制的渲染参数多次绘制同一个网格。使用 RenderParams.worldBounds
定义边界以剔除和排序使用此方法渲染的几何体作为单个实体。
在着色器中的传递部分添加以下行以访问 UnityIndirect.cginc 中指定的命令、实例和顶点 ID。
#define UNITY_INDIRECT_DRAW_ARGS IndirectDrawIndexedArgs #include "UnityIndirect.cginc"
在着色器函数的开头添加以下行以设置 ID 访问函数
InitIndirectDrawArgs(0); // pass SV_DrawID semantic value here for multi-draw support
其他资源:RenderMeshInstanced。
以下示例执行两个间接渲染命令。每个命令渲染 10 个网格实例。关联的材质必须使用下面的自定义着色器
using UnityEngine;
public class ExampleClass : MonoBehaviour { public Material material; public Mesh mesh;
GraphicsBuffer commandBuf; GraphicsBuffer.IndirectDrawIndexedArgs[] commandData; const int commandCount = 2;
void Start() { commandBuf = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, commandCount, GraphicsBuffer.IndirectDrawIndexedArgs.size); commandData = new GraphicsBuffer.IndirectDrawIndexedArgs[commandCount]; }
void OnDestroy() { commandBuf?.Release(); commandBuf = null; }
void Update() { RenderParams rp = new RenderParams(material); rp.worldBounds = new Bounds(Vector3.zero, 10000*Vector3.one); // use tighter bounds for better FOV culling rp.matProps = new MaterialPropertyBlock(); rp.matProps.SetMatrix("_ObjectToWorld", Matrix4x4.Translate(new Vector3(-4.5f, 0, 0))); commandData[0].indexCountPerInstance = mesh.GetIndexCount(0); commandData[0].instanceCount = 10; commandData[1].indexCountPerInstance = mesh.GetIndexCount(0); commandData[1].instanceCount = 10; commandBuf.SetData(commandData); Graphics.RenderMeshIndirect(rp, mesh, commandBuf, commandCount); } }
使用以下示例着色器与上面的 C# 示例代码一起使用
Shader "ExampleShader" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag
#include "UnityCG.cginc" #define UNITY_INDIRECT_DRAW_ARGS IndirectDrawIndexedArgs #include "UnityIndirect.cginc"
struct v2f { float4 pos : SV_POSITION; float4 color : COLOR0; };
uniform float4x4 _ObjectToWorld;
v2f vert(appdata_base v, uint svInstanceID : SV_InstanceID) { InitIndirectDrawArgs(0); v2f o; uint cmdID = GetCommandID(0); uint instanceID = GetIndirectInstanceID(svInstanceID); float4 wpos = mul(_ObjectToWorld, v.vertex + float4(instanceID, cmdID, 0, 0)); o.pos = mul(UNITY_MATRIX_VP, wpos); o.color = float4(cmdID & 1 ? 0.0f : 1.0f, cmdID & 1 ? 1.0f : 0.0f, instanceID / float(GetIndirectInstanceCount()), 0.0f); return o; }
float4 frag(v2f i) : SV_Target { return i.color; } ENDCG } } }