@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/graph/graph.test.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
1
12
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
13
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
14
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -41,12 +52,14 @@ import { generate } from '@shaderfrog/glsl-parser';
|
|
|
41
52
|
import { addNode, outputNode, sourceNode } from './graph-node';
|
|
42
53
|
import { shaderSectionsToProgram, mergeShaderSections, findShaderSections, } from './shader-sections';
|
|
43
54
|
import { numberNode } from './data-nodes';
|
|
44
|
-
import { makeEdge } from './edge';
|
|
55
|
+
import { linkFromVertToFrag, makeEdge } from './edge';
|
|
45
56
|
import { evaluateNode } from './evaluate';
|
|
46
|
-
import { compileSource } from './graph';
|
|
57
|
+
import { compileSource, nodeName } from './graph';
|
|
47
58
|
import { texture2DStrategy } from '../strategy';
|
|
48
59
|
import { isError } from './context';
|
|
49
60
|
import { fail } from '../test-util';
|
|
61
|
+
import { SourceType } from './code-nodes';
|
|
62
|
+
import { makeId } from 'src/util/id';
|
|
50
63
|
var inspect = function (thing) {
|
|
51
64
|
return console.log(util.inspect(thing, false, null, true));
|
|
52
65
|
};
|
|
@@ -65,9 +78,7 @@ var dedupe = function (code) {
|
|
|
65
78
|
includeVersion: true,
|
|
66
79
|
}));
|
|
67
80
|
};
|
|
68
|
-
var counter = 0;
|
|
69
81
|
var p = { x: 0, y: 0 };
|
|
70
|
-
var id = function () { return '' + counter++; };
|
|
71
82
|
var constructor = function () { return ({
|
|
72
83
|
config: {
|
|
73
84
|
version: 3,
|
|
@@ -103,7 +114,7 @@ var engine = {
|
|
|
103
114
|
includeVersion: true,
|
|
104
115
|
},
|
|
105
116
|
importers: {},
|
|
106
|
-
preserve: new Set(),
|
|
117
|
+
preserve: new Set('vUv'),
|
|
107
118
|
parsers: {},
|
|
108
119
|
};
|
|
109
120
|
var makeSourceNode = function (id, source, stage, strategies) {
|
|
@@ -115,45 +126,22 @@ var makeSourceNode = function (id, source, stage, strategies) {
|
|
|
115
126
|
uniforms: [],
|
|
116
127
|
}, source, stage);
|
|
117
128
|
};
|
|
118
|
-
|
|
119
|
-
* What exactly am I doing here?
|
|
120
|
-
*
|
|
121
|
-
* I opened shaderfrog to start looking at the backfilling case and inlining
|
|
122
|
-
* function calls at the top of functions
|
|
123
|
-
*
|
|
124
|
-
* WHie doing that I found jest not to work well anyore and switched to vitest,
|
|
125
|
-
* which is fine, but with esm by default I can't stub the mangleName() function
|
|
126
|
-
* call, which means mangling happens as-is in the tests.
|
|
127
|
-
*
|
|
128
|
-
* Without changing the mangling strategy, the strategies.test.ts file fails
|
|
129
|
-
* because the uniform strategy looks for a mangled variable name, but the
|
|
130
|
-
* program itself isn't mangled.
|
|
131
|
-
*
|
|
132
|
-
* One way to fix this is to make fillers not have to care about mangling names,
|
|
133
|
-
* which would be simpler on the surface.
|
|
134
|
-
*
|
|
135
|
-
* Then everything in the tests broke and you found out the reason why was
|
|
136
|
-
* trying to use scopes to rename things, and most of the ast manipulation steps
|
|
137
|
-
* don't modify scopes, so you made some of them modify scopes, and now things
|
|
138
|
-
* are fucked
|
|
139
|
-
*/
|
|
140
|
-
it('compileSource() fragment produces inlined output', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
129
|
+
it('compileSource() fragment produces inlined output without', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
141
130
|
var outV, outF, imageReplacemMe, input1, input2, graph, engineContext, result, imgOut;
|
|
142
131
|
return __generator(this, function (_a) {
|
|
143
132
|
switch (_a.label) {
|
|
144
133
|
case 0:
|
|
145
|
-
outV = outputNode(
|
|
146
|
-
outF = outputNode(
|
|
147
|
-
imageReplacemMe = makeSourceNode(
|
|
148
|
-
input1 = makeSourceNode(
|
|
149
|
-
input2 = makeSourceNode(
|
|
134
|
+
outV = outputNode(makeId(), 'Output v', p, 'vertex');
|
|
135
|
+
outF = outputNode(makeId(), 'Output f', p, 'fragment');
|
|
136
|
+
imageReplacemMe = makeSourceNode(makeId(), "uniform sampler2D image1;\nuniform sampler2D image2;\nvoid main() {\n vec3 col1 = texture2D(image1, posTurn - 0.4 * time).rgb + 1.0;\n vec3 col2 = texture2D(image2, negTurn - 0.4 * time).rgb + 2.0;\n gl_FragColor = vec4(col1 + col2, 1.0);\n}\n", 'fragment');
|
|
137
|
+
input1 = makeSourceNode(makeId(), "float a = 1.0;\nvoid main() {\n gl_FragColor = vec4(0.0);\n}\n", 'fragment');
|
|
138
|
+
input2 = makeSourceNode(makeId(), "float a = 2.0;\nvoid main() {\n gl_FragColor = vec4(1.0);\n}\n", 'fragment');
|
|
150
139
|
graph = {
|
|
151
140
|
nodes: [outV, outF, imageReplacemMe, input1, input2],
|
|
152
141
|
edges: [
|
|
153
|
-
makeEdge(
|
|
154
|
-
makeEdge(
|
|
155
|
-
makeEdge(
|
|
156
|
-
makeEdge(id(), input2.id, imageReplacemMe.id, 'out', 'filler_image2', 'fragment'),
|
|
142
|
+
makeEdge(makeId(), imageReplacemMe.id, outF.id, 'out', 'filler_frogFragOut', 'fragment'),
|
|
143
|
+
makeEdge(makeId(), input1.id, imageReplacemMe.id, 'out', 'filler_image1', 'fragment'),
|
|
144
|
+
makeEdge(makeId(), input2.id, imageReplacemMe.id, 'out', 'filler_image2', 'fragment'),
|
|
157
145
|
],
|
|
158
146
|
};
|
|
159
147
|
engineContext = {
|
|
@@ -178,18 +166,206 @@ it('compileSource() fragment produces inlined output', function () { return __aw
|
|
|
178
166
|
}
|
|
179
167
|
});
|
|
180
168
|
}); });
|
|
169
|
+
it('compileSource() vertex produces inlined output', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
170
|
+
var outV, outF, vert, graph, engineContext, result, iMainName;
|
|
171
|
+
return __generator(this, function (_a) {
|
|
172
|
+
switch (_a.label) {
|
|
173
|
+
case 0:
|
|
174
|
+
outV = outputNode(makeId(), 'Output v', p, 'vertex');
|
|
175
|
+
outF = outputNode(makeId(), 'Output f', p, 'fragment');
|
|
176
|
+
vert = makeSourceNode(makeId(), "uniform vec4 modelViewMatrix;\nattribute vec3 position;\nfloat a = 2.0;\nvoid main() {\n gl_Position = modelViewMatrix * vec4(position, 1.0);\n}\n", 'vertex');
|
|
177
|
+
graph = {
|
|
178
|
+
nodes: [outV, outF, vert],
|
|
179
|
+
edges: [
|
|
180
|
+
makeEdge(makeId(), vert.id, outV.id, 'out', 'filler_gl_Position', 'vertex'),
|
|
181
|
+
],
|
|
182
|
+
};
|
|
183
|
+
engineContext = {
|
|
184
|
+
engine: 'three',
|
|
185
|
+
nodes: {},
|
|
186
|
+
runtime: {},
|
|
187
|
+
debuggingNonsense: {},
|
|
188
|
+
};
|
|
189
|
+
return [4 /*yield*/, compileSource(graph, engine, engineContext)];
|
|
190
|
+
case 1:
|
|
191
|
+
result = _a.sent();
|
|
192
|
+
if (isError(result)) {
|
|
193
|
+
fail(result);
|
|
194
|
+
}
|
|
195
|
+
iMainName = nodeName(vert);
|
|
196
|
+
expect(result.vertexResult).toContain("\nvoid main() {\n gl_Position = ".concat(iMainName, "();\n}"));
|
|
197
|
+
return [2 /*return*/];
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}); });
|
|
201
|
+
it('compileSource() fragment backfilling one level', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
202
|
+
var outV, outF, imageReplacemMe, input1, graph, engineContext, preserver, result, inputMain, imageMain;
|
|
203
|
+
return __generator(this, function (_a) {
|
|
204
|
+
switch (_a.label) {
|
|
205
|
+
case 0:
|
|
206
|
+
outV = outputNode(makeId(), 'Output v', p, 'vertex');
|
|
207
|
+
outF = outputNode(makeId(), 'Output f', p, 'fragment');
|
|
208
|
+
imageReplacemMe = makeSourceNode(makeId(), "attribute vec2 vUv;\nuniform sampler2D image1;\nuniform sampler2D image2;\nvoid main() {\n vec3 col1 = texture2D(image1, vUv - 0.4 * time).rgb + 1.0;\n vec3 other1 = texture2D(image1, vUv + 1.0).rgb;\n vec3 col2 = texture2D(image2, negTurn - 0.4 * time).rgb + 2.0;\n gl_FragColor = vec4(col1 + col2, 1.0);\n}\n", 'fragment');
|
|
209
|
+
imageReplacemMe.backfillers = {
|
|
210
|
+
filler_image1: [
|
|
211
|
+
{
|
|
212
|
+
argType: 'vec2',
|
|
213
|
+
targetVariable: 'vUv',
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
};
|
|
217
|
+
input1 = makeSourceNode(makeId(), "attribute vec2 vUv;\nvoid main() {\n gl_FragColor = vec4(vUv, 1.0, 1.0);\n}\n", 'fragment');
|
|
218
|
+
graph = {
|
|
219
|
+
nodes: [outV, outF, imageReplacemMe, input1],
|
|
220
|
+
edges: [
|
|
221
|
+
makeEdge(makeId(), imageReplacemMe.id, outF.id, 'out', 'filler_frogFragOut', 'fragment'),
|
|
222
|
+
makeEdge(makeId(), input1.id, imageReplacemMe.id, 'out', 'filler_image1', 'fragment'),
|
|
223
|
+
],
|
|
224
|
+
};
|
|
225
|
+
engineContext = {
|
|
226
|
+
engine: 'three',
|
|
227
|
+
nodes: {},
|
|
228
|
+
runtime: {},
|
|
229
|
+
debuggingNonsense: {},
|
|
230
|
+
};
|
|
231
|
+
preserver = __assign(__assign({}, engine), { preserve: new Set(['vUv']) });
|
|
232
|
+
return [4 /*yield*/, compileSource(graph, preserver, engineContext)];
|
|
233
|
+
case 1:
|
|
234
|
+
result = _a.sent();
|
|
235
|
+
if (isError(result)) {
|
|
236
|
+
fail(result);
|
|
237
|
+
}
|
|
238
|
+
inputMain = nodeName(input1);
|
|
239
|
+
imageMain = nodeName(imageReplacemMe);
|
|
240
|
+
// Should preserve global variable despite backfilling
|
|
241
|
+
expect(result.fragmentResult).toContain("in vec2 vUv;");
|
|
242
|
+
// Backfilled variable should be in the main fn parameters
|
|
243
|
+
// I don't think is inlined? I think this is expected by convertToMain
|
|
244
|
+
expect(result.fragmentResult).toContain("\nvec4 ".concat(inputMain, "(vec2 vUv) {\n frogOut_").concat(input1.id, " = vec4(vUv, 1.0, 1.0);\n return frogOut_").concat(input1.id, ";\n}"));
|
|
245
|
+
// The image function should pass its parameters to the child
|
|
246
|
+
expect(result.fragmentResult).toContain("\nvec4 ".concat(imageMain, "() {\n vec3 col1 = ").concat(inputMain, "(vUv - 0.4 * time).rgb + 1.0;\n vec3 other1 = ").concat(inputMain, "(vUv + 1.0).rgb;\n vec3 col2 = texture(image2"));
|
|
247
|
+
return [2 /*return*/];
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}); });
|
|
251
|
+
it('compileSource() orphaned vertex nodes are called properly in output', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
252
|
+
var outV, outF, vert, frag, graph, engineContext, result, iMainName;
|
|
253
|
+
return __generator(this, function (_a) {
|
|
254
|
+
switch (_a.label) {
|
|
255
|
+
case 0:
|
|
256
|
+
outV = outputNode(makeId(), 'Output v', p, 'vertex');
|
|
257
|
+
outF = outputNode(makeId(), 'Output f', p, 'fragment');
|
|
258
|
+
vert = makeSourceNode(makeId(), "uniform vec4 modelViewMatrix;\nattribute vec3 position;\nfloat a = 2.0;\nvoid main() {\n gl_Position = modelViewMatrix * vec4(position, 1.0);\n}\n", 'vertex');
|
|
259
|
+
frag = makeSourceNode(makeId(), "attribute vec2 vUv;\nvoid main() {\n gl_FragColor = vec4(vUv, 0.0, 1.0);\n}\n", 'fragment');
|
|
260
|
+
graph = {
|
|
261
|
+
nodes: [outV, outF, frag, vert],
|
|
262
|
+
edges: [
|
|
263
|
+
makeEdge(makeId(), frag.id, outF.id, 'out', 'filler_frogFragOut', 'fragment'),
|
|
264
|
+
linkFromVertToFrag(makeId(), vert.id, frag.id),
|
|
265
|
+
],
|
|
266
|
+
};
|
|
267
|
+
engineContext = {
|
|
268
|
+
engine: 'three',
|
|
269
|
+
nodes: {},
|
|
270
|
+
runtime: {},
|
|
271
|
+
debuggingNonsense: {},
|
|
272
|
+
};
|
|
273
|
+
return [4 /*yield*/, compileSource(graph, engine, engineContext)];
|
|
274
|
+
case 1:
|
|
275
|
+
result = _a.sent();
|
|
276
|
+
if (isError(result)) {
|
|
277
|
+
fail(result);
|
|
278
|
+
}
|
|
279
|
+
iMainName = nodeName(vert);
|
|
280
|
+
expect(result.vertexResult).toContain("\nvoid main() {\n ".concat(iMainName, "();\n gl_Position = vec4(1.0);\n}"));
|
|
281
|
+
return [2 /*return*/];
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}); });
|
|
285
|
+
it('compileSource() inlining a fragment expression', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
286
|
+
var outV, outF, imageReplacemMe, input, graph, engineContext, result;
|
|
287
|
+
return __generator(this, function (_a) {
|
|
288
|
+
switch (_a.label) {
|
|
289
|
+
case 0:
|
|
290
|
+
outV = outputNode(makeId(), 'Output v', p, 'vertex');
|
|
291
|
+
outF = outputNode(makeId(), 'Output f', p, 'fragment');
|
|
292
|
+
imageReplacemMe = makeSourceNode(makeId(), "uniform sampler2D image1;\nvoid main() {\n vec3 col1 = texture2D(image1, posTurn - 0.4 * time).rgb + 1.0;\n gl_FragColor = vec4(col1, 1.0);\n}\n", 'fragment');
|
|
293
|
+
input = makeSourceNode(makeId(), "vec4(1.0)", 'fragment');
|
|
294
|
+
input.sourceType = SourceType.EXPRESSION;
|
|
295
|
+
graph = {
|
|
296
|
+
nodes: [outV, outF, imageReplacemMe, input],
|
|
297
|
+
edges: [
|
|
298
|
+
makeEdge(makeId(), imageReplacemMe.id, outF.id, 'out', 'filler_frogFragOut', 'fragment'),
|
|
299
|
+
makeEdge(makeId(), input.id, imageReplacemMe.id, 'out', 'filler_image1', 'fragment'),
|
|
300
|
+
],
|
|
301
|
+
};
|
|
302
|
+
engineContext = {
|
|
303
|
+
engine: 'three',
|
|
304
|
+
nodes: {},
|
|
305
|
+
runtime: {},
|
|
306
|
+
debuggingNonsense: {},
|
|
307
|
+
};
|
|
308
|
+
return [4 /*yield*/, compileSource(graph, engine, engineContext)];
|
|
309
|
+
case 1:
|
|
310
|
+
result = _a.sent();
|
|
311
|
+
if (isError(result)) {
|
|
312
|
+
fail(result);
|
|
313
|
+
}
|
|
314
|
+
// Verify it inlined the expression and did not memoize the source into a
|
|
315
|
+
// varaible
|
|
316
|
+
expect(result.fragmentResult).toContain("vec4 ".concat(nodeName(imageReplacemMe), "() {\n vec3 col1 = vec4(1.0).rgb + 1.0;"));
|
|
317
|
+
return [2 /*return*/];
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}); });
|
|
321
|
+
it('compileSource() binary properly inlines dependencies', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
322
|
+
var outV, outF, color, expr, add, graph, engineContext, result;
|
|
323
|
+
return __generator(this, function (_a) {
|
|
324
|
+
switch (_a.label) {
|
|
325
|
+
case 0:
|
|
326
|
+
outV = outputNode(makeId(), 'Output v', p, 'vertex');
|
|
327
|
+
outF = outputNode(makeId(), 'Output f', p, 'fragment');
|
|
328
|
+
color = makeSourceNode(makeId(), "uniform sampler2D image;\nvoid main() {\n vec3 col = texture2D(image, vec2(0.0)).rgb;\n gl_FragColor = vec4(col, 1.0);\n}\n", 'fragment');
|
|
329
|
+
expr = makeSourceNode(makeId(), "vec4(1.0)", 'fragment');
|
|
330
|
+
expr.sourceType = SourceType.EXPRESSION;
|
|
331
|
+
add = addNode(makeId(), p);
|
|
332
|
+
graph = {
|
|
333
|
+
nodes: [color, expr, add, outV, outF],
|
|
334
|
+
edges: [
|
|
335
|
+
makeEdge(makeId(), color.id, add.id, 'out', 'a'),
|
|
336
|
+
makeEdge(makeId(), expr.id, add.id, 'out', 'b'),
|
|
337
|
+
makeEdge(makeId(), add.id, outF.id, 'out', 'filler_frogFragOut', 'fragment'),
|
|
338
|
+
],
|
|
339
|
+
};
|
|
340
|
+
engineContext = {
|
|
341
|
+
engine: 'three',
|
|
342
|
+
nodes: {},
|
|
343
|
+
runtime: {},
|
|
344
|
+
debuggingNonsense: {},
|
|
345
|
+
};
|
|
346
|
+
return [4 /*yield*/, compileSource(graph, engine, engineContext)];
|
|
347
|
+
case 1:
|
|
348
|
+
result = _a.sent();
|
|
349
|
+
if (isError(result)) {
|
|
350
|
+
fail(result);
|
|
351
|
+
}
|
|
352
|
+
expect(result.fragmentResult).toContain("void main() {\n frogFragOut = (".concat(nodeName(color), "()+ vec4(1.0));\n}"));
|
|
353
|
+
return [2 /*return*/];
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}); });
|
|
181
357
|
it('compileSource() base case', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
182
358
|
var outV, outF, imageReplacemMe, graph, engineContext, result, imgOut;
|
|
183
359
|
return __generator(this, function (_a) {
|
|
184
360
|
switch (_a.label) {
|
|
185
361
|
case 0:
|
|
186
|
-
outV = outputNode(
|
|
187
|
-
outF = outputNode(
|
|
188
|
-
imageReplacemMe = makeSourceNode(
|
|
362
|
+
outV = outputNode(makeId(), 'Output v', p, 'vertex');
|
|
363
|
+
outF = outputNode(makeId(), 'Output f', p, 'fragment');
|
|
364
|
+
imageReplacemMe = makeSourceNode(makeId(), "float a = 1.0;\nvoid main() {\n gl_FragColor = vec4(1.0);\n}\n", 'fragment');
|
|
189
365
|
graph = {
|
|
190
366
|
nodes: [outV, outF, imageReplacemMe],
|
|
191
367
|
edges: [
|
|
192
|
-
makeEdge(
|
|
368
|
+
makeEdge(makeId(), imageReplacemMe.id, outF.id, 'out', 'filler_frogFragOut', 'fragment'),
|
|
193
369
|
],
|
|
194
370
|
};
|
|
195
371
|
engineContext = {
|
|
@@ -214,18 +390,18 @@ it('compileSource() base case', function () { return __awaiter(void 0, void 0, v
|
|
|
214
390
|
}); });
|
|
215
391
|
describe('evaluateNode()', function () {
|
|
216
392
|
it('evaluates binary nodes', function () {
|
|
217
|
-
var finalAdd = addNode(
|
|
218
|
-
var add2 = addNode(
|
|
219
|
-
var num1 = numberNode(
|
|
220
|
-
var num2 = numberNode(
|
|
221
|
-
var num3 = numberNode(
|
|
393
|
+
var finalAdd = addNode(makeId(), p);
|
|
394
|
+
var add2 = addNode(makeId(), p);
|
|
395
|
+
var num1 = numberNode(makeId(), 'number', p, '3');
|
|
396
|
+
var num2 = numberNode(makeId(), 'number', p, '5');
|
|
397
|
+
var num3 = numberNode(makeId(), 'number', p, '7');
|
|
222
398
|
var graph = {
|
|
223
399
|
nodes: [num1, num2, num3, finalAdd, add2],
|
|
224
400
|
edges: [
|
|
225
|
-
makeEdge(
|
|
226
|
-
makeEdge(
|
|
227
|
-
makeEdge(
|
|
228
|
-
makeEdge(
|
|
401
|
+
makeEdge(makeId(), num1.id, finalAdd.id, 'out', 'a'),
|
|
402
|
+
makeEdge(makeId(), add2.id, finalAdd.id, 'out', 'b'),
|
|
403
|
+
makeEdge(makeId(), num2.id, add2.id, 'out', 'a'),
|
|
404
|
+
makeEdge(makeId(), num3.id, add2.id, 'out', 'b'),
|
|
229
405
|
],
|
|
230
406
|
};
|
|
231
407
|
expect(evaluateNode(engine, graph, finalAdd)).toBe(15);
|
package/graph/parsers.d.ts
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
import { AstNode, Program } from '@shaderfrog/glsl-parser/ast';
|
|
2
2
|
import { Engine, EngineContext } from '../engine';
|
|
3
|
+
import { ComputedInput, Filler } from '../strategy';
|
|
3
4
|
import { Edge } from './edge';
|
|
4
5
|
import { SourceNode } from './code-nodes';
|
|
5
|
-
import { NodeInput } from './base-node';
|
|
6
6
|
import { Graph } from './graph-types';
|
|
7
7
|
import { Evaluate } from './evaluate';
|
|
8
8
|
export declare const alphabet = "abcdefghijklmnopqrstuvwxyz";
|
|
9
|
-
export type Filler = AstNode | AstNode[] | void;
|
|
10
|
-
export type InputFiller = (filler: Filler) => AstNode | Program;
|
|
11
|
-
export type InputFillerGroup = {
|
|
12
|
-
filler: InputFiller;
|
|
13
|
-
backfillArgs?: AstNode[];
|
|
14
|
-
};
|
|
15
|
-
export type InputFillers = Record<string, InputFillerGroup>;
|
|
16
|
-
type FillerArguments = AstNode[];
|
|
17
|
-
export type ComputedInput = [NodeInput, InputFiller, FillerArguments?];
|
|
18
9
|
export type ProduceAst = (engineContext: EngineContext, engine: Engine, graph: Graph, node: SourceNode, inputEdges: Edge[]) => AstNode | Program;
|
|
19
10
|
export type OnBeforeCompile = (graph: Graph, engineContext: EngineContext, node: SourceNode, sibling?: SourceNode) => Promise<void>;
|
|
20
11
|
export type ManipulateAst = (engineContext: EngineContext, engine: Engine, graph: Graph, ast: AstNode | Program, inputEdges: Edge[], node: SourceNode, sibling: SourceNode) => AstNode | Program;
|
|
@@ -24,7 +15,7 @@ export type NodeParser = {
|
|
|
24
15
|
findInputs?: FindInputs;
|
|
25
16
|
produceFiller?: ProduceNodeFiller;
|
|
26
17
|
};
|
|
27
|
-
export type FindInputs = (engineContext: EngineContext, ast: Program | AstNode, inputEdges: Edge[], node: SourceNode, sibling
|
|
18
|
+
export type FindInputs = (engineContext: EngineContext, ast: Program | AstNode, inputEdges: Edge[], node: SourceNode, sibling?: SourceNode) => ComputedInput[];
|
|
28
19
|
export type ProduceNodeFiller = (node: SourceNode, ast: Program | AstNode) => Filler;
|
|
29
20
|
type CoreNodeParser = {
|
|
30
21
|
produceAst: ProduceAst;
|
package/graph/parsers.js
CHANGED
|
@@ -27,13 +27,14 @@ var _a;
|
|
|
27
27
|
import { parser } from '@shaderfrog/glsl-parser';
|
|
28
28
|
import { visit, } from '@shaderfrog/glsl-parser/ast';
|
|
29
29
|
import preprocess from '@shaderfrog/glsl-parser/preprocessor';
|
|
30
|
-
import { convert300MainToReturn, from2To3, makeExpression, makeExpressionWithScopes, makeFnBodyStatementWithScopes,
|
|
30
|
+
import { convert300MainToReturn, findMainOrThrow, from2To3, makeExpression, makeExpressionWithScopes, makeFnBodyStatementWithScopes, } from '../util/ast';
|
|
31
31
|
import { applyStrategy } from '../strategy';
|
|
32
32
|
import { SourceType } from './code-nodes';
|
|
33
33
|
import { nodeInput } from './base-node';
|
|
34
34
|
import { MAGIC_OUTPUT_STMTS, NodeType } from './graph-types';
|
|
35
35
|
import { nodeName } from './graph';
|
|
36
36
|
import { generateFiller } from '../util/ast';
|
|
37
|
+
import { unshiftFnStmtWithIndent } from '../util/whitespace';
|
|
37
38
|
/*
|
|
38
39
|
* Core graph parsers, which is the plumbing/interface the graph and context
|
|
39
40
|
* calls into, to parse, find inputs, etc, and define this per-node type.
|
|
@@ -109,11 +110,20 @@ export var coreParsers = (_a = {},
|
|
|
109
110
|
});
|
|
110
111
|
},
|
|
111
112
|
produceFiller: function (node, ast) {
|
|
112
|
-
return
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
return function () {
|
|
114
|
+
var args = [];
|
|
115
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
116
|
+
args[_i] = arguments[_i];
|
|
117
|
+
}
|
|
118
|
+
var fillerNode = node.sourceType === SourceType.EXPRESSION
|
|
119
|
+
? ast.program[0]
|
|
120
|
+
: node.sourceType === SourceType.FN_BODY_FRAGMENT
|
|
121
|
+
? ast.program
|
|
122
|
+
: // Backfilling into the call of this program's filler.
|
|
123
|
+
// Similar to texutre2D.ts filler
|
|
124
|
+
makeExpression("".concat(nodeName(node), "(").concat(args.join(', '), ")"));
|
|
125
|
+
return fillerNode;
|
|
126
|
+
};
|
|
117
127
|
},
|
|
118
128
|
},
|
|
119
129
|
// TODO: Output node assumes strategies are still passed in on node creation,
|
|
@@ -128,16 +138,16 @@ export var coreParsers = (_a = {},
|
|
|
128
138
|
})), false), [
|
|
129
139
|
[
|
|
130
140
|
nodeInput(MAGIC_OUTPUT_STMTS, "filler_".concat(MAGIC_OUTPUT_STMTS), 'filler', 'rgba', ['code'], false),
|
|
131
|
-
function (
|
|
132
|
-
var
|
|
133
|
-
|
|
141
|
+
function (filler) {
|
|
142
|
+
var main = findMainOrThrow(ast);
|
|
143
|
+
main.body.statements = unshiftFnStmtWithIndent(main, generateFiller(filler()));
|
|
134
144
|
return ast;
|
|
135
145
|
},
|
|
136
146
|
],
|
|
137
147
|
], false);
|
|
138
148
|
},
|
|
139
149
|
produceFiller: function (node, ast) {
|
|
140
|
-
return makeExpression('impossible_call()');
|
|
150
|
+
return function () { return makeExpression('impossible_call()'); };
|
|
141
151
|
},
|
|
142
152
|
},
|
|
143
153
|
_a[NodeType.BINARY] = {
|
|
@@ -158,7 +168,7 @@ export var coreParsers = (_a = {},
|
|
|
158
168
|
var letter = alphabet.charAt(index);
|
|
159
169
|
return [
|
|
160
170
|
nodeInput(letter, letter, 'filler', undefined, ['data', 'code'], false),
|
|
161
|
-
function (
|
|
171
|
+
function (filler) {
|
|
162
172
|
var foundPath;
|
|
163
173
|
var visitors = {
|
|
164
174
|
identifier: {
|
|
@@ -175,18 +185,18 @@ export var coreParsers = (_a = {},
|
|
|
175
185
|
}
|
|
176
186
|
if (foundPath.parent && foundPath.key) {
|
|
177
187
|
// @ts-ignore
|
|
178
|
-
foundPath.parent[foundPath.key] =
|
|
188
|
+
foundPath.parent[foundPath.key] = filler();
|
|
179
189
|
return ast;
|
|
180
190
|
}
|
|
181
191
|
else {
|
|
182
|
-
return
|
|
192
|
+
return filler();
|
|
183
193
|
}
|
|
184
194
|
},
|
|
185
195
|
];
|
|
186
196
|
});
|
|
187
197
|
},
|
|
188
198
|
produceFiller: function (node, ast) {
|
|
189
|
-
return ast;
|
|
199
|
+
return function () { return ast; };
|
|
190
200
|
},
|
|
191
201
|
evaluate: function (node, inputEdges, inputNodes, evaluateNode) {
|
|
192
202
|
var operator = node.operator;
|
|
@@ -13,7 +13,7 @@ export interface ShaderSections {
|
|
|
13
13
|
uniforms: DeclarationStatementNode[];
|
|
14
14
|
program: AstNode[];
|
|
15
15
|
}
|
|
16
|
-
export declare const
|
|
16
|
+
export declare const shaderSectionsCons: () => ShaderSections;
|
|
17
17
|
declare enum Precision {
|
|
18
18
|
highp = 2,
|
|
19
19
|
mediump = 1,
|
package/graph/shader-sections.js
CHANGED
|
@@ -36,7 +36,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
36
36
|
};
|
|
37
37
|
import { generate } from '@shaderfrog/glsl-parser';
|
|
38
38
|
import { makeStatement } from '../util/ast';
|
|
39
|
-
export var
|
|
39
|
+
export var shaderSectionsCons = function () { return ({
|
|
40
40
|
precision: [],
|
|
41
41
|
preprocessor: [],
|
|
42
42
|
version: [],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shaderfrog/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Shaderfrog core",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
"@babel/core": "^7.21.8",
|
|
35
35
|
"@babel/preset-env": "^7.21.5",
|
|
36
36
|
"@babel/preset-typescript": "^7.21.5",
|
|
37
|
-
"@shaderfrog/glsl-parser": "^5.
|
|
37
|
+
"@shaderfrog/glsl-parser": "^5.2.0",
|
|
38
38
|
"@swc/core": "^1.6.7",
|
|
39
39
|
"@types/lodash.groupby": "^4.6.7",
|
|
40
|
-
"@types/three": "^0.
|
|
40
|
+
"@types/three": "^0.169.0",
|
|
41
41
|
"babylonjs": "^6.2.0",
|
|
42
42
|
"prettier": "^3.3.2",
|
|
43
|
-
"three": "^0.
|
|
43
|
+
"three": "^0.169.0",
|
|
44
44
|
"typescript": "^5.5.3",
|
|
45
45
|
"vitest": "^1.6.0"
|
|
46
46
|
},
|
|
@@ -531,7 +531,6 @@ export var babylengine = {
|
|
|
531
531
|
'normal',
|
|
532
532
|
'uv',
|
|
533
533
|
'world',
|
|
534
|
-
'time',
|
|
535
534
|
'Light0',
|
|
536
535
|
'Light1',
|
|
537
536
|
'Light2',
|
|
@@ -555,6 +554,10 @@ export var babylengine = {
|
|
|
555
554
|
'vSphericalL22',
|
|
556
555
|
'vAlbedoInfos',
|
|
557
556
|
'reflectionSampler',
|
|
557
|
+
// passed by shaderfrog. maybe should have separate names? duplicated across
|
|
558
|
+
// all the engines.
|
|
559
|
+
'time',
|
|
560
|
+
'renderResolution',
|
|
558
561
|
]),
|
|
559
562
|
parsers: (_b = {},
|
|
560
563
|
_b[NodeType.SOURCE] = {
|
|
@@ -472,7 +472,6 @@ export var playengine = {
|
|
|
472
472
|
'matrix_normal',
|
|
473
473
|
'matrix_view',
|
|
474
474
|
'matrix_viewProjection',
|
|
475
|
-
'time',
|
|
476
475
|
'vertex_color',
|
|
477
476
|
'vertex_normal',
|
|
478
477
|
'vertex_position',
|
|
@@ -483,6 +482,10 @@ export var playengine = {
|
|
|
483
482
|
'vNormalW',
|
|
484
483
|
'vPositionW',
|
|
485
484
|
'vUv0',
|
|
485
|
+
// passed by shaderfrog. maybe should have separate names? duplicated across
|
|
486
|
+
// all the engines.
|
|
487
|
+
'time',
|
|
488
|
+
'renderResolution',
|
|
486
489
|
]),
|
|
487
490
|
parsers: (_b = {},
|
|
488
491
|
_b[NodeType.SOURCE] = {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { EngineImporters } from '../../engine';
|
|
2
|
+
export declare const defaultShadertoyVertex = "\nprecision highp float;\nprecision highp int;\n\nattribute vec3 position;\nattribute vec2 uv;\nvarying vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position * 2.0, 1.0);\n}\n";
|
|
2
3
|
declare const importers: EngineImporters;
|
|
3
4
|
export default importers;
|
|
@@ -1,5 +1,53 @@
|
|
|
1
|
-
import { renameBindings } from '@shaderfrog/glsl-parser/parser/utils';
|
|
1
|
+
import { renameBindings, renameFunction, } from '@shaderfrog/glsl-parser/parser/utils';
|
|
2
|
+
import { findMainOrThrow, makeStatement } from '../../util/ast';
|
|
3
|
+
export var defaultShadertoyVertex = "\nprecision highp float;\nprecision highp int;\n\nattribute vec3 position;\nattribute vec2 uv;\nvarying vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position * 2.0, 1.0);\n}\n";
|
|
2
4
|
var importers = {
|
|
5
|
+
shadertoy: {
|
|
6
|
+
code: {
|
|
7
|
+
defaultShadertoyVertex: defaultShadertoyVertex,
|
|
8
|
+
},
|
|
9
|
+
convertAst: function (ast, type) {
|
|
10
|
+
ast.program.unshift(makeStatement('uniform vec2 renderResolution', '\n')[0]);
|
|
11
|
+
// These do not catch variables in preprocessor definitions! See "SAD HACK"
|
|
12
|
+
//if (ast.scopes.some((s) => 'iTime' in s.bindings)) {
|
|
13
|
+
ast.program.unshift(makeStatement('uniform float time')[0]);
|
|
14
|
+
//}
|
|
15
|
+
//if (ast.scopes.some((s) => 'iMouse' in s.bindings)) {
|
|
16
|
+
ast.program.unshift(makeStatement('uniform vec2 mouse')[0]);
|
|
17
|
+
//}
|
|
18
|
+
ast.program.unshift(makeStatement('precision highp int', '\n')[0]);
|
|
19
|
+
ast.program.unshift(makeStatement('precision highp float')[0]);
|
|
20
|
+
ast.scopes[0].functions.main = renameFunction(ast.scopes[0].functions.mainImage, 'main');
|
|
21
|
+
var main = findMainOrThrow(ast);
|
|
22
|
+
main.prototype.parameters = [];
|
|
23
|
+
main.prototype.header.lp.whitespace = '';
|
|
24
|
+
main.prototype.rp.whitespace = ' ';
|
|
25
|
+
// These renames do not catch variables in preprocessor definitions! See
|
|
26
|
+
// "SAD HACK" comment in Editor.tsx
|
|
27
|
+
for (var i = 0; i < ast.scopes.length; i++) {
|
|
28
|
+
ast.scopes[i].bindings = renameBindings(ast.scopes[i].bindings, function (name) {
|
|
29
|
+
if (name === 'iTime') {
|
|
30
|
+
return 'time';
|
|
31
|
+
}
|
|
32
|
+
if (name === 'iMouse') {
|
|
33
|
+
return 'mouse';
|
|
34
|
+
}
|
|
35
|
+
if (name === 'iResolution') {
|
|
36
|
+
return 'renderResolution';
|
|
37
|
+
}
|
|
38
|
+
if (name === 'fragColor') {
|
|
39
|
+
return 'gl_FragColor';
|
|
40
|
+
}
|
|
41
|
+
if (name === 'fragCoord') {
|
|
42
|
+
return 'gl_FragCoord.xy';
|
|
43
|
+
}
|
|
44
|
+
return name;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
nodeInputMap: {},
|
|
49
|
+
edgeMap: {},
|
|
50
|
+
},
|
|
3
51
|
babylon: {
|
|
4
52
|
convertAst: function (ast, type) {
|
|
5
53
|
ast.scopes[0].bindings = renameBindings(ast.scopes[0].bindings, function (name) {
|
|
@@ -460,7 +460,6 @@ export var threngine = {
|
|
|
460
460
|
'opacity',
|
|
461
461
|
'map',
|
|
462
462
|
'specularTint',
|
|
463
|
-
'time',
|
|
464
463
|
'normalScale',
|
|
465
464
|
'normalMap',
|
|
466
465
|
'envMap',
|
|
@@ -502,6 +501,10 @@ export var threngine = {
|
|
|
502
501
|
'displacementMap',
|
|
503
502
|
'displacementScale',
|
|
504
503
|
'displacementBias',
|
|
504
|
+
// passed by shaderfrog. maybe should have separate names? duplicated across
|
|
505
|
+
// all the engines.
|
|
506
|
+
'time',
|
|
507
|
+
'renderResolution',
|
|
505
508
|
]),
|
|
506
509
|
parsers: (_b = {},
|
|
507
510
|
_b[NodeType.SOURCE] = {
|
|
@@ -561,7 +564,7 @@ export var threngine = {
|
|
|
561
564
|
};
|
|
562
565
|
export var createMaterial = function (compileResult, ctx) {
|
|
563
566
|
var engineMaterial = ctx.runtime.engineMaterial;
|
|
564
|
-
var finalUniforms = __assign(__assign(__assign(__assign({}, ShaderLib.phong.uniforms), ShaderLib.toon.uniforms), ShaderLib.physical.uniforms), { time: { value: 0 }, cameraPosition: { value: new Vector3(1.0) } });
|
|
567
|
+
var finalUniforms = __assign(__assign(__assign(__assign({}, ShaderLib.phong.uniforms), ShaderLib.toon.uniforms), ShaderLib.physical.uniforms), { time: { value: 0 }, cameraPosition: { value: new Vector3(1.0) }, renderResolution: { value: new Vector2(1.0) } });
|
|
565
568
|
// Also the ThreeComponent's sceneConfig properties modify the material
|
|
566
569
|
var initialProperties = {
|
|
567
570
|
name: 'ShaderFrog Material',
|