浏览代码

Moved shadow sampling patterns into a new file called ShadowSampling.hlsl.

Modified functions in ShadowAlgorthims.hlsl to use the sampling functions in the new sampling header.
/main
uygar 8 年前
当前提交
02e3fa95
共有 7 个文件被更改,包括 132 次插入78 次删除
  1. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  2. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl
  3. 88
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowAlgorithms.hlsl
  4. 15
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs
  5. 5
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowContext.hlsl
  6. 86
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowSampling.hlsl
  7. 9
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowSampling.hlsl.meta

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


scInit.storage.maxShadowDataSlots = k_MaxShadowDataSlots;
scInit.storage.maxPayloadSlots = k_MaxShadowDataSlots * k_MaxPayloadSlotsPerShadowData;
scInit.storage.maxTex2DArraySlots = 4;
scInit.storage.maxTexCubeArraySlots = 1;
scInit.storage.maxComparisonSamplerSlots = 1;
scInit.storage.maxSamplerSlots = 1;
scInit.storage.maxTexCubeArraySlots = 2;
scInit.storage.maxComparisonSamplerSlots = 2;
scInit.storage.maxSamplerSlots = 2;
scInit.dataSyncer = syncer;
scInit.resourceBinder = binder;

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl


// wedge in the actual shadow sampling algorithms
#include "ShadowSampling.hlsl" // sampling patterns
#include "ShadowAlgorithms.hlsl" // engine default algorithms (don't modify)
#include "ShadowAlgorithmsCustom.hlsl" // project specific custom algorithms (project can modify this)

88
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowAlgorithms.hlsl


// Various shadow algorithms
// There are two variants provided, one takes the texture and sampler explicitly so they can be statically passed in.
// The variant without resource parameters dynamically accesses the texture when sampling.

return posTC;
}
//
// Point shadows
//
float EvalShadow_PointDepth( ShadowContext shadowContext, float3 positionWS, int index, float3 L )
{
// load the right shadow data for the current face

uint texIdx, sampIdx;
float slice;
unpackShadowmapId( sd.id, texIdx, sampIdx, slice );
return SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, posTC, slice ).x;
return SampleShadow_PCF_1tap( shadowContext, posTC, slice, texIdx, sampIdx );
}
float EvalShadow_PointDepth( ShadowContext shadowContext, Texture2DArray tex, SamplerComparisonState compSamp, float3 positionWS, int index, float3 L )

// sample the texture
float slice;
unpackShadowmapId( sd.id, slice );
return SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, posTC, slice );
return SampleShadow_PCF_1tap( shadowContext, posTC, slice, tex, compSamp );
//
// Spot shadows
//
float EvalShadow_SpotDepth( ShadowContext shadowContext, float3 positionWS, int index, float3 L )
{
// load the right shadow data for the current face

uint texIdx, sampIdx;
float slice;
unpackShadowmapId( sd.id, texIdx, sampIdx, slice );
return SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, posTC, slice ).x;
return SampleShadow_PCF_1tap( shadowContext, posTC, slice, texIdx, sampIdx );
}
float EvalShadow_SpotDepth( ShadowContext shadowContext, Texture2DArray tex, SamplerComparisonState compSamp, float3 positionWS, int index, float3 L )

// sample the texture
float slice;
unpackShadowmapId( sd.id, slice );
return SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, posTC, slice );
return SampleShadow_PCF_1tap( shadowContext, posTC, slice, tex, compSamp );
//
// Punctual shadows for Point and Spot
//
float EvalShadow_PunctualDepth( ShadowContext shadowContext, float3 positionWS, int index, float3 L )
{
// load the right shadow data for the current face

uint texIdx, sampIdx;
float slice;
unpackShadowmapId( sd.id, texIdx, sampIdx, slice );
return SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, posTC, slice ).x;
return SampleShadow_PCF_1tap( shadowContext, posTC, slice, texIdx, sampIdx );
}
float EvalShadow_PunctualDepth( ShadowContext shadowContext, Texture2DArray tex, SamplerComparisonState compSamp, float3 positionWS, int index, float3 L )

// sample the texture
float slice;
unpackShadowmapId( sd.id, slice );
return SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, posTC, slice );
return SampleShadow_PCF_1tap( shadowContext, posTC, slice, tex, compSamp );
//
// Directional shadows (cascaded shadow map)
//
uint EvalShadow_GetSplitSphereIndexForDirshadows( float3 positionWS, float4 dirShadowSplitSpheres[4] )
{
float3 fromCenter0 = positionWS.xyz - dirShadowSplitSpheres[0].xyz;

float slice;
unpackShadowmapId( sd.id, texIdx, sampIdx, slice );
float4 vShadow3x3PCFTerms0;
float4 vShadow3x3PCFTerms1;
float4 vShadow3x3PCFTerms2;
float4 vShadow3x3PCFTerms3;
vShadow3x3PCFTerms0 = float4( 20.0f / 267.0f, 33.0f / 267.0f, 55.0f / 267.0f, 0.0f );
vShadow3x3PCFTerms1 = float4( sd.texelSizeRcp.x, sd.texelSizeRcp.y, -sd.texelSizeRcp.x, -sd.texelSizeRcp.y );
vShadow3x3PCFTerms2 = float4( sd.texelSizeRcp.x, sd.texelSizeRcp.y, 0.0f, 0.0f );
vShadow3x3PCFTerms3 = float4(-sd.texelSizeRcp.x, -sd.texelSizeRcp.y, 0.0f, 0.0f );
float4 v20Taps;
v20Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( posTC.xy + vShadow3x3PCFTerms1.xy, posTC.z ), slice ).x; // 1 1
v20Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( posTC.xy + vShadow3x3PCFTerms1.zy, posTC.z ), slice ).x; // -1 1
v20Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( posTC.xy + vShadow3x3PCFTerms1.xw, posTC.z ), slice ).x; // 1 -1
v20Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( posTC.xy + vShadow3x3PCFTerms1.zw, posTC.z ), slice ).x; // -1 -1
float flSum = dot( v20Taps.xyzw, float4( 0.25, 0.25, 0.25, 0.25 ) );
if( ( flSum == 0.0 ) || ( flSum == 1.0 ) )
return flSum;
flSum *= vShadow3x3PCFTerms0.x * 4.0;
float4 v33Taps;
v33Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( posTC.xy + vShadow3x3PCFTerms2.xz, posTC.z ), slice ).x; // 1 0
v33Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( posTC.xy + vShadow3x3PCFTerms3.xz, posTC.z ), slice ).x; // -1 0
v33Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( posTC.xy + vShadow3x3PCFTerms3.zy, posTC.z ), slice ).x; // 0 -1
v33Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( posTC.xy + vShadow3x3PCFTerms2.zy, posTC.z ), slice ).x; // 0 1
flSum += dot(v33Taps.xyzw, vShadow3x3PCFTerms0.yyyy);
flSum += SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, posTC, slice ).x * vShadow3x3PCFTerms0.z;
return flSum;
return SampleShadow_PCF_9tap_Adaptive( shadowContext, sd.texelSizeRcp, posTC, slice, texIdx, sampIdx );
}
float EvalShadow_CascadedDepth( ShadowContext shadowContext, Texture2DArray tex, SamplerComparisonState compSamp, float3 positionWS, int index, float3 L )

float slice;
unpackShadowmapId(sd.id, slice);
float4 vShadow3x3PCFTerms0;
float4 vShadow3x3PCFTerms1;
float4 vShadow3x3PCFTerms2;
float4 vShadow3x3PCFTerms3;
vShadow3x3PCFTerms0 = float4( 20.0f / 267.0f, 33.0f / 267.0f, 55.0f / 267.0f, 0.0f );
vShadow3x3PCFTerms1 = float4( sd.texelSizeRcp.x, sd.texelSizeRcp.y, -sd.texelSizeRcp.x, -sd.texelSizeRcp.y );
vShadow3x3PCFTerms2 = float4( sd.texelSizeRcp.x, sd.texelSizeRcp.y, 0.0f, 0.0f );
vShadow3x3PCFTerms3 = float4(-sd.texelSizeRcp.x, -sd.texelSizeRcp.y, 0.0f, 0.0f );
float4 v20Taps;
v20Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( posTC.xy + vShadow3x3PCFTerms1.xy, posTC.z ), slice ).x; // 1 1
v20Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( posTC.xy + vShadow3x3PCFTerms1.zy, posTC.z ), slice ).x; // -1 1
v20Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( posTC.xy + vShadow3x3PCFTerms1.xw, posTC.z ), slice ).x; // 1 -1
v20Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( posTC.xy + vShadow3x3PCFTerms1.zw, posTC.z ), slice ).x; // -1 -1
float flSum = dot( v20Taps.xyzw, float4( 0.25, 0.25, 0.25, 0.25 ) );
if( ( flSum == 0.0 ) || ( flSum == 1.0 ) )
return flSum;
flSum *= vShadow3x3PCFTerms0.x * 4.0;
float4 v33Taps;
v33Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( posTC.xy + vShadow3x3PCFTerms2.xz, posTC.z ), slice ).x; // 1 0
v33Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( posTC.xy + vShadow3x3PCFTerms3.xz, posTC.z ), slice ).x; // -1 0
v33Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( posTC.xy + vShadow3x3PCFTerms3.zy, posTC.z ), slice ).x; // 0 -1
v33Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( posTC.xy + vShadow3x3PCFTerms2.zy, posTC.z ), slice ).x; // 0 1
flSum += dot(v33Taps.xyzw, vShadow3x3PCFTerms0.yyyy);
flSum += SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, posTC, slice ).x * vShadow3x3PCFTerms0.z;
return flSum;
return SampleShadow_PCF_9tap_Adaptive( shadowContext, sd.texelSizeRcp, posTC, slice, tex, compSamp );
}

15
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs


Unknown = MAX,
All = Point | Spot | Directional
};
public enum GPUShadowSampling
{
PCF_1tap,
PCF_9Taps_Adaptive,
};
namespace ShadowExp // temporary namespace until everything can be merged into the HDPipeline
{

public Matrix4x4 worldToShadow; // to light space matrix
public Vector4 scaleOffset; // scale and offset of shadowmap in atlas
public Vector2 texelSizeRcp; // reciprocal of the shadowmap's texel size in x and y
public uint id; // texture array slice idx (may be removed again if we decide that all shadows must fit into one texture atlas slice)
public uint id; // packed texture id, sampler id and slice idx
public GPUShadowType shadowType; // determines the shadow algorithm, i.e. which map to sample and how to interpret the data
public uint payloadOffset; // if this shadow type requires additional data it can be fetched from a global Buffer<uint> at payloadOffset.

public void PackShadowmapId( uint texIdx, uint sampIdx, uint slice )
{
Debug.Assert( texIdx < 0xff );
Debug.Assert( sampIdx < 0xff );
Debug.Assert( slice < 0xffff );
Debug.Assert( texIdx <= 0xff );
Debug.Assert( sampIdx <= 0xff );
Debug.Assert( slice <= 0xffff );
id = texIdx << 24 | sampIdx << 16 | slice;
}
};

5
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowContext.hlsl


// This can be custom for each project and needs to be in sync with the ShadowMgr
#define SHADOWCONTEXT_MAX_TEX2DARRAY 2
#define SHADOWCONTEXT_MAX_TEXCUBEARRAY 2
#define SHADOWCONTEXT_MAX_SAMPLER 2
#define SHADOWCONTEXT_MAX_TEXCUBEARRAY 1
#define SHADOWCONTEXT_MAX_SAMPLER 1
#define SHADOWCONTEXT_MAX_COMPSAMPLER 2
SHADOWCONTEXT_DECLARE( SHADOWCONTEXT_MAX_TEX2DARRAY, SHADOWCONTEXT_MAX_TEXCUBEARRAY, SHADOWCONTEXT_MAX_COMPSAMPLER, SHADOWCONTEXT_MAX_SAMPLER );

SAMPLER2D_SHADOW(sampler_ShadowmapExp_Dir);
TEXTURE2D_ARRAY(_ShadowmapExp_PointSpot);
SAMPLER2D_SHADOW(sampler_ShadowmapExp_PointSpot);
ShadowContext InitShadowContext()
{

86
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowSampling.hlsl


// Various shadow sampling logic.
// Again two versions, one for dynamic resource indexing, one for static resource access.
//
// 1 tap PCF sampling
//
float SampleShadow_PCF_1tap( ShadowContext shadowContext, float3 tcs, uint slice, uint texIdx, uint sampIdx )
{
// sample the texture
return SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, tcs, slice ).x;
}
float SampleShadow_PCF_1tap( ShadowContext shadowContext, float3 tcs, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
{
// sample the texture
return SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, tcs, slice );
}
//
// 9 tap adaptive PCF sampling
//
float SampleShadow_PCF_9tap_Adaptive( ShadowContext shadowContext, float2 texelSizeRcp, float3 tcs, uint slice, uint texIdx, uint sampIdx )
{
// Terms0 are weights for the individual samples, the other terms are offsets in texel space
float4 vShadow3x3PCFTerms0 = float4( 20.0f / 267.0f, 33.0f / 267.0f, 55.0f / 267.0f, 0.0f );
float4 vShadow3x3PCFTerms1 = float4( texelSizeRcp.x, texelSizeRcp.y, -texelSizeRcp.x, -texelSizeRcp.y );
float4 vShadow3x3PCFTerms2 = float4( texelSizeRcp.x, texelSizeRcp.y, 0.0f, 0.0f );
float4 vShadow3x3PCFTerms3 = float4(-texelSizeRcp.x, -texelSizeRcp.y, 0.0f, 0.0f );
float4 v20Taps;
v20Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z ), slice ).x; // 1 1
v20Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z ), slice ).x; // -1 1
v20Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z ), slice ).x; // 1 -1
v20Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z ), slice ).x; // -1 -1
float flSum = dot( v20Taps.xyzw, float4( 0.25, 0.25, 0.25, 0.25 ) );
// fully in light or shadow? -> bail
if( ( flSum == 0.0 ) || ( flSum == 1.0 ) )
return flSum;
// we're in a transition area, do 5 more taps
flSum *= vShadow3x3PCFTerms0.x * 4.0;
float4 v33Taps;
v33Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z ), slice ).x; // 1 0
v33Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z ), slice ).x; // -1 0
v33Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z ), slice ).x; // 0 -1
v33Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z ), slice ).x; // 0 1
flSum += dot( v33Taps.xyzw, vShadow3x3PCFTerms0.yyyy );
flSum += SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, tcs, slice ).x * vShadow3x3PCFTerms0.z;
return flSum;
}
float SampleShadow_PCF_9tap_Adaptive(ShadowContext shadowContext, float2 texelSizeRcp, float3 tcs, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
{
// Terms0 are weights for the individual samples, the other terms are offsets in texel space
float4 vShadow3x3PCFTerms0 = float4(20.0f / 267.0f, 33.0f / 267.0f, 55.0f / 267.0f, 0.0f);
float4 vShadow3x3PCFTerms1 = float4( texelSizeRcp.x, texelSizeRcp.y, -texelSizeRcp.x, -texelSizeRcp.y);
float4 vShadow3x3PCFTerms2 = float4( texelSizeRcp.x, texelSizeRcp.y, 0.0f, 0.0f);
float4 vShadow3x3PCFTerms3 = float4(-texelSizeRcp.x, -texelSizeRcp.y, 0.0f, 0.0f);
float4 v20Taps;
v20Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z ), slice ).x; // 1 1
v20Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z ), slice ).x; // -1 1
v20Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z ), slice ).x; // 1 -1
v20Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z ), slice ).x; // -1 -1
float flSum = dot( v20Taps.xyzw, float4( 0.25, 0.25, 0.25, 0.25 ) );
// fully in light or shadow? -> bail
if( ( flSum == 0.0 ) || ( flSum == 1.0 ) )
return flSum;
// we're in a transition area, do 5 more taps
flSum *= vShadow3x3PCFTerms0.x * 4.0;
float4 v33Taps;
v33Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z ), slice ).x; // 1 0
v33Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z ), slice ).x; // -1 0
v33Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z ), slice ).x; // 0 -1
v33Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z ), slice ).x; // 0 1
flSum += dot( v33Taps.xyzw, vShadow3x3PCFTerms0.yyyy );
flSum += SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, tcs, slice ).x * vShadow3x3PCFTerms0.z;
return flSum;
}

9
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowSampling.hlsl.meta


fileFormatVersion: 2
guid: 32c86a80860fd014ba44f8b7a7914a5c
timeCreated: 1487253249
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存