diff --git a/src/materials/nodes/NodeMaterial.js b/src/materials/nodes/NodeMaterial.js index 361a15d25479ce..dde60aa7a7f7b5 100644 --- a/src/materials/nodes/NodeMaterial.js +++ b/src/materials/nodes/NodeMaterial.js @@ -265,6 +265,17 @@ class NodeMaterial extends Material { */ this.positionNode = null; + /** + * Allows to overwrite {@link positionLocal} immediately after it has + * been transformed by the instance matrix in the vertex shader. + * Note: this node property only has an effect when used with + * an {@link InstancedMesh} or a {@link BatchedMesh}. + * + * @type {?Node} + * @default null + */ + this.instancePositionNode = null; + /** * This node property is intended for logic which modifies geometry data once or per animation step. * Apps usually place such logic randomly in initialization routines or in the animation loop. diff --git a/src/nodes/accessors/BatchNode.js b/src/nodes/accessors/BatchNode.js index 9138e54d3b7089..097529ee74f7d3 100644 --- a/src/nodes/accessors/BatchNode.js +++ b/src/nodes/accessors/BatchNode.js @@ -7,6 +7,7 @@ import { textureSize } from './TextureSizeNode.js'; import { tangentLocal } from './Tangent.js'; import { instanceIndex, drawIndex } from '../core/IndexNode.js'; import { varyingProperty } from '../core/PropertyNode.js'; +import NodeMaterial from '../../materials/nodes/NodeMaterial.js'; /** * This node implements the vertex shader logic which is required @@ -134,6 +135,12 @@ class BatchNode extends Node { positionLocal.assign( batchingMatrix.mul( positionLocal ) ); + if ( builder.material instanceof NodeMaterial && builder.material.instancePositionNode != null ) { + + positionLocal.assign( builder.material.instancePositionNode ); + + } + const transformedNormal = normalLocal.div( vec3( bm[ 0 ].dot( bm[ 0 ] ), bm[ 1 ].dot( bm[ 1 ] ), bm[ 2 ].dot( bm[ 2 ] ) ) ); const batchingNormal = bm.mul( transformedNormal ).xyz; diff --git a/src/nodes/accessors/InstanceNode.js b/src/nodes/accessors/InstanceNode.js index 53e81015bad740..e349617e7edc9c 100644 --- a/src/nodes/accessors/InstanceNode.js +++ b/src/nodes/accessors/InstanceNode.js @@ -12,6 +12,7 @@ import { instanceIndex } from '../core/IndexNode.js'; import { InstancedInterleavedBuffer } from '../../core/InstancedInterleavedBuffer.js'; import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js'; import { DynamicDrawUsage } from '../../constants.js'; +import NodeMaterial from '../../materials/nodes/NodeMaterial.js'; /** * This node implements the vertex shader logic which is required @@ -187,6 +188,12 @@ class InstanceNode extends Node { const instancePosition = instanceMatrixNode.mul( positionLocal ).xyz; positionLocal.assign( instancePosition ); + if ( builder.material instanceof NodeMaterial && builder.material.instancePositionNode != null ) { + + positionLocal.assign( builder.material.instancePositionNode ); + + } + if ( builder.needsPreviousData() ) { positionPrevious.assign( this.getPreviousInstancedPosition( builder ) );