之前用超过两篇的篇长分析了GetSurfaceAndBuiltinData,现在回到Frag函数:
BSDFData bsdfData = ConvertSurfaceDataToBSDFData(input.positionSS.xy, surfaceData);
PreLightData preLightData = GetPreLightData(V, posInput, bsdfData);
这里重新计算了bsdfData和preLightData,没看到有宏参与,只能先默认Unity编译时有优化。
#ifdef _SURFACE_TYPE_TRANSPARENT
uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_TRANSPARENT;
#else
uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_OPAQUE;
#endif
在计算光照之前还有一个featureFlags,后面的宏定义在LightLoop.cs.hlsl:
#define LIGHT_FEATURE_MASK_FLAGS_OPAQUE (16642048)
#define LIGHT_FEATURE_MASK_FLAGS_TRANSPARENT (16510976)
这是一个24位flag,每一位都表示了一种feature。
接下来重点介绍LightLoop:
LightLoop定义在LightLoop.hlsl,代码过长,不放在文章里了,看新的结构体定义。
struct LightLoopContext
{
int sampleReflection;
HDShadowContext shadowContext;
float contactShadow; // Currently we support only one contact shadow per view
float shadowValue; // Stores the value of the cascade shadow map
};
同样定义在LightLoop.hlsl,里面套了个HDShadowContext:
struct HDShadowContext
{
StructuredBuffer<HDShadowData> shadowDatas;
HDDirectionalShadowData directionalShadowData;
};
定义在HDShadowContext.hlsl,又套了两个娃:
struct HDShadowData
{
float3 rot0;
float3 rot1;
float3 rot2;
float3 pos;
float4 proj;
float2 atlasOffset;
float edgeTolerance;
int flags;
float4 zBufferParam;
float4 shadowMapSize;
float4 viewBias;
float3 normalBias;
float _padding;
float4 shadowFilterParams0;
float4x4 shadowToWorld;
};
struct HDDirectionalShadowData
{
float4 sphereCascades[4];
float4 cascadeDirection;
float cascadeBorders[4];
};
定义在HDShadowManager.cs.hlsl。
以后就不写定义在哪个文件里了。
LightLoopContext context;
context.shadowContext = InitShadowContext();
context.contactShadow = InitContactShadow(posInput);
context.shadowValue = 1;
context.sampleReflection = 0;
LightLoop一开始声明并初始化了LightLoopContext。
HDShadowContext InitShadowContext()
{
HDShadowContext sc;
sc.shadowDatas = _HDShadowDatas;
sc.directionalShadowData = _HDDirectionalShadowData[0];
return sc;
}
直接从CPU传的StructuredBuffer。
float InitContactShadow(PositionInputs posInput)
{
// For now we only support one contact shadow
// Contactshadow is store in Red Channel of _DeferredShadowTexture
// Note: When we ImageLoad outside of texture size, the value returned by Load is 0 (Note: On Metal maybe it clamp to value of texture which is also fine)
// We use this property to have a neutral value for contact shadows that doesn't consume a sampler and work also with compute shader (i.e use ImageLoad)
// We store inverse contact shadow so neutral is white. So either we sample inside or outside the texture it return 1 in case of neutral
return 1.0 - LOAD_TEXTURE2D(_DeferredShadowTexture, posInput.positionSS).x;
}
获取计算好的contact shadow。
// First of all we compute the shadow value of the directional light to reduce the VGPR pressure
if (featureFlags & LIGHTFEATUREFLAGS_DIRECTIONAL)
{
// Evaluate sun shadows.
if (_DirectionalShadowIndex >= 0)
{
DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex];
// TODO: this will cause us to load from the normal buffer first. Does this cause a performance problem?
// Also, the light direction is not consistent with the sun disk highlight hack, which modifies the light vector.
float NdotL = dot(bsdfData.normalWS, -light.forward);
float3 shadowBiasNormal = GetNormalForShadowBias(bsdfData