From 26de4f2e78bb43a5d758c5de6138e036310a0835 Mon Sep 17 00:00:00 2001 From: Dusan Bosnjak Date: Fri, 24 Jul 2026 09:21:58 +0200 Subject: [PATCH 1/3] fix typos (#34105) --- examples/jsm/geometries/BoxLineGeometry.js | 2 +- examples/jsm/geometries/ParametricGeometry.js | 2 +- examples/jsm/geometries/RoundedBoxGeometry.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/jsm/geometries/BoxLineGeometry.js b/examples/jsm/geometries/BoxLineGeometry.js index 9ee5476bd33c49..c344c4ee765ca4 100644 --- a/examples/jsm/geometries/BoxLineGeometry.js +++ b/examples/jsm/geometries/BoxLineGeometry.js @@ -7,7 +7,7 @@ import { * A special type of box geometry intended for {@link LineSegments}. * * ```js - * const geometry = new THREE.BoxLineGeometry(); + * const geometry = new BoxLineGeometry(); * const material = new THREE.LineBasicMaterial( { color: 0x00ff00 } ); * const lines = new THREE.LineSegments( geometry, material ); * scene.add( lines ); diff --git a/examples/jsm/geometries/ParametricGeometry.js b/examples/jsm/geometries/ParametricGeometry.js index b2f0d59728d586..5aedebc93bfd4c 100644 --- a/examples/jsm/geometries/ParametricGeometry.js +++ b/examples/jsm/geometries/ParametricGeometry.js @@ -10,7 +10,7 @@ import { * Reference: [Mesh Generation with Python](https://prideout.net/blog/old/blog/index.html@p=44.html) * * ```js - * const geometry = new THREE.ParametricGeometry( klein, 25, 25 ); + * const geometry = new ParametricGeometry( klein, 25, 25 ); * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); * const klein = new THREE.Mesh( geometry, material ); * scene.add( klein ); diff --git a/examples/jsm/geometries/RoundedBoxGeometry.js b/examples/jsm/geometries/RoundedBoxGeometry.js index 25cbf6154fc1f9..038370c48e7cbc 100644 --- a/examples/jsm/geometries/RoundedBoxGeometry.js +++ b/examples/jsm/geometries/RoundedBoxGeometry.js @@ -42,7 +42,7 @@ function getUv( faceDirVector, normal, uvAxis, projectionAxis, radius, sideLengt * A special type of box geometry with rounded corners and edges. * * ```js - * const geometry = new THREE.RoundedBoxGeometry(); + * const geometry = new RoundedBoxGeometry(); * const material = new THREE.MeshStandardMaterial( { color: 0x00ff00 } ); * const cube = new THREE.Mesh( geometry, material ); * scene.add( cube ); From fbaeb680bba0af03b87f85d4dc4b0a6bf2a3eddc Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 24 Jul 2026 09:23:22 +0200 Subject: [PATCH 2/3] TSL: Add `OnAfterObjectUpdate()`. (#34101) --- src/Three.TSL.js | 1 + src/nodes/accessors/Batch.js | 4 ++-- src/nodes/accessors/Instance.js | 4 ++-- src/nodes/utils/EventNode.js | 21 +++++++++++++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/Three.TSL.js b/src/Three.TSL.js index 76a0c83656e7d4..310e7a8ed66c36 100644 --- a/src/Three.TSL.js +++ b/src/Three.TSL.js @@ -411,6 +411,7 @@ export const objectRadius = TSL.objectRadius; export const objectScale = TSL.objectScale; export const objectViewPosition = TSL.objectViewPosition; export const objectWorldMatrix = TSL.objectWorldMatrix; +export const OnAfterObjectUpdate = TSL.OnAfterObjectUpdate; export const OnBeforeObjectUpdate = TSL.OnBeforeObjectUpdate; export const OnBeforeMaterialUpdate = TSL.OnBeforeMaterialUpdate; export const OnBeforeRenderPipeline = TSL.OnBeforeRenderPipeline; diff --git a/src/nodes/accessors/Batch.js b/src/nodes/accessors/Batch.js index 78dd344134d49f..6cfafc095c755a 100644 --- a/src/nodes/accessors/Batch.js +++ b/src/nodes/accessors/Batch.js @@ -7,7 +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 { OnObjectUpdate } from '../utils/EventNode.js'; +import { OnAfterObjectUpdate } from '../utils/EventNode.js'; import { DataTexture } from '../../textures/DataTexture.js'; const _previousBatchingMatrices = /*@__PURE__*/ new WeakMap(); @@ -140,7 +140,7 @@ export const batch = /*@__PURE__*/ Fn( ( [ batchMesh ], builder ) => { if ( builder.needsPreviousData() ) { - OnObjectUpdate( ( { object } ) => { + OnAfterObjectUpdate( ( { object } ) => { const previousBatchData = _previousBatchingMatrices.get( object ); diff --git a/src/nodes/accessors/Instance.js b/src/nodes/accessors/Instance.js index f5755340b66ce1..7c991dfbfaf81f 100644 --- a/src/nodes/accessors/Instance.js +++ b/src/nodes/accessors/Instance.js @@ -1,6 +1,6 @@ import { vec3, mat4, Fn } from '../tsl/TSLBase.js'; -import { OnFrameUpdate, OnObjectUpdate } from '../utils/EventNode.js'; +import { OnAfterObjectUpdate, OnFrameUpdate } from '../utils/EventNode.js'; import { normalLocal, transformNormal } from './Normal.js'; import { positionLocal, positionPrevious } from './Position.js'; import { varyingProperty } from '../core/PropertyNode.js'; @@ -210,7 +210,7 @@ export const instance = /*@__PURE__*/ Fn( ( [ matrices, colors = null ], builder const instancedMesh = builder.object; - OnObjectUpdate( ( { object } ) => { + OnAfterObjectUpdate( ( { object } ) => { const previousInstanceData = _previousInstanceMatrices.get( object ); diff --git a/src/nodes/utils/EventNode.js b/src/nodes/utils/EventNode.js index 4294d509809287..e0bc26232a8bd6 100644 --- a/src/nodes/utils/EventNode.js +++ b/src/nodes/utils/EventNode.js @@ -39,6 +39,10 @@ class EventNode extends Node { this.updateType = NodeUpdateType.FRAME; + } else if ( eventType === EventNode.AFTER_OBJECT ) { + + this.updateAfterType = NodeUpdateType.OBJECT; + } else if ( eventType === EventNode.BEFORE_OBJECT ) { this.updateBeforeType = NodeUpdateType.OBJECT; @@ -97,11 +101,18 @@ class EventNode extends Node { } + updateAfter( frame ) { + + this.callback( frame ); + + } + } EventNode.OBJECT = 'object'; EventNode.MATERIAL = 'material'; EventNode.FRAME = 'frame'; +EventNode.AFTER_OBJECT = 'afterObject'; EventNode.BEFORE_OBJECT = 'beforeObject'; EventNode.BEFORE_MATERIAL = 'beforeMaterial'; EventNode.BEFORE_FRAME = 'beforeFrame'; @@ -149,6 +160,16 @@ export const OnMaterialUpdate = ( callback ) => createEvent( EventNode.MATERIAL, */ export const OnFrameUpdate = ( callback ) => createEvent( EventNode.FRAME, callback ); +/** + * Creates an event that triggers a function every time an object (Mesh|Sprite) has been rendered. + * + * The event will be bound to the declared TSL function `Fn()`; it must be declared within a `Fn()` or the JS function call must be inherited from one. + * + * @param {Function} callback - The callback function. + * @returns {EventNode} + */ +export const OnAfterObjectUpdate = ( callback ) => createEvent( EventNode.AFTER_OBJECT, callback ); + /** * Creates an event that triggers a function before an object (Mesh|Sprite) is updated. * From 27e70ddf91e95c40d03bca7b2bac5a212e4c4151 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 24 Jul 2026 10:19:44 +0200 Subject: [PATCH 3/3] TSL: Fix update of previous instance matrix data. (#34107) --- src/nodes/accessors/Instance.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/nodes/accessors/Instance.js b/src/nodes/accessors/Instance.js index 7c991dfbfaf81f..80a14cbb3c76bb 100644 --- a/src/nodes/accessors/Instance.js +++ b/src/nodes/accessors/Instance.js @@ -212,9 +212,16 @@ export const instance = /*@__PURE__*/ Fn( ( [ matrices, colors = null ], builder OnAfterObjectUpdate( ( { object } ) => { - const previousInstanceData = _previousInstanceMatrices.get( object ); + const { previousInstanceMatrix } = _previousInstanceMatrices.get( object ); - previousInstanceData.previousInstanceMatrix.array.set( matrices.array ); + previousInstanceMatrix.array.set( matrices.array ); + previousInstanceMatrix.version = matrices.version; + + // handle interleaved path + + const previousInterleavedMatrix = _matrixBuffers.get( previousInstanceMatrix ); + + if ( previousInterleavedMatrix !== undefined ) previousInterleavedMatrix.version = matrices.version; } );