Skip to content

Commit aff8217

Browse files
authored
WebGPURenderer: Fix point light shadows. (#32365)
1 parent 53e7451 commit aff8217

File tree

1 file changed

+77
-8
lines changed

1 file changed

+77
-8
lines changed

src/nodes/lighting/PointShadowNode.js

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,57 @@ import { texture } from '../accessors/TextureNode.js';
66
import { max, abs, sign } from '../math/MathNode.js';
77
import { sub, div } from '../math/OperatorNode.js';
88
import { renderGroup } from '../core/UniformGroupNode.js';
9+
import { Matrix4 } from '../../math/Matrix4.js';
910
import { Vector2 } from '../../math/Vector2.js';
11+
import { Vector3 } from '../../math/Vector3.js';
1012
import { Vector4 } from '../../math/Vector4.js';
1113
import { Color } from '../../math/Color.js';
1214
import { BasicShadowMap } from '../../constants.js';
1315

1416
const _clearColor = /*@__PURE__*/ new Color();
17+
const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
18+
const _lightPositionWorld = /*@__PURE__*/ new Vector3();
19+
const _lookTarget = /*@__PURE__*/ new Vector3();
20+
21+
// These viewports map a cube-map onto a 2D texture with the
22+
// following orientation:
23+
//
24+
// xzXZ
25+
// y Y
26+
//
27+
// X - Positive x direction
28+
// x - Negative x direction
29+
// Y - Positive y direction
30+
// y - Negative y direction
31+
// Z - Positive z direction
32+
// z - Negative z direction
33+
34+
const _frameExtents = /*@__PURE__*/ new Vector2( 4, 2 );
35+
36+
const _viewports = [
37+
// positive X
38+
/*@__PURE__*/ new Vector4( 2, 1, 1, 1 ),
39+
// negative X
40+
/*@__PURE__*/ new Vector4( 0, 1, 1, 1 ),
41+
// positive Z
42+
/*@__PURE__*/ new Vector4( 3, 1, 1, 1 ),
43+
// negative Z
44+
/*@__PURE__*/ new Vector4( 1, 1, 1, 1 ),
45+
// positive Y
46+
/*@__PURE__*/ new Vector4( 3, 0, 1, 1 ),
47+
// negative Y
48+
/*@__PURE__*/ new Vector4( 1, 0, 1, 1 )
49+
];
50+
51+
const _cubeDirections = [
52+
/*@__PURE__*/ new Vector3( 1, 0, 0 ), /*@__PURE__*/ new Vector3( - 1, 0, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ),
53+
/*@__PURE__*/ new Vector3( 0, 0, - 1 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 )
54+
];
55+
56+
const _cubeUps = [
57+
/*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ),
58+
/*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 )
59+
];
1560

1661
// cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D
1762
// vector suitable for 2D texture mapping. This code uses the following layout for the
@@ -239,10 +284,11 @@ class PointShadowNode extends ShadowNode {
239284
const { shadow, shadowMap, light } = this;
240285
const { renderer, scene } = frame;
241286

242-
const shadowFrameExtents = shadow.getFrameExtents();
287+
const camera = shadow.camera;
288+
const shadowMatrix = shadow.matrix;
243289

244290
_shadowMapSize.copy( shadow.mapSize );
245-
_shadowMapSize.multiply( shadowFrameExtents );
291+
_shadowMapSize.multiply( _frameExtents );
246292

247293
shadowMap.setSize( _shadowMapSize.width, _shadowMapSize.height );
248294

@@ -259,11 +305,9 @@ class PointShadowNode extends ShadowNode {
259305
renderer.setClearColor( shadow.clearColor, shadow.clearAlpha );
260306
renderer.clear();
261307

262-
const viewportCount = shadow.getViewportCount();
308+
for ( let vp = 0; vp < 6; vp ++ ) {
263309

264-
for ( let vp = 0; vp < viewportCount; vp ++ ) {
265-
266-
const viewport = shadow.getViewport( vp );
310+
const viewport = _viewports[ vp ];
267311

268312
const x = _viewportSize.x * viewport.x;
269313
const y = _shadowMapSize.y - _viewportSize.y - ( _viewportSize.y * viewport.y );
@@ -277,13 +321,38 @@ class PointShadowNode extends ShadowNode {
277321

278322
shadowMap.viewport.copy( _viewport );
279323

280-
shadow.updateMatrices( light, vp );
324+
// Update shadow camera matrices for this face
325+
326+
const far = light.distance || camera.far;
327+
328+
if ( far !== camera.far ) {
329+
330+
camera.far = far;
331+
camera.updateProjectionMatrix();
332+
333+
}
334+
335+
_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
336+
camera.position.copy( _lightPositionWorld );
337+
338+
_lookTarget.copy( camera.position );
339+
_lookTarget.add( _cubeDirections[ vp ] );
340+
camera.up.copy( _cubeUps[ vp ] );
341+
camera.lookAt( _lookTarget );
342+
camera.updateMatrixWorld();
343+
344+
shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
345+
346+
_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
347+
shadow._frustum.setFromProjectionMatrix( _projScreenMatrix, camera.coordinateSystem, camera.reversedDepth );
348+
349+
//
281350

282351
const currentSceneName = scene.name;
283352

284353
scene.name = `Point Light Shadow [ ${ light.name || 'ID: ' + light.id } ] - Face ${ vp + 1 }`;
285354

286-
renderer.render( scene, shadow.camera );
355+
renderer.render( scene, camera );
287356

288357
scene.name = currentSceneName;
289358

0 commit comments

Comments
 (0)