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..996f175e08d449 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 './MaterialProperties.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/MaterialProperties.js b/src/nodes/accessors/MaterialProperties.js index 3f46b2de0d40ef..10fd2f98b648cd 100644 --- a/src/nodes/accessors/MaterialProperties.js +++ b/src/nodes/accessors/MaterialProperties.js @@ -1,9 +1,59 @@ +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. * * @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. + * When `material.envMap` is set, the value is `material.envMapIntensity` otherwise `scene.environmentIntensity`. + * + * @tsl + * @type {Node} + */ +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. + * 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; + +} ).onObjectUpdate( 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..f2a15a737e630d 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/MaterialProperties.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..693cc7ad670e3d 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/MaterialProperties.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 ) ); //