From cdf24d73eaad50c36ff9578f96e8c3c83fc5e118 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 10 Aug 2026 09:30:56 +0200 Subject: [PATCH 1/3] Examples: Change preset in backdrop area. (#34195) --- examples/screenshots/webgpu_backdrop_area.jpg | Bin 13172 -> 16018 bytes examples/webgpu_backdrop_area.html | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/screenshots/webgpu_backdrop_area.jpg b/examples/screenshots/webgpu_backdrop_area.jpg index b02962b19a48d1c80ff134cef6a00ef7c1d95e25..402a809ebce56588de262aacc3a910311323df9d 100644 GIT binary patch literal 16018 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 Date: Mon, 10 Aug 2026 10:41:54 +0200 Subject: [PATCH 2/3] Skinning: Support bone counts exceeding UBO limit. (#34200) --- src/nodes/accessors/Skinning.js | 130 +++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 10 deletions(-) diff --git a/src/nodes/accessors/Skinning.js b/src/nodes/accessors/Skinning.js index 5b349a954d8e34..437e0c02c98c38 100644 --- a/src/nodes/accessors/Skinning.js +++ b/src/nodes/accessors/Skinning.js @@ -1,5 +1,5 @@ -import { Fn, add, uniform, mat3 } from '../tsl/TSLBase.js'; +import { Fn, add, uniform, int, ivec2, mat3, mat4 } from '../tsl/TSLBase.js'; import { attribute } from '../core/AttributeNode.js'; import { OnObjectUpdate } from '../utils/EventNode.js'; import { normalLocal } from './Normal.js'; @@ -8,13 +8,87 @@ import { tangentLocal } from './Tangent.js'; import { reference, referenceBuffer } from './ReferenceNode.js'; import { buffer } from './BufferNode.js'; import { storage } from './StorageBufferNode.js'; +import { texture } from './TextureNode.js'; +import { textureSize } from './TextureSizeNode.js'; import { instanceIndex } from '../core/IndexNode.js'; import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js'; +import { DataTexture } from '../../textures/DataTexture.js'; +import { RGBAFormat, FloatType } from '../../constants.js'; const _skeletonsUpdated = /*@__PURE__*/ new WeakMap(); const _previousBoneMatricesData = /*@__PURE__*/ new WeakMap(); +/** + * Creates an accessor for bone matrices stored in a bone texture. + * + * @param {TextureNode} boneTexture - The bone texture node. + * @returns {Object} An accessor with the same `element()` interface as a buffer node. + */ +function getBoneTextureMatrices( boneTexture ) { + + return { + element: ( i ) => { + + const size = int( textureSize( boneTexture ).x ).toConst(); + const j = int( i ).mul( 4 ).toConst(); + const y = j.div( size ).toConst(); + const x = j.sub( y.mul( size ) ).toConst(); + + return mat4( + boneTexture.load( ivec2( x, y ) ), + boneTexture.load( ivec2( x.add( 1 ), y ) ), + boneTexture.load( ivec2( x.add( 2 ), y ) ), + boneTexture.load( ivec2( x.add( 3 ), y ) ) + ); + + } + }; + +} + +/** + * Creates the bone matrices node. Skeletons that fit within the uniform buffer limit + * use a uniform buffer, larger skeletons fall back to a bone texture. + * + * @param {NodeBuilder} builder - The current node builder. + * @param {Skeleton} skeleton - The skeleton. + * @returns {Object} The bone matrices node. + */ +function getBoneMatricesNode( builder, skeleton ) { + + let node; + + const uniformBufferSize = skeleton.bones.length * 16 * 4; + + if ( uniformBufferSize <= builder.getUniformBufferLimit() ) { + + node = referenceBuffer( 'skeleton.boneMatrices', 'mat4', skeleton.bones.length ); + + } else { + + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); + + const boneTexture = texture( skeleton.boneTexture ); + + OnObjectUpdate( ( { object } ) => { + + const skeleton = object.skeleton; + + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); + + boneTexture.value = skeleton.boneTexture; + + } ); + + node = getBoneTextureMatrices( boneTexture ); + + } + + return node; + +} + /** * Computes the skinned position by applying bone matrices based on weights. * @@ -91,6 +165,7 @@ function getSkinnedNormalAndTangent( boneMatrices, normal, tangent, bindMatrix, * Retrieves or initializes the previous frame skinned position node for motion vectors. * Uses a WeakMap to cache previous frame bone matrix arrays and their TSL buffer nodes. * + * @param {NodeBuilder} builder - The current node builder. * @param {SkinnedMesh} skinnedMesh - The skinned mesh. * @param {Node} bindMatrixNode - The bind matrix node. * @param {Node} bindMatrixInverseNode - The inverse bind matrix node. @@ -98,7 +173,7 @@ function getSkinnedNormalAndTangent( boneMatrices, normal, tangent, bindMatrix, * @param {Node} skinWeightNode - The skin weight attribute. * @returns {Node} The skinned position from the previous frame. */ -function getPreviousSkinnedPosition( skinnedMesh, bindMatrixNode, bindMatrixInverseNode, skinIndexNode, skinWeightNode ) { +function getPreviousSkinnedPosition( builder, skinnedMesh, bindMatrixNode, bindMatrixInverseNode, skinIndexNode, skinWeightNode ) { const skeleton = skinnedMesh.skeleton; @@ -108,12 +183,35 @@ function getPreviousSkinnedPosition( skinnedMesh, bindMatrixNode, bindMatrixInve skeleton.update(); - const previousBoneMatrices = new Float32Array( skeleton.boneMatrices ); + const uniformBufferSize = skeleton.bones.length * 16 * 4; + + if ( uniformBufferSize <= builder.getUniformBufferLimit() ) { + + const previousBoneMatrices = new Float32Array( skeleton.boneMatrices ); + + data = { + previousBoneMatrices, + previousBoneTexture: null, + node: buffer( previousBoneMatrices, 'mat4', skeleton.bones.length ) + }; - data = { - previousBoneMatrices, - node: buffer( previousBoneMatrices, 'mat4', skeleton.bones.length ) - }; + } else { + + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); + + const { width, height } = skeleton.boneTexture.image; + + const previousBoneMatrices = new Float32Array( skeleton.boneMatrices ); + const previousBoneTexture = new DataTexture( previousBoneMatrices, width, height, RGBAFormat, FloatType ); + previousBoneTexture.needsUpdate = true; + + data = { + previousBoneMatrices, + previousBoneTexture, + node: getBoneTextureMatrices( texture( previousBoneTexture ) ) + }; + + } _previousBoneMatricesData.set( skeleton, data ); @@ -137,7 +235,7 @@ export const skinning = /*@__PURE__*/ Fn( ( [ skinnedMesh ], builder ) => { const skinWeightNode = attribute( 'skinWeight', 'vec4' ); const bindMatrixNode = reference( 'bindMatrix', 'mat4' ); const bindMatrixInverseNode = reference( 'bindMatrixInverse', 'mat4' ); - const boneMatricesNode = referenceBuffer( 'skeleton.boneMatrices', 'mat4', skinnedMesh.skeleton.bones.length ); + const boneMatricesNode = getBoneMatricesNode( builder, skinnedMesh.skeleton ); OnObjectUpdate( ( { object, frameId } ) => { @@ -153,6 +251,12 @@ export const skinning = /*@__PURE__*/ Fn( ( [ skinnedMesh ], builder ) => { skeletonData.previousBoneMatrices.set( skeleton.boneMatrices ); + if ( skeletonData.previousBoneTexture !== null ) { + + skeletonData.previousBoneTexture.needsUpdate = true; + + } + } skeleton.update(); @@ -163,7 +267,7 @@ export const skinning = /*@__PURE__*/ Fn( ( [ skinnedMesh ], builder ) => { if ( builder.needsPreviousData() ) { - const previousSkinnedPosition = getPreviousSkinnedPosition( skinnedMesh, bindMatrixNode, bindMatrixInverseNode, skinIndexNode, skinWeightNode ); + const previousSkinnedPosition = getPreviousSkinnedPosition( builder, skinnedMesh, bindMatrixNode, bindMatrixInverseNode, skinIndexNode, skinWeightNode ); positionPrevious.assign( previousSkinnedPosition ); @@ -220,6 +324,12 @@ export const computeSkinning = /*@__PURE__*/ Fn( ( [ skinnedMesh, toPosition = n state.previousBoneMatrices.set( skeleton.boneMatrices ); + if ( state.previousBoneTexture !== null ) { + + state.previousBoneTexture.needsUpdate = true; + + } + } skeleton.update(); @@ -230,7 +340,7 @@ export const computeSkinning = /*@__PURE__*/ Fn( ( [ skinnedMesh, toPosition = n if ( builder.needsPreviousData() ) { - const previousSkinnedPosition = getPreviousSkinnedPosition( skinnedMesh, bindMatrixNode, bindMatrixInverseNode, skinIndexNode, skinWeightNode ); + const previousSkinnedPosition = getPreviousSkinnedPosition( builder, skinnedMesh, bindMatrixNode, bindMatrixInverseNode, skinIndexNode, skinWeightNode ); positionPrevious.assign( previousSkinnedPosition ); From 2af274f064a41209718648e640810037f86dd07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=94=92=E9=92=B1=E9=80=A0=E6=A0=B8=E5=BC=B9?= <42568170+Virtycle@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:55:35 +0800 Subject: [PATCH 3/3] PCDLoader: Fix regex to remove comments. (#34199) Co-authored-by: Michael Herzog --- examples/jsm/loaders/PCDLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/jsm/loaders/PCDLoader.js b/examples/jsm/loaders/PCDLoader.js index cd8a7a93344cac..ef7ca1cc7cfdaf 100644 --- a/examples/jsm/loaders/PCDLoader.js +++ b/examples/jsm/loaders/PCDLoader.js @@ -269,7 +269,7 @@ class PCDLoader extends Loader { // remove comments - PCDheader.str = PCDheader.str.replace( /#.*/gi, '' ); + PCDheader.str = PCDheader.str.replace( /^#.*/gm, '' ); // parse