浏览代码

Fixed normal bias leading to light leaking with point shadows.

/RenderPassXR_Sandbox
uygar 7 年前
当前提交
303965c0
共有 8 个文件被更改,包括 78 次插入51 次删除
  1. 2
      Assets/ScriptableRenderPipeline/Core/Shadow/Shadow.cs
  2. 16
      Assets/ScriptableRenderPipeline/Fptl/LightingTemplate.hlsl
  3. 4
      Assets/ScriptableRenderPipeline/Fptl/ShadowDispatch.hlsl
  4. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/ShadowDispatch.hlsl
  5. 3
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  6. 12
      Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Shadow.hlsl
  7. 78
      Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  8. 10
      Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithmsCustom.hlsl

2
Assets/ScriptableRenderPipeline/Core/Shadow/Shadow.cs


// For lights with multiple faces, the first shadow data contains
// per light information, so not all fields contain valid data.
// Shader code must make sure to read per face data from per face entries.
sd.texelSizeRcp = new Vector2( m_WidthRcp, m_HeightRcp );
sd.texelSizeRcp = new Vector4( m_WidthRcp, m_HeightRcp, 1.0f / widths[0], 1.0f / heights[0] );
sd.PackShadowType( sr.shadowType, sanitizedAlgo );
sd.payloadOffset = payload.Count();
entries.AddUnchecked( sd );

16
Assets/ScriptableRenderPipeline/Fptl/LightingTemplate.hlsl


DirectionalLight lightData = g_dirLightData[i];
float atten = 1;
UnityLight light;
light.dir.xyz = mul((float3x3) g_mViewToWorld, -lightData.lightAxisZ).xyz;
float shadow = GetDirectionalShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, 0.0.xxx);
float shadow = GetDirectionalShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, normalize(light.dir.xyz));
UnityLight light;
light.dir.xyz = mul((float3x3) g_mViewToWorld, -lightData.lightAxisZ).xyz;
ints += EvalMaterial(light, ind);
}

}
atten *= angularAtt.w*(fProjVec>0.0); // finally apply this to the dist att.
UnityLight light;
light.dir.xyz = mul((float3x3) g_mViewToWorld, vL).xyz; //unity_CameraToWorld
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, 0.0.xxx);
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, float4(normalize(light.dir.xyz), dist));
UnityLight light;
light.dir.xyz = mul((float3x3) g_mViewToWorld, vL).xyz; //unity_CameraToWorld
ints += EvalMaterial(light, ind);

[branch]
if (shadowIdx >= 0)
{
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, vLw);
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, float4(vLw, dist));
atten *= shadow;
}

4
Assets/ScriptableRenderPipeline/Fptl/ShadowDispatch.hlsl


// example of overriding punctual lights
#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
{
// example for choosing the same algo
Texture2DArray tex = shadowContext.tex2DArray[0];

}
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
}

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/ShadowDispatch.hlsl


// example of overriding punctual lights
#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
{
#ifdef SHADOW_DISPATCH_USE_SEPARATE_PUNC_ALGOS
// example for choosing different algos for point and spot lights

return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L );
#endif
}
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
}

3
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


{
// TODO: make projector lights cast shadows.
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
float4 L_dist = { normalize( L.xyz ), length( unL ) };
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L_dist, posInput.unPositionSS);
shadow = lerp(1.0, shadow, lightData.shadowDimmer);
illuminance *= shadow;

12
Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Shadow.hlsl


// shadow sampling prototypes
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS );
// shadow sampling prototypes with screenspace info
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L );
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS );

// default dispatchers for the individual shadow types (with and without screenspace support)
// point/spot light shadows
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS )
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuationDefault( shadowContext, positionWS, normalWS, shadowDataIndex, L );
}

// if shadow dispatch is empty we'll fall back to default shadow sampling implementations
#ifndef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuationDefault( shadowContext, positionWS, normalWS, shadowDataIndex, L, unPositionSS );
}

78
Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl


//
// Point shadows
//
float EvalShadow_PointDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
float EvalShadow_PointDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float4 L )
ShadowData sd = shadowContext.shadowDatas[index];
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
float3 lpos = positionWS + L.xyz * L.w;
positionWS = biased_posWS;
int faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1;
int faceIndex = EvalShadow_GetCubeFaceID( L ) + 1;
ShadowData sd = shadowContext.shadowDatas[index + faceIndex];
sd = shadowContext.shadowDatas[index + faceIndex];
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
// get the algorithm

}
#define EvalShadow_PointDepth_( _samplerType ) \
float EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
float EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float4 L ) \
ShadowData sd = shadowContext.shadowDatas[index]; \
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
float3 lpos = positionWS + L.xyz * L.w; \
positionWS = biased_posWS; \
int faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1; \
int faceIndex = EvalShadow_GetCubeFaceID( L ) + 1; \
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; \
sd = shadowContext.shadowDatas[index + faceIndex]; \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \

ShadowData sd = shadowContext.shadowDatas[index]; \
uint payloadOffset = GetPayloadOffset( sd ); \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \

//
// Punctual shadows for Point and Spot
//
float EvalShadow_PunctualDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
float EvalShadow_PunctualDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float4 L )
ShadowData sd = shadowContext.shadowDatas[index];
UnpackShadowType( shadowContext.shadowDatas[index].shadowType, shadowType );
UnpackShadowType( sd.shadowType, shadowType );
faceIndex = EvalShadow_GetCubeFaceID( L ) + 1;
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
float3 lpos = positionWS + L.xyz * L.w;
positionWS = biased_posWS;
faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1;
else
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
ShadowData sd = shadowContext.shadowDatas[index + faceIndex];
sd = shadowContext.shadowDatas[index + faceIndex];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
// sample the texture according to the given algorithm

UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
}
return SampleShadow_SelectAlgorithm(shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx);
}
float EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
float EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float4 L ) \
ShadowData sd = shadowContext.shadowDatas[index]; \
UnpackShadowType( shadowContext.shadowDatas[index].shadowType, shadowType ); \
UnpackShadowType( sd.shadowType, shadowType ); \
faceIndex = EvalShadow_GetCubeFaceID( L ) + 1; \
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
float3 lpos = positionWS + L.xyz * L.w; \
positionWS = biased_posWS; \
faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1; \
else \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; \
sd = shadowContext.shadowDatas[index + faceIndex]; \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \

float EvalShadow_CascadedDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
{
ShadowData sd = shadowContext.shadowDatas[index];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// load the right shadow data for the current face
float4 dirShadowSplitSpheres[4];
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres );

ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );

#define EvalShadow_CascadedDepth_( _samplerType ) \
float EvalShadow_CascadedDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
{ \
ShadowData sd = shadowContext.shadowDatas[index]; \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
\
/* load the right shadow data for the current face */ \
float4 dirShadowSplitSpheres[4]; \
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); \

\
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \

10
Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithmsCustom.hlsl


float EvalShadow_CascadedMoment( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
{
ShadowData sd = shadowContext.shadowDatas[shadowDataIndex];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// load the right shadow data for the current face
float4 dirShadowSplitSpheres[4];
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, shadowDataIndex, dirShadowSplitSpheres );

ShadowData sd = shadowContext.shadowDatas[shadowDataIndex + 1 + shadowSplitIndex];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get the shadowmap data for the correct cascade
sd = shadowContext.shadowDatas[shadowDataIndex + 1 + shadowSplitIndex];
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );

正在加载...
取消
保存