diff --git a/examples/screenshots/physics_jolt_instancing.jpg b/examples/screenshots/physics_jolt_instancing.jpg index c2d8f43418c2a8..cff7be43ea4506 100644 Binary files a/examples/screenshots/physics_jolt_instancing.jpg and b/examples/screenshots/physics_jolt_instancing.jpg differ diff --git a/examples/screenshots/webgl_postprocessing_godrays.jpg b/examples/screenshots/webgl_postprocessing_godrays.jpg index 0a8a358541c7bd..213c3d38bf7df4 100644 Binary files a/examples/screenshots/webgl_postprocessing_godrays.jpg and b/examples/screenshots/webgl_postprocessing_godrays.jpg differ diff --git a/src/Three.TSL.js b/src/Three.TSL.js index 608c2fb17a326f..81ccd5539c58d7 100644 --- a/src/Three.TSL.js +++ b/src/Three.TSL.js @@ -626,6 +626,7 @@ export const workgroupBarrier = TSL.workgroupBarrier; export const workgroupId = TSL.workgroupId; export const workingToColorSpace = TSL.workingToColorSpace; export const xor = TSL.xor; +export const invocationIndex = TSL.invocationIndex; /* // Use this code to generate the export statements dynamically diff --git a/src/nodes/core/IndexNode.js b/src/nodes/core/IndexNode.js index 5908cc694d75ea..30c9f4cba66c8f 100644 --- a/src/nodes/core/IndexNode.js +++ b/src/nodes/core/IndexNode.js @@ -123,6 +123,15 @@ export default IndexNode; */ export const vertexIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.VERTEX ); +/** + * TSL object that represents the global index of a compute shader invocation. + * This is the linearized index across all workgroups, equivalent to the global invocation ID. + * + * @tsl + * @type {IndexNode} + */ +export const invocationIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INVOCATION_GLOBAL ); + /** * TSL object that represents the index of either a mesh instance or an invocation of a compute shader. * diff --git a/src/nodes/core/NodeBuilder.js b/src/nodes/core/NodeBuilder.js index d83ca104d85921..3c84287ca764bf 100644 --- a/src/nodes/core/NodeBuilder.js +++ b/src/nodes/core/NodeBuilder.js @@ -1035,6 +1035,18 @@ class NodeBuilder { } + /** + * Returns the global invocation index for compute shaders. + * This is the linearized index of a compute invocation within a grid of workgroups. + * + * @abstract + * @return {string} The invocation index shader string. + */ + getInvocationIndex() { + + warn( 'Abstract function.' ); + + } /** * Contextually returns either the vertex stage instance index builtin * or the linearized index of an compute invocation within a grid of workgroups. diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index 89736ff30c7ae9..24faf965662966 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -1206,6 +1206,18 @@ ${ flowData.code } * * @return {string} The instance index. */ + getInvocationIndex() { + + if ( this.shaderStage === 'compute' ) { + + return 'invocationIndex'; + + } + + throw new Error( 'getInvocationIndex() is only valid in compute shaders' ); + + } + getInstanceIndex() { if ( this.shaderStage === 'vertex' ) { @@ -1214,7 +1226,7 @@ ${ flowData.code } } - return 'instanceIndex'; + throw new Error( 'instanceIndex is only valid in vertex shaders. Use invocationIndex for compute shaders.' ); } @@ -2319,7 +2331,7 @@ fn main( ${shaderData.varyings} ) -> ${shaderData.returnType} { ${ shaderData.directives } // system -var instanceIndex : u32; +var invocationIndex : u32; // locals ${ shaderData.scopedArrays } @@ -2337,7 +2349,7 @@ ${ shaderData.codes } fn main( ${ shaderData.attributes } ) { // system - instanceIndex = globalId.x + invocationIndex = globalId.x + globalId.y * ( ${ workgroupSizeX } * numWorkgroups.x ) + globalId.z * ( ${ workgroupSizeX } * numWorkgroups.x ) * ( ${ workgroupSizeY } * numWorkgroups.y );