From e4110f5aeaf202c7ef61875d80b444837be14552 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 7 Apr 2026 13:33:07 +0200 Subject: [PATCH 1/2] MathNode: Fix `transformDirection()`. (#33347) --- src/nodes/accessors/Normal.js | 6 +++--- src/nodes/accessors/ReflectVector.js | 6 +++--- src/nodes/accessors/Tangent.js | 4 ++-- src/nodes/lighting/EnvironmentNode.js | 4 ++-- src/nodes/math/MathNode.js | 15 +++++++-------- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/nodes/accessors/Normal.js b/src/nodes/accessors/Normal.js index 9ba97f3f44a879..3a7eb4c0c62497 100644 --- a/src/nodes/accessors/Normal.js +++ b/src/nodes/accessors/Normal.js @@ -1,5 +1,5 @@ import { attribute } from '../core/AttributeNode.js'; -import { cameraViewMatrix } from './Camera.js'; +import { cameraViewMatrix, cameraWorldMatrix } from './Camera.js'; import { modelNormalMatrix, modelWorldMatrix } from './ModelNode.js'; import { mat3, vec3, Fn } from '../tsl/TSLBase.js'; import { positionView } from './Position.js'; @@ -74,7 +74,7 @@ export const normalViewGeometry = /*@__PURE__*/ ( Fn( ( builder ) => { */ export const normalWorldGeometry = /*@__PURE__*/ ( Fn( ( builder ) => { - let normal = normalViewGeometry.transformDirection( cameraViewMatrix ); + let normal = normalViewGeometry.transformDirection( cameraWorldMatrix ); if ( builder.isFlatShading() !== true ) { @@ -124,7 +124,7 @@ export const normalView = /*@__PURE__*/ ( Fn( ( builder ) => { * @tsl * @type {Node} */ -export const normalWorld = /*@__PURE__*/ normalView.transformDirection( cameraViewMatrix ).toVar( 'normalWorld' ); +export const normalWorld = /*@__PURE__*/ normalView.transformDirection( cameraWorldMatrix ).toVar( 'normalWorld' ); /** * TSL object that represents the clearcoat vertex normal of the current rendered object in view space. diff --git a/src/nodes/accessors/ReflectVector.js b/src/nodes/accessors/ReflectVector.js index f7274b5c722238..3012f01ba7f8be 100644 --- a/src/nodes/accessors/ReflectVector.js +++ b/src/nodes/accessors/ReflectVector.js @@ -1,4 +1,4 @@ -import { cameraViewMatrix } from './Camera.js'; +import { cameraWorldMatrix } from './Camera.js'; import { normalView } from './Normal.js'; import { positionViewDirection } from './Position.js'; import { materialRefractionRatio } from './MaterialProperties.js'; @@ -25,7 +25,7 @@ export const refractView = /*@__PURE__*/ positionViewDirection.negate().refract( * @tsl * @type {Node} */ -export const reflectVector = /*@__PURE__*/ reflectView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); +export const reflectVector = /*@__PURE__*/ reflectView.transformDirection( cameraWorldMatrix ).toVar( 'reflectVector' ); /** * Used for sampling cube maps when using cube refraction mapping. @@ -33,4 +33,4 @@ export const reflectVector = /*@__PURE__*/ reflectView.transformDirection( camer * @tsl * @type {Node} */ -export const refractVector = /*@__PURE__*/ refractView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); +export const refractVector = /*@__PURE__*/ refractView.transformDirection( cameraWorldMatrix ).toVar( 'reflectVector' ); diff --git a/src/nodes/accessors/Tangent.js b/src/nodes/accessors/Tangent.js index 40a9fabeec6033..f01f383eae8e2c 100644 --- a/src/nodes/accessors/Tangent.js +++ b/src/nodes/accessors/Tangent.js @@ -1,5 +1,5 @@ import { attribute } from '../core/AttributeNode.js'; -import { cameraViewMatrix } from './Camera.js'; +import { cameraWorldMatrix } from './Camera.js'; import { modelViewMatrix } from './ModelNode.js'; import { Fn, vec4 } from '../tsl/TSLBase.js'; import { tangentViewFrame } from './TangentUtils.js'; @@ -57,4 +57,4 @@ export const tangentView = /*@__PURE__*/ ( Fn( ( builder ) => { * @tsl * @type {Node} */ -export const tangentWorld = /*@__PURE__*/ tangentView.transformDirection( cameraViewMatrix ).toVarying( 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' ); +export const tangentWorld = /*@__PURE__*/ tangentView.transformDirection( cameraWorldMatrix ).toVarying( 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' ); diff --git a/src/nodes/lighting/EnvironmentNode.js b/src/nodes/lighting/EnvironmentNode.js index afed15d0f793ec..f794d638815d01 100644 --- a/src/nodes/lighting/EnvironmentNode.js +++ b/src/nodes/lighting/EnvironmentNode.js @@ -1,7 +1,7 @@ import LightingNode from './LightingNode.js'; import { isolate } from '../core/IsolateNode.js'; import { roughness, clearcoatRoughness } from '../core/PropertyNode.js'; -import { cameraViewMatrix } from '../accessors/Camera.js'; +import { cameraWorldMatrix } from '../accessors/Camera.js'; import { normalView, clearcoatNormalView, normalWorld } from '../accessors/Normal.js'; import { positionViewDirection } from '../accessors/Position.js'; import { float, pow4 } from '../tsl/TSLBase.js'; @@ -144,7 +144,7 @@ const createRadianceContext = ( roughnessNode, normalViewNode ) => { // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane. reflectVec = pow4( roughnessNode ).mix( reflectVec, normalViewNode ).normalize(); - reflectVec = reflectVec.transformDirection( cameraViewMatrix ); + reflectVec = reflectVec.transformDirection( cameraWorldMatrix ); } diff --git a/src/nodes/math/MathNode.js b/src/nodes/math/MathNode.js index 3688c7bd55f338..e804172cf5375d 100644 --- a/src/nodes/math/MathNode.js +++ b/src/nodes/math/MathNode.js @@ -184,22 +184,21 @@ class MathNode extends TempNode { // dir can be either a direction vector or a normal vector // upper-left 3x3 of matrix is assumed to be orthogonal - let tA = aNode; - let tB = bNode; + let matrixNode, dirNode; - if ( builder.isMatrix( tA.getNodeType( builder ) ) ) { + if ( builder.isMatrix( aNode.getNodeType( builder ) ) ) { - tB = vec4( vec3( tB ), 0.0 ); + matrixNode = aNode; + dirNode = vec4( vec3( bNode ), 0.0 ); } else { - tA = vec4( vec3( tA ), 0.0 ); + matrixNode = bNode; + dirNode = vec4( vec3( aNode ), 0.0 ); } - const mulNode = mul( tA, tB ).xyz; - - outputNode = normalize( mulNode ); + outputNode = normalize( mul( matrixNode, dirNode ).xyz ); } From 8b169b04fffa5fdaf546b7c53159c78288dd69f3 Mon Sep 17 00:00:00 2001 From: WestLangley Date: Tue, 7 Apr 2026 08:42:07 -0400 Subject: [PATCH 2/2] Revert "MathNode: Fix `transformDirection()`." (#33349) --- src/nodes/accessors/Normal.js | 6 +++--- src/nodes/accessors/ReflectVector.js | 6 +++--- src/nodes/accessors/Tangent.js | 4 ++-- src/nodes/lighting/EnvironmentNode.js | 4 ++-- src/nodes/math/MathNode.js | 15 ++++++++------- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/nodes/accessors/Normal.js b/src/nodes/accessors/Normal.js index 3a7eb4c0c62497..9ba97f3f44a879 100644 --- a/src/nodes/accessors/Normal.js +++ b/src/nodes/accessors/Normal.js @@ -1,5 +1,5 @@ import { attribute } from '../core/AttributeNode.js'; -import { cameraViewMatrix, cameraWorldMatrix } from './Camera.js'; +import { cameraViewMatrix } from './Camera.js'; import { modelNormalMatrix, modelWorldMatrix } from './ModelNode.js'; import { mat3, vec3, Fn } from '../tsl/TSLBase.js'; import { positionView } from './Position.js'; @@ -74,7 +74,7 @@ export const normalViewGeometry = /*@__PURE__*/ ( Fn( ( builder ) => { */ export const normalWorldGeometry = /*@__PURE__*/ ( Fn( ( builder ) => { - let normal = normalViewGeometry.transformDirection( cameraWorldMatrix ); + let normal = normalViewGeometry.transformDirection( cameraViewMatrix ); if ( builder.isFlatShading() !== true ) { @@ -124,7 +124,7 @@ export const normalView = /*@__PURE__*/ ( Fn( ( builder ) => { * @tsl * @type {Node} */ -export const normalWorld = /*@__PURE__*/ normalView.transformDirection( cameraWorldMatrix ).toVar( 'normalWorld' ); +export const normalWorld = /*@__PURE__*/ normalView.transformDirection( cameraViewMatrix ).toVar( 'normalWorld' ); /** * TSL object that represents the clearcoat vertex normal of the current rendered object in view space. diff --git a/src/nodes/accessors/ReflectVector.js b/src/nodes/accessors/ReflectVector.js index 3012f01ba7f8be..f7274b5c722238 100644 --- a/src/nodes/accessors/ReflectVector.js +++ b/src/nodes/accessors/ReflectVector.js @@ -1,4 +1,4 @@ -import { cameraWorldMatrix } from './Camera.js'; +import { cameraViewMatrix } from './Camera.js'; import { normalView } from './Normal.js'; import { positionViewDirection } from './Position.js'; import { materialRefractionRatio } from './MaterialProperties.js'; @@ -25,7 +25,7 @@ export const refractView = /*@__PURE__*/ positionViewDirection.negate().refract( * @tsl * @type {Node} */ -export const reflectVector = /*@__PURE__*/ reflectView.transformDirection( cameraWorldMatrix ).toVar( 'reflectVector' ); +export const reflectVector = /*@__PURE__*/ reflectView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); /** * Used for sampling cube maps when using cube refraction mapping. @@ -33,4 +33,4 @@ export const reflectVector = /*@__PURE__*/ reflectView.transformDirection( camer * @tsl * @type {Node} */ -export const refractVector = /*@__PURE__*/ refractView.transformDirection( cameraWorldMatrix ).toVar( 'reflectVector' ); +export const refractVector = /*@__PURE__*/ refractView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); diff --git a/src/nodes/accessors/Tangent.js b/src/nodes/accessors/Tangent.js index f01f383eae8e2c..40a9fabeec6033 100644 --- a/src/nodes/accessors/Tangent.js +++ b/src/nodes/accessors/Tangent.js @@ -1,5 +1,5 @@ import { attribute } from '../core/AttributeNode.js'; -import { cameraWorldMatrix } from './Camera.js'; +import { cameraViewMatrix } from './Camera.js'; import { modelViewMatrix } from './ModelNode.js'; import { Fn, vec4 } from '../tsl/TSLBase.js'; import { tangentViewFrame } from './TangentUtils.js'; @@ -57,4 +57,4 @@ export const tangentView = /*@__PURE__*/ ( Fn( ( builder ) => { * @tsl * @type {Node} */ -export const tangentWorld = /*@__PURE__*/ tangentView.transformDirection( cameraWorldMatrix ).toVarying( 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' ); +export const tangentWorld = /*@__PURE__*/ tangentView.transformDirection( cameraViewMatrix ).toVarying( 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' ); diff --git a/src/nodes/lighting/EnvironmentNode.js b/src/nodes/lighting/EnvironmentNode.js index f794d638815d01..afed15d0f793ec 100644 --- a/src/nodes/lighting/EnvironmentNode.js +++ b/src/nodes/lighting/EnvironmentNode.js @@ -1,7 +1,7 @@ import LightingNode from './LightingNode.js'; import { isolate } from '../core/IsolateNode.js'; import { roughness, clearcoatRoughness } from '../core/PropertyNode.js'; -import { cameraWorldMatrix } from '../accessors/Camera.js'; +import { cameraViewMatrix } from '../accessors/Camera.js'; import { normalView, clearcoatNormalView, normalWorld } from '../accessors/Normal.js'; import { positionViewDirection } from '../accessors/Position.js'; import { float, pow4 } from '../tsl/TSLBase.js'; @@ -144,7 +144,7 @@ const createRadianceContext = ( roughnessNode, normalViewNode ) => { // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane. reflectVec = pow4( roughnessNode ).mix( reflectVec, normalViewNode ).normalize(); - reflectVec = reflectVec.transformDirection( cameraWorldMatrix ); + reflectVec = reflectVec.transformDirection( cameraViewMatrix ); } diff --git a/src/nodes/math/MathNode.js b/src/nodes/math/MathNode.js index e804172cf5375d..3688c7bd55f338 100644 --- a/src/nodes/math/MathNode.js +++ b/src/nodes/math/MathNode.js @@ -184,21 +184,22 @@ class MathNode extends TempNode { // dir can be either a direction vector or a normal vector // upper-left 3x3 of matrix is assumed to be orthogonal - let matrixNode, dirNode; + let tA = aNode; + let tB = bNode; - if ( builder.isMatrix( aNode.getNodeType( builder ) ) ) { + if ( builder.isMatrix( tA.getNodeType( builder ) ) ) { - matrixNode = aNode; - dirNode = vec4( vec3( bNode ), 0.0 ); + tB = vec4( vec3( tB ), 0.0 ); } else { - matrixNode = bNode; - dirNode = vec4( vec3( aNode ), 0.0 ); + tA = vec4( vec3( tA ), 0.0 ); } - outputNode = normalize( mul( matrixNode, dirNode ).xyz ); + const mulNode = mul( tA, tB ).xyz; + + outputNode = normalize( mulNode ); }