diff --git a/examples/webgpu_caustics.html b/examples/webgpu_caustics.html index b5355f7028d91a..ee7fdcc067d3f1 100644 --- a/examples/webgpu_caustics.html +++ b/examples/webgpu_caustics.html @@ -179,7 +179,7 @@ renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setAnimationLoop( animate ); renderer.shadowMap.enabled = true; - renderer.shadowMap.color = true; + renderer.shadowMap.colored = true; renderer.inspector = new Inspector(); document.body.appendChild( renderer.domElement ); diff --git a/examples/webgpu_shadowmap_opacity.html b/examples/webgpu_shadowmap_opacity.html index 459c2b6f243f8a..3e3224e8cff39b 100644 --- a/examples/webgpu_shadowmap_opacity.html +++ b/examples/webgpu_shadowmap_opacity.html @@ -59,7 +59,7 @@ renderer.toneMapping = THREE.AgXToneMapping; renderer.toneMappingExposure = 1.5; renderer.shadowMap.enabled = true; - renderer.shadowMap.color = true; + renderer.shadowMap.colored = true; renderer.inspector = new Inspector(); container.appendChild( renderer.domElement ); diff --git a/examples/webgpu_volume_caustics.html b/examples/webgpu_volume_caustics.html index d9dc37582b08b6..de5cde95015c79 100644 --- a/examples/webgpu_volume_caustics.html +++ b/examples/webgpu_volume_caustics.html @@ -165,7 +165,7 @@ renderer = new THREE.WebGPURenderer( { antialias: true } ); renderer.shadowMap.enabled = true; - renderer.shadowMap.color = true; + renderer.shadowMap.colored = true; renderer.inspector = new Inspector(); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); diff --git a/src/nodes/core/NodeBuilder.js b/src/nodes/core/NodeBuilder.js index 527ddc54c0e930..d83ca104d85921 100644 --- a/src/nodes/core/NodeBuilder.js +++ b/src/nodes/core/NodeBuilder.js @@ -653,7 +653,16 @@ class NodeBuilder { const uniforms = bindings[ shaderStage ][ groupName ]; const groupUniforms = groups[ groupName ] || ( groups[ groupName ] = [] ); - groupUniforms.push( ...uniforms ); + + for ( const uniform of uniforms ) { + + if ( groupUniforms.includes( uniform ) === false ) { + + groupUniforms.push( uniform ); + + } + + } } diff --git a/src/nodes/lighting/ShadowNode.js b/src/nodes/lighting/ShadowNode.js index 0d1db19cf77bc9..fa15566fb55fc9 100644 --- a/src/nodes/lighting/ShadowNode.js +++ b/src/nodes/lighting/ShadowNode.js @@ -518,7 +518,7 @@ class ShadowNode extends ShadowBaseNode { let shadowColor; - if ( renderer.shadowMap.color === true ) { + if ( renderer.shadowMap.colored === true ) { if ( shadowMap.texture.isCubeTexture ) { diff --git a/src/renderers/common/Renderer.js b/src/renderers/common/Renderer.js index 1685be3b1c9040..f75fe884f273d1 100644 --- a/src/renderers/common/Renderer.js +++ b/src/renderers/common/Renderer.js @@ -658,7 +658,7 @@ class Renderer { * Shadow map configuration * @typedef {Object} ShadowMapConfig * @property {boolean} enabled - Whether to globally enable shadows or not. - * @property {boolean} color - Whether to include shadow color or not. + * @property {boolean} colored - Whether shadows can have a custom color or not. * @property {number} type - The shadow map type. */ @@ -669,7 +669,7 @@ class Renderer { */ this.shadowMap = { enabled: false, - color: false, + colored: false, type: PCFShadowMap }; @@ -3053,9 +3053,9 @@ class Renderer { shadowRGB = material.castShadowNode.rgb; shadowAlpha = material.castShadowNode.a; - if ( this.shadowMap.color !== true ) { + if ( this.shadowMap.colored !== true ) { - warnOnce( 'Renderer: `shadowMap.color` needs to be enabled when using `material.castShadowNode`.' ); + warnOnce( 'Renderer: `shadowMap.colored` needs to be set to `true` when using `material.castShadowNode`.' ); } diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index 7370d60124d3f5..22511d2415462b 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -177,6 +177,14 @@ class WGSLNodeBuilder extends NodeBuilder { */ this.uniformGroups = {}; + /** + * A dictionary that holds the assigned binding indices for each uniform group. + * This ensures the same binding index is used across all shader stages. + * + * @type {Object} + */ + this.uniformGroupsBindings = {}; + /** * A dictionary that holds for each shader stage a Map of builtins. * @@ -1859,7 +1867,7 @@ ${ flowData.code } const groupName = uniform.groupNode.name; - // Check if this group has already been processed + // Check if this group has already been processed in this shader stage if ( uniformGroups[ groupName ] === undefined ) { // Get the shared uniform group that contains uniforms from all stages @@ -1878,9 +1886,24 @@ ${ flowData.code } } + // Check if this group already has an assigned binding index (from another shader stage) + let groupBinding = this.uniformGroupsBindings[ groupName ]; + + if ( groupBinding === undefined ) { + + // First time processing this group - assign a new binding index + groupBinding = { + index: uniformIndexes.binding ++, + id: uniformIndexes.group + }; + + this.uniformGroupsBindings[ groupName ] = groupBinding; + + } + uniformGroups[ groupName ] = { - index: uniformIndexes.binding ++, - id: uniformIndexes.group, + index: groupBinding.index, + id: groupBinding.id, snippets: snippets };