Skip to content

Commit 49fef39

Browse files
authored
Renderer: Shadow map improvements. (#32705)
1 parent fbdbb63 commit 49fef39

14 files changed

+57
-62
lines changed
-29.2 KB
Loading
-19.1 KB
Loading
-50 KB
Loading

examples/webgpu_postprocessing_outline.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@
8787
light.castShadow = true;
8888
light.shadow.mapSize.width = 2048;
8989
light.shadow.mapSize.height = 2048;
90-
light.shadow.bias = - 0.005;
9190

9291
const d = 10;
9392

examples/webgpu_postprocessing_sss.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
dirLight.shadow.camera.right = 4;
7474
dirLight.shadow.camera.near = 0.1;
7575
dirLight.shadow.camera.far = 40;
76-
dirLight.shadow.bias = - 0.001;
7776
dirLight.shadow.mapSize.width = 1024;
7877
dirLight.shadow.mapSize.height = 1024;
7978
scene.add( dirLight );

examples/webgpu_shadowmap.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
spotLight.shadow.camera.far = 200;
6969
spotLight.shadow.mapSize.width = 2048;
7070
spotLight.shadow.mapSize.height = 2048;
71-
spotLight.shadow.bias = - 0.002;
7271
spotLight.shadow.radius = 4;
7372
scene.add( spotLight );
7473

@@ -85,7 +84,6 @@
8584
dirLight.shadow.mapSize.width = 2048;
8685
dirLight.shadow.mapSize.height = 2048;
8786
dirLight.shadow.radius = 4;
88-
dirLight.shadow.bias = - 0.0005;
8987

9088
dirGroup = new THREE.Group();
9189
dirGroup.add( dirLight );

examples/webgpu_shadowmap_csm.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@
126126
csmDirectionalLight.shadow.camera.bottom = - 1000;
127127
csmDirectionalLight.shadow.camera.left = - 1000;
128128
csmDirectionalLight.shadow.camera.right = 1000;
129-
csmDirectionalLight.shadow.bias = - 0.001;
130129

131130
csm = new CSMShadowNode( csmDirectionalLight, { cascades: 4, maxFar: params.maxFar, mode: params.mode } );
132131

examples/webgpu_shadowmap_opacity.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@
8383
dirLight.shadow.mapSize.width = 2048;
8484
dirLight.shadow.mapSize.height = 2048;
8585
dirLight.shadow.radius = 4;
86-
dirLight.shadow.bias = - 0.0005;
8786

8887
dirLight.shadow.autoUpdate = false;
8988
dirLight.shadow.needsUpdate = true;

src/nodes/lighting/PointShadowNode.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import { renderGroup } from '../core/UniformGroupNode.js';
77
import { Matrix4 } from '../../math/Matrix4.js';
88
import { Vector3 } from '../../math/Vector3.js';
99
import { Color } from '../../math/Color.js';
10-
import { BasicShadowMap, LessCompare, WebGPUCoordinateSystem } from '../../constants.js';
10+
import { BasicShadowMap, LessEqualCompare, WebGPUCoordinateSystem } from '../../constants.js';
1111
import { CubeDepthTexture } from '../../textures/CubeDepthTexture.js';
1212
import { screenCoordinate } from '../display/ScreenNode.js';
1313
import { interleavedGradientNoise, vogelDiskSample } from '../utils/PostProcessingUtils.js';
1414
import { abs, normalize, cross } from '../math/MathNode.js';
15+
import { viewZToPerspectiveDepth } from '../display/ViewportDepthNode.js';
1516

1617
const _clearColor = /*@__PURE__*/ new Color();
1718
const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
@@ -97,23 +98,23 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo
9798

9899
// for point lights, the uniform @vShadowCoord is re-purposed to hold
99100
// the vector from the light to the world-space position of the fragment.
100-
const lightToPosition = shadowCoord.xyz.toVar();
101-
const lightToPositionLength = lightToPosition.length();
101+
const shadowPosition = shadowCoord.xyz.toConst();
102+
const shadowPositionAbs = shadowPosition.abs().toConst();
103+
const viewZ = shadowPositionAbs.x.max( shadowPositionAbs.y ).max( shadowPositionAbs.z );
102104

103-
const cameraNearLocal = uniform( 'float' ).setGroup( renderGroup ).onRenderUpdate( () => shadow.camera.near );
104-
const cameraFarLocal = uniform( 'float' ).setGroup( renderGroup ).onRenderUpdate( () => shadow.camera.far );
105+
const shadowCameraNear = uniform( 'float' ).setGroup( renderGroup ).onRenderUpdate( () => shadow.camera.near );
106+
const shadowCameraFar = uniform( 'float' ).setGroup( renderGroup ).onRenderUpdate( () => shadow.camera.far );
105107
const bias = reference( 'bias', 'float', shadow ).setGroup( renderGroup );
106108

107109
const result = float( 1.0 ).toVar();
108110

109-
If( lightToPositionLength.sub( cameraFarLocal ).lessThanEqual( 0.0 ).and( lightToPositionLength.sub( cameraNearLocal ).greaterThanEqual( 0.0 ) ), () => {
111+
If( viewZ.sub( shadowCameraFar ).lessThanEqual( 0.0 ).and( viewZ.sub( shadowCameraNear ).greaterThanEqual( 0.0 ) ), () => {
110112

111-
// dp = normalized distance from light to fragment position
112-
const dp = lightToPositionLength.sub( cameraNearLocal ).div( cameraFarLocal.sub( cameraNearLocal ) ).toVar(); // need to clamp?
113+
const dp = viewZToPerspectiveDepth( viewZ.negate(), shadowCameraNear, shadowCameraFar );
113114
dp.addAssign( bias );
114115

115116
// bd3D = base direction 3D (direction from light to fragment)
116-
const bd3D = lightToPosition.normalize();
117+
const bd3D = shadowPosition.normalize();
117118

118119
// percentage-closer filtering using cube texture sampling
119120
result.assign( filterFn( { depthTexture, bd3D, dp, shadow } ) );
@@ -205,7 +206,7 @@ class PointShadowNode extends ShadowNode {
205206

206207
const depthTexture = new CubeDepthTexture( shadow.mapSize.width );
207208
depthTexture.name = 'PointShadowDepthTexture';
208-
depthTexture.compareFunction = LessCompare;
209+
depthTexture.compareFunction = LessEqualCompare;
209210

210211
const shadowMap = builder.createCubeRenderTarget( shadow.mapSize.width );
211212
shadowMap.texture.name = 'PointShadowMap';

src/nodes/lighting/ShadowFilterNode.js

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import { mix, fract, step, max, clamp } from '../math/MathNode.js';
55
import { add, sub } from '../math/OperatorNode.js';
66
import { renderGroup } from '../core/UniformGroupNode.js';
77
import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
8-
import { objectPosition } from '../accessors/Object3DNode.js';
9-
import { positionWorld } from '../accessors/Position.js';
108
import { screenCoordinate } from '../display/ScreenNode.js';
119
import { interleavedGradientNoise, vogelDiskSample } from '../utils/PostProcessingUtils.js';
10+
import { NoBlending } from '../../constants.js';
1211

1312
const shadowMaterialLib = /*@__PURE__*/ new WeakMap();
1413

@@ -211,31 +210,6 @@ export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord,
211210

212211
} );
213212

214-
//
215-
216-
const linearDistance = /*@__PURE__*/ Fn( ( [ position, cameraNear, cameraFar ] ) => {
217-
218-
let dist = positionWorld.sub( position ).length();
219-
dist = dist.sub( cameraNear ).div( cameraFar.sub( cameraNear ) );
220-
dist = dist.saturate(); // clamp to [ 0, 1 ]
221-
222-
return dist;
223-
224-
} );
225-
226-
const linearShadowDistance = ( light ) => {
227-
228-
const camera = light.shadow.camera;
229-
230-
const nearDistance = reference( 'near', 'float', camera ).setGroup( renderGroup );
231-
const farDistance = reference( 'far', 'float', camera ).setGroup( renderGroup );
232-
233-
const referencePosition = objectPosition( light );
234-
235-
return linearDistance( referencePosition, nearDistance, farDistance );
236-
237-
};
238-
239213
/**
240214
* Retrieves or creates a shadow material for the given light source.
241215
*
@@ -256,13 +230,11 @@ export const getShadowMaterial = ( light ) => {
256230

257231
if ( material === undefined ) {
258232

259-
const depthNode = light.isPointLight ? linearShadowDistance( light ) : null;
260-
261233
material = new NodeMaterial();
262234
material.colorNode = vec4( 0, 0, 0, 1 );
263-
material.depthNode = depthNode;
264235
material.isShadowPassMaterial = true; // Use to avoid other overrideMaterial override material.colorNode unintentionally when using material.shadowNode
265236
material.name = 'ShadowMaterial';
237+
material.blending = NoBlending;
266238
material.fog = false;
267239

268240
shadowMaterialLib.set( light, material );

0 commit comments

Comments
 (0)