diff --git a/examples/webgpu_materials_envmaps.html b/examples/webgpu_materials_envmaps.html index dde1c4e0736e22..c752791e3e75f3 100644 --- a/examples/webgpu_materials_envmaps.html +++ b/examples/webgpu_materials_envmaps.html @@ -103,7 +103,10 @@ sphereMaterial.needsUpdate = true; }, - Refraction: false + Refraction: false, + backgroundRotationX: false, + backgroundRotationY: false, + backgroundRotationZ: false }; const gui = new GUI( { width: 300 } ); @@ -126,6 +129,9 @@ sphereMaterial.needsUpdate = true; } ); + gui.add( params, 'backgroundRotationX' ); + gui.add( params, 'backgroundRotationY' ); + gui.add( params, 'backgroundRotationZ' ); gui.open(); window.addEventListener( 'resize', onWindowResize ); @@ -145,6 +151,24 @@ function animate() { + if ( params.backgroundRotationX ) { + + scene.backgroundRotation.x += 0.001; + + } + + if ( params.backgroundRotationY ) { + + scene.backgroundRotation.y += 0.001; + + } + + if ( params.backgroundRotationZ ) { + + scene.backgroundRotation.z += 0.001; + + } + camera.lookAt( scene.position ); renderer.render( scene, camera ); diff --git a/src/nodes/accessors/SceneNode.js b/src/nodes/accessors/SceneNode.js index 5e386bc8fc1b4a..27ad4863765df7 100644 --- a/src/nodes/accessors/SceneNode.js +++ b/src/nodes/accessors/SceneNode.js @@ -1,7 +1,14 @@ +import { UVMapping } from '../../constants.js'; +import { Euler } from '../../math/Euler.js'; +import { Matrix4 } from '../../math/Matrix4.js'; import Node from '../core/Node.js'; -import { nodeImmutable } from '../tsl/TSLBase.js'; +import { renderGroup } from '../core/UniformGroupNode.js'; +import { nodeImmutable, uniform } from '../tsl/TSLBase.js'; import { reference } from './ReferenceNode.js'; +const _e1 = /*@__PURE__*/ new Euler(); +const _m1 = /*@__PURE__*/ new Matrix4(); + class SceneNode extends Node { static get type() { @@ -34,6 +41,31 @@ class SceneNode extends Node { output = reference( 'backgroundIntensity', 'float', scene ); + } else if ( scope === SceneNode.BACKGROUND_ROTATION ) { + + output = uniform( 'mat4' ).label( 'backgroundRotation' ).setGroup( renderGroup ).onRenderUpdate( () => { + + const background = scene.background; + + if ( background !== null && background.isTexture && background.mapping !== UVMapping ) { + + _e1.copy( scene.backgroundRotation ); + + // accommodate left-handed frame + _e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1; + + _m1.makeRotationFromEuler( _e1 ); + + } else { + + _m1.identity(); + + } + + return _m1; + + } ); + } else { console.error( 'THREE.SceneNode: Unknown scope:', scope ); @@ -48,8 +80,10 @@ class SceneNode extends Node { SceneNode.BACKGROUND_BLURRINESS = 'backgroundBlurriness'; SceneNode.BACKGROUND_INTENSITY = 'backgroundIntensity'; +SceneNode.BACKGROUND_ROTATION = 'backgroundRotation'; export default SceneNode; export const backgroundBlurriness = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_BLURRINESS ); export const backgroundIntensity = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_INTENSITY ); +export const backgroundRotation = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_ROTATION ); diff --git a/src/renderers/common/Background.js b/src/renderers/common/Background.js index 72e7aa3404b5d9..a47ddb3b370187 100644 --- a/src/renderers/common/Background.js +++ b/src/renderers/common/Background.js @@ -1,6 +1,6 @@ import DataMap from './DataMap.js'; import Color4 from './Color4.js'; -import { vec4, context, normalWorld, backgroundBlurriness, backgroundIntensity, modelViewProjection } from '../../nodes/TSL.js'; +import { vec4, context, normalWorld, backgroundBlurriness, backgroundIntensity, backgroundRotation, modelViewProjection } from '../../nodes/TSL.js'; import NodeMaterial from '../../materials/nodes/NodeMaterial.js'; import { Mesh } from '../../objects/Mesh.js'; @@ -56,7 +56,7 @@ class Background extends DataMap { const backgroundMeshNode = context( vec4( backgroundNode ).mul( backgroundIntensity ), { // @TODO: Add Texture2D support using node context - getUV: () => normalWorld, + getUV: () => backgroundRotation.mul( normalWorld ), getTextureLevel: () => backgroundBlurriness } ); diff --git a/src/renderers/common/nodes/Nodes.js b/src/renderers/common/nodes/Nodes.js index a33dd4fef7e176..2debdeddfaf87b 100644 --- a/src/renderers/common/nodes/Nodes.js +++ b/src/renderers/common/nodes/Nodes.js @@ -3,7 +3,7 @@ import ChainMap from '../ChainMap.js'; import NodeBuilderState from './NodeBuilderState.js'; import { cubeMapNode } from '../../../nodes/utils/CubeMapNode.js'; import { NodeFrame } from '../../../nodes/Nodes.js'; -import { objectGroup, renderGroup, frameGroup, cubeTexture, texture, rangeFog, densityFog, reference, normalWorld, pmremTexture, screenUV } from '../../../nodes/TSL.js'; +import { objectGroup, renderGroup, frameGroup, cubeTexture, texture, rangeFog, densityFog, reference, pmremTexture, screenUV } from '../../../nodes/TSL.js'; import { CubeUVReflectionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from '../../../constants.js'; import { hashArray } from '../../../nodes/core/NodeUtils.js'; @@ -279,7 +279,7 @@ class Nodes extends DataMap { if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { - backgroundNode = pmremTexture( background, normalWorld ); + backgroundNode = pmremTexture( background ); } else {