@@ -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
const sourceString = shaderModifier . toString ( )
@@ -27,13 +29,17 @@ function shadergenerator(p5, fn) {
27
29
} ) ;
28
30
ancestor ( ast , ASTCallbacks , undefined , { varyings : { } } ) ;
29
31
const transpiledSource = escodegen . generate ( ast ) ;
30
- generatorFunction = new Function (
32
+ const scopeKeys = Object . keys ( scope ) ;
33
+ const internalGeneratorFunction = new Function (
34
+ 'p5' ,
35
+ ...scopeKeys ,
31
36
transpiledSource
32
37
. slice (
33
38
transpiledSource . indexOf ( '{' ) + 1 ,
34
39
transpiledSource . lastIndexOf ( '}' )
35
40
) . replaceAll ( ';' , '' )
36
41
) ;
42
+ generatorFunction = ( ) => internalGeneratorFunction ( p5 , ...scopeKeys . map ( key => scope [ key ] ) ) ;
37
43
} else {
38
44
generatorFunction = shaderModifier ;
39
45
}
@@ -64,15 +70,24 @@ function shadergenerator(p5, fn) {
64
70
}
65
71
}
66
72
67
- function ancestorIsUniform ( ancestor ) {
73
+ function nodeIsUniform ( ancestor ) {
68
74
return ancestor . type === 'CallExpression'
69
- && ancestor . callee ?. type === 'Identifier'
70
- && ancestor . callee ?. name . startsWith ( 'uniform' ) ;
75
+ && (
76
+ (
77
+ // Global mode
78
+ ancestor . callee ?. type === 'Identifier' &&
79
+ ancestor . callee ?. name . startsWith ( 'uniform' )
80
+ ) || (
81
+ // Instance mode
82
+ ancestor . callee ?. type === 'MemberExpression' &&
83
+ ancestor . callee ?. property . name . startsWith ( 'uniform' )
84
+ )
85
+ ) ;
71
86
}
72
87
73
88
const ASTCallbacks = {
74
- UnaryExpression ( node , _state , _ancestors ) {
75
- if ( _ancestors . some ( ancestorIsUniform ) ) { return ; }
89
+ UnaryExpression ( node , _state , ancestors ) {
90
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
76
91
77
92
const signNode = {
78
93
type : 'Literal' ,
@@ -83,7 +98,7 @@ function shadergenerator(p5, fn) {
83
98
node . type = 'CallExpression'
84
99
node . callee = {
85
100
type : 'Identifier' ,
86
- name : 'unaryNode' ,
101
+ name : 'p5. unaryNode' ,
87
102
}
88
103
node . arguments = [ node . argument , signNode ]
89
104
}
@@ -106,7 +121,7 @@ function shadergenerator(p5, fn) {
106
121
type : 'CallExpression' ,
107
122
callee : {
108
123
type : 'Identifier' ,
109
- name : 'unaryNode'
124
+ name : 'p5. unaryNode'
110
125
} ,
111
126
arguments : [ node . argument . object , signNode ] ,
112
127
} ;
@@ -123,8 +138,9 @@ function shadergenerator(p5, fn) {
123
138
delete node . argument ;
124
139
delete node . operator ;
125
140
} ,
126
- VariableDeclarator ( node , _state , _ancestors ) {
127
- if ( node . init . callee && node . init . callee . name ?. startsWith ( 'uniform' ) ) {
141
+ VariableDeclarator ( node , _state , ancestors ) {
142
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
143
+ if ( nodeIsUniform ( node . init ) ) {
128
144
const uniformNameLiteral = {
129
145
type : 'Literal' ,
130
146
value : node . id . name
@@ -140,7 +156,8 @@ function shadergenerator(p5, fn) {
140
156
_state . varyings [ node . id . name ] = varyingNameLiteral ;
141
157
}
142
158
} ,
143
- Identifier ( node , _state , _ancestors ) {
159
+ Identifier ( node , _state , ancestors ) {
160
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
144
161
if ( _state . varyings [ node . name ]
145
162
&& ! _ancestors . some ( a => a . type === 'AssignmentExpression' && a . left === node ) ) {
146
163
node . type = 'ExpressionStatement' ;
@@ -163,16 +180,18 @@ function shadergenerator(p5, fn) {
163
180
} ,
164
181
// The callbacks for AssignmentExpression and BinaryExpression handle
165
182
// operator overloading including +=, *= assignment expressions
166
- ArrayExpression ( node , _state , _ancestors ) {
183
+ ArrayExpression ( node , _state , ancestors ) {
184
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
167
185
const original = JSON . parse ( JSON . stringify ( node ) ) ;
168
186
node . type = 'CallExpression' ;
169
187
node . callee = {
170
188
type : 'Identifier' ,
171
- name : 'dynamicNode' ,
189
+ name : 'p5. dynamicNode' ,
172
190
} ;
173
191
node . arguments = [ original ] ;
174
192
} ,
175
- AssignmentExpression ( node , _state , _ancestors ) {
193
+ AssignmentExpression ( node , _state , ancestors ) {
194
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
176
195
if ( node . operator !== '=' ) {
177
196
const methodName = replaceBinaryOperator ( node . operator . replace ( '=' , '' ) ) ;
178
197
const rightReplacementNode = {
@@ -209,10 +228,10 @@ function shadergenerator(p5, fn) {
209
228
}
210
229
}
211
230
} ,
212
- BinaryExpression ( node , _state , _ancestors ) {
231
+ BinaryExpression ( node , _state , ancestors ) {
213
232
// Don't convert uniform default values to node methods, as
214
233
// they should be evaluated at runtime, not compiled.
215
- if ( _ancestors . some ( ancestorIsUniform ) ) { return ; }
234
+ if ( ancestors . some ( nodeIsUniform ) ) { return ; }
216
235
// If the left hand side of an expression is one of these types,
217
236
// we should construct a node from it.
218
237
const unsafeTypes = [ 'Literal' , 'ArrayExpression' , 'Identifier' ] ;
@@ -221,7 +240,7 @@ function shadergenerator(p5, fn) {
221
240
type : 'CallExpression' ,
222
241
callee : {
223
242
type : 'Identifier' ,
224
- name : 'dynamicNode' ,
243
+ name : 'p5. dynamicNode' ,
225
244
} ,
226
245
arguments : [ node . left ]
227
246
}
@@ -1010,7 +1029,7 @@ function shadergenerator(p5, fn) {
1010
1029
return length
1011
1030
}
1012
1031
1013
- fn . dynamicNode = function ( input ) {
1032
+ p5 . dynamicNode = function ( input ) {
1014
1033
if ( isShaderNode ( input ) ) {
1015
1034
return input ;
1016
1035
}
@@ -1023,8 +1042,8 @@ function shadergenerator(p5, fn) {
1023
1042
}
1024
1043
1025
1044
// For replacing unary expressions
1026
- fn . unaryNode = function ( input , sign ) {
1027
- input = dynamicNode ( input ) ;
1045
+ p5 . unaryNode = function ( input , sign ) {
1046
+ input = p5 . dynamicNode ( input ) ;
1028
1047
return dynamicAddSwizzleTrap ( new UnaryExpressionNode ( input , sign ) ) ;
1029
1048
}
1030
1049
@@ -1131,6 +1150,7 @@ function shadergenerator(p5, fn) {
1131
1150
}
1132
1151
1133
1152
const windowOverrides = { } ;
1153
+ const fnOverrides = { } ;
1134
1154
1135
1155
Object . keys ( availableHooks ) . forEach ( ( hookName ) => {
1136
1156
const hookTypes = originalShader . hookTypes ( hookName ) ;
@@ -1166,7 +1186,7 @@ function shadergenerator(p5, fn) {
1166
1186
// If the expected return type is a struct we need to evaluate each of its properties
1167
1187
if ( ! isGLSLNativeType ( expectedReturnType . typeName ) ) {
1168
1188
Object . entries ( returnedValue ) . forEach ( ( [ propertyName , propertyNode ] ) => {
1169
- propertyNode = dynamicNode ( propertyNode ) ;
1189
+ propertyNode = p5 . dynamicNode ( propertyNode ) ;
1170
1190
toGLSLResults [ propertyName ] = propertyNode . toGLSLBase ( this . context ) ;
1171
1191
this . context . updateComponents ( propertyNode ) ;
1172
1192
} ) ;
@@ -1216,18 +1236,25 @@ function shadergenerator(p5, fn) {
1216
1236
this . resetGLSLContext ( ) ;
1217
1237
}
1218
1238
windowOverrides [ hookTypes . name ] = window [ hookTypes . name ] ;
1239
+ fnOverrides [ hookTypes . name ] = fn [ hookTypes . name ] ;
1219
1240
1220
1241
// Expose the Functions to global scope for users to use
1221
1242
window [ hookTypes . name ] = function ( userOverride ) {
1222
1243
GLOBAL_SHADER [ hookTypes . name ] ( userOverride ) ;
1223
1244
} ;
1245
+ fn [ hookTypes . name ] = function ( userOverride ) {
1246
+ GLOBAL_SHADER [ hookTypes . name ] ( userOverride ) ;
1247
+ } ;
1224
1248
} ) ;
1225
1249
1226
1250
1227
1251
this . cleanup = ( ) => {
1228
1252
for ( const key in windowOverrides ) {
1229
1253
window [ key ] = windowOverrides [ key ] ;
1230
1254
}
1255
+ for ( const key in fnOverrides ) {
1256
+ fn [ key ] = fnOverrides [ key ] ;
1257
+ }
1231
1258
} ;
1232
1259
}
1233
1260
@@ -1636,14 +1663,14 @@ function shadergenerator(p5, fn) {
1636
1663
if ( ! GLOBAL_SHADER ?. isGenerating ) {
1637
1664
return originalNoise . apply ( this , args ) ; // fallback to regular p5.js noise
1638
1665
}
1639
-
1666
+
1640
1667
GLOBAL_SHADER . output . vertexDeclarations . add ( noiseGLSL ) ;
1641
1668
GLOBAL_SHADER . output . fragmentDeclarations . add ( noiseGLSL ) ;
1642
1669
return fnNodeConstructor ( 'noise' , args , { args : [ 'vec2' ] , returnType : 'float' } ) ;
1643
1670
} ;
1644
1671
}
1645
-
1646
-
1672
+
1673
+
1647
1674
export default shadergenerator ;
1648
1675
1649
1676
if ( typeof p5 !== 'undefined' ) {
0 commit comments