diff --git a/examples/files.json b/examples/files.json index 7bac8861c4693a..10094900b055a7 100644 --- a/examples/files.json +++ b/examples/files.json @@ -467,6 +467,7 @@ "webgpu_tsl_galaxy", "webgpu_tsl_halftone", "webgpu_tsl_interoperability", + "webgpu_tsl_override_context", "webgpu_tsl_procedural_terrain", "webgpu_tsl_raging_sea", "webgpu_tsl_transpiler", diff --git a/examples/screenshots/webgpu_tsl_override_context.jpg b/examples/screenshots/webgpu_tsl_override_context.jpg new file mode 100644 index 00000000000000..da440263035c30 Binary files /dev/null and b/examples/screenshots/webgpu_tsl_override_context.jpg differ diff --git a/examples/webgpu_tsl_override_context.html b/examples/webgpu_tsl_override_context.html new file mode 100644 index 00000000000000..e4894115386e6c --- /dev/null +++ b/examples/webgpu_tsl_override_context.html @@ -0,0 +1,136 @@ + + + + + Three.js webgpu - tsl override context + + + + + +
+ three.js - WebGPU - TSL Override Context
+ Left: Default Normals | Right: Overridden Normals (Rotated via Context) +
+ + + + + + + diff --git a/src/Three.TSL.js b/src/Three.TSL.js index 0ea6849fbe2758..9e1d85ab8a8a2c 100644 --- a/src/Three.TSL.js +++ b/src/Three.TSL.js @@ -133,6 +133,7 @@ export const compute = TSL.compute; export const computeKernel = TSL.computeKernel; export const computeSkinning = TSL.computeSkinning; export const context = TSL.context; +export const overrideContext = TSL.overrideContext; export const convert = TSL.convert; export const convertColorSpace = TSL.convertColorSpace; export const convertToTexture = TSL.convertToTexture; diff --git a/src/nodes/core/ContextNode.js b/src/nodes/core/ContextNode.js index da770f8e3252fc..5824e42fe3ac77 100644 --- a/src/nodes/core/ContextNode.js +++ b/src/nodes/core/ContextNode.js @@ -220,7 +220,26 @@ export function label( node, name ) { } +/** + * TSL function for overriding a context for a given node. + * + * @tsl + * @function + * @param {Node} node - The node whose context should be modified. + * @param {Node} targetNode - The node that will be replaced. + * @param {Node} sourceNode - The node that will replace the targetNode. + * @returns {ContextNode} + */ +export const overrideContext = ( node, targetNode, sourceNode ) => { + + const cleanSource = context( sourceNode, { [ targetNode.uuid ]: undefined } ); + + return context( node, { [ targetNode.uuid ]: cleanSource } ); + +}; + addMethodChaining( 'context', context ); addMethodChaining( 'label', label ); addMethodChaining( 'uniformFlow', uniformFlow ); addMethodChaining( 'setName', setName ); +addMethodChaining( 'overrideContext', overrideContext ); diff --git a/src/nodes/core/Node.js b/src/nodes/core/Node.js index 241ec9d2c4adf1..f8cd4bcd8f8957 100644 --- a/src/nodes/core/Node.js +++ b/src/nodes/core/Node.js @@ -720,6 +720,16 @@ class Node extends EventDispatcher { */ build( builder, output = null ) { + const nodeFromContext = builder.context[ this.uuid ]; + + if ( nodeFromContext !== undefined ) { + + return nodeFromContext.build( builder, output ); + + } + + // + const refNode = this.getShared( builder ); if ( this !== refNode ) { diff --git a/src/nodes/core/VarNode.js b/src/nodes/core/VarNode.js index 3727a0234d0a5e..70e9238f093cb4 100644 --- a/src/nodes/core/VarNode.js +++ b/src/nodes/core/VarNode.js @@ -181,6 +181,14 @@ class VarNode extends Node { const builder = params[ 0 ]; + const nodeFromContext = builder.context[ this.uuid ]; + + if ( nodeFromContext !== undefined ) { + + return nodeFromContext.build( ...params ); + + } + if ( this._hasStack( builder ) === false && builder.buildStage === 'setup' ) { if ( builder.context.nodeLoop || builder.context.nodeBlock ) {