Skip to content

Commit

Permalink
Compensate PCSS kernel with depth range for directional lights (#5441)
Browse files Browse the repository at this point in the history
* Compensate PCSS kernel with depth range for directional lights

* Copy depth range values to render data and initialize properly.

* Save only the depth range compensation we want in the light render data and submit directly.
  • Loading branch information
GSterbrant committed Jun 28, 2023
1 parent c30f8d8 commit 1855a58
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/scene/light.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class LightRenderData {
// scissor rectangle for the shadow rendering to the texture (x, y, width, height)
this.shadowScissor = new Vec4(0, 0, 1, 1);

// depth range compensation for PCSS with directional lights
this.depthRangeCompensation = 0;

// face index, value is based on light type:
// - spot: always 0
// - omni: cubemap face, 0..5
Expand Down
6 changes: 3 additions & 3 deletions src/scene/renderer/forward-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class ForwardRenderer extends Renderer {

const cameraParams = directional._shadowCameraParams;
cameraParams.length = 4;
cameraParams[0] = 0;
cameraParams[0] = lightRenderData.depthRangeCompensation;
cameraParams[1] = lightRenderData.shadowCamera._farClip;
cameraParams[2] = lightRenderData.shadowCamera._nearClip;
cameraParams[3] = 1;
Expand Down Expand Up @@ -337,7 +337,7 @@ class ForwardRenderer extends Renderer {
const cameraParams = omni._shadowCameraParams;

cameraParams.length = 4;
cameraParams[0] = 0;
cameraParams[0] = 1;
cameraParams[1] = lightRenderData.shadowCamera._farClip;
cameraParams[2] = lightRenderData.shadowCamera._nearClip;
cameraParams[3] = 0;
Expand Down Expand Up @@ -405,7 +405,7 @@ class ForwardRenderer extends Renderer {

const cameraParams = spot._shadowCameraParams;
cameraParams.length = 4;
cameraParams[0] = 0;
cameraParams[0] = 1;
cameraParams[1] = lightRenderData.shadowCamera._farClip;
cameraParams[2] = lightRenderData.shadowCamera._nearClip;
cameraParams[3] = 0;
Expand Down
1 change: 1 addition & 0 deletions src/scene/renderer/shadow-renderer-directional.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ class ShadowRendererDirectional {
// calculate depth range of the caster's AABB from the point of view of the shadow camera
shadowCamView.copy(shadowCamNode.getWorldTransform()).invert();
const depthRange = getDepthRange(shadowCamView, visibleSceneAabb.getMin(), visibleSceneAabb.getMax());
lightRenderData.depthRangeCompensation = (depthRange.max - depthRange.min) / light.shadowDistance;

// adjust shadow camera's near and far plane to the depth range of casters to maximize precision
// of values stored in the shadow map. Make it slightly larger to avoid clipping on near / far plane.
Expand Down
3 changes: 1 addition & 2 deletions src/scene/shader-lib/chunks/lit/frag/shadowPCSS.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,12 @@ float PCSS(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoords, vec4 cameraParams, vec2
samplePoints[i] = vogelDisk(i, float(PCSS_SAMPLE_COUNT), noise, pcssPresample);
}
// Calculate the ratio of FOV between 45.0 degrees (tan(45) == 1) and the FOV of the camera
float averageBlocker = PCSSBlockerDistance(TEXTURE_PASS(shadowMap), samplePoints, shadowCoords.xy, shadowSearchArea, receiverDepth);
if (averageBlocker == -1.0) {
return 1.0;
} else {
vec2 filterRadius = ((receiverDepth - averageBlocker) / averageBlocker) * shadowSearchArea;
vec2 filterRadius = ((receiverDepth - averageBlocker) / averageBlocker) * shadowSearchArea * cameraParams.x;
float shadow = 0.0;
Expand Down

0 comments on commit 1855a58

Please sign in to comment.