浏览代码

Modified ShadowmapBase by adding a new enum bitmask designating the supported shadow types by this shadowmap.

Modified ShadowManager to take an array of shadow maps instead of only one. The shadowmanager will allocate lights according to each shadowmap's supported shadows mask. Shadowmaps are traversed in order specified in the constructor. Currently there's a limit of 4 maps per light type.
Changed shadow sampling functions in shader code to support multiple comparison samplers.
Modified tilepass to pass two shadowmaps, one for directional, one for point lights, to the shadowmanager to test the new functionality. This will probably change again soon.
/main
uygar 7 年前
当前提交
a9dc4866
共有 9 个文件被更改,包括 196 次插入151 次删除
  1. 29
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  2. 75
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.cs
  3. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl
  4. 24
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowAlgorithms.hlsl
  5. 15
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs
  6. 19
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowContext.hlsl
  7. 14
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowDispatch.hlsl
  8. 149
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowTexFetch.hlsl
  9. 20
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowUtilities.cs

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


const int k_MaxShadowDataSlots = 64;
const int k_MaxPayloadSlotsPerShadowData = 16;
FrameId m_frameId;
ShadowmapBase m_Shadowmap;
ShadowmapBase[] m_Shadowmaps;
uint m_ShadowDatasCount;
ShadowExp.ShadowData[] m_ShadowDatas;
uint m_ShadowPayloadsCount;
int[] m_ShadowPayloads;
List<int> m_ShadowRequests = new List<int>();
Dictionary<int, int> m_ShadowIndices = new Dictionary<int,int>();

atlasInit.baseInit.shadowmapFormat = RenderTextureFormat.Shadowmap;
atlasInit.baseInit.clearColor = new Vector4( 0.0f, 0.0f, 0.0f, 0.0f );
atlasInit.baseInit.maxPayloadCount = 0;
atlasInit.baseInit.shadowSupport = ShadowmapBase.ShadowSupport.Directional;
m_Shadowmap = new ShadowExp.ShadowAtlas( ref atlasInit );
var atlasInit2 = atlasInit;
atlasInit2.baseInit.shadowSupport = ShadowmapBase.ShadowSupport.Point | ShadowmapBase.ShadowSupport.Spot;
m_Shadowmaps = new ShadowmapBase[] { new ShadowExp.ShadowAtlas( ref atlasInit ), new ShadowExp.ShadowAtlas( ref atlasInit2 ) };
ShadowContext.SyncDel syncer = (ShadowContext sc) =>
{

uint offset, count;
RenderTargetIdentifier[] tex;
sc.GetTex2DArrays( out tex, out offset, out count );
cb.SetGlobalTexture( "_ShadowmapExp", tex[0] );
cb.SetGlobalTexture( "_ShadowmapExp_Dir", tex[0] );
cb.SetGlobalTexture( "_ShadowmapExp_PointSpot", tex[1] );
//cb.SetGlobalTexture( "_ShadowmapMomentum", tex[1] );
// TODO: Currently samplers are hard coded in ShadowContext.hlsl, so we can't really set them here
};

scInit.dataSyncer = syncer;
scInit.resourceBinder = binder;
m_ShadowMgr = new ShadowExp.ShadowManager(shadowSettings, ref scInit, m_Shadowmap);
m_ShadowMgr = new ShadowExp.ShadowManager( shadowSettings, ref scInit, m_Shadowmaps );
if( m_Shadowmap != null )
if( m_Shadowmaps != null )
(m_Shadowmap as ShadowAtlas).Dispose();
m_Shadowmap = null;
(m_Shadowmaps[0] as ShadowAtlas).Dispose();
m_Shadowmaps = null;
}
m_ShadowMgr = null;

GetDirectionalLightData(shadowSettings, gpuLightType, light, additionalData, lightIndex, ref shadowOutput, ref directionalShadowcount);
#if (SHADOWS_ENABLED && SHADOWS_FIXSHADOWIDX)
// fix up shadow information (TODO: Directional bails early, need to fix up that one as well)
// fix up shadow information
int shadowIdxDir;
if( m_ShadowIndices.TryGetValue( lightIndex, out shadowIdxDir ) )
{

GetLightVolumeDataAndBound(lightCategory, gpuLightType, lightVolumeType, light, m_lightList.lights[m_lightList.lights.Count - 1], worldToView);
#if (SHADOWS_ENABLED && SHADOWS_FIXSHADOWIDX)
// fix up shadow information (TODO: Directional bails early, need to fix up that one as well)
// fix up shadow information
int shadowIdx;
if( m_ShadowIndices.TryGetValue( lightIndex, out shadowIdx ) )
{

75
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.cs


using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Profiling;
using System;

m_SampSlot = IsNativeDepth() ? sc.RequestSamplerSlot( m_CompSamplerState ) : sc.RequestSamplerSlot( m_SamplerState );
}
public override void Fill( ShadowContextStorage cs )
override public void Fill( ShadowContextStorage cs )
{
cs.SetTex2DArraySlot( m_TexSlot, m_ShadowmapId );
}

public VectorArray<int> payloads { get { return m_Payloads; } set { m_Payloads = value; } }
}
private const int k_MaxShadowmapPerType = 4;
private ShadowmapBase m_Shadowmap;
private ShadowmapBase[] m_Shadowmaps;
private ShadowmapBase[,] m_ShadowmapsPerType = new ShadowmapBase[(int)GPUShadowType.MAX, k_MaxShadowmapPerType];
private ShadowContextAccess m_ShadowCtxt;
private int[,] m_MaxShadows = new int[(int)GPUShadowType.MAX,2];
// The following vectors are just temporary helpers to avoid reallocation each frame. Contents are not stable.

private ShadowIndicesVector m_ShadowIndices = new ShadowIndicesVector( 0, false );
public ShadowManager( ShadowSettings shadowSettings, ref ShadowContext.CtxtInit ctxtInitializer, ShadowmapBase shadowmap )
public ShadowManager( ShadowSettings shadowSettings, ref ShadowContext.CtxtInit ctxtInitializer, ShadowmapBase[] shadowmaps )
m_Shadowmap = shadowmap;
m_Shadowmap.ReserveSlots( m_ShadowCtxt );
Debug.Assert( shadowmaps != null && shadowmaps.Length > 0 );
m_Shadowmaps = shadowmaps;
foreach( var sm in shadowmaps )
{
sm.ReserveSlots( m_ShadowCtxt );
ShadowmapBase.ShadowSupport smsupport = sm.QueryShadowSupport();
for( int i = 0, bit = 1; i < (int) GPUShadowType.MAX; ++i, bit <<= 1 )
{
if( ((int)smsupport & bit) == 0 )
continue;
for( int idx = 0; i < k_MaxShadowmapPerType; ++idx )
{
if( m_ShadowmapsPerType[i,idx] == null )
{
m_ShadowmapsPerType[i,idx] = sm;
break;
}
}
Debug.Assert( m_ShadowmapsPerType[i,k_MaxShadowmapPerType-1] == null || m_ShadowmapsPerType[i,k_MaxShadowmapPerType-1] == sm,
"Only up to " + k_MaxShadowmapPerType + " are allowed per light type. If more are needed then increase ShadowManager.k_MaxShadowmapPerType" );
}
}
m_MaxShadows[(int)GPUShadowType.Point ,0] = m_MaxShadows[(int)GPUShadowType.Point ,1] = 4;
m_MaxShadows[(int)GPUShadowType.Spot ,0] = m_MaxShadows[(int)GPUShadowType.Spot ,1] = 8;

// TODO:
// Cached the cullResults here so we don't need to pass them around.
// Allocate needs to pass them to the shadowmap, as the ShadowUtil functions calculating view/proj matrices need them to call into C++ land.
// Allocate needs to pass them to the shadowmaps, as the ShadowUtil functions calculating view/proj matrices need them to call into C++ land.
m_Shadowmap.Assign( cullResults );
foreach( var sm in m_Shadowmaps )
{
sm.Assign( cullResults );
}
if( shadowRequestsCount == 0 || lights == null || shadowRequests == null )
{

AdditionalLightData ald = l.GetComponent<AdditionalLightData>();
// set light specific values that are not related to the shadowmap
ShadowUtils.MapLightType( ald.archetype, vl.lightType, out sd.lightType );
GPUShadowType shadowtype;
ShadowUtils.MapLightType( ald.archetype, vl.lightType, out sd.lightType, out shadowtype );
if( !m_Shadowmap.Reserve( frameId, ref sd, grantedRequests[i], (uint) ald.shadowResolution, (uint) ald.shadowResolution, ref shadowDatas, ref shadowmapPayload, lights ) )
throw new ArgumentException("The requested shadows do not fit into the shadowmap.");
int smidx = 0;
while( smidx < k_MaxShadowmapPerType )
{
if( m_ShadowmapsPerType[(int)shadowtype,smidx].Reserve( frameId, ref sd, grantedRequests[i], (uint) ald.shadowResolution, (uint) ald.shadowResolution, ref shadowDatas, ref shadowmapPayload, lights ) )
break;
smidx++;
}
if( smidx == k_MaxShadowmapPerType )
throw new ArgumentException("The requested shadows do not fit into any shadowmap.");
if( !m_Shadowmap.ReserveFinalize( frameId, ref shadowDatas, ref shadowmapPayload ) )
throw new ArgumentException( "Shadow allocation failed in the ReserveFinalize step." );
foreach( var sm in m_Shadowmaps )
{
if( !sm.ReserveFinalize( frameId, ref shadowDatas, ref shadowmapPayload ) )
throw new ArgumentException( "Shadow allocation failed in the ReserveFinalize step." );
}
}
public override void RenderShadows( FrameId frameId, ScriptableRenderContext renderContext, CullResults cullResults, VisibleLight[] lights )

m_Shadowmap.Update( frameId, renderContext, cullResults, lights );
foreach( var sm in m_Shadowmaps )
{
sm.Update( frameId, renderContext, cullResults, lights );
}
}
}

public override void BindResources( ScriptableRenderContext renderContext )
{
m_Shadowmap.Fill( m_ShadowCtxt );
foreach( var sm in m_Shadowmaps )
{
sm.Fill( m_ShadowCtxt );
}
CommandBuffer cb = new CommandBuffer(); // <- can we just keep this around or does this have to be newed every frame?
cb.name = "Bind resources to GPU";
m_ShadowCtxt.BindResources( cb );

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl


#define SHADOWS_USE_SHADOWCTXT
#ifdef SHADOWS_USE_SHADOWCTXT
#define SHADOW_SUPPORTS_DYNAMIC_INDEXING 0
#define SHADOW_SUPPORTS_DYNAMIC_INDEXING 0 // only on >= sm 5.1
// TODO: Remove this once we've moved over to the new system. Also delete the undef at the bottom again.
#define ShadowData ShadowDataExp

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


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

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

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

vShadow3x3PCFTerms3 = float4(-sd.texelSizeRcp.x, -sd.texelSizeRcp.y, 0.0f, 0.0f );
float4 v20Taps;
v20Taps.x = SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], float3( posTC.xy + vShadow3x3PCFTerms1.xy, posTC.z ), slice ).x; // 1 1
v20Taps.y = SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], float3( posTC.xy + vShadow3x3PCFTerms1.zy, posTC.z ), slice ).x; // -1 1
v20Taps.z = SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], float3( posTC.xy + vShadow3x3PCFTerms1.xw, posTC.z ), slice ).x; // 1 -1
v20Taps.w = SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], float3( posTC.xy + vShadow3x3PCFTerms1.zw, posTC.z ), slice ).x; // -1 -1
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;

v33Taps.x = SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], float3( posTC.xy + vShadow3x3PCFTerms2.xz, posTC.z ), slice ).x; // 1 0
v33Taps.y = SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], float3( posTC.xy + vShadow3x3PCFTerms3.xz, posTC.z ), slice ).x; // -1 0
v33Taps.z = SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], float3( posTC.xy + vShadow3x3PCFTerms3.zy, posTC.z ), slice ).x; // 0 -1
v33Taps.w = SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], float3( posTC.xy + vShadow3x3PCFTerms2.zy, posTC.z ), slice ).x; // 0 1
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 += SampleShadow_T2DA( shadowContext, texIdx, shadowContext.compSamplers[sampIdx], posTC, slice ).x * vShadow3x3PCFTerms0.z;
flSum += SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, posTC, slice ).x * vShadow3x3PCFTerms0.z;
return flSum;
}

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


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

// Specific implementations managing atlases and the likes should inherit from this
abstract public class ShadowmapBase
{
[Flags]
public enum ShadowSupport
{
Point = 1 << GPUShadowType.Point,
Spot = 1 << GPUShadowType.Spot,
Directional = 1 << GPUShadowType.Directional
}
public struct ShadowRequest
{
private const byte k_IndexBits = 24;

protected readonly float m_WidthRcp;
protected readonly float m_HeightRcp;
protected readonly uint m_MaxPayloadCount;
protected readonly ShadowSupport m_ShadowSupport;
protected uint m_ShadowId;
protected CullResults m_CullResults; // TODO: Temporary, due to CullResults dependency in ShadowUtils' matrix extraction code. Remove this member once that dependency is gone.

public ComparisonSamplerState comparisonSamplerState; // the desired sampler state for native shadowmaps doing depth comparisons as well
public Vector4 clearColor; // the clear color used for non-native shadowmaps
public uint maxPayloadCount; // how many ints will be pushed into the payload buffer for each invocation of Reserve
public ShadowSupport shadowSupport; // bitmask of all shadow types that this shadowmap supports
};
protected ShadowmapBase( ref BaseInit initializer )

m_WidthRcp = 1.0f / initializer.width;
m_HeightRcp = 1.0f / initializer.height;
m_MaxPayloadCount = initializer.maxPayloadCount;
m_ShadowSupport = initializer.shadowSupport;
m_ShadowId = 0;
if( IsNativeDepth() && m_Slices > 1 )

}
public ShadowSupport QueryShadowSupport() { return m_ShadowSupport; }
public uint GetMaxPayload() { return m_MaxPayloadCount; }
public void AssignId( uint shadowId ) { m_ShadowId = shadowId; }
public void Assign( CullResults cullResults ) { m_CullResults = cullResults; } // TODO: Remove when m_CullResults is removed again

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


#define SHADOWCONTEXT_MAX_TEX2DARRAY 2
#define SHADOWCONTEXT_MAX_TEXCUBEARRAY 2
#define SHADOWCONTEXT_MAX_SAMPLER 2
#define SHADOWCONTEXT_MAX_COMPSAMPLER 1
#define SHADOWCONTEXT_MAX_COMPSAMPLER 2
TEXTURE2D_ARRAY(_ShadowmapExp);
SAMPLER2D_SHADOW(sampler_ShadowmapExp);
TEXTURE2D_ARRAY(_ShadowmapMomentum);
SAMPLER2D(sampler_ShadowmapMomentum);
TEXTURE2D_ARRAY(_ShadowmapExp_Dir);
SAMPLER2D_SHADOW(sampler_ShadowmapExp_Dir);
TEXTURE2D_ARRAY(_ShadowmapExp_PointSpot);
SAMPLER2D_SHADOW(sampler_ShadowmapExp_PointSpot);
ShadowContext InitShadowContext()

sc.payloads = _ShadowPayloads;
sc.tex2DArray[0] = _ShadowmapExp;
sc.tex2DArray[1] = _ShadowmapMomentum;
sc.compSamplers[0] = sampler_ShadowmapExp;
sc.samplers[0] = sampler_ShadowmapMomentum;
sc.tex2DArray[0] = _ShadowmapExp_Dir;
sc.tex2DArray[1] = _ShadowmapExp_PointSpot;
sc.compSamplers[0] = sampler_ShadowmapExp_Dir;
sc.compSamplers[1] = sampler_ShadowmapExp_PointSpot;

14
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowDispatch.hlsl


// Check Shadow.hlsl right below where this header is included for the individual defines.
// example of overriding directional lights
#define SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL
//#define SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL
#ifdef SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L )
{

#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, int shadowDataIndex, float3 L )
{
Texture2DArray tex = shadowContext.tex2DArray[0];
SamplerComparisonState compSamp = shadowContext.compSamplers[0];
Texture2DArray tex = shadowContext.tex2DArray[1];
SamplerComparisonState compSamp = shadowContext.compSamplers[1];
return EvalShadow_PunctualDepth( shadowContext, positionWS, shadowDataIndex, L );
return EvalShadow_PunctualDepth( shadowContext, tex, compSamp, positionWS, shadowDataIndex, L );
Texture2DArray tex = shadowContext.tex2DArray[0];
SamplerComparisonState compSamp = shadowContext.compSamplers[0];
Texture2DArray tex = shadowContext.tex2DArray[1];
SamplerComparisonState compSamp = shadowContext.compSamplers[1];
return EvalShadow_PunctualDepth( shadowContext, positionWS, shadowDataIndex, L );
return EvalShadow_PunctualDepth( shadowContext, tex, compSamp, positionWS, shadowDataIndex, L );
}
#endif

149
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowTexFetch.hlsl


// shadow lookup routines when dynamic array access is possible
#if SHADOW_SUPPORTS_DYNAMIC_INDEXING != 0
// Shader model >= 5.1
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, SamplerComparisonState ss, float3 tcs, float slice ) { return SAMPLE_TEXTURE2D_ARRAY_SHADOW(ctxt.tex2DArray[texIdx], ss, tcs, slice); } \
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, SamplerState ss, float2 tcs, float slice, float lod = 0.0 ) { return SAMPLE_TEXTURE2D_ARRAY_LOD(ctxt.tex2DArray[texIdx], ss, tcs, slice, lod); } \
float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, SamplerComparisonState ss, float4 tcs, float cubeIdx ) { return SAMPLE_TEXTURECUBE_ARRAY_SHADOW(ctxt.texCubeArray[texIdx], ss, tcs, cubeIdx); } \
float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, SamplerState ss, float3 tcs, float cubeIdx, float lod = 0.0) { return SAMPLE_TEXTURECUBE_ARRAY_LOD(ctxt.texCubeArray[texIdx], ss, tcs, cubeIdx, lod);}
float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ) { return SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[texIdx], ctxt.compSamplers[sampIdx], tcs, slice ); } \
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ) { return SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[texIdx], ctxt.samplers[sampIdx], tcs, slice, lod ); } \
float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ) { return SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[texIdx], ctxt.compSamplers[sampIdx], tcs, cubeIdx );} \
float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ) { return SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[texIdx], ctxt.samplers[sampIdx], tcs, cubeIdx, lod ); }
// recursion helpers
# define SHADOW_T2DA_SAMPLE_COMP( _idx ) case _idx : return SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[_idx], ss, tcs, slice );
# define SHADOW_T2DA_SAMPLE( _idx ) case _idx : return SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[_idx], ss, tcs.xy, tcs.z, lod );
# define SHADOW_TCA_SAMPLE_COMP( _idx ) case _idx : return SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[texIdx], ss, tcs, cubeIdx );
# define SHADOW_TCA_SAMPLE( _idx ) case _idx : return SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[texIdx], ss, tcs, cubeIdx, lod );
// poor man's recursion
# define SHADOW_REC_FUNC( _a, _b, _idx ) _a ## _b( _idx )
# define SHADOW_REC0( _a, _b) // expands to nothing
# define SHADOW_REC1( _a, _b) default: \
SHADOW_REC_FUNC( _a, _b, 0 )
# define SHADOW_REC2( _a, _b) SHADOW_REC1( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 1 )
# define SHADOW_REC3( _a, _b) SHADOW_REC2( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 2 )
# define SHADOW_REC4( _a, _b) SHADOW_REC3( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 3 )
# define SHADOW_REC5( _a, _b) SHADOW_REC4( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 4 )
# define SHADOW_REC6( _a, _b) SHADOW_REC5( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 5 )
# define SHADOW_REC7( _a, _b) SHADOW_REC6( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 6 )
# define SHADOW_REC8( _a, _b) SHADOW_REC7( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 7 )
# define SHADOW_REC9( _a, _b) SHADOW_REC8( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 8 )
# define SHADOW_REC10( _a, _b) SHADOW_REC9( _a, _b ) \
SHADOW_REC_FUNC( _a, _b, 9 )
// standard macro helpers
# define SHADOW_EXPAND( _x ) _x
# define SHADOW_CAT( _x, _y ) _x ## _y
# define SHADOW_REC_ENTRY( _x, _y, _z, _w ) SHADOW_CAT( _x, _y )( _z, _w )
// and the actual definition of the sampling functions
# define SHADOW_DEFINE_SAMPLING_FUNCS( _Tex2DArraySlots, _TexCubeArraySlots, _SamplerCompSlots, _SamplerSlots ) \
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, SamplerComparisonState ss, float3 tcs, float slice ) \
{ \
[branch] \
switch( texIdx ) \
{ \
SHADOW_REC_ENTRY( SHADOW_REC, SHADOW_EXPAND( _Tex2DArraySlots ), SHADOW_T2DA_, SAMPLE_COMP ) \
} \
} \
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, SamplerState ss, float3 tcs, float lod = 0.0 ) \
{ \
[branch] \
switch( texIdx ) \
{ \
SHADOW_REC_ENTRY( SHADOW_REC, SHADOW_EXPAND( _Tex2DArraySlots ), SHADOW_T2DA_, SAMPLE ) \
} \
} \
float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, SamplerComparisonState ss, float4 tcs, float cubeIdx ) \
{ \
[branch] \
switch( texIdx ) \
{ \
SHADOW_REC_ENTRY( SHADOW_REC, SHADOW_EXPAND( _TexCubeArraySlots ), SHADOW_TCA_, SAMPLE_COMP ) \
} \
} \
float4 SampleShadow_TCA(ShadowContext ctxt, uint texIdx, SamplerState ss, float3 tcs, float cubeIdx, float lod = 0.0 ) \
{ \
[branch] \
switch( texIdx ) \
{ \
SHADOW_REC_ENTRY( SHADOW_REC, SHADOW_EXPAND( _TexCubeArraySlots ), SHADOW_TCA_, SAMPLE ) \
} \
// Sampler and texture combinations are static. No shadowmap will ever be sampled with two different samplers.
// Once shadowmaps and samplers are fixed consider writing custom dispatchers directly accessing textures and samplers.
# define SHADOW_DEFINE_SAMPLING_FUNCS( _Tex2DArraySlots, _TexCubeArraySlots, _SamplerCompSlots, _SamplerSlots ) \
\
float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ) \
{ \
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \
{ \
[unroll] for( uint j = 0; j < _SamplerCompSlots; j++ ) \
{ \
[branch] if( i == texIdx && j == sampIdx ) \
{ \
return SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[i], ctxt.compSamplers[j], tcs, slice ); \
} \
} \
} \
return 1.0; \
} \
\
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ) \
{ \
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \
{ \
[unroll] for( uint j = 0; j < _SamplerSlots; j++ ) \
{ \
[branch] if( i == texIdx && j == sampIdx ) \
{ \
return SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[i], ctxt.samplers[j], tcs, slice, lod ); \
} \
} \
} \
return 1.0; \
} \
\
float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ) \
{ \
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \
{ \
[unroll] for( uint j = 0; j < _SamplerCompSlots; j++ ) \
{ \
[branch] if( i == texIdx && j == sampIdx ) \
{ \
return SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[i], ctxt.compSamplers[j], tcs, cubeIdx ); \
} \
} \
} \
return 1.0; \
} \
\
float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ) \
{ \
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \
{ \
[unroll] for( uint j = 0; j < _SamplerSlots; j++ ) \
{ \
[branch] if( i == texIdx && j == sampIdx ) \
{ \
return SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[i], ctxt.samplers[j], tcs, cubeIdx, lod ); \
} \
} \
} \
return 1.0; \
#endif

20
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowUtilities.cs


return proj * view;
}
public static bool MapLightType( LightArchetype la, LightType lt, out GPULightType gputype )
public static bool MapLightType( LightArchetype la, LightType lt, out GPULightType gputype, out GPUShadowType shadowtype )
case LightArchetype.Punctual : return MapLightType( lt, out gputype );
case LightArchetype.Rectangle : gputype = GPULightType.Rectangle; return true;
case LightArchetype.Line : gputype = GPULightType.Line; return true;
default : gputype = GPULightType.Spot; return false; // <- probably not what you want
case LightArchetype.Punctual : return MapLightType( lt, out gputype, out shadowtype );
case LightArchetype.Rectangle : gputype = GPULightType.Rectangle; shadowtype = GPUShadowType.Unknown; return true;
case LightArchetype.Line : gputype = GPULightType.Line; shadowtype = GPUShadowType.Unknown; return true;
default : gputype = GPULightType.Spot; shadowtype = GPUShadowType.Unknown; return false; // <- probably not what you want
public static bool MapLightType( LightType lt, out GPULightType gputype )
public static bool MapLightType( LightType lt, out GPULightType gputype, out GPUShadowType shadowtype )
case LightType.Spot : gputype = GPULightType.Spot; return true;
case LightType.Directional : gputype = GPULightType.Directional; return true;
case LightType.Point : gputype = GPULightType.Point; return true;
case LightType.Spot : gputype = GPULightType.Spot; shadowtype = GPUShadowType.Spot; return true;
case LightType.Directional : gputype = GPULightType.Directional; shadowtype = GPUShadowType.Directional; return true;
case LightType.Point : gputype = GPULightType.Point; shadowtype = GPUShadowType.Point; return true;
case LightType.Area : gputype = GPULightType.Rectangle; return false; // area lights by themselves can't be mapped to any GPU type
case LightType.Area : gputype = GPULightType.Rectangle; shadowtype = GPUShadowType.Unknown; return false; // area lights by themselves can't be mapped to any GPU type
}
}

正在加载...
取消
保存