浏览代码

PCSS is now working

/main
Antoine Lelievre 6 年前
当前提交
3072fc83
共有 8 个文件被更改,包括 180 次插入58 次删除
  1. 92
      com.unity.render-pipelines.core/CoreRP/ShaderLibrary/Shadow/PCSS.hlsl
  2. 49
      com.unity.render-pipelines.core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl
  3. 9
      com.unity.render-pipelines.core/CoreRP/Shadow/AdditionalShadowData.cs
  4. 65
      com.unity.render-pipelines.core/CoreRP/Shadow/Shadow.cs
  5. 3
      com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/AdditionalShadowDataEditor.cs
  6. 2
      com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.Styles.cs
  7. 6
      com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.cs
  8. 12
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoop.cs

92
com.unity.render-pipelines.core/CoreRP/ShaderLibrary/Shadow/PCSS.hlsl


return abs((Reciever - Blocker) / Blocker);
}
bool BlockerSearch(inout real AverageBlockerDepth, inout real NumBlockers, real LightArea, real3 Coord, float Slice, real2 SampleBias, Texture2DArray ShadowMap, SamplerState PointSampler)
bool BlockerSearch(inout real AverageBlockerDepth, inout real NumBlockers, real LightArea, real3 coord, float slice, real2 sampleBias, Texture2DArray shadowMap, SamplerState PointSampler, int sampleCount )
return 0;
real2 Offset = real2(PoissonDisk64[i].x * SampleBias.y + PoissonDisk64[i].y * SampleBias.x,
PoissonDisk64[i].x * -SampleBias.x + PoissonDisk64[i].y * SampleBias.y) * LightArea;
real2 Offset = real2(PoissonDisk64[i].x * sampleBias.y + PoissonDisk64[i].y * sampleBias.x,
PoissonDisk64[i].x * -sampleBias.x + PoissonDisk64[i].y * sampleBias.y) * LightArea;
real ShadowMapDepth = SAMPLE_TEXTURE2D_ARRAY_LOD( ShadowMap, PointSampler, Coord.xy + Offset, Slice, 0.0 ).x;
real ShadowMapDepth = SAMPLE_TEXTURE2D_ARRAY_LOD( shadowMap, PointSampler, coord.xy + Offset, slice, 0.0 ).x;
if(ShadowMapDepth > Coord.z)
if(ShadowMapDepth > coord.z)
{
BlockerSum += ShadowMapDepth;
NumBlockers += 1.0;

return true;
}
real PCSS(real3 Coord, real FilterRadius, real4 ScaleOffset, float Slice, real2 SampleBias, Texture2DArray ShadowMap, SamplerComparisonState CompSampler)
bool BlockerSearch(inout real AverageBlockerDepth, inout real NumBlockers, real LightArea, real3 coord, real2 sampleBias, ShadowContext shadowContext, float slice, uint texIdx, uint sampIdx, int sampleCount )
real UMin = ScaleOffset.z;
real UMax = ScaleOffset.z + ScaleOffset.x;
return 0;
real BlockerSum = 0.0;
for (int i = 0; i < 64; ++i)
{
real2 offset = real2(PoissonDisk64[i].x * sampleBias.y + PoissonDisk64[i].y * sampleBias.x,
PoissonDisk64[i].x * -sampleBias.x + PoissonDisk64[i].y * sampleBias.y) * LightArea;
real VMin = ScaleOffset.w;
real VMax = ScaleOffset.w + ScaleOffset.y;
real ShadowMapDepth = SampleCompShadow_T2DA(shadowContext, texIdx, sampIdx, coord.xyz, slice).x;
if(ShadowMapDepth > coord.z)
{
BlockerSum += ShadowMapDepth;
NumBlockers += 1.0;
}
}
AverageBlockerDepth = BlockerSum / NumBlockers;
if (NumBlockers < 1)
return false;
return true;
}
real PCSS(real3 coord, real filterRadius, real4 scaleOffset, float slice, real2 sampleBias, Texture2DArray shadowMap, SamplerComparisonState compSampler, int sampleCount )
{
return 0;
real UMin = scaleOffset.z;
real UMax = scaleOffset.z + scaleOffset.x;
real VMin = scaleOffset.w;
real VMax = scaleOffset.w + scaleOffset.y;
for(int i = 0; i < 64; ++i)
for(int i = 0; i < sampleCount; ++i)
real2 Offset = real2(PoissonDisk64[i].x * SampleBias.y + PoissonDisk64[i].y * SampleBias.x,
PoissonDisk64[i].x * -SampleBias.x + PoissonDisk64[i].y * SampleBias.y) * FilterRadius;
real2 offset = real2(PoissonDisk64[i].x * sampleBias.y + PoissonDisk64[i].y * sampleBias.x,
PoissonDisk64[i].x * -sampleBias.x + PoissonDisk64[i].y * sampleBias.y) * filterRadius;
real U = Coord.x + Offset.x;
real V = Coord.y + Offset.y;
real U = coord.x + offset.x;
real V = coord.y + offset.y;
Sum += SAMPLE_TEXTURE2D_ARRAY_SHADOW(ShadowMap, CompSampler, real3(Coord.xy, Coord.z), Slice);
Sum += SAMPLE_TEXTURE2D_ARRAY_SHADOW(shadowMap, compSampler, real3(coord.xy, coord.z), slice);
Sum += SAMPLE_TEXTURE2D_ARRAY_SHADOW(ShadowMap, CompSampler, real3(U, V, Coord.z), Slice);
Sum += SAMPLE_TEXTURE2D_ARRAY_SHADOW(shadowMap, compSampler, real3(U, V, coord.z), slice);
return Sum / 64.0;
return Sum / sampleCount;
}
real PCSS(real3 coord, real filterRadius, real4 scaleOffset, float slice, real2 sampleBias, ShadowContext shadowContext, uint texIdx, uint sampIdx, int sampleCount )
{
return 0;
real UMin = scaleOffset.z;
real UMax = scaleOffset.z + scaleOffset.x;
real VMin = scaleOffset.w;
real VMax = scaleOffset.w + scaleOffset.y;
real Sum = 0.0;
for(int i = 0; i < sampleCount; ++i)
{
real2 offset = real2(PoissonDisk64[i].x * sampleBias.y + PoissonDisk64[i].y * sampleBias.x,
PoissonDisk64[i].x * -sampleBias.x + PoissonDisk64[i].y * sampleBias.y) * filterRadius;
real U = coord.x + offset.x;
real V = coord.y + offset.y;
//NOTE: We must clamp the sampling within the bounds of the shadow atlas.
// Overfiltering will leak results from other shadow lights.
//TODO: Investigate moving this to blocker search.
if (U <= UMin || U >= UMax || V <= VMin || V >= VMax)
Sum += SampleCompShadow_T2DA(shadowContext, texIdx, sampIdx, real3(coord.xy, coord.z), slice);
else
Sum += SampleCompShadow_T2DA(shadowContext, texIdx, sampIdx, real3(U, V, coord.z), slice);
}
return Sum / sampleCount;
}

49
com.unity.render-pipelines.core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl


}
#include "PCSS.hlsl"
real SampleShadow_PCSS(ShadowContext shadowContext, inout uint payloadOffset, real3 coord, real4 scaleOffset, float slice, Texture2DArray tex, SamplerComparisonState compSamp, SamplerState samp)
real SampleShadow_PCSS( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, real4 scaleOffset, real2 sampleBias, float slice, uint texIdx, uint sampIdx )
return 1;
real LightArea = (params.x / 255.0); //TODO: Floats through payload.
real MinimumFilterSize = (params.y / 255.0);
real shadowSoftnesss = params.x;
int sampleCount = params.y;
real2 SampleBias = real2(sin(GenerateHashedRandomFloat(asuint(coord.x))),
cos(GenerateHashedRandomFloat(asuint(coord.y))));
real2 SampleBias = real2(sin(GenerateHashedRandomFloat(asuint(tcs.x))),
cos(GenerateHashedRandomFloat(asuint(tcs.y))));
if (!BlockerSearch(AverageBlockerDepth, NumBlockers, LightArea + MinimumFilterSize, coord, slice, SampleBias, tex, samp))
if (!BlockerSearch(AverageBlockerDepth, NumBlockers, shadowSoftnesss + 0.001, tcs, sampleBias, shadowContext, slice, texIdx, sampIdx, sampleCount))
real FilterSize = LightArea * PenumbraSize(coord.z, AverageBlockerDepth);
FilterSize = max(FilterSize, MinimumFilterSize);
real FilterSize = shadowSoftnesss * PenumbraSize(tcs.z, AverageBlockerDepth);
FilterSize = max(FilterSize, 0.001);
//3) Filter
return PCSS(tcs, FilterSize, scaleOffset, slice, SampleBias, shadowContext, texIdx, sampIdx, sampleCount);
}
real SampleShadow_PCSS( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, real4 scaleOffset, float slice, Texture2DArray tex, SamplerComparisonState compSamp, SamplerState samp )
{
return 1;
real2 params = asfloat(shadowContext.payloads[payloadOffset].xy);
real shadowSoftnesss = params.x;
int sampleCount = params.y;
payloadOffset++;
real2 SampleBias = real2(sin(GenerateHashedRandomFloat(asuint(tcs.x))),
cos(GenerateHashedRandomFloat(asuint(tcs.y))));
//1) Blocker Search
real AverageBlockerDepth = 0.0;
real NumBlockers = 0.0;
// if (!BlockerSearch(AverageBlockerDepth, NumBlockers, shadowSoftnesss + 0.001, tcs, slice, SampleBias, tex, samp, sampleCount))
// return 1.0;
//2) Penumbra Estimation
real FilterSize = shadowSoftnesss * PenumbraSize(tcs.z, AverageBlockerDepth);
FilterSize = max(FilterSize, 0.001);
return PCSS(coord, FilterSize, scaleOffset, slice, SampleBias, tex, compSamp);
return PCSS(tcs, FilterSize, scaleOffset, slice, SampleBias, tex, compSamp, sampleCount);
//-----------------------------------------------------------------------------------------------------
// helper function to dispatch a specific shadow algorithm
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real2 sampleBias, uint algorithm, uint texIdx, uint sampIdx )

case GPUSHADOWALGORITHM_PCF_TENT_3X3 : return SampleShadow_PCF_Tent_3x3( shadowContext, payloadOffset, shadowData.textureSize, shadowData.texelSizeRcp, posTC, sampleBias, shadowData.slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_TENT_5X5 : return SampleShadow_PCF_Tent_5x5( shadowContext, payloadOffset, shadowData.textureSize, shadowData.texelSizeRcp, posTC, sampleBias, shadowData.slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_TENT_7X7 : return SampleShadow_PCF_Tent_7x7( shadowContext, payloadOffset, shadowData.textureSize, shadowData.texelSizeRcp, posTC, sampleBias, shadowData.slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCSS : return SampleShadow_PCSS( shadowContext, payloadOffset, posTC, shadowData.scaleOffset, sampleBias, shadowData.slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_VSM : return SampleShadow_VSM_1tap( shadowContext, payloadOffset, posTC, shadowData.slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_EVSM_2 : return SampleShadow_EVSM_1tap( shadowContext, payloadOffset, posTC, shadowData.slice, texIdx, sampIdx, false );
case GPUSHADOWALGORITHM_EVSM_4 : return SampleShadow_EVSM_1tap( shadowContext, payloadOffset, posTC, shadowData.slice, texIdx, sampIdx, true );

case GPUSHADOWALGORITHM_PCF_TENT_3X3 : return SampleShadow_PCF_Tent_3x3( shadowContext, payloadOffset, shadowData.textureSize, shadowData.texelSizeRcp, posTC, sampleBias, shadowData.slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_TENT_5X5 : return SampleShadow_PCF_Tent_5x5( shadowContext, payloadOffset, shadowData.textureSize, shadowData.texelSizeRcp, posTC, sampleBias, shadowData.slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_TENT_7X7 : return SampleShadow_PCF_Tent_7x7( shadowContext, payloadOffset, shadowData.textureSize, shadowData.texelSizeRcp, posTC, sampleBias, shadowData.slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCSS : return SampleShadow_PCSS(shadowContext, payloadOffset, posTC, shadowData.scaleOffset, shadowData.slice, tex, compSamp, s_point_clamp_sampler);
case GPUSHADOWALGORITHM_PCSS : return SampleShadow_PCSS( shadowContext, payloadOffset, posTC, shadowData.scaleOffset, shadowData.slice, tex, compSamp, s_point_clamp_sampler );
default: return 1.0;
}

9
com.unity.render-pipelines.core/CoreRP/Shadow/AdditionalShadowData.cs


return DefaultShadowResolution;
}
//TODO: put these elsewhere ?
// PCSS specific parameters (can be moved somewhere else)
public float shadowSoftness = 0.5f;
[Range(0.0f, 0.001f)]
public float shadowMinimumSoftness = 0.0f;
public float shadowSoftness = 0.5f;
[Range(0, 64)]
public int sampleCount = 32;
// End of PCSS parameters
[Range(0.0f, 1.0f)]
public float shadowDimmer = 1.0f;

65
com.unity.render-pipelines.core/CoreRP/Shadow/Shadow.cs


readonly ValRange m_DefPCF_DepthBias = new ValRange("Depth Bias", 0.0f, 0.0f, 1.0f, 000.1f);
readonly ValRange m_DefPCF_FilterSize = new ValRange("Filter Size", 1.0f, 1.0f, 10.0f, 1.0f);
readonly ValRange m_DefPCSS_ShadowSoftness = new ValRange("Shadow Softness", 0.0f, 0.5f, 1.0f, 0.01f);
readonly ValRange m_DefPCSS_SampleCount = new ValRange("Sample Count", 0, 32, 64, 1);
public ShadowAtlas(ref AtlasInit init) : base(ref init.baseInit)
{

if (dataVariant == ShadowVariant.V1)
m_DefPCF_FilterSize.Slider(ref dataBlock[1]);
};
ShadowRegistry.VariantDelegate pcssDel = (Light l, ShadowAlgorithm dataAlgorithm, ShadowVariant dataVariant, ShadowPrecision dataPrecision, ref int[] dataBlock) =>
{
CheckDataIntegrity(dataAlgorithm, dataVariant, dataPrecision, ref dataBlock);
m_DefPCSS_ShadowSoftness.Slider(ref dataBlock[0]);
m_DefPCSS_SampleCount.Slider(ref dataBlock[1]);
};
registry.Register(type, precision, ShadowAlgorithm.PCF, "Percentage Closer Filtering (PCF)",
new ShadowVariant[] { ShadowVariant.V0, ShadowVariant.V1, ShadowVariant.V2, ShadowVariant.V3, ShadowVariant.V4 },
new string[] {"1 tap", "9 tap adaptive", "tent 3x3 (4 taps)", "tent 5x5 (9 taps)", "tent 7x7 (16 taps)" },

new ShadowVariant[] { ShadowVariant.V0 },
new string[] { "poisson 64" },
new ShadowRegistry.VariantDelegate[] { del });
new ShadowRegistry.VariantDelegate[] { pcssDel });
if (algorithm != ShadowAlgorithm.PCF ||
if ((algorithm != ShadowAlgorithm.PCF && algorithm != ShadowAlgorithm.PCSS) ||
(variant != ShadowVariant.V0 &&
variant != ShadowVariant.V1 &&
variant != ShadowVariant.V2 &&

const int k_BlockSize = 2;
if (dataBlock == null || dataBlock.Length != k_BlockSize)
switch (algorithm)
// set defaults
dataBlock = new int[k_BlockSize];
dataBlock[0] = m_DefPCF_DepthBias.Default();
dataBlock[1] = m_DefPCF_FilterSize.Default();
return false;
case ShadowAlgorithm.PCF:
const int k_PcfBlockSize = 2;
if (dataBlock == null || dataBlock.Length != k_PcfBlockSize)
{
// set defaults
dataBlock = new int[k_PcfBlockSize];
dataBlock[0] = m_DefPCF_DepthBias.Default();
dataBlock[1] = m_DefPCF_FilterSize.Default();
return false;
}
break;
case ShadowAlgorithm.PCSS:
const int k_PcssBlockSize = 2;
if (dataBlock == null || dataBlock.Length != k_PcssBlockSize)
{
// set defaults
dataBlock = new int[k_PcssBlockSize];
dataBlock[0] = m_DefPCSS_ShadowSoftness.Default();
dataBlock[1] = m_DefPCSS_SampleCount.Default();
return false;
}
break;
}
return true;
}

virtual protected uint ReservePayload(ShadowRequest sr)
{
uint payloadSize = sr.shadowType == GPUShadowType.Directional ? (1 + k_MaxCascadesInShader + ((uint)m_TmpBorders.Length / 4)) : 0;
payloadSize += ShadowUtils.ExtractAlgorithm(sr.shadowAlgorithm) == ShadowAlgorithm.PCF ? 1u : 0;
payloadSize += ShadowUtils.ExtractAlgorithm(sr.shadowAlgorithm) == ShadowAlgorithm.PCSS ? 1u : 0;
switch (ShadowUtils.ExtractAlgorithm(sr.shadowAlgorithm))
{
case ShadowAlgorithm.PCF:
payloadSize += 1;
break;
case ShadowAlgorithm.PCSS:
payloadSize += 1;
break;
default:
break;
}
return payloadSize;
}

}
else // PCSS
{
sp.Set((0.01f * asd.shadowSoftness) * 255, asd.shadowMinimumSoftness * 255, 0, 0);
sp.Set(shadowData[0], shadowData[1], 0, 0);
payload[payloadOffset] = sp;
payloadOffset++;
}

3
com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/AdditionalShadowDataEditor.cs


namespace UnityEditor.Experimental.Rendering.HDPipeline
{
[CanEditMultipleObjects]
[CustomEditor(typeof(AdditionalShadowData))]
// TODO: uncomment this when the pcss implementation will be finished
// [CustomEditor(typeof(AdditionalShadowData))]
class AdditionalShadowDataEditor : Editor
{
public override void OnInspectorGUI()

2
com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.Styles.cs


public readonly GUIContent shadowDimmer = new GUIContent("Dimmer", "Aim to be use with script, timeline or animation. It allows dimming one or multiple shadows. This can also be used as an optimization to fit in shadow budget manually and minimize popping.");
public readonly GUIContent contactShadows = new GUIContent("Enable Contact Shadows", "Enable support for contact shadows on this light. Better for lights with a lot of visible shadows.");
public readonly GUIContent shadowSoftness = new GUIContent("Penumbra Softness", "TODO !");
public readonly GUIContent shadowMinimumSoftness = new GUIContent("Minimum Penumbra Softness", "TODO !");
public readonly GUIContent pcssSampleCount = new GUIContent("PCSS Sample count", "TODO !");
// Bias control
public readonly GUIContent viewBiasMin = new GUIContent("View Bias");

6
com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.cs


public SerializedProperty resolution;
public SerializedProperty contactShadows;
public SerializedProperty softness;
public SerializedProperty minimumSoftness;
public SerializedProperty pcssSampleCount;
// Bias control
public SerializedProperty viewBiasMin;

resolution = o.Find(x => x.shadowResolution),
contactShadows = o.Find(x => x.contactShadows),
softness = o.Find(x => x.shadowSoftness),
minimumSoftness = o.Find(x => x.shadowMinimumSoftness),
pcssSampleCount = o.Find(x => x.sampleCount),
viewBiasMin = o.Find(x => x.viewBiasMin),
viewBiasMax = o.Find(x => x.viewBiasMax),

//TOOD: check the current shadowing algorithm and hide these fields
EditorGUILayout.Slider(m_AdditionalShadowData.softness, 0.0f, 1.0f, s_Styles.shadowSoftness);
EditorGUILayout.Slider(m_AdditionalShadowData.minimumSoftness, 0.0f, 0.001f, s_Styles.shadowMinimumSoftness);
EditorGUILayout.IntSlider(m_AdditionalShadowData.pcssSampleCount, 0, 64, s_Styles.pcssSampleCount);
EditorGUILayout.PropertyField(m_AdditionalShadowData.contactShadows, s_Styles.contactShadows);

12
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoop.cs


m_ShadowMgr = new ShadowManager(shadowSettings, ref scInit, ref budgets, m_Shadowmaps);
// set global overrides - these need to match the override specified in LightLoop/Shadow.hlsl
bool useGlobalOverrides = true;
/*
//TODO: reset this to true
bool useGlobalOverrides = false;
m_ShadowMgr.SetGlobalShadowOverride(GPUShadowType.Directional , ShadowAlgorithm.PCF, ShadowVariant.V3, ShadowPrecision.High, useGlobalOverrides);*/
//TODO: do not include this in the final PR !
m_ShadowMgr.SetGlobalShadowOverride(GPUShadowType.Point , ShadowAlgorithm.PCSS, ShadowVariant.V0, ShadowPrecision.High, useGlobalOverrides);
m_ShadowMgr.SetGlobalShadowOverride(GPUShadowType.Spot , ShadowAlgorithm.PCSS, ShadowVariant.V0, ShadowPrecision.High, useGlobalOverrides);
m_ShadowMgr.SetGlobalShadowOverride(GPUShadowType.Directional , ShadowAlgorithm.PCSS, ShadowVariant.V0, ShadowPrecision.High, useGlobalOverrides);
m_ShadowMgr.SetGlobalShadowOverride(GPUShadowType.Directional , ShadowAlgorithm.PCF, ShadowVariant.V3, ShadowPrecision.High, useGlobalOverrides);
m_ShadowMgr.SetShadowLightTypeDelegate(HDShadowLightType);

正在加载...
取消
保存