@@ -16,8 +16,10 @@ function shadergenerator(p5, fn) {
1616
1717 const oldModify = p5 . Shader . prototype . modify
1818
19- p5 . Shader . prototype . modify = function ( shaderModifier , options = { parser : true , srcLocations : false } ) {
19+ p5 . Shader . prototype . modify = function ( shaderModifier , scope = { } ) {
2020 if ( shaderModifier instanceof Function ) {
21+ // TODO make this public. Currently for debugging only.
22+ const options = { parser : true , srcLocations : false } ;
2123 let generatorFunction ;
2224 if ( options . parser ) {
2325 // #7955 Wrap function declaration code in brackets so anonymous functions are not top level statements, which causes an error in acorn when parsing
@@ -29,13 +31,17 @@ function shadergenerator(p5, fn) {
2931 } ) ;
3032 ancestor ( ast , ASTCallbacks , undefined , { varyings : { } } ) ;
3133 const transpiledSource = escodegen . generate ( ast ) ;
32- generatorFunction = new Function (
34+ const scopeKeys = Object . keys ( scope ) ;
35+ const internalGeneratorFunction = new Function (
36+ 'p5' ,
37+ ...scopeKeys ,
3338 transpiledSource
3439 . slice (
3540 transpiledSource . indexOf ( '{' ) + 1 ,
3641 transpiledSource . lastIndexOf ( '}' )
3742 ) . replaceAll ( ';' , '' )
3843 ) ;
44+ generatorFunction = ( ) => internalGeneratorFunction ( p5 , ...scopeKeys . map ( key => scope [ key ] ) ) ;
3945 } else {
4046 generatorFunction = shaderModifier ;
4147 }
@@ -66,15 +72,24 @@ function shadergenerator(p5, fn) {
6672 }
6773 }
6874
69- function ancestorIsUniform ( ancestor ) {
75+ function nodeIsUniform ( ancestor ) {
7076 return ancestor . type === 'CallExpression'
71- && ancestor . callee ?. type === 'Identifier'
72- && ancestor . callee ?. name . startsWith ( 'uniform' ) ;
77+ && (
78+ (
79+ // Global mode
80+ ancestor . callee ?. type === 'Identifier' &&
81+ ancestor . callee ?. name . startsWith ( 'uniform' )
82+ ) || (
83+ // Instance mode
84+ ancestor . callee ?. type === 'MemberExpression' &&
85+ ancestor . callee ?. property . name . startsWith ( 'uniform' )
86+ )
87+ ) ;
7388 }
7489
7590 const ASTCallbacks = {
76- UnaryExpression ( node , _state , _ancestors ) {
77- if ( _ancestors . some ( ancestorIsUniform ) ) { return ; }
91+ UnaryExpression ( node , _state , ancestors ) {
92+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
7893
7994 const signNode = {
8095 type : 'Literal' ,
@@ -85,7 +100,7 @@ function shadergenerator(p5, fn) {
85100 node . type = 'CallExpression'
86101 node . callee = {
87102 type : 'Identifier' ,
88- name : 'unaryNode' ,
103+ name : 'p5. unaryNode' ,
89104 }
90105 node . arguments = [ node . argument , signNode ]
91106 }
@@ -108,7 +123,7 @@ function shadergenerator(p5, fn) {
108123 type : 'CallExpression' ,
109124 callee : {
110125 type : 'Identifier' ,
111- name : 'unaryNode'
126+ name : 'p5. unaryNode'
112127 } ,
113128 arguments : [ node . argument . object , signNode ] ,
114129 } ;
@@ -125,8 +140,9 @@ function shadergenerator(p5, fn) {
125140 delete node . argument ;
126141 delete node . operator ;
127142 } ,
128- VariableDeclarator ( node , _state , _ancestors ) {
129- if ( node . init . callee && node . init . callee . name ?. startsWith ( 'uniform' ) ) {
143+ VariableDeclarator ( node , _state , ancestors ) {
144+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
145+ if ( nodeIsUniform ( node . init ) ) {
130146 const uniformNameLiteral = {
131147 type : 'Literal' ,
132148 value : node . id . name
@@ -142,7 +158,8 @@ function shadergenerator(p5, fn) {
142158 _state . varyings [ node . id . name ] = varyingNameLiteral ;
143159 }
144160 } ,
145- Identifier ( node , _state , _ancestors ) {
161+ Identifier ( node , _state , ancestors ) {
162+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
146163 if ( _state . varyings [ node . name ]
147164 && ! _ancestors . some ( a => a . type === 'AssignmentExpression' && a . left === node ) ) {
148165 node . type = 'ExpressionStatement' ;
@@ -165,16 +182,18 @@ function shadergenerator(p5, fn) {
165182 } ,
166183 // The callbacks for AssignmentExpression and BinaryExpression handle
167184 // operator overloading including +=, *= assignment expressions
168- ArrayExpression ( node , _state , _ancestors ) {
185+ ArrayExpression ( node , _state , ancestors ) {
186+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
169187 const original = JSON . parse ( JSON . stringify ( node ) ) ;
170188 node . type = 'CallExpression' ;
171189 node . callee = {
172190 type : 'Identifier' ,
173- name : 'dynamicNode' ,
191+ name : 'p5. dynamicNode' ,
174192 } ;
175193 node . arguments = [ original ] ;
176194 } ,
177- AssignmentExpression ( node , _state , _ancestors ) {
195+ AssignmentExpression ( node , _state , ancestors ) {
196+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
178197 if ( node . operator !== '=' ) {
179198 const methodName = replaceBinaryOperator ( node . operator . replace ( '=' , '' ) ) ;
180199 const rightReplacementNode = {
@@ -211,10 +230,10 @@ function shadergenerator(p5, fn) {
211230 }
212231 }
213232 } ,
214- BinaryExpression ( node , _state , _ancestors ) {
233+ BinaryExpression ( node , _state , ancestors ) {
215234 // Don't convert uniform default values to node methods, as
216235 // they should be evaluated at runtime, not compiled.
217- if ( _ancestors . some ( ancestorIsUniform ) ) { return ; }
236+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
218237 // If the left hand side of an expression is one of these types,
219238 // we should construct a node from it.
220239 const unsafeTypes = [ 'Literal' , 'ArrayExpression' , 'Identifier' ] ;
@@ -223,7 +242,7 @@ function shadergenerator(p5, fn) {
223242 type : 'CallExpression' ,
224243 callee : {
225244 type : 'Identifier' ,
226- name : 'dynamicNode' ,
245+ name : 'p5. dynamicNode' ,
227246 } ,
228247 arguments : [ node . left ]
229248 }
@@ -1012,7 +1031,7 @@ function shadergenerator(p5, fn) {
10121031 return length
10131032 }
10141033
1015- fn . dynamicNode = function ( input ) {
1034+ p5 . dynamicNode = function ( input ) {
10161035 if ( isShaderNode ( input ) ) {
10171036 return input ;
10181037 }
@@ -1025,8 +1044,8 @@ function shadergenerator(p5, fn) {
10251044 }
10261045
10271046 // For replacing unary expressions
1028- fn . unaryNode = function ( input , sign ) {
1029- input = dynamicNode ( input ) ;
1047+ p5 . unaryNode = function ( input , sign ) {
1048+ input = p5 . dynamicNode ( input ) ;
10301049 return dynamicAddSwizzleTrap ( new UnaryExpressionNode ( input , sign ) ) ;
10311050 }
10321051
@@ -1133,6 +1152,7 @@ function shadergenerator(p5, fn) {
11331152 }
11341153
11351154 const windowOverrides = { } ;
1155+ const fnOverrides = { } ;
11361156
11371157 Object . keys ( availableHooks ) . forEach ( ( hookName ) => {
11381158 const hookTypes = originalShader . hookTypes ( hookName ) ;
@@ -1168,7 +1188,7 @@ function shadergenerator(p5, fn) {
11681188 // If the expected return type is a struct we need to evaluate each of its properties
11691189 if ( ! isGLSLNativeType ( expectedReturnType . typeName ) ) {
11701190 Object . entries ( returnedValue ) . forEach ( ( [ propertyName , propertyNode ] ) => {
1171- propertyNode = dynamicNode ( propertyNode ) ;
1191+ propertyNode = p5 . dynamicNode ( propertyNode ) ;
11721192 toGLSLResults [ propertyName ] = propertyNode . toGLSLBase ( this . context ) ;
11731193 this . context . updateComponents ( propertyNode ) ;
11741194 } ) ;
@@ -1218,18 +1238,25 @@ function shadergenerator(p5, fn) {
12181238 this . resetGLSLContext ( ) ;
12191239 }
12201240 windowOverrides [ hookTypes . name ] = window [ hookTypes . name ] ;
1241+ fnOverrides [ hookTypes . name ] = fn [ hookTypes . name ] ;
12211242
12221243 // Expose the Functions to global scope for users to use
12231244 window [ hookTypes . name ] = function ( userOverride ) {
12241245 GLOBAL_SHADER [ hookTypes . name ] ( userOverride ) ;
12251246 } ;
1247+ fn [ hookTypes . name ] = function ( userOverride ) {
1248+ GLOBAL_SHADER [ hookTypes . name ] ( userOverride ) ;
1249+ } ;
12261250 } ) ;
12271251
12281252
12291253 this . cleanup = ( ) => {
12301254 for ( const key in windowOverrides ) {
12311255 window [ key ] = windowOverrides [ key ] ;
12321256 }
1257+ for ( const key in fnOverrides ) {
1258+ fn [ key ] = fnOverrides [ key ] ;
1259+ }
12331260 } ;
12341261 }
12351262
@@ -1638,14 +1665,14 @@ function shadergenerator(p5, fn) {
16381665 if ( ! GLOBAL_SHADER ?. isGenerating ) {
16391666 return originalNoise . apply ( this , args ) ; // fallback to regular p5.js noise
16401667 }
1641-
1668+
16421669 GLOBAL_SHADER . output . vertexDeclarations . add ( noiseGLSL ) ;
16431670 GLOBAL_SHADER . output . fragmentDeclarations . add ( noiseGLSL ) ;
16441671 return fnNodeConstructor ( 'noise' , args , { args : [ 'vec2' ] , returnType : 'float' } ) ;
16451672 } ;
16461673}
1647-
1648-
1674+
1675+
16491676export default shadergenerator ;
16501677
16511678if ( typeof p5 !== 'undefined' ) {
0 commit comments