Skip to content

Commit

Permalink
Compensate PCSS kernel with depth range for directional lights
Browse files Browse the repository at this point in the history
  • Loading branch information
GSterbrant committed Jun 27, 2023
1 parent 6b6e45f commit 6cd276b
Show file tree
Hide file tree
Showing 4 changed files with 9 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 for cascaded shadows
this.depthRange = 0;

// face index, value is based on light type:
// - spot: always 0
// - omni: cubemap face, 0..5
Expand Down
7 changes: 4 additions & 3 deletions src/scene/renderer/forward-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,12 @@ class ForwardRenderer extends Renderer {
this.lightShadowIntensity[cnt].setValue(directional.shadowIntensity);

const pixelsPerMeter = 1.0 / (lightRenderData.shadowCamera.renderTarget.width / directional.penumbraSize);
const rangeCompensation = (lightRenderData.depthRange.max - lightRenderData.depthRange.min) / directional.shadowDistance;
this.lightShadowSearchAreaId[cnt].setValue(pixelsPerMeter);

const cameraParams = directional._shadowCameraParams;
cameraParams.length = 4;
cameraParams[0] = 0;
cameraParams[0] = rangeCompensation;
cameraParams[1] = lightRenderData.shadowCamera._farClip;
cameraParams[2] = lightRenderData.shadowCamera._nearClip;
cameraParams[3] = 1;
Expand Down Expand Up @@ -337,7 +338,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 +406,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.depthRange = depthRange;

// 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 6cd276b

Please sign in to comment.