From 089ba615268f3e4b7b6423baaeaf2b510f5ad74d Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Sat, 15 Feb 2025 13:03:25 +0100 Subject: [PATCH 1/3] WebGPURenderer: Support rotation of env maps. --- examples/webgpu_materials_envmaps.html | 10 ++++- src/nodes/accessors/CubeTextureNode.js | 9 ++--- src/nodes/accessors/MaterialNode.js | 52 ++++++++++++++++++++++++++ src/nodes/lighting/EnvironmentNode.js | 11 ++---- src/nodes/pmrem/PMREMNode.js | 3 +- 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/examples/webgpu_materials_envmaps.html b/examples/webgpu_materials_envmaps.html index dcac1f4065f264..46d41deddc667b 100644 --- a/examples/webgpu_materials_envmaps.html +++ b/examples/webgpu_materials_envmaps.html @@ -107,7 +107,8 @@ Refraction: false, backgroundRotationX: false, backgroundRotationY: false, - backgroundRotationZ: false + backgroundRotationZ: false, + syncMaterial: false }; const gui = new GUI( { width: 300 } ); @@ -133,6 +134,7 @@ gui.add( params, 'backgroundRotationX' ); gui.add( params, 'backgroundRotationY' ); gui.add( params, 'backgroundRotationZ' ); + gui.add( params, 'syncMaterial' ); gui.open(); window.addEventListener( 'resize', onWindowResize ); @@ -170,6 +172,12 @@ } + if ( params.syncMaterial ) { + + sphereMesh.material.envMapRotation.copy( scene.backgroundRotation ); + + } + camera.lookAt( scene.position ); renderer.render( scene, camera ); diff --git a/src/nodes/accessors/CubeTextureNode.js b/src/nodes/accessors/CubeTextureNode.js index bafbddc60c21c4..947c45945a092d 100644 --- a/src/nodes/accessors/CubeTextureNode.js +++ b/src/nodes/accessors/CubeTextureNode.js @@ -3,6 +3,7 @@ import { reflectVector, refractVector } from './ReflectVector.js'; import { nodeProxy, vec3 } from '../tsl/TSLBase.js'; import { CubeReflectionMapping, CubeRefractionMapping, WebGPUCoordinateSystem } from '../../constants.js'; +import { materialEnvRotation } from './MaterialNode.js'; /** * This type of uniform node represents a cube texture. @@ -101,14 +102,12 @@ class CubeTextureNode extends TextureNode { if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem || ! texture.isRenderTargetTexture ) { - return vec3( uvNode.x.negate(), uvNode.yz ); - - } else { - - return uvNode; + uvNode = vec3( uvNode.x.negate(), uvNode.yz ); } + return materialEnvRotation.mul( uvNode ); + } /** diff --git a/src/nodes/accessors/MaterialNode.js b/src/nodes/accessors/MaterialNode.js index 6a54d5c57d2377..dc35f720d91537 100644 --- a/src/nodes/accessors/MaterialNode.js +++ b/src/nodes/accessors/MaterialNode.js @@ -7,8 +7,12 @@ import { uniform } from '../core/UniformNode.js'; import { normalMap } from '../display/NormalMapNode.js'; import { bumpMap } from '../display/BumpMapNode.js'; import { Vector2 } from '../../math/Vector2.js'; +import { Euler } from '../../math/Euler.js'; +import { Matrix4 } from '../../math/Matrix4.js'; const _propertyCache = new Map(); +const _e1 = /*@__PURE__*/ new Euler(); +const _m1 = /*@__PURE__*/ new Matrix4(); /** * This class should simplify the node access to material properties. @@ -386,6 +390,12 @@ class MaterialNode extends Node { node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 ); + } else if ( scope === MaterialNode.ENV_INTENSITY ) { + + const scene = builder.scene; + + node = material.envMap ? this.getFloat( 'envMapIntensity' ) : reference( 'environmentIntensity', 'float', scene ); + } else { const outputType = this.getNodeType( builder ); @@ -437,6 +447,7 @@ MaterialNode.POINT_SIZE = 'size'; MaterialNode.DISPERSION = 'dispersion'; MaterialNode.LIGHT_MAP = 'light'; MaterialNode.AO = 'ao'; +MaterialNode.ENV_INTENSITY = 'envIntensity'; export default MaterialNode; @@ -769,3 +780,44 @@ export const materialAnisotropyVector = /*@__PURE__*/ uniform( new Vector2() ).o this.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); } ); + +/** + * TSL object that represents the intensity of environment maps of PBR materials. + * When `material.envMap` is set, the value is `material.envMapIntensity` otherwise `scene.environmentIntensity`. + * + * @tsl + * @type {Node} + */ +export const materialEnvIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ENV_INTENSITY ); + +/** + * TSL object that represents the rotation of environment maps. + * When `material.envMap` is set, the value is `material.envMapRotation`. `scene.environmentRotation` controls the + * rotation of `scene.environment` instead. + * + * @tsl + * @type {Node} + */ +export const materialEnvRotation = /*@__PURE__*/ uniform( new Matrix4() ).onReference( function ( frame ) { + + return frame.material; + +} ).onRenderUpdate( function ( { material, scene } ) { + + const rotation = ( scene.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; + + if ( rotation ) { + + _e1.copy( rotation ); + + _m1.makeRotationFromEuler( _e1 ); + + } else { + + _m1.identity(); + + } + + return _m1; + +} ); diff --git a/src/nodes/lighting/EnvironmentNode.js b/src/nodes/lighting/EnvironmentNode.js index 3db64254096526..e61fa88af161bf 100644 --- a/src/nodes/lighting/EnvironmentNode.js +++ b/src/nodes/lighting/EnvironmentNode.js @@ -5,9 +5,9 @@ import { cameraViewMatrix } from '../accessors/Camera.js'; import { transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld } from '../accessors/Normal.js'; import { positionViewDirection } from '../accessors/Position.js'; import { float } from '../tsl/TSLBase.js'; -import { reference } from '../accessors/ReferenceNode.js'; import { transformedBentNormalView } from '../accessors/AccessorsUtils.js'; import { pmremTexture } from '../pmrem/PMREMNode.js'; +import { materialEnvIntensity } from '../accessors/MaterialNode.js'; const _envNodeCache = new WeakMap(); @@ -71,14 +71,11 @@ class EnvironmentNode extends LightingNode { // - const envMap = material.envMap; - const intensity = envMap ? reference( 'envMapIntensity', 'float', builder.material ) : reference( 'environmentIntensity', 'float', builder.scene ); // @TODO: Add materialEnvIntensity in MaterialNode - const useAnisotropy = material.useAnisotropy === true || material.anisotropy > 0; const radianceNormalView = useAnisotropy ? transformedBentNormalView : transformedNormalView; - const radiance = envNode.context( createRadianceContext( roughness, radianceNormalView ) ).mul( intensity ); - const irradiance = envNode.context( createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity ); + const radiance = envNode.context( createRadianceContext( roughness, radianceNormalView ) ).mul( materialEnvIntensity ); + const irradiance = envNode.context( createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( materialEnvIntensity ); const isolateRadiance = cache( radiance ); const isolateIrradiance = cache( irradiance ); @@ -95,7 +92,7 @@ class EnvironmentNode extends LightingNode { if ( clearcoatRadiance ) { - const clearcoatRadianceContext = envNode.context( createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( intensity ); + const clearcoatRadianceContext = envNode.context( createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( materialEnvIntensity ); const isolateClearcoatRadiance = cache( clearcoatRadianceContext ); clearcoatRadiance.addAssign( isolateClearcoatRadiance ); diff --git a/src/nodes/pmrem/PMREMNode.js b/src/nodes/pmrem/PMREMNode.js index ea4dc939e67377..23749fd08969f4 100644 --- a/src/nodes/pmrem/PMREMNode.js +++ b/src/nodes/pmrem/PMREMNode.js @@ -7,6 +7,7 @@ import { nodeProxy, vec3 } from '../tsl/TSLBase.js'; import { Texture } from '../../textures/Texture.js'; import PMREMGenerator from '../../renderers/common/extras/PMREMGenerator.js'; +import { materialEnvRotation } from '../accessors/MaterialNode.js'; const _cache = new WeakMap(); @@ -313,7 +314,7 @@ class PMREMNode extends TempNode { // - uvNode = vec3( uvNode.x, uvNode.y.negate(), uvNode.z ); + uvNode = materialEnvRotation.mul( vec3( uvNode.x, uvNode.y.negate(), uvNode.z ) ); // From 4ca0b40e33b125fec2e1e3bee46211ac5d57a9be Mon Sep 17 00:00:00 2001 From: sunag Date: Sat, 15 Feb 2025 17:37:39 -0300 Subject: [PATCH 2/3] move `materialEnvIntensity` and `materialEnvRotation` to `MaterialProperties` --- src/nodes/accessors/CubeTextureNode.js | 2 +- src/nodes/accessors/MaterialNode.js | 52 ----------------------- src/nodes/accessors/MaterialProperties.js | 46 ++++++++++++++++++++ src/nodes/lighting/EnvironmentNode.js | 2 +- src/nodes/pmrem/PMREMNode.js | 2 +- 5 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/nodes/accessors/CubeTextureNode.js b/src/nodes/accessors/CubeTextureNode.js index 947c45945a092d..996f175e08d449 100644 --- a/src/nodes/accessors/CubeTextureNode.js +++ b/src/nodes/accessors/CubeTextureNode.js @@ -3,7 +3,7 @@ import { reflectVector, refractVector } from './ReflectVector.js'; import { nodeProxy, vec3 } from '../tsl/TSLBase.js'; import { CubeReflectionMapping, CubeRefractionMapping, WebGPUCoordinateSystem } from '../../constants.js'; -import { materialEnvRotation } from './MaterialNode.js'; +import { materialEnvRotation } from './MaterialProperties.js'; /** * This type of uniform node represents a cube texture. diff --git a/src/nodes/accessors/MaterialNode.js b/src/nodes/accessors/MaterialNode.js index dc35f720d91537..6a54d5c57d2377 100644 --- a/src/nodes/accessors/MaterialNode.js +++ b/src/nodes/accessors/MaterialNode.js @@ -7,12 +7,8 @@ import { uniform } from '../core/UniformNode.js'; import { normalMap } from '../display/NormalMapNode.js'; import { bumpMap } from '../display/BumpMapNode.js'; import { Vector2 } from '../../math/Vector2.js'; -import { Euler } from '../../math/Euler.js'; -import { Matrix4 } from '../../math/Matrix4.js'; const _propertyCache = new Map(); -const _e1 = /*@__PURE__*/ new Euler(); -const _m1 = /*@__PURE__*/ new Matrix4(); /** * This class should simplify the node access to material properties. @@ -390,12 +386,6 @@ class MaterialNode extends Node { node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 ); - } else if ( scope === MaterialNode.ENV_INTENSITY ) { - - const scene = builder.scene; - - node = material.envMap ? this.getFloat( 'envMapIntensity' ) : reference( 'environmentIntensity', 'float', scene ); - } else { const outputType = this.getNodeType( builder ); @@ -447,7 +437,6 @@ MaterialNode.POINT_SIZE = 'size'; MaterialNode.DISPERSION = 'dispersion'; MaterialNode.LIGHT_MAP = 'light'; MaterialNode.AO = 'ao'; -MaterialNode.ENV_INTENSITY = 'envIntensity'; export default MaterialNode; @@ -780,44 +769,3 @@ export const materialAnisotropyVector = /*@__PURE__*/ uniform( new Vector2() ).o this.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); } ); - -/** - * TSL object that represents the intensity of environment maps of PBR materials. - * When `material.envMap` is set, the value is `material.envMapIntensity` otherwise `scene.environmentIntensity`. - * - * @tsl - * @type {Node} - */ -export const materialEnvIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ENV_INTENSITY ); - -/** - * TSL object that represents the rotation of environment maps. - * When `material.envMap` is set, the value is `material.envMapRotation`. `scene.environmentRotation` controls the - * rotation of `scene.environment` instead. - * - * @tsl - * @type {Node} - */ -export const materialEnvRotation = /*@__PURE__*/ uniform( new Matrix4() ).onReference( function ( frame ) { - - return frame.material; - -} ).onRenderUpdate( function ( { material, scene } ) { - - const rotation = ( scene.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; - - if ( rotation ) { - - _e1.copy( rotation ); - - _m1.makeRotationFromEuler( _e1 ); - - } else { - - _m1.identity(); - - } - - return _m1; - -} ); diff --git a/src/nodes/accessors/MaterialProperties.js b/src/nodes/accessors/MaterialProperties.js index 3f46b2de0d40ef..18000826512c31 100644 --- a/src/nodes/accessors/MaterialProperties.js +++ b/src/nodes/accessors/MaterialProperties.js @@ -1,5 +1,10 @@ +import { Euler } from '../../math/Euler.js'; +import { Matrix4 } from '../../math/Matrix4.js'; import { uniform } from '../core/UniformNode.js'; +const _e1 = /*@__PURE__*/ new Euler(); +const _m1 = /*@__PURE__*/ new Matrix4(); + /** * TSL object that represents the refraction ratio of the material used for rendering the current object. * @@ -7,3 +12,44 @@ import { uniform } from '../core/UniformNode.js'; * @type {UniformNode} */ export const materialRefractionRatio = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onRenderUpdate( ( { material } ) => material.refractionRatio ); + +/** + * TSL object that represents the intensity of environment maps of PBR materials. + * When `material.envMap` is set, the value is `material.envMapIntensity` otherwise `scene.environmentIntensity`. + * + * @tsl + * @type {Node} + */ +export const materialEnvIntensity = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onRenderUpdate( ( { material, scene } ) => material.envMap ? material.envIntensity : scene.environmentIntensity ); + +/** + * TSL object that represents the rotation of environment maps. + * When `material.envMap` is set, the value is `material.envMapRotation`. `scene.environmentRotation` controls the + * rotation of `scene.environment` instead. + * + * @tsl + * @type {Node} + */ +export const materialEnvRotation = /*@__PURE__*/ uniform( new Matrix4() ).onReference( function ( frame ) { + + return frame.material; + +} ).onRenderUpdate( function ( { material, scene } ) { + + const rotation = ( scene.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; + + if ( rotation ) { + + _e1.copy( rotation ); + + _m1.makeRotationFromEuler( _e1 ); + + } else { + + _m1.identity(); + + } + + return _m1; + +} ); diff --git a/src/nodes/lighting/EnvironmentNode.js b/src/nodes/lighting/EnvironmentNode.js index e61fa88af161bf..f2a15a737e630d 100644 --- a/src/nodes/lighting/EnvironmentNode.js +++ b/src/nodes/lighting/EnvironmentNode.js @@ -7,7 +7,7 @@ import { positionViewDirection } from '../accessors/Position.js'; import { float } from '../tsl/TSLBase.js'; import { transformedBentNormalView } from '../accessors/AccessorsUtils.js'; import { pmremTexture } from '../pmrem/PMREMNode.js'; -import { materialEnvIntensity } from '../accessors/MaterialNode.js'; +import { materialEnvIntensity } from '../accessors/MaterialProperties.js'; const _envNodeCache = new WeakMap(); diff --git a/src/nodes/pmrem/PMREMNode.js b/src/nodes/pmrem/PMREMNode.js index 23749fd08969f4..693cc7ad670e3d 100644 --- a/src/nodes/pmrem/PMREMNode.js +++ b/src/nodes/pmrem/PMREMNode.js @@ -7,7 +7,7 @@ import { nodeProxy, vec3 } from '../tsl/TSLBase.js'; import { Texture } from '../../textures/Texture.js'; import PMREMGenerator from '../../renderers/common/extras/PMREMGenerator.js'; -import { materialEnvRotation } from '../accessors/MaterialNode.js'; +import { materialEnvRotation } from '../accessors/MaterialProperties.js'; const _cache = new WeakMap(); From fc850e1565f7156e917aa571115909728b7dd19d Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Sat, 15 Feb 2025 23:07:38 +0100 Subject: [PATCH 3/3] MaterialPropeties: Fix update. --- src/nodes/accessors/MaterialProperties.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/nodes/accessors/MaterialProperties.js b/src/nodes/accessors/MaterialProperties.js index 18000826512c31..10fd2f98b648cd 100644 --- a/src/nodes/accessors/MaterialProperties.js +++ b/src/nodes/accessors/MaterialProperties.js @@ -11,7 +11,7 @@ const _m1 = /*@__PURE__*/ new Matrix4(); * @tsl * @type {UniformNode} */ -export const materialRefractionRatio = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onRenderUpdate( ( { material } ) => material.refractionRatio ); +export const materialRefractionRatio = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onObjectUpdate( ( { material } ) => material.refractionRatio ); /** * TSL object that represents the intensity of environment maps of PBR materials. @@ -20,7 +20,11 @@ export const materialRefractionRatio = /*@__PURE__*/ uniform( 0 ).onReference( ( * @tsl * @type {Node} */ -export const materialEnvIntensity = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onRenderUpdate( ( { material, scene } ) => material.envMap ? material.envIntensity : scene.environmentIntensity ); +export const materialEnvIntensity = /*@__PURE__*/ uniform( 1 ).onReference( ( { material } ) => material ).onObjectUpdate( function ( { material, scene } ) { + + return material.envMap ? material.envMapIntensity : scene.environmentIntensity; + +} ); /** * TSL object that represents the rotation of environment maps. @@ -34,7 +38,7 @@ export const materialEnvRotation = /*@__PURE__*/ uniform( new Matrix4() ).onRefe return frame.material; -} ).onRenderUpdate( function ( { material, scene } ) { +} ).onObjectUpdate( function ( { material, scene } ) { const rotation = ( scene.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation;