diff --git a/examples/16-shadowmaps/common.sh b/examples/16-shadowmaps/common.sh index 50244a711..553e93eec 100644 --- a/examples/16-shadowmaps/common.sh +++ b/examples/16-shadowmaps/common.sh @@ -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; +} \ No newline at end of file diff --git a/examples/16-shadowmaps/fs_shadowmaps_color_lighting.sh b/examples/16-shadowmaps/fs_shadowmaps_color_lighting.sh index b0da55ba8..eeb750558 100644 --- a/examples/16-shadowmaps/fs_shadowmaps_color_lighting.sh +++ b/examples/16-shadowmaps/fs_shadowmaps_color_lighting.sh @@ -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 diff --git a/examples/16-shadowmaps/fs_shadowmaps_color_lighting_main.sh b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_main.sh index 1b2b6be31..cb368f94f 100644 --- a/examples/16-shadowmaps/fs_shadowmaps_color_lighting_main.sh +++ b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_main.sh @@ -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 diff --git a/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss.sc b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss.sc new file mode 100644 index 000000000..908013562 --- /dev/null +++ b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss.sc @@ -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" +} diff --git a/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_csm.sc b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_csm.sc new file mode 100644 index 000000000..c9e81ef27 --- /dev/null +++ b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_csm.sc @@ -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" +} diff --git a/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear.sc b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear.sc new file mode 100644 index 000000000..4b576ee1c --- /dev/null +++ b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear.sc @@ -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" +} diff --git a/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear_csm.sc b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear_csm.sc new file mode 100644 index 000000000..3fbb44ba7 --- /dev/null +++ b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear_csm.sc @@ -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" +} diff --git a/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear_omni.sc b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear_omni.sc new file mode 100644 index 000000000..624034003 --- /dev/null +++ b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_linear_omni.sc @@ -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" +} diff --git a/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_omni.sc b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_omni.sc new file mode 100644 index 000000000..d8c9a2b16 --- /dev/null +++ b/examples/16-shadowmaps/fs_shadowmaps_color_lighting_pcss_omni.sc @@ -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" +} diff --git a/examples/16-shadowmaps/shadowmaps.cpp b/examples/16-shadowmaps/shadowmaps.cpp index a4c2d9ce7..7af9803cc 100644 --- a/examples/16-shadowmaps/shadowmaps.cpp +++ b/examples/16-shadowmaps/shadowmaps.cpp @@ -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);