diff --git a/src/nodes/accessors/Morph.js b/src/nodes/accessors/Morph.js index 361dd79b2db7b5..e9b9319658097b 100644 --- a/src/nodes/accessors/Morph.js +++ b/src/nodes/accessors/Morph.js @@ -1,6 +1,5 @@ import { float, Fn, ivec2, int, If, uniform } from '../tsl/TSLBase.js'; -import { reference } from './ReferenceNode.js'; import { Loop } from '../utils/LoopNode.js'; import { OnObjectUpdate } from '../utils/EventNode.js'; import { textureLoad } from './TextureNode.js'; @@ -12,10 +11,11 @@ import { DataArrayTexture } from '../../textures/DataArrayTexture.js'; import { Vector2 } from '../../math/Vector2.js'; import { Vector4 } from '../../math/Vector4.js'; import { FloatType } from '../../constants.js'; +import { uniformArray } from './UniformArrayNode.js'; const _morphTextures = /*@__PURE__*/ new WeakMap(); const _morphVec4 = /*@__PURE__*/ new Vector4(); -const _morphBaseInfluences = /*@__PURE__*/ new WeakMap(); +const _morphInfluencesData = /*@__PURE__*/ new WeakMap(); /** * TSL function that retrieves and scales the morphed attribute (position or normal) texel value. @@ -174,13 +174,6 @@ function getEntry( geometry ) { } -/** - * TSL object representing a reference to the mesh's morphTargetInfluences array. - * - * @type {ReferenceNode} - */ -export const morphTargetInfluences = /*@__PURE__*/ reference( 'morphTargetInfluences', 'float' ); - /** * TSL function representing the vertex shader morph targets blend setup. * Dynamically computes morph targets weights and updates positionLocal and normalLocal in-place. @@ -201,33 +194,30 @@ export const morphReference = /*@__PURE__*/ Fn( ( [ mesh ] ) => { if ( morphTargetsCount === 0 ) return; - let morphBaseInfluence = _morphBaseInfluences.get( mesh ); - - if ( ! morphBaseInfluence ) { - - morphBaseInfluence = uniform( 1 ); - _morphBaseInfluences.set( mesh, morphBaseInfluence ); - - OnObjectUpdate( ( { object } ) => { + // Init - if ( object.geometry.morphTargetsRelative ) { + let morphInfluenceData = _morphInfluencesData.get( mesh ); - morphBaseInfluence.value = 1; + if ( morphInfluenceData === undefined || morphInfluenceData.count !== morphTargetsCount ) { - } else { + morphInfluenceData = { + base: uniform( 1 ), + influences: mesh.morphTargetInfluences ? uniformArray( mesh.morphTargetInfluences, 'float' ) : null, + count: morphTargetsCount + }; - morphBaseInfluence.value = 1 - object.morphTargetInfluences.reduce( ( a, b ) => a + b, 0 ); + _morphInfluencesData.set( mesh, morphInfluenceData ); - } + } - } ); + const { base, influences } = morphInfluenceData; - } + // Shader const { texture: bufferMap, stride, size } = getEntry( geometry ); - if ( hasMorphPosition === true ) positionLocal.mulAssign( morphBaseInfluence ); - if ( hasMorphNormals === true ) normalLocal.mulAssign( morphBaseInfluence ); + if ( hasMorphPosition === true ) positionLocal.mulAssign( base ); + if ( hasMorphNormals === true ) normalLocal.mulAssign( base ); const width = int( size.width ); @@ -241,7 +231,7 @@ export const morphReference = /*@__PURE__*/ Fn( ( [ mesh ] ) => { } else { - influence.assign( morphTargetInfluences.element( i ).toVar() ); + influence.assign( influences.element( i ).toVar() ); } @@ -277,6 +267,31 @@ export const morphReference = /*@__PURE__*/ Fn( ( [ mesh ] ) => { } ); + // Update + + OnObjectUpdate( ( { object } ) => { + + const { base, influences } = morphInfluenceData; + + if ( object.geometry.morphTargetsRelative ) { + + base.value = 1; + + } else { + + base.value = 1 - object.morphTargetInfluences.reduce( ( a, b ) => a + b, 0 ); + + } + + if ( influences ) { + + influences.array = object.morphTargetInfluences; + influences.update(); + + } + + } ); + }, 'void' ); diff --git a/src/nodes/accessors/ReferenceNode.js b/src/nodes/accessors/ReferenceNode.js index 583d6bd361265f..856d39f84d0771 100644 --- a/src/nodes/accessors/ReferenceNode.js +++ b/src/nodes/accessors/ReferenceNode.js @@ -262,6 +262,7 @@ class ReferenceNode extends Node { } else if ( Array.isArray( this.getValueFromReference() ) ) { node = uniformArray( null, uniformType ); + node.updateType = NodeUpdateType.OBJECT; } else if ( uniformType === 'texture' ) { diff --git a/src/renderers/common/RenderObject.js b/src/renderers/common/RenderObject.js index 1503ff56e96c92..5bc668530cc21d 100644 --- a/src/renderers/common/RenderObject.js +++ b/src/renderers/common/RenderObject.js @@ -809,7 +809,7 @@ class RenderObject { } - if ( object.isInstancedMesh || object.count > 1 || Array.isArray( object.morphTargetInfluences ) ) { + if ( object.isInstancedMesh || object.count > 1 ) { // TODO: https://github.com/mrdoob/three.js/pull/29066#issuecomment-2269400850