Просмотр исходного кода

WebGPURenderer: Compute `modelViewMatrix` using GPU (#29299)

* Compute `modelViewMatrix` using GPU

* update `webgpu_tsl_raging_sea` example

* update `webgpu_tsl_procedural_terrain` example

* testing `modelNormalViewMatrix`

* Update MaterialNode.js

* Update webgpu_tsl_raging_sea.jpg

* introduce `transformNormal()` and `transformNormalToView()`

* Update InstanceNode.js

* cleanup

* Update VelocityNode.js

* introduce `highPrecisionModelViewMatrix`

* introduce `highPrecisionModelNormalMatrix`
sunag 1 год назад
Родитель
Сommit
29cb17fecd

BIN
examples/screenshots/webgpu_tsl_raging_sea.jpg


+ 2 - 2
examples/webgpu_tsl_procedural_terrain.html

@@ -27,7 +27,7 @@
 		<script type="module">
 		<script type="module">
 
 
 			import * as THREE from 'three';
 			import * as THREE from 'three';
-			import { mx_noise_float, color, cross, dot, float, modelNormalMatrix, positionLocal, sign, step, Fn, uniform, varying, vec2, vec3, Loop } from 'three/tsl';
+			import { mx_noise_float, color, cross, dot, float, transformNormalToView, positionLocal, sign, step, Fn, uniform, varying, vec2, vec3, Loop } from 'three/tsl';
 
 
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -150,7 +150,7 @@
 			
 			
 				} )();
 				} )();
 
 
-				material.normalNode = modelNormalMatrix.mul( vNormal );
+				material.normalNode = transformNormalToView( vNormal );
 
 
 				material.colorNode = Fn( () => {
 				material.colorNode = Fn( () => {
 
 

+ 2 - 2
examples/webgpu_tsl_raging_sea.html

@@ -27,7 +27,7 @@
 		<script type="module">
 		<script type="module">
 
 
 			import * as THREE from 'three';
 			import * as THREE from 'three';
-			import { float, mx_noise_float, Loop, color, positionLocal, sin, vec2, vec3, mul, timerLocal, uniform, Fn, modelNormalMatrix } from 'three/tsl';
+			import { float, mx_noise_float, Loop, color, positionLocal, sin, vec2, vec3, mul, timerLocal, uniform, Fn, transformNormalToView } from 'three/tsl';
 
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
@@ -122,7 +122,7 @@
 				const toB = positionB.sub( position ).normalize();
 				const toB = positionB.sub( position ).normalize();
 				const normal = toA.cross( toB );
 				const normal = toA.cross( toB );
 
 
-				material.normalNode = modelNormalMatrix.mul( normal );
+				material.normalNode = transformNormalToView( normal );
 
 
 				// emissive
 				// emissive
 
 

+ 3 - 7
src/nodes/accessors/InstanceNode.js

@@ -1,9 +1,9 @@
 import Node from '../core/Node.js';
 import Node from '../core/Node.js';
 import { varyingProperty } from '../core/PropertyNode.js';
 import { varyingProperty } from '../core/PropertyNode.js';
 import { instancedBufferAttribute, instancedDynamicBufferAttribute } from './BufferAttributeNode.js';
 import { instancedBufferAttribute, instancedDynamicBufferAttribute } from './BufferAttributeNode.js';
-import { normalLocal } from './Normal.js';
+import { normalLocal, transformNormal } from './Normal.js';
 import { positionLocal } from './Position.js';
 import { positionLocal } from './Position.js';
-import { nodeProxy, vec3, mat3, mat4 } from '../tsl/TSLBase.js';
+import { nodeProxy, vec3, mat4 } from '../tsl/TSLBase.js';
 import { NodeUpdateType } from '../core/constants.js';
 import { NodeUpdateType } from '../core/constants.js';
 import { buffer } from '../accessors/BufferNode.js';
 import { buffer } from '../accessors/BufferNode.js';
 import { instanceIndex } from '../core/IndexNode.js';
 import { instanceIndex } from '../core/IndexNode.js';
@@ -103,11 +103,7 @@ class InstanceNode extends Node {
 
 
 		if ( builder.hasGeometryAttribute( 'normal' ) ) {
 		if ( builder.hasGeometryAttribute( 'normal' ) ) {
 
 
-			const m = mat3( instanceMatrixNode );
-
-			const transformedNormal = normalLocal.div( vec3( m[ 0 ].dot( m[ 0 ] ), m[ 1 ].dot( m[ 1 ] ), m[ 2 ].dot( m[ 2 ] ) ) );
-
-			const instanceNormal = m.mul( transformedNormal ).xyz;
+			const instanceNormal = transformNormal( normalLocal, instanceMatrixNode );
 
 
 			// ASSIGNS
 			// ASSIGNS
 
 

+ 1 - 0
src/nodes/accessors/MaterialNode.js

@@ -184,6 +184,7 @@ class MaterialNode extends Node {
 			if ( material.normalMap ) {
 			if ( material.normalMap ) {
 
 
 				node = normalMap( this.getTexture( 'normal' ), this.getCache( 'normalScale', 'vec2' ) );
 				node = normalMap( this.getTexture( 'normal' ), this.getCache( 'normalScale', 'vec2' ) );
+				node.normalMapType = material.normalMapType;
 
 
 			} else if ( material.bumpMap ) {
 			} else if ( material.bumpMap ) {
 
 

+ 34 - 4
src/nodes/accessors/ModelNode.js

@@ -1,8 +1,9 @@
 import Object3DNode from './Object3DNode.js';
 import Object3DNode from './Object3DNode.js';
-import { nodeImmutable } from '../tsl/TSLBase.js';
+import { Fn, nodeImmutable } from '../tsl/TSLBase.js';
 import { uniform } from '../core/UniformNode.js';
 import { uniform } from '../core/UniformNode.js';
 
 
 import { Matrix4 } from '../../math/Matrix4.js';
 import { Matrix4 } from '../../math/Matrix4.js';
+import { cameraViewMatrix } from './Camera.js';
 
 
 class ModelNode extends Object3DNode {
 class ModelNode extends Object3DNode {
 
 
@@ -12,7 +13,7 @@ class ModelNode extends Object3DNode {
 
 
 	}
 	}
 
 
-	constructor( scope = ModelNode.VIEW_MATRIX ) {
+	constructor( scope ) {
 
 
 		super( scope );
 		super( scope );
 
 
@@ -31,10 +32,39 @@ class ModelNode extends Object3DNode {
 export default ModelNode;
 export default ModelNode;
 
 
 export const modelDirection = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.DIRECTION );
 export const modelDirection = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.DIRECTION );
-export const modelViewMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.VIEW_MATRIX ).label( 'modelViewMatrix' ).toVar( 'ModelViewMatrix' );
-export const modelNormalMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.NORMAL_MATRIX );
 export const modelWorldMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX );
 export const modelWorldMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX );
 export const modelPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.POSITION );
 export const modelPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.POSITION );
 export const modelScale = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.SCALE );
 export const modelScale = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.SCALE );
 export const modelViewPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.VIEW_POSITION );
 export const modelViewPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.VIEW_POSITION );
 export const modelWorldMatrixInverse = /*@__PURE__*/ uniform( new Matrix4() ).onObjectUpdate( ( { object }, self ) => self.value.copy( object.matrixWorld ).invert() );
 export const modelWorldMatrixInverse = /*@__PURE__*/ uniform( new Matrix4() ).onObjectUpdate( ( { object }, self ) => self.value.copy( object.matrixWorld ).invert() );
+export const modelViewMatrix = /*@__PURE__*/ cameraViewMatrix.mul( modelWorldMatrix ).toVar( 'modelViewMatrix' );
+
+export const highPrecisionModelViewMatrix = /*@__PURE__*/ ( Fn( ( builder ) => {
+
+	builder.context.isHighPrecisionModelViewMatrix = true;
+
+	return uniform( 'mat4' ).onObjectUpdate( ( { object, camera } ) => {
+
+		return object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
+
+	} );
+
+} ).once() )().toVar( 'highPrecisionModelViewMatrix' );
+
+export const highPrecisionModelNormalMatrix = /*@__PURE__*/ ( Fn( ( builder ) => {
+
+	const isHighPrecisionModelViewMatrix = builder.context.isHighPrecisionModelViewMatrix;
+
+	return uniform( 'mat3' ).onObjectUpdate( ( { object, camera } ) => {
+
+		if ( isHighPrecisionModelViewMatrix !== true ) {
+
+			object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
+
+		}
+
+		return object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
+
+	} );
+
+} ).once() )().toVar( 'highPrecisionModelNormalMatrix' );

+ 3 - 2
src/nodes/accessors/ModelViewProjectionNode.js

@@ -1,8 +1,8 @@
 import TempNode from '../core/TempNode.js';
 import TempNode from '../core/TempNode.js';
 import { cameraProjectionMatrix } from './Camera.js';
 import { cameraProjectionMatrix } from './Camera.js';
-import { modelViewMatrix } from './ModelNode.js';
 import { positionLocal } from './Position.js';
 import { positionLocal } from './Position.js';
 import { nodeProxy, varying } from '../tsl/TSLBase.js';
 import { nodeProxy, varying } from '../tsl/TSLBase.js';
+import { modelViewMatrix } from './ModelNode.js';
 
 
 class ModelViewProjectionNode extends TempNode {
 class ModelViewProjectionNode extends TempNode {
 
 
@@ -29,8 +29,9 @@ class ModelViewProjectionNode extends TempNode {
 		}
 		}
 
 
 		const position = this.positionNode || positionLocal;
 		const position = this.positionNode || positionLocal;
+		const viewMatrix = builder.renderer.nodes.modelViewMatrix || modelViewMatrix;
 
 
-		return cameraProjectionMatrix.mul( modelViewMatrix ).mul( position );
+		return cameraProjectionMatrix.mul( viewMatrix ).mul( position );
 
 
 	}
 	}
 
 

+ 27 - 5
src/nodes/accessors/Normal.js

@@ -1,7 +1,7 @@
 import { attribute } from '../core/AttributeNode.js';
 import { attribute } from '../core/AttributeNode.js';
 import { cameraViewMatrix } from './Camera.js';
 import { cameraViewMatrix } from './Camera.js';
-import { modelNormalMatrix } from './ModelNode.js';
-import { vec3 } from '../tsl/TSLBase.js';
+import { modelWorldMatrix } from './ModelNode.js';
+import { mat3, vec3 } from '../tsl/TSLBase.js';
 import { positionView } from './Position.js';
 import { positionView } from './Position.js';
 import { Fn, varying } from '../tsl/TSLBase.js';
 import { Fn, varying } from '../tsl/TSLBase.js';
 import { faceDirection } from '../display/FrontFacingNode.js';
 import { faceDirection } from '../display/FrontFacingNode.js';
@@ -24,8 +24,6 @@ export const normalLocal = /*@__PURE__*/ ( Fn( ( builder ) => {
 
 
 export const normalFlat = /*@__PURE__*/ positionView.dFdx().cross( positionView.dFdy() ).normalize().toVar( 'normalFlat' );
 export const normalFlat = /*@__PURE__*/ positionView.dFdx().cross( positionView.dFdy() ).normalize().toVar( 'normalFlat' );
 
 
-let normalViewVarying = null;
-
 export const normalView = /*@__PURE__*/ ( Fn( ( builder ) => {
 export const normalView = /*@__PURE__*/ ( Fn( ( builder ) => {
 
 
 	let node;
 	let node;
@@ -36,7 +34,7 @@ export const normalView = /*@__PURE__*/ ( Fn( ( builder ) => {
 
 
 	} else {
 	} else {
 
 
-		node = normalViewVarying || ( normalViewVarying = varying( modelNormalMatrix.mul( normalLocal ).normalize(), 'v_normalView' ).normalize() );
+		node = varying( transformNormalToView( normalLocal ), 'v_normalView' ).normalize();
 
 
 	}
 	}
 
 
@@ -60,3 +58,27 @@ export const transformedClearcoatNormalView = /*@__PURE__*/ ( Fn( ( builder ) =>
 	return builder.context.setupClearcoatNormal();
 	return builder.context.setupClearcoatNormal();
 
 
 }, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' );
 }, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' );
+
+export const transformNormal = /*@__PURE__*/ Fn( ( [ normal, matrix = modelWorldMatrix ] ) => {
+
+	const m = mat3( matrix );
+
+	const transformedNormal = normal.div( vec3( m[ 0 ].dot( m[ 0 ] ), m[ 1 ].dot( m[ 1 ] ), m[ 2 ].dot( m[ 2 ] ) ) );
+
+	return m.mul( transformedNormal ).xyz;
+
+} );
+
+export const transformNormalToView = /*@__PURE__*/ Fn( ( [ normal, matrix = modelWorldMatrix ], builder ) => {
+
+	const modelNormalMatrix = builder.renderer.nodes.modelNormalMatrix;
+
+	if ( modelNormalMatrix !== null ) {
+
+		return modelNormalMatrix.transformDirection( normal );
+
+	}
+
+	return cameraViewMatrix.transformDirection( transformNormal( normal, matrix ) );
+
+} );

+ 4 - 24
src/nodes/accessors/Object3DNode.js

@@ -13,7 +13,7 @@ class Object3DNode extends Node {
 
 
 	}
 	}
 
 
-	constructor( scope = Object3DNode.VIEW_MATRIX, object3d = null ) {
+	constructor( scope, object3d = null ) {
 
 
 		super();
 		super();
 
 
@@ -30,14 +30,10 @@ class Object3DNode extends Node {
 
 
 		const scope = this.scope;
 		const scope = this.scope;
 
 
-		if ( scope === Object3DNode.WORLD_MATRIX || scope === Object3DNode.VIEW_MATRIX ) {
+		if ( scope === Object3DNode.WORLD_MATRIX ) {
 
 
 			return 'mat4';
 			return 'mat4';
 
 
-		} else if ( scope === Object3DNode.NORMAL_MATRIX ) {
-
-			return 'mat3';
-
 		} else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) {
 		} else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) {
 
 
 			return 'vec3';
 			return 'vec3';
@@ -52,15 +48,7 @@ class Object3DNode extends Node {
 		const uniformNode = this._uniformNode;
 		const uniformNode = this._uniformNode;
 		const scope = this.scope;
 		const scope = this.scope;
 
 
-		if ( scope === Object3DNode.VIEW_MATRIX ) {
-
-			uniformNode.value = object.modelViewMatrix;
-
-		} else if ( scope === Object3DNode.NORMAL_MATRIX ) {
-
-			uniformNode.value = object.normalMatrix;
-
-		} else if ( scope === Object3DNode.WORLD_MATRIX ) {
+		if ( scope === Object3DNode.WORLD_MATRIX ) {
 
 
 			uniformNode.value = object.matrixWorld;
 			uniformNode.value = object.matrixWorld;
 
 
@@ -99,14 +87,10 @@ class Object3DNode extends Node {
 
 
 		const scope = this.scope;
 		const scope = this.scope;
 
 
-		if ( scope === Object3DNode.WORLD_MATRIX || scope === Object3DNode.VIEW_MATRIX ) {
+		if ( scope === Object3DNode.WORLD_MATRIX ) {
 
 
 			this._uniformNode.nodeType = 'mat4';
 			this._uniformNode.nodeType = 'mat4';
 
 
-		} else if ( scope === Object3DNode.NORMAL_MATRIX ) {
-
-			this._uniformNode.nodeType = 'mat3';
-
 		} else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) {
 		} else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) {
 
 
 			this._uniformNode.nodeType = 'vec3';
 			this._uniformNode.nodeType = 'vec3';
@@ -135,8 +119,6 @@ class Object3DNode extends Node {
 
 
 }
 }
 
 
-Object3DNode.VIEW_MATRIX = 'viewMatrix';
-Object3DNode.NORMAL_MATRIX = 'normalMatrix';
 Object3DNode.WORLD_MATRIX = 'worldMatrix';
 Object3DNode.WORLD_MATRIX = 'worldMatrix';
 Object3DNode.POSITION = 'position';
 Object3DNode.POSITION = 'position';
 Object3DNode.SCALE = 'scale';
 Object3DNode.SCALE = 'scale';
@@ -146,8 +128,6 @@ Object3DNode.DIRECTION = 'direction';
 export default Object3DNode;
 export default Object3DNode;
 
 
 export const objectDirection = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.DIRECTION );
 export const objectDirection = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.DIRECTION );
-export const objectViewMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.VIEW_MATRIX );
-export const objectNormalMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.NORMAL_MATRIX );
 export const objectWorldMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX );
 export const objectWorldMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX );
 export const objectPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.POSITION );
 export const objectPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.POSITION );
 export const objectScale = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.SCALE );
 export const objectScale = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.SCALE );

+ 66 - 19
src/nodes/accessors/VelocityNode.js

@@ -8,7 +8,7 @@ import { uniform } from '../core/UniformNode.js';
 import { sub } from '../math/OperatorNode.js';
 import { sub } from '../math/OperatorNode.js';
 import { cameraProjectionMatrix } from './Camera.js';
 import { cameraProjectionMatrix } from './Camera.js';
 
 
-const _matrixCache = new WeakMap();
+const _objectData = new WeakMap();
 
 
 class VelocityNode extends TempNode {
 class VelocityNode extends TempNode {
 
 
@@ -25,35 +25,66 @@ class VelocityNode extends TempNode {
 		this.updateType = NodeUpdateType.OBJECT;
 		this.updateType = NodeUpdateType.OBJECT;
 		this.updateAfterType = NodeUpdateType.OBJECT;
 		this.updateAfterType = NodeUpdateType.OBJECT;
 
 
+		this.previousModelWorldMatrix = uniform( new Matrix4() );
 		this.previousProjectionMatrix = uniform( new Matrix4() );
 		this.previousProjectionMatrix = uniform( new Matrix4() );
-		this.previousModelViewMatrix = uniform( new Matrix4() );
+		this.previousCameraViewMatrix = uniform( new Matrix4() );
 
 
 	}
 	}
 
 
-	update( { camera, object } ) {
+	update( { frameId, camera, object } ) {
 
 
 		const previousModelMatrix = getPreviousMatrix( object );
 		const previousModelMatrix = getPreviousMatrix( object );
-		const previousCameraMatrix = getPreviousMatrix( camera );
 
 
-		this.previousModelViewMatrix.value.copy( previousModelMatrix );
-		this.previousProjectionMatrix.value.copy( previousCameraMatrix );
+		this.previousModelWorldMatrix.value.copy( previousModelMatrix );
 
 
-	}
+		//
 
 
-	updateAfter( { camera, object } ) {
+		const cameraData = getData( camera );
 
 
-		const previousModelMatrix = getPreviousMatrix( object );
-		const previousCameraMatrix = getPreviousMatrix( camera );
+		if ( cameraData.frameId !== frameId ) {
+
+			cameraData.frameId = frameId;
+
+			if ( cameraData.previousProjectionMatrix === undefined ) {
+
+				cameraData.previousProjectionMatrix = new Matrix4();
+				cameraData.previousCameraViewMatrix = new Matrix4();
+
+				cameraData.currentProjectionMatrix = new Matrix4();
+				cameraData.currentCameraViewMatrix = new Matrix4();
+
+				cameraData.previousProjectionMatrix.copy( camera.projectionMatrix );
+				cameraData.previousCameraViewMatrix.copy( camera.matrixWorldInverse );
 
 
-		previousModelMatrix.copy( object.modelViewMatrix );
-		previousCameraMatrix.copy( camera.projectionMatrix );
+			} else {
+
+				cameraData.previousProjectionMatrix.copy( cameraData.currentProjectionMatrix );
+				cameraData.previousCameraViewMatrix.copy( cameraData.currentCameraViewMatrix );
+
+			}
+
+			cameraData.currentProjectionMatrix.copy( camera.projectionMatrix );
+			cameraData.currentCameraViewMatrix.copy( camera.matrixWorldInverse );
+
+			this.previousProjectionMatrix.value.copy( cameraData.previousProjectionMatrix );
+			this.previousCameraViewMatrix.value.copy( cameraData.previousCameraViewMatrix );
+
+		}
+
+	}
+
+	updateAfter( { object } ) {
+
+		getPreviousMatrix( object ).copy( object.matrixWorld );
 
 
 	}
 	}
 
 
 	setup( /*builder*/ ) {
 	setup( /*builder*/ ) {
 
 
+		const previousModelViewMatrix = this.previousCameraViewMatrix.mul( this.previousModelWorldMatrix );
+
 		const clipPositionCurrent = cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal );
 		const clipPositionCurrent = cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal );
-		const clipPositionPrevious = this.previousProjectionMatrix.mul( this.previousModelViewMatrix ).mul( positionPrevious );
+		const clipPositionPrevious = this.previousProjectionMatrix.mul( previousModelViewMatrix ).mul( positionPrevious );
 
 
 		const ndcPositionCurrent = clipPositionCurrent.xy.div( clipPositionCurrent.w );
 		const ndcPositionCurrent = clipPositionCurrent.xy.div( clipPositionCurrent.w );
 		const ndcPositionPrevious = clipPositionPrevious.xy.div( clipPositionPrevious.w );
 		const ndcPositionPrevious = clipPositionPrevious.xy.div( clipPositionPrevious.w );
@@ -66,18 +97,34 @@ class VelocityNode extends TempNode {
 
 
 }
 }
 
 
-function getPreviousMatrix( object ) {
+function getData( object ) {
+
+	let objectData = _objectData.get( object );
+
+	if ( objectData === undefined ) {
+
+		objectData = {};
+		_objectData.set( object, objectData );
+
+	}
+
+	return objectData;
+
+}
+
+function getPreviousMatrix( object, index = 0 ) {
+
+	const objectData = getData( object );
 
 
-	let previousMatrix = _matrixCache.get( object );
+	let matrix = objectData[ index ];
 
 
-	if ( previousMatrix === undefined ) {
+	if ( matrix === undefined ) {
 
 
-		previousMatrix = new Matrix4();
-		_matrixCache.set( object, previousMatrix );
+		objectData[ index ] = matrix = new Matrix4();
 
 
 	}
 	}
 
 
-	return previousMatrix;
+	return matrix;
 
 
 }
 }
 
 

+ 2 - 3
src/nodes/display/NormalMapNode.js

@@ -1,8 +1,7 @@
 import TempNode from '../core/TempNode.js';
 import TempNode from '../core/TempNode.js';
 import { add } from '../math/OperatorNode.js';
 import { add } from '../math/OperatorNode.js';
 
 
-import { modelNormalMatrix } from '../accessors/ModelNode.js';
-import { normalView } from '../accessors/Normal.js';
+import { normalView, transformNormalToView } from '../accessors/Normal.js';
 import { positionView } from '../accessors/Position.js';
 import { positionView } from '../accessors/Position.js';
 import { TBNViewMatrix } from '../accessors/AccessorsUtils.js';
 import { TBNViewMatrix } from '../accessors/AccessorsUtils.js';
 import { uv } from '../accessors/UV.js';
 import { uv } from '../accessors/UV.js';
@@ -73,7 +72,7 @@ class NormalMapNode extends TempNode {
 
 
 		if ( normalMapType === ObjectSpaceNormalMap ) {
 		if ( normalMapType === ObjectSpaceNormalMap ) {
 
 
-			outputNode = modelNormalMatrix.mul( normalMap ).normalize();
+			outputNode = transformNormalToView( normalMap );
 
 
 		} else if ( normalMapType === TangentSpaceNormalMap ) {
 		} else if ( normalMapType === TangentSpaceNormalMap ) {
 
 

+ 3 - 15
src/renderers/common/Renderer.js

@@ -80,7 +80,9 @@ class Renderer {
 		this.info = new Info();
 		this.info = new Info();
 
 
 		this.nodes = {
 		this.nodes = {
-			library: new NodeLibrary()
+			library: new NodeLibrary(),
+			modelViewMatrix: null,
+			modelNormalMatrix: null
 		};
 		};
 
 
 		// internals
 		// internals
@@ -458,11 +460,6 @@ class Renderer {
 
 
 				this._nodes.updateBefore( renderObject );
 				this._nodes.updateBefore( renderObject );
 
 
-				//
-
-				renderObject.object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, renderObject.object.matrixWorld );
-				renderObject.object.normalMatrix.getNormalMatrix( renderObject.object.modelViewMatrix );
-
 				this._nodes.updateForRender( renderObject );
 				this._nodes.updateForRender( renderObject );
 				this._bindings.updateForRender( renderObject );
 				this._bindings.updateForRender( renderObject );
 
 
@@ -1577,13 +1574,6 @@ class Renderer {
 
 
 		this._nodes.updateBefore( renderObject );
 		this._nodes.updateBefore( renderObject );
 
 
-		//
-
-		object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
-		object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
-
-		//
-
 		this._nodes.updateForRender( renderObject );
 		this._nodes.updateForRender( renderObject );
 		this._geometries.updateForRender( renderObject );
 		this._geometries.updateForRender( renderObject );
 		this._bindings.updateForRender( renderObject );
 		this._bindings.updateForRender( renderObject );
@@ -1613,8 +1603,6 @@ class Renderer {
 
 
 		this._nodes.updateBefore( renderObject );
 		this._nodes.updateBefore( renderObject );
 
 
-		//
-
 		this._nodes.updateForRender( renderObject );
 		this._nodes.updateForRender( renderObject );
 		this._geometries.updateForRender( renderObject );
 		this._geometries.updateForRender( renderObject );
 		this._bindings.updateForRender( renderObject );
 		this._bindings.updateForRender( renderObject );

粤ICP备19079148号