Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGPURenderer: Support rotation of env maps. #30528

Merged
merged 3 commits into from
Feb 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 } ) {
Copy link
Collaborator Author

@Mugen87 Mugen87 Feb 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to change the update scope from render to object otherwise different intensity values in different materials were not honored correctly. Same for rotation and refraction ratio.


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