Browse Source

WebGPURenderer: Support rotation of env maps. (#30528)

* WebGPURenderer: Support rotation of env maps.

* move `materialEnvIntensity` and `materialEnvRotation` to `MaterialProperties`

* MaterialPropeties: Fix update.

---------

Co-authored-by: sunag <sunagbrasil@gmail.com>
Michael Herzog 10 months ago
parent
commit
a39dbfad24

+ 9 - 1
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 );
 

+ 4 - 5
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 );
+
 	}
 
 	/**

+ 51 - 1
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<float>}
  */
-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<float>}
+ */
+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<mat4>}
+ */
+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;
+
+} );

+ 4 - 7
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 );

+ 2 - 1
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 ) );
 
 		//
 

粤ICP备19079148号