Added pcss shadow implementation. Improved pcf blur samples with poisson disk rotation (#3583)

This commit is contained in:
unravel-dev
2026-02-08 02:16:51 +02:00
committed by GitHub
parent 0f6983be58
commit 6e3186ae6a
10 changed files with 417 additions and 38 deletions

View File

@@ -5,6 +5,23 @@
#include "../common/common.sh"
#define BLOCKER_SEARCH_NUM_SAMPLES 16
#define PCF_LOD_OFFSET_NUM_SAMPLES 16
vec2 sampleVogelDisk(int index, int sampleCount)
{
const float goldenAngle = 2.39996323; // radians
float i = float(index);
float r = sqrt((i + 0.5) / float(sampleCount));
float a = i * goldenAngle;
return vec2(cos(a), sin(a)) * r;
}
vec2 samplePoisson(int index)
{
return sampleVogelDisk(index, 10);
}
float linstep(float _edge0, float _edge1, float _x)
{
return clamp((_x-_edge0)/(_edge1-_edge0), 0.0, 1.0);
@@ -77,52 +94,80 @@ float texcoordInRange(vec2 _texcoord)
return float(inRange);
}
float hardShadow(sampler2D _sampler, vec4 _shadowCoord, float _bias)
// Rotate a 2D sample by a precomputed sin/cos pair.
// _sincos = vec2(sin(angle), cos(angle))
vec2 rotateSample(vec2 _sample, vec2 _sincos)
{
vec2 texCoord = _shadowCoord.xy/_shadowCoord.w;
bool outside = any(greaterThan(texCoord, vec2_splat(1.0)))
|| any(lessThan (texCoord, vec2_splat(0.0)))
;
if (outside)
{
return 1.0;
}
float receiver = (_shadowCoord.z-_bias)/_shadowCoord.w;
float occluder = unpackRgbaToFloat(texture2D(_sampler, texCoord) );
float visibility = step(receiver, occluder);
return visibility;
return vec2(_sample.x * _sincos.y - _sample.y * _sincos.x,
_sample.x * _sincos.x + _sample.y * _sincos.y);
}
float PCF(sampler2D _sampler, vec4 _shadowCoord, float _bias, vec4 _pcfParams, vec2 _texelSize)
// Interleaved gradient noise for per-pixel Poisson disk rotation.
// Produces well-distributed noise that avoids the clustering artifacts of
// traditional fract(sin(...)) hashes. Converts structured Poisson banding
// into smooth, perceptually-uniform noise.
// Source: "Next Generation Post Processing in Call of Duty: AW" (Jimenez 2014)
float interleavedGradientNoise(vec2 _screenPos)
{
float result = 0.0;
vec2 offset = _pcfParams.zw * _texelSize * _shadowCoord.w;
vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189);
return fract(magic.z * fract(dot(_screenPos, magic.xy)));
}
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-1.5, -1.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-1.5, -0.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-1.5, 0.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-1.5, 1.5) * offset, 0.0, 0.0), _bias);
float hardShadowLod(sampler2D _sampler, float lod, vec4 _shadowCoord, float _bias)
{
vec2 texCoord = _shadowCoord.xy/_shadowCoord.w;
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-0.5, -1.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-0.5, -0.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-0.5, 0.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-0.5, 1.5) * offset, 0.0, 0.0), _bias);
bool outside = any(greaterThan(texCoord, vec2_splat(1.0)))
|| any(lessThan (texCoord, vec2_splat(0.0)))
;
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(0.5, -1.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(0.5, -0.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(0.5, 0.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(0.5, 1.5) * offset, 0.0, 0.0), _bias);
if (outside)
{
return 1.0;
}
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(1.5, -1.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(1.5, -0.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(1.5, 0.5) * offset, 0.0, 0.0), _bias);
result += hardShadow(_sampler, _shadowCoord + vec4(vec2(1.5, 1.5) * offset, 0.0, 0.0), _bias);
float receiver = (_shadowCoord.z-_bias)/_shadowCoord.w;
float occluder = unpackRgbaToFloat(texture2DLod(_sampler, texCoord, lod) );
return result / 16.0;
float visibility = step(receiver, occluder);
return visibility;
}
float hardShadow(sampler2D _sampler, vec4 _shadowCoord, float _bias)
{
return hardShadowLod(_sampler, 0.0, _shadowCoord, _bias);
}
// _diskRotation = vec2(sin(angle), cos(angle)) for per-pixel Poisson disk rotation.
// Pass vec2(0.0, 1.0) for no rotation (identity).
float PCFLodOffset(sampler2D _sampler, float lod, vec2 offset, vec4 _shadowCoord, float _bias, vec2 _texelSize, vec2 _diskRotation)
{
float result = 0.0;
for ( int i = 0; i < PCF_LOD_OFFSET_NUM_SAMPLES; ++i )
{
vec2 jitteredOffset = rotateSample(samplePoisson(i), _diskRotation) * offset;
result += hardShadowLod(_sampler, lod, _shadowCoord + vec4(jitteredOffset, 0.0, 0.0), _bias);
}
return result / float(PCF_LOD_OFFSET_NUM_SAMPLES);
}
float PCFLod(sampler2D _sampler, float lod, vec2 filterRadius, vec4 _shadowCoord, float _bias, vec4 _pcfParams, vec2 _texelSize, vec2 _diskRotation)
{
vec2 offset = filterRadius * _pcfParams.zw * _texelSize * _shadowCoord.w;
return PCFLodOffset(_sampler, lod, offset, _shadowCoord, _bias, _texelSize, _diskRotation);
}
float PCF(sampler2D _sampler, vec4 _shadowCoord, float _bias, vec4 _pcfParams, vec2 _texelSize, vec2 fragCoord)
{
// Per-pixel Poisson disk rotation from shadow map texel coordinates
vec2 noiseCoord = fragCoord;
//vec2 noiseCoord = (_shadowCoord.xy / _shadowCoord.w) * (1.0 / _texelSize.x);
float angle = interleavedGradientNoise(noiseCoord) * 6.283185;
vec2 diskRotation = vec2(sin(angle), cos(angle));
return PCFLod(_sampler, 0.0, vec2(2.0, 2.0), _shadowCoord, _bias, _pcfParams, _texelSize, diskRotation);
}
float VSM(sampler2D _sampler, vec4 _shadowCoord, float _bias, float _depthMultiplier, float _minVariance)
@@ -233,3 +278,116 @@ vec4 blur9VSM(sampler2D _sampler, vec2 _uv0, vec4 _uv1, vec4 _uv2, vec4 _uv3, ve
return vec4(packHalfFloat(blur.x), packHalfFloat(blur.y));
}
// Returns vec3(avgBlockerDepth, closestBlockerDepth, blockerRatio)
// avgBlockerDepth: mean depth of all blockers found (for general penumbra)
// closestBlockerDepth: maximum depth among blockers (nearest to receiver, for contact hardening)
// blockerRatio: fraction of search samples that found a blocker [0..1]
// _diskRotation = vec2(sin(angle), cos(angle)) for per-pixel Poisson disk rotation
vec3 findBlocker(sampler2D _sampler, vec4 _shadowCoord, vec2 _searchSize, float _bias, vec2 _diskRotation)
{
int blockerCount = 0;
float avgBlockerDepth = 0.0;
float closestBlockerDepth = 0.0;
vec2 texCoord = _shadowCoord.xy / _shadowCoord.w;
float receiverDepth = (_shadowCoord.z / _shadowCoord.w) - _bias;
// Search around the shadow coordinate to find blockers
for( int i = 0; i < BLOCKER_SEARCH_NUM_SAMPLES; ++i )
{
vec2 offset = rotateSample(samplePoisson(i), _diskRotation) * _searchSize;
float shadowMapDepth = unpackRgbaToFloat(texture2D(_sampler, texCoord + offset));
if (shadowMapDepth < receiverDepth)
{
avgBlockerDepth += shadowMapDepth;
closestBlockerDepth = max(closestBlockerDepth, shadowMapDepth);
blockerCount++;
}
}
// Calculate average blocker depth
if (blockerCount > 0)
{
avgBlockerDepth /= float(blockerCount);
}
else
{
avgBlockerDepth = -1.0; // No blockers found
}
float blockerRatio = float(blockerCount) / float(BLOCKER_SEARCH_NUM_SAMPLES);
return vec3(avgBlockerDepth, closestBlockerDepth, blockerRatio);
}
float PCSS(sampler2D _sampler, vec4 _shadowCoord, float _bias, vec4 _pcssParams, vec2 _texelSize, vec2 fragCoord)
{
// -----------------------------------------------------------------------
// PCSS Parameters
// -----------------------------------------------------------------------
// Blocker search radius in UV space (~10 texels on 1024 map).
float searchRadiusUV = 0.01;
// Penumbra scale. Amplifies the squared depth ratio into a UV-space
// filter radius. Higher = softer shadows at distance.
float penumbraScaleX = _pcssParams.z;
float penumbraScaleY = _pcssParams.w;
// Maximum filter radius in UV space (~50 texels on 1024 map).
float maxFilterRadius = 0.25;
// -----------------------------------------------------------------------
// Per-pixel Poisson disk rotation (Interleaved Gradient Noise)
// -----------------------------------------------------------------------
vec2 noiseCoord = fragCoord;
//vec2 noiseCoord = (_shadowCoord.xy / _shadowCoord.w) * (1.0 / _texelSize.x);
float noise = interleavedGradientNoise(noiseCoord);
float rotationAngle = noise * 6.283185;
vec2 diskRotation = vec2(sin(rotationAngle), cos(rotationAngle));
// Receiver depth in normalized shadow map space
float receiverDepth = (_shadowCoord.z / _shadowCoord.w) - _bias;
// -----------------------------------------------------------------------
// Step 1: Blocker Search
// -----------------------------------------------------------------------
vec3 blockerResult = findBlocker(_sampler, _shadowCoord, vec2(searchRadiusUV, searchRadiusUV), _bias, diskRotation);
float avgBlockerDepth = blockerResult.x;
float blockerRatio = blockerResult.z;
if (avgBlockerDepth < -0.99)
{
return 1.0;
}
// -----------------------------------------------------------------------
// Step 2: Penumbra Estimation (standard PCSS, Fernando 2005)
//
// penumbraWidth = lightSize * (d_receiver - d_blocker) / d_blocker
//
// The depth gap at contact equals the object's thickness along the
// light direction. For curved objects (spheres, characters), the gap
// varies across the shadow giving the contact-hardening gradient.
// For flat objects (cubes), the gap is constant → uniform penumbra.
// -----------------------------------------------------------------------
float penumbraWidth = penumbraScaleX * max(0.0, receiverDepth - avgBlockerDepth) / avgBlockerDepth;
float penumbraHeight = penumbraScaleY * max(0.0, receiverDepth - avgBlockerDepth) / avgBlockerDepth;
float filterRadiusU = clamp(penumbraWidth, 0.0, maxFilterRadius);
float filterRadiusV = clamp(penumbraHeight, 0.0, maxFilterRadius);
// -----------------------------------------------------------------------
// Step 3: Percentage-Closer Filtering
// -----------------------------------------------------------------------
float visibility = PCFLodOffset(_sampler, 0.0, vec2(filterRadiusU, filterRadiusV), _shadowCoord, _bias, _texelSize, diskRotation);
// -----------------------------------------------------------------------
// Step 4: Edge fade based on blocker ratio
// -----------------------------------------------------------------------
float edgeFade = smoothstep(0.0, 0.25, blockerRatio);
visibility = mix(1.0, visibility, edgeFade);
return visibility;
}

View File

@@ -60,6 +60,7 @@ float computeVisibility(sampler2D _sampler
, float _depthMultiplier
, float _minVariance
, float _hardness
, vec2 _fragCoord
)
{
float visibility;
@@ -73,7 +74,9 @@ float computeVisibility(sampler2D _sampler
#if SM_HARD
visibility = hardShadow(_sampler, shadowcoord, _bias);
#elif SM_PCF
visibility = PCF(_sampler, shadowcoord, _bias, _samplingParams, _texelSize);
visibility = PCF(_sampler, shadowcoord, _bias, _samplingParams, _texelSize, _fragCoord);
#elif SM_PCSS
visibility = PCSS(_sampler, shadowcoord, _bias, _samplingParams, _texelSize, _fragCoord);
#elif SM_VSM
visibility = VSM(_sampler, shadowcoord, _bias, _depthMultiplier, _minVariance);
#elif SM_ESM

View File

@@ -29,6 +29,7 @@
vec3 colorCoverage;
float visibility;
vec2 fragCoord = gl_FragCoord.xy;
#if SM_CSM
vec2 texelSize = vec2_splat(u_shadowMapTexelSize);
@@ -56,6 +57,7 @@
, u_shadowMapDepthMultiplier
, u_shadowMapMinVariance
, u_shadowMapHardness
, fragCoord
);
}
else if (selection1)
@@ -72,6 +74,7 @@
, u_shadowMapDepthMultiplier
, u_shadowMapMinVariance
, u_shadowMapHardness
, fragCoord
);
}
else if (selection2)
@@ -88,6 +91,7 @@
, u_shadowMapDepthMultiplier
, u_shadowMapMinVariance
, u_shadowMapHardness
, fragCoord
);
}
else //selection3
@@ -104,6 +108,7 @@
, u_shadowMapDepthMultiplier
, u_shadowMapMinVariance
, u_shadowMapHardness
, fragCoord
);
}
#elif SM_OMNI
@@ -155,6 +160,7 @@
, u_shadowMapDepthMultiplier
, u_shadowMapMinVariance
, u_shadowMapHardness
, fragCoord
);
#else
vec2 texelSize = vec2_splat(u_shadowMapTexelSize);
@@ -170,6 +176,7 @@
, u_shadowMapDepthMultiplier
, u_shadowMapMinVariance
, u_shadowMapHardness
, fragCoord
);
#endif

View File

@@ -0,0 +1,15 @@
$input v_normal, v_view, v_shadowcoord
/*
* Copyright 2013-2014 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
#define SM_PCSS 1
#include "fs_shadowmaps_color_lighting.sh"
void main()
{
#include "fs_shadowmaps_color_lighting_main.sh"
}

View File

@@ -0,0 +1,16 @@
$input v_position, v_normal, v_view, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4
/*
* Copyright 2013-2014 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
#define SM_PCSS 1
#define SM_CSM 1
#include "fs_shadowmaps_color_lighting.sh"
void main()
{
#include "fs_shadowmaps_color_lighting_main.sh"
}

View File

@@ -0,0 +1,16 @@
$input v_normal, v_view, v_shadowcoord
/*
* Copyright 2013-2014 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
#define SM_PCSS 1
#define SM_LINEAR 1
#include "fs_shadowmaps_color_lighting.sh"
void main()
{
#include "fs_shadowmaps_color_lighting_main.sh"
}

View File

@@ -0,0 +1,16 @@
$input v_position, v_normal, v_view, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4
/*
* Copyright 2013-2014 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
#define SM_PCSS 1
#define SM_LINEAR 1
#define SM_CSM 1
#include "fs_shadowmaps_color_lighting.sh"
void main()
{
#include "fs_shadowmaps_color_lighting_main.sh"
}

View File

@@ -0,0 +1,16 @@
$input v_position, v_normal, v_view, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4
/*
* Copyright 2013-2014 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
#define SM_PCSS 1
#define SM_LINEAR 1
#define SM_OMNI 1
#include "fs_shadowmaps_color_lighting.sh"
void main()
{
#include "fs_shadowmaps_color_lighting_main.sh"
}

View File

@@ -0,0 +1,16 @@
$input v_position, v_normal, v_view, v_texcoord1, v_texcoord2, v_texcoord3, v_texcoord4
/*
* Copyright 2013-2014 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
#define SM_PCSS 1
#define SM_OMNI 1
#include "fs_shadowmaps_color_lighting.sh"
void main()
{
#include "fs_shadowmaps_color_lighting_main.sh"
}

View File

@@ -88,6 +88,7 @@ struct SmImpl
{
Hard,
PCF,
PCSS,
VSM,
ESM,
@@ -992,31 +993,37 @@ struct Programs
// Color lighting.
m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::Hard] = loadProgram("vs_shadowmaps_color_lighting", "fs_shadowmaps_color_lighting_hard");
m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::PCF] = loadProgram("vs_shadowmaps_color_lighting", "fs_shadowmaps_color_lighting_pcf");
m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::PCSS] = loadProgram("vs_shadowmaps_color_lighting", "fs_shadowmaps_color_lighting_pcss");
m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::VSM] = loadProgram("vs_shadowmaps_color_lighting", "fs_shadowmaps_color_lighting_vsm");
m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::ESM] = loadProgram("vs_shadowmaps_color_lighting", "fs_shadowmaps_color_lighting_esm");
m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::Hard] = loadProgram("vs_shadowmaps_color_lighting_linear", "fs_shadowmaps_color_lighting_hard_linear");
m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::PCF] = loadProgram("vs_shadowmaps_color_lighting_linear", "fs_shadowmaps_color_lighting_pcf_linear");
m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::PCSS] = loadProgram("vs_shadowmaps_color_lighting_linear", "fs_shadowmaps_color_lighting_pcss_linear");
m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::VSM] = loadProgram("vs_shadowmaps_color_lighting_linear", "fs_shadowmaps_color_lighting_vsm_linear");
m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::ESM] = loadProgram("vs_shadowmaps_color_lighting_linear", "fs_shadowmaps_color_lighting_esm_linear");
m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::Hard] = loadProgram("vs_shadowmaps_color_lighting_omni", "fs_shadowmaps_color_lighting_hard_omni");
m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::PCF] = loadProgram("vs_shadowmaps_color_lighting_omni", "fs_shadowmaps_color_lighting_pcf_omni");
m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::PCSS] = loadProgram("vs_shadowmaps_color_lighting_omni", "fs_shadowmaps_color_lighting_pcss_omni");
m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::VSM] = loadProgram("vs_shadowmaps_color_lighting_omni", "fs_shadowmaps_color_lighting_vsm_omni");
m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::ESM] = loadProgram("vs_shadowmaps_color_lighting_omni", "fs_shadowmaps_color_lighting_esm_omni");
m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::Hard] = loadProgram("vs_shadowmaps_color_lighting_linear_omni", "fs_shadowmaps_color_lighting_hard_linear_omni");
m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::PCF] = loadProgram("vs_shadowmaps_color_lighting_linear_omni", "fs_shadowmaps_color_lighting_pcf_linear_omni");
m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::PCSS] = loadProgram("vs_shadowmaps_color_lighting_linear_omni", "fs_shadowmaps_color_lighting_pcss_linear_omni");
m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::VSM] = loadProgram("vs_shadowmaps_color_lighting_linear_omni", "fs_shadowmaps_color_lighting_vsm_linear_omni");
m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::ESM] = loadProgram("vs_shadowmaps_color_lighting_linear_omni", "fs_shadowmaps_color_lighting_esm_linear_omni");
m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::Hard] = loadProgram("vs_shadowmaps_color_lighting_csm", "fs_shadowmaps_color_lighting_hard_csm");
m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::PCF] = loadProgram("vs_shadowmaps_color_lighting_csm", "fs_shadowmaps_color_lighting_pcf_csm");
m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::PCSS] = loadProgram("vs_shadowmaps_color_lighting_csm", "fs_shadowmaps_color_lighting_pcss_csm");
m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::VSM] = loadProgram("vs_shadowmaps_color_lighting_csm", "fs_shadowmaps_color_lighting_vsm_csm");
m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::ESM] = loadProgram("vs_shadowmaps_color_lighting_csm", "fs_shadowmaps_color_lighting_esm_csm");
m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::Hard] = loadProgram("vs_shadowmaps_color_lighting_linear_csm", "fs_shadowmaps_color_lighting_hard_linear_csm");
m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::PCF] = loadProgram("vs_shadowmaps_color_lighting_linear_csm", "fs_shadowmaps_color_lighting_pcf_linear_csm");
m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::PCSS] = loadProgram("vs_shadowmaps_color_lighting_linear_csm", "fs_shadowmaps_color_lighting_pcss_linear_csm");
m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::VSM] = loadProgram("vs_shadowmaps_color_lighting_linear_csm", "fs_shadowmaps_color_lighting_vsm_linear_csm");
m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::ESM] = loadProgram("vs_shadowmaps_color_lighting_linear_csm", "fs_shadowmaps_color_lighting_esm_linear_csm");
}
@@ -1284,6 +1291,23 @@ public:
, &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw
},
{ //SmImpl::PCSS
10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo
, 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
, 1.0f, 1.0f, 99.0f, 1.0f // m_near
, 250.0f, 100.0f, 2000.0f, 50.0f // m_far
, 0.001f, 0.0f, 0.01f, 0.00001f // m_bias
, 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset
, 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0
, 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1
, 2.0f, 0.0f, 8.0f, 1.0f // m_xNum
, 2.0f, 0.0f, 8.0f, 1.0f // m_yNum
, 15.0f, 0.0f, 30.0f, 0.01f // m_xOffset
, 15.0f, 0.0f, 30.0f, 0.01f // m_yOffset
, true // m_doBlur
, &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::PCSS] //m_progDraw
},
{ //SmImpl::VSM
10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo
, 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
@@ -1356,6 +1380,23 @@ public:
, &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::PCF] //m_progDraw
},
{ //SmImpl::PCSS
10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo
, 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
, 1.0f, 1.0f, 99.0f, 1.0f // m_near
, 250.0f, 100.0f, 2000.0f, 50.0f // m_far
, 0.0025f, 0.0f, 0.01f, 0.00001f // m_bias
, 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset
, 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0
, 2000.0f, 1.0f, 2000.0f, 1.0f // m_customParam1
, 2.0f, 0.0f, 8.0f, 1.0f // m_xNum
, 2.0f, 0.0f, 8.0f, 1.0f // m_yNum
, 0.04f, 0.0f, 1.0f, 0.01f // m_xOffset
, 0.04f, 0.0f, 1.0f, 0.01f // m_yOffset
, true // m_doBlur
, &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::PCSS] //m_progDraw
},
{ //SmImpl::VSM
10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo
, 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
@@ -1432,6 +1473,23 @@ public:
, &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw
},
{ //SmImpl::PCSS
12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo
, 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
, 1.0f, 1.0f, 99.0f, 1.0f // m_near
, 250.0f, 100.0f, 2000.0f, 50.0f // m_far
, 0.001f, 0.0f, 0.01f, 0.00001f // m_bias
, 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset
, 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0
, 50.0f, 1.0f, 300.0f, 1.0f // m_customParam1
, 2.0f, 0.0f, 8.0f, 1.0f // m_xNum
, 2.0f, 0.0f, 8.0f, 1.0f // m_yNum
, 4.5f, 0.0f, 15.0f, 0.01f // m_xOffset
, 4.5f, 0.0f, 15.0f, 0.01f // m_yOffset
, true // m_doBlur
, &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::PCSS] //m_progDraw
},
{ //SmImpl::VSM
12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo
, 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
@@ -1504,6 +1562,23 @@ public:
, &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::PCF] //m_progDraw
},
{ //SmImpl::PCSS
12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo
, 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
, 1.0f, 1.0f, 99.0f, 1.0f // m_near
, 250.0f, 100.0f, 2000.0f, 50.0f // m_far
, 0.001f, 0.0f, 0.01f, 0.00001f // m_bias
, 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset
, 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0
, 120.0f, 1.0f, 300.0f, 1.0f // m_customParam1
, 2.0f, 0.0f, 8.0f, 1.0f // m_xNum
, 2.0f, 0.0f, 8.0f, 1.0f // m_yNum
, 0.02f, 0.0f, 0.1f, 0.01f // m_xOffset
, 0.02f, 0.0f, 0.1f, 0.01f // m_yOffset
, true // m_doBlur
, &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::PCSS] //m_progDraw
},
{ //SmImpl::VSM
12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo
, 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
@@ -1580,6 +1655,23 @@ public:
, &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw
},
{ //SmImpl::PCSS
11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo
, 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
, 1.0f, 1.0f, 99.0f, 1.0f // m_near
, 550.0f, 100.0f, 2000.0f, 50.0f // m_far
, 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias
, 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset
, 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0
, 200.0f, 1.0f, 400.0f, 1.0f // m_customParam1
, 2.0f, 0.0f, 8.0f, 1.0f // m_xNum
, 2.0f, 0.0f, 8.0f, 1.0f // m_yNum
, 0.5f, 0.0f, 3.0f, 0.01f // m_xOffset
, 0.5f, 0.0f, 3.0f, 0.01f // m_yOffset
, true // m_doBlur
, &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::PCSS] //m_progDraw
},
{ //SmImpl::VSM
11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo
, 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
@@ -1652,6 +1744,23 @@ public:
, &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::PCF] //m_progDraw
},
{ //SmImpl::PCSS
11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo
, 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
, 1.0f, 1.0f, 99.0f, 1.0f // m_near
, 550.0f, 100.0f, 2000.0f, 50.0f // m_far
, 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias
, 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset
, 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0
, 200.0f, 1.0f, 400.0f, 1.0f // m_customParam1
, 2.0f, 0.0f, 8.0f, 1.0f // m_xNum
, 2.0f, 0.0f, 8.0f, 1.0f // m_yNum
, 0.5f, 0.0f, 3.0f, 0.01f // m_xOffset
, 0.5f, 0.0f, 3.0f, 0.01f // m_yOffset
, true // m_doBlur
, &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack
, &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::PCSS] //m_progDraw
},
{ //SmImpl::VSM
11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo
, 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow
@@ -1861,6 +1970,7 @@ public:
ImGui::Text("Shadow Map implementation");
IMGUI_RADIO_BUTTON("Hard", m_settings.m_smImpl, SmImpl::Hard);
IMGUI_RADIO_BUTTON("PCF", m_settings.m_smImpl, SmImpl::PCF);
IMGUI_RADIO_BUTTON("PCSS", m_settings.m_smImpl, SmImpl::PCSS);
IMGUI_RADIO_BUTTON("VSM", m_settings.m_smImpl, SmImpl::VSM);
IMGUI_RADIO_BUTTON("ESM", m_settings.m_smImpl, SmImpl::ESM);
currentSmSettings = &m_smSettings[m_settings.m_lightType][m_settings.m_depthImpl][m_settings.m_smImpl];
@@ -1888,6 +1998,12 @@ public:
IMGUI_FLOAT_SLIDER("Y Offset", currentSmSettings->m_yOffset);
break;
case SmImpl::PCSS:
ImGui::Text("PCSS");
IMGUI_FLOAT_SLIDER("Penumbra X", currentSmSettings->m_xOffset);
IMGUI_FLOAT_SLIDER("Penumbra Y", currentSmSettings->m_yOffset);
break;
case SmImpl::VSM:
ImGui::Text("VSM");
IMGUI_FLOAT_SLIDER("Min variance", currentSmSettings->m_customParam0);