@@ -16,8 +16,10 @@ function shadergenerator(p5, fn) {
16
16
17
17
const oldModify = p5 . Shader . prototype . modify
18
18
19
- p5 . Shader . prototype . modify = function ( shaderModifier , options = { parser : true , srcLocations : false } ) {
19
+ p5 . Shader . prototype . modify = function ( shaderModifier , scope = { } ) {
20
20
if ( shaderModifier instanceof Function ) {
21
+ // TODO make this public. Currently for debugging only.
22
+ const options = { parser : true , srcLocations : false } ;
21
23
let generatorFunction ;
22
24
if ( options . parser ) {
23
25
// #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) {
29
31
} ) ;
30
32
ancestor ( ast , ASTCallbacks , undefined , { varyings : { } } ) ;
31
33
const transpiledSource = escodegen . generate ( ast ) ;
32
- generatorFunction = new Function (
34
+ const scopeKeys = Object . keys ( scope ) ;
35
+ const internalGeneratorFunction = new Function (
36
+ 'p5' ,
37
+ ...scopeKeys ,
33
38
transpiledSource
34
39
. slice (
35
40
transpiledSource . indexOf ( '{' ) + 1 ,
36
41
transpiledSource . lastIndexOf ( '}' )
37
42
) . replaceAll ( ';' , '' )
38
43
) ;
44
+ generatorFunction = ( ) => internalGeneratorFunction ( p5 , ...scopeKeys . map ( key => scope [ key ] ) ) ;
39
45
} else {
40
46
generatorFunction = shaderModifier ;
41
47
}
@@ -66,15 +72,24 @@ function shadergenerator(p5, fn) {
66
72
}
67
73
}
68
74
69
- function ancestorIsUniform ( ancestor ) {
75
+ function nodeIsUniform ( ancestor ) {
70
76
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
+ ) ;
73
88
}
74
89
75
90
const ASTCallbacks = {
76
- UnaryExpression ( node , _state , _ancestors ) {
77
- if ( _ancestors . some ( ancestorIsUniform ) ) { return ; }
91
+ UnaryExpression ( node , _state , ancestors ) {
92
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
78
93
79
94
const signNode = {
80
95
type : 'Literal' ,
@@ -85,7 +100,7 @@ function shadergenerator(p5, fn) {
85
100
node . type = 'CallExpression'
86
101
node . callee = {
87
102
type : 'Identifier' ,
88
- name : 'unaryNode' ,
103
+ name : 'p5. unaryNode' ,
89
104
}
90
105
node . arguments = [ node . argument , signNode ]
91
106
}
@@ -108,7 +123,7 @@ function shadergenerator(p5, fn) {
108
123
type : 'CallExpression' ,
109
124
callee : {
110
125
type : 'Identifier' ,
111
- name : 'unaryNode'
126
+ name : 'p5. unaryNode'
112
127
} ,
113
128
arguments : [ node . argument . object , signNode ] ,
114
129
} ;
@@ -125,8 +140,9 @@ function shadergenerator(p5, fn) {
125
140
delete node . argument ;
126
141
delete node . operator ;
127
142
} ,
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 ) ) {
130
146
const uniformNameLiteral = {
131
147
type : 'Literal' ,
132
148
value : node . id . name
@@ -142,7 +158,8 @@ function shadergenerator(p5, fn) {
142
158
_state . varyings [ node . id . name ] = varyingNameLiteral ;
143
159
}
144
160
} ,
145
- Identifier ( node , _state , _ancestors ) {
161
+ Identifier ( node , _state , ancestors ) {
162
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
146
163
if ( _state . varyings [ node . name ]
147
164
&& ! _ancestors . some ( a => a . type === 'AssignmentExpression' && a . left === node ) ) {
148
165
node . type = 'ExpressionStatement' ;
@@ -165,16 +182,18 @@ function shadergenerator(p5, fn) {
165
182
} ,
166
183
// The callbacks for AssignmentExpression and BinaryExpression handle
167
184
// operator overloading including +=, *= assignment expressions
168
- ArrayExpression ( node , _state , _ancestors ) {
185
+ ArrayExpression ( node , _state , ancestors ) {
186
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
169
187
const original = JSON . parse ( JSON . stringify ( node ) ) ;
170
188
node . type = 'CallExpression' ;
171
189
node . callee = {
172
190
type : 'Identifier' ,
173
- name : 'dynamicNode' ,
191
+ name : 'p5. dynamicNode' ,
174
192
} ;
175
193
node . arguments = [ original ] ;
176
194
} ,
177
- AssignmentExpression ( node , _state , _ancestors ) {
195
+ AssignmentExpression ( node , _state , ancestors ) {
196
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
178
197
if ( node . operator !== '=' ) {
179
198
const methodName = replaceBinaryOperator ( node . operator . replace ( '=' , '' ) ) ;
180
199
const rightReplacementNode = {
@@ -211,10 +230,10 @@ function shadergenerator(p5, fn) {
211
230
}
212
231
}
213
232
} ,
214
- BinaryExpression ( node , _state , _ancestors ) {
233
+ BinaryExpression ( node , _state , ancestors ) {
215
234
// Don't convert uniform default values to node methods, as
216
235
// they should be evaluated at runtime, not compiled.
217
- if ( _ancestors . some ( ancestorIsUniform ) ) { return ; }
236
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
218
237
// If the left hand side of an expression is one of these types,
219
238
// we should construct a node from it.
220
239
const unsafeTypes = [ 'Literal' , 'ArrayExpression' , 'Identifier' ] ;
@@ -223,7 +242,7 @@ function shadergenerator(p5, fn) {
223
242
type : 'CallExpression' ,
224
243
callee : {
225
244
type : 'Identifier' ,
226
- name : 'dynamicNode' ,
245
+ name : 'p5. dynamicNode' ,
227
246
} ,
228
247
arguments : [ node . left ]
229
248
}
@@ -1012,7 +1031,7 @@ function shadergenerator(p5, fn) {
1012
1031
return length
1013
1032
}
1014
1033
1015
- fn . dynamicNode = function ( input ) {
1034
+ p5 . dynamicNode = function ( input ) {
1016
1035
if ( isShaderNode ( input ) ) {
1017
1036
return input ;
1018
1037
}
@@ -1025,8 +1044,8 @@ function shadergenerator(p5, fn) {
1025
1044
}
1026
1045
1027
1046
// 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 ) ;
1030
1049
return dynamicAddSwizzleTrap ( new UnaryExpressionNode ( input , sign ) ) ;
1031
1050
}
1032
1051
@@ -1133,6 +1152,7 @@ function shadergenerator(p5, fn) {
1133
1152
}
1134
1153
1135
1154
const windowOverrides = { } ;
1155
+ const fnOverrides = { } ;
1136
1156
1137
1157
Object . keys ( availableHooks ) . forEach ( ( hookName ) => {
1138
1158
const hookTypes = originalShader . hookTypes ( hookName ) ;
@@ -1168,7 +1188,7 @@ function shadergenerator(p5, fn) {
1168
1188
// If the expected return type is a struct we need to evaluate each of its properties
1169
1189
if ( ! isGLSLNativeType ( expectedReturnType . typeName ) ) {
1170
1190
Object . entries ( returnedValue ) . forEach ( ( [ propertyName , propertyNode ] ) => {
1171
- propertyNode = dynamicNode ( propertyNode ) ;
1191
+ propertyNode = p5 . dynamicNode ( propertyNode ) ;
1172
1192
toGLSLResults [ propertyName ] = propertyNode . toGLSLBase ( this . context ) ;
1173
1193
this . context . updateComponents ( propertyNode ) ;
1174
1194
} ) ;
@@ -1218,18 +1238,25 @@ function shadergenerator(p5, fn) {
1218
1238
this . resetGLSLContext ( ) ;
1219
1239
}
1220
1240
windowOverrides [ hookTypes . name ] = window [ hookTypes . name ] ;
1241
+ fnOverrides [ hookTypes . name ] = fn [ hookTypes . name ] ;
1221
1242
1222
1243
// Expose the Functions to global scope for users to use
1223
1244
window [ hookTypes . name ] = function ( userOverride ) {
1224
1245
GLOBAL_SHADER [ hookTypes . name ] ( userOverride ) ;
1225
1246
} ;
1247
+ fn [ hookTypes . name ] = function ( userOverride ) {
1248
+ GLOBAL_SHADER [ hookTypes . name ] ( userOverride ) ;
1249
+ } ;
1226
1250
} ) ;
1227
1251
1228
1252
1229
1253
this . cleanup = ( ) => {
1230
1254
for ( const key in windowOverrides ) {
1231
1255
window [ key ] = windowOverrides [ key ] ;
1232
1256
}
1257
+ for ( const key in fnOverrides ) {
1258
+ fn [ key ] = fnOverrides [ key ] ;
1259
+ }
1233
1260
} ;
1234
1261
}
1235
1262
@@ -1638,14 +1665,14 @@ function shadergenerator(p5, fn) {
1638
1665
if ( ! GLOBAL_SHADER ?. isGenerating ) {
1639
1666
return originalNoise . apply ( this , args ) ; // fallback to regular p5.js noise
1640
1667
}
1641
-
1668
+
1642
1669
GLOBAL_SHADER . output . vertexDeclarations . add ( noiseGLSL ) ;
1643
1670
GLOBAL_SHADER . output . fragmentDeclarations . add ( noiseGLSL ) ;
1644
1671
return fnNodeConstructor ( 'noise' , args , { args : [ 'vec2' ] , returnType : 'float' } ) ;
1645
1672
} ;
1646
1673
}
1647
-
1648
-
1674
+
1675
+
1649
1676
export default shadergenerator ;
1650
1677
1651
1678
if ( typeof p5 !== 'undefined' ) {
0 commit comments