@shaderfrog/core 2.0.0-beta.3 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/engine.d.ts +1 -0
- package/graph/code-nodes.d.ts +8 -2
- package/graph/code-nodes.js +5 -1
- package/graph/context.d.ts +3 -2
- package/graph/context.js +25 -12
- package/graph/evaluate.js +7 -0
- package/graph/graph.d.ts +8 -2
- package/graph/graph.js +105 -125
- package/graph/graph.test.js +226 -50
- package/graph/parsers.d.ts +2 -11
- package/graph/parsers.js +24 -14
- package/graph/shader-sections.d.ts +1 -1
- package/graph/shader-sections.js +1 -1
- package/package.json +4 -4
- package/plugins/babylon/bablyengine.js +4 -1
- package/plugins/playcanvas/playengine.js +4 -1
- package/plugins/three/importers.d.ts +1 -0
- package/plugins/three/importers.js +49 -1
- package/plugins/three/threngine.js +5 -2
- package/plugins/three/threngine.test.js +52 -4
- package/strategy/assignemntTo.js +4 -3
- package/strategy/declarationOf.js +2 -2
- package/strategy/hardCode.js +1 -4
- package/strategy/inject.js +3 -4
- package/strategy/namedAttribute.js +2 -2
- package/strategy/strategy.d.ts +28 -3
- package/strategy/stratgies.test.js +59 -31
- package/strategy/texture2D.js +20 -22
- package/strategy/uniform.js +54 -56
- package/strategy/variable.js +5 -5
- package/util/ast.d.ts +7 -3
- package/util/ast.js +29 -8
- package/util/ast.test.d.ts +1 -0
- package/util/ast.test.js +14 -0
- package/util/whitespace.d.ts +2 -0
- package/util/whitespace.js +27 -1
package/README.md
CHANGED
|
@@ -119,9 +119,9 @@ export interface Engine {
|
|
|
119
119
|
|
|
120
120
|
Shaderfrog works by searching each node's AST for certain patterns, like
|
|
121
121
|
`uniform` variables, and creating an interface where you can replace each
|
|
122
|
-
`uniform` variable with the output of another node.
|
|
122
|
+
`uniform` variable with the output of another node.
|
|
123
123
|
|
|
124
|
-
Each fillable part of the AST is called a
|
|
124
|
+
Each fillable part of the AST is called a **hole**. Holes are found by executing
|
|
125
125
|
user defined _strategies_ against an AST. With a program such as:
|
|
126
126
|
|
|
127
127
|
```glsl
|
package/engine.d.ts
CHANGED
package/graph/code-nodes.d.ts
CHANGED
|
@@ -26,17 +26,23 @@ export interface NodeProperty {
|
|
|
26
26
|
export declare const property: (displayName: string, property: string, type: GraphDataType, fillerName?: string, defaultValue?: any) => NodeProperty;
|
|
27
27
|
export declare enum SourceType {
|
|
28
28
|
SHADER_PROGRAM = "Shader Program",
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
FN_BODY_FRAGMENT = "Function Body Fragment",
|
|
30
|
+
EXPRESSION = "Expression"
|
|
31
31
|
}
|
|
32
|
+
export type Backfillers = Record<string, {
|
|
33
|
+
argType: string;
|
|
34
|
+
targetVariable: string;
|
|
35
|
+
}[]>;
|
|
32
36
|
export interface CodeNode extends BaseNode {
|
|
33
37
|
config: NodeConfig;
|
|
38
|
+
type: string;
|
|
34
39
|
engine: boolean;
|
|
35
40
|
source: string;
|
|
36
41
|
sourceType?: SourceType;
|
|
37
42
|
stage?: ShaderStage;
|
|
38
43
|
biStage?: boolean;
|
|
39
44
|
originalEngine?: string;
|
|
45
|
+
backfillers?: Backfillers;
|
|
40
46
|
}
|
|
41
47
|
export interface BinaryNode extends CodeNode {
|
|
42
48
|
operator: string;
|
package/graph/code-nodes.js
CHANGED
|
@@ -13,6 +13,10 @@ export var property = function (displayName, property, type, fillerName, default
|
|
|
13
13
|
export var SourceType;
|
|
14
14
|
(function (SourceType) {
|
|
15
15
|
SourceType["SHADER_PROGRAM"] = "Shader Program";
|
|
16
|
-
|
|
16
|
+
// Function body fragments are parsed, and parsed differently than shader
|
|
17
|
+
// programs. This confuses me all the time. TODO: Remove fn_body_framgent
|
|
18
|
+
// and just try/catch parsing a program, then try fn body fragment?
|
|
17
19
|
SourceType["FN_BODY_FRAGMENT"] = "Function Body Fragment";
|
|
20
|
+
// Expressions are inlined as is
|
|
21
|
+
SourceType["EXPRESSION"] = "Expression";
|
|
18
22
|
})(SourceType || (SourceType = {}));
|
package/graph/context.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type GlslSyntaxError } from '@shaderfrog/glsl-parser';
|
|
2
|
-
import { AstNode, Program } from '@shaderfrog/glsl-parser/ast';
|
|
2
|
+
import { AstNode, FunctionNode, Program } from '@shaderfrog/glsl-parser/ast';
|
|
3
3
|
import { Engine, EngineContext } from '../engine';
|
|
4
4
|
import { NodeInput } from './base-node';
|
|
5
5
|
import { Graph, GraphNode } from './graph-types';
|
|
6
|
-
import { InputFillers } from '
|
|
6
|
+
import { InputFillers } from '../strategy';
|
|
7
7
|
/**
|
|
8
8
|
* A node's context is the runtime / in-memory computed data associated with a
|
|
9
9
|
* graph node. It includes the parsed AST representation of the node, as well as
|
|
@@ -17,6 +17,7 @@ export type NodeContext = {
|
|
|
17
17
|
inputs?: NodeInput[];
|
|
18
18
|
inputFillers: InputFillers;
|
|
19
19
|
errors?: NodeErrors;
|
|
20
|
+
mainFn?: FunctionNode;
|
|
20
21
|
};
|
|
21
22
|
export type NodeErrors = {
|
|
22
23
|
type: 'errors';
|
package/graph/context.js
CHANGED
|
@@ -73,8 +73,9 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
73
73
|
import groupBy from 'lodash.groupby';
|
|
74
74
|
import { mapInputName, SourceType } from './code-nodes';
|
|
75
75
|
import { NodeType } from './graph-types';
|
|
76
|
-
import { collectConnectedNodes, filterGraphFromNode, findLinkedNode, findLinkedVertexNodes, isSourceNode, mangleEntireProgram, } from './graph';
|
|
76
|
+
import { collectConnectedNodes, filterGraphFromNode, findLinkedNode, findLinkedVertexNodes, isSourceNode, mangleEntireProgram, shouldNodeHaveMainFn, } from './graph';
|
|
77
77
|
import { coreParsers } from './parsers';
|
|
78
|
+
import { findMain } from '../util/ast';
|
|
78
79
|
var makeError = function (nodeId) {
|
|
79
80
|
var errors = [];
|
|
80
81
|
for (var _i = 1; _i < arguments.length; _i++) {
|
|
@@ -97,7 +98,7 @@ var collapseNodeInputs = function (node, updatedInputs) {
|
|
|
97
98
|
return Object.values(groupBy(__spreadArray(__spreadArray([], __read(updatedInputs), false), __read(node.inputs), false), function (i) { return i.id; })).map(function (dupes) { return dupes.reduce(function (node, dupe) { return (__assign(__assign({}, node), dupe)); }); });
|
|
98
99
|
};
|
|
99
100
|
var computeNodeContext = function (engineContext, engine, graph, node) { return __awaiter(void 0, void 0, void 0, function () {
|
|
100
|
-
var parser, sibling, onBeforeCompile, manipulateAst, inputEdges, ast, dataInputs, computedInputs, nodeContext;
|
|
101
|
+
var parser, sibling, onBeforeCompile, manipulateAst, inputEdges, mainFn, ast, dataInputs, computedInputs, nodeContext;
|
|
101
102
|
return __generator(this, function (_a) {
|
|
102
103
|
switch (_a.label) {
|
|
103
104
|
case 0:
|
|
@@ -113,6 +114,10 @@ var computeNodeContext = function (engineContext, engine, graph, node) { return
|
|
|
113
114
|
inputEdges = graph.edges.filter(function (edge) { return edge.to === node.id; });
|
|
114
115
|
try {
|
|
115
116
|
ast = parser.produceAst(engineContext, engine, graph, node, inputEdges);
|
|
117
|
+
// Find the main function before mangling
|
|
118
|
+
if (shouldNodeHaveMainFn(node)) {
|
|
119
|
+
mainFn = findMain(ast);
|
|
120
|
+
}
|
|
116
121
|
if (manipulateAst) {
|
|
117
122
|
ast = manipulateAst(engineContext, engine, graph, ast, inputEdges, node, sibling);
|
|
118
123
|
}
|
|
@@ -134,13 +139,20 @@ var computeNodeContext = function (engineContext, engine, graph, node) { return
|
|
|
134
139
|
nodeContext = {
|
|
135
140
|
ast: ast,
|
|
136
141
|
id: node.id,
|
|
142
|
+
mainFn: mainFn,
|
|
137
143
|
inputFillers: computedInputs.reduce(function (acc, _a) {
|
|
138
144
|
var _b;
|
|
139
|
-
var _c = __read(_a,
|
|
140
|
-
|
|
145
|
+
var _c = __read(_a, 4), input = _c[0], filler = _c[1], fillerArgs = _c[2], fillerStmt = _c[3];
|
|
146
|
+
// This is intentionally broken out into an explicit return to force
|
|
147
|
+
// this type declaration. Inlining the object in [input.id]: {...}
|
|
148
|
+
// doesn't force it to be an InputFillerGroup, and it can contain extra
|
|
149
|
+
// arguments by accident
|
|
150
|
+
var fillerGroup = {
|
|
141
151
|
filler: filler,
|
|
142
|
-
|
|
143
|
-
|
|
152
|
+
fillerArgs: fillerArgs,
|
|
153
|
+
fillerStmt: fillerStmt,
|
|
154
|
+
};
|
|
155
|
+
return __assign(__assign({}, acc), (_b = {}, _b[input.id] = fillerGroup, _b));
|
|
144
156
|
}, {}),
|
|
145
157
|
};
|
|
146
158
|
// Skip mangling if the node tells us to, which probably means it's an engine
|
|
@@ -206,7 +218,7 @@ export var computeAllContexts = function (engineContext, engine, graph) { return
|
|
|
206
218
|
* Used to only (re)-compute context for any actively used nodes
|
|
207
219
|
*/
|
|
208
220
|
export var computeGraphContext = function (engineContext, engine, graph) { return __awaiter(void 0, void 0, void 0, function () {
|
|
209
|
-
var outputFrag, outputVert,
|
|
221
|
+
var outputFrag, outputVert, vertexes, fragments, vertexIds, unlinkedNodes, vertNodesOrError, fragNodesOrError;
|
|
210
222
|
return __generator(this, function (_a) {
|
|
211
223
|
switch (_a.label) {
|
|
212
224
|
case 0:
|
|
@@ -218,12 +230,13 @@ export var computeGraphContext = function (engineContext, engine, graph) { retur
|
|
|
218
230
|
if (!outputVert) {
|
|
219
231
|
throw new Error('No vertex output in graph');
|
|
220
232
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
233
|
+
vertexes = collectConnectedNodes(graph, outputVert);
|
|
234
|
+
fragments = collectConnectedNodes(graph, outputFrag);
|
|
235
|
+
vertexIds = new Set(Object.keys(vertexes));
|
|
236
|
+
unlinkedNodes = findLinkedVertexNodes(graph, vertexes);
|
|
224
237
|
return [4 /*yield*/, computeContextForNodes(engineContext, engine, graph, __spreadArray(__spreadArray([
|
|
225
238
|
outputVert
|
|
226
|
-
], __read(Object.values(
|
|
239
|
+
], __read(Object.values(vertexes).filter(function (node) { return node.id !== outputVert.id; })), false), __read(unlinkedNodes), false))];
|
|
227
240
|
case 1:
|
|
228
241
|
vertNodesOrError = _a.sent();
|
|
229
242
|
if (isError(vertNodesOrError)) {
|
|
@@ -231,7 +244,7 @@ export var computeGraphContext = function (engineContext, engine, graph) { retur
|
|
|
231
244
|
}
|
|
232
245
|
return [4 /*yield*/, computeContextForNodes(engineContext, engine, graph, __spreadArray([
|
|
233
246
|
outputFrag
|
|
234
|
-
], __read(Object.values(
|
|
247
|
+
], __read(Object.values(fragments).filter(function (node) { return node.id !== outputFrag.id && !vertexIds.has(node.id); })), false))];
|
|
235
248
|
case 2:
|
|
236
249
|
fragNodesOrError = _a.sent();
|
|
237
250
|
if (isError(fragNodesOrError)) {
|
package/graph/evaluate.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { coreParsers } from './parsers';
|
|
2
2
|
export var toGlsl = function (node) {
|
|
3
3
|
var type = node.type, value = node.value;
|
|
4
|
+
if (type === 'number') {
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
4
7
|
if (type === 'vector2') {
|
|
5
8
|
return "vec2(".concat(value[0], ", ").concat(value[1], ")");
|
|
6
9
|
}
|
|
@@ -10,6 +13,10 @@ export var toGlsl = function (node) {
|
|
|
10
13
|
if (type === 'vector4' || type === 'rgba') {
|
|
11
14
|
return "vec4(".concat(value[0], ", ").concat(value[1], ", ").concat(value[2], ", ").concat(value[3], ")");
|
|
12
15
|
}
|
|
16
|
+
// Right now hard coding that an array is floats. Need type from node later.
|
|
17
|
+
if (type === 'array') {
|
|
18
|
+
return "float[".concat(value.length, "](").concat(value.join(', '), ")");
|
|
19
|
+
}
|
|
13
20
|
throw new Error("Unknown GLSL inline type: \"".concat(node.type, "\""));
|
|
14
21
|
};
|
|
15
22
|
export var evaluateNode = function (engine, graph, node) {
|
package/graph/graph.d.ts
CHANGED
|
@@ -11,16 +11,22 @@ import { ProduceNodeFiller } from './parsers';
|
|
|
11
11
|
import { Graph, GraphNode } from './graph-types';
|
|
12
12
|
export declare const isDataNode: (node: GraphNode) => node is DataNode;
|
|
13
13
|
export declare const isSourceNode: (node: GraphNode) => node is SourceNode;
|
|
14
|
+
/**
|
|
15
|
+
* Determine if a node's source code / AST should have a main function. Essentially
|
|
16
|
+
* check if the source code is a full program or not.
|
|
17
|
+
*/
|
|
18
|
+
export declare const shouldNodeHaveMainFn: (node: GraphNode) => node is SourceNode;
|
|
14
19
|
export declare const findNode: (graph: Graph, id: string) => GraphNode;
|
|
15
20
|
export declare const doesLinkThruShader: (graph: Graph, node: GraphNode) => boolean;
|
|
16
21
|
export declare const nodeName: (node: GraphNode) => string;
|
|
22
|
+
export declare const resultName: (node: GraphNode) => string;
|
|
17
23
|
export declare const mangleName: (name: string, node: GraphNode, nextSibling?: GraphNode) => string;
|
|
18
24
|
export declare const mangleVar: (name: string, engine: Engine, node: GraphNode, sibling?: GraphNode) => string;
|
|
19
25
|
export declare const mangleEntireProgram: (engine: Engine, ast: FrogProgram, node: GraphNode, sibling?: GraphNode) => void;
|
|
20
26
|
export declare const mangleMainFn: (ast: Program, node: GraphNode, sibling?: GraphNode) => void;
|
|
21
|
-
export declare const ensureFromNode: (graph: Graph, inputEdge: Edge) => import("./data-nodes").NumberNode | import("./data-nodes").TextureNode | import("./data-nodes").SamplerCubeNode | import("./data-nodes").ArrayNode | import("./data-nodes").Vector2Node | import("./data-nodes").Vector3Node | import("./data-nodes").Vector4Node | import("./data-nodes").RgbNode | import("./data-nodes").RgbaNode |
|
|
27
|
+
export declare const ensureFromNode: (graph: Graph, inputEdge: Edge) => import("./data-nodes").NumberNode | import("./data-nodes").TextureNode | import("./data-nodes").SamplerCubeNode | import("./data-nodes").ArrayNode | import("./data-nodes").Vector2Node | import("./data-nodes").Vector3Node | import("./data-nodes").Vector4Node | import("./data-nodes").RgbNode | import("./data-nodes").RgbaNode | import("./code-nodes").BinaryNode | CodeNode;
|
|
22
28
|
export declare const resetGraphIds: (graph: Graph) => Graph;
|
|
23
|
-
export declare const findLinkedNode: (graph: Graph, id: string) =>
|
|
29
|
+
export declare const findLinkedNode: (graph: Graph, id: string) => SourceNode | undefined;
|
|
24
30
|
/**
|
|
25
31
|
* Find any unconnected vertex nodes linked to collected fragment nodes
|
|
26
32
|
*/
|
package/graph/graph.js
CHANGED
|
@@ -72,8 +72,8 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
72
72
|
};
|
|
73
73
|
import { renameBindings, renameFunctions, } from '@shaderfrog/glsl-parser/parser/utils';
|
|
74
74
|
import { computeGraphContext, isError, } from './context';
|
|
75
|
-
import {
|
|
76
|
-
import { makeExpression } from '../util/ast';
|
|
75
|
+
import { shaderSectionsCons, findShaderSections, mergeShaderSections, shaderSectionsToProgram, } from './shader-sections';
|
|
76
|
+
import { backfillAst, makeExpression, } from '../util/ast';
|
|
77
77
|
import { ensure } from '../util/ensure';
|
|
78
78
|
import { SourceType } from './code-nodes';
|
|
79
79
|
import { nodeInput } from './base-node';
|
|
@@ -96,6 +96,21 @@ export var isDataNode = function (node) {
|
|
|
96
96
|
export var isSourceNode = function (node) {
|
|
97
97
|
return !isDataNode(node);
|
|
98
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* Determine if a node's source code / AST should have a main function. Essentially
|
|
101
|
+
* check if the source code is a full program or not.
|
|
102
|
+
*/
|
|
103
|
+
export var shouldNodeHaveMainFn = function (node) {
|
|
104
|
+
// Some legacy shaders have an output node that does not have a sourceType,
|
|
105
|
+
// otherwise the sourceType second check would always work
|
|
106
|
+
return node.type === NodeType.OUTPUT ||
|
|
107
|
+
// Same for code nodes :(
|
|
108
|
+
(isSourceNode(node) && !node.sourceType) ||
|
|
109
|
+
node.sourceType === SourceType.SHADER_PROGRAM ||
|
|
110
|
+
// Engine nodes can have rando types like "physical", so if they are engine
|
|
111
|
+
// nodes, assume they have a main fn.
|
|
112
|
+
node.engine;
|
|
113
|
+
};
|
|
99
114
|
export var findNode = function (graph, id) {
|
|
100
115
|
return ensure(graph.nodes.find(function (node) { return node.id === id; }));
|
|
101
116
|
};
|
|
@@ -120,6 +135,7 @@ export var doesLinkThruShader = function (graph, node) {
|
|
|
120
135
|
export var nodeName = function (node) {
|
|
121
136
|
return 'main_' + node.name.replace(/[^a-zA-Z0-9]/g, ' ').replace(/ +/g, '_');
|
|
122
137
|
};
|
|
138
|
+
export var resultName = function (node) { return nodeName(node) + '_out'; };
|
|
123
139
|
export var mangleName = function (name, node, nextSibling) {
|
|
124
140
|
// Mangle a name to its next stage node, so the vertex suffix becomes the
|
|
125
141
|
// fragment id, but not the other way around.
|
|
@@ -160,6 +176,7 @@ export var resetGraphIds = function (graph) {
|
|
|
160
176
|
export var findLinkedNode = function (graph, id) {
|
|
161
177
|
var edgeLink = graph.edges.find(function (e) { return e.type === EdgeLink.NEXT_STAGE && (e.from === id || e.to === id); });
|
|
162
178
|
var otherId = (edgeLink === null || edgeLink === void 0 ? void 0 : edgeLink.from) === id ? edgeLink === null || edgeLink === void 0 ? void 0 : edgeLink.to : edgeLink === null || edgeLink === void 0 ? void 0 : edgeLink.from;
|
|
179
|
+
// Only source nodes can be linked, so cast it
|
|
163
180
|
return graph.nodes.find(function (node) { return node.id === otherId; });
|
|
164
181
|
};
|
|
165
182
|
/**
|
|
@@ -264,10 +281,11 @@ export var isDataInput = function (input) {
|
|
|
264
281
|
return (input.type === 'uniform' || input.type === 'property') && !input.baked;
|
|
265
282
|
};
|
|
266
283
|
export var compileNode = function (engine, graph, edges, engineContext, node, activeIds) {
|
|
267
|
-
var _a
|
|
284
|
+
var _a;
|
|
268
285
|
if (activeIds === void 0) { activeIds = {}; }
|
|
269
286
|
// THIS DUPLICATES OTHER LINE
|
|
270
287
|
var parser = __assign(__assign({}, (coreParsers[node.type] || coreParsers[NodeType.SOURCE])), (engine.parsers[node.type] || {}));
|
|
288
|
+
var codeNode = node;
|
|
271
289
|
var inputs = node.inputs;
|
|
272
290
|
if (!parser) {
|
|
273
291
|
console.error(node);
|
|
@@ -276,135 +294,97 @@ export var compileNode = function (engine, graph, edges, engineContext, node, ac
|
|
|
276
294
|
var nodeContext = isDataNode(node)
|
|
277
295
|
? null
|
|
278
296
|
: ensure(engineContext.nodes[node.id], "No node context found for \"".concat(node.name, "\" (id ").concat(node.id, ")!"));
|
|
279
|
-
var
|
|
297
|
+
var _b = (nodeContext || {}), ast = _b.ast, inputFillers = _b.inputFillers;
|
|
280
298
|
if (!inputs) {
|
|
281
299
|
throw new Error("I'm drunk and I think this case should be impossible");
|
|
282
300
|
}
|
|
283
301
|
var compiledIds = activeIds;
|
|
284
302
|
var inputEdges = edges.filter(function (edge) { return edge.to === node.id; });
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
})
|
|
300
|
-
.join(', '))),
|
|
301
|
-
}); })
|
|
302
|
-
.filter(function (_a) {
|
|
303
|
-
var input = _a.input;
|
|
304
|
-
return !isDataInput(input);
|
|
303
|
+
var continuation = shaderSectionsCons();
|
|
304
|
+
// Compile children recursively
|
|
305
|
+
inputEdges
|
|
306
|
+
.filter(function (edge) { return edge.type !== EdgeLink.NEXT_STAGE; })
|
|
307
|
+
.map(function (edge) { return ({
|
|
308
|
+
edge: edge,
|
|
309
|
+
fromNode: ensure(graph.nodes.find(function (node) { return edge.from === node.id; }), "GraphNode for edge ".concat(edge.from, " not found")),
|
|
310
|
+
input: ensure(inputs.find(function (_a) {
|
|
311
|
+
var id = _a.id;
|
|
312
|
+
return id == edge.input;
|
|
313
|
+
}), "GraphNode \"".concat(node.name, "\"").concat(node.stage ? " (".concat(node.stage, ")") : '', " has no input ").concat(edge.input, "!\nAvailable:").concat(inputs
|
|
314
|
+
.map(function (_a) {
|
|
315
|
+
var id = _a.id;
|
|
316
|
+
return id;
|
|
305
317
|
})
|
|
306
|
-
.
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
//
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
if (fromNode.type === 'source') {
|
|
358
|
-
// @ts-ignore
|
|
359
|
-
fillerAst.args = filler.backfillArgs;
|
|
360
|
-
// const fc = engineContext.nodes[sourceNode.id];
|
|
361
|
-
var fc = engineContext.nodes[fromNode.id];
|
|
362
|
-
var main = Object.values(fc.ast.scopes[0].functions.main)[0].declaration;
|
|
363
|
-
main.prototype.parameters = [
|
|
364
|
-
'vec2 vv',
|
|
365
|
-
];
|
|
366
|
-
// @ts-ignore
|
|
367
|
-
var scope = fc.ast.scopes[0];
|
|
368
|
-
// renameBindings(scope, (name, node) => {
|
|
369
|
-
// return node.type !== 'declaration' && name === 'vUv'
|
|
370
|
-
// ? 'vv'
|
|
371
|
-
// : name;
|
|
372
|
-
// });
|
|
373
|
-
}
|
|
374
|
-
// })
|
|
375
|
-
}
|
|
376
|
-
// Fill in the input! The return value is the new AST of the filled in
|
|
377
|
-
// fromNode.
|
|
378
|
-
nodeContext.ast = filler.filler(fillerAst);
|
|
318
|
+
.join(', '))),
|
|
319
|
+
}); })
|
|
320
|
+
.filter(function (_a) {
|
|
321
|
+
var input = _a.input;
|
|
322
|
+
return !isDataInput(input);
|
|
323
|
+
})
|
|
324
|
+
.forEach(function (_a) {
|
|
325
|
+
var _b, _c;
|
|
326
|
+
var fromNode = _a.fromNode, input = _a.input;
|
|
327
|
+
// const [inputSections, fillerFn, childIds, childDeps] = compileNode(
|
|
328
|
+
var _d = __read(compileNode(engine, graph, edges, engineContext, fromNode, activeIds), 3), inputSections = _d[0], fillerFn = _d[1], childIds = _d[2];
|
|
329
|
+
if (!fillerFn) {
|
|
330
|
+
throw new TypeError("Expected a filler ast from node ID ".concat(fromNode.id, " (").concat(fromNode.type, ") but none was returned"));
|
|
331
|
+
}
|
|
332
|
+
continuation = mergeShaderSections(continuation, inputSections);
|
|
333
|
+
compiledIds = __assign(__assign({}, compiledIds), childIds);
|
|
334
|
+
// Continue on if there's no context I don't know what case causes this
|
|
335
|
+
if (!nodeContext) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
// Produce the input filler
|
|
339
|
+
var filler;
|
|
340
|
+
var fillerName;
|
|
341
|
+
if (input.property) {
|
|
342
|
+
fillerName = ensure((_b = (codeNode.config.properties || []).find(function (p) { return p.property === input.property; })) === null || _b === void 0 ? void 0 : _b.fillerName, "Node \"".concat(node.name, "\" has no property named \"").concat(input.property, "\" to find the filler for"));
|
|
343
|
+
filler = inputFillers[fillerName];
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
filler = inputFillers[input.id];
|
|
347
|
+
}
|
|
348
|
+
if (!filler) {
|
|
349
|
+
console.error('No filler for property', {
|
|
350
|
+
input: input,
|
|
351
|
+
node: node,
|
|
352
|
+
inputFillers: inputFillers,
|
|
353
|
+
fillerName: fillerName,
|
|
354
|
+
});
|
|
355
|
+
throw new Error("Node \"".concat(node.name, "\"").concat(node.stage ? " (".concat(node.stage, ")") : '', " has no filler for input \"").concat(input.displayName, "\" named ").concat(fillerName));
|
|
356
|
+
}
|
|
357
|
+
// Test if it needs to be backfilled - this only goes one level deep
|
|
358
|
+
// because we're only backfilling fromNode
|
|
359
|
+
var backfillers = (_c = codeNode.backfillers) === null || _c === void 0 ? void 0 : _c[input.id];
|
|
360
|
+
if (backfillers && shouldNodeHaveMainFn(fromNode)) {
|
|
361
|
+
var childAst_1 = engineContext.nodes[fromNode.id].ast;
|
|
362
|
+
// For now we can only backfill programs
|
|
363
|
+
if (childAst_1.type === 'program') {
|
|
364
|
+
backfillers.forEach(function (backfiller) {
|
|
365
|
+
// This is where the variable name gets injected into the main
|
|
366
|
+
// function parameter of the backfilled child
|
|
367
|
+
backfillAst(childAst_1, backfiller.argType, backfiller.targetVariable, engineContext.nodes[fromNode.id].mainFn);
|
|
368
|
+
});
|
|
379
369
|
}
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
var sections = isDataNode(node) ||
|
|
399
|
-
node.sourceType === SourceType.EXPRESSION ||
|
|
400
|
-
node.sourceType === SourceType.FN_BODY_FRAGMENT
|
|
401
|
-
? emptyShaderSections()
|
|
402
|
-
: findShaderSections(ast);
|
|
403
|
-
var filler = isDataNode(node)
|
|
404
|
-
? makeExpression(toGlsl(node))
|
|
405
|
-
: parser.produceFiller(node, ast);
|
|
406
|
-
return [sections, filler, __assign(__assign({}, compiledIds), (_b = {}, _b[node.id] = node, _b))];
|
|
407
|
-
}
|
|
370
|
+
nodeContext.ast = filler.filler(fillerFn);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
// Don't backfill by discarding the backfiller args
|
|
374
|
+
nodeContext.ast = filler.filler(function () { return fillerFn(); });
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
// Order matters here! *Prepend* the input nodes to this one, because
|
|
378
|
+
// you have to declare functions in order of use in GLSL
|
|
379
|
+
var sections = mergeShaderSections(continuation, isDataNode(node) ||
|
|
380
|
+
codeNode.sourceType === SourceType.EXPRESSION ||
|
|
381
|
+
codeNode.sourceType === SourceType.FN_BODY_FRAGMENT
|
|
382
|
+
? shaderSectionsCons()
|
|
383
|
+
: findShaderSections(ast));
|
|
384
|
+
var filler = isDataNode(node)
|
|
385
|
+
? function () { return makeExpression(toGlsl(node)); }
|
|
386
|
+
: parser.produceFiller(node, ast);
|
|
387
|
+
return [sections, filler, __assign(__assign({}, compiledIds), (_a = {}, _a[node.id] = node, _a))];
|
|
408
388
|
};
|
|
409
389
|
export var compileGraph = function (engineContext, engine, graph) {
|
|
410
390
|
// computeGraphContext(engineContext, engine, graph);
|