Skip to content

Commit

Permalink
WebGPURenderer: Support rotation of env maps. (#30528)
Browse files Browse the repository at this point in the history
* WebGPURenderer: Support rotation of env maps.

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

* MaterialPropeties: Fix update.

---------

Co-authored-by: sunag <sunagbrasil@gmail.com>
  • Loading branch information
Mugen87 and sunag authored Feb 15, 2025
1 parent 4144826 commit a39dbfa
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 15 deletions.
10 changes: 9 additions & 1 deletion examples/webgpu_materials_envmaps.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@
Refraction: false,
backgroundRotationX: false,
backgroundRotationY: false,
backgroundRotationZ: false
backgroundRotationZ: false,
syncMaterial: false
};

const gui = new GUI( { width: 300 } );
Expand All @@ -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 );
Expand Down Expand Up @@ -170,6 +172,12 @@

}

if ( params.syncMaterial ) {

sphereMesh.material.envMapRotation.copy( scene.backgroundRotation );

}

camera.lookAt( scene.position );
renderer.render( scene, camera );

Expand Down
9 changes: 4 additions & 5 deletions src/nodes/accessors/CubeTextureNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 );

}

/**
Expand Down
52 changes: 51 additions & 1 deletion src/nodes/accessors/MaterialProperties.js
Original file line number Diff line number Diff line change
@@ -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;

} );
11 changes: 4 additions & 7 deletions src/nodes/lighting/EnvironmentNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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 );
Expand All @@ -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 );
Expand Down
3 changes: 2 additions & 1 deletion src/nodes/pmrem/PMREMNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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 ) );

//

Expand Down

0 comments on commit a39dbfa

Please sign in to comment.