diff --git a/examples/jsm/csm/CSMShadowNode.js b/examples/jsm/csm/CSMShadowNode.js index 0a14977d9dfdc7..2c4cfd4c1842b8 100644 --- a/examples/jsm/csm/CSMShadowNode.js +++ b/examples/jsm/csm/CSMShadowNode.js @@ -6,8 +6,7 @@ import { Box3, Object3D, WebGLCoordinateSystem, - NodeUpdateType, - Node + ShadowBaseNode } from 'three/webgpu'; import { CSMFrustum } from './CSMFrustum.js'; @@ -36,13 +35,12 @@ class LwLight extends Object3D { } -class CSMShadowNode extends Node { +class CSMShadowNode extends ShadowBaseNode { constructor( light, data = {} ) { - super(); + super( light ); - this.light = light; this.camera = null; this.cascades = data.cascades || 3; this.maxFar = data.maxFar || 100000; @@ -57,7 +55,6 @@ class CSMShadowNode extends Node { this._cascades = []; this.mainFrustum = null; this.frustums = []; - this.updateBeforeType = NodeUpdateType.FRAME; this.lights = []; @@ -264,7 +261,9 @@ class CSMShadowNode extends Node { const linearDepth = viewZToOrthographicDepth( positionView.z, cameraNear, shadowFar ).toVar( 'linearDepth' ); const lastCascade = this.cascades - 1; - return Fn( () => { + return Fn( ( builder ) => { + + this.setupShadowPosition( builder ); const ret = vec4( 1, 1, 1, 1 ).toVar( 'shadowValue' ); @@ -337,7 +336,9 @@ class CSMShadowNode extends Node { const linearDepth = viewZToOrthographicDepth( positionView.z, cameraNear, shadowFar ).toVar( 'linearDepth' ); - return Fn( () => { + return Fn( ( builder ) => { + + this.setupShadowPosition( builder ); const ret = vec4( 1, 1, 1, 1 ).toVar( 'shadowValue' ); const cascade = vec2().toVar( 'cascade' ); @@ -430,6 +431,8 @@ class CSMShadowNode extends Node { } + super.dispose(); + } } diff --git a/src/Three.TSL.js b/src/Three.TSL.js index a2dd262411c7e9..635358e7fbb500 100644 --- a/src/Three.TSL.js +++ b/src/Three.TSL.js @@ -407,6 +407,7 @@ export const select = TSL.select; export const setCurrentStack = TSL.setCurrentStack; export const shaderStages = TSL.shaderStages; export const shadow = TSL.shadow; +export const shadowWorldPosition = TSL.shadowWorldPosition; export const sharedUniformGroup = TSL.sharedUniformGroup; export const sheen = TSL.sheen; export const sheenRoughness = TSL.sheenRoughness; diff --git a/src/nodes/Nodes.js b/src/nodes/Nodes.js index 7af1ad3c0ca9fd..3802ae29173d69 100644 --- a/src/nodes/Nodes.js +++ b/src/nodes/Nodes.js @@ -132,6 +132,7 @@ export { default as BasicEnvironmentNode } from './lighting/BasicEnvironmentNode export { default as IrradianceNode } from './lighting/IrradianceNode.js'; export { default as AONode } from './lighting/AONode.js'; export { default as AnalyticLightNode } from './lighting/AnalyticLightNode.js'; +export { default as ShadowBaseNode } from './lighting/ShadowBaseNode.js'; export { default as ShadowNode } from './lighting/ShadowNode.js'; // pmrem diff --git a/src/nodes/lighting/ShadowBaseNode.js b/src/nodes/lighting/ShadowBaseNode.js new file mode 100644 index 00000000000000..965f9b002e6650 --- /dev/null +++ b/src/nodes/lighting/ShadowBaseNode.js @@ -0,0 +1,43 @@ +import Node from '../core/Node.js'; +import { NodeUpdateType } from '../core/constants.js'; +import { vec3 } from '../tsl/TSLBase.js'; +import { positionWorld } from '../accessors/Position.js'; + +class ShadowBaseNode extends Node { + + static get type() { + + return 'ShadowBaseNode'; + + } + + constructor( light ) { + + super(); + + this.light = light; + this.updateBeforeType = NodeUpdateType.RENDER; + + this.isShadowBaseNode = true; + + } + + setupShadowPosition( { material } ) { + + // Use assign inside an Fn() + + shadowWorldPosition.assign( material.shadowPositionNode || positionWorld ); + + } + + dispose() { + + this.updateBeforeType = NodeUpdateType.NONE; + + } + +} + +export const shadowWorldPosition = /*@__PURE__*/ vec3().toVar( 'shadowWorldPosition' ); + +export default ShadowBaseNode; diff --git a/src/nodes/lighting/ShadowNode.js b/src/nodes/lighting/ShadowNode.js index c7088a29eb0bc4..eb414597b80a04 100644 --- a/src/nodes/lighting/ShadowNode.js +++ b/src/nodes/lighting/ShadowNode.js @@ -1,5 +1,4 @@ -import Node from '../core/Node.js'; -import { NodeUpdateType } from '../core/constants.js'; +import ShadowBaseNode, { shadowWorldPosition } from './ShadowBaseNode.js'; import { float, vec2, vec3, vec4, If, int, Fn, nodeObject } from '../tsl/TSLBase.js'; import { reference } from '../accessors/ReferenceNode.js'; import { texture } from '../accessors/TextureNode.js'; @@ -19,8 +18,6 @@ import { objectPosition } from '../accessors/Object3DNode.js'; import { lightShadowMatrix } from '../accessors/Lights.js'; const shadowMaterialLib = /*@__PURE__*/ new WeakMap(); -const shadowWorldPosition = /*@__PURE__*/ vec3().toVar( 'shadowWorldPosition' ); - const linearDistance = /*@__PURE__*/ Fn( ( [ position, cameraNear, cameraFar ] ) => { let dist = positionWorld.sub( position ).length(); @@ -250,7 +247,7 @@ const _shadowFilterLib = [ BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilt const _quadMesh = /*@__PURE__*/ new QuadMesh(); -class ShadowNode extends Node { +class ShadowNode extends ShadowBaseNode { static get type() { @@ -260,9 +257,8 @@ class ShadowNode extends Node { constructor( light, shadow = null ) { - super(); + super( light ); - this.light = light; this.shadow = shadow || light.shadow; this.shadowMap = null; @@ -273,7 +269,6 @@ class ShadowNode extends Node { this.vsmMaterialVertical = null; this.vsmMaterialHorizontal = null; - this.updateBeforeType = NodeUpdateType.RENDER; this._node = null; this.isShadowNode = true; @@ -425,12 +420,12 @@ class ShadowNode extends Node { if ( builder.renderer.shadowMap.enabled === false ) return; - return Fn( ( { material } ) => { - - shadowWorldPosition.assign( material.shadowPositionNode || positionWorld ); + return Fn( () => { let node = this._node; + this.setupShadowPosition( builder ); + if ( node === null ) { this._node = node = this.setupShadow( builder ); @@ -566,7 +561,7 @@ class ShadowNode extends Node { } - this.updateBeforeType = NodeUpdateType.NONE; + super.dispose(); }