Unity Instancing.hlsl
A.平台适配
UNITY_SUPPORT_INSTANCING
- SHADER_TARGET >= 35且D3D11/GLES3/GLCore/XboxOne/GameCore/PSSL/Vulkan/Metal/Switch
UNITY_SUPPORT_STEREO_INSTANCING
- D3D11/GLCore/GLES3/Vulkan
UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE
- D3D11/GLCore/GLES3/Metal/PSSL/Vulkan/Switch
undef UNITY_SUPPORT_INSTANCING
defined(SHADER_TARGET_SURFACE_ANALYSIS) && defined(UNITY_SUPPORT_INSTANCING)
B.instancing paths (根据绘制指令选择不同的Instance路径)
- UNITY_INSTANCING_ENABLED Defined if instancing path is taken.
- UNITY_PROCEDURAL_INSTANCING_ENABLED Defined if procedural instancing path is taken.
- UNITY_STEREO_INSTANCING_ENABLED Defined if stereo instancing path is taken.
- UNITY_ANY_INSTANCING_ENABLED Defined if any instancing path is taken
#if defined(UNITY_SUPPORT_INSTANCING) && defined(INSTANCING_ON)
#define UNITY_INSTANCING_ENABLED
#endif
#if defined(UNITY_SUPPORT_INSTANCING) && defined(PROCEDURAL_INSTANCING_ON)
#define UNITY_PROCEDURAL_INSTANCING_ENABLED
#endif
#if defined(UNITY_SUPPORT_INSTANCING) && defined(DOTS_INSTANCING_ON)
#define UNITY_DOTS_INSTANCING_ENABLED
#endif
#if defined(UNITY_SUPPORT_STEREO_INSTANCING) && defined(STEREO_INSTANCING_ON)
#define UNITY_STEREO_INSTANCING_ENABLED
#endif
#if defined(UNITY_INSTANCING_ENABLED) || defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) || defined(UNITY_DOTS_INSTANCING_ENABLED) || defined(UNITY_STEREO_INSTANCING_ENABLED)
#define UNITY_ANY_INSTANCING_ENABLED 1
#else
#define UNITY_ANY_INSTANCING_ENABLED 0
#endif
- UNITY_SUPPORT_INSTANCING 平台支持Instance的情况下,根据Instance的定义情况开启对应的InstancePath宏定义
[UNITY_INSTANCING_ENABLED/UNITY_PROCEDURAL_INSTANCING_ENABLED/UNITY_DOTS_INSTANCING_ENABLED] - UNITY_SUPPORT_STEREO_INSTANCING 平台支持Stereo Instance的情况下,根据Stereo Instance的定义情况开启
[UNITY_STEREO_INSTANCING_ENABLED] - instancing/procedural/dots procedural/stereo instancing
只要有开Instance都会开启[UNITY_ANY_INSTANCING_ENABLED]
C.Instance的CBUFFER_SCOPE Begin/End
- GLES3/GLCore/Metal/Vulkan
- UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(name): cbuffer name {
- UNITY_INSTANCING_CBUFFER_SCOPE_END: }
- 其他平台
- UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(name): CBUFFER_START(name)
- UNITY_INSTANCING_CBUFFER_SCOPE_END: CBUFFER_END
D.基本的instancing宏定义函数设置
- UNITY_VERTEX_INPUT_INSTANCE_ID
- 用来定义instance ID field在顶点着色器的input / output struct.
- UNITY_GET_INSTANCE_ID
- (全局Instance唯一Id) 用Input struct获取instance ID
#if UNITY_ANY_INSTANCING_ENABLED
// A global instance ID variable that functions can directly access.
static uint unity_InstanceID;
// Don‘t make UnityDrawCallInfo an actual CB on GL
#if !defined(SHADER_API_GLES3) && !defined(SHADER_API_GLCORE)
UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityDrawCallInfo)
#endif
int unity_BaseInstanceID;
int unity_InstanceCount;
#if !defined(SHADER_API_GLES3) && !defined(SHADER_API_GLCORE)
UNITY_INSTANCING_CBUFFER_SCOPE_END
#endif
#ifdef SHADER_API_PSSL
#define DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID uint instanceID;
#define UNITY_GET_INSTANCE_ID(input) _GETINSTANCEID(input)
#else
#define DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID uint instanceID : SV_InstanceID;
#define UNITY_GET_INSTANCE_ID(input) input.instanceID
#endif
#else
#define DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID
#endif // UNITY_INSTANCING_ENABLED || UNITY_PROCEDURAL_INSTANCING_ENABLED || UNITY_STEREO_INSTANCING_ENABLED
#if !defined(UNITY_VERTEX_INPUT_INSTANCE_0ID)
# define UNITY_VERTEX_INPUT_INSTANCE_ID DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID
#endif
- UNITY_ANY_INSTANCING_ENABLED[即任意Instance]
-
static uint unity_InstanceID;
-
Don‘t make UnityDrawCallInfo an actual CB on GL
- 对非GL(ES3/Core)平台上定义
- UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityDrawCallInfo)
- int unity_BaseInstanceID;
- int unity_InstanceCount;
- UNITY_INSTANCING_CBUFFER_SCOPE_END
- UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityDrawCallInfo)
- 对非GL(ES3/Core)平台上定义
-
DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID
- 在PS平台上定义
- uint instanceID;
- 其他平台
- uint instanceID : SV_InstanceID;
- 在PS平台上定义
-
UNITY_GET_INSTANCE_ID(input)
- 在PS平台上定义
- _GETINSTANCEID(input)
- 其他平台
- input.instanceID
- 在PS平台上定义
-
DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID 对没有定义UNITY_ANY_INSTANCING_ENABLED的情况置空
-
-
UNITY_VERTEX_INPUT_INSTANCE_ID
- 定义为 DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID
E.basic stereo instancing setups 跳过
- UNITY_VERTEX_OUTPUT_STEREO
- Declare stereo target eye field in vertex shader output struct.
- UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO
- Assign the stereo target eye.
- UNITY_TRANSFER_VERTEX_OUTPUT_STEREO
- Copy stero target from input struct to output struct. Used in vertex shader.
- UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX
F.UNITY_SETUP_INSTANCE_ID和UNITY_TRANSFER_INSTANCE_ID
////////////////////////////////////////////////////////
// - UNITY_SETUP_INSTANCE_ID Should be used at the very beginning of the vertex shader / fragment shader,
// so that succeeding code can have access to the global unity_InstanceID.
// Also procedural function is called to setup instance data.
// - UNITY_TRANSFER_INSTANCE_ID Copy instance ID from input struct to output struct. Used in vertex shader.
- 对任意的Instance
- 初步定义void UnitySetupInstanceID(uint inputInstanceID)给下面DEFAULT_UNITY_SETUP_INSTANCE_ID使用
- UNITY_STEREO_INSTANCING_ENABLED处理跳过
- unity_InstanceID = inputInstanceID + unity_BaseInstanceID;
#if UNITY_ANY_INSTANCING_ENABLED void UnitySetupInstanceID(uint inputInstanceID) { #ifdef UNITY_STEREO_INSTANCING_ENABLED #if !defined(SHADEROPTIONS_XR_MAX_VIEWS) || SHADEROPTIONS_XR_MAX_VIEWS <= 2 #if defined(SHADER_API_GLES3) // We must calculate the stereo eye index differently for GLES3 // because otherwise, the unity shader compiler will emit a bitfieldInsert function. // bitfieldInsert requires support for glsl version 400 or later. Therefore the // generated glsl code will fail to compile on lower end devices. By changing the // way we calculate the stereo eye index, we can help the shader compiler to avoid // emitting the bitfieldInsert function and thereby increase the number of devices we // can run stereo instancing on. unity_StereoEyeIndex = round(fmod(inputInstanceID, 2.0)); unity_InstanceID = unity_BaseInstanceID + (inputInstanceID >> 1); #else // stereo eye index is automatically figured out from the instance ID unity_StereoEyeIndex = inputInstanceID & 0x01; unity_InstanceID = unity_BaseInstanceID + (inputInstanceID >> 1); #endif #else unity_StereoEyeIndex = inputInstanceID % _XRViewCount; unity_InstanceID = unity_BaseInstanceID + (inputInstanceID / _XRViewCount); #endif #else unity_InstanceID = inputInstanceID + unity_BaseInstanceID; #endif }
- 定义DEFAULT_UNITY_SETUP_INSTANCE_ID(input)
- 对Procedural instance处理
- 检查Procedural函数没有就报错#error
- 定义void UNITY_INSTANCING_PROCEDURAL_FUNC()
- 定义DEFAULT_UNITY_SETUP_INSTANCE_ID为
- UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));
- UNITY_INSTANCING_PROCEDURAL_FUNC();
- 普通Instance
- UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));
- 对Procedural instance处理
#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED #ifndef UNITY_INSTANCING_PROCEDURAL_FUNC #error "UNITY_INSTANCING_PROCEDURAL_FUNC must be defined." #else void UNITY_INSTANCING_PROCEDURAL_FUNC(); // forward declaration of the procedural function #define DEFAULT_UNITY_SETUP_INSTANCE_ID(input) { UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input)); UNITY_INSTANCING_PROCEDURAL_FUNC();} #endif #else #define DEFAULT_UNITY_SETUP_INSTANCE_ID(input) { UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));} #endif
-
UNITY_TRANSFER_INSTANCE_ID(input, output)
- output.instanceID = UNITY_GET_INSTANCE_ID(input)
#define UNITY_TRANSFER_INSTANCE_ID(input, output) output.instanceID = UNITY_GET_INSTANCE_ID(input)
- 初步定义void UnitySetupInstanceID(uint inputInstanceID)给下面DEFAULT_UNITY_SETUP_INSTANCE_ID使用
- 对不是Instance的情况Fallback置空
#else #define DEFAULT_UNITY_SETUP_INSTANCE_ID(input) #define UNITY_TRANSFER_INSTANCE_ID(input, output) #endif
- 定义 UNITY_SETUP_INSTANCE_ID为
- DEFAULT_UNITY_SETUP_INSTANCE_ID(input)
#if !defined(UNITY_SETUP_INSTANCE_ID) #define UNITY_SETUP_INSTANCE_ID(input) DEFAULT_UNITY_SETUP_INSTANCE_ID(input) #endif
-
总结:
- UNITY_SETUP_INSTANCE_ID(input)
=> DEFAULT_UNITY_SETUP_INSTANCE_ID
=>1.Procedural
UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input))
UNITY_INSTANCING_PROCEDURAL_FUNC();
=>2.非Procedural
直接 UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input)); - UNITY_TRANSFER_INSTANCE_ID(input, output)
=>output.instanceID = UNITY_GET_INSTANCE_ID(input)
=>input.instanceID
- UNITY_SETUP_INSTANCE_ID(input)
G.instanced property arrays
- 对一般的Instance以及DotsInstance,根据Options设置对应宏参数
- UNITY_INSTANCED_ARRAY_SIZE[实例化数组大小]
- Options:UNITY_FORCE_MAX_INSTANCE_COUNT forcemaxcount
例如://#pragma instancing_options forcemaxcount:50 - Options:UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE
- Options:UNITY_MAX_INSTANCE_COUNT
- FallBack:
- Vulkan/Mobile/Switch:250
- 其他平台:500
//////////////////////////////////////////////////////// // instanced property arrays #if defined(UNITY_INSTANCING_ENABLED) || defined(UNITY_DOTS_INSTANCING_ENABLED) #ifdef UNITY_FORCE_MAX_INSTANCE_COUNT #define UNITY_INSTANCED_ARRAY_SIZE UNITY_FORCE_MAX_INSTANCE_COUNT #elif defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE) #define UNITY_INSTANCED_ARRAY_SIZE 2 // minimum array size that ensures dynamic indexing #elif defined(UNITY_MAX_INSTANCE_COUNT) #define UNITY_INSTANCED_ARRAY_SIZE UNITY_MAX_INSTANCE_COUNT #else #if (defined(SHADER_API_VULKAN) && defined(SHADER_API_MOBILE)) || defined(SHADER_API_SWITCH) #define UNITY_INSTANCED_ARRAY_SIZE 250 #else #define UNITY_INSTANCED_ARRAY_SIZE 500 #endif #endif
- Options:UNITY_FORCE_MAX_INSTANCE_COUNT forcemaxcount
- UNITY_INSTANCING_BUFFER_START/UNITY_INSTANCING_BUFFER_END定义
- Dots跳过
- 非Dots情况
- UNITY_INSTANCING_BUFFER_START(buf)
- UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityInstancing_##buf)
- UNITY_INSTANCING_BUFFER_END(arr)
- } arr##Array[UNITY_INSTANCED_ARRAY_SIZE]; UNITY_INSTANCING_CBUFFER_SCOPE_END
- UNITY_DEFINE_INSTANCED_PROP(type, var)
- type var;
- UNITY_ACCESS_INSTANCED_PROP(arr, var)
- arr##Array[unity_InstanceID].var
- Dots相关宏置空/实例化报错处理
- UNITY_INSTANCING_BUFFER_START(buf)
#if defined(UNITY_DOTS_INSTANCING_ENABLED) #define UNITY_INSTANCING_BUFFER_START(buf) UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityInstancing_##buf) #define UNITY_INSTANCING_BUFFER_END(arr) UNITY_INSTANCING_CBUFFER_SCOPE_END #define UNITY_DEFINE_INSTANCED_PROP(type, var) type var; #define UNITY_ACCESS_INSTANCED_PROP(arr, var) var #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityDOTSInstancing.hlsl" #else #define UNITY_INSTANCING_BUFFER_START(buf) UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityInstancing_##buf) struct{ #define UNITY_INSTANCING_BUFFER_END(arr) } arr##Array[UNITY_INSTANCED_ARRAY_SIZE]; UNITY_INSTANCING_CBUFFER_SCOPE_END #define UNITY_DEFINE_INSTANCED_PROP(type, var) type var; #define UNITY_ACCESS_INSTANCED_PROP(arr, var) arr##Array[unity_InstanceID].var #define UNITY_DOTS_INSTANCING_START(name) #define UNITY_DOTS_INSTANCING_END(name) #define UNITY_DOTS_INSTANCED_PROP(type, name) #define UNITY_ACCESS_DOTS_INSTANCED_PROP(type, var) var #define UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(type, metadata_underscore_var) This_macro_cannot_be_called_without_UNITY_DOTS_INSTANCING_ENABLED #define UNITY_ACCESS_DOTS_AND_TRADITIONAL_INSTANCED_PROP(type, arr, var) UNITY_ACCESS_INSTANCED_PROP(arr, var) #endif
- Options:UNITY_ASSUME_UNIFORM_SCALING
- UNITY_WORLDTOOBJECTARRAY_CB [1]
- UNITY_WORLDTOOBJECTARRAY_CB [0]
- 例如#pragma instancing_options assumeuniformscaling
- Options:Lod fade相关
- UNITY_INSTANCED_LOD_FADE/LOD_FADE_PERCENTAGE/LOD_FADE_CROSSFADE
- UNITY_USE_LODFADE_ARRAY
- UNITY_INSTANCED_LOD_FADE/LOD_FADE_PERCENTAGE/LOD_FADE_CROSSFADE
- Options:RENDERING_LAYER
- UNITY_INSTANCED_RENDERING_LAYER
- UNITY_USE_RENDERINGLAYER_ARRAY
- UNITY_INSTANCED_RENDERING_LAYER
- Options:UNITY_INSTANCED_LIGHTMAPSTS LightMap数组
- 如果开启LightMap[KeyWord:LIGHTMAP_ON]
- UNITY_USE_LIGHTMAPST_ARRAY
- 如果开启动态LightMap[KeyWord:DYNAMICLIGHTMAP_ON]
- UNITY_USE_DYNAMICLIGHTMAPST_ARRAY
- 如果开启LightMap[KeyWord:LIGHTMAP_ON]
- Options:UNITY_INSTANCED_SH 使用SH不使用LightMap
- 不使用动态Lightmap
- UNITY_USE_SHCOEFFS_ARRAYS 即使用SH数组
- SHADOWS_SHADOWMASK
- UNITY_USE_PROBESOCCLUSION_ARRAY ShadowMask使用SH+Occlusion数组
- 不使用动态Lightmap
// Put worldToObject array to a separate CB if UNITY_ASSUME_UNIFORM_SCALING is defined. Most of the time it will not be used. #ifdef UNITY_ASSUME_UNIFORM_SCALING #define UNITY_WORLDTOOBJECTARRAY_CB 1 #else #define UNITY_WORLDTOOBJECTARRAY_CB 0 #endif #if defined(UNITY_INSTANCED_LOD_FADE) && (defined(LOD_FADE_PERCENTAGE) || defined(LOD_FADE_CROSSFADE)) #define UNITY_USE_LODFADE_ARRAY #endif #if defined(UNITY_INSTANCED_RENDERING_LAYER) #define UNITY_USE_RENDERINGLAYER_ARRAY #endif #ifdef UNITY_INSTANCED_LIGHTMAPSTS #ifdef LIGHTMAP_ON #define UNITY_USE_LIGHTMAPST_ARRAY #endif #ifdef DYNAMICLIGHTMAP_ON #define UNITY_USE_DYNAMICLIGHTMAPST_ARRAY #endif #endif #if defined(UNITY_INSTANCED_SH) && !defined(LIGHTMAP_ON) #if !defined(DYNAMICLIGHTMAP_ON) #define UNITY_USE_SHCOEFFS_ARRAYS #endif #if defined(SHADOWS_SHADOWMASK) #define UNITY_USE_PROBESOCCLUSION_ARRAY #endif #endif
- 非Dots情况
- UNITY_INSTANCING_BUFFER_START(PerDraw0) CB:0
- 没定义UNITY_DONT_INSTANCE_OBJECT_MATRICES
- 定义unity_ObjectToWorldArray M矩阵数组
- 如果 UNITY_WORLDTOOBJECTARRAY_CB为0
- 定义unity_WorldToObjectArray I_M数组
- 如果使用了LodFade数组
- 定义 unity_LODFadeArray数组
- 复写 unity_LODFade
- 如果使用了RenderLayer数组
- 定义 unity_RenderingLayerArray数组
- 复写 unity_RenderingLayer
- HYBRID_V1_CUSTOM_ADDITIONAL_MATERIAL_VARS跳过,不清楚
- 没定义UNITY_DONT_INSTANCE_OBJECT_MATRICES
- UNITY_INSTANCING_BUFFER_END(unity_Builtins0)
#if !defined(UNITY_DOTS_INSTANCING_ENABLED) UNITY_INSTANCING_BUFFER_START(PerDraw0) #ifndef UNITY_DONT_INSTANCE_OBJECT_MATRICES UNITY_DEFINE_INSTANCED_PROP(float4x4, unity_ObjectToWorldArray) #if UNITY_WORLDTOOBJECTARRAY_CB == 0 UNITY_DEFINE_INSTANCED_PROP(float4x4, unity_WorldToObjectArray) #endif #endif #if defined(UNITY_USE_LODFADE_ARRAY) && defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE) UNITY_DEFINE_INSTANCED_PROP(float2, unity_LODFadeArray) #define unity_LODFade UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_LODFadeArray).xyxx #endif #if defined(UNITY_USE_RENDERINGLAYER_ARRAY) && defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE) UNITY_DEFINE_INSTANCED_PROP(float, unity_RenderingLayerArray) #define unity_RenderingLayer UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_RenderingLayerArray).xxxx #endif // TODO: Hybrid V1 compatibility, remove once Hybrid V1 is removed #if defined(UNITY_HYBRID_V1_INSTANCING_ENABLED) && defined(HYBRID_V1_CUSTOM_ADDITIONAL_MATERIAL_VARS) HYBRID_V1_CUSTOM_ADDITIONAL_MATERIAL_VARS #endif UNITY_INSTANCING_BUFFER_END(unity_Builtins0)
- UNITY_INSTANCING_BUFFER_START(PerDraw1)
- 没定义UNITY_DONT_INSTANCE_OBJECT_MATRICES且 UNITY_WORLDTOOBJECTARRAY_CB=1
- 定义unity_WorldToObjectArray数组
- 如果使用了LodFade数组
- 定义 unity_LODFadeArray数组
- 复写 unity_LODFade
- 如果使用了RenderLayer数组
- 定义 unity_RenderingLayerArray数组
- 复写 unity_RenderingLayer
- 没定义UNITY_DONT_INSTANCE_OBJECT_MATRICES且 UNITY_WORLDTOOBJECTARRAY_CB=1
- UNITY_INSTANCING_BUFFER_END(unity_Builtins1)
UNITY_INSTANCING_BUFFER_START(PerDraw1) #if !defined(UNITY_DONT_INSTANCE_OBJECT_MATRICES) && UNITY_WORLDTOOBJECTARRAY_CB == 1 UNITY_DEFINE_INSTANCED_PROP(float4x4, unity_WorldToObjectArray) #endif #if defined(UNITY_USE_LODFADE_ARRAY) && !defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE) UNITY_DEFINE_INSTANCED_PROP(float2, unity_LODFadeArray) #define unity_LODFade UNITY_ACCESS_INSTANCED_PROP(unity_Builtins1, unity_LODFadeArray).xyxx #endif #if defined(UNITY_USE_RENDERINGLAYER_ARRAY) && !defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE) UNITY_DEFINE_INSTANCED_PROP(float, unity_RenderingLayerArray) #define unity_RenderingLayer UNITY_ACCESS_INSTANCED_PROP(unity_Builtins1, unity_RenderingLayerArray).xxxx #endif UNITY_INSTANCING_BUFFER_END(unity_Builtins1)
- UNITY_INSTANCING_BUFFER_START(PerDraw2)
- 使用LightMap数组
- 定义unity_LightmapSTArray数组
- 定义unity_LightmapIndexArray数组
- 复写 unity_LightmapST
- 使用动态LightMap数组
- 定义 unity_DynamicLightmapSTArray数组
- 复写 unity_DynamicLightmapST
- 使用SH系数数组
- 定义 unity_LODFadeArray数组
- 复写 unity_LODFade
- 使用SH+Occlusion数组
- 定义 unity_SHArArray/unity_SHAgArray/unity_SHAbArray/unity_SHBrArray/unity_SHBgArray/unity_SHBbArray/unity_SHCArray数组
- 复写 unity_SHAr/unity_SHAg/unity_SHAb/unity_SHBr/unity_SHBg/unity_SHBb/unity_SHC
- 使用Occlusion数组
- 定义 unity_ProbesOcclusionArray 数组
- 复习 unity_ProbesOcclusion
- 使用LightMap数组
- UNITY_INSTANCING_BUFFER_END(unity_Builtins2)
UNITY_INSTANCING_BUFFER_START(PerDraw2) #ifdef UNITY_USE_LIGHTMAPST_ARRAY UNITY_DEFINE_INSTANCED_PROP(float4, unity_LightmapSTArray) UNITY_DEFINE_INSTANCED_PROP(float4, unity_LightmapIndexArray) #define unity_LightmapST UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_LightmapSTArray) #endif #ifdef UNITY_USE_DYNAMICLIGHTMAPST_ARRAY UNITY_DEFINE_INSTANCED_PROP(float4, unity_DynamicLightmapSTArray) #define unity_DynamicLightmapST UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_DynamicLightmapSTArray) #endif #ifdef UNITY_USE_SHCOEFFS_ARRAYS UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHArArray) UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHAgArray) UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHAbArray) UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHBrArray) UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHBgArray) UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHBbArray) UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHCArray) #define unity_SHAr UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHArArray) #define unity_SHAg UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHAgArray) #define unity_SHAb UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHAbArray) #define unity_SHBr UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHBrArray) #define unity_SHBg UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHBgArray) #define unity_SHBb UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHBbArray) #define unity_SHC UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHCArray) #endif #ifdef UNITY_USE_PROBESOCCLUSION_ARRAY UNITY_DEFINE_INSTANCED_PROP(half4, unity_ProbesOcclusionArray) #define unity_ProbesOcclusion UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_ProbesOcclusionArray) #endif UNITY_INSTANCING_BUFFER_END(unity_Builtins2) #endif
- UNITY_INSTANCING_BUFFER_START(PerDraw0) CB:0
- UNITY_DONT_INSTANCE_OBJECT_MATRICES对Dots处理跳过
- UNITY_DONT_INSTANCE_OBJECT_MATRICES复写M,I_M
- undef UNITY_MATRIX_M/UNITY_MATRIX_I_M
- UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY
- unity_Builtins0 [CB=0]
- unity_Builtins1 [CB=1]
- MODIFY_MATRIX_FOR_CAMERA_RELATIVE_RENDERING
- UNITY_MATRIX_M
复写 UNITY_MATRIX_M为ApplyCameraTranslationToMatrix(UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_ObjectToWorldArray))- 复写 UNITY_MATRIX_I_M为ApplyCameraTranslationToMatrix(UNITY_ACCESS_INSTANCED_PROP(UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY, unity_WorldToObjectArray))
- UNITY_MATRIX_I_M
- UNITY_MATRIX_M
- 复写UNITY_MATRIX_M为获取在unity_ObjectToWorldArray数组中对应Instance的值
- 复写UNITY_MATRIX_I_M为获取在unity_WorldToObjectArray数组中对应Instance的值
#if defined(UNITY_DOTS_INSTANCING_ENABLED) #undef UNITY_MATRIX_M #undef UNITY_MATRIX_I_M #ifdef MODIFY_MATRIX_FOR_CAMERA_RELATIVE_RENDERING #define UNITY_MATRIX_M ApplyCameraTranslationToMatrix(LoadDOTSInstancedData_float4x4_from_float3x4(UNITY_DOTS_INSTANCED_METADATA_NAME_FROM_MACRO(float3x4, Metadata_unity_ObjectToWorld))) #define UNITY_MATRIX_I_M ApplyCameraTranslationToInverseMatrix(LoadDOTSInstancedData_float4x4_from_float3x4(UNITY_DOTS_INSTANCED_METADATA_NAME_FROM_MACRO(float3x4, Metadata_unity_WorldToObject))) #else #define UNITY_MATRIX_M LoadDOTSInstancedData_float4x4_from_float3x4(UNITY_DOTS_INSTANCED_METADATA_NAME_FROM_MACRO(float3x4, Metadata_unity_ObjectToWorld)) #define UNITY_MATRIX_I_M LoadDOTSInstancedData_float4x4_from_float3x4(UNITY_DOTS_INSTANCED_METADATA_NAME_FROM_MACRO(float3x4, Metadata_unity_WorldToObject)) #endif #else #ifndef UNITY_DONT_INSTANCE_OBJECT_MATRICES #undef UNITY_MATRIX_M #undef UNITY_MATRIX_I_M // Use #if instead of preprocessor concatenation to avoid really hard to debug // preprocessing issues in some cases. #if UNITY_WORLDTOOBJECTARRAY_CB == 0 #define UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY unity_Builtins0 #else #define UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY unity_Builtins1 #endif #ifdef MODIFY_MATRIX_FOR_CAMERA_RELATIVE_RENDERING #define UNITY_MATRIX_M ApplyCameraTranslationToMatrix(UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_ObjectToWorldArray)) #define UNITY_MATRIX_I_M ApplyCameraTranslationToInverseMatrix(UNITY_ACCESS_INSTANCED_PROP(UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY, unity_WorldToObjectArray)) #else #define UNITY_MATRIX_M UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_ObjectToWorldArray) #define UNITY_MATRIX_I_M UNITY_ACCESS_INSTANCED_PROP(UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY, unity_WorldToObjectArray) #endif #endif #endif
- UNITY_INSTANCED_ARRAY_SIZE[实例化数组大小]
- 其他Instance情况
- Procedural instance
- 复写UNITY_INSTANCING_BUFFER_START/END为置空
- 复写UNITY_DEFINE_INSTANCED_PROP为普通静态变量
- static type var;
- 非instance情况
- 复写UNITY_INSTANCING_BUFFER_START/END为CBuffer
- CBUFFER_START(buf)/END
- 复写UNITY_DEFINE_INSTANCED_PROP为普通静态变量
- type var
- 复写UNITY_INSTANCING_BUFFER_START/END为CBuffer
- 复写UNITY_ACCESS_INSTANCED_PROP获取值方式为普通var
- var
// in procedural mode we don‘t need cbuffer, and properties are not uniforms #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED #define UNITY_INSTANCING_BUFFER_START(buf) #define UNITY_INSTANCING_BUFFER_END(arr) #define UNITY_DEFINE_INSTANCED_PROP(type, var) static type var; #else #define UNITY_INSTANCING_BUFFER_START(buf) CBUFFER_START(buf) #define UNITY_INSTANCING_BUFFER_END(arr) CBUFFER_END #define UNITY_DEFINE_INSTANCED_PROP(type, var) type var; #endif #define UNITY_ACCESS_INSTANCED_PROP(arr, var) var
- Procedural instance
-
总结:
- 这一段主要是根据不同的Instance Path定义实例化数组大小
- [普通Instance]
- UNITY_INSTANCING_BUFFER_START/END CBuffer Scope宏处理
- 根据Option定义宏参数然后影响CBuffer里生成的内容unity_Builtins0/unity_Builtins1/unity_Builtins2
- unity_Builtins0:CB=0 非UNITY_ASSUME_UNIFORM_SCALING
- unity_Builtins1:CB=1 UNITY_ASSUME_UNIFORM_SCALING
- unity_Builtins2:
- GI相关设置
- LightMapArray
- SHArray
- OcclusionArray
- GI相关设置
- M/I_M矩阵复写
- [其他Instance情况处理]
- Procedural instance 置空
- 不是实例化的变回普通的CBuffer Scope
H.One more thing
- 分析下普通Instance的Scope构造
UNITY_INSTANCING_BUFFER_START(buf)
UNITY_DEFINE_INSTANCED_PROP(type, var)
UNITY_DEFINE_INSTANCED_PROP(type, var)
UNITY_INSTANCING_BUFFER_END(arr)
UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityInstancing_##buf) struct{
type var;
type var;
} arr##Array[UNITY_INSTANCED_ARRAY_SIZE]; UNITY_INSTANCING_CBUFFER_SCOPE_END
[非GL平台]
CBUFFER_START(UnityInstancing_##buf)
struct{
type var;
type var;
} arr##Array[UNITY_INSTANCED_ARRAY_SIZE];
CBUFFER_END
例子:
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float4, _TestColor)
UNITY_INSTANCING_BUFFER_END(Props)
name of arr=buf=Props
[非GL平台]
CBUFFER_START(UnityInstancing_Props)
struct{
float4 _TestColor;
} PropsArray[UNITY_INSTANCED_ARRAY_SIZE];
CBUFFER_END
- 获取变量时:UNITY_ACCESS_INSTANCED_PROP(arr, var)
UNITY_ACCESS_INSTANCED_PROP(arr, var) =>arrArray[unity_InstanceID].var
例子:
UNITY_ACCESS_INSTANCED_PROP(Props, _TestColor) =>PropsArray[unity_InstanceID]._TestColor
- UNITY_SETUP_INSTANCE_ID和UNITY_TRANSFER_INSTANCE_ID(input, output)
- UNITY_SETUP_INSTANCE_ID(input)
=> DEFAULT_UNITY_SETUP_INSTANCE_ID
=>1.Procedural
UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));
UNITY_INSTANCING_PROCEDURAL_FUNC();
=>2.非Procedural
UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));
[非PS平台] UnitySetupInstanceID(input.instanceID);
unity_InstanceID = input.instanceID + unity_BaseInstanceID;
- UNITY_TRANSFER_INSTANCE_ID(input, output)
=>output.instanceID = UNITY_GET_INSTANCE_ID(input)
=>output.instanceID = input.instanceID