Skip to content

Commit 089ba61

Browse files
committed
WebGPURenderer: Support rotation of env maps.
1 parent d264b7c commit 089ba61

File tree

5 files changed

+71
-14
lines changed

5 files changed

+71
-14
lines changed

examples/webgpu_materials_envmaps.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@
107107
Refraction: false,
108108
backgroundRotationX: false,
109109
backgroundRotationY: false,
110-
backgroundRotationZ: false
110+
backgroundRotationZ: false,
111+
syncMaterial: false
111112
};
112113

113114
const gui = new GUI( { width: 300 } );
@@ -133,6 +134,7 @@
133134
gui.add( params, 'backgroundRotationX' );
134135
gui.add( params, 'backgroundRotationY' );
135136
gui.add( params, 'backgroundRotationZ' );
137+
gui.add( params, 'syncMaterial' );
136138
gui.open();
137139

138140
window.addEventListener( 'resize', onWindowResize );
@@ -170,6 +172,12 @@
170172

171173
}
172174

175+
if ( params.syncMaterial ) {
176+
177+
sphereMesh.material.envMapRotation.copy( scene.backgroundRotation );
178+
179+
}
180+
173181
camera.lookAt( scene.position );
174182
renderer.render( scene, camera );
175183

src/nodes/accessors/CubeTextureNode.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { reflectVector, refractVector } from './ReflectVector.js';
33
import { nodeProxy, vec3 } from '../tsl/TSLBase.js';
44

55
import { CubeReflectionMapping, CubeRefractionMapping, WebGPUCoordinateSystem } from '../../constants.js';
6+
import { materialEnvRotation } from './MaterialNode.js';
67

78
/**
89
* This type of uniform node represents a cube texture.
@@ -101,14 +102,12 @@ class CubeTextureNode extends TextureNode {
101102

102103
if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem || ! texture.isRenderTargetTexture ) {
103104

104-
return vec3( uvNode.x.negate(), uvNode.yz );
105-
106-
} else {
107-
108-
return uvNode;
105+
uvNode = vec3( uvNode.x.negate(), uvNode.yz );
109106

110107
}
111108

109+
return materialEnvRotation.mul( uvNode );
110+
112111
}
113112

114113
/**

src/nodes/accessors/MaterialNode.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ import { uniform } from '../core/UniformNode.js';
77
import { normalMap } from '../display/NormalMapNode.js';
88
import { bumpMap } from '../display/BumpMapNode.js';
99
import { Vector2 } from '../../math/Vector2.js';
10+
import { Euler } from '../../math/Euler.js';
11+
import { Matrix4 } from '../../math/Matrix4.js';
1012

1113
const _propertyCache = new Map();
14+
const _e1 = /*@__PURE__*/ new Euler();
15+
const _m1 = /*@__PURE__*/ new Matrix4();
1216

1317
/**
1418
* This class should simplify the node access to material properties.
@@ -386,6 +390,12 @@ class MaterialNode extends Node {
386390

387391
node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 );
388392

393+
} else if ( scope === MaterialNode.ENV_INTENSITY ) {
394+
395+
const scene = builder.scene;
396+
397+
node = material.envMap ? this.getFloat( 'envMapIntensity' ) : reference( 'environmentIntensity', 'float', scene );
398+
389399
} else {
390400

391401
const outputType = this.getNodeType( builder );
@@ -437,6 +447,7 @@ MaterialNode.POINT_SIZE = 'size';
437447
MaterialNode.DISPERSION = 'dispersion';
438448
MaterialNode.LIGHT_MAP = 'light';
439449
MaterialNode.AO = 'ao';
450+
MaterialNode.ENV_INTENSITY = 'envIntensity';
440451

441452
export default MaterialNode;
442453

@@ -769,3 +780,44 @@ export const materialAnisotropyVector = /*@__PURE__*/ uniform( new Vector2() ).o
769780
this.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) );
770781

771782
} );
783+
784+
/**
785+
* TSL object that represents the intensity of environment maps of PBR materials.
786+
* When `material.envMap` is set, the value is `material.envMapIntensity` otherwise `scene.environmentIntensity`.
787+
*
788+
* @tsl
789+
* @type {Node<float>}
790+
*/
791+
export const materialEnvIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ENV_INTENSITY );
792+
793+
/**
794+
* TSL object that represents the rotation of environment maps.
795+
* When `material.envMap` is set, the value is `material.envMapRotation`. `scene.environmentRotation` controls the
796+
* rotation of `scene.environment` instead.
797+
*
798+
* @tsl
799+
* @type {Node<mat4>}
800+
*/
801+
export const materialEnvRotation = /*@__PURE__*/ uniform( new Matrix4() ).onReference( function ( frame ) {
802+
803+
return frame.material;
804+
805+
} ).onRenderUpdate( function ( { material, scene } ) {
806+
807+
const rotation = ( scene.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation;
808+
809+
if ( rotation ) {
810+
811+
_e1.copy( rotation );
812+
813+
_m1.makeRotationFromEuler( _e1 );
814+
815+
} else {
816+
817+
_m1.identity();
818+
819+
}
820+
821+
return _m1;
822+
823+
} );

src/nodes/lighting/EnvironmentNode.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import { cameraViewMatrix } from '../accessors/Camera.js';
55
import { transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld } from '../accessors/Normal.js';
66
import { positionViewDirection } from '../accessors/Position.js';
77
import { float } from '../tsl/TSLBase.js';
8-
import { reference } from '../accessors/ReferenceNode.js';
98
import { transformedBentNormalView } from '../accessors/AccessorsUtils.js';
109
import { pmremTexture } from '../pmrem/PMREMNode.js';
10+
import { materialEnvIntensity } from '../accessors/MaterialNode.js';
1111

1212
const _envNodeCache = new WeakMap();
1313

@@ -71,14 +71,11 @@ class EnvironmentNode extends LightingNode {
7171

7272
//
7373

74-
const envMap = material.envMap;
75-
const intensity = envMap ? reference( 'envMapIntensity', 'float', builder.material ) : reference( 'environmentIntensity', 'float', builder.scene ); // @TODO: Add materialEnvIntensity in MaterialNode
76-
7774
const useAnisotropy = material.useAnisotropy === true || material.anisotropy > 0;
7875
const radianceNormalView = useAnisotropy ? transformedBentNormalView : transformedNormalView;
7976

80-
const radiance = envNode.context( createRadianceContext( roughness, radianceNormalView ) ).mul( intensity );
81-
const irradiance = envNode.context( createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity );
77+
const radiance = envNode.context( createRadianceContext( roughness, radianceNormalView ) ).mul( materialEnvIntensity );
78+
const irradiance = envNode.context( createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( materialEnvIntensity );
8279

8380
const isolateRadiance = cache( radiance );
8481
const isolateIrradiance = cache( irradiance );
@@ -95,7 +92,7 @@ class EnvironmentNode extends LightingNode {
9592

9693
if ( clearcoatRadiance ) {
9794

98-
const clearcoatRadianceContext = envNode.context( createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( intensity );
95+
const clearcoatRadianceContext = envNode.context( createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( materialEnvIntensity );
9996
const isolateClearcoatRadiance = cache( clearcoatRadianceContext );
10097

10198
clearcoatRadiance.addAssign( isolateClearcoatRadiance );

src/nodes/pmrem/PMREMNode.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { nodeProxy, vec3 } from '../tsl/TSLBase.js';
77

88
import { Texture } from '../../textures/Texture.js';
99
import PMREMGenerator from '../../renderers/common/extras/PMREMGenerator.js';
10+
import { materialEnvRotation } from '../accessors/MaterialNode.js';
1011

1112
const _cache = new WeakMap();
1213

@@ -313,7 +314,7 @@ class PMREMNode extends TempNode {
313314

314315
//
315316

316-
uvNode = vec3( uvNode.x, uvNode.y.negate(), uvNode.z );
317+
uvNode = materialEnvRotation.mul( vec3( uvNode.x, uvNode.y.negate(), uvNode.z ) );
317318

318319
//
319320

0 commit comments

Comments
 (0)