浏览代码

Added new helper function to calculate a guard angle for spot and point lights that gets added to the given fov so that biasing and filtering cannot access the shadowmap outside the valid range.

/main
uygar 7 年前
当前提交
c278421b
共有 3 个文件被更改,包括 69 次插入16 次删除
  1. 8
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  2. 55
      ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs
  3. 22
      ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowUtilities.cs

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


float2 EvalShadow_SampleBias_Persp( ShadowData sd, float3 positionWS, float3 normalWS, float3 tcs )
{
float3 e1, e2;
if( abs( normalWS.z ) > 0.05 )
if( abs( normalWS.z ) > 0.65 )
else if( abs( normalWS.y ) > 0.05 )
else if( abs( normalWS.y ) > 0.65 )
{
e1 = float3( 1.0, -normalWS.x / normalWS.y, 0.0 );
e2 = float3( 0.0, -normalWS.z / normalWS.y, 1.0 );

float3 nrm = cross( p1.xyz - tcs, p2.xyz - tcs );
nrm.xy /= -nrm.z;
return all( isfinite( nrm.xy ) ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
return isfinite( nrm.xy ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
}
float2 EvalShadow_SampleBias_Ortho( ShadowData sd, float3 normalWS )

nrm.xy /= -nrm.z;
return all( isfinite( nrm.xy ) ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
return isfinite( nrm.xy ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
}
#else // SHADOW_USE_SAMPLE_BIASING != 0
float2 EvalShadow_SampleBias_Persp( ShadowData sd, float3 positionWS, float3 normalWS, float3 tcs ) { return 0.0.xx; }

55
ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs


float nearPlaneOffset = QualitySettings.shadowNearPlaneOffset;
GPUShadowAlgorithm sanitizedAlgo = ShadowUtils.ClearPrecision( sr.shadowAlgorithm );
AdditionalShadowData asd = lights[sr.index].light.GetComponent<AdditionalShadowData>();
if( !asd )
return false;
int cascadeCnt = 0;
int cascadeCnt = 0;
AdditionalShadowData asd = lights[sr.index].light.GetComponent<AdditionalShadowData>();
if( !asd )
return false;
asd.GetShadowCascades( out cascadeCnt, out cascadeRatios, out cascadeBorders );
}

CachedEntry ce = m_EntryCache[ceIdx];
ce.zclip = sr.shadowType != GPUShadowType.Directional;
vp = ShadowUtils.ExtractPointLightMatrix( lights[sr.index], key.faceIdx, 4.0f, out ce.current.view, out ce.current.proj, out invvp, out ce.current.lightDir, out ce.current.splitData );
{
// calculate the fov bias
float guardAngle = ShadowUtils.CalcGuardAnglePerspective( 90.0f, ce.current.viewport.width, GetFilterWidthInTexels( sr, asd ), asd.nrmlBiasMax, 79.0f );
vp = ShadowUtils.ExtractPointLightMatrix( lights[sr.index], key.faceIdx, guardAngle, out ce.current.view, out ce.current.proj, out invvp, out ce.current.lightDir, out ce.current.splitData );
}
vp = ShadowUtils.ExtractSpotLightMatrix( lights[sr.index], out ce.current.view, out ce.current.proj, out invvp, out ce.current.lightDir, out ce.current.splitData );
{
float spotAngle = lights[sr.index].spotAngle;
float guardAngle = ShadowUtils.CalcGuardAnglePerspective( spotAngle, ce.current.viewport.width, GetFilterWidthInTexels( sr, asd ), asd.nrmlBiasMax, 180.0f - spotAngle );
vp = ShadowUtils.ExtractSpotLightMatrix( lights[sr.index], guardAngle, out ce.current.view, out ce.current.proj, out invvp, out ce.current.lightDir, out ce.current.splitData );
}
else if( sr.shadowType == GPUShadowType.Directional )
{
vp = ShadowUtils.ExtractDirectionalLightMatrix( lights[sr.index], key.faceIdx, cascadeCnt, cascadeRatios, nearPlaneOffset, width, height, out ce.current.view, out ce.current.proj, out invvp, out ce.current.lightDir, out ce.current.splitData, m_CullResults, (int) sr.index );

}
// extract texel size in world space
AdditionalShadowData asd = lights[sr.index].light.GetComponent<AdditionalShadowData>();
int flags = 0;
flags |= asd.sampleBiasScale ? (1 << 0) : 0;
flags |= asd.edgeLeakFixup ? (1 << 1) : 0;

uint payloadSize = sr.shadowType == GPUShadowType.Directional ? (k_MaxCascadesInShader + ((uint)m_TmpScales.Length / 4) + ((uint)m_TmpBorders.Length / 4)) : 0;
payloadSize += ShadowUtils.ExtractAlgorithm( sr.shadowAlgorithm ) == ShadowAlgorithm.PCF ? 1u : 0;
return payloadSize;
}
virtual protected float GetFilterWidthInTexels( ShadowRequest sr, AdditionalShadowData asd )
{
ShadowAlgorithm algo;
ShadowVariant vari;
ShadowPrecision prec;
ShadowUtils.Unpack( sr.shadowAlgorithm, out algo, out vari, out prec );
if( algo != ShadowAlgorithm.PCF )
return 1.0f;
switch( vari )
{
case ShadowVariant.V0: return 1;
case ShadowVariant.V1:
{
int shadowDataFormat;
int[] shadowData = asd.GetShadowData( out shadowDataFormat );
return ShadowUtils.Asfloat( shadowData[1] );
}
case ShadowVariant.V2: return 3;
case ShadowVariant.V3: return 5;
case ShadowVariant.V4: return 7;
default: return 1.0f;
}
}
// Writes additional per light data into the payload vector. Make sure to call base.WritePerLightPayload first.

case ShadowAlgorithm.MSM : return cnt + 1;
default: return cnt;
}
}
override protected float GetFilterWidthInTexels( ShadowRequest sr, AdditionalShadowData asd )
{
return 1.0f;
}
// Writes additional per light data into the payload vector. Make sure to call base.WritePerLightPayload first.

22
ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowUtilities.cs


vpinv = invview * invproj;
}
public static Matrix4x4 ExtractSpotLightMatrix( VisibleLight vl, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData )
public static Matrix4x4 ExtractSpotLightMatrix( VisibleLight vl, float guardAngle, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData )
{
splitData = new ShadowSplitData();
splitData.cullingSphere.Set( 0.0f, 0.0f, 0.0f, float.NegativeInfinity );

// calculate projection
float zfar = vl.range;
float znear = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin;
float fov = vl.spotAngle;
float fov = vl.spotAngle + guardAngle;
proj = Matrix4x4.Perspective(fov, 1.0f, znear, zfar);
// and the compound (deviceProj will potentially inverse-Z)
Matrix4x4 deviceProj = GL.GetGPUProjectionMatrix( proj, false );

public static Matrix4x4 ExtractPointLightMatrix( VisibleLight vl, uint faceIdx, float fovBias, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData )
public static Matrix4x4 ExtractPointLightMatrix( VisibleLight vl, uint faceIdx, float guardAngle, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData )
{
if( faceIdx > (uint) CubemapFace.NegativeZ )
Debug.LogError( "Tried to extract cubemap face " + faceIdx + "." );

// calculate projection
float farPlane = vl.range;
float nearPlane = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin;
proj = Matrix4x4.Perspective( 90.0f + fovBias, 1.0f, nearPlane, farPlane );
proj = Matrix4x4.Perspective( 90.0f + guardAngle, 1.0f, nearPlane, farPlane );
// and the compound (deviceProj will potentially inverse-Z)
Matrix4x4 deviceProj = GL.GetGPUProjectionMatrix( proj, false );
InvertPerspective( ref deviceProj, ref view, out vpinverse );

Matrix4x4 deviceProj = GL.GetGPUProjectionMatrix( proj, false );
InvertOrthographic( ref deviceProj, ref view, out vpinverse );
return deviceProj * view;
}
public static float CalcGuardAnglePerspective( float angleInDeg, float resolution, float filterWidth, float normalBiasMax, float guardAngleMaxInDeg )
{
float angleInRad = angleInDeg * 0.5f * Mathf.Deg2Rad;
float res = 2.0f / resolution;
float texelSize = Mathf.Cos( angleInRad ) * res;
float beta = normalBiasMax * texelSize * 1.4142135623730950488016887242097f;
float guardAngle = Mathf.Atan( beta );
texelSize = Mathf.Tan( angleInRad + guardAngle ) * res;
guardAngle = Mathf.Atan( (resolution + Mathf.Ceil( filterWidth )) * texelSize * 0.5f ) * 2.0f * Mathf.Rad2Deg - angleInDeg;
guardAngle *= 2.0f;
return guardAngle < guardAngleMaxInDeg ? guardAngle : guardAngleMaxInDeg;
}
public static GPUShadowAlgorithm Pack( ShadowAlgorithm algo, ShadowVariant vari, ShadowPrecision prec )

正在加载...
取消
保存