@luma.gl/shaders 10.0.0-alpha.5 → 10.0.0-alpha.7
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/LICENSE +38 -0
- package/dist/dist.dev.js +159 -127
- package/dist/dist.min.js +110 -105
- package/dist/glsl.cjs.map +1 -1
- package/dist/index.cjs.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/glsl-shader-assembler.cjs +1 -1
- package/dist/lib/glsl-shader-assembler.js +1 -1
- package/dist/lib/glsl-shader-assembler.js.map +1 -1
- package/dist/lib/preprocessor/preprocessor.cjs +21 -0
- package/dist/lib/preprocessor/preprocessor.js +21 -0
- package/dist/lib/preprocessor/preprocessor.js.map +1 -1
- package/dist/lib/shader-assembly/assemble-glsl-shaders.cjs +11 -19
- package/dist/lib/shader-assembly/assemble-glsl-shaders.d.ts +2 -2
- package/dist/lib/shader-assembly/assemble-glsl-shaders.d.ts.map +1 -1
- package/dist/lib/shader-assembly/assemble-glsl-shaders.js +12 -20
- package/dist/lib/shader-assembly/assemble-glsl-shaders.js.map +1 -1
- package/dist/lib/shader-assembly/assemble-wgsl-shaders.cjs +6 -6
- package/dist/lib/shader-assembly/assemble-wgsl-shaders.js +7 -7
- package/dist/lib/shader-assembly/assemble-wgsl-shaders.js.map +1 -1
- package/dist/lib/shader-assembly/shader-assembly-types.d.ts +7 -7
- package/dist/lib/shader-assembly/shader-assembly-types.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.cjs +4 -1
- package/dist/lib/shader-assembly/shader-hooks.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.js +4 -1
- package/dist/lib/shader-assembly/shader-hooks.js.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.d.ts +2 -0
- package/dist/lib/shader-assembly/shader-injections.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.js.map +1 -1
- package/dist/lib/shader-assembly/shader-plugin-varyings.cjs +39 -22
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts +5 -5
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-plugin-varyings.js +45 -19
- package/dist/lib/shader-assembly/shader-plugin-varyings.js.map +1 -1
- package/dist/lib/shader-generator/glsl/generate-glsl.d.ts +1 -1
- package/dist/lib/shader-generator/glsl/generate-glsl.d.ts.map +1 -1
- package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts +1 -1
- package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts.map +1 -1
- package/dist/lib/shader-plugin.cjs +44 -30
- package/dist/lib/shader-plugin.d.ts +33 -32
- package/dist/lib/shader-plugin.d.ts.map +1 -1
- package/dist/lib/shader-plugin.js +49 -31
- package/dist/lib/shader-plugin.js.map +1 -1
- package/dist/lib/wgsl-shader-assembler.cjs +1 -1
- package/dist/lib/wgsl-shader-assembler.js +1 -1
- package/dist/lib/wgsl-shader-assembler.js.map +1 -1
- package/dist/modules/engine/clip/clip.cjs +18 -30
- package/dist/modules/engine/clip/clip.d.ts.map +1 -1
- package/dist/modules/engine/clip/clip.js +19 -31
- package/dist/modules/engine/clip/clip.js.map +1 -1
- package/dist/modules/engine/filter/filter.cjs +9 -18
- package/dist/modules/engine/filter/filter.d.ts.map +1 -1
- package/dist/modules/engine/filter/filter.js +9 -18
- package/dist/modules/engine/filter/filter.js.map +1 -1
- package/dist/modules/math/fp64/fp64.cjs +1 -1
- package/dist/modules/math/fp64/fp64.d.ts +1 -1
- package/dist/modules/math/fp64/fp64.d.ts.map +1 -1
- package/dist/modules/math/fp64/fp64.js +1 -1
- package/dist/modules/math/fp64/fp64.js.map +1 -1
- package/dist/types.cjs +27 -16
- package/dist/types.d.ts +7 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -7
- package/dist/types.js.map +1 -1
- package/dist/wgsl.cjs +20 -4
- package/dist/wgsl.cjs.map +1 -1
- package/dist/wgsl.d.ts +1 -1
- package/dist/wgsl.d.ts.map +1 -1
- package/dist/wgsl.js +1 -1
- package/dist/wgsl.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +3 -4
- package/src/lib/glsl-shader-assembler.ts +1 -1
- package/src/lib/preprocessor/preprocessor.ts +25 -0
- package/src/lib/shader-assembly/assemble-glsl-shaders.ts +17 -22
- package/src/lib/shader-assembly/assemble-wgsl-shaders.ts +8 -8
- package/src/lib/shader-assembly/shader-assembly-types.ts +7 -7
- package/src/lib/shader-assembly/shader-hooks.ts +6 -1
- package/src/lib/shader-assembly/shader-injections.ts +2 -0
- package/src/lib/shader-assembly/shader-plugin-varyings.ts +58 -27
- package/src/lib/shader-generator/glsl/generate-glsl.ts +1 -1
- package/src/lib/shader-generator/wgsl/generate-wgsl.ts +1 -1
- package/src/lib/shader-module/shader-module-dependencies.ts +1 -1
- package/src/lib/shader-plugin.ts +75 -68
- package/src/lib/wgsl-shader-assembler.ts +1 -1
- package/src/modules/engine/clip/clip.ts +19 -31
- package/src/modules/engine/filter/filter.ts +9 -18
- package/src/modules/math/fp64/fp64.ts +1 -1
- package/src/types.ts +75 -7
- package/src/wgsl.ts +12 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
luma.gl is provided under the MIT license
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 vis.gl contributors
|
|
4
|
+
|
|
5
|
+
This software includes parts initially developed by Uber and open sourced under MIT license.
|
|
6
|
+
Copyright (c) 2015 Uber Technologies, Inc.
|
|
7
|
+
|
|
8
|
+
This software includes parts of PhiloGL (https://github.com/philogb/philogl)
|
|
9
|
+
under MIT license. PhiloGL parts Copyright © 2013 Sencha Labs.
|
|
10
|
+
|
|
11
|
+
This software includes adaptations of some postprocessing code from
|
|
12
|
+
THREE.js (https://github.com/mrdoob/three.js/) under MIT license.
|
|
13
|
+
THREE.js parts Copyright © 2010-2018 three.js authors.
|
|
14
|
+
|
|
15
|
+
This software includes adaptations of Gaussian-splat rendering and
|
|
16
|
+
level-of-detail behavior from Spark (https://github.com/sparkjsdev/spark)
|
|
17
|
+
under MIT license.
|
|
18
|
+
Spark parts Copyright © 2025 WORLD LABS TECHNOLOGIES, INC.
|
|
19
|
+
|
|
20
|
+
Additional attribution given in specific source files.
|
|
21
|
+
|
|
22
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
23
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
24
|
+
in the Software without restriction, including without limitation the rights
|
|
25
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
26
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
27
|
+
furnished to do so, subject to the following conditions:
|
|
28
|
+
|
|
29
|
+
The above copyright notice and this permission notice shall be included in
|
|
30
|
+
all copies or substantial portions of the Software.
|
|
31
|
+
|
|
32
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
33
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
34
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
35
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
36
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
37
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
38
|
+
THE SOFTWARE.
|
package/dist/dist.dev.js
CHANGED
|
@@ -1384,47 +1384,52 @@ ${fragmentString}${source7.slice(insertionIndex)}`;
|
|
|
1384
1384
|
// src/lib/shader-plugin.ts
|
|
1385
1385
|
var SHADER_PLUGIN_INJECTION_TARGET_REGEX = /^(vs|fs):(?:#(?:decl|main-start|main-end)|[A-Za-z_][\w-]*)$/;
|
|
1386
1386
|
function resolveShaderPlugins(plugins = [], shaderLanguage) {
|
|
1387
|
-
const
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1387
|
+
const resolved = {
|
|
1388
|
+
modules: [],
|
|
1389
|
+
defines: {},
|
|
1390
|
+
injections: {},
|
|
1391
|
+
vertexInputs: {},
|
|
1392
|
+
interStageVariables: {}
|
|
1393
|
+
};
|
|
1392
1394
|
for (const plugin of plugins) {
|
|
1393
|
-
|
|
1394
|
-
appendShaderPluginVariant(
|
|
1395
|
-
{ modules, defines, injections, vertexInputs, varyings },
|
|
1396
|
-
plugin[shaderLanguage]
|
|
1397
|
-
);
|
|
1395
|
+
appendShaderPlugin(resolved, plugin, shaderLanguage);
|
|
1398
1396
|
}
|
|
1399
|
-
|
|
1397
|
+
const { vertexInputs, interStageVariables } = resolved;
|
|
1398
|
+
for (const name of Object.keys(interStageVariables)) {
|
|
1400
1399
|
if (vertexInputs[name]) {
|
|
1401
1400
|
throw new Error(`ShaderPlugin name "${name}" cannot be both a vertex input and a varying`);
|
|
1402
1401
|
}
|
|
1403
1402
|
}
|
|
1404
|
-
return
|
|
1403
|
+
return resolved;
|
|
1405
1404
|
}
|
|
1406
|
-
function mergeShaderPluginModules(modules = [], pluginModules = []) {
|
|
1405
|
+
function mergeShaderPluginModules(modules = [], pluginModules = [], options = {}) {
|
|
1407
1406
|
const mergedModules = [...modules];
|
|
1408
|
-
const
|
|
1407
|
+
const selectedModules = /* @__PURE__ */ new Map();
|
|
1408
|
+
for (const module of mergedModules) {
|
|
1409
|
+
const selected = selectedModules.get(module.name);
|
|
1410
|
+
if (selected && selected !== module) options.onConflict?.(module.name, selected, module);
|
|
1411
|
+
if (!selected) selectedModules.set(module.name, module);
|
|
1412
|
+
}
|
|
1409
1413
|
for (const pluginModule of pluginModules) {
|
|
1410
|
-
|
|
1414
|
+
const selected = selectedModules.get(pluginModule.name);
|
|
1415
|
+
if (selected && selected !== pluginModule) {
|
|
1416
|
+
options.onConflict?.(pluginModule.name, selected, pluginModule);
|
|
1417
|
+
}
|
|
1418
|
+
if (!selected) {
|
|
1411
1419
|
mergedModules.push(pluginModule);
|
|
1412
|
-
|
|
1420
|
+
selectedModules.set(pluginModule.name, pluginModule);
|
|
1413
1421
|
}
|
|
1414
1422
|
}
|
|
1415
1423
|
return mergedModules;
|
|
1416
1424
|
}
|
|
1417
|
-
function
|
|
1418
|
-
if (
|
|
1419
|
-
|
|
1420
|
-
}
|
|
1421
|
-
if (variant.modules?.length) {
|
|
1422
|
-
resolved.modules.push(...variant.modules);
|
|
1425
|
+
function appendShaderPlugin(resolved, plugin, shaderLanguage) {
|
|
1426
|
+
if (plugin.module) {
|
|
1427
|
+
resolved.modules.push(plugin.module);
|
|
1423
1428
|
}
|
|
1424
|
-
if (
|
|
1425
|
-
Object.assign(resolved.defines,
|
|
1429
|
+
if (plugin.defines) {
|
|
1430
|
+
Object.assign(resolved.defines, plugin.defines);
|
|
1426
1431
|
}
|
|
1427
|
-
for (const [name, type] of Object.entries(
|
|
1432
|
+
for (const [name, type] of Object.entries(plugin.vertexInputs || {})) {
|
|
1428
1433
|
assertShaderPluginInterfaceName(name, "vertex input");
|
|
1429
1434
|
const existingType = resolved.vertexInputs[name];
|
|
1430
1435
|
if (existingType && existingType !== type) {
|
|
@@ -1434,25 +1439,28 @@ ${fragmentString}${source7.slice(insertionIndex)}`;
|
|
|
1434
1439
|
}
|
|
1435
1440
|
resolved.vertexInputs[name] = type;
|
|
1436
1441
|
}
|
|
1437
|
-
for (const [name, varying] of Object.entries(
|
|
1442
|
+
for (const [name, varying] of Object.entries(plugin.interStageVariables || {})) {
|
|
1438
1443
|
assertShaderPluginInterfaceName(name, "varying");
|
|
1439
|
-
const normalizedVarying =
|
|
1440
|
-
const existingVarying = resolved.
|
|
1444
|
+
const normalizedVarying = normalizeShaderPluginInterStageVariable(name, varying);
|
|
1445
|
+
const existingVarying = resolved.interStageVariables[name];
|
|
1441
1446
|
if (existingVarying && (existingVarying.type !== normalizedVarying.type || existingVarying.interpolation !== normalizedVarying.interpolation)) {
|
|
1442
1447
|
throw new Error(
|
|
1443
1448
|
`ShaderPlugin varying "${name}" has conflicting declarations "${existingVarying.type}/${existingVarying.interpolation}" and "${normalizedVarying.type}/${normalizedVarying.interpolation}"`
|
|
1444
1449
|
);
|
|
1445
1450
|
}
|
|
1446
|
-
resolved.
|
|
1451
|
+
resolved.interStageVariables[name] = normalizedVarying;
|
|
1447
1452
|
}
|
|
1448
|
-
for (const injection of
|
|
1453
|
+
for (const injection of plugin.injections || []) {
|
|
1454
|
+
const source7 = injection[shaderLanguage];
|
|
1455
|
+
if (source7 === void 0) continue;
|
|
1449
1456
|
assertNamedShaderPluginInjectionTarget(injection.target);
|
|
1450
1457
|
if (!resolved.injections[injection.target]) {
|
|
1451
1458
|
resolved.injections[injection.target] = [];
|
|
1452
1459
|
}
|
|
1453
1460
|
const injections = resolved.injections[injection.target];
|
|
1454
1461
|
injections.push({
|
|
1455
|
-
|
|
1462
|
+
pluginName: plugin.name,
|
|
1463
|
+
injection: source7,
|
|
1456
1464
|
order: injection.order ?? 0
|
|
1457
1465
|
});
|
|
1458
1466
|
}
|
|
@@ -1462,7 +1470,7 @@ ${fragmentString}${source7.slice(insertionIndex)}`;
|
|
|
1462
1470
|
throw new Error(`ShaderPlugin ${kind} "${name}" must be a valid non-reserved identifier`);
|
|
1463
1471
|
}
|
|
1464
1472
|
}
|
|
1465
|
-
function
|
|
1473
|
+
function normalizeShaderPluginInterStageVariable(name, varying) {
|
|
1466
1474
|
const { primitiveType } = shaderTypeDecoder.getAttributeShaderTypeInfo(varying.type);
|
|
1467
1475
|
const integerType = primitiveType === "i32" || primitiveType === "u32";
|
|
1468
1476
|
const interpolation = varying.interpolation || (integerType ? "flat" : "smooth");
|
|
@@ -1973,6 +1981,29 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
1973
1981
|
if (trimmedExpression === "false") {
|
|
1974
1982
|
return false;
|
|
1975
1983
|
}
|
|
1984
|
+
const operandPattern = "(?:[A-Za-z_][A-Za-z0-9_]*|[+-]?\\d+(?:\\.\\d+)?)";
|
|
1985
|
+
const comparison = trimmedExpression.match(
|
|
1986
|
+
new RegExp(`^(${operandPattern})\\s*(==|!=|<=|>=|<|>)\\s*(${operandPattern})$`)
|
|
1987
|
+
);
|
|
1988
|
+
if (comparison) {
|
|
1989
|
+
const resolveOperand = (operand) => /^[A-Za-z_]/.test(operand) ? Number(defines[operand] ?? 0) : Number(operand);
|
|
1990
|
+
const left = resolveOperand(comparison[1]);
|
|
1991
|
+
const right = resolveOperand(comparison[3]);
|
|
1992
|
+
switch (comparison[2]) {
|
|
1993
|
+
case "==":
|
|
1994
|
+
return left === right;
|
|
1995
|
+
case "!=":
|
|
1996
|
+
return left !== right;
|
|
1997
|
+
case "<=":
|
|
1998
|
+
return left <= right;
|
|
1999
|
+
case ">=":
|
|
2000
|
+
return left >= right;
|
|
2001
|
+
case "<":
|
|
2002
|
+
return left < right;
|
|
2003
|
+
case ">":
|
|
2004
|
+
return left > right;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
1976
2007
|
const negatedDefineMatch = trimmedExpression.match(new RegExp(`^!\\s*${DEFINE_NAME_PATTERN}$`));
|
|
1977
2008
|
if (negatedDefineMatch) {
|
|
1978
2009
|
return !Boolean(defines[negatedDefineMatch[1]]);
|
|
@@ -2225,10 +2256,10 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
2225
2256
|
}
|
|
2226
2257
|
|
|
2227
2258
|
// src/lib/shader-assembly/shader-plugin-varyings.ts
|
|
2228
|
-
function
|
|
2259
|
+
function assembleShaderPluginInterStageVariablesGLSL(source7, stage, interStageVariables) {
|
|
2229
2260
|
const declarations = [];
|
|
2230
2261
|
const initialization = [];
|
|
2231
|
-
for (const [name, varying] of Object.entries(
|
|
2262
|
+
for (const [name, varying] of Object.entries(interStageVariables)) {
|
|
2232
2263
|
assertGLSLVaryingIsNew(source7, name);
|
|
2233
2264
|
const qualifier = varying.interpolation === "flat" ? "flat " : "";
|
|
2234
2265
|
const direction = stage === "vertex" ? "out" : "in";
|
|
@@ -2239,8 +2270,8 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
2239
2270
|
}
|
|
2240
2271
|
return { declarations: declarations.join("\n"), initialization: initialization.join("\n") };
|
|
2241
2272
|
}
|
|
2242
|
-
function
|
|
2243
|
-
const entries = Object.entries(
|
|
2273
|
+
function assembleShaderPluginInterStageVariablesWGSL(source7, vertexEntryPoint, fragmentEntryPoint, interStageVariables) {
|
|
2274
|
+
const entries = Object.entries(interStageVariables);
|
|
2244
2275
|
if (entries.length === 0) {
|
|
2245
2276
|
return {
|
|
2246
2277
|
source: source7,
|
|
@@ -2255,18 +2286,20 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
2255
2286
|
let fragmentFunction = getWGSLFunctionRange(transformedSource, fragmentEntryPoint, "fragment");
|
|
2256
2287
|
const fragmentInput = getWGSLFragmentStructInput(transformedSource, fragmentFunction);
|
|
2257
2288
|
const vertexOutputStruct = getWGSLStructRange(transformedSource, vertexOutputType);
|
|
2258
|
-
const fragmentInputStruct = getWGSLStructRange(transformedSource, fragmentInput.type);
|
|
2289
|
+
const fragmentInputStruct = fragmentInput ? getWGSLStructRange(transformedSource, fragmentInput.type) : null;
|
|
2259
2290
|
const interfaceNames = /* @__PURE__ */ new Set([
|
|
2260
2291
|
...getWGSLDeclaredNames2(vertexFunction.parameters),
|
|
2261
2292
|
...getWGSLDeclaredNames2(vertexOutputStruct.body),
|
|
2262
2293
|
...getWGSLDeclaredNames2(fragmentFunction.parameters),
|
|
2263
|
-
...getWGSLDeclaredNames2(fragmentInputStruct
|
|
2294
|
+
...getWGSLDeclaredNames2(fragmentInputStruct?.body || "")
|
|
2264
2295
|
]);
|
|
2265
2296
|
const usedLocations = /* @__PURE__ */ new Set([
|
|
2266
2297
|
...getWGSLLocations2(vertexOutputStruct.body),
|
|
2267
|
-
...getWGSLLocations2(fragmentInputStruct
|
|
2298
|
+
...getWGSLLocations2(fragmentInputStruct?.body || ""),
|
|
2299
|
+
...getWGSLLocations2(fragmentFunction.parameters)
|
|
2268
2300
|
]);
|
|
2269
2301
|
const fields = [];
|
|
2302
|
+
const fragmentParameters = [];
|
|
2270
2303
|
const declarations = [];
|
|
2271
2304
|
const vertexInitialization = [];
|
|
2272
2305
|
const fragmentInitialization = [];
|
|
@@ -2282,7 +2315,20 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
2282
2315
|
fields.push(` @location(${location})${interpolation} ${name}: ${varying.type},`);
|
|
2283
2316
|
declarations.push(`var<private> ${name}: ${varying.type};`);
|
|
2284
2317
|
vertexInitialization.push(`${name} = ${getWGSLZeroValue(varying.type)};`);
|
|
2285
|
-
|
|
2318
|
+
if (fragmentInput) {
|
|
2319
|
+
fragmentInitialization.push(`${name} = ${fragmentInput.name}.${name};`);
|
|
2320
|
+
} else {
|
|
2321
|
+
const parameterName = `_luma_${name}`;
|
|
2322
|
+
if (interfaceNames.has(parameterName)) {
|
|
2323
|
+
throw new Error(
|
|
2324
|
+
`ShaderPlugin varying "${name}" conflicts with a generated fragment parameter`
|
|
2325
|
+
);
|
|
2326
|
+
}
|
|
2327
|
+
fragmentParameters.push(
|
|
2328
|
+
`@location(${location})${interpolation} ${parameterName}: ${varying.type}`
|
|
2329
|
+
);
|
|
2330
|
+
fragmentInitialization.push(`${name} = ${parameterName};`);
|
|
2331
|
+
}
|
|
2286
2332
|
}
|
|
2287
2333
|
assertWGSLStructConstructorsAreLocal(
|
|
2288
2334
|
transformedSource,
|
|
@@ -2302,16 +2348,21 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
2302
2348
|
vertexFunction,
|
|
2303
2349
|
entries.map(([name]) => name)
|
|
2304
2350
|
);
|
|
2305
|
-
const structNames = vertexOutputType === fragmentInput.type ? [vertexOutputType] : [vertexOutputType, fragmentInput.type];
|
|
2351
|
+
const structNames = !fragmentInput || vertexOutputType === fragmentInput.type ? [vertexOutputType] : [vertexOutputType, fragmentInput.type];
|
|
2306
2352
|
const structInsertions = structNames.map((structName) => getWGSLStructRange(transformedSource, structName).closeBrace).sort((left, right) => right - left);
|
|
2307
2353
|
for (const insertionIndex of structInsertions) {
|
|
2308
2354
|
transformedSource = transformedSource.slice(0, insertionIndex) + `${fields.join("\n")}
|
|
2309
2355
|
` + transformedSource.slice(insertionIndex);
|
|
2310
2356
|
}
|
|
2311
2357
|
fragmentFunction = getWGSLFunctionRange(transformedSource, fragmentEntryPoint, "fragment");
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2358
|
+
if (fragmentParameters.length) {
|
|
2359
|
+
let parameters = fragmentFunction.parameters;
|
|
2360
|
+
const parameterTokens = maskWGSLComments(parameters).trimEnd();
|
|
2361
|
+
if (parameterTokens.trim() && !parameterTokens.endsWith(",")) {
|
|
2362
|
+
const insertionIndex = parameterTokens.length;
|
|
2363
|
+
parameters = `${parameters.slice(0, insertionIndex)},${parameters.slice(insertionIndex)}`;
|
|
2364
|
+
}
|
|
2365
|
+
transformedSource = transformedSource.slice(0, fragmentFunction.openParenthesis + 1) + parameters + "\n " + fragmentParameters.join(",\n ") + "\n" + transformedSource.slice(fragmentFunction.closeParenthesis);
|
|
2315
2366
|
}
|
|
2316
2367
|
return {
|
|
2317
2368
|
source: transformedSource,
|
|
@@ -2324,7 +2375,9 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
2324
2375
|
const functionPattern = new RegExp(`\\bfn\\s+${escapeRegExp3(entryPoint)}\\s*\\(`, "g");
|
|
2325
2376
|
const match = functionPattern.exec(source7);
|
|
2326
2377
|
if (!match) {
|
|
2327
|
-
throw new Error(
|
|
2378
|
+
throw new Error(
|
|
2379
|
+
`ShaderPlugin interStageVariables require WGSL ${stage} entry point "${entryPoint}"`
|
|
2380
|
+
);
|
|
2328
2381
|
}
|
|
2329
2382
|
const openParenthesis = source7.indexOf("(", match.index);
|
|
2330
2383
|
const closeParenthesis = findMatchingDelimiter2(source7, openParenthesis, "(", ")");
|
|
@@ -2346,14 +2399,14 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
2346
2399
|
const match = /->\s*([A-Za-z_][\w]*)\s*$/.exec(resultSource.trim());
|
|
2347
2400
|
if (!match || getWGSLStructRangeOrNull(source7, match[1]) === null) {
|
|
2348
2401
|
throw new Error(
|
|
2349
|
-
"ShaderPlugin
|
|
2402
|
+
"ShaderPlugin interStageVariables require the WGSL vertex entry point to return a named struct"
|
|
2350
2403
|
);
|
|
2351
2404
|
}
|
|
2352
2405
|
return match[1];
|
|
2353
2406
|
}
|
|
2354
2407
|
function getWGSLFragmentStructInput(source7, functionRange) {
|
|
2355
2408
|
const candidates = [];
|
|
2356
|
-
for (const parameter of splitTopLevel(functionRange.parameters, ",")) {
|
|
2409
|
+
for (const parameter of splitTopLevel(maskWGSLComments(functionRange.parameters), ",")) {
|
|
2357
2410
|
const match = /(?:@[A-Za-z_][\w]*(?:\([^)]*\))?\s*)*([A-Za-z_][\w]*)\s*:\s*([A-Za-z_][\w]*)\s*$/.exec(
|
|
2358
2411
|
parameter.trim()
|
|
2359
2412
|
);
|
|
@@ -2361,12 +2414,12 @@ ${DECLARATION_INJECT_MARKER}
|
|
|
2361
2414
|
candidates.push({ name: match[1], type: match[2] });
|
|
2362
2415
|
}
|
|
2363
2416
|
}
|
|
2364
|
-
if (candidates.length
|
|
2417
|
+
if (candidates.length > 1) {
|
|
2365
2418
|
throw new Error(
|
|
2366
|
-
`ShaderPlugin
|
|
2419
|
+
`ShaderPlugin interStageVariables require exactly one named WGSL fragment input struct; found ${candidates.length}`
|
|
2367
2420
|
);
|
|
2368
2421
|
}
|
|
2369
|
-
return candidates[0];
|
|
2422
|
+
return candidates[0] || null;
|
|
2370
2423
|
}
|
|
2371
2424
|
function getWGSLStructRange(source7, structName) {
|
|
2372
2425
|
const range = getWGSLStructRangeOrNull(source7, structName);
|
|
@@ -2677,7 +2730,12 @@ return ${outputName};
|
|
|
2677
2730
|
continue;
|
|
2678
2731
|
}
|
|
2679
2732
|
if (!isShaderHookRegistered(registry, hookName)) {
|
|
2680
|
-
|
|
2733
|
+
const pluginNames = [
|
|
2734
|
+
...new Set(hookInjections[hookName].map((injection) => injection.pluginName).filter(Boolean))
|
|
2735
|
+
];
|
|
2736
|
+
throw new Error(
|
|
2737
|
+
`Unknown shader hook ${hookName}${pluginNames.length ? ` (plugins: ${pluginNames.join(", ")})` : ""}`
|
|
2738
|
+
);
|
|
2681
2739
|
}
|
|
2682
2740
|
}
|
|
2683
2741
|
}
|
|
@@ -2734,7 +2792,7 @@ return ${outputName};
|
|
|
2734
2792
|
inject = {},
|
|
2735
2793
|
pluginInjections = {},
|
|
2736
2794
|
pluginVertexInputs = {},
|
|
2737
|
-
|
|
2795
|
+
pluginInterStageVariables = {},
|
|
2738
2796
|
vertexEntryPoint = "vertexMain",
|
|
2739
2797
|
fragmentEntryPoint = "fragmentMain",
|
|
2740
2798
|
log
|
|
@@ -2746,11 +2804,11 @@ return ${outputName};
|
|
|
2746
2804
|
vertexEntryPoint,
|
|
2747
2805
|
pluginVertexInputs
|
|
2748
2806
|
);
|
|
2749
|
-
const pluginVaryingAssembly =
|
|
2807
|
+
const pluginVaryingAssembly = assembleShaderPluginInterStageVariablesWGSL(
|
|
2750
2808
|
pluginVertexInputAssembly.source,
|
|
2751
2809
|
vertexEntryPoint,
|
|
2752
2810
|
fragmentEntryPoint,
|
|
2753
|
-
|
|
2811
|
+
pluginInterStageVariables
|
|
2754
2812
|
);
|
|
2755
2813
|
const coreSource = pluginVaryingAssembly.source;
|
|
2756
2814
|
let assembledSource = "";
|
|
@@ -2767,15 +2825,15 @@ return ${outputName};
|
|
|
2767
2825
|
const name = match[3];
|
|
2768
2826
|
if (hash) {
|
|
2769
2827
|
if (name === "decl") {
|
|
2770
|
-
declInjections[key] = [injection];
|
|
2828
|
+
declInjections[key] = [...declInjections[key] || [], injection];
|
|
2771
2829
|
} else {
|
|
2772
|
-
mainInjections[key] = [injection];
|
|
2830
|
+
mainInjections[key] = [...mainInjections[key] || [], injection];
|
|
2773
2831
|
}
|
|
2774
2832
|
} else {
|
|
2775
|
-
hookInjections[key] = [injection];
|
|
2833
|
+
hookInjections[key] = [...hookInjections[key] || [], injection];
|
|
2776
2834
|
}
|
|
2777
2835
|
} else {
|
|
2778
|
-
mainInjections[key] = [injection];
|
|
2836
|
+
mainInjections[key] = [...mainInjections[key] || [], injection];
|
|
2779
2837
|
}
|
|
2780
2838
|
}
|
|
2781
2839
|
appendGeneratedVertexInputInjections(
|
|
@@ -3376,7 +3434,7 @@ return ${outputName};
|
|
|
3376
3434
|
inject = {},
|
|
3377
3435
|
pluginInjections = {},
|
|
3378
3436
|
pluginVertexInputs = {},
|
|
3379
|
-
|
|
3437
|
+
pluginInterStageVariables = {},
|
|
3380
3438
|
prologue = true,
|
|
3381
3439
|
log
|
|
3382
3440
|
} = options;
|
|
@@ -3425,35 +3483,30 @@ ${getApplicationDefines(allDefines)}
|
|
|
3425
3483
|
const name = match[3];
|
|
3426
3484
|
if (hash) {
|
|
3427
3485
|
if (name === "decl") {
|
|
3428
|
-
declInjections[key] = [injection];
|
|
3486
|
+
declInjections[key] = [...declInjections[key] || [], injection];
|
|
3429
3487
|
} else {
|
|
3430
|
-
mainInjections[key] = [injection];
|
|
3488
|
+
mainInjections[key] = [...mainInjections[key] || [], injection];
|
|
3431
3489
|
}
|
|
3432
3490
|
} else {
|
|
3433
|
-
hookInjections[key] = [injection];
|
|
3491
|
+
hookInjections[key] = [...hookInjections[key] || [], injection];
|
|
3434
3492
|
}
|
|
3435
3493
|
} else {
|
|
3436
|
-
mainInjections[key] = [injection];
|
|
3494
|
+
mainInjections[key] = [...mainInjections[key] || [], injection];
|
|
3437
3495
|
}
|
|
3438
3496
|
}
|
|
3439
3497
|
if (stage === "vertex") {
|
|
3440
3498
|
const declarations = getShaderPluginVertexInputDeclarationsGLSL(coreSource, pluginVertexInputs);
|
|
3441
|
-
if (declarations) {
|
|
3442
|
-
|
|
3443
|
-
declInjections["vs:#decl"].push({
|
|
3444
|
-
injection: declarations,
|
|
3445
|
-
order: Number.MIN_SAFE_INTEGER
|
|
3446
|
-
});
|
|
3447
|
-
}
|
|
3499
|
+
if (declarations) assembledSource += `${declarations}
|
|
3500
|
+
`;
|
|
3448
3501
|
}
|
|
3449
|
-
const pluginVaryingAssembly =
|
|
3502
|
+
const pluginVaryingAssembly = assembleShaderPluginInterStageVariablesGLSL(
|
|
3503
|
+
coreSource,
|
|
3504
|
+
stage,
|
|
3505
|
+
pluginInterStageVariables
|
|
3506
|
+
);
|
|
3450
3507
|
if (pluginVaryingAssembly.declarations) {
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
declInjections[declarationTarget].push({
|
|
3454
|
-
injection: pluginVaryingAssembly.declarations,
|
|
3455
|
-
order: Number.MIN_SAFE_INTEGER
|
|
3456
|
-
});
|
|
3508
|
+
assembledSource += `${pluginVaryingAssembly.declarations}
|
|
3509
|
+
`;
|
|
3457
3510
|
}
|
|
3458
3511
|
if (pluginVaryingAssembly.initialization) {
|
|
3459
3512
|
mainInjections["vs:#main-start"] = mainInjections["vs:#main-start"] || [];
|
|
@@ -3635,7 +3688,7 @@ ${getApplicationDefines(allDefines)}
|
|
|
3635
3688
|
*/
|
|
3636
3689
|
assembleGLSLShaderPair(props) {
|
|
3637
3690
|
const modules = this._getModuleList(props.modules);
|
|
3638
|
-
const hookFunctions = this._hookFunctions;
|
|
3691
|
+
const hookFunctions = [...this._hookFunctions, ...props.hookFunctions || []];
|
|
3639
3692
|
const vertex = this._transpileShader(props, modules, props.vs, "vertex");
|
|
3640
3693
|
const fragment = this._transpileShader(props, modules, props.fs, "fragment");
|
|
3641
3694
|
const assembled = assembleGLSLShaderPair({
|
|
@@ -3661,7 +3714,7 @@ ${getApplicationDefines(allDefines)}
|
|
|
3661
3714
|
*/
|
|
3662
3715
|
assembleWGSLShader(props) {
|
|
3663
3716
|
const modules = this._getModuleList(props.modules);
|
|
3664
|
-
const hookFunctions = this._hookFunctions;
|
|
3717
|
+
const hookFunctions = [...this._hookFunctions, ...props.hookFunctions || []];
|
|
3665
3718
|
const translated = this._transpileShader(
|
|
3666
3719
|
props,
|
|
3667
3720
|
modules,
|
|
@@ -11614,30 +11667,21 @@ fn filter_isVisible(value: f32) -> bool {
|
|
|
11614
11667
|
};
|
|
11615
11668
|
var filterShaderPlugin = {
|
|
11616
11669
|
name: "filter",
|
|
11617
|
-
|
|
11670
|
+
module: filterShaderModule,
|
|
11618
11671
|
vertexInputs: {
|
|
11619
11672
|
filterValues: "f32"
|
|
11620
11673
|
},
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11624
|
-
|
|
11625
|
-
injection: `if (!filter_isVisible(filterValues)) {
|
|
11674
|
+
injections: [
|
|
11675
|
+
{
|
|
11676
|
+
target: "vs:FILTER_POSITION",
|
|
11677
|
+
glsl: `if (!filter_isVisible(filterValues)) {
|
|
11626
11678
|
position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
11627
|
-
}
|
|
11628
|
-
|
|
11629
|
-
]
|
|
11630
|
-
},
|
|
11631
|
-
wgsl: {
|
|
11632
|
-
injections: [
|
|
11633
|
-
{
|
|
11634
|
-
target: "vs:FILTER_POSITION",
|
|
11635
|
-
injection: `if (!filter_isVisible(filterValues)) {
|
|
11679
|
+
}`,
|
|
11680
|
+
wgsl: `if (!filter_isVisible(filterValues)) {
|
|
11636
11681
|
*position = vec4<f32>(2.0, 2.0, 2.0, 1.0);
|
|
11637
11682
|
}`
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
}
|
|
11683
|
+
}
|
|
11684
|
+
]
|
|
11641
11685
|
};
|
|
11642
11686
|
|
|
11643
11687
|
// src/modules/engine/clip/clip.ts
|
|
@@ -11724,48 +11768,36 @@ fn clip_isInBounds(coordinates: vec2<f32>) -> bool {
|
|
|
11724
11768
|
};
|
|
11725
11769
|
var clipShaderPlugin = {
|
|
11726
11770
|
name: "clip",
|
|
11727
|
-
|
|
11728
|
-
|
|
11771
|
+
module: clipShaderModule,
|
|
11772
|
+
interStageVariables: {
|
|
11729
11773
|
clipCoordinates: { type: "vec2<f32>", interpolation: "smooth" }
|
|
11730
11774
|
},
|
|
11731
|
-
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
injection: `clipCoordinates = geometryCoordinates;
|
|
11775
|
+
injections: [
|
|
11776
|
+
{
|
|
11777
|
+
target: "vs:CLIP_POSITION",
|
|
11778
|
+
glsl: `clipCoordinates = geometryCoordinates;
|
|
11736
11779
|
if (clipState.enabled != 0 && clipState.mode == ${CLIP_MODE_INSTANCE} &&
|
|
11737
11780
|
!clip_isInBounds(instanceCoordinates)) {
|
|
11738
11781
|
position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
11739
|
-
}
|
|
11740
|
-
|
|
11741
|
-
{
|
|
11742
|
-
target: "fs:CLIP_COLOR",
|
|
11743
|
-
injection: `if (clipState.enabled != 0 && clipState.mode == ${CLIP_MODE_GEOMETRY} &&
|
|
11744
|
-
!clip_isInBounds(clipCoordinates)) {
|
|
11745
|
-
discard;
|
|
11746
|
-
}`
|
|
11747
|
-
}
|
|
11748
|
-
]
|
|
11749
|
-
},
|
|
11750
|
-
wgsl: {
|
|
11751
|
-
injections: [
|
|
11752
|
-
{
|
|
11753
|
-
target: "vs:CLIP_POSITION",
|
|
11754
|
-
injection: `clipCoordinates = geometryCoordinates;
|
|
11782
|
+
}`,
|
|
11783
|
+
wgsl: `clipCoordinates = geometryCoordinates;
|
|
11755
11784
|
if (clipUniforms.enabled != 0 && clipUniforms.mode == ${CLIP_MODE_INSTANCE} &&
|
|
11756
11785
|
!clip_isInBounds(instanceCoordinates)) {
|
|
11757
11786
|
*position = vec4<f32>(2.0, 2.0, 2.0, 1.0);
|
|
11758
11787
|
}`
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
11788
|
+
},
|
|
11789
|
+
{
|
|
11790
|
+
target: "fs:CLIP_COLOR",
|
|
11791
|
+
glsl: `if (clipState.enabled != 0 && clipState.mode == ${CLIP_MODE_GEOMETRY} &&
|
|
11792
|
+
!clip_isInBounds(clipCoordinates)) {
|
|
11793
|
+
discard;
|
|
11794
|
+
}`,
|
|
11795
|
+
wgsl: `if (clipUniforms.enabled != 0 && clipUniforms.mode == ${CLIP_MODE_GEOMETRY} &&
|
|
11763
11796
|
!clip_isInBounds(clipCoordinates)) {
|
|
11764
11797
|
discard;
|
|
11765
11798
|
}`
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
}
|
|
11799
|
+
}
|
|
11800
|
+
]
|
|
11769
11801
|
};
|
|
11770
11802
|
|
|
11771
11803
|
// src/modules/engine/skin/skin.ts
|