@@ -289,7 +289,7 @@ function rendererWebGPU(p5, fn) {
289289 // Check if we already have a buffer for this data
290290 let existingBuffer = buffers [ dst ] ;
291291 const needsNewBuffer = ! existingBuffer ;
292-
292+
293293 // Only create new buffer and write data if buffer doesn't exist or data is dirty
294294 if ( needsNewBuffer || geometry . dirtyFlags [ src ] !== false ) {
295295 const raw = map ? map ( srcData ) : srcData ;
@@ -1349,7 +1349,7 @@ function rendererWebGPU(p5, fn) {
13491349 }
13501350
13511351 _getShaderAttributes ( shader ) {
1352- const mainMatch = / f n m a i n \( .+ : \s * ( \S + ) \s * \ )/ . exec ( shader . _vertSrc ) ;
1352+ const mainMatch = / f n m a i n \( .+ : \s * ( [ ^ \s \) ] + ) / . exec ( shader . _vertSrc ) ;
13531353 if ( ! mainMatch ) throw new Error ( "Can't find `fn main` in vertex shader source" ) ;
13541354 const inputType = mainMatch [ 1 ] ;
13551355
@@ -1740,7 +1740,12 @@ function rendererWebGPU(p5, fn) {
17401740 }
17411741 ) ;
17421742
1743- let [ preMain , main , postMain ] = src . split ( / ( (?: @ (?: v e r t e x | f r a g m e n t ) \s * ) ? f n m a i n ) / ) ;
1743+ let [ preMain , main , postMain ] = src . split ( / ( (?: @ (?: v e r t e x | f r a g m e n t ) \s * ) ? f n m a i n [ ^ { ] + \{ ) / ) ;
1744+ if ( shaderType !== 'fragment' ) {
1745+ if ( ! main . match ( / \@ b u i l t i n \s * \( \s * i n s t a n c e _ i n d e x \s * \) / ) ) {
1746+ main = main . replace ( / \) \s * ( - > | \{ ) / , ', @builtin(instance_index) instanceID: u32) $1' ) ;
1747+ }
1748+ }
17441749
17451750 let uniforms = '' ;
17461751 for ( const key in shader . hooks . uniforms ) {
@@ -1850,14 +1855,57 @@ function rendererWebGPU(p5, fn) {
18501855 shader . hooks . modified [ shaderType ] [ hookDef ] ? 'true' : 'false'
18511856 } ;\n`;
18521857
1853- const [ _ , params , body ] = / ^ ( \( [ ^ \) ] * \) ) ( (?: .| \n ) * ) $ / . exec ( shader . hooks [ shaderType ] [ hookDef ] ) ;
1858+ let [ _ , params , body ] = / ^ ( \( [ ^ \) ] * \) ) ( (?: .| \n ) * ) $ / . exec ( shader . hooks [ shaderType ] [ hookDef ] ) ;
1859+
1860+ if ( shaderType !== 'fragment' ) {
1861+ // Splice the instance ID in as a final parameter to every WGSL hook function
1862+ let hasParams = ! ! params . match ( / ^ \( \s * \S + .* \) $ / ) ;
1863+ params = params . slice ( 0 , - 1 ) + ( hasParams ? ', ' : '' ) + 'instanceID: u32)' ;
1864+ }
1865+
18541866 if ( hookType === 'void' ) {
18551867 hooks += `fn HOOK_${ hookName } ${ params } ${ body } \n` ;
18561868 } else {
18571869 hooks += `fn HOOK_${ hookName } ${ params } -> ${ hookType } ${ body } \n` ;
18581870 }
18591871 }
18601872
1873+ // Add the instance ID as a final parameter to each hook call
1874+ if ( shaderType !== 'fragment' ) {
1875+ const addInstanceIDParam = ( src ) => {
1876+ let result = src ;
1877+ let idx = 0 ;
1878+ let match ;
1879+ do {
1880+ match = / H O O K _ \w + \( / . exec ( result . slice ( idx ) ) ;
1881+ if ( match ) {
1882+ idx += match . index + match [ 0 ] . length - 1 ;
1883+ let nesting = 0 ;
1884+ let hasParams = false ;
1885+ while ( idx < result . length ) {
1886+ if ( result [ idx ] === '(' ) {
1887+ nesting ++ ;
1888+ } else if ( result [ idx ] === ')' ) {
1889+ nesting -- ;
1890+ } else if ( result [ idx ] . match ( / \S / ) ) {
1891+ hasParams = true ;
1892+ }
1893+ idx ++ ;
1894+ if ( nesting === 0 ) {
1895+ break ;
1896+ }
1897+ }
1898+ const insertion = ( hasParams ? ', ' : '' ) + 'instanceID' ;
1899+ result = result . slice ( 0 , idx - 1 ) + insertion + result . slice ( idx - 1 ) ;
1900+ idx += insertion . length ;
1901+ }
1902+ } while ( match ) ;
1903+ return result ;
1904+ } ;
1905+ preMain = addInstanceIDParam ( preMain ) ;
1906+ postMain = addInstanceIDParam ( postMain ) ;
1907+ }
1908+
18611909 return preMain + '\n' + defines + hooks + main + postMain ;
18621910 }
18631911
0 commit comments