要加载实例数据(例如变换矩阵),着色器需要定义 DOTS 实例化属性。以下是一个简单的 DOTS 实例化属性块示例:
UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
UNITY_DOTS_INSTANCED_PROP(float4, Color)
UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
要标记属性块的开头和结尾,请使用 UNITY_DOTS_INSTANCING_START 和 UNITY_DOTS_INSTANCING_END 宏以及块的名称。示例使用名称 MaterialPropertyMetadata。允许的块名称有三个:
着色器可以声明其中一个,因此 DOTS 实例化着色器可以具有零到三个这样的块。Unity 定义的着色器代码不使用 UserPropertyMetadata,因此能够保证此名称可免费使用。URP 和 HDRP 会为其提供的每个着色器定义 BuiltinPropertyMetadata,并为其中大多数着色器定义 MaterialPropertyMetadata,因此最好使用 UserPropertyMetadata。自定义着色器可以使用所有三个可能名称,甚至可以同时使用所有名称。
该代码块可以包含任意数量的 DOTS 实例化属性定义,格式如下:
UNITY_DOTS_INSTANCED_PROP(PropertyType, PropertyName)
PropertyType 可以是任何 HLSL 内置类型(如 uint、float4、float4x4 或 int2x4),布尔矢量除外,PropertyName 是 DOTS 实例化属性的名称。DOTS 实例化属性与常规材质属性完全独立,您可以为它们指定与其他常规材质属性相同的名称。这是可以实现的,因为 UNITY_DOTS_INSTANCED_PROP 宏会生成 Unity 识别的特殊常量名称,这些名称与其他属性名称并不冲突。Unity 提供的着色器为 DOTS 实例化属性提供与常规材质属性相同的名称,但您无需遵循此约定。
Unity 在内部为着色器提供了 32 位整数元数据值,用于着色器声明的每个 DOTS 实例化属性。在代码调用 BatchRendererGroup.AddBatch 创建与绘制关联的批次时,Unity 会设置元数据值。如果 Unity 未设置元数据值,则该值默认为 0。着色器还可以访问 ByteAddressBuffer unity_DOTSInstanceData,Unity 会将其设置为 GraphicsBuffer,它将作为参数传递给 BatchRendererGroup.AddBatch。此缓冲区通常是着色器加载实例数据的位置。多个批次可以共享单个 GraphicsBuffer,但每个批次也可以使用自己单独的 GraphicsBuffer 来 unity_DOTSInstanceData。
注意:Unity 不会自动提供任何 DOTS 实例化数据。您有责任确保每个批次的 unity_DOTSInstanceData 缓冲区包含正确的数据。实例数据必须包含 Unity 通常为游戏对象提供的许多属性,例如变换矩阵、光照探针系数和光照贴图纹理坐标。