From c2b9e237663af69fbae09a9da66bb605b60f517b Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Fri, 23 Jan 2026 13:44:26 +0100 Subject: [PATCH 1/3] ShadowFilterNode: Fix TSL warning in `VSMShadowFilter`. (#32836) --- src/nodes/lighting/ShadowFilterNode.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/nodes/lighting/ShadowFilterNode.js b/src/nodes/lighting/ShadowFilterNode.js index 4773cab1ef58af..7b57dd340267bf 100644 --- a/src/nodes/lighting/ShadowFilterNode.js +++ b/src/nodes/lighting/ShadowFilterNode.js @@ -190,23 +190,23 @@ export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord, const hardShadow = step( shadowCoord.z, mean ); - // Early return if fully lit - If( hardShadow.equal( 1.0 ), () => { + const output = float( 1 ).toVar(); // default, fully lit - return float( 1.0 ); + If( hardShadow.notEqual( 1.0 ), () => { - } ); + // Distance from mean + const d = shadowCoord.z.sub( mean ); - // Distance from mean - const d = shadowCoord.z.sub( mean ); + // Chebyshev's inequality for upper bound on probability + let p_max = variance.div( variance.add( d.mul( d ) ) ); - // Chebyshev's inequality for upper bound on probability - let p_max = variance.div( variance.add( d.mul( d ) ) ); + // Reduce light bleeding by remapping [amount, 1] to [0, 1] + p_max = clamp( sub( p_max, 0.3 ).div( 0.65 ) ); - // Reduce light bleeding by remapping [amount, 1] to [0, 1] - p_max = clamp( sub( p_max, 0.3 ).div( 0.65 ) ); + output.assign( max( hardShadow, p_max ) ); - return max( hardShadow, p_max ); + } ); + return output; } ); From 3ce02ccc409f8645b7acc4781f95de8e45f3c49a Mon Sep 17 00:00:00 2001 From: sean tai <105983513+seantai@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:38:21 +0100 Subject: [PATCH 2/3] Inspector: Add "Copy All" button to Console tab. (#32825) Co-authored-by: sunag --- examples/jsm/inspector/tabs/Console.js | 44 +++++++++++++++++++++++--- examples/jsm/inspector/ui/Style.js | 26 ++++++++++++++- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/examples/jsm/inspector/tabs/Console.js b/examples/jsm/inspector/tabs/Console.js index d28825080caec1..2668c114bfc389 100644 --- a/examples/jsm/inspector/tabs/Console.js +++ b/examples/jsm/inspector/tabs/Console.js @@ -33,8 +33,14 @@ class Console extends Tab { } ); - const filtersGroup = document.createElement( 'div' ); - filtersGroup.className = 'console-filters-group'; + const copyButton = document.createElement( 'button' ); + copyButton.className = 'console-copy-button'; + copyButton.title = 'Copy all'; + copyButton.innerHTML = ''; + copyButton.addEventListener( 'click', () => this.copyAll( copyButton ) ); + + const buttonsGroup = document.createElement( 'div' ); + buttonsGroup.className = 'console-buttons-group'; Object.keys( this.filters ).forEach( type => { @@ -53,11 +59,11 @@ class Console extends Tab { label.appendChild( checkbox ); label.appendChild( checkmark ); label.append( type.charAt( 0 ).toUpperCase() + type.slice( 1 ) ); - filtersGroup.appendChild( label ); + buttonsGroup.appendChild( label ); } ); - filtersGroup.addEventListener( 'change', ( e ) => { + buttonsGroup.addEventListener( 'change', ( e ) => { const type = e.target.dataset.type; if ( type in this.filters ) { @@ -69,8 +75,10 @@ class Console extends Tab { } ); + buttonsGroup.appendChild( copyButton ); + header.appendChild( filterInput ); - header.appendChild( filtersGroup ); + header.appendChild( buttonsGroup ); this.content.appendChild( header ); } @@ -92,6 +100,32 @@ class Console extends Tab { } + copyAll( button ) { + + const win = this.logContainer.ownerDocument.defaultView; + const selection = win.getSelection(); + const selectedText = selection.toString(); + const textInConsole = selectedText && this.logContainer.contains( selection.anchorNode ); + + let text; + if ( textInConsole ) { + + text = selectedText; + + } else { + + const messages = this.logContainer.querySelectorAll( '.log-message:not(.hidden)' ); + text = Array.from( messages ).map( msg => msg.dataset.rawText ).join( '\n' ); + + } + + navigator.clipboard.writeText( text ); + + button.classList.add( 'copied' ); + setTimeout( () => button.classList.remove( 'copied' ), 350 ); + + } + _getIcon( type, subType ) { let icon; diff --git a/examples/jsm/inspector/ui/Style.js b/examples/jsm/inspector/ui/Style.js index 7efa9753ac49af..ebb66efcf724a4 100644 --- a/examples/jsm/inspector/ui/Style.js +++ b/examples/jsm/inspector/ui/Style.js @@ -1057,7 +1057,7 @@ export class Style { justify-content: space-between; } -.console-filters-group { +.console-buttons-group { display: flex; gap: 20px; } @@ -1074,6 +1074,28 @@ export class Style { border-radius: 15px; } +.console-copy-button { + background: transparent; + border: none; + color: var(--text-secondary); + cursor: pointer; + padding: 4px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + transition: color 0.2s, background-color 0.2s; +} + +.console-copy-button:hover { + color: var(--text-primary); + background-color: var(--profiler-hover); +} + +.console-copy-button.copied { + color: var(--color-green); +} + #console-log { display: flex; flex-direction: column; @@ -1081,6 +1103,8 @@ export class Style { padding: 10px; overflow-y: auto; flex-grow: 1; + user-select: text; + -webkit-user-select: text; } .log-message { From 83b7ea53d3d6cb42fdeaca1f42daea5f1d0587e4 Mon Sep 17 00:00:00 2001 From: NateSmyth Date: Fri, 23 Jan 2026 11:00:54 -0500 Subject: [PATCH 3/3] StorageTextureNode: Add TSL read/write support (#32734) --- examples/webgpu_compute_texture_pingpong.html | 103 +++++++----------- src/nodes/accessors/StorageTextureNode.js | 16 ++- src/renderers/webgpu/nodes/WGSLNodeBuilder.js | 30 ++++- .../accessors/StorageTextureNode.tests.js | 39 +++++++ .../webgpu/nodes/WGSLNodeBuilder.tests.js | 69 ++++++++++++ test/unit/three.source.unit.js | 6 + 6 files changed, 196 insertions(+), 67 deletions(-) create mode 100644 test/unit/src/nodes/accessors/StorageTextureNode.tests.js create mode 100644 test/unit/src/renderers/webgpu/nodes/WGSLNodeBuilder.tests.js diff --git a/examples/webgpu_compute_texture_pingpong.html b/examples/webgpu_compute_texture_pingpong.html index 45fc59c070de45..129ef5556130cd 100644 --- a/examples/webgpu_compute_texture_pingpong.html +++ b/examples/webgpu_compute_texture_pingpong.html @@ -16,7 +16,7 @@ - Compute ping/pong texture using GPU. + Compute ping/pong texture using GPU (pure TSL). @@ -34,7 +34,7 @@