diff --git a/src/nodes/accessors/Camera.js b/src/nodes/accessors/Camera.js index 331d331c297a79..4264831b7d469f 100644 --- a/src/nodes/accessors/Camera.js +++ b/src/nodes/accessors/Camera.js @@ -1,7 +1,7 @@ import { uniform } from '../core/UniformNode.js'; import { renderGroup, sharedUniformGroup } from '../core/UniformGroupNode.js'; import { Vector3 } from '../../math/Vector3.js'; -import { Fn, vec4 } from '../tsl/TSLBase.js'; +import { Fn, vec4, mat3 } from '../tsl/TSLBase.js'; import { uniformArray } from './UniformArrayNode.js'; import { builtin } from './BuiltinNode.js'; import { screenSize } from '../display/ScreenNode.js'; @@ -197,6 +197,34 @@ export const cameraViewMatrix = /*@__PURE__*/ ( Fn( ( { camera } ) => { } ).once() )(); +/** + * TSL object that represents the view rotation matrix of the camera used for the current render. + * + * It is the upper-left 3x3 of {@link cameraViewMatrix} (translation removed) and is typically used to transform + * direction vectors (e.g. normals) from world space into view space. + * + * @tsl + * @type {Node} + */ +export const cameraViewRotationMatrix = /*@__PURE__*/ mat3( + + cameraViewMatrix[ 0 ].xyz, + + cameraViewMatrix[ 1 ].xyz, + + cameraViewMatrix[ 2 ].xyz + +).toVar( 'cameraViewRotationMatrix' ); + +/** + * TSL function that transforms a vector from world space to view space. + * + * @tsl + * @param {Node} vector The vector to transform. + * @returns {Node} + */ +export const worldToViewRotation = Fn( ( [ vector ] ) => cameraViewRotationMatrix.mul( vector ) ); + /** * TSL object that represents the world matrix of the camera used for the current render. * diff --git a/src/nodes/accessors/Lights.js b/src/nodes/accessors/Lights.js index ac4245aca26faa..bd970476c9eead 100644 --- a/src/nodes/accessors/Lights.js +++ b/src/nodes/accessors/Lights.js @@ -1,7 +1,7 @@ import { uniform } from '../core/UniformNode.js'; import { renderGroup } from '../core/UniformGroupNode.js'; import { Vector3 } from '../../math/Vector3.js'; -import { cameraViewMatrix } from './Camera.js'; +import { worldToViewRotation } from './Camera.js'; import { positionWorld } from './Position.js'; let uniformsLib; @@ -136,4 +136,4 @@ export function lightViewPosition( light ) { * @param {Light} light -The light source. * @returns {Node} The light's target direction. */ -export const lightTargetDirection = ( light ) => cameraViewMatrix.transformDirection( lightPosition( light ).sub( lightTargetPosition( light ) ) ); +export const lightTargetDirection = ( light ) => worldToViewRotation( lightPosition( light ).sub( lightTargetPosition( light ) ) ).normalize(); diff --git a/src/nodes/accessors/Normal.js b/src/nodes/accessors/Normal.js index 9ba97f3f44a879..b8fe28399750cb 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, worldToViewRotation } from './Camera.js'; import { modelNormalMatrix, modelWorldMatrix } from './ModelNode.js'; import { mat3, vec3, Fn } from '../tsl/TSLBase.js'; import { positionView } from './Position.js'; @@ -194,7 +194,7 @@ export const transformNormalToView = /*@__PURE__*/ Fn( ( [ normal ], builder ) = const transformedNormal = modelNormalMatrix.mul( normal ); - return cameraViewMatrix.transformDirection( transformedNormal ); + return worldToViewRotation( transformedNormal ).normalize(); } );