浏览代码

Improve the quality of the auto-thickness results

/main
Evgenii Golubev 6 年前
当前提交
54ddb928
共有 2 个文件被更改,包括 96 次插入28 次删除
  1. 85
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  2. 39
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl

85
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl


return EvalShadow_GetTexcoords( sd, positionWS, ndc, perspProj );
}
uint2 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC, bool perspProj )
real2 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC, bool perspProj )
{
real4 posCS = EvalShadow_WorldToShadow( sd, positionWS, perspProj );
real2 posNDC = perspProj ? (posCS.xy / posCS.w) : posCS.xy;

return uint2( (posTC * sd.scaleOffset.xy + sd.scaleOffset.zw) * sd.textureSize.xy );
return posTC * sd.scaleOffset.xy + sd.scaleOffset.zw;
uint2 EvalShadow_GetIntTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC, bool perspProj )
{
real2 texCoords = EvalShadow_GetTexcoords(sd, positionWS, closestSampleNDC, perspProj);
return uint2(texCoords * sd.textureSize.xy);
}
//
// Biasing functions

sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
uint texIdx, sampIdx;

sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, sd.slice, 0 ).x;

ShadowData sd = shadowContext.shadowDatas[index];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
uint texIdx, sampIdx;

ShadowData sd = shadowContext.shadowDatas[index];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, sd.slice, 0 ).x;

sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
uint texIdx, sampIdx;

sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, sd.slice, 0 ).x;

return closestWS.xyz / closestWS.w;
}
real EvalShadow_SampleClosestDistance_Punctual( ShadowContext shadowContext, Texture2DArray tex, SamplerState sampl,
real3 positionWS, int index, real3 L, real3 lightPositionWS )
{
// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];
uint shadowType;
UnpackShadowType( sd.shadowType, shadowType );
// load the right shadow data for the current face
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (CubeMapFaceID( -L ) + 1) : 0;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
real2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
// sample the shadow map
closestNDC.z = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, sampl, texelIdx, sd.slice, 0 ).x;
// reconstruct depth position
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
real3 occluderPosWS = closestWS.xyz / closestWS.w;
return distance( occluderPosWS, lightPositionWS );
}
real3 EvalShadow_GetClosestSample_Cascade( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real4 L )
{
// load the right shadow data for the current face

if( shadowSplitIndex < 0 )
return 1.0;
return 0.0;
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, false );
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, false );
// load the texel
uint texIdx, sampIdx;

int shadowSplitIndex = EvalShadow_GetSplitIndex( shadowContext, index, positionWS, payloadOffset, alpha );
if( shadowSplitIndex < 0 )
return 1.0;
return 0.0;
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, false );
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, false );
// load the texel
uint texIdx, sampIdx;

real4 closestWS = mul( closestNDC, sd.shadowToWorld );
return closestWS.xyz / closestWS.w;
}
real EvalShadow_SampleClosestDistance_Cascade( ShadowContext shadowContext, Texture2DArray tex, SamplerState sampl,
real3 positionWS, real3 normalWS, int index, real4 L, out real3 nearPlanePositionWS )
{
// load the right shadow data for the current face
uint payloadOffset;
real alpha;
int shadowSplitIndex = EvalShadow_GetSplitIndex( shadowContext, index, positionWS, payloadOffset, alpha );
if( shadowSplitIndex < 0 )
return 0.0;
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
real4 closestNDC = { 0,0,0,1 };
real2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, false );
// sample the shadow map
uint texIdx, sampIdx;
UnpackShadowmapId( sd.id, texIdx, sampIdx );
closestNDC.z = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, sampl, texelIdx, sd.slice, 0 ).x;
// reconstruct depth position
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
real3 occluderPosWS = closestWS.xyz / closestWS.w;
// TODO: avoid the matrix multiplication here.
real4 nearPlanePos = mul( real4( 0,0,1,1 ), sd.shadowToWorld ); // Note the reversed Z
nearPlanePositionWS = nearPlanePos.xyz / nearPlanePos.w;
return distance( occluderPosWS, nearPlanePositionWS );
}

39
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl


UNITY_BRANCH
if (autoThicknessMode && NdotL < 0 && lightData.shadowIndex >= 0)
{
// TODO: perform bilinear filtering of the shadow map.
#if 0
// Does not work, I get a compiler crash...
float3 occluderPosWS = EvalShadow_GetClosestSample_Cascade(lightLoopContext.shadowContext, posInput.positionWS, bsdfData.normalWS, lightData.shadowIndex, float4(L, 0));
#else
float3 occluderPosWS = EvalShadow_GetClosestSample_Cascade(lightLoopContext.shadowContext, lightLoopContext.shadowContext.tex2DArray[SHADOW_DISPATCH_DIR_TEX], posInput.positionWS, bsdfData.normalWS, lightData.shadowIndex, float4(L, 0));
#endif
// Compute the distance from the light to the back face of the object along the light direction.
float3 nearPlanePositionWS;
float backNearPlaneDist = EvalShadow_SampleClosestDistance_Cascade(lightLoopContext.shadowContext, lightLoopContext.shadowContext.tex2DArray[SHADOW_DISPATCH_DIR_TEX],
s_linear_clamp_sampler, posInput.positionWS, bsdfData.normalWS, lightData.shadowIndex, float4(L, 0),
nearPlanePositionWS);
float thicknessInUnits = distance(posInput.positionWS, occluderPosWS);
// Our subsurface scattering models use the semi-infinite planar slab assumption.
// Therefore, we need to find the thickness along the normal.
float frontNearPlaneDist = distance(nearPlanePositionWS, posInput.positionWS);
float thicknessInUnits = (frontNearPlaneDist - backNearPlaneDist) * -NdotL;
// We need to make sure it's not less than the baked thickness to minimize light leaking.
thicknessInMillimeters = max(thicknessInMillimeters, bsdfData.thickness);
// TODO: optimize.
#if SHADEROPTIONS_USE_DISNEY_SSS

UNITY_BRANCH
if (autoThicknessMode && NdotL < 0 && lightData.shadowIndex >= 0)
{
// TODO: perform bilinear filtering of the shadow map.
#if 0
// Does not work, I get a compiler crash...
float3 occluderPosWS = EvalShadow_GetClosestSample_Punctual(lightLoopContext.shadowContext, posInput.positionWS, lightData.shadowIndex, L);
#else
float3 occluderPosWS = EvalShadow_GetClosestSample_Punctual(lightLoopContext.shadowContext, lightLoopContext.shadowContext.tex2DArray[SHADOW_DISPATCH_PUNC_TEX], posInput.positionWS, lightData.shadowIndex, L);
#endif
float thicknessInUnits = distance(posInput.positionWS, occluderPosWS);
// Compute the distance from the light to the back face of the object along the light direction.
float backLightDist = EvalShadow_SampleClosestDistance_Punctual(lightLoopContext.shadowContext, lightLoopContext.shadowContext.tex2DArray[SHADOW_DISPATCH_PUNC_TEX],
s_linear_clamp_sampler, posInput.positionWS, lightData.shadowIndex, L, lightData.positionWS);
// Our subsurface scattering models use the semi-infinite planar slab assumption.
// Therefore, we need to find the thickness along the normal.
float thicknessInUnits = (distances.x - backLightDist) * -NdotL;
// We need to make sure it's not less than the baked thickness to minimize light leaking.
thicknessInMillimeters = max(thicknessInMillimeters, bsdfData.thickness);
// TODO: optimize.
#if SHADEROPTIONS_USE_DISNEY_SSS

正在加载...
取消
保存