浏览代码

Added a combined contact shadows + normal biasing pass.

Replaced shadow specific cubemap face function. The shadow system is now going to use the one from common.hlsl.
Renamed nrml to normal.
Added a few comments.
/main
uygar 6 年前
当前提交
75a06b95
共有 7 个文件被更改,包括 55 次插入76 次删除
  1. 84
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  2. 8
      ScriptableRenderPipeline/Core/CoreRP/Shadow/AdditionalShadowData.cs
  3. 14
      ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs
  4. 2
      ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs
  5. 6
      ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs.hlsl
  6. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/DeferredDirectionalShadow.compute
  7. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs

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


return uint2( (posTC * sd.scaleOffset.xy + sd.scaleOffset.zw) * sd.textureSize.xy );
}
int EvalShadow_GetCubeFaceID( real3 sampleToLight )
{
real3 lightToSample = -sampleToLight; // TODO: pass the correct (flipped) direction
#ifdef INTRINSIC_CUBEMAP_FACE_ID
return (int)CubeMapFaceID(lightToSample);
#else
// TODO: use CubeMapFaceID() defined in Common.hlsl for all pipelines on all platforms.
real3 dir = sampleToLight;
real3 adir = abs(dir);
// +Z -Z
int faceIndex = dir.z > 0.0 ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
// +X -X
if (adir.x > adir.y && adir.x > adir.z)
{
faceIndex = dir.x > 0.0 ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
}
// +Y -Y
else if (adir.y > adir.x && adir.y > adir.z)
{
faceIndex = dir.y > 0.0 ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
}
return faceIndex;
#endif
}
//
// Biasing functions

[branch]
if( shadowAlgorithm <= GPUSHADOWALGORITHM_PCF_TENT_7X7 )
{
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ), sd.edgeTolerance, EvalShadow_ReceiverBiasWeightUseNormalFlag( sd.nrmlBias.w ) );
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ), sd.edgeTolerance, EvalShadow_ReceiverBiasWeightUseNormalFlag( sd.normalBias.w ) );
return lerp( 1.0, weight, EvalShadow_ReceiverBiasWeightFlag( sd.nrmlBias.w ) );
return lerp( 1.0, weight, EvalShadow_ReceiverBiasWeightFlag( sd.normalBias.w ) );
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ), sd.edgeTolerance, EvalShadow_ReceiverBiasWeightUseNormalFlag( sd.nrmlBias.w ) );
return lerp( 1.0, SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, samp, EvalShadow_GetTexcoords( sd, pos, perspProj ), sd.slice ).x, EvalShadow_ReceiverBiasWeightFlag( sd.nrmlBias.w ) );
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ), sd.edgeTolerance, EvalShadow_ReceiverBiasWeightUseNormalFlag( sd.normalBias.w ) );
return lerp( 1.0, SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, samp, EvalShadow_GetTexcoords( sd, pos, perspProj ), sd.slice ).x, EvalShadow_ReceiverBiasWeightFlag( sd.normalBias.w ) );
}
real EvalShadow_ReceiverBiasWeight( ShadowData sd, Texture2DArray tex, SamplerState samp, real3 positionWS, real3 normalWS, real3 L, real L_dist, bool perspProj )

float viewBiasMin = sd.viewBias.x;
float viewBiasMax = sd.viewBias.y;
float viewBiasScale = sd.viewBias.z;
float nrmlBiasMin = sd.nrmlBias.x;
float nrmlBiasMax = sd.nrmlBias.y;
float nrmlBiasScale = sd.nrmlBias.z;
float normalBiasMin = sd.normalBias.x;
float normalBiasMax = sd.normalBias.y;
float normalBiasScale = sd.normalBias.z;
sine = clamp( sine * nrmlBiasScale, nrmlBiasMin, nrmlBiasMax );
sine = clamp( sine * normalBiasScale, normalBiasMin, normalBiasMax );
tangent = clamp( tangent * viewBiasScale * lightviewBiasWeight, viewBiasMin, viewBiasMax );
float3 view_bias = L * tangent;
float3 normal_bias = normalWS * sine;

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

nrm.xy /= -nrm.z;
return isfinite( nrm.xy ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
return isfinite( nrm.xy ) ? (EvalShadow_SampleBiasFlag( sd.normalBias.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; }

//
real EvalShadow_PointDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist )
{
ShadowData sd = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1];
ShadowData sd = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1];
// get the algorithm
uint shadowType, shadowAlgorithm;
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );

#define EvalShadow_PointDepth_( _samplerType ) \
real EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist ) \
{ \
ShadowData sd = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1]; \
ShadowData sd = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1]; \
/* bias the world position */ \
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( sd, tex, samp, positionWS, normalWS, L, L_dist, true ); \
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, L_dist, recvBiasWeight, true ); \

[branch]
if( shadowType == GPUSHADOWTYPE_POINT )
{
sd.rot0 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot0;
sd.rot1 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot1;
sd.rot2 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot2;
sd.shadowToWorld = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].shadowToWorld;
sd.scaleOffset.zw = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].scaleOffset.zw;
sd.slice = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].slice;
sd.rot0 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot0;
sd.rot1 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot1;
sd.rot2 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot2;
sd.shadowToWorld = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].shadowToWorld;
sd.scaleOffset.zw = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].scaleOffset.zw;
sd.slice = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].slice;
}
uint texIdx, sampIdx;

[branch] \
if( shadowType == GPUSHADOWTYPE_POINT ) \
{ \
sd.rot0 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot0; \
sd.rot1 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot1; \
sd.rot2 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot2; \
sd.shadowToWorld = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].shadowToWorld; \
sd.scaleOffset.zw = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].scaleOffset.zw; \
sd.slice = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].slice; \
sd.rot0 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot0; \
sd.rot1 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot1; \
sd.rot2 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot2; \
sd.shadowToWorld = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].shadowToWorld; \
sd.scaleOffset.zw = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].scaleOffset.zw; \
sd.slice = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].slice; \
} \
\
/* bias the world position */ \

// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];
// load the right shadow data for the current face
int faceIndex = EvalShadow_GetCubeFaceID( L ) + 1;
int faceIndex = CubeMapFaceID( -L ) + 1;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };

// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];
// load the right shadow data for the current face
int faceIndex = EvalShadow_GetCubeFaceID( L ) + 1;
int faceIndex = CubeMapFaceID( -L ) + 1;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };

uint shadowType;
UnpackShadowType( sd.shadowType, shadowType );
// load the right shadow data for the current face
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (EvalShadow_GetCubeFaceID( L ) + 1) : 0;
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (CubeMapFaceID( -L ) + 1) : 0;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };

uint shadowType;
UnpackShadowType( sd.shadowType, shadowType );
// load the right shadow data for the current face
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (EvalShadow_GetCubeFaceID( L ) + 1) : 0;
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (CubeMapFaceID( -L ) + 1) : 0;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };

8
ScriptableRenderPipeline/Core/CoreRP/Shadow/AdditionalShadowData.cs


public float viewBiasMax = 10.0f;
[Range(0.0F, 15.0F)]
public float viewBiasScale = 1.0f;
public float nrmlBiasMin = 0.2f;
public float nrmlBiasMax = 4.0f;
public float normalBiasMin = 0.2f;
public float normalBiasMax = 4.0f;
public float nrmlBiasScale = 1.0f;
public float normalBiasScale = 1.0f;
public bool edgeToleranceNrml = true;
public bool edgeToleranceNormal = true;
[Range(0.0F, 1.0F)]
public float edgeTolerance = 1.0f;

14
ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs


if( sr.shadowType == GPUShadowType.Point )
{
// calculate the fov bias
float guardAngle = ShadowUtils.CalcGuardAnglePerspective( 90.0f, ce.current.viewport.width, GetFilterWidthInTexels( sr, asd ), asd.nrmlBiasMax, 79.0f );
float guardAngle = ShadowUtils.CalcGuardAnglePerspective( 90.0f, ce.current.viewport.width, GetFilterWidthInTexels( sr, asd ), asd.normalBiasMax, 79.0f );
float guardAngle = ShadowUtils.CalcGuardAnglePerspective( spotAngle, ce.current.viewport.width, GetFilterWidthInTexels( sr, asd ), asd.nrmlBiasMax, 180.0f - spotAngle );
float guardAngle = ShadowUtils.CalcGuardAnglePerspective( spotAngle, ce.current.viewport.width, GetFilterWidthInTexels( sr, asd ), asd.normalBiasMax, 180.0f - spotAngle );
vp = ShadowUtils.ExtractSpotLightMatrix( lights[sr.index], guardAngle, out ce.current.view, out ce.current.proj, out devproj, out invvp, out ce.current.lightDir, out ce.current.splitData );
}
else if( sr.shadowType == GPUShadowType.Directional )

// extract texel size in world space
int flags = 0;
flags |= asd.sampleBiasScale ? (1 << 0) : 0;
flags |= asd.edgeLeakFixup ? (1 << 1) : 0;
flags |= asd.edgeToleranceNrml ? (1 << 2) : 0;
flags |= asd.sampleBiasScale ? (1 << 0) : 0;
flags |= asd.edgeLeakFixup ? (1 << 1) : 0;
flags |= asd.edgeToleranceNormal ? (1 << 2) : 0;
sd.viewBias = new Vector4( asd.viewBiasMin, asd.viewBiasMax, asd.viewBiasScale, 2.0f / ce.current.proj.m00 / ce.current.viewport.width * 1.4142135623730950488016887242097f );
sd.nrmlBias = new Vector4( asd.nrmlBiasMin, asd.nrmlBiasMax, asd.nrmlBiasScale, ShadowUtils.Asfloat( flags ) );
sd.viewBias = new Vector4( asd.viewBiasMin, asd.viewBiasMax, asd.viewBiasScale, 2.0f / ce.current.proj.m00 / ce.current.viewport.width * 1.4142135623730950488016887242097f );
sd.normalBias = new Vector4( asd.normalBiasMin, asd.normalBiasMax, asd.normalBiasScale, ShadowUtils.Asfloat( flags ) );
// write :(
ce.current.shadowAlgo = (GPUShadowAlgorithm) shadowAlgo;

2
ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs


public uint payloadOffset; // if this shadow type requires additional data it can be fetched from a global Buffer<uint> at payloadOffset.
public float slice; // shadowmap slice
public Vector4 viewBias; // x = min, y = max, z = scale, w = shadowmap texel size in world space at distance 1 from light
public Vector4 nrmlBias; // x = min, y = max, z = scale, w = enable/disable sample biasing
public Vector4 normalBias; // x = min, y = max, z = scale, w = enable/disable sample biasing
public float edgeTolerance; // specifies the offset along either the normal or view vector used for calculating the edge leak fixup
public Vector3 _pad; // 16 byte padding
public Matrix4x4 shadowToWorld; // from light space matrix

6
ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs.hlsl


uint payloadOffset;
float slice;
float4 viewBias;
float4 nrmlBias;
float4 normalBias;
float edgeTolerance;
float3 _pad;
float4x4 shadowToWorld;

{
return value.viewBias;
}
float4 GetNrmlBias(ShadowData value)
float4 GetNormalBias(ShadowData value)
return value.nrmlBias;
return value.normalBias;
}
float GetEdgeTolerance(ShadowData value)
{

9
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/DeferredDirectionalShadow.compute


// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel DeferredDirectionalShadow DEFERRED_DIRECTIONAL=DeferredDirectionalShadow
#pragma kernel DeferredDirectionalShadow_Contact DEFERRED_DIRECTIONAL=DeferredDirectionalShadow_Contact ENABLE_CONTACT_SHADOWS
#pragma kernel DeferredDirectionalShadow_Normals DEFERRED_DIRECTIONAL=DeferredDirectionalShadow_Normals ENABLE_NORMALS
#pragma kernel DeferredDirectionalShadow DEFERRED_DIRECTIONAL=DeferredDirectionalShadow
#pragma kernel DeferredDirectionalShadow_Contact DEFERRED_DIRECTIONAL=DeferredDirectionalShadow_Contact ENABLE_CONTACT_SHADOWS
#pragma kernel DeferredDirectionalShadow_Normals DEFERRED_DIRECTIONAL=DeferredDirectionalShadow_Normals ENABLE_NORMALS
#pragma kernel DeferredDirectionalShadow_Contact_Normals DEFERRED_DIRECTIONAL=DeferredDirectionalShadow_Contact_Normals ENABLE_CONTACT_SHADOWS ENABLE_NORMALS
#ifdef ENABLE_NORMALS
# define LIGHTLOOP_TILE_PASS 1

#endif
#ifdef SHADER_API_PSSL
# pragma argument( scheduler=minpressure )
# pragma argument( scheduler=minpressure ) // instruct the shader compiler to prefer minimizing vgpr usage
#endif
#include "CoreRP/ShaderLibrary/Common.hlsl"

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs


static int s_deferredDirectionalShadowKernel;
static int s_deferredDirectionalShadow_Contact_Kernel;
static int s_deferredDirectionalShadow_Normals_Kernel;
static int s_deferredDirectionalShadow_Contact_Normals_Kernel;
static ComputeBuffer s_LightVolumeDataBuffer = null;
static ComputeBuffer s_ConvexBoundsBuffer = null;

s_deferredDirectionalShadowKernel = deferredDirectionalShadowComputeShader.FindKernel("DeferredDirectionalShadow");
s_deferredDirectionalShadow_Contact_Kernel = deferredDirectionalShadowComputeShader.FindKernel("DeferredDirectionalShadow_Contact");
s_deferredDirectionalShadow_Normals_Kernel = deferredDirectionalShadowComputeShader.FindKernel("DeferredDirectionalShadow_Normals");
s_deferredDirectionalShadow_Contact_Normals_Kernel = deferredDirectionalShadowComputeShader.FindKernel("DeferredDirectionalShadow_Contact_Normals");
for (int variant = 0; variant < LightDefinitions.s_NumFeatureVariants; variant++)
{

AdditionalShadowData asd = m_CurrentSunLight.GetComponent<AdditionalShadowData>();
bool enableContactShadows = m_FrameSettings.enableContactShadows && asd.enableContactShadows && asd.contactShadowLength > 0.0f;
int kernel = enableContactShadows ? s_deferredDirectionalShadow_Contact_Kernel : (m_FrameSettings.enableForwardRenderingOnly ? s_deferredDirectionalShadowKernel : s_deferredDirectionalShadow_Normals_Kernel);
int kernel;
if (enableContactShadows)
kernel = m_FrameSettings.enableForwardRenderingOnly ? s_deferredDirectionalShadow_Contact_Kernel : s_deferredDirectionalShadow_Contact_Normals_Kernel;
else
kernel = m_FrameSettings.enableForwardRenderingOnly ? s_deferredDirectionalShadowKernel : s_deferredDirectionalShadow_Normals_Kernel;
m_ShadowMgr.BindResources(cmd, deferredDirectionalShadowComputeShader, kernel);

正在加载...
取消
保存