6
6
*/
7
7
8
8
import { parse } from 'acorn' ;
9
- import { simple } from 'acorn-walk' ;
9
+ import { ancestor } from 'acorn-walk' ;
10
10
import escodegen from 'escodegen' ;
11
11
12
12
function shadergen ( p5 , fn ) {
@@ -23,7 +23,7 @@ function shadergen(p5, fn) {
23
23
ecmaVersion : 2021 ,
24
24
locations : options . srcLocations
25
25
} ) ;
26
- simple ( ast , ASTCallbacks ) ;
26
+ ancestor ( ast , ASTCallbacks ) ;
27
27
const transpiledSource = escodegen . generate ( ast ) ;
28
28
generatorFunction = new Function (
29
29
transpiledSource . slice (
@@ -103,7 +103,6 @@ function shadergen(p5, fn) {
103
103
} ,
104
104
}
105
105
106
-
107
106
// Javascript Node API.
108
107
// These classes are for expressing GLSL functions in Javascript without
109
108
// needing to transpile the user's code.
@@ -114,7 +113,6 @@ function shadergen(p5, fn) {
114
113
}
115
114
this . type = type ;
116
115
this . componentNames = [ ] ;
117
- this . swizzleAccessed = false ;
118
116
this . swizzleChanged = false ;
119
117
// For tracking recursion depth and creating temporary variables
120
118
this . isInternal = isInternal ;
@@ -151,7 +149,6 @@ function shadergen(p5, fn) {
151
149
let value = new ComponentNode ( this , componentName , 'float' , true ) ;
152
150
Object . defineProperty ( this , componentName , {
153
151
get ( ) {
154
- this . swizzleAccessed = true ;
155
152
return value ;
156
153
} ,
157
154
set ( newValue ) {
@@ -215,7 +212,6 @@ function shadergen(p5, fn) {
215
212
mod ( other ) { return new ModulusNode ( this , this . enforceType ( other ) ) ; }
216
213
217
214
// Check that the types of the operands are compatible.
218
- // TODO: improve this with less branching if elses
219
215
enforceType ( other ) {
220
216
if ( isShaderNode ( other ) ) {
221
217
if ( ( isFloatNode ( this ) || isVectorNode ( this ) ) && isIntNode ( other ) ) {
@@ -228,7 +224,10 @@ function shadergen(p5, fn) {
228
224
return new IntNode ( other ) ;
229
225
}
230
226
return new FloatNode ( other ) ;
231
- }
227
+ }
228
+ else if ( Array . isArray ( other ) ) {
229
+ return new VectorNode ( other , `vec${ other . length } ` )
230
+ }
232
231
else {
233
232
return new this . constructor ( other ) ;
234
233
}
@@ -474,7 +473,7 @@ function shadergen(p5, fn) {
474
473
return ( isShaderNode ( node ) && ( node . type === 'float' ) ) ;
475
474
}
476
475
477
- function isVectorNode ( node ) {
476
+ function isVectorNode ( node ) {
478
477
return ( isShaderNode ( node ) && ( node . type === 'vec2' || node . type === 'vec3' || node . type === 'vec4' ) ) ;
479
478
}
480
479
@@ -507,27 +506,35 @@ function shadergen(p5, fn) {
507
506
return this . output ;
508
507
}
509
508
509
+ // This method generates the hook overrides which the user calls in their modify function.
510
510
generateHookOverrides ( originalShader ) {
511
511
const availableHooks = {
512
512
...originalShader . hooks . vertex ,
513
513
...originalShader . hooks . fragment ,
514
514
}
515
- // Defines a function for each of the hooks for the shader we are modifying.
515
+
516
516
Object . keys ( availableHooks ) . forEach ( ( hookName ) => {
517
517
const hookTypes = originalShader . hookTypes ( hookName )
518
518
console . log ( hookTypes ) ;
519
+
519
520
this [ hookTypes . name ] = function ( userOverride ) {
520
521
let argNodes = [ ]
522
+
521
523
const argsArray = hookTypes . parameters . map ( ( parameter ) => {
522
524
argNodes . push (
523
525
new VariableNode ( parameter . name , parameter . type . typeName , true )
524
526
) ;
525
527
const qualifiers = parameter . type . qualifiers . length > 0 ? parameter . type . qualifiers . join ( ' ' ) : '' ;
526
528
return `${ qualifiers } ${ parameter . type . typeName } ${ parameter . name } ` . trim ( ) ;
527
529
} ) ;
528
-
529
530
const argsString = `(${ argsArray . join ( ', ' ) } ) {` ;
530
- const toGLSLResult = userOverride ( ...argNodes ) . toGLSLBase ( this . context ) ;
531
+
532
+ let returnedValue = userOverride ( ...argNodes ) ;
533
+ if ( ! isShaderNode ( returnedValue ) ) {
534
+ const expectedReturnType = hookTypes . returnType ;
535
+ returnedValue = nodeConstructors [ expectedReturnType . typeName ] ( returnedValue )
536
+ }
537
+ const toGLSLResult = returnedValue . toGLSLBase ( this . context ) ;
531
538
let codeLines = [ argsString , ...this . context . declarations ] ;
532
539
codeLines . push ( `\n${ hookTypes . returnType . typeName } finalReturnValue = ${ toGLSLResult } ;
533
540
\nreturn finalReturnValue;
@@ -602,13 +609,12 @@ function shadergen(p5, fn) {
602
609
603
610
ShaderGenerator . prototype [ uniformMethodName ] = function ( ...args ) {
604
611
let [ name , ...defaultValue ] = args ;
612
+
605
613
if ( glslType . startsWith ( 'vec' ) ) {
606
614
defaultValue = conformVectorParameters ( defaultValue , + glslType . slice ( 3 ) ) ;
607
615
this . output . uniforms [ `${ glslType } ${ name } ` ] = defaultValue ;
608
616
}
609
617
else {
610
- console . log ( "defaultValue: " , defaultValue ) ;
611
- console . log ( "defaultValue[0]: " , defaultValue [ 0 ] )
612
618
this . output . uniforms [ `${ glslType } ${ name } ` ] = defaultValue [ 0 ] ;
613
619
}
614
620
@@ -637,59 +643,69 @@ function shadergen(p5, fn) {
637
643
}
638
644
639
645
// GLSL Built in functions
640
- // TODO:
641
646
// Add a whole lot of these functions.
642
647
// https://docs.gl/el3/abs
648
+ // TODO:
649
+ // In reality many of these have multiple overrides which will need to address later.
650
+ // Also, their return types depend on the genType which will need to address urgently
651
+ // genType clamp(genType x,
652
+ // genType minVal,
653
+ // genType maxVal);
654
+ // genType clamp(genType x,
655
+ // float minVal,
656
+ // float maxVal);
657
+
643
658
644
- // constructor(name, args, type, isInternal = false) {
645
659
646
660
const builtInFunctions = {
647
- // Trigonometry
648
- 'acos' : { } ,
661
+ //////////// Trigonometry //////////
662
+ 'acos' : { args : [ 'genType' ] , returnType : 'float' } ,
649
663
// 'acosh': {},
650
- 'asin' : { } ,
664
+ 'asin' : { args : [ 'genType' ] , returnType : 'float' } ,
651
665
// 'asinh': {},
652
- 'atan' : { } ,
666
+ 'atan' : { args : [ 'genType' ] , returnType : 'float' } ,
653
667
// 'atanh': {},
654
- 'cos' : { } ,
668
+ 'cos' : { args : [ 'genType' ] , returnType : 'float' , isp5Function : true } ,
655
669
// 'cosh': {},
656
- 'degrees' : { } ,
657
- 'radians' : { } ,
658
- 'sin' : { } ,
670
+ 'degrees' : { args : [ 'genType' ] , returnType : 'float' } ,
671
+ 'radians' : { args : [ 'genType' ] , returnType : 'float' } ,
672
+ 'sin' : { args : [ 'genType' ] , returnType : 'float' , isp5Function : true } ,
659
673
// 'sinh': {},
660
- 'tan' : { } ,
674
+ 'tan' : { args : [ 'genType' ] , returnType : 'float' , isp5Function : true } ,
661
675
// 'tanh': {},
662
- // Mathematics
663
- 'abs' : { } ,
664
- 'ceil' : { } ,
665
- 'clamp' : { } ,
666
- 'dFdx' : { } ,
667
- 'dFdy' : { } ,
668
- 'exp' : { } ,
669
- 'exp2' : { } ,
670
- 'floor' : { } ,
676
+
677
+ ////////// Mathematics //////////
678
+ 'abs' : { args : [ 'genType' ] , returnType : 'float' } ,
679
+ 'ceil' : { args : [ 'genType' ] , returnType : 'float' } ,
680
+ 'clamp' : { args : [ 'genType' , 'genType' , 'genType' ] , returnType : 'float' } ,
681
+ // 'dFdx': {},
682
+ // 'dFdy': {},
683
+ 'exp' : { args : [ 'genType' ] , returnType : 'float' } ,
684
+ 'exp2' : { args : [ 'genType' ] , returnType : 'float' } ,
685
+ 'floor' : { args : [ 'genType' ] , returnType : 'float' } ,
671
686
// 'fma': {},
672
- 'fract' : { } ,
687
+ 'fract' : { args : [ 'genType' ] , returnType : 'float' } ,
673
688
// 'fwidth': {},
674
689
// 'inversesqrt': {},
675
690
// 'isinf': {},
676
691
// 'isnan': {},
677
692
// 'log': {},
678
693
// 'log2': {},
679
- 'max' : { } ,
680
- 'min' : { } ,
681
- 'mix' : { } ,
694
+ 'max' : { args : [ 'genType' ] , returnType : 'genType' } ,
695
+ 'min' : { args : [ 'genType' ] , returnType : 'genType' } ,
696
+ 'mix' : { args : [ 'genType' ] , returnType : 'genType' } ,
682
697
// 'mod': {},
683
698
// 'modf': {},
684
- 'pow' : { } ,
699
+ 'pow' : { args : [ 'genType' ] , returnType : 'float' } ,
685
700
// 'round': {},
686
701
// 'roundEven': {},
687
702
// 'sign': {},
688
- 'smoothstep' : { } ,
689
- 'sqrt' : { } ,
690
- 'step' : { } ,
703
+ 'smoothstep' : { args : [ 'genType' , 'genType' , 'genType' ] , returnType : 'float' } ,
704
+ 'sqrt' : { args : [ 'genType' ] , returnType : 'genType' } ,
705
+ 'step' : { args : [ 'genType' , 'genType' ] , returnType : 'genType' } ,
691
706
// 'trunc': {},
692
- // Vector
707
+
708
+ ////////// Vector //////////
693
709
'cross' : { } ,
694
710
'distance' : { } ,
695
711
'dot' : { } ,
@@ -704,7 +720,10 @@ function shadergen(p5, fn) {
704
720
'texture' : { } ,
705
721
}
706
722
707
- // Object.entries(builtInFunctions).forEach(([glslFnName, properties]) => {
723
+ // Object.entries(builtInFunctions).forEach(([functionName, properties]) => {
724
+ // fn[functionName] = function () {
725
+ // new FunctionCallNode(functionName, args, type, isInternal = false)
726
+ // }
708
727
// })
709
728
710
729
const oldTexture = p5 . prototype . texture ;
0 commit comments