@luma.gl/shadertools 9.3.6 → 9.4.0-alpha.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/dist/dist.dev.js +6555 -2373
- package/dist/dist.min.js +2984 -237
- package/dist/index.cjs +4356 -268
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +13 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/preprocessor/preprocessor.d.ts +11 -1
- package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
- package/dist/lib/preprocessor/preprocessor.js +47 -2
- package/dist/lib/preprocessor/preprocessor.js.map +1 -1
- package/dist/lib/shader-assembler.d.ts +10 -10
- package/dist/lib/shader-assembler.d.ts.map +1 -1
- package/dist/lib/shader-assembler.js +36 -20
- package/dist/lib/shader-assembler.js.map +1 -1
- package/dist/lib/shader-assembly/assemble-shaders.d.ts +28 -7
- package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
- package/dist/lib/shader-assembly/assemble-shaders.js +133 -15
- package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
- package/dist/lib/shader-assembly/platform-info.d.ts +2 -0
- package/dist/lib/shader-assembly/platform-info.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.d.ts +1 -1
- package/dist/lib/shader-assembly/shader-hooks.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.js +6 -3
- package/dist/lib/shader-assembly/shader-hooks.js.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.d.ts +4 -1
- package/dist/lib/shader-assembly/shader-injections.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.js +68 -11
- package/dist/lib/shader-assembly/shader-injections.js.map +1 -1
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts +15 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.js +412 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.js.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.d.ts +12 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.d.ts.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.js +237 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.js.map +1 -0
- package/dist/lib/shader-module/shader-module.d.ts +3 -0
- package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
- package/dist/lib/shader-module/shader-module.js.map +1 -1
- package/dist/lib/shader-module/shader-pass-pipeline.d.ts +14 -0
- package/dist/lib/shader-module/shader-pass-pipeline.d.ts.map +1 -0
- package/dist/lib/shader-module/shader-pass-pipeline.js +5 -0
- package/dist/lib/shader-module/shader-pass-pipeline.js.map +1 -0
- package/dist/lib/shader-module/shader-pass.d.ts +21 -4
- package/dist/lib/shader-module/shader-pass.d.ts.map +1 -1
- package/dist/lib/shader-plugin.d.ts +68 -0
- package/dist/lib/shader-plugin.d.ts.map +1 -0
- package/dist/lib/shader-plugin.js +98 -0
- package/dist/lib/shader-plugin.js.map +1 -0
- package/dist/lib/utils/assert.js +1 -1
- package/dist/lib/utils/assert.js.map +1 -1
- package/dist/modules/color/float-colors.d.ts +111 -5
- package/dist/modules/color/float-colors.d.ts.map +1 -1
- package/dist/modules/color/float-colors.js +200 -34
- package/dist/modules/color/float-colors.js.map +1 -1
- package/dist/modules/engine/clip/clip.d.ts +12 -0
- package/dist/modules/engine/clip/clip.d.ts.map +1 -0
- package/dist/modules/engine/clip/clip.js +129 -0
- package/dist/modules/engine/clip/clip.js.map +1 -0
- package/dist/modules/engine/filter/filter.d.ts +12 -0
- package/dist/modules/engine/filter/filter.d.ts.map +1 -0
- package/dist/modules/engine/filter/filter.js +88 -0
- package/dist/modules/engine/filter/filter.js.map +1 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.d.ts +3 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.d.ts.map +1 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.js +1892 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.js.map +1 -0
- package/dist/modules/geospatial/dggs/dggs.d.ts +6 -0
- package/dist/modules/geospatial/dggs/dggs.d.ts.map +1 -0
- package/dist/modules/geospatial/dggs/dggs.js +10 -0
- package/dist/modules/geospatial/dggs/dggs.js.map +1 -0
- package/dist/modules/lighting/water-material/water-material.d.ts +28 -0
- package/dist/modules/lighting/water-material/water-material.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-material.js +179 -0
- package/dist/modules/lighting/water-material/water-material.js.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.d.ts +3 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.js +232 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.js.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.d.ts +2 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.js +230 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.js.map +1 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -1
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -1
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +268 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +50 -3
- package/src/lib/preprocessor/preprocessor.ts +68 -3
- package/src/lib/shader-assembler.ts +49 -20
- package/src/lib/shader-assembly/assemble-shaders.ts +242 -30
- package/src/lib/shader-assembly/platform-info.ts +2 -0
- package/src/lib/shader-assembly/shader-hooks.ts +7 -3
- package/src/lib/shader-assembly/shader-injections.ts +96 -11
- package/src/lib/shader-assembly/shader-plugin-varyings.ts +524 -0
- package/src/lib/shader-assembly/shader-plugin-vertex-inputs.ts +279 -0
- package/src/lib/shader-module/shader-module.ts +3 -0
- package/src/lib/shader-module/shader-pass-pipeline.ts +19 -0
- package/src/lib/shader-module/shader-pass.ts +29 -4
- package/src/lib/shader-plugin.ts +214 -0
- package/src/lib/utils/assert.ts +1 -1
- package/src/modules/color/float-colors.ts +272 -37
- package/src/modules/engine/clip/clip.ts +149 -0
- package/src/modules/engine/filter/filter.ts +107 -0
- package/src/modules/geospatial/dggs/dggs-wgsl.ts +1892 -0
- package/src/modules/geospatial/dggs/dggs.ts +12 -0
- package/src/modules/lighting/water-material/water-material.ts +234 -0
- package/src/modules/lighting/water-material/water-shaders-glsl.ts +233 -0
- package/src/modules/lighting/water-material/water-shaders-wgsl.ts +230 -0
- package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +268 -0
package/dist/index.cjs
CHANGED
|
@@ -25,15 +25,22 @@ var __publicField = (obj, key, value) => {
|
|
|
25
25
|
// dist/index.js
|
|
26
26
|
var dist_exports = {};
|
|
27
27
|
__export(dist_exports, {
|
|
28
|
+
STORAGE_COLOR_DEFAULT_BYTE_STRIDES: () => STORAGE_COLOR_DEFAULT_BYTE_STRIDES,
|
|
29
|
+
STORAGE_COLOR_FORMAT: () => STORAGE_COLOR_FORMAT,
|
|
30
|
+
STORAGE_COLOR_FORMAT_BYTE_LENGTHS: () => STORAGE_COLOR_FORMAT_BYTE_LENGTHS,
|
|
28
31
|
ShaderAssembler: () => ShaderAssembler,
|
|
29
32
|
_getDependencyGraph: () => getDependencyGraph,
|
|
30
33
|
_resolveModules: () => resolveModules,
|
|
31
34
|
assembleGLSLShaderPair: () => assembleGLSLShaderPair,
|
|
32
35
|
capitalize: () => capitalize,
|
|
33
36
|
checkShaderModuleDeprecations: () => checkShaderModuleDeprecations,
|
|
37
|
+
clipShaderPlugin: () => clipShaderPlugin,
|
|
38
|
+
colors: () => colors,
|
|
34
39
|
combineInjects: () => combineInjects,
|
|
35
40
|
convertToVec4: () => convertToVec4,
|
|
41
|
+
dggs: () => dggs,
|
|
36
42
|
dirlight: () => dirlight,
|
|
43
|
+
filterShaderPlugin: () => filterShaderPlugin,
|
|
37
44
|
floatColors: () => floatColors,
|
|
38
45
|
fp32: () => fp32,
|
|
39
46
|
fp64: () => fp64,
|
|
@@ -59,6 +66,7 @@ __export(dist_exports, {
|
|
|
59
66
|
initializeShaderModules: () => initializeShaderModules,
|
|
60
67
|
lambertMaterial: () => lambertMaterial,
|
|
61
68
|
lighting: () => lighting,
|
|
69
|
+
mergeShaderPluginModules: () => mergeShaderPluginModules,
|
|
62
70
|
normalizeByteColor3: () => normalizeByteColor3,
|
|
63
71
|
normalizeByteColor4: () => normalizeByteColor4,
|
|
64
72
|
pbrMaterial: () => pbrMaterial,
|
|
@@ -67,13 +75,16 @@ __export(dist_exports, {
|
|
|
67
75
|
picking: () => picking,
|
|
68
76
|
preprocess: () => preprocess,
|
|
69
77
|
random: () => random,
|
|
78
|
+
resolveShaderPlugins: () => resolveShaderPlugins,
|
|
70
79
|
resolveUseByteColors: () => resolveUseByteColors,
|
|
71
80
|
skin: () => skin,
|
|
81
|
+
storageColors: () => storageColors,
|
|
72
82
|
toHalfFloat: () => toHalfFloat,
|
|
73
83
|
typeToChannelCount: () => typeToChannelCount,
|
|
74
84
|
typeToChannelSuffix: () => typeToChannelSuffix,
|
|
75
85
|
validateShaderModuleUniformLayout: () => validateShaderModuleUniformLayout,
|
|
76
|
-
warnIfGLSLUniformBlocksAreNotStd140: () => warnIfGLSLUniformBlocksAreNotStd140
|
|
86
|
+
warnIfGLSLUniformBlocksAreNotStd140: () => warnIfGLSLUniformBlocksAreNotStd140,
|
|
87
|
+
waterMaterial: () => waterMaterial
|
|
77
88
|
});
|
|
78
89
|
module.exports = __toCommonJS(dist_exports);
|
|
79
90
|
|
|
@@ -218,7 +229,7 @@ function getHookStage(hook) {
|
|
|
218
229
|
throw new Error(type);
|
|
219
230
|
}
|
|
220
231
|
}
|
|
221
|
-
function injectShader(source4, stage, inject, injectStandardStubs = false) {
|
|
232
|
+
function injectShader(source4, stage, inject, injectStandardStubs = false, language = "glsl", entryPoints = {}) {
|
|
222
233
|
const isVertex = stage === "vertex";
|
|
223
234
|
for (const key in inject) {
|
|
224
235
|
const fragmentData = inject[key];
|
|
@@ -231,33 +242,33 @@ function injectShader(source4, stage, inject, injectStandardStubs = false) {
|
|
|
231
242
|
`;
|
|
232
243
|
switch (key) {
|
|
233
244
|
case "vs:#decl":
|
|
234
|
-
if (isVertex) {
|
|
245
|
+
if (language === "wgsl" || isVertex) {
|
|
235
246
|
source4 = source4.replace(DECLARATION_INJECT_MARKER, fragmentString);
|
|
236
247
|
}
|
|
237
248
|
break;
|
|
238
249
|
case "vs:#main-start":
|
|
239
|
-
if (isVertex) {
|
|
240
|
-
source4 = source4.replace(REGEX_START_OF_MAIN, (match) => match + fragmentString);
|
|
250
|
+
if (language === "wgsl" || isVertex) {
|
|
251
|
+
source4 = language === "wgsl" ? injectWGSLStageMain(source4, "vertex", fragmentString, "start", entryPoints.vertex) : source4.replace(REGEX_START_OF_MAIN, (match) => match + fragmentString);
|
|
241
252
|
}
|
|
242
253
|
break;
|
|
243
254
|
case "vs:#main-end":
|
|
244
|
-
if (isVertex) {
|
|
245
|
-
source4 = source4.replace(REGEX_END_OF_MAIN, (match) => fragmentString + match);
|
|
255
|
+
if (language === "wgsl" || isVertex) {
|
|
256
|
+
source4 = language === "wgsl" ? injectWGSLStageMain(source4, "vertex", fragmentString, "end", entryPoints.vertex) : source4.replace(REGEX_END_OF_MAIN, (match) => fragmentString + match);
|
|
246
257
|
}
|
|
247
258
|
break;
|
|
248
259
|
case "fs:#decl":
|
|
249
|
-
if (!isVertex) {
|
|
260
|
+
if (language === "wgsl" || !isVertex) {
|
|
250
261
|
source4 = source4.replace(DECLARATION_INJECT_MARKER, fragmentString);
|
|
251
262
|
}
|
|
252
263
|
break;
|
|
253
264
|
case "fs:#main-start":
|
|
254
|
-
if (!isVertex) {
|
|
255
|
-
source4 = source4.replace(REGEX_START_OF_MAIN, (match) => match + fragmentString);
|
|
265
|
+
if (language === "wgsl" || !isVertex) {
|
|
266
|
+
source4 = language === "wgsl" ? injectWGSLStageMain(source4, "fragment", fragmentString, "start", entryPoints.fragment) : source4.replace(REGEX_START_OF_MAIN, (match) => match + fragmentString);
|
|
256
267
|
}
|
|
257
268
|
break;
|
|
258
269
|
case "fs:#main-end":
|
|
259
|
-
if (!isVertex) {
|
|
260
|
-
source4 = source4.replace(REGEX_END_OF_MAIN, (match) => fragmentString + match);
|
|
270
|
+
if (language === "wgsl" || !isVertex) {
|
|
271
|
+
source4 = language === "wgsl" ? injectWGSLStageMain(source4, "fragment", fragmentString, "end", entryPoints.fragment) : source4.replace(REGEX_END_OF_MAIN, (match) => fragmentString + match);
|
|
261
272
|
}
|
|
262
273
|
break;
|
|
263
274
|
default:
|
|
@@ -281,6 +292,49 @@ ${inject[key]}` : inject[key];
|
|
|
281
292
|
});
|
|
282
293
|
return result;
|
|
283
294
|
}
|
|
295
|
+
function injectWGSLStageMain(source4, stage, fragmentString, position, entryPoint) {
|
|
296
|
+
const bodyRange = getWGSLStageFunctionBodyRange(source4, stage, entryPoint);
|
|
297
|
+
if (!bodyRange) {
|
|
298
|
+
return source4;
|
|
299
|
+
}
|
|
300
|
+
if (position === "start") {
|
|
301
|
+
const insertionIndex = bodyRange.openBraceIndex + 1;
|
|
302
|
+
return `${source4.slice(0, insertionIndex)}
|
|
303
|
+
${fragmentString}${source4.slice(insertionIndex)}`;
|
|
304
|
+
}
|
|
305
|
+
return `${source4.slice(0, bodyRange.closeBraceIndex)}${fragmentString}${source4.slice(bodyRange.closeBraceIndex)}`;
|
|
306
|
+
}
|
|
307
|
+
function getWGSLStageFunctionBodyRange(source4, stage, entryPoint) {
|
|
308
|
+
const stageAttribute = stage === "vertex" ? "@vertex" : "@fragment";
|
|
309
|
+
const stageIndex = source4.indexOf(stageAttribute);
|
|
310
|
+
if (stageIndex < 0) {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
const functionIndex = entryPoint ? source4.search(new RegExp(`\\bfn\\s+${escapeRegExp(entryPoint)}\\s*\\(`)) : source4.indexOf("fn", stageIndex);
|
|
314
|
+
if (functionIndex < 0) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
const openBraceIndex = source4.indexOf("{", functionIndex);
|
|
318
|
+
if (openBraceIndex < 0) {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
let braceDepth = 0;
|
|
322
|
+
for (let index = openBraceIndex; index < source4.length; index++) {
|
|
323
|
+
const character = source4[index];
|
|
324
|
+
if (character === "{") {
|
|
325
|
+
braceDepth++;
|
|
326
|
+
} else if (character === "}") {
|
|
327
|
+
braceDepth--;
|
|
328
|
+
if (braceDepth === 0) {
|
|
329
|
+
return { openBraceIndex, closeBraceIndex: index };
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
function escapeRegExp(value) {
|
|
336
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
337
|
+
}
|
|
284
338
|
|
|
285
339
|
// dist/lib/shader-module/shader-module.js
|
|
286
340
|
function initializeShaderModules(modules) {
|
|
@@ -392,6 +446,97 @@ function resolveModules(modules) {
|
|
|
392
446
|
return getShaderDependencies(modules);
|
|
393
447
|
}
|
|
394
448
|
|
|
449
|
+
// dist/lib/shader-plugin.js
|
|
450
|
+
var import_core = require("@luma.gl/core");
|
|
451
|
+
var SHADER_PLUGIN_INJECTION_TARGET_REGEX = /^(vs|fs):(?:#(?:decl|main-start|main-end)|[A-Za-z_][\w-]*)$/;
|
|
452
|
+
function resolveShaderPlugins(plugins = [], shaderLanguage) {
|
|
453
|
+
const modules = [];
|
|
454
|
+
const defines = {};
|
|
455
|
+
const injections = {};
|
|
456
|
+
const vertexInputs = {};
|
|
457
|
+
const varyings = {};
|
|
458
|
+
for (const plugin of plugins) {
|
|
459
|
+
appendShaderPluginVariant({ modules, defines, injections, vertexInputs, varyings }, plugin);
|
|
460
|
+
appendShaderPluginVariant({ modules, defines, injections, vertexInputs, varyings }, plugin[shaderLanguage]);
|
|
461
|
+
}
|
|
462
|
+
for (const name of Object.keys(varyings)) {
|
|
463
|
+
if (vertexInputs[name]) {
|
|
464
|
+
throw new Error(`ShaderPlugin name "${name}" cannot be both a vertex input and a varying`);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return { modules, defines, injections, vertexInputs, varyings };
|
|
468
|
+
}
|
|
469
|
+
function mergeShaderPluginModules(modules = [], pluginModules = []) {
|
|
470
|
+
const mergedModules = [...modules];
|
|
471
|
+
const seenModuleNames = new Set(mergedModules.map((module2) => module2.name));
|
|
472
|
+
for (const pluginModule of pluginModules) {
|
|
473
|
+
if (!seenModuleNames.has(pluginModule.name)) {
|
|
474
|
+
mergedModules.push(pluginModule);
|
|
475
|
+
seenModuleNames.add(pluginModule.name);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return mergedModules;
|
|
479
|
+
}
|
|
480
|
+
function appendShaderPluginVariant(resolved, variant) {
|
|
481
|
+
var _a;
|
|
482
|
+
if (!variant) {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
if ((_a = variant.modules) == null ? void 0 : _a.length) {
|
|
486
|
+
resolved.modules.push(...variant.modules);
|
|
487
|
+
}
|
|
488
|
+
if (variant.defines) {
|
|
489
|
+
Object.assign(resolved.defines, variant.defines);
|
|
490
|
+
}
|
|
491
|
+
for (const [name, type] of Object.entries(variant.vertexInputs || {})) {
|
|
492
|
+
assertShaderPluginInterfaceName(name, "vertex input");
|
|
493
|
+
const existingType = resolved.vertexInputs[name];
|
|
494
|
+
if (existingType && existingType !== type) {
|
|
495
|
+
throw new Error(`ShaderPlugin vertex input "${name}" has conflicting types "${existingType}" and "${type}"`);
|
|
496
|
+
}
|
|
497
|
+
resolved.vertexInputs[name] = type;
|
|
498
|
+
}
|
|
499
|
+
for (const [name, varying] of Object.entries(variant.varyings || {})) {
|
|
500
|
+
assertShaderPluginInterfaceName(name, "varying");
|
|
501
|
+
const normalizedVarying = normalizeShaderPluginVarying(name, varying);
|
|
502
|
+
const existingVarying = resolved.varyings[name];
|
|
503
|
+
if (existingVarying && (existingVarying.type !== normalizedVarying.type || existingVarying.interpolation !== normalizedVarying.interpolation)) {
|
|
504
|
+
throw new Error(`ShaderPlugin varying "${name}" has conflicting declarations "${existingVarying.type}/${existingVarying.interpolation}" and "${normalizedVarying.type}/${normalizedVarying.interpolation}"`);
|
|
505
|
+
}
|
|
506
|
+
resolved.varyings[name] = normalizedVarying;
|
|
507
|
+
}
|
|
508
|
+
for (const injection of variant.injections || []) {
|
|
509
|
+
assertNamedShaderPluginInjectionTarget(injection.target);
|
|
510
|
+
if (!resolved.injections[injection.target]) {
|
|
511
|
+
resolved.injections[injection.target] = [];
|
|
512
|
+
}
|
|
513
|
+
const injections = resolved.injections[injection.target];
|
|
514
|
+
injections.push({
|
|
515
|
+
injection: injection.injection,
|
|
516
|
+
order: injection.order ?? 0
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
function assertShaderPluginInterfaceName(name, kind) {
|
|
521
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name) || name.startsWith("_luma_")) {
|
|
522
|
+
throw new Error(`ShaderPlugin ${kind} "${name}" must be a valid non-reserved identifier`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function normalizeShaderPluginVarying(name, varying) {
|
|
526
|
+
const { primitiveType } = import_core.shaderTypeDecoder.getAttributeShaderTypeInfo(varying.type);
|
|
527
|
+
const integerType = primitiveType === "i32" || primitiveType === "u32";
|
|
528
|
+
const interpolation = varying.interpolation || (integerType ? "flat" : "smooth");
|
|
529
|
+
if (integerType && interpolation === "smooth") {
|
|
530
|
+
throw new Error(`ShaderPlugin integer varying "${name}" must use flat interpolation`);
|
|
531
|
+
}
|
|
532
|
+
return { type: varying.type, interpolation };
|
|
533
|
+
}
|
|
534
|
+
function assertNamedShaderPluginInjectionTarget(target) {
|
|
535
|
+
if (!SHADER_PLUGIN_INJECTION_TARGET_REGEX.test(target)) {
|
|
536
|
+
throw new Error(`ShaderPlugin injection target "${target}" must be a named shader anchor or hook`);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
395
540
|
// dist/lib/shader-module/shader-module-uniform-layout.js
|
|
396
541
|
var GLSL_UNIFORM_BLOCK_FIELD_REGEXP = /^(?:uniform\s+)?(?:(?:lowp|mediump|highp)\s+)?[A-Za-z0-9_]+(?:<[^>]+>)?\s+([A-Za-z0-9_]+)(?:\s*\[[^\]]+\])?\s*;/;
|
|
397
542
|
var GLSL_UNIFORM_BLOCK_REGEXP = /((?:layout\s*\([^)]*\)\s*)*)uniform\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{([\s\S]*?)\}\s*([A-Za-z_][A-Za-z0-9_]*)?\s*;/g;
|
|
@@ -684,11 +829,12 @@ function makeVariableTextRegExp(qualifier) {
|
|
|
684
829
|
}
|
|
685
830
|
|
|
686
831
|
// dist/lib/shader-assembly/shader-hooks.js
|
|
687
|
-
function getShaderHooks(hookFunctions, hookInjections) {
|
|
832
|
+
function getShaderHooks(hookFunctions, hookInjections, shaderLanguage = "glsl") {
|
|
688
833
|
let result = "";
|
|
689
834
|
for (const hookName in hookFunctions) {
|
|
690
835
|
const hookFunction = hookFunctions[hookName];
|
|
691
|
-
|
|
836
|
+
const functionPrefix = shaderLanguage === "wgsl" ? "fn" : "void";
|
|
837
|
+
result += `${functionPrefix} ${hookFunction.signature} {
|
|
692
838
|
`;
|
|
693
839
|
if (hookFunction.header) {
|
|
694
840
|
result += ` ${hookFunction.header}`;
|
|
@@ -721,7 +867,9 @@ function normalizeShaderHooks(hookFunctions) {
|
|
|
721
867
|
hook = hookFunction;
|
|
722
868
|
}
|
|
723
869
|
hook = hook.trim();
|
|
724
|
-
const
|
|
870
|
+
const stageSeparatorIndex = hook.indexOf(":");
|
|
871
|
+
const shaderStage = hook.slice(0, stageSeparatorIndex);
|
|
872
|
+
const signature = hook.slice(stageSeparatorIndex + 1);
|
|
725
873
|
const name = hook.replace(/\(.+/, "");
|
|
726
874
|
const normalizedHook = Object.assign(opts, { signature });
|
|
727
875
|
switch (shaderStage) {
|
|
@@ -1051,140 +1199,856 @@ function getStorageTextureAccess(resourceType) {
|
|
|
1051
1199
|
return match == null ? void 0 : match[1];
|
|
1052
1200
|
}
|
|
1053
1201
|
|
|
1054
|
-
// dist/lib/
|
|
1055
|
-
var
|
|
1202
|
+
// dist/lib/preprocessor/preprocessor.js
|
|
1203
|
+
var DEFINE_NAME_PATTERN = "([a-zA-Z_][a-zA-Z0-9_]*)";
|
|
1204
|
+
var IF_REGEXP = /^\s*\#\s*if\s+(.+?)\s*(?:\/\/.*)?$/;
|
|
1205
|
+
var IFDEF_REGEXP = new RegExp(`^\\s*\\#\\s*ifdef\\s*${DEFINE_NAME_PATTERN}\\s*$`);
|
|
1206
|
+
var IFNDEF_REGEXP = new RegExp(`^\\s*\\#\\s*ifndef\\s*${DEFINE_NAME_PATTERN}\\s*(?:\\/\\/.*)?$`);
|
|
1207
|
+
var ELSE_REGEXP = /^\s*\#\s*else\s*(?:\/\/.*)?$/;
|
|
1208
|
+
var ENDIF_REGEXP = /^\s*\#\s*endif\s*$/;
|
|
1209
|
+
var IFDEF_WITH_COMMENT_REGEXP = new RegExp(`^\\s*\\#\\s*ifdef\\s*${DEFINE_NAME_PATTERN}\\s*(?:\\/\\/.*)?$`);
|
|
1210
|
+
var ENDIF_WITH_COMMENT_REGEXP = /^\s*\#\s*endif\s*(?:\/\/.*)?$/;
|
|
1211
|
+
function preprocess(source4, options) {
|
|
1212
|
+
var _a, _b;
|
|
1213
|
+
const lines = source4.split("\n");
|
|
1214
|
+
const output = [];
|
|
1215
|
+
const conditionalStack = [];
|
|
1216
|
+
let conditional = true;
|
|
1217
|
+
for (const line of lines) {
|
|
1218
|
+
const matchIfExpression = line.match(IF_REGEXP);
|
|
1219
|
+
const matchIf = line.match(IFDEF_WITH_COMMENT_REGEXP) || line.match(IFDEF_REGEXP);
|
|
1220
|
+
const matchIfNot = line.match(IFNDEF_REGEXP);
|
|
1221
|
+
const matchElse = line.match(ELSE_REGEXP);
|
|
1222
|
+
const matchEnd = line.match(ENDIF_WITH_COMMENT_REGEXP) || line.match(ENDIF_REGEXP);
|
|
1223
|
+
if (matchIfExpression) {
|
|
1224
|
+
const branchTaken = evaluateIfExpression(matchIfExpression[1], (options == null ? void 0 : options.defines) || {});
|
|
1225
|
+
const active = conditional && branchTaken;
|
|
1226
|
+
conditionalStack.push({ parentActive: conditional, branchTaken, active });
|
|
1227
|
+
conditional = active;
|
|
1228
|
+
} else if (matchIf || matchIfNot) {
|
|
1229
|
+
const defineName = (_a = matchIf || matchIfNot) == null ? void 0 : _a[1];
|
|
1230
|
+
const defineValue = Boolean((_b = options == null ? void 0 : options.defines) == null ? void 0 : _b[defineName]);
|
|
1231
|
+
const branchTaken = matchIf ? defineValue : !defineValue;
|
|
1232
|
+
const active = conditional && branchTaken;
|
|
1233
|
+
conditionalStack.push({ parentActive: conditional, branchTaken, active });
|
|
1234
|
+
conditional = active;
|
|
1235
|
+
} else if (matchElse) {
|
|
1236
|
+
const currentConditional = conditionalStack[conditionalStack.length - 1];
|
|
1237
|
+
if (!currentConditional) {
|
|
1238
|
+
throw new Error("Encountered #else without matching #if, #ifdef or #ifndef");
|
|
1239
|
+
}
|
|
1240
|
+
currentConditional.active = currentConditional.parentActive && !currentConditional.branchTaken;
|
|
1241
|
+
currentConditional.branchTaken = true;
|
|
1242
|
+
conditional = currentConditional.active;
|
|
1243
|
+
} else if (matchEnd) {
|
|
1244
|
+
conditionalStack.pop();
|
|
1245
|
+
conditional = conditionalStack.length ? conditionalStack[conditionalStack.length - 1].active : true;
|
|
1246
|
+
} else if (conditional) {
|
|
1247
|
+
output.push(line);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
if (conditionalStack.length > 0) {
|
|
1251
|
+
throw new Error("Unterminated conditional block in shader source");
|
|
1252
|
+
}
|
|
1253
|
+
return output.join("\n");
|
|
1254
|
+
}
|
|
1255
|
+
function evaluateIfExpression(expression, defines) {
|
|
1256
|
+
const trimmedExpression = expression.trim();
|
|
1257
|
+
if (/^[+-]?\d+(?:\.\d+)?$/.test(trimmedExpression)) {
|
|
1258
|
+
return Number(trimmedExpression) !== 0;
|
|
1259
|
+
}
|
|
1260
|
+
if (trimmedExpression === "true") {
|
|
1261
|
+
return true;
|
|
1262
|
+
}
|
|
1263
|
+
if (trimmedExpression === "false") {
|
|
1264
|
+
return false;
|
|
1265
|
+
}
|
|
1266
|
+
const negatedDefineMatch = trimmedExpression.match(new RegExp(`^!\\s*${DEFINE_NAME_PATTERN}$`));
|
|
1267
|
+
if (negatedDefineMatch) {
|
|
1268
|
+
return !Boolean(defines[negatedDefineMatch[1]]);
|
|
1269
|
+
}
|
|
1270
|
+
const defineMatch = trimmedExpression.match(new RegExp(`^${DEFINE_NAME_PATTERN}$`));
|
|
1271
|
+
if (defineMatch) {
|
|
1272
|
+
return Boolean(defines[defineMatch[1]]);
|
|
1273
|
+
}
|
|
1274
|
+
const definedMatch = trimmedExpression.match(new RegExp(`^defined\\s*\\(\\s*${DEFINE_NAME_PATTERN}\\s*\\)$`));
|
|
1275
|
+
if (definedMatch) {
|
|
1276
|
+
return defines[definedMatch[1]] !== void 0;
|
|
1277
|
+
}
|
|
1278
|
+
const negatedDefinedMatch = trimmedExpression.match(new RegExp(`^!\\s*defined\\s*\\(\\s*${DEFINE_NAME_PATTERN}\\s*\\)$`));
|
|
1279
|
+
if (negatedDefinedMatch) {
|
|
1280
|
+
return defines[negatedDefinedMatch[1]] === void 0;
|
|
1281
|
+
}
|
|
1282
|
+
throw new Error(`Unsupported #if expression "${expression}"`);
|
|
1283
|
+
}
|
|
1056
1284
|
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
`
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1285
|
+
// dist/lib/shader-assembly/shader-plugin-vertex-inputs.js
|
|
1286
|
+
var import_core2 = require("@luma.gl/core");
|
|
1287
|
+
function getShaderPluginVertexInputDeclarationsGLSL(source4, vertexInputs) {
|
|
1288
|
+
const declarations = [];
|
|
1289
|
+
for (const [name, type] of Object.entries(vertexInputs)) {
|
|
1290
|
+
assertGLSLVertexInputIsNew(source4, name);
|
|
1291
|
+
declarations.push(`in ${getGLSLAttributeType(type)} ${name};`);
|
|
1292
|
+
}
|
|
1293
|
+
return declarations.join("\n");
|
|
1294
|
+
}
|
|
1295
|
+
function assembleShaderPluginVertexInputsWGSL(source4, vertexEntryPoint, vertexInputs) {
|
|
1296
|
+
const entries = Object.entries(vertexInputs);
|
|
1297
|
+
if (entries.length === 0) {
|
|
1298
|
+
return { source: source4, declarations: "", initialization: "" };
|
|
1299
|
+
}
|
|
1300
|
+
const functionRange = getWGSLFunctionParameterRange(source4, vertexEntryPoint);
|
|
1301
|
+
const parameterSource = source4.slice(functionRange.openParenthesis + 1, functionRange.closeParenthesis);
|
|
1302
|
+
const interfaceInfo = getWGSLVertexInterfaceInfo(source4, parameterSource);
|
|
1303
|
+
const usedLocations = new Set(interfaceInfo.locations);
|
|
1304
|
+
const generatedParameters = [];
|
|
1305
|
+
const declarations = [];
|
|
1306
|
+
const initialization = [];
|
|
1307
|
+
for (const [name, type] of entries) {
|
|
1308
|
+
if (interfaceInfo.names.has(name) || hasWGSLModuleVariable(source4, name)) {
|
|
1309
|
+
throw new Error(`ShaderPlugin vertex input "${name}" conflicts with an existing WGSL shader input or variable`);
|
|
1310
|
+
}
|
|
1311
|
+
const location = getFirstUnusedLocation(usedLocations);
|
|
1312
|
+
usedLocations.add(location);
|
|
1313
|
+
const parameterName = `_luma_${name}`;
|
|
1314
|
+
generatedParameters.push(`@location(${location}) ${parameterName}: ${type}`);
|
|
1315
|
+
declarations.push(`var<private> ${name}: ${type};`);
|
|
1316
|
+
initialization.push(`${name} = ${parameterName};`);
|
|
1317
|
+
}
|
|
1318
|
+
const separator = parameterSource.trim() ? ",\n " : "\n ";
|
|
1319
|
+
const suffix = parameterSource.trim() ? "" : "\n";
|
|
1320
|
+
const injectedParameters = `${parameterSource}${separator}${generatedParameters.join(",\n ")}${suffix}`;
|
|
1321
|
+
const transformedSource = source4.slice(0, functionRange.openParenthesis + 1) + injectedParameters + source4.slice(functionRange.closeParenthesis);
|
|
1073
1322
|
return {
|
|
1074
|
-
source:
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
bindingTable: getShaderBindingDebugRowsFromWGSL(source4, bindingAssignments)
|
|
1323
|
+
source: transformedSource,
|
|
1324
|
+
declarations: declarations.join("\n"),
|
|
1325
|
+
initialization: initialization.join("\n")
|
|
1078
1326
|
};
|
|
1079
1327
|
}
|
|
1080
|
-
function
|
|
1081
|
-
const {
|
|
1082
|
-
const
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1328
|
+
function getGLSLAttributeType(type) {
|
|
1329
|
+
const { primitiveType, components } = import_core2.shaderTypeDecoder.getAttributeShaderTypeInfo(type);
|
|
1330
|
+
const scalarType = primitiveType === "i32" ? "int" : primitiveType === "u32" ? "uint" : "float";
|
|
1331
|
+
if (components === 1) {
|
|
1332
|
+
return scalarType;
|
|
1333
|
+
}
|
|
1334
|
+
const prefix = scalarType === "int" ? "i" : scalarType === "uint" ? "u" : "";
|
|
1335
|
+
return `${prefix}vec${components}`;
|
|
1336
|
+
}
|
|
1337
|
+
function assertGLSLVertexInputIsNew(source4, name) {
|
|
1338
|
+
const escapedName = escapeRegExp2(name);
|
|
1339
|
+
const declaration = new RegExp(`\\b(?:in|attribute)\\s+(?:(?:lowp|mediump|highp)\\s+)?[A-Za-z_][A-Za-z0-9_]*\\s+${escapedName}\\s*(?:\\[|;)`);
|
|
1340
|
+
if (declaration.test(source4)) {
|
|
1341
|
+
throw new Error(`ShaderPlugin vertex input "${name}" conflicts with an existing GLSL input`);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
function getWGSLFunctionParameterRange(source4, entryPoint) {
|
|
1345
|
+
const functionPattern = new RegExp(`\\bfn\\s+${escapeRegExp2(entryPoint)}\\s*\\(`, "g");
|
|
1346
|
+
const match = functionPattern.exec(source4);
|
|
1347
|
+
if (!match) {
|
|
1348
|
+
throw new Error(`ShaderPlugin vertex inputs require WGSL vertex entry point "${entryPoint}"`);
|
|
1349
|
+
}
|
|
1350
|
+
const openParenthesis = source4.indexOf("(", match.index);
|
|
1351
|
+
const closeParenthesis = findMatchingDelimiter(source4, openParenthesis, "(", ")");
|
|
1352
|
+
if (closeParenthesis < 0) {
|
|
1353
|
+
throw new Error(`Unable to parse WGSL vertex entry point "${entryPoint}" parameters`);
|
|
1354
|
+
}
|
|
1355
|
+
return { openParenthesis, closeParenthesis };
|
|
1356
|
+
}
|
|
1357
|
+
function getWGSLVertexInterfaceInfo(source4, parameterSource) {
|
|
1358
|
+
const locations = getWGSLLocations(parameterSource);
|
|
1359
|
+
const names = new Set(getWGSLDeclaredNames(parameterSource));
|
|
1360
|
+
const parameterTypes = getWGSLParameterTypes(parameterSource);
|
|
1361
|
+
for (const parameterType of parameterTypes) {
|
|
1362
|
+
const structBody = getWGSLStructBody(source4, parameterType);
|
|
1363
|
+
if (structBody === null) {
|
|
1364
|
+
continue;
|
|
1365
|
+
}
|
|
1366
|
+
locations.push(...getWGSLLocations(structBody));
|
|
1367
|
+
for (const name of getWGSLDeclaredNames(structBody)) {
|
|
1368
|
+
names.add(name);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return { locations, names };
|
|
1099
1372
|
}
|
|
1100
|
-
function
|
|
1101
|
-
|
|
1102
|
-
const
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1373
|
+
function getWGSLLocations(source4) {
|
|
1374
|
+
const locations = [];
|
|
1375
|
+
const locationPattern = /@location\s*\(\s*(\d+)\s*\)/g;
|
|
1376
|
+
let match = locationPattern.exec(source4);
|
|
1377
|
+
while (match) {
|
|
1378
|
+
locations.push(Number(match[1]));
|
|
1379
|
+
match = locationPattern.exec(source4);
|
|
1380
|
+
}
|
|
1381
|
+
return locations;
|
|
1382
|
+
}
|
|
1383
|
+
function getWGSLDeclaredNames(source4) {
|
|
1384
|
+
const names = [];
|
|
1385
|
+
const namePattern = /(?:^|,)\s*(?:@[A-Za-z_][\w]*(?:\([^)]*\))?\s*)*([A-Za-z_][\w]*)\s*:/gm;
|
|
1386
|
+
let match = namePattern.exec(source4);
|
|
1387
|
+
while (match) {
|
|
1388
|
+
names.push(match[1]);
|
|
1389
|
+
match = namePattern.exec(source4);
|
|
1390
|
+
}
|
|
1391
|
+
return names;
|
|
1392
|
+
}
|
|
1393
|
+
function getWGSLParameterTypes(source4) {
|
|
1394
|
+
const types = [];
|
|
1395
|
+
const typePattern = /:\s*([A-Za-z_][\w]*)\b/g;
|
|
1396
|
+
let match = typePattern.exec(source4);
|
|
1397
|
+
while (match) {
|
|
1398
|
+
types.push(match[1]);
|
|
1399
|
+
match = typePattern.exec(source4);
|
|
1400
|
+
}
|
|
1401
|
+
return types;
|
|
1402
|
+
}
|
|
1403
|
+
function getWGSLStructBody(source4, structName) {
|
|
1404
|
+
const structPattern = new RegExp(`\\bstruct\\s+${escapeRegExp2(structName)}\\s*\\{`, "g");
|
|
1405
|
+
const match = structPattern.exec(source4);
|
|
1406
|
+
if (!match) {
|
|
1407
|
+
return null;
|
|
1408
|
+
}
|
|
1409
|
+
const openBrace = source4.indexOf("{", match.index);
|
|
1410
|
+
const closeBrace = findMatchingDelimiter(source4, openBrace, "{", "}");
|
|
1411
|
+
return closeBrace < 0 ? null : source4.slice(openBrace + 1, closeBrace);
|
|
1412
|
+
}
|
|
1413
|
+
function hasWGSLModuleVariable(source4, name) {
|
|
1414
|
+
const escapedName = escapeRegExp2(name);
|
|
1415
|
+
const variablePattern = new RegExp(`\\b(?:var(?:<[^>]+>)?|let|const)\\s+${escapedName}\\b`, "g");
|
|
1416
|
+
let match = variablePattern.exec(source4);
|
|
1417
|
+
while (match) {
|
|
1418
|
+
if (getBraceDepthAt(source4, match.index) === 0) {
|
|
1419
|
+
return true;
|
|
1136
1420
|
}
|
|
1421
|
+
match = variablePattern.exec(source4);
|
|
1137
1422
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1423
|
+
return false;
|
|
1424
|
+
}
|
|
1425
|
+
function getFirstUnusedLocation(usedLocations) {
|
|
1426
|
+
let location = 0;
|
|
1427
|
+
while (usedLocations.has(location)) {
|
|
1428
|
+
location++;
|
|
1429
|
+
}
|
|
1430
|
+
return location;
|
|
1431
|
+
}
|
|
1432
|
+
function findMatchingDelimiter(source4, openIndex, openCharacter, closeCharacter) {
|
|
1433
|
+
let depth = 0;
|
|
1434
|
+
let blockCommentDepth = 0;
|
|
1435
|
+
let lineComment = false;
|
|
1436
|
+
for (let index = openIndex; index < source4.length; index++) {
|
|
1437
|
+
const character = source4[index];
|
|
1438
|
+
const nextCharacter = source4[index + 1];
|
|
1439
|
+
if (lineComment) {
|
|
1440
|
+
if (character === "\n")
|
|
1441
|
+
lineComment = false;
|
|
1442
|
+
continue;
|
|
1146
1443
|
}
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
assembledSource += moduleSource;
|
|
1155
|
-
const injections = ((_a = module2.injections) == null ? void 0 : _a[stage]) || {};
|
|
1156
|
-
for (const key in injections) {
|
|
1157
|
-
const match = /^(v|f)s:#([\w-]+)$/.exec(key);
|
|
1158
|
-
if (match) {
|
|
1159
|
-
const name = match[2];
|
|
1160
|
-
const injectionType = name === "decl" ? declInjections : mainInjections;
|
|
1161
|
-
injectionType[key] = injectionType[key] || [];
|
|
1162
|
-
injectionType[key].push(injections[key]);
|
|
1163
|
-
} else {
|
|
1164
|
-
hookInjections[key] = hookInjections[key] || [];
|
|
1165
|
-
hookInjections[key].push(injections[key]);
|
|
1444
|
+
if (blockCommentDepth > 0) {
|
|
1445
|
+
if (character === "/" && nextCharacter === "*") {
|
|
1446
|
+
blockCommentDepth++;
|
|
1447
|
+
index++;
|
|
1448
|
+
} else if (character === "*" && nextCharacter === "/") {
|
|
1449
|
+
blockCommentDepth--;
|
|
1450
|
+
index++;
|
|
1166
1451
|
}
|
|
1452
|
+
continue;
|
|
1453
|
+
}
|
|
1454
|
+
if (character === "/" && nextCharacter === "/") {
|
|
1455
|
+
lineComment = true;
|
|
1456
|
+
index++;
|
|
1457
|
+
continue;
|
|
1458
|
+
}
|
|
1459
|
+
if (character === "/" && nextCharacter === "*") {
|
|
1460
|
+
blockCommentDepth = 1;
|
|
1461
|
+
index++;
|
|
1462
|
+
continue;
|
|
1167
1463
|
}
|
|
1464
|
+
if (character === openCharacter)
|
|
1465
|
+
depth++;
|
|
1466
|
+
if (character === closeCharacter && --depth === 0)
|
|
1467
|
+
return index;
|
|
1168
1468
|
}
|
|
1169
|
-
|
|
1170
|
-
assembledSource = injectShader(assembledSource, stage, declInjections);
|
|
1171
|
-
assembledSource += getShaderHooks(hookFunctionMap[stage], hookInjections);
|
|
1172
|
-
assembledSource += formatWGSLBindingAssignmentComments(bindingAssignments);
|
|
1173
|
-
assembledSource += applicationRelocation.source;
|
|
1174
|
-
assembledSource = injectShader(assembledSource, stage, mainInjections);
|
|
1175
|
-
assertNoUnresolvedAutoBindings(assembledSource);
|
|
1176
|
-
return { source: assembledSource, bindingAssignments };
|
|
1469
|
+
return -1;
|
|
1177
1470
|
}
|
|
1178
|
-
function
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1471
|
+
function getBraceDepthAt(source4, endIndex) {
|
|
1472
|
+
let depth = 0;
|
|
1473
|
+
let blockCommentDepth = 0;
|
|
1474
|
+
let lineComment = false;
|
|
1475
|
+
for (let index = 0; index < endIndex; index++) {
|
|
1476
|
+
const character = source4[index];
|
|
1477
|
+
const nextCharacter = source4[index + 1];
|
|
1478
|
+
if (lineComment) {
|
|
1479
|
+
if (character === "\n")
|
|
1480
|
+
lineComment = false;
|
|
1481
|
+
continue;
|
|
1482
|
+
}
|
|
1483
|
+
if (blockCommentDepth > 0) {
|
|
1484
|
+
if (character === "/" && nextCharacter === "*") {
|
|
1485
|
+
blockCommentDepth++;
|
|
1486
|
+
index++;
|
|
1487
|
+
} else if (character === "*" && nextCharacter === "/") {
|
|
1488
|
+
blockCommentDepth--;
|
|
1489
|
+
index++;
|
|
1490
|
+
}
|
|
1491
|
+
continue;
|
|
1492
|
+
}
|
|
1493
|
+
if (character === "/" && nextCharacter === "/") {
|
|
1494
|
+
lineComment = true;
|
|
1495
|
+
index++;
|
|
1496
|
+
} else if (character === "/" && nextCharacter === "*") {
|
|
1497
|
+
blockCommentDepth = 1;
|
|
1498
|
+
index++;
|
|
1499
|
+
} else if (character === "{") {
|
|
1500
|
+
depth++;
|
|
1501
|
+
} else if (character === "}") {
|
|
1502
|
+
depth--;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
return depth;
|
|
1506
|
+
}
|
|
1507
|
+
function escapeRegExp2(value) {
|
|
1508
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
// dist/lib/shader-assembly/shader-plugin-varyings.js
|
|
1512
|
+
var import_core3 = require("@luma.gl/core");
|
|
1513
|
+
function assembleShaderPluginVaryingsGLSL(source4, stage, varyings) {
|
|
1514
|
+
const declarations = [];
|
|
1515
|
+
const initialization = [];
|
|
1516
|
+
for (const [name, varying] of Object.entries(varyings)) {
|
|
1517
|
+
assertGLSLVaryingIsNew(source4, name);
|
|
1518
|
+
const qualifier = varying.interpolation === "flat" ? "flat " : "";
|
|
1519
|
+
const direction = stage === "vertex" ? "out" : "in";
|
|
1520
|
+
declarations.push(`${qualifier}${direction} ${getGLSLAttributeType(varying.type)} ${name};`);
|
|
1521
|
+
if (stage === "vertex") {
|
|
1522
|
+
initialization.push(`${name} = ${getGLSLZeroValue(varying.type)};`);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
return { declarations: declarations.join("\n"), initialization: initialization.join("\n") };
|
|
1526
|
+
}
|
|
1527
|
+
function assembleShaderPluginVaryingsWGSL(source4, vertexEntryPoint, fragmentEntryPoint, varyings) {
|
|
1528
|
+
const entries = Object.entries(varyings);
|
|
1529
|
+
if (entries.length === 0) {
|
|
1530
|
+
return {
|
|
1531
|
+
source: source4,
|
|
1532
|
+
declarations: "",
|
|
1533
|
+
vertexInitialization: "",
|
|
1534
|
+
fragmentInitialization: ""
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
let transformedSource = source4;
|
|
1538
|
+
let vertexFunction = getWGSLFunctionRange(transformedSource, vertexEntryPoint, "vertex");
|
|
1539
|
+
const vertexOutputType = getWGSLNamedReturnType(transformedSource, vertexFunction);
|
|
1540
|
+
let fragmentFunction = getWGSLFunctionRange(transformedSource, fragmentEntryPoint, "fragment");
|
|
1541
|
+
const fragmentInput = getWGSLFragmentStructInput(transformedSource, fragmentFunction);
|
|
1542
|
+
const vertexOutputStruct = getWGSLStructRange(transformedSource, vertexOutputType);
|
|
1543
|
+
const fragmentInputStruct = getWGSLStructRange(transformedSource, fragmentInput.type);
|
|
1544
|
+
const interfaceNames = /* @__PURE__ */ new Set([
|
|
1545
|
+
...getWGSLDeclaredNames2(vertexFunction.parameters),
|
|
1546
|
+
...getWGSLDeclaredNames2(vertexOutputStruct.body),
|
|
1547
|
+
...getWGSLDeclaredNames2(fragmentFunction.parameters),
|
|
1548
|
+
...getWGSLDeclaredNames2(fragmentInputStruct.body)
|
|
1549
|
+
]);
|
|
1550
|
+
const usedLocations = /* @__PURE__ */ new Set([
|
|
1551
|
+
...getWGSLLocations2(vertexOutputStruct.body),
|
|
1552
|
+
...getWGSLLocations2(fragmentInputStruct.body)
|
|
1553
|
+
]);
|
|
1554
|
+
const fields = [];
|
|
1555
|
+
const declarations = [];
|
|
1556
|
+
const vertexInitialization = [];
|
|
1557
|
+
const fragmentInitialization = [];
|
|
1558
|
+
for (const [name, varying] of entries) {
|
|
1559
|
+
if (interfaceNames.has(name) || hasWGSLModuleVariable2(transformedSource, name)) {
|
|
1560
|
+
throw new Error(`ShaderPlugin varying "${name}" conflicts with existing WGSL stage I/O or a module variable`);
|
|
1561
|
+
}
|
|
1562
|
+
const location = getFirstUnusedLocation2(usedLocations);
|
|
1563
|
+
usedLocations.add(location);
|
|
1564
|
+
const interpolation = varying.interpolation === "flat" ? " @interpolate(flat)" : "";
|
|
1565
|
+
fields.push(` @location(${location})${interpolation} ${name}: ${varying.type},`);
|
|
1566
|
+
declarations.push(`var<private> ${name}: ${varying.type};`);
|
|
1567
|
+
vertexInitialization.push(`${name} = ${getWGSLZeroValue(varying.type)};`);
|
|
1568
|
+
fragmentInitialization.push(`${name} = ${fragmentInput.name}.${name};`);
|
|
1569
|
+
}
|
|
1570
|
+
assertWGSLStructConstructorsAreLocal(transformedSource, vertexOutputType, vertexFunction.openBrace, vertexFunction.closeBrace);
|
|
1571
|
+
transformedSource = appendWGSLConstructorArgumentsInFunction(transformedSource, vertexOutputType, vertexFunction, entries.map(([name]) => name));
|
|
1572
|
+
vertexFunction = getWGSLFunctionRange(transformedSource, vertexEntryPoint, "vertex");
|
|
1573
|
+
transformedSource = rewriteWGSLVertexReturns(transformedSource, vertexFunction, entries.map(([name]) => name));
|
|
1574
|
+
const structNames = vertexOutputType === fragmentInput.type ? [vertexOutputType] : [vertexOutputType, fragmentInput.type];
|
|
1575
|
+
const structInsertions = structNames.map((structName) => getWGSLStructRange(transformedSource, structName).closeBrace).sort((left, right) => right - left);
|
|
1576
|
+
for (const insertionIndex of structInsertions) {
|
|
1577
|
+
transformedSource = transformedSource.slice(0, insertionIndex) + `${fields.join("\n")}
|
|
1578
|
+
` + transformedSource.slice(insertionIndex);
|
|
1579
|
+
}
|
|
1580
|
+
fragmentFunction = getWGSLFunctionRange(transformedSource, fragmentEntryPoint, "fragment");
|
|
1581
|
+
const fragmentInputPattern = new RegExp(`\\b${escapeRegExp3(fragmentInput.name)}\\s*:`);
|
|
1582
|
+
if (!fragmentInputPattern.test(fragmentFunction.parameters)) {
|
|
1583
|
+
throw new Error(`Unable to preserve WGSL fragment input "${fragmentInput.name}"`);
|
|
1584
|
+
}
|
|
1585
|
+
return {
|
|
1586
|
+
source: transformedSource,
|
|
1587
|
+
declarations: declarations.join("\n"),
|
|
1588
|
+
vertexInitialization: vertexInitialization.join("\n"),
|
|
1589
|
+
fragmentInitialization: fragmentInitialization.join("\n")
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
function getWGSLFunctionRange(source4, entryPoint, stage) {
|
|
1593
|
+
const functionPattern = new RegExp(`\\bfn\\s+${escapeRegExp3(entryPoint)}\\s*\\(`, "g");
|
|
1594
|
+
const match = functionPattern.exec(source4);
|
|
1595
|
+
if (!match) {
|
|
1596
|
+
throw new Error(`ShaderPlugin varyings require WGSL ${stage} entry point "${entryPoint}"`);
|
|
1597
|
+
}
|
|
1598
|
+
const openParenthesis = source4.indexOf("(", match.index);
|
|
1599
|
+
const closeParenthesis = findMatchingDelimiter2(source4, openParenthesis, "(", ")");
|
|
1600
|
+
const openBrace = source4.indexOf("{", closeParenthesis);
|
|
1601
|
+
const closeBrace = findMatchingDelimiter2(source4, openBrace, "{", "}");
|
|
1602
|
+
if (closeParenthesis < 0 || openBrace < 0 || closeBrace < 0) {
|
|
1603
|
+
throw new Error(`Unable to parse WGSL ${stage} entry point "${entryPoint}"`);
|
|
1604
|
+
}
|
|
1605
|
+
return {
|
|
1606
|
+
openParenthesis,
|
|
1607
|
+
closeParenthesis,
|
|
1608
|
+
openBrace,
|
|
1609
|
+
closeBrace,
|
|
1610
|
+
parameters: source4.slice(openParenthesis + 1, closeParenthesis)
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
function getWGSLNamedReturnType(source4, functionRange) {
|
|
1614
|
+
const resultSource = source4.slice(functionRange.closeParenthesis + 1, functionRange.openBrace);
|
|
1615
|
+
const match = /->\s*([A-Za-z_][\w]*)\s*$/.exec(resultSource.trim());
|
|
1616
|
+
if (!match || getWGSLStructRangeOrNull(source4, match[1]) === null) {
|
|
1617
|
+
throw new Error("ShaderPlugin varyings require the WGSL vertex entry point to return a named struct");
|
|
1618
|
+
}
|
|
1619
|
+
return match[1];
|
|
1620
|
+
}
|
|
1621
|
+
function getWGSLFragmentStructInput(source4, functionRange) {
|
|
1622
|
+
const candidates = [];
|
|
1623
|
+
for (const parameter of splitTopLevel(functionRange.parameters, ",")) {
|
|
1624
|
+
const match = /(?:@[A-Za-z_][\w]*(?:\([^)]*\))?\s*)*([A-Za-z_][\w]*)\s*:\s*([A-Za-z_][\w]*)\s*$/.exec(parameter.trim());
|
|
1625
|
+
if (match && getWGSLStructRangeOrNull(source4, match[2])) {
|
|
1626
|
+
candidates.push({ name: match[1], type: match[2] });
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
if (candidates.length !== 1) {
|
|
1630
|
+
throw new Error(`ShaderPlugin varyings require exactly one named WGSL fragment input struct; found ${candidates.length}`);
|
|
1631
|
+
}
|
|
1632
|
+
return candidates[0];
|
|
1633
|
+
}
|
|
1634
|
+
function getWGSLStructRange(source4, structName) {
|
|
1635
|
+
const range = getWGSLStructRangeOrNull(source4, structName);
|
|
1636
|
+
if (!range) {
|
|
1637
|
+
throw new Error(`Unable to find WGSL stage I/O struct "${structName}"`);
|
|
1638
|
+
}
|
|
1639
|
+
return range;
|
|
1640
|
+
}
|
|
1641
|
+
function getWGSLStructRangeOrNull(source4, structName) {
|
|
1642
|
+
const structPattern = new RegExp(`\\bstruct\\s+${escapeRegExp3(structName)}\\s*\\{`, "g");
|
|
1643
|
+
const match = structPattern.exec(source4);
|
|
1644
|
+
if (!match) {
|
|
1645
|
+
return null;
|
|
1646
|
+
}
|
|
1647
|
+
const openBrace = source4.indexOf("{", match.index);
|
|
1648
|
+
const closeBrace = findMatchingDelimiter2(source4, openBrace, "{", "}");
|
|
1649
|
+
return closeBrace < 0 ? null : { openBrace, closeBrace, body: source4.slice(openBrace + 1, closeBrace) };
|
|
1650
|
+
}
|
|
1651
|
+
function assertWGSLStructConstructorsAreLocal(source4, structName, functionStart, functionEnd) {
|
|
1652
|
+
const constructorPattern = new RegExp(`\\b${escapeRegExp3(structName)}\\s*\\(`, "g");
|
|
1653
|
+
let match = constructorPattern.exec(source4);
|
|
1654
|
+
while (match) {
|
|
1655
|
+
if (match.index < functionStart || match.index > functionEnd) {
|
|
1656
|
+
throw new Error(`ShaderPlugin varying output struct "${structName}" is constructed outside the selected vertex entry point`);
|
|
1657
|
+
}
|
|
1658
|
+
match = constructorPattern.exec(source4);
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
function appendWGSLConstructorArgumentsInFunction(source4, structName, functionRange, varyingNames) {
|
|
1662
|
+
const constructorPattern = new RegExp(`\\b${escapeRegExp3(structName)}\\s*\\(`, "g");
|
|
1663
|
+
const insertions = [];
|
|
1664
|
+
let match = constructorPattern.exec(source4);
|
|
1665
|
+
while (match) {
|
|
1666
|
+
if (match.index > functionRange.openBrace && match.index < functionRange.closeBrace) {
|
|
1667
|
+
const openParenthesis = source4.indexOf("(", match.index);
|
|
1668
|
+
const closeParenthesis = findMatchingDelimiter2(source4, openParenthesis, "(", ")");
|
|
1669
|
+
if (closeParenthesis < 0 || closeParenthesis > functionRange.closeBrace) {
|
|
1670
|
+
throw new Error(`Unable to parse WGSL output constructor "${structName}"`);
|
|
1671
|
+
}
|
|
1672
|
+
insertions.push({ openParenthesis, closeParenthesis });
|
|
1673
|
+
}
|
|
1674
|
+
match = constructorPattern.exec(source4);
|
|
1675
|
+
}
|
|
1676
|
+
for (const insertion of insertions.sort((left, right) => right.closeParenthesis - left.closeParenthesis)) {
|
|
1677
|
+
const existingArguments = source4.slice(insertion.openParenthesis + 1, insertion.closeParenthesis).trim();
|
|
1678
|
+
const separator = existingArguments ? ", " : "";
|
|
1679
|
+
source4 = source4.slice(0, insertion.closeParenthesis) + separator + varyingNames.join(", ") + source4.slice(insertion.closeParenthesis);
|
|
1680
|
+
}
|
|
1681
|
+
return source4;
|
|
1682
|
+
}
|
|
1683
|
+
function rewriteWGSLVertexReturns(source4, functionRange, varyingNames) {
|
|
1684
|
+
const returns = findWGSLReturnStatements(source4, functionRange.openBrace + 1, functionRange.closeBrace);
|
|
1685
|
+
for (let returnIndex = returns.length - 1; returnIndex >= 0; returnIndex--) {
|
|
1686
|
+
const statement = returns[returnIndex];
|
|
1687
|
+
const expression = source4.slice(statement.expressionStart, statement.semicolon).trim();
|
|
1688
|
+
if (!expression) {
|
|
1689
|
+
throw new Error("ShaderPlugin varying vertex entry point cannot use an empty return");
|
|
1690
|
+
}
|
|
1691
|
+
const outputName = `_luma_vertexOutput${returnIndex}`;
|
|
1692
|
+
const assignments = varyingNames.map((name) => `${outputName}.${name} = ${name};`).join("\n");
|
|
1693
|
+
const replacement = `{
|
|
1694
|
+
var ${outputName} = ${expression};
|
|
1695
|
+
${assignments}
|
|
1696
|
+
return ${outputName};
|
|
1697
|
+
}`;
|
|
1698
|
+
source4 = source4.slice(0, statement.start) + replacement + source4.slice(statement.semicolon + 1);
|
|
1699
|
+
}
|
|
1700
|
+
return source4;
|
|
1701
|
+
}
|
|
1702
|
+
function findWGSLReturnStatements(source4, startIndex, endIndex) {
|
|
1703
|
+
const statements = [];
|
|
1704
|
+
let index = startIndex;
|
|
1705
|
+
while (index < endIndex) {
|
|
1706
|
+
index = skipWGSLTrivia(source4, index, endIndex);
|
|
1707
|
+
if (source4.slice(index, index + 6) === "return" && !/[A-Za-z0-9_]/.test(source4[index + 6] || "")) {
|
|
1708
|
+
const expressionStart = index + 6;
|
|
1709
|
+
const semicolon = findStatementSemicolon(source4, expressionStart, endIndex);
|
|
1710
|
+
if (semicolon < 0) {
|
|
1711
|
+
throw new Error("Unable to parse WGSL return statement in selected vertex entry point");
|
|
1712
|
+
}
|
|
1713
|
+
statements.push({ start: index, expressionStart, semicolon });
|
|
1714
|
+
index = semicolon + 1;
|
|
1715
|
+
} else {
|
|
1716
|
+
index++;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
return statements;
|
|
1720
|
+
}
|
|
1721
|
+
function findStatementSemicolon(source4, startIndex, endIndex) {
|
|
1722
|
+
let parenthesisDepth = 0;
|
|
1723
|
+
let bracketDepth = 0;
|
|
1724
|
+
for (let index = startIndex; index < endIndex; index++) {
|
|
1725
|
+
const skippedIndex = skipWGSLTrivia(source4, index, endIndex);
|
|
1726
|
+
if (skippedIndex !== index) {
|
|
1727
|
+
index = skippedIndex - 1;
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
const character = source4[index];
|
|
1731
|
+
if (character === "(")
|
|
1732
|
+
parenthesisDepth++;
|
|
1733
|
+
if (character === ")")
|
|
1734
|
+
parenthesisDepth--;
|
|
1735
|
+
if (character === "[")
|
|
1736
|
+
bracketDepth++;
|
|
1737
|
+
if (character === "]")
|
|
1738
|
+
bracketDepth--;
|
|
1739
|
+
if (character === ";" && parenthesisDepth === 0 && bracketDepth === 0)
|
|
1740
|
+
return index;
|
|
1741
|
+
}
|
|
1742
|
+
return -1;
|
|
1743
|
+
}
|
|
1744
|
+
function skipWGSLTrivia(source4, startIndex, endIndex) {
|
|
1745
|
+
let index = startIndex;
|
|
1746
|
+
if (source4[index] === "/" && source4[index + 1] === "/") {
|
|
1747
|
+
const newline = source4.indexOf("\n", index + 2);
|
|
1748
|
+
return newline < 0 || newline > endIndex ? endIndex : newline + 1;
|
|
1749
|
+
}
|
|
1750
|
+
if (source4[index] === "/" && source4[index + 1] === "*") {
|
|
1751
|
+
let depth = 1;
|
|
1752
|
+
index += 2;
|
|
1753
|
+
while (index < endIndex && depth > 0) {
|
|
1754
|
+
if (source4[index] === "/" && source4[index + 1] === "*") {
|
|
1755
|
+
depth++;
|
|
1756
|
+
index += 2;
|
|
1757
|
+
} else if (source4[index] === "*" && source4[index + 1] === "/") {
|
|
1758
|
+
depth--;
|
|
1759
|
+
index += 2;
|
|
1760
|
+
} else {
|
|
1761
|
+
index++;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
return index;
|
|
1766
|
+
}
|
|
1767
|
+
function splitTopLevel(source4, delimiter) {
|
|
1768
|
+
const parts = [];
|
|
1769
|
+
let startIndex = 0;
|
|
1770
|
+
let parenthesisDepth = 0;
|
|
1771
|
+
let angleDepth = 0;
|
|
1772
|
+
for (let index = 0; index < source4.length; index++) {
|
|
1773
|
+
const character = source4[index];
|
|
1774
|
+
if (character === "(")
|
|
1775
|
+
parenthesisDepth++;
|
|
1776
|
+
if (character === ")")
|
|
1777
|
+
parenthesisDepth--;
|
|
1778
|
+
if (character === "<")
|
|
1779
|
+
angleDepth++;
|
|
1780
|
+
if (character === ">")
|
|
1781
|
+
angleDepth--;
|
|
1782
|
+
if (character === delimiter && parenthesisDepth === 0 && angleDepth === 0) {
|
|
1783
|
+
parts.push(source4.slice(startIndex, index));
|
|
1784
|
+
startIndex = index + 1;
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
parts.push(source4.slice(startIndex));
|
|
1788
|
+
return parts;
|
|
1789
|
+
}
|
|
1790
|
+
function getWGSLLocations2(source4) {
|
|
1791
|
+
const locations = [];
|
|
1792
|
+
const locationPattern = /@location\s*\(\s*(\d+)\s*\)/g;
|
|
1793
|
+
let match = locationPattern.exec(source4);
|
|
1794
|
+
while (match) {
|
|
1795
|
+
locations.push(Number(match[1]));
|
|
1796
|
+
match = locationPattern.exec(source4);
|
|
1797
|
+
}
|
|
1798
|
+
return locations;
|
|
1799
|
+
}
|
|
1800
|
+
function getWGSLDeclaredNames2(source4) {
|
|
1801
|
+
const names = [];
|
|
1802
|
+
const namePattern = /(?:^|,)\s*(?:@[A-Za-z_][\w]*(?:\([^)]*\))?\s*)*([A-Za-z_][\w]*)\s*:/gm;
|
|
1803
|
+
let match = namePattern.exec(source4);
|
|
1804
|
+
while (match) {
|
|
1805
|
+
names.push(match[1]);
|
|
1806
|
+
match = namePattern.exec(source4);
|
|
1807
|
+
}
|
|
1808
|
+
return names;
|
|
1809
|
+
}
|
|
1810
|
+
function hasWGSLModuleVariable2(source4, name) {
|
|
1811
|
+
const variablePattern = new RegExp(`\\b(?:var(?:<[^>]+>)?|let|const)\\s+${escapeRegExp3(name)}\\b`, "g");
|
|
1812
|
+
let match = variablePattern.exec(source4);
|
|
1813
|
+
while (match) {
|
|
1814
|
+
if (getBraceDepthAt2(source4, match.index) === 0) {
|
|
1815
|
+
return true;
|
|
1816
|
+
}
|
|
1817
|
+
match = variablePattern.exec(source4);
|
|
1818
|
+
}
|
|
1819
|
+
return false;
|
|
1820
|
+
}
|
|
1821
|
+
function getFirstUnusedLocation2(usedLocations) {
|
|
1822
|
+
let location = 0;
|
|
1823
|
+
while (usedLocations.has(location))
|
|
1824
|
+
location++;
|
|
1825
|
+
return location;
|
|
1826
|
+
}
|
|
1827
|
+
function getGLSLZeroValue(type) {
|
|
1828
|
+
const { primitiveType, components } = import_core3.shaderTypeDecoder.getAttributeShaderTypeInfo(type);
|
|
1829
|
+
const scalar = primitiveType === "u32" ? "0u" : primitiveType === "i32" ? "0" : "0.0";
|
|
1830
|
+
return components === 1 ? scalar : `${getGLSLAttributeType(type)}(${scalar})`;
|
|
1831
|
+
}
|
|
1832
|
+
function getWGSLZeroValue(type) {
|
|
1833
|
+
const { primitiveType, components } = import_core3.shaderTypeDecoder.getAttributeShaderTypeInfo(type);
|
|
1834
|
+
const scalar = `${primitiveType}(0)`;
|
|
1835
|
+
return components === 1 ? scalar : `${type}(${scalar})`;
|
|
1836
|
+
}
|
|
1837
|
+
function assertGLSLVaryingIsNew(source4, name) {
|
|
1838
|
+
const declaration = new RegExp(`\\b(?:flat\\s+|smooth\\s+)?(?:in|out|varying)\\s+(?:(?:lowp|mediump|highp)\\s+)?[A-Za-z_][A-Za-z0-9_]*\\s+${escapeRegExp3(name)}\\s*(?:\\[|;)`);
|
|
1839
|
+
if (declaration.test(source4)) {
|
|
1840
|
+
throw new Error(`ShaderPlugin varying "${name}" conflicts with existing GLSL stage I/O`);
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
function findMatchingDelimiter2(source4, openIndex, openCharacter, closeCharacter) {
|
|
1844
|
+
let depth = 0;
|
|
1845
|
+
let blockCommentDepth = 0;
|
|
1846
|
+
let lineComment = false;
|
|
1847
|
+
for (let index = openIndex; index < source4.length; index++) {
|
|
1848
|
+
const character = source4[index];
|
|
1849
|
+
const nextCharacter = source4[index + 1];
|
|
1850
|
+
if (lineComment) {
|
|
1851
|
+
if (character === "\n")
|
|
1852
|
+
lineComment = false;
|
|
1853
|
+
continue;
|
|
1854
|
+
}
|
|
1855
|
+
if (blockCommentDepth > 0) {
|
|
1856
|
+
if (character === "/" && nextCharacter === "*") {
|
|
1857
|
+
blockCommentDepth++;
|
|
1858
|
+
index++;
|
|
1859
|
+
} else if (character === "*" && nextCharacter === "/") {
|
|
1860
|
+
blockCommentDepth--;
|
|
1861
|
+
index++;
|
|
1862
|
+
}
|
|
1863
|
+
continue;
|
|
1864
|
+
}
|
|
1865
|
+
if (character === "/" && nextCharacter === "/") {
|
|
1866
|
+
lineComment = true;
|
|
1867
|
+
index++;
|
|
1868
|
+
continue;
|
|
1869
|
+
}
|
|
1870
|
+
if (character === "/" && nextCharacter === "*") {
|
|
1871
|
+
blockCommentDepth = 1;
|
|
1872
|
+
index++;
|
|
1873
|
+
continue;
|
|
1874
|
+
}
|
|
1875
|
+
if (character === openCharacter)
|
|
1876
|
+
depth++;
|
|
1877
|
+
if (character === closeCharacter && --depth === 0)
|
|
1878
|
+
return index;
|
|
1879
|
+
}
|
|
1880
|
+
return -1;
|
|
1881
|
+
}
|
|
1882
|
+
function getBraceDepthAt2(source4, endIndex) {
|
|
1883
|
+
let depth = 0;
|
|
1884
|
+
for (let index = 0; index < endIndex; index++) {
|
|
1885
|
+
const skippedIndex = skipWGSLTrivia(source4, index, endIndex);
|
|
1886
|
+
if (skippedIndex !== index) {
|
|
1887
|
+
index = skippedIndex - 1;
|
|
1888
|
+
continue;
|
|
1889
|
+
}
|
|
1890
|
+
if (source4[index] === "{")
|
|
1891
|
+
depth++;
|
|
1892
|
+
if (source4[index] === "}")
|
|
1893
|
+
depth--;
|
|
1894
|
+
}
|
|
1895
|
+
return depth;
|
|
1896
|
+
}
|
|
1897
|
+
function escapeRegExp3(value) {
|
|
1898
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
// dist/lib/shader-assembly/assemble-shaders.js
|
|
1902
|
+
var INJECT_SHADER_DECLARATIONS = `
|
|
1903
|
+
|
|
1904
|
+
${DECLARATION_INJECT_MARKER}
|
|
1905
|
+
`;
|
|
1906
|
+
var RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT = 100;
|
|
1907
|
+
var FRAGMENT_SHADER_PROLOGUE = (
|
|
1908
|
+
/* glsl */
|
|
1909
|
+
`precision highp float;
|
|
1910
|
+
`
|
|
1911
|
+
);
|
|
1912
|
+
function assembleWGSLShader(options) {
|
|
1913
|
+
const modules = getShaderModuleDependencies(options.modules || []);
|
|
1914
|
+
const { source: source4, bindingAssignments } = assembleShaderWGSL(options.platformInfo, {
|
|
1915
|
+
...options,
|
|
1916
|
+
source: options.source,
|
|
1917
|
+
stage: "vertex",
|
|
1918
|
+
modules
|
|
1919
|
+
});
|
|
1920
|
+
return {
|
|
1921
|
+
source: source4,
|
|
1922
|
+
getUniforms: assembleGetUniforms(modules),
|
|
1923
|
+
bindingAssignments,
|
|
1924
|
+
bindingTable: getShaderBindingDebugRowsFromWGSL(source4, bindingAssignments)
|
|
1925
|
+
};
|
|
1926
|
+
}
|
|
1927
|
+
function assembleGLSLShaderPair(options) {
|
|
1928
|
+
const { vs: vs4, fs: fs5 } = options;
|
|
1929
|
+
const modules = getShaderModuleDependencies(options.modules || []);
|
|
1930
|
+
return {
|
|
1931
|
+
vs: assembleShaderGLSL(options.platformInfo, {
|
|
1932
|
+
...options,
|
|
1933
|
+
source: vs4,
|
|
1934
|
+
stage: "vertex",
|
|
1935
|
+
modules
|
|
1936
|
+
}),
|
|
1937
|
+
fs: assembleShaderGLSL(options.platformInfo, {
|
|
1938
|
+
...options,
|
|
1939
|
+
// @ts-expect-error
|
|
1940
|
+
source: fs5,
|
|
1941
|
+
stage: "fragment",
|
|
1942
|
+
modules
|
|
1943
|
+
}),
|
|
1944
|
+
getUniforms: assembleGetUniforms(modules)
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
function assembleShaderWGSL(platformInfo, options) {
|
|
1948
|
+
const {
|
|
1949
|
+
// id,
|
|
1950
|
+
source: source4,
|
|
1951
|
+
stage,
|
|
1952
|
+
modules,
|
|
1953
|
+
// defines = {},
|
|
1954
|
+
defines = {},
|
|
1955
|
+
hookFunctions = [],
|
|
1956
|
+
inject = {},
|
|
1957
|
+
pluginInjections = {},
|
|
1958
|
+
pluginVertexInputs = {},
|
|
1959
|
+
pluginVaryings = {},
|
|
1960
|
+
vertexEntryPoint = "vertexMain",
|
|
1961
|
+
fragmentEntryPoint = "fragmentMain",
|
|
1962
|
+
log: log2
|
|
1963
|
+
} = options;
|
|
1964
|
+
assert(typeof source4 === "string", "shader source must be a string");
|
|
1965
|
+
const preprocessedSource = preprocess(source4, { defines });
|
|
1966
|
+
const pluginVertexInputAssembly = assembleShaderPluginVertexInputsWGSL(preprocessedSource, vertexEntryPoint, pluginVertexInputs);
|
|
1967
|
+
const pluginVaryingAssembly = assembleShaderPluginVaryingsWGSL(pluginVertexInputAssembly.source, vertexEntryPoint, fragmentEntryPoint, pluginVaryings);
|
|
1968
|
+
const coreSource = pluginVaryingAssembly.source;
|
|
1969
|
+
let assembledSource = "";
|
|
1970
|
+
const hookFunctionMap = normalizeShaderHooks(hookFunctions);
|
|
1971
|
+
const hookInjections = {};
|
|
1972
|
+
const declInjections = {};
|
|
1973
|
+
const mainInjections = {};
|
|
1974
|
+
appendInjections(pluginInjections, hookInjections, declInjections, mainInjections);
|
|
1975
|
+
for (const key in inject) {
|
|
1976
|
+
const injection = typeof inject[key] === "string" ? { injection: inject[key], order: 0 } : inject[key];
|
|
1977
|
+
const match = /^(v|f)s:(#)?([\w-]+)$/.exec(key);
|
|
1978
|
+
if (match) {
|
|
1979
|
+
const hash = match[2];
|
|
1980
|
+
const name = match[3];
|
|
1981
|
+
if (hash) {
|
|
1982
|
+
if (name === "decl") {
|
|
1983
|
+
declInjections[key] = [injection];
|
|
1984
|
+
} else {
|
|
1985
|
+
mainInjections[key] = [injection];
|
|
1986
|
+
}
|
|
1987
|
+
} else {
|
|
1988
|
+
hookInjections[key] = [injection];
|
|
1989
|
+
}
|
|
1990
|
+
} else {
|
|
1991
|
+
mainInjections[key] = [injection];
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
appendGeneratedVertexInputInjections(pluginVertexInputAssembly.declarations, pluginVertexInputAssembly.initialization, declInjections, mainInjections);
|
|
1995
|
+
appendGeneratedVaryingInjections(pluginVaryingAssembly, declInjections, mainInjections);
|
|
1996
|
+
const modulesToInject = modules;
|
|
1997
|
+
const applicationRelocation = relocateWGSLApplicationBindings(coreSource);
|
|
1998
|
+
const usedBindingsByGroup = getUsedBindingsByGroupFromApplicationWGSL(applicationRelocation.source);
|
|
1999
|
+
const reservedBindingKeysByGroup = reserveRegisteredModuleBindings(modulesToInject, options._bindingRegistry, usedBindingsByGroup, defines);
|
|
2000
|
+
const bindingAssignments = [];
|
|
2001
|
+
for (const module2 of modulesToInject) {
|
|
2002
|
+
if (log2) {
|
|
2003
|
+
checkShaderModuleDeprecations(module2, coreSource, log2);
|
|
2004
|
+
}
|
|
2005
|
+
const preprocessedModuleSource = preprocess(getShaderModuleSource(module2, "wgsl", log2), {
|
|
2006
|
+
defines
|
|
2007
|
+
});
|
|
2008
|
+
const relocation = relocateWGSLModuleBindings(preprocessedModuleSource, module2, {
|
|
2009
|
+
usedBindingsByGroup,
|
|
2010
|
+
bindingRegistry: options._bindingRegistry,
|
|
2011
|
+
reservedBindingKeysByGroup
|
|
2012
|
+
});
|
|
2013
|
+
bindingAssignments.push(...relocation.bindingAssignments);
|
|
2014
|
+
const relocatedModuleSource = relocation.source;
|
|
2015
|
+
assembledSource += relocatedModuleSource;
|
|
2016
|
+
const injections = getWGSLModuleInjections(module2);
|
|
2017
|
+
for (const key in injections) {
|
|
2018
|
+
const match = /^(v|f)s:#([\w-]+)$/.exec(key);
|
|
2019
|
+
if (match) {
|
|
2020
|
+
const name = match[2];
|
|
2021
|
+
const injectionType = name === "decl" ? declInjections : mainInjections;
|
|
2022
|
+
injectionType[key] = injectionType[key] || [];
|
|
2023
|
+
injectionType[key].push(injections[key]);
|
|
2024
|
+
} else {
|
|
2025
|
+
hookInjections[key] = hookInjections[key] || [];
|
|
2026
|
+
hookInjections[key].push(injections[key]);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
assembledSource += INJECT_SHADER_DECLARATIONS;
|
|
2031
|
+
assembledSource = injectShader(assembledSource, stage, getWGSLDeclarationInjections(declInjections), false, "wgsl", { vertex: vertexEntryPoint, fragment: fragmentEntryPoint });
|
|
2032
|
+
assembledSource += getWGSLShaderHooks(hookFunctionMap, hookInjections);
|
|
2033
|
+
assembledSource += formatWGSLBindingAssignmentComments(bindingAssignments);
|
|
2034
|
+
assembledSource += applicationRelocation.source;
|
|
2035
|
+
assembledSource = injectShader(assembledSource, stage, mainInjections, false, "wgsl", {
|
|
2036
|
+
vertex: vertexEntryPoint,
|
|
2037
|
+
fragment: fragmentEntryPoint
|
|
2038
|
+
});
|
|
2039
|
+
assertNoUnresolvedAutoBindings(assembledSource);
|
|
2040
|
+
return { source: assembledSource, bindingAssignments };
|
|
2041
|
+
}
|
|
2042
|
+
function assembleShaderGLSL(platformInfo, options) {
|
|
2043
|
+
var _a;
|
|
2044
|
+
const { source: source4, stage, language = "glsl", modules, defines = {}, hookFunctions = [], inject = {}, pluginInjections = {}, pluginVertexInputs = {}, pluginVaryings = {}, prologue = true, log: log2 } = options;
|
|
2045
|
+
assert(typeof source4 === "string", "shader source must be a string");
|
|
2046
|
+
const sourceVersion = language === "glsl" ? getShaderInfo(source4).version : -1;
|
|
2047
|
+
const targetVersion = platformInfo.shaderLanguageVersion;
|
|
2048
|
+
const sourceVersionDirective = sourceVersion === 100 ? "#version 100" : "#version 300 es";
|
|
2049
|
+
const sourceLines = source4.split("\n");
|
|
2050
|
+
const coreSource = sourceLines.slice(1).join("\n");
|
|
2051
|
+
const allDefines = {};
|
|
1188
2052
|
modules.forEach((module2) => {
|
|
1189
2053
|
Object.assign(allDefines, module2.defines);
|
|
1190
2054
|
});
|
|
@@ -1214,6 +2078,7 @@ ${getApplicationDefines(allDefines)}
|
|
|
1214
2078
|
const hookInjections = {};
|
|
1215
2079
|
const declInjections = {};
|
|
1216
2080
|
const mainInjections = {};
|
|
2081
|
+
appendInjections(pluginInjections, hookInjections, declInjections, mainInjections);
|
|
1217
2082
|
for (const key in inject) {
|
|
1218
2083
|
const injection = typeof inject[key] === "string" ? { injection: inject[key], order: 0 } : inject[key];
|
|
1219
2084
|
const match = /^(v|f)s:(#)?([\w-]+)$/.exec(key);
|
|
@@ -1233,6 +2098,32 @@ ${getApplicationDefines(allDefines)}
|
|
|
1233
2098
|
mainInjections[key] = [injection];
|
|
1234
2099
|
}
|
|
1235
2100
|
}
|
|
2101
|
+
if (stage === "vertex") {
|
|
2102
|
+
const declarations = getShaderPluginVertexInputDeclarationsGLSL(coreSource, pluginVertexInputs);
|
|
2103
|
+
if (declarations) {
|
|
2104
|
+
declInjections["vs:#decl"] = declInjections["vs:#decl"] || [];
|
|
2105
|
+
declInjections["vs:#decl"].push({
|
|
2106
|
+
injection: declarations,
|
|
2107
|
+
order: Number.MIN_SAFE_INTEGER
|
|
2108
|
+
});
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
const pluginVaryingAssembly = assembleShaderPluginVaryingsGLSL(coreSource, stage, pluginVaryings);
|
|
2112
|
+
if (pluginVaryingAssembly.declarations) {
|
|
2113
|
+
const declarationTarget = stage === "vertex" ? "vs:#decl" : "fs:#decl";
|
|
2114
|
+
declInjections[declarationTarget] = declInjections[declarationTarget] || [];
|
|
2115
|
+
declInjections[declarationTarget].push({
|
|
2116
|
+
injection: pluginVaryingAssembly.declarations,
|
|
2117
|
+
order: Number.MIN_SAFE_INTEGER
|
|
2118
|
+
});
|
|
2119
|
+
}
|
|
2120
|
+
if (pluginVaryingAssembly.initialization) {
|
|
2121
|
+
mainInjections["vs:#main-start"] = mainInjections["vs:#main-start"] || [];
|
|
2122
|
+
mainInjections["vs:#main-start"].push({
|
|
2123
|
+
injection: pluginVaryingAssembly.initialization,
|
|
2124
|
+
order: Number.MIN_SAFE_INTEGER
|
|
2125
|
+
});
|
|
2126
|
+
}
|
|
1236
2127
|
for (const module2 of modules) {
|
|
1237
2128
|
if (log2) {
|
|
1238
2129
|
checkShaderModuleDeprecations(module2, coreSource, log2);
|
|
@@ -1278,23 +2169,94 @@ function assembleGetUniforms(modules) {
|
|
|
1278
2169
|
return uniforms;
|
|
1279
2170
|
};
|
|
1280
2171
|
}
|
|
1281
|
-
function
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
2172
|
+
function appendInjections(injections, hookInjections, declInjections, mainInjections) {
|
|
2173
|
+
for (const key in injections) {
|
|
2174
|
+
const match = /^(v|f)s:(#)?([\w-]+)$/.exec(key);
|
|
2175
|
+
if (match) {
|
|
2176
|
+
const hash = match[2];
|
|
2177
|
+
const name = match[3];
|
|
2178
|
+
const injectionType = hash ? name === "decl" ? declInjections : mainInjections : hookInjections;
|
|
2179
|
+
injectionType[key] = injectionType[key] || [];
|
|
2180
|
+
injectionType[key].push(...injections[key]);
|
|
2181
|
+
} else {
|
|
2182
|
+
mainInjections[key] = mainInjections[key] || [];
|
|
2183
|
+
mainInjections[key].push(...injections[key]);
|
|
1288
2184
|
}
|
|
1289
2185
|
}
|
|
1290
|
-
return sourceText;
|
|
1291
2186
|
}
|
|
1292
|
-
function
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
2187
|
+
function appendGeneratedVertexInputInjections(declarations, initialization, declarationInjections, mainInjections) {
|
|
2188
|
+
if (declarations) {
|
|
2189
|
+
declarationInjections["vs:#decl"] = declarationInjections["vs:#decl"] || [];
|
|
2190
|
+
declarationInjections["vs:#decl"].push({
|
|
2191
|
+
injection: declarations,
|
|
2192
|
+
order: Number.MIN_SAFE_INTEGER
|
|
2193
|
+
});
|
|
2194
|
+
}
|
|
2195
|
+
if (initialization) {
|
|
2196
|
+
mainInjections["vs:#main-start"] = mainInjections["vs:#main-start"] || [];
|
|
2197
|
+
mainInjections["vs:#main-start"].push({
|
|
2198
|
+
injection: initialization,
|
|
2199
|
+
order: Number.MIN_SAFE_INTEGER
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
function appendGeneratedVaryingInjections(assembly, declarationInjections, mainInjections) {
|
|
2204
|
+
if (assembly.declarations) {
|
|
2205
|
+
declarationInjections["vs:#decl"] = declarationInjections["vs:#decl"] || [];
|
|
2206
|
+
declarationInjections["vs:#decl"].push({
|
|
2207
|
+
injection: assembly.declarations,
|
|
2208
|
+
order: Number.MIN_SAFE_INTEGER
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
if (assembly.vertexInitialization) {
|
|
2212
|
+
mainInjections["vs:#main-start"] = mainInjections["vs:#main-start"] || [];
|
|
2213
|
+
mainInjections["vs:#main-start"].push({
|
|
2214
|
+
injection: assembly.vertexInitialization,
|
|
2215
|
+
order: Number.MIN_SAFE_INTEGER
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
if (assembly.fragmentInitialization) {
|
|
2219
|
+
mainInjections["fs:#main-start"] = mainInjections["fs:#main-start"] || [];
|
|
2220
|
+
mainInjections["fs:#main-start"].push({
|
|
2221
|
+
injection: assembly.fragmentInitialization,
|
|
2222
|
+
order: Number.MIN_SAFE_INTEGER
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
function getWGSLModuleInjections(module2) {
|
|
2227
|
+
var _a, _b;
|
|
2228
|
+
return {
|
|
2229
|
+
...((_a = module2.instance) == null ? void 0 : _a.normalizedInjections.vertex) || {},
|
|
2230
|
+
...((_b = module2.instance) == null ? void 0 : _b.normalizedInjections.fragment) || {}
|
|
2231
|
+
};
|
|
2232
|
+
}
|
|
2233
|
+
function getWGSLDeclarationInjections(declarationInjections) {
|
|
2234
|
+
const unifiedDeclarations = [
|
|
2235
|
+
...declarationInjections["vs:#decl"] || [],
|
|
2236
|
+
...declarationInjections["fs:#decl"] || []
|
|
2237
|
+
];
|
|
2238
|
+
return unifiedDeclarations.length ? { "vs:#decl": unifiedDeclarations } : {};
|
|
2239
|
+
}
|
|
2240
|
+
function getWGSLShaderHooks(hookFunctionMap, hookInjections) {
|
|
2241
|
+
return getShaderHooks(hookFunctionMap.vertex, hookInjections, "wgsl") + getShaderHooks(hookFunctionMap.fragment, hookInjections, "wgsl");
|
|
2242
|
+
}
|
|
2243
|
+
function getApplicationDefines(defines = {}) {
|
|
2244
|
+
let sourceText = "";
|
|
2245
|
+
for (const define in defines) {
|
|
2246
|
+
const value = defines[define];
|
|
2247
|
+
if (value || Number.isFinite(value)) {
|
|
2248
|
+
sourceText += `#define ${define.toUpperCase()} ${defines[define]}
|
|
2249
|
+
`;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
return sourceText;
|
|
2253
|
+
}
|
|
2254
|
+
function getShaderModuleSource(module2, stage, log2) {
|
|
2255
|
+
let moduleSource;
|
|
2256
|
+
switch (stage) {
|
|
2257
|
+
case "vertex":
|
|
2258
|
+
moduleSource = module2.vs || "";
|
|
2259
|
+
break;
|
|
1298
2260
|
case "fragment":
|
|
1299
2261
|
moduleSource = module2.fs || "";
|
|
1300
2262
|
break;
|
|
@@ -1409,13 +2371,13 @@ function relocateWGSLApplicationBindingMatch(declarationMatch, usedBindingsByGro
|
|
|
1409
2371
|
relocationState.sawSupportedBindingDeclaration = true;
|
|
1410
2372
|
return match;
|
|
1411
2373
|
}
|
|
1412
|
-
function reserveRegisteredModuleBindings(modules, bindingRegistry, usedBindingsByGroup) {
|
|
2374
|
+
function reserveRegisteredModuleBindings(modules, bindingRegistry, usedBindingsByGroup, defines) {
|
|
1413
2375
|
const reservedBindingKeysByGroup = /* @__PURE__ */ new Map();
|
|
1414
2376
|
if (!bindingRegistry) {
|
|
1415
2377
|
return reservedBindingKeysByGroup;
|
|
1416
2378
|
}
|
|
1417
2379
|
for (const module2 of modules) {
|
|
1418
|
-
for (const binding of getModuleWGSLBindingDeclarations(module2)) {
|
|
2380
|
+
for (const binding of getModuleWGSLBindingDeclarations(module2, defines)) {
|
|
1419
2381
|
const registryKey = getBindingRegistryKey(binding.group, module2.name, binding.name);
|
|
1420
2382
|
const location = bindingRegistry.get(registryKey);
|
|
1421
2383
|
if (location !== void 0) {
|
|
@@ -1446,9 +2408,9 @@ function claimReservedBindingLocation(reservedBindingKeysByGroup, group, locatio
|
|
|
1446
2408
|
}
|
|
1447
2409
|
return true;
|
|
1448
2410
|
}
|
|
1449
|
-
function getModuleWGSLBindingDeclarations(module2) {
|
|
2411
|
+
function getModuleWGSLBindingDeclarations(module2, defines) {
|
|
1450
2412
|
const declarations = [];
|
|
1451
|
-
const moduleSource = module2.source || "";
|
|
2413
|
+
const moduleSource = preprocess(module2.source || "", { defines });
|
|
1452
2414
|
for (const match of getWGSLBindingDeclarationMatches(moduleSource, MODULE_WGSL_BINDING_DECLARATION_REGEXES)) {
|
|
1453
2415
|
declarations.push({
|
|
1454
2416
|
name: match.name,
|
|
@@ -1539,53 +2501,6 @@ function formatWGSLSourceSnippet(source4) {
|
|
|
1539
2501
|
return source4.replace(/\s+/g, " ").trim();
|
|
1540
2502
|
}
|
|
1541
2503
|
|
|
1542
|
-
// dist/lib/preprocessor/preprocessor.js
|
|
1543
|
-
var DEFINE_NAME_PATTERN = "([a-zA-Z_][a-zA-Z0-9_]*)";
|
|
1544
|
-
var IFDEF_REGEXP = new RegExp(`^\\s*\\#\\s*ifdef\\s*${DEFINE_NAME_PATTERN}\\s*$`);
|
|
1545
|
-
var IFNDEF_REGEXP = new RegExp(`^\\s*\\#\\s*ifndef\\s*${DEFINE_NAME_PATTERN}\\s*(?:\\/\\/.*)?$`);
|
|
1546
|
-
var ELSE_REGEXP = /^\s*\#\s*else\s*(?:\/\/.*)?$/;
|
|
1547
|
-
var ENDIF_REGEXP = /^\s*\#\s*endif\s*$/;
|
|
1548
|
-
var IFDEF_WITH_COMMENT_REGEXP = new RegExp(`^\\s*\\#\\s*ifdef\\s*${DEFINE_NAME_PATTERN}\\s*(?:\\/\\/.*)?$`);
|
|
1549
|
-
var ENDIF_WITH_COMMENT_REGEXP = /^\s*\#\s*endif\s*(?:\/\/.*)?$/;
|
|
1550
|
-
function preprocess(source4, options) {
|
|
1551
|
-
var _a, _b;
|
|
1552
|
-
const lines = source4.split("\n");
|
|
1553
|
-
const output = [];
|
|
1554
|
-
const conditionalStack = [];
|
|
1555
|
-
let conditional = true;
|
|
1556
|
-
for (const line of lines) {
|
|
1557
|
-
const matchIf = line.match(IFDEF_WITH_COMMENT_REGEXP) || line.match(IFDEF_REGEXP);
|
|
1558
|
-
const matchIfNot = line.match(IFNDEF_REGEXP);
|
|
1559
|
-
const matchElse = line.match(ELSE_REGEXP);
|
|
1560
|
-
const matchEnd = line.match(ENDIF_WITH_COMMENT_REGEXP) || line.match(ENDIF_REGEXP);
|
|
1561
|
-
if (matchIf || matchIfNot) {
|
|
1562
|
-
const defineName = (_a = matchIf || matchIfNot) == null ? void 0 : _a[1];
|
|
1563
|
-
const defineValue = Boolean((_b = options == null ? void 0 : options.defines) == null ? void 0 : _b[defineName]);
|
|
1564
|
-
const branchTaken = matchIf ? defineValue : !defineValue;
|
|
1565
|
-
const active = conditional && branchTaken;
|
|
1566
|
-
conditionalStack.push({ parentActive: conditional, branchTaken, active });
|
|
1567
|
-
conditional = active;
|
|
1568
|
-
} else if (matchElse) {
|
|
1569
|
-
const currentConditional = conditionalStack[conditionalStack.length - 1];
|
|
1570
|
-
if (!currentConditional) {
|
|
1571
|
-
throw new Error("Encountered #else without matching #ifdef or #ifndef");
|
|
1572
|
-
}
|
|
1573
|
-
currentConditional.active = currentConditional.parentActive && !currentConditional.branchTaken;
|
|
1574
|
-
currentConditional.branchTaken = true;
|
|
1575
|
-
conditional = currentConditional.active;
|
|
1576
|
-
} else if (matchEnd) {
|
|
1577
|
-
conditionalStack.pop();
|
|
1578
|
-
conditional = conditionalStack.length ? conditionalStack[conditionalStack.length - 1].active : true;
|
|
1579
|
-
} else if (conditional) {
|
|
1580
|
-
output.push(line);
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
if (conditionalStack.length > 0) {
|
|
1584
|
-
throw new Error("Unterminated conditional block in shader source");
|
|
1585
|
-
}
|
|
1586
|
-
return output.join("\n");
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
2504
|
// dist/lib/shader-assembler.js
|
|
1590
2505
|
var _ShaderAssembler = class {
|
|
1591
2506
|
/** Hook functions */
|
|
@@ -1596,14 +2511,15 @@ var _ShaderAssembler = class {
|
|
|
1596
2511
|
_wgslBindingRegistry = /* @__PURE__ */ new Map();
|
|
1597
2512
|
/**
|
|
1598
2513
|
* A default shader assembler instance - the natural place to register default modules and hooks
|
|
1599
|
-
* @returns
|
|
2514
|
+
* @returns Shared default shader assembler.
|
|
1600
2515
|
*/
|
|
1601
2516
|
static getDefaultShaderAssembler() {
|
|
1602
2517
|
_ShaderAssembler.defaultShaderAssembler = _ShaderAssembler.defaultShaderAssembler || new _ShaderAssembler();
|
|
1603
2518
|
return _ShaderAssembler.defaultShaderAssembler;
|
|
1604
2519
|
}
|
|
1605
2520
|
/**
|
|
1606
|
-
* Add a default module that does not have to be provided with every call
|
|
2521
|
+
* Add a default module that does not have to be provided with every assembly call.
|
|
2522
|
+
* @param module Shader module to include in later assembly calls.
|
|
1607
2523
|
*/
|
|
1608
2524
|
addDefaultModule(module2) {
|
|
1609
2525
|
if (!this._defaultModules.find((m) => m.name === (typeof module2 === "string" ? module2 : module2.name))) {
|
|
@@ -1612,6 +2528,7 @@ var _ShaderAssembler = class {
|
|
|
1612
2528
|
}
|
|
1613
2529
|
/**
|
|
1614
2530
|
* Remove a default module
|
|
2531
|
+
* @param module Shader module to remove from later assembly calls.
|
|
1615
2532
|
*/
|
|
1616
2533
|
removeDefaultModule(module2) {
|
|
1617
2534
|
const moduleName = typeof module2 === "string" ? module2 : module2.name;
|
|
@@ -1619,8 +2536,8 @@ var _ShaderAssembler = class {
|
|
|
1619
2536
|
}
|
|
1620
2537
|
/**
|
|
1621
2538
|
* Register a shader hook
|
|
1622
|
-
* @param hook
|
|
1623
|
-
* @param opts
|
|
2539
|
+
* @param hook Stage-prefixed hook signature, such as `vs:OFFSET_POSITION(inout vec4 position)`.
|
|
2540
|
+
* @param opts Optional hook metadata such as always-on header and footer source.
|
|
1624
2541
|
*/
|
|
1625
2542
|
addShaderHook(hook, opts) {
|
|
1626
2543
|
if (opts) {
|
|
@@ -1630,29 +2547,24 @@ var _ShaderAssembler = class {
|
|
|
1630
2547
|
}
|
|
1631
2548
|
/**
|
|
1632
2549
|
* Assemble a WGSL unified shader
|
|
1633
|
-
* @param
|
|
1634
|
-
* @
|
|
1635
|
-
* @returns
|
|
2550
|
+
* @param props WGSL source, platform information, shader modules, defines, and injections.
|
|
2551
|
+
* @returns Assembled WGSL source, resolved modules, uniforms, and binding debug metadata.
|
|
1636
2552
|
*/
|
|
1637
2553
|
assembleWGSLShader(props) {
|
|
1638
2554
|
const modules = this._getModuleList(props.modules);
|
|
1639
2555
|
const hookFunctions = this._hookFunctions;
|
|
1640
|
-
const
|
|
2556
|
+
const defines = getShaderPreprocessorDefines(props, modules);
|
|
2557
|
+
const preprocessedApplicationSource = props.platformInfo.shaderLanguage === "wgsl" && props.source ? preprocess(props.source, { defines }) : props.source;
|
|
2558
|
+
const { source: assembledSource, getUniforms: getUniforms4, bindingAssignments } = assembleWGSLShader({
|
|
1641
2559
|
...props,
|
|
1642
2560
|
// @ts-expect-error
|
|
1643
|
-
source:
|
|
2561
|
+
source: preprocessedApplicationSource,
|
|
2562
|
+
defines,
|
|
1644
2563
|
_bindingRegistry: this._wgslBindingRegistry,
|
|
1645
2564
|
modules,
|
|
1646
2565
|
hookFunctions
|
|
1647
2566
|
});
|
|
1648
|
-
const
|
|
1649
|
-
...modules.reduce((accumulator, module2) => {
|
|
1650
|
-
Object.assign(accumulator, module2.defines);
|
|
1651
|
-
return accumulator;
|
|
1652
|
-
}, {}),
|
|
1653
|
-
...props.defines
|
|
1654
|
-
};
|
|
1655
|
-
const preprocessedSource = props.platformInfo.shaderLanguage === "wgsl" ? preprocess(source4, { defines }) : source4;
|
|
2567
|
+
const preprocessedSource = props.platformInfo.shaderLanguage === "wgsl" ? preprocess(assembledSource, { defines }) : assembledSource;
|
|
1656
2568
|
return {
|
|
1657
2569
|
source: preprocessedSource,
|
|
1658
2570
|
getUniforms: getUniforms4,
|
|
@@ -1663,9 +2575,8 @@ var _ShaderAssembler = class {
|
|
|
1663
2575
|
}
|
|
1664
2576
|
/**
|
|
1665
2577
|
* Assemble a pair of shaders into a single shader program
|
|
1666
|
-
* @param
|
|
1667
|
-
* @
|
|
1668
|
-
* @returns
|
|
2578
|
+
* @param props GLSL vertex and fragment source, platform information, shader modules, defines, and injections.
|
|
2579
|
+
* @returns Assembled GLSL source, resolved modules, and combined uniform getter.
|
|
1669
2580
|
*/
|
|
1670
2581
|
assembleGLSLShaderPair(props) {
|
|
1671
2582
|
const modules = this._getModuleList(props.modules);
|
|
@@ -1710,6 +2621,22 @@ var _ShaderAssembler = class {
|
|
|
1710
2621
|
var ShaderAssembler = _ShaderAssembler;
|
|
1711
2622
|
/** Default ShaderAssembler instance */
|
|
1712
2623
|
__publicField(ShaderAssembler, "defaultShaderAssembler");
|
|
2624
|
+
function getShaderPreprocessorDefines(props, modules) {
|
|
2625
|
+
return {
|
|
2626
|
+
...getPlatformPreprocessorDefines(props.platformInfo),
|
|
2627
|
+
...modules.reduce((accumulator, module2) => {
|
|
2628
|
+
Object.assign(accumulator, module2.defines);
|
|
2629
|
+
return accumulator;
|
|
2630
|
+
}, {}),
|
|
2631
|
+
...props.defines
|
|
2632
|
+
};
|
|
2633
|
+
}
|
|
2634
|
+
function getPlatformPreprocessorDefines(platformInfo) {
|
|
2635
|
+
const limits = platformInfo.limits || {};
|
|
2636
|
+
return {
|
|
2637
|
+
LUMA_SUPPORTS_VERTEX_STORAGE_BUFFERS: platformInfo.type === "webgpu" && (limits["maxStorageBuffersInVertexStage"] || 0) > 0
|
|
2638
|
+
};
|
|
2639
|
+
}
|
|
1713
2640
|
|
|
1714
2641
|
// dist/lib/glsl-utils/shader-utils.js
|
|
1715
2642
|
var FS_GLES = (
|
|
@@ -1909,14 +2836,14 @@ function generateShaderForModule(module2, options) {
|
|
|
1909
2836
|
}
|
|
1910
2837
|
|
|
1911
2838
|
// dist/modules/math/fp16/fp16-utils.js
|
|
1912
|
-
var
|
|
2839
|
+
var import_core4 = require("@math.gl/core");
|
|
1913
2840
|
var float16Tables = null;
|
|
1914
2841
|
var buffer = new ArrayBuffer(4);
|
|
1915
2842
|
var floatView = new Float32Array(buffer);
|
|
1916
2843
|
var uint32View = new Uint32Array(buffer);
|
|
1917
2844
|
function toHalfFloat(val) {
|
|
1918
2845
|
float16Tables ||= generateFloat16Tables();
|
|
1919
|
-
val = (0,
|
|
2846
|
+
val = (0, import_core4.clamp)(val, -65504, 65504);
|
|
1920
2847
|
floatView[0] = val;
|
|
1921
2848
|
const f = uint32View[0];
|
|
1922
2849
|
const e = f >> 23 & 511;
|
|
@@ -2435,11 +3362,278 @@ var fp64arithmeticWGSL = (
|
|
|
2435
3362
|
|
|
2436
3363
|
@group(0) @binding(auto) var<uniform> fp64arithmetic : Fp64ArithmeticUniforms;
|
|
2437
3364
|
|
|
3365
|
+
struct Fp64Bits {
|
|
3366
|
+
sign: u32,
|
|
3367
|
+
exponent: i32,
|
|
3368
|
+
significand: vec2u,
|
|
3369
|
+
isZero: bool,
|
|
3370
|
+
isInf: bool,
|
|
3371
|
+
isNan: bool,
|
|
3372
|
+
};
|
|
3373
|
+
|
|
2438
3374
|
fn fp64_nan(seed: f32) -> f32 {
|
|
2439
3375
|
let nanBits = 0x7fc00000u | select(0u, 1u, seed < 0.0);
|
|
2440
3376
|
return bitcast<f32>(nanBits);
|
|
2441
3377
|
}
|
|
2442
3378
|
|
|
3379
|
+
fn fp64_u64_is_zero(value: vec2u) -> bool {
|
|
3380
|
+
return value.x == 0u && value.y == 0u;
|
|
3381
|
+
}
|
|
3382
|
+
|
|
3383
|
+
fn fp64_u64_compare(a: vec2u, b: vec2u) -> i32 {
|
|
3384
|
+
if (a.x != b.x) {
|
|
3385
|
+
return select(-1, 1, a.x > b.x);
|
|
3386
|
+
}
|
|
3387
|
+
if (a.y != b.y) {
|
|
3388
|
+
return select(-1, 1, a.y > b.y);
|
|
3389
|
+
}
|
|
3390
|
+
return 0;
|
|
3391
|
+
}
|
|
3392
|
+
|
|
3393
|
+
fn fp64_u64_add(a: vec2u, b: vec2u) -> vec2u {
|
|
3394
|
+
let low = a.y + b.y;
|
|
3395
|
+
let carry = select(0u, 1u, low < a.y);
|
|
3396
|
+
return vec2u(a.x + b.x + carry, low);
|
|
3397
|
+
}
|
|
3398
|
+
|
|
3399
|
+
fn fp64_u64_sub(a: vec2u, b: vec2u) -> vec2u {
|
|
3400
|
+
let borrow = select(0u, 1u, a.y < b.y);
|
|
3401
|
+
return vec2u(a.x - b.x - borrow, a.y - b.y);
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
fn fp64_u64_shift_left(value: vec2u, shift: u32) -> vec2u {
|
|
3405
|
+
if (shift == 0u) {
|
|
3406
|
+
return value;
|
|
3407
|
+
}
|
|
3408
|
+
if (shift < 32u) {
|
|
3409
|
+
return vec2u((value.x << shift) | (value.y >> (32u - shift)), value.y << shift);
|
|
3410
|
+
}
|
|
3411
|
+
if (shift == 32u) {
|
|
3412
|
+
return vec2u(value.y, 0u);
|
|
3413
|
+
}
|
|
3414
|
+
if (shift < 64u) {
|
|
3415
|
+
return vec2u(value.y << (shift - 32u), 0u);
|
|
3416
|
+
}
|
|
3417
|
+
return vec2u(0u);
|
|
3418
|
+
}
|
|
3419
|
+
|
|
3420
|
+
fn fp64_u64_shift_right(value: vec2u, shift: u32) -> vec2u {
|
|
3421
|
+
if (shift == 0u) {
|
|
3422
|
+
return value;
|
|
3423
|
+
}
|
|
3424
|
+
if (shift < 32u) {
|
|
3425
|
+
return vec2u(value.x >> shift, (value.y >> shift) | (value.x << (32u - shift)));
|
|
3426
|
+
}
|
|
3427
|
+
if (shift == 32u) {
|
|
3428
|
+
return vec2u(0u, value.x);
|
|
3429
|
+
}
|
|
3430
|
+
if (shift < 64u) {
|
|
3431
|
+
return vec2u(0u, value.x >> (shift - 32u));
|
|
3432
|
+
}
|
|
3433
|
+
return vec2u(0u);
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3436
|
+
fn fp64_u64_get_bit(value: vec2u, bitIndex: u32) -> bool {
|
|
3437
|
+
if (bitIndex >= 64u) {
|
|
3438
|
+
return false;
|
|
3439
|
+
}
|
|
3440
|
+
if (bitIndex >= 32u) {
|
|
3441
|
+
return ((value.x >> (bitIndex - 32u)) & 1u) != 0u;
|
|
3442
|
+
}
|
|
3443
|
+
return ((value.y >> bitIndex) & 1u) != 0u;
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3446
|
+
fn fp64_u64_has_bits_below(value: vec2u, bitCount: u32) -> bool {
|
|
3447
|
+
if (bitCount == 0u) {
|
|
3448
|
+
return false;
|
|
3449
|
+
}
|
|
3450
|
+
if (bitCount >= 64u) {
|
|
3451
|
+
return !fp64_u64_is_zero(value);
|
|
3452
|
+
}
|
|
3453
|
+
if (bitCount > 32u) {
|
|
3454
|
+
let highBitCount = bitCount - 32u;
|
|
3455
|
+
let highMask = (1u << highBitCount) - 1u;
|
|
3456
|
+
return value.y != 0u || (value.x & highMask) != 0u;
|
|
3457
|
+
}
|
|
3458
|
+
if (bitCount == 32u) {
|
|
3459
|
+
return value.y != 0u;
|
|
3460
|
+
}
|
|
3461
|
+
let lowMask = (1u << bitCount) - 1u;
|
|
3462
|
+
return (value.y & lowMask) != 0u;
|
|
3463
|
+
}
|
|
3464
|
+
|
|
3465
|
+
fn fp64_u64_shift_right_sticky(value: vec2u, shift: u32) -> vec2u {
|
|
3466
|
+
var shifted = fp64_u64_shift_right(value, shift);
|
|
3467
|
+
if (fp64_u64_has_bits_below(value, shift)) {
|
|
3468
|
+
shifted.y = shifted.y | 1u;
|
|
3469
|
+
}
|
|
3470
|
+
return shifted;
|
|
3471
|
+
}
|
|
3472
|
+
|
|
3473
|
+
fn fp64_u64_count_leading_zeros(value: vec2u) -> u32 {
|
|
3474
|
+
if (value.x != 0u) {
|
|
3475
|
+
return countLeadingZeros(value.x);
|
|
3476
|
+
}
|
|
3477
|
+
return 32u + countLeadingZeros(value.y);
|
|
3478
|
+
}
|
|
3479
|
+
|
|
3480
|
+
fn fp64_round_shift_right_to_u32(value: vec2u, shift: u32) -> u32 {
|
|
3481
|
+
if (shift == 0u) {
|
|
3482
|
+
return value.y;
|
|
3483
|
+
}
|
|
3484
|
+
|
|
3485
|
+
let truncated = fp64_u64_shift_right(value, shift);
|
|
3486
|
+
var rounded = truncated.y;
|
|
3487
|
+
let guard = fp64_u64_get_bit(value, shift - 1u);
|
|
3488
|
+
let hasTrailingBits = fp64_u64_has_bits_below(value, shift - 1u);
|
|
3489
|
+
if (guard && (hasTrailingBits || (rounded & 1u) == 1u)) {
|
|
3490
|
+
rounded = rounded + 1u;
|
|
3491
|
+
}
|
|
3492
|
+
return rounded;
|
|
3493
|
+
}
|
|
3494
|
+
|
|
3495
|
+
fn fp64_make_f32_bits_from_u64(sign: u32, significand: vec2u, baseExponent: i32) -> u32 {
|
|
3496
|
+
if (fp64_u64_is_zero(significand)) {
|
|
3497
|
+
return sign << 31u;
|
|
3498
|
+
}
|
|
3499
|
+
|
|
3500
|
+
let leadingZeros = fp64_u64_count_leading_zeros(significand);
|
|
3501
|
+
let mostSignificantBit = 63u - leadingZeros;
|
|
3502
|
+
var exponent = baseExponent + i32(mostSignificantBit);
|
|
3503
|
+
|
|
3504
|
+
if (exponent > 127) {
|
|
3505
|
+
return (sign << 31u) | 0x7f800000u;
|
|
3506
|
+
}
|
|
3507
|
+
|
|
3508
|
+
if (exponent >= -126) {
|
|
3509
|
+
let shift = i32(mostSignificantBit) - 23;
|
|
3510
|
+
var significand24: u32;
|
|
3511
|
+
if (shift > 0) {
|
|
3512
|
+
significand24 = fp64_round_shift_right_to_u32(significand, u32(shift));
|
|
3513
|
+
} else {
|
|
3514
|
+
significand24 = fp64_u64_shift_left(significand, u32(-shift)).y;
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3517
|
+
if (significand24 >= 0x1000000u) {
|
|
3518
|
+
significand24 = significand24 >> 1u;
|
|
3519
|
+
exponent = exponent + 1;
|
|
3520
|
+
if (exponent > 127) {
|
|
3521
|
+
return (sign << 31u) | 0x7f800000u;
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
return (sign << 31u) | (u32(exponent + 127) << 23u) | (significand24 & 0x7fffffu);
|
|
3526
|
+
}
|
|
3527
|
+
|
|
3528
|
+
let scaleExponent = baseExponent + 149;
|
|
3529
|
+
var mantissa: u32;
|
|
3530
|
+
if (scaleExponent >= 0) {
|
|
3531
|
+
mantissa = fp64_u64_shift_left(significand, u32(scaleExponent)).y;
|
|
3532
|
+
} else {
|
|
3533
|
+
mantissa = fp64_round_shift_right_to_u32(significand, u32(-scaleExponent));
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3536
|
+
if (mantissa >= 0x800000u) {
|
|
3537
|
+
return (sign << 31u) | 0x00800000u;
|
|
3538
|
+
}
|
|
3539
|
+
return (sign << 31u) | mantissa;
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3542
|
+
fn fp64_decode_bits(bits: vec2u) -> Fp64Bits {
|
|
3543
|
+
let sign = bits.x >> 31u;
|
|
3544
|
+
let exponentBits = (bits.x >> 20u) & 0x7ffu;
|
|
3545
|
+
let fractionHigh = bits.x & 0xfffffu;
|
|
3546
|
+
let fractionLow = bits.y;
|
|
3547
|
+
let fraction = vec2u(fractionHigh, fractionLow);
|
|
3548
|
+
|
|
3549
|
+
if (exponentBits == 0x7ffu) {
|
|
3550
|
+
let isInf = fp64_u64_is_zero(fraction);
|
|
3551
|
+
return Fp64Bits(sign, 0, vec2u(0u), false, isInf, !isInf);
|
|
3552
|
+
}
|
|
3553
|
+
|
|
3554
|
+
if (exponentBits == 0u) {
|
|
3555
|
+
let isZero = fp64_u64_is_zero(fraction);
|
|
3556
|
+
return Fp64Bits(sign, -1022, fraction, isZero, false, false);
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3559
|
+
return Fp64Bits(sign, i32(exponentBits) - 1023, vec2u((1u << 20u) | fractionHigh, fractionLow), false, false, false);
|
|
3560
|
+
}
|
|
3561
|
+
|
|
3562
|
+
fn fp64_finite_magnitude_compare(a: Fp64Bits, b: Fp64Bits) -> i32 {
|
|
3563
|
+
if (a.exponent != b.exponent) {
|
|
3564
|
+
return select(-1, 1, a.exponent > b.exponent);
|
|
3565
|
+
}
|
|
3566
|
+
return fp64_u64_compare(a.significand, b.significand);
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
fn fp64_add_aligned_magnitudes_to_f32_bits(sign: u32, larger: Fp64Bits, smaller: Fp64Bits) -> u32 {
|
|
3570
|
+
let largeSignificand = fp64_u64_shift_left(larger.significand, 3u);
|
|
3571
|
+
let smallSignificand = fp64_u64_shift_right_sticky(
|
|
3572
|
+
fp64_u64_shift_left(smaller.significand, 3u),
|
|
3573
|
+
u32(larger.exponent - smaller.exponent)
|
|
3574
|
+
);
|
|
3575
|
+
let resultSignificand = fp64_u64_add(largeSignificand, smallSignificand);
|
|
3576
|
+
return fp64_make_f32_bits_from_u64(sign, resultSignificand, larger.exponent - 55);
|
|
3577
|
+
}
|
|
3578
|
+
|
|
3579
|
+
fn fp64_sub_aligned_magnitudes_to_f32_bits(sign: u32, larger: Fp64Bits, smaller: Fp64Bits) -> u32 {
|
|
3580
|
+
let largeSignificand = fp64_u64_shift_left(larger.significand, 3u);
|
|
3581
|
+
let smallSignificand = fp64_u64_shift_right_sticky(
|
|
3582
|
+
fp64_u64_shift_left(smaller.significand, 3u),
|
|
3583
|
+
u32(larger.exponent - smaller.exponent)
|
|
3584
|
+
);
|
|
3585
|
+
let resultSignificand = fp64_u64_sub(largeSignificand, smallSignificand);
|
|
3586
|
+
return fp64_make_f32_bits_from_u64(sign, resultSignificand, larger.exponent - 55);
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
// Subtract two raw binary64 values and round the exact result once to f32.
|
|
3590
|
+
// The input words are canonical high/low words: .x contains sign/exponent/high
|
|
3591
|
+
// fraction bits, and .y contains the low 32 fraction bits.
|
|
3592
|
+
fn sub_fp64u32_to_f32_bits(aBits: vec2u, bBits: vec2u) -> u32 {
|
|
3593
|
+
let a = fp64_decode_bits(aBits);
|
|
3594
|
+
let b = fp64_decode_bits(bBits);
|
|
3595
|
+
let bSubtractionSign = b.sign ^ 1u;
|
|
3596
|
+
|
|
3597
|
+
if (a.isNan || b.isNan) {
|
|
3598
|
+
return 0x7fc00000u;
|
|
3599
|
+
}
|
|
3600
|
+
if (a.isInf && b.isInf) {
|
|
3601
|
+
if (a.sign == bSubtractionSign) {
|
|
3602
|
+
return (a.sign << 31u) | 0x7f800000u;
|
|
3603
|
+
}
|
|
3604
|
+
return 0x7fc00000u;
|
|
3605
|
+
}
|
|
3606
|
+
if (a.isInf) {
|
|
3607
|
+
return (a.sign << 31u) | 0x7f800000u;
|
|
3608
|
+
}
|
|
3609
|
+
if (b.isInf) {
|
|
3610
|
+
return (bSubtractionSign << 31u) | 0x7f800000u;
|
|
3611
|
+
}
|
|
3612
|
+
if (a.isZero && b.isZero) {
|
|
3613
|
+
return select(0u, 0x80000000u, a.sign == 1u && b.sign == 0u);
|
|
3614
|
+
}
|
|
3615
|
+
|
|
3616
|
+
let magnitudeComparison = fp64_finite_magnitude_compare(a, b);
|
|
3617
|
+
if (a.sign == bSubtractionSign) {
|
|
3618
|
+
if (magnitudeComparison >= 0) {
|
|
3619
|
+
return fp64_add_aligned_magnitudes_to_f32_bits(a.sign, a, b);
|
|
3620
|
+
}
|
|
3621
|
+
return fp64_add_aligned_magnitudes_to_f32_bits(a.sign, b, a);
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3624
|
+
if (magnitudeComparison == 0) {
|
|
3625
|
+
return 0u;
|
|
3626
|
+
}
|
|
3627
|
+
if (magnitudeComparison > 0) {
|
|
3628
|
+
return fp64_sub_aligned_magnitudes_to_f32_bits(a.sign, a, b);
|
|
3629
|
+
}
|
|
3630
|
+
return fp64_sub_aligned_magnitudes_to_f32_bits(bSubtractionSign, b, a);
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
fn sub_fp64u32_to_f32(aBits: vec2u, bBits: vec2u) -> f32 {
|
|
3634
|
+
return bitcast<f32>(sub_fp64u32_to_f32_bits(aBits, bBits));
|
|
3635
|
+
}
|
|
3636
|
+
|
|
2443
3637
|
fn fp64_runtime_zero() -> f32 {
|
|
2444
3638
|
return fp64arithmetic.ONE * 0.0;
|
|
2445
3639
|
}
|
|
@@ -3342,59 +4536,2054 @@ var fp64 = {
|
|
|
3342
4536
|
fp64ifyMatrix4
|
|
3343
4537
|
};
|
|
3344
4538
|
|
|
3345
|
-
// dist/modules/
|
|
3346
|
-
var
|
|
3347
|
-
/*
|
|
3348
|
-
`
|
|
4539
|
+
// dist/modules/geospatial/dggs/dggs-wgsl.js
|
|
4540
|
+
var dggsWGSL = (
|
|
4541
|
+
/* wgsl */
|
|
4542
|
+
`const DGGS_H3_CELL_MODE: u32 = 1u;
|
|
4543
|
+
const DGGS_H3_MAX_RESOLUTION: u32 = 15u;
|
|
4544
|
+
const DGGS_H3_MAX_BASE_CELL: u32 = 121u;
|
|
4545
|
+
const DGGS_H3_UNUSED_DIGIT: u32 = 7u;
|
|
4546
|
+
const DGGS_H3_RES0_U_GNOMONIC: f32 = 0.381966011250105;
|
|
4547
|
+
const DGGS_H3_RSQRT7: f32 = 0.3779644730092272;
|
|
4548
|
+
const DGGS_H3_ONETHIRD: f32 = 0.3333333333333333;
|
|
4549
|
+
const DGGS_H3_AP7_ROT_RADS: f32 = 0.3334731722518321;
|
|
4550
|
+
const DGGS_H3_SQRT3_2: f32 = 0.8660254037844386;
|
|
4551
|
+
const DGGS_S2_MAX_LEVEL: u32 = 30u;
|
|
4552
|
+
const DGGS_GEOHASH_MAX_LENGTH: u32 = 12u;
|
|
4553
|
+
const DGGS_GEOHASH_LENGTH_BIT_OFFSET: u32 = 60u;
|
|
4554
|
+
const DGGS_QUADKEY_MAX_LENGTH: u32 = 29u;
|
|
4555
|
+
const DGGS_QUADKEY_LENGTH_BIT_OFFSET: u32 = 58u;
|
|
4556
|
+
const DGGS_A5_FIRST_HILBERT_RESOLUTION: u32 = 2u;
|
|
4557
|
+
const DGGS_A5_MAX_RESOLUTION: u32 = 30u;
|
|
4558
|
+
const DGGS_A5_HILBERT_START_BIT: u32 = 58u;
|
|
4559
|
+
const DGGS_PI: f32 = 3.141592653589793;
|
|
4560
|
+
const DGGS_TWO_PI: f32 = 6.283185307179586;
|
|
4561
|
+
const DGGS_TWO_PI_OVER_5: f32 = 1.2566370614359172;
|
|
4562
|
+
const DGGS_PI_OVER_5: f32 = 0.6283185307179586;
|
|
4563
|
+
const DGGS_PI_OVER_2: f32 = 1.5707963267948966;
|
|
4564
|
+
const DGGS_A5_DISTANCE_TO_EDGE: f32 = 0.6180339887498949;
|
|
4565
|
+
const DGGS_A5_REFLECTED_TRIANGLE_SCALE: f32 = 3.23606797749979;
|
|
4566
|
+
const DGGS_A5_LONGITUDE_OFFSET: f32 = 93.0;
|
|
4567
|
+
const DGGS_RADIANS_TO_DEGREES: f32 = 57.29577951308232;
|
|
4568
|
+
const DGGS_DEGREES_TO_RADIANS: f32 = 0.017453292519943295;
|
|
4569
|
+
const DGGS_U64_HIGH_WORD_FLOAT_SCALE: f32 = 4294967296.0;
|
|
4570
|
+
|
|
4571
|
+
// DGGS 64-bit helper functions use canonical word order vec2u(high, low).
|
|
4572
|
+
// Arrow BigInt64/BigUint64 buffers are read as little-endian vec2u(low, high),
|
|
4573
|
+
// so storage-buffer reads should pass through dggs_u64_from_little_endian_words().
|
|
4574
|
+
fn dggs_u64_make(high: u32, low: u32) -> vec2u {
|
|
4575
|
+
return vec2u(high, low);
|
|
4576
|
+
}
|
|
4577
|
+
|
|
4578
|
+
fn dggs_u64_from_little_endian_words(words: vec2u) -> vec2u {
|
|
4579
|
+
return words.yx;
|
|
4580
|
+
}
|
|
4581
|
+
|
|
4582
|
+
fn dggs_u64_to_little_endian_words(value: vec2u) -> vec2u {
|
|
4583
|
+
return value.yx;
|
|
4584
|
+
}
|
|
4585
|
+
|
|
4586
|
+
fn dggs_u64_high(value: vec2u) -> u32 {
|
|
4587
|
+
return value.x;
|
|
4588
|
+
}
|
|
4589
|
+
|
|
4590
|
+
fn dggs_u64_low(value: vec2u) -> u32 {
|
|
4591
|
+
return value.y;
|
|
4592
|
+
}
|
|
4593
|
+
|
|
4594
|
+
fn dggs_u64_is_zero(value: vec2u) -> bool {
|
|
4595
|
+
return value.x == 0u && value.y == 0u;
|
|
4596
|
+
}
|
|
4597
|
+
|
|
4598
|
+
fn dggs_u64_equal(a: vec2u, b: vec2u) -> bool {
|
|
4599
|
+
return a.x == b.x && a.y == b.y;
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
fn dggs_u64_compare(a: vec2u, b: vec2u) -> i32 {
|
|
4603
|
+
if (a.x != b.x) {
|
|
4604
|
+
return select(-1, 1, a.x > b.x);
|
|
4605
|
+
}
|
|
4606
|
+
if (a.y != b.y) {
|
|
4607
|
+
return select(-1, 1, a.y > b.y);
|
|
4608
|
+
}
|
|
4609
|
+
return 0;
|
|
4610
|
+
}
|
|
4611
|
+
|
|
4612
|
+
fn dggs_u64_less(a: vec2u, b: vec2u) -> bool {
|
|
4613
|
+
return dggs_u64_compare(a, b) < 0;
|
|
4614
|
+
}
|
|
4615
|
+
|
|
4616
|
+
fn dggs_u64_add(a: vec2u, b: vec2u) -> vec2u {
|
|
4617
|
+
let low = a.y + b.y;
|
|
4618
|
+
let carry = select(0u, 1u, low < a.y);
|
|
4619
|
+
return vec2u(a.x + b.x + carry, low);
|
|
4620
|
+
}
|
|
4621
|
+
|
|
4622
|
+
fn dggs_u64_subtract(a: vec2u, b: vec2u) -> vec2u {
|
|
4623
|
+
let borrow = select(0u, 1u, a.y < b.y);
|
|
4624
|
+
return vec2u(a.x - b.x - borrow, a.y - b.y);
|
|
4625
|
+
}
|
|
4626
|
+
|
|
4627
|
+
fn dggs_u64_to_f32(value: vec2u) -> f32 {
|
|
4628
|
+
return f32(value.x) * DGGS_U64_HIGH_WORD_FLOAT_SCALE + f32(value.y);
|
|
4629
|
+
}
|
|
4630
|
+
|
|
4631
|
+
fn dggs_i64_from_little_endian_words(words: vec2u) -> vec2u {
|
|
4632
|
+
return dggs_u64_from_little_endian_words(words);
|
|
4633
|
+
}
|
|
4634
|
+
|
|
4635
|
+
fn dggs_i64_to_little_endian_words(value: vec2u) -> vec2u {
|
|
4636
|
+
return dggs_u64_to_little_endian_words(value);
|
|
4637
|
+
}
|
|
4638
|
+
|
|
4639
|
+
fn dggs_i64_is_negative(value: vec2u) -> bool {
|
|
4640
|
+
return (value.x & 0x80000000u) != 0u;
|
|
4641
|
+
}
|
|
4642
|
+
|
|
4643
|
+
fn dggs_i64_negate(value: vec2u) -> vec2u {
|
|
4644
|
+
return dggs_u64_add(vec2u(~value.x, ~value.y), vec2u(0u, 1u));
|
|
4645
|
+
}
|
|
4646
|
+
|
|
4647
|
+
fn dggs_i64_compare(a: vec2u, b: vec2u) -> i32 {
|
|
4648
|
+
let highA = bitcast<i32>(a.x);
|
|
4649
|
+
let highB = bitcast<i32>(b.x);
|
|
4650
|
+
if (highA != highB) {
|
|
4651
|
+
return select(-1, 1, highA > highB);
|
|
4652
|
+
}
|
|
4653
|
+
if (a.y != b.y) {
|
|
4654
|
+
return select(-1, 1, a.y > b.y);
|
|
4655
|
+
}
|
|
4656
|
+
return 0;
|
|
4657
|
+
}
|
|
4658
|
+
|
|
4659
|
+
fn dggs_i64_less(a: vec2u, b: vec2u) -> bool {
|
|
4660
|
+
return dggs_i64_compare(a, b) < 0;
|
|
4661
|
+
}
|
|
4662
|
+
|
|
4663
|
+
fn dggs_i64_subtract(a: vec2u, b: vec2u) -> vec2u {
|
|
4664
|
+
return dggs_u64_subtract(a, b);
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4667
|
+
fn dggs_i64_to_f32(value: vec2u) -> f32 {
|
|
4668
|
+
if (dggs_i64_is_negative(value)) {
|
|
4669
|
+
return -dggs_u64_to_f32(dggs_i64_negate(value));
|
|
4670
|
+
}
|
|
4671
|
+
return dggs_u64_to_f32(value);
|
|
4672
|
+
}
|
|
4673
|
+
|
|
4674
|
+
fn dggs_u32_mask_low(bitCount: u32) -> u32 {
|
|
4675
|
+
if (bitCount == 0u) {
|
|
4676
|
+
return 0u;
|
|
4677
|
+
}
|
|
4678
|
+
if (bitCount >= 32u) {
|
|
4679
|
+
return 0xffffffffu;
|
|
4680
|
+
}
|
|
4681
|
+
return (1u << bitCount) - 1u;
|
|
4682
|
+
}
|
|
4683
|
+
|
|
4684
|
+
fn dggs_u64_shift_left(value: vec2u, shift: u32) -> vec2u {
|
|
4685
|
+
if (shift == 0u) {
|
|
4686
|
+
return value;
|
|
4687
|
+
}
|
|
4688
|
+
if (shift < 32u) {
|
|
4689
|
+
return vec2u((value.x << shift) | (value.y >> (32u - shift)), value.y << shift);
|
|
4690
|
+
}
|
|
4691
|
+
if (shift == 32u) {
|
|
4692
|
+
return vec2u(value.y, 0u);
|
|
4693
|
+
}
|
|
4694
|
+
if (shift < 64u) {
|
|
4695
|
+
return vec2u(value.y << (shift - 32u), 0u);
|
|
4696
|
+
}
|
|
4697
|
+
return vec2u(0u);
|
|
4698
|
+
}
|
|
4699
|
+
|
|
4700
|
+
fn dggs_u64_shift_right(value: vec2u, shift: u32) -> vec2u {
|
|
4701
|
+
if (shift == 0u) {
|
|
4702
|
+
return value;
|
|
4703
|
+
}
|
|
4704
|
+
if (shift < 32u) {
|
|
4705
|
+
return vec2u(value.x >> shift, (value.y >> shift) | (value.x << (32u - shift)));
|
|
4706
|
+
}
|
|
4707
|
+
if (shift == 32u) {
|
|
4708
|
+
return vec2u(0u, value.x);
|
|
4709
|
+
}
|
|
4710
|
+
if (shift < 64u) {
|
|
4711
|
+
return vec2u(0u, value.x >> (shift - 32u));
|
|
4712
|
+
}
|
|
4713
|
+
return vec2u(0u);
|
|
4714
|
+
}
|
|
4715
|
+
|
|
4716
|
+
fn dggs_u64_extract_bits(value: vec2u, bitOffset: u32, bitCount: u32) -> u32 {
|
|
4717
|
+
if (bitCount == 0u || bitOffset >= 64u) {
|
|
4718
|
+
return 0u;
|
|
4719
|
+
}
|
|
4720
|
+
let shifted = dggs_u64_shift_right(value, bitOffset);
|
|
4721
|
+
return shifted.y & dggs_u32_mask_low(bitCount);
|
|
4722
|
+
}
|
|
4723
|
+
|
|
4724
|
+
fn dggs_u64_set_bits(value: vec2u, bitOffset: u32, bitCount: u32, bits: u32) -> vec2u {
|
|
4725
|
+
if (bitCount == 0u || bitOffset >= 64u) {
|
|
4726
|
+
return value;
|
|
4727
|
+
}
|
|
4728
|
+
let bitMask = dggs_u32_mask_low(bitCount);
|
|
4729
|
+
let fieldMask = dggs_u64_shift_left(vec2u(0u, bitMask), bitOffset);
|
|
4730
|
+
let fieldBits = dggs_u64_shift_left(vec2u(0u, bits & bitMask), bitOffset);
|
|
4731
|
+
return (value & vec2u(~fieldMask.x, ~fieldMask.y)) | fieldBits;
|
|
4732
|
+
}
|
|
4733
|
+
|
|
4734
|
+
fn dggs_u64_count_trailing_zeros(value: vec2u) -> u32 {
|
|
4735
|
+
if (value.y != 0u) {
|
|
4736
|
+
return countTrailingZeros(value.y);
|
|
4737
|
+
}
|
|
4738
|
+
if (value.x != 0u) {
|
|
4739
|
+
return 32u + countTrailingZeros(value.x);
|
|
4740
|
+
}
|
|
4741
|
+
return 64u;
|
|
4742
|
+
}
|
|
4743
|
+
|
|
4744
|
+
struct DggsA5Cell {
|
|
4745
|
+
origin : u32,
|
|
4746
|
+
segment : u32,
|
|
4747
|
+
resolution : u32,
|
|
4748
|
+
valid : u32,
|
|
4749
|
+
quintantShift : u32,
|
|
4750
|
+
hilbertResolution : u32,
|
|
4751
|
+
};
|
|
4752
|
+
|
|
4753
|
+
struct DggsA5Anchor {
|
|
4754
|
+
q : u32,
|
|
4755
|
+
offset : vec2i,
|
|
4756
|
+
flips : vec2i,
|
|
4757
|
+
orientation : u32,
|
|
4758
|
+
quintant : u32,
|
|
4759
|
+
};
|
|
4760
|
+
|
|
4761
|
+
struct DggsA5FaceTriangle {
|
|
4762
|
+
a : vec2f,
|
|
4763
|
+
b : vec2f,
|
|
4764
|
+
c : vec2f,
|
|
4765
|
+
};
|
|
4766
|
+
|
|
4767
|
+
struct DggsA5SphericalTriangle {
|
|
4768
|
+
a : vec3f,
|
|
4769
|
+
b : vec3f,
|
|
4770
|
+
c : vec3f,
|
|
4771
|
+
};
|
|
4772
|
+
|
|
4773
|
+
struct DggsH3FaceIJK {
|
|
4774
|
+
face : u32,
|
|
4775
|
+
coord : vec3i,
|
|
4776
|
+
valid : u32,
|
|
4777
|
+
};
|
|
4778
|
+
|
|
4779
|
+
struct DggsH3BoundaryVertex {
|
|
4780
|
+
face : u32,
|
|
4781
|
+
coord : vec3i,
|
|
4782
|
+
resolution : u32,
|
|
4783
|
+
valid : u32,
|
|
4784
|
+
};
|
|
4785
|
+
|
|
4786
|
+
fn dggs_boundary_point_to_fp64_split(point : vec2f) -> vec4f {
|
|
4787
|
+
return vec4f(point.x, point.y, 0.0, 0.0);
|
|
4788
|
+
}
|
|
4789
|
+
|
|
4790
|
+
fn dggs_a5_positive_mod_i32(value : i32, modulus : i32) -> i32 {
|
|
4791
|
+
return ((value % modulus) + modulus) % modulus;
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4794
|
+
fn dggs_a5_has_bit(index : vec2u, bitOffset : u32) -> bool {
|
|
4795
|
+
return dggs_u64_extract_bits(index, bitOffset, 1u) != 0u;
|
|
4796
|
+
}
|
|
4797
|
+
|
|
4798
|
+
fn dggs_a5_get_resolution(index : vec2u) -> u32 {
|
|
4799
|
+
if (dggs_u64_is_zero(index)) {
|
|
4800
|
+
return 0u;
|
|
4801
|
+
}
|
|
4802
|
+
if (
|
|
4803
|
+
dggs_a5_has_bit(index, 0u) ||
|
|
4804
|
+
dggs_u64_extract_bits(index, 0u, 3u) == 4u ||
|
|
4805
|
+
dggs_u64_extract_bits(index, 0u, 5u) == 16u
|
|
4806
|
+
) {
|
|
4807
|
+
return DGGS_A5_MAX_RESOLUTION;
|
|
4808
|
+
}
|
|
4809
|
+
|
|
4810
|
+
var resolution = DGGS_A5_MAX_RESOLUTION - 1u;
|
|
4811
|
+
var shifted = dggs_u64_shift_right(index, 1u);
|
|
4812
|
+
if (dggs_u64_is_zero(shifted)) {
|
|
4813
|
+
return 0u;
|
|
4814
|
+
}
|
|
4815
|
+
|
|
4816
|
+
var remaining = shifted.y;
|
|
4817
|
+
if (remaining == 0u) {
|
|
4818
|
+
shifted = dggs_u64_shift_right(shifted, 32u);
|
|
4819
|
+
resolution -= 16u;
|
|
4820
|
+
remaining = shifted.y;
|
|
4821
|
+
}
|
|
4822
|
+
if ((remaining & 0xffffu) == 0u) {
|
|
4823
|
+
remaining >>= 16u;
|
|
4824
|
+
resolution -= 8u;
|
|
4825
|
+
}
|
|
4826
|
+
if (resolution >= 6u && (remaining & 0xffu) == 0u) {
|
|
4827
|
+
remaining >>= 8u;
|
|
4828
|
+
resolution -= 4u;
|
|
4829
|
+
}
|
|
4830
|
+
if (resolution >= 4u && (remaining & 0xfu) == 0u) {
|
|
4831
|
+
remaining >>= 4u;
|
|
4832
|
+
resolution -= 2u;
|
|
4833
|
+
}
|
|
4834
|
+
loop {
|
|
4835
|
+
if ((remaining & 1u) != 0u) {
|
|
4836
|
+
break;
|
|
4837
|
+
}
|
|
4838
|
+
if (resolution == 0u) {
|
|
4839
|
+
break;
|
|
4840
|
+
}
|
|
4841
|
+
resolution -= 1u;
|
|
4842
|
+
remaining >>= select(2u, 1u, resolution < DGGS_A5_FIRST_HILBERT_RESOLUTION);
|
|
4843
|
+
}
|
|
4844
|
+
return resolution;
|
|
4845
|
+
}
|
|
4846
|
+
|
|
4847
|
+
fn dggs_a5_get_origin_first_quintant(origin : u32) -> u32 {
|
|
4848
|
+
let values = array<u32, 12>(
|
|
4849
|
+
4u, 2u, 3u, 0u, 2u, 4u, 2u, 2u, 3u, 0u, 3u, 0u
|
|
4850
|
+
);
|
|
4851
|
+
return values[min(origin, 11u)];
|
|
4852
|
+
}
|
|
4853
|
+
|
|
4854
|
+
fn dggs_a5_get_origin_step(origin : u32) -> i32 {
|
|
4855
|
+
let values = array<i32, 12>(
|
|
4856
|
+
-1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1
|
|
4857
|
+
);
|
|
4858
|
+
return values[min(origin, 11u)];
|
|
4859
|
+
}
|
|
4860
|
+
|
|
4861
|
+
fn dggs_a5_get_origin_orientation(origin : u32, faceRelativeQuintant : u32) -> u32 {
|
|
4862
|
+
// Orientation codes: uv=0, vu=1, uw=2, wu=3, vw=4, wv=5.
|
|
4863
|
+
let values = array<u32, 60>(
|
|
4864
|
+
1u, 2u, 4u, 4u, 4u,
|
|
4865
|
+
1u, 0u, 5u, 3u, 2u,
|
|
4866
|
+
3u, 0u, 5u, 3u, 2u,
|
|
4867
|
+
3u, 0u, 5u, 3u, 2u,
|
|
4868
|
+
3u, 2u, 4u, 1u, 2u,
|
|
4869
|
+
1u, 0u, 5u, 3u, 2u,
|
|
4870
|
+
3u, 2u, 4u, 1u, 2u,
|
|
4871
|
+
3u, 2u, 4u, 1u, 2u,
|
|
4872
|
+
3u, 0u, 5u, 3u, 2u,
|
|
4873
|
+
1u, 0u, 5u, 3u, 2u,
|
|
4874
|
+
1u, 0u, 5u, 3u, 2u,
|
|
4875
|
+
3u, 2u, 4u, 1u, 2u
|
|
4876
|
+
);
|
|
4877
|
+
return values[min(origin, 11u) * 5u + min(faceRelativeQuintant, 4u)];
|
|
4878
|
+
}
|
|
4879
|
+
|
|
4880
|
+
fn dggs_a5_get_origin_angle(origin : u32) -> f32 {
|
|
4881
|
+
if (origin == 0u || origin == 9u) {
|
|
4882
|
+
return 0.0;
|
|
4883
|
+
}
|
|
4884
|
+
return DGGS_PI_OVER_5;
|
|
4885
|
+
}
|
|
4886
|
+
|
|
4887
|
+
fn dggs_a5_get_origin_quaternion(origin : u32) -> vec4f {
|
|
4888
|
+
let values = array<vec4f, 12>(
|
|
4889
|
+
vec4f(0.0, 0.0, 0.0, 1.0),
|
|
4890
|
+
vec4f(0.0, 0.525731112119, 0.0, 0.850650808352),
|
|
4891
|
+
vec4f(-0.5, 0.688190960236, 0.0, 0.525731112119),
|
|
4892
|
+
vec4f(-0.809016994375, -0.262865556060, 0.0, 0.525731112119),
|
|
4893
|
+
vec4f(-0.5, 0.162459848116, 0.0, 0.850650808352),
|
|
4894
|
+
vec4f(-0.309016994375, -0.425325404176, 0.0, 0.850650808352),
|
|
4895
|
+
vec4f(0.309016994375, -0.425325404176, 0.0, 0.850650808352),
|
|
4896
|
+
vec4f(0.809016994375, -0.262865556060, 0.0, 0.525731112119),
|
|
4897
|
+
vec4f(0.0, -0.850650808352, 0.0, 0.525731112119),
|
|
4898
|
+
vec4f(0.0, -1.0, 0.0, 0.0),
|
|
4899
|
+
vec4f(0.5, 0.688190960236, 0.0, 0.525731112119),
|
|
4900
|
+
vec4f(0.5, 0.162459848116, 0.0, 0.850650808352)
|
|
4901
|
+
);
|
|
4902
|
+
return values[min(origin, 11u)];
|
|
4903
|
+
}
|
|
4904
|
+
|
|
4905
|
+
fn dggs_a5_quaternion_rotate(point : vec3f, quaternion : vec4f) -> vec3f {
|
|
4906
|
+
let q = quaternion.xyz;
|
|
4907
|
+
let t = 2.0 * cross(q, point);
|
|
4908
|
+
return point + quaternion.w * t + cross(q, t);
|
|
4909
|
+
}
|
|
4910
|
+
|
|
4911
|
+
fn dggs_a5_deserialize(index : vec2u) -> DggsA5Cell {
|
|
4912
|
+
if (dggs_u64_is_zero(index)) {
|
|
4913
|
+
return DggsA5Cell(0u, 0u, 0u, 0u, DGGS_A5_HILBERT_START_BIT, 0u);
|
|
4914
|
+
}
|
|
4915
|
+
|
|
4916
|
+
let resolution = dggs_a5_get_resolution(index);
|
|
4917
|
+
var quintantShift = DGGS_A5_HILBERT_START_BIT;
|
|
4918
|
+
var quintantOffset = 0u;
|
|
4919
|
+
if (resolution == DGGS_A5_MAX_RESOLUTION) {
|
|
4920
|
+
var markerBits = 5u;
|
|
4921
|
+
if (dggs_a5_has_bit(index, 0u)) {
|
|
4922
|
+
markerBits = 1u;
|
|
4923
|
+
} else if (dggs_a5_has_bit(index, 2u)) {
|
|
4924
|
+
markerBits = 3u;
|
|
4925
|
+
}
|
|
4926
|
+
quintantShift = DGGS_A5_HILBERT_START_BIT + markerBits;
|
|
4927
|
+
quintantOffset = select(select(40u, 32u, markerBits == 3u), 0u, markerBits == 1u);
|
|
4928
|
+
}
|
|
4929
|
+
|
|
4930
|
+
let topBits = dggs_u64_shift_right(index, quintantShift).y + quintantOffset;
|
|
4931
|
+
if (resolution == 0u) {
|
|
4932
|
+
if (topBits >= 12u) {
|
|
4933
|
+
return DggsA5Cell(0u, 0u, resolution, 0u, quintantShift, 0u);
|
|
4934
|
+
}
|
|
4935
|
+
return DggsA5Cell(topBits, 0u, resolution, 1u, quintantShift, 0u);
|
|
4936
|
+
}
|
|
4937
|
+
|
|
4938
|
+
let origin = topBits / 5u;
|
|
4939
|
+
if (origin >= 12u) {
|
|
4940
|
+
return DggsA5Cell(0u, 0u, resolution, 0u, quintantShift, 0u);
|
|
4941
|
+
}
|
|
4942
|
+
let segment = (topBits + dggs_a5_get_origin_first_quintant(origin)) % 5u;
|
|
4943
|
+
let hilbertResolution = select(0u, resolution - 1u, resolution >= 2u);
|
|
4944
|
+
return DggsA5Cell(origin, segment, resolution, 1u, quintantShift, hilbertResolution);
|
|
4945
|
+
}
|
|
4946
|
+
|
|
4947
|
+
fn dggs_a5_segment_to_anchor_info(cell : DggsA5Cell) -> DggsA5Anchor {
|
|
4948
|
+
let firstQuintant = dggs_a5_get_origin_first_quintant(cell.origin);
|
|
4949
|
+
let faceRelativeQuintant = (cell.segment + 5u - firstQuintant) % 5u;
|
|
4950
|
+
let orientation = dggs_a5_get_origin_orientation(cell.origin, faceRelativeQuintant);
|
|
4951
|
+
let step = dggs_a5_get_origin_step(cell.origin);
|
|
4952
|
+
let quintant = u32(dggs_a5_positive_mod_i32(
|
|
4953
|
+
i32(firstQuintant) + step * i32(faceRelativeQuintant),
|
|
4954
|
+
5
|
|
4955
|
+
));
|
|
4956
|
+
return DggsA5Anchor(0u, vec2i(0), vec2i(1), orientation, quintant);
|
|
4957
|
+
}
|
|
4958
|
+
|
|
4959
|
+
fn dggs_a5_is_reverse_orientation(orientation : u32) -> bool {
|
|
4960
|
+
return orientation == 1u || orientation == 3u || orientation == 4u;
|
|
4961
|
+
}
|
|
4962
|
+
|
|
4963
|
+
fn dggs_a5_is_invert_j_orientation(orientation : u32) -> bool {
|
|
4964
|
+
return orientation == 5u || orientation == 4u;
|
|
4965
|
+
}
|
|
4966
|
+
|
|
4967
|
+
fn dggs_a5_is_flip_ij_orientation(orientation : u32) -> bool {
|
|
4968
|
+
return orientation == 3u || orientation == 2u;
|
|
4969
|
+
}
|
|
4970
|
+
|
|
4971
|
+
fn dggs_a5_pattern_value(index : u32, flipIj : bool) -> u32 {
|
|
4972
|
+
let pattern = array<u32, 8>(0u, 1u, 3u, 4u, 5u, 6u, 7u, 2u);
|
|
4973
|
+
let flippedPattern = array<u32, 8>(0u, 1u, 2u, 7u, 3u, 4u, 5u, 6u);
|
|
4974
|
+
return select(pattern[min(index, 7u)], flippedPattern[min(index, 7u)], flipIj);
|
|
4975
|
+
}
|
|
4976
|
+
|
|
4977
|
+
fn dggs_a5_quaternary_to_flips(digit : u32) -> vec2i {
|
|
4978
|
+
if (digit == 1u) {
|
|
4979
|
+
return vec2i(1, -1);
|
|
4980
|
+
}
|
|
4981
|
+
if (digit == 3u) {
|
|
4982
|
+
return vec2i(-1, 1);
|
|
4983
|
+
}
|
|
4984
|
+
return vec2i(1, 1);
|
|
4985
|
+
}
|
|
4986
|
+
|
|
4987
|
+
fn dggs_a5_quaternary_to_kj(digit : u32, flips : vec2i) -> vec2i {
|
|
4988
|
+
var p = vec2i(0);
|
|
4989
|
+
var q = vec2i(0);
|
|
4990
|
+
if (flips.x == 1 && flips.y == 1) {
|
|
4991
|
+
p = vec2i(1, 0);
|
|
4992
|
+
q = vec2i(0, 1);
|
|
4993
|
+
} else if (flips.x == -1 && flips.y == 1) {
|
|
4994
|
+
p = vec2i(0, -1);
|
|
4995
|
+
q = vec2i(-1, 0);
|
|
4996
|
+
} else if (flips.x == 1 && flips.y == -1) {
|
|
4997
|
+
p = vec2i(0, 1);
|
|
4998
|
+
q = vec2i(1, 0);
|
|
4999
|
+
} else {
|
|
5000
|
+
p = vec2i(-1, 0);
|
|
5001
|
+
q = vec2i(0, -1);
|
|
5002
|
+
}
|
|
5003
|
+
|
|
5004
|
+
if (digit == 1u) {
|
|
5005
|
+
return p;
|
|
5006
|
+
}
|
|
5007
|
+
if (digit == 2u) {
|
|
5008
|
+
return p + q;
|
|
5009
|
+
}
|
|
5010
|
+
if (digit == 3u) {
|
|
5011
|
+
return q + 2 * p;
|
|
5012
|
+
}
|
|
5013
|
+
return vec2i(0);
|
|
5014
|
+
}
|
|
5015
|
+
|
|
5016
|
+
fn dggs_a5_kj_to_ij(kj : vec2i) -> vec2i {
|
|
5017
|
+
return vec2i(kj.x - kj.y, kj.y);
|
|
5018
|
+
}
|
|
5019
|
+
|
|
5020
|
+
fn dggs_a5_shift_digits(
|
|
5021
|
+
digits : ptr<function, array<u32, 29>>,
|
|
5022
|
+
digitIndex : u32,
|
|
5023
|
+
flips : vec2i,
|
|
5024
|
+
invertJ : bool,
|
|
5025
|
+
flipIj : bool
|
|
5026
|
+
) {
|
|
5027
|
+
if (digitIndex == 0u) {
|
|
5028
|
+
return;
|
|
5029
|
+
}
|
|
5030
|
+
let parentK = (*digits)[digitIndex];
|
|
5031
|
+
let childK = (*digits)[digitIndex - 1u];
|
|
5032
|
+
let flipSum = flips.x + flips.y;
|
|
5033
|
+
var needsShift = true;
|
|
5034
|
+
var first = true;
|
|
5035
|
+
if (invertJ != (flipSum == 0)) {
|
|
5036
|
+
needsShift = parentK == 1u || parentK == 2u;
|
|
5037
|
+
first = parentK == 1u;
|
|
5038
|
+
} else {
|
|
5039
|
+
needsShift = parentK < 2u;
|
|
5040
|
+
first = parentK == 0u;
|
|
5041
|
+
}
|
|
5042
|
+
if (!needsShift) {
|
|
5043
|
+
return;
|
|
5044
|
+
}
|
|
5045
|
+
let source = select(childK + 4u, childK, first);
|
|
5046
|
+
let destination = dggs_a5_pattern_value(source, flipIj);
|
|
5047
|
+
(*digits)[digitIndex - 1u] = destination % 4u;
|
|
5048
|
+
(*digits)[digitIndex] = u32(dggs_a5_positive_mod_i32(
|
|
5049
|
+
i32(parentK) + 4 + i32(destination / 4u) - i32(source / 4u),
|
|
5050
|
+
4
|
|
5051
|
+
));
|
|
5052
|
+
}
|
|
5053
|
+
|
|
5054
|
+
fn dggs_a5_make_anchor(index : vec2u, cell : DggsA5Cell, anchorInfo : DggsA5Anchor) -> DggsA5Anchor {
|
|
5055
|
+
if (cell.hilbertResolution == 0u) {
|
|
5056
|
+
return anchorInfo;
|
|
5057
|
+
}
|
|
5058
|
+
|
|
5059
|
+
let reverse = dggs_a5_is_reverse_orientation(anchorInfo.orientation);
|
|
5060
|
+
let invertJ = dggs_a5_is_invert_j_orientation(anchorInfo.orientation);
|
|
5061
|
+
let flipIj = dggs_a5_is_flip_ij_orientation(anchorInfo.orientation);
|
|
5062
|
+
let hilbertBits = 2u * cell.hilbertResolution;
|
|
5063
|
+
let sBitOffset = cell.quintantShift - hilbertBits;
|
|
5064
|
+
var digits : array<u32, 29>;
|
|
5065
|
+
var digitIndex = 0u;
|
|
5066
|
+
loop {
|
|
5067
|
+
if (digitIndex >= cell.hilbertResolution) {
|
|
5068
|
+
break;
|
|
5069
|
+
}
|
|
5070
|
+
var digit = dggs_u64_extract_bits(index, sBitOffset + 2u * digitIndex, 2u);
|
|
5071
|
+
if (reverse) {
|
|
5072
|
+
digit = 3u - digit;
|
|
5073
|
+
}
|
|
5074
|
+
digits[digitIndex] = digit;
|
|
5075
|
+
digitIndex += 1u;
|
|
5076
|
+
}
|
|
5077
|
+
|
|
5078
|
+
var flips = vec2i(1, 1);
|
|
5079
|
+
digitIndex = cell.hilbertResolution;
|
|
5080
|
+
loop {
|
|
5081
|
+
if (digitIndex == 0u) {
|
|
5082
|
+
break;
|
|
5083
|
+
}
|
|
5084
|
+
digitIndex -= 1u;
|
|
5085
|
+
dggs_a5_shift_digits(&digits, digitIndex, flips, invertJ, flipIj);
|
|
5086
|
+
flips *= dggs_a5_quaternary_to_flips(digits[digitIndex]);
|
|
5087
|
+
}
|
|
5088
|
+
|
|
5089
|
+
flips = vec2i(1, 1);
|
|
5090
|
+
var offset = vec2i(0);
|
|
5091
|
+
digitIndex = cell.hilbertResolution;
|
|
5092
|
+
loop {
|
|
5093
|
+
if (digitIndex == 0u) {
|
|
5094
|
+
break;
|
|
5095
|
+
}
|
|
5096
|
+
digitIndex -= 1u;
|
|
5097
|
+
offset *= 2;
|
|
5098
|
+
offset += dggs_a5_quaternary_to_kj(digits[digitIndex], flips);
|
|
5099
|
+
flips *= dggs_a5_quaternary_to_flips(digits[digitIndex]);
|
|
5100
|
+
}
|
|
5101
|
+
|
|
5102
|
+
var anchorOffset = dggs_a5_kj_to_ij(offset);
|
|
5103
|
+
if (flipIj) {
|
|
5104
|
+
let originalOffset = anchorOffset;
|
|
5105
|
+
anchorOffset = originalOffset.yx;
|
|
5106
|
+
if (flips.x == -1) {
|
|
5107
|
+
anchorOffset += vec2i(-1, 1);
|
|
5108
|
+
}
|
|
5109
|
+
if (flips.y == -1) {
|
|
5110
|
+
anchorOffset -= vec2i(-1, 1);
|
|
5111
|
+
}
|
|
5112
|
+
}
|
|
5113
|
+
if (invertJ) {
|
|
5114
|
+
let i = anchorOffset.x;
|
|
5115
|
+
let j = i32(1u << cell.hilbertResolution) - (i + anchorOffset.y);
|
|
5116
|
+
flips.x = -flips.x;
|
|
5117
|
+
anchorOffset.y = j;
|
|
5118
|
+
}
|
|
5119
|
+
|
|
5120
|
+
return DggsA5Anchor(
|
|
5121
|
+
digits[0],
|
|
5122
|
+
anchorOffset,
|
|
5123
|
+
flips,
|
|
5124
|
+
anchorInfo.orientation,
|
|
5125
|
+
anchorInfo.quintant
|
|
5126
|
+
);
|
|
5127
|
+
}
|
|
5128
|
+
|
|
5129
|
+
fn dggs_a5_rotate_face_point(point : vec2f, quintant : u32) -> vec2f {
|
|
5130
|
+
let angle = f32(quintant) * DGGS_TWO_PI_OVER_5;
|
|
5131
|
+
let cosine = cos(angle);
|
|
5132
|
+
let sine = sin(angle);
|
|
5133
|
+
return vec2f(point.x * cosine - point.y * sine, point.x * sine + point.y * cosine);
|
|
5134
|
+
}
|
|
5135
|
+
|
|
5136
|
+
fn dggs_a5_get_base_pentagon_vertex(vertexIndex : u32) -> vec2f {
|
|
5137
|
+
let vertices = array<vec2f, 5>(
|
|
5138
|
+
vec2f(0.0, 0.0),
|
|
5139
|
+
vec2f(0.199381847431, 0.375413822391),
|
|
5140
|
+
vec2f(0.618033988750, 0.449027976580),
|
|
5141
|
+
vec2f(0.817415836181, 0.073614154188),
|
|
5142
|
+
vec2f(0.418652141319, -0.073614154188)
|
|
5143
|
+
);
|
|
5144
|
+
return vertices[min(vertexIndex, 4u)];
|
|
5145
|
+
}
|
|
5146
|
+
|
|
5147
|
+
fn dggs_a5_get_base_triangle_vertex(vertexIndex : u32) -> vec2f {
|
|
5148
|
+
let vertices = array<vec2f, 3>(
|
|
5149
|
+
vec2f(0.0, 0.0),
|
|
5150
|
+
vec2f(0.618033988750, 0.449027976580),
|
|
5151
|
+
vec2f(0.618033988750, -0.449027976580)
|
|
5152
|
+
);
|
|
5153
|
+
return vertices[min(vertexIndex, 2u)];
|
|
5154
|
+
}
|
|
5155
|
+
|
|
5156
|
+
fn dggs_a5_get_face_vertex(vertexIndex : u32) -> vec2f {
|
|
5157
|
+
return dggs_a5_rotate_face_point(dggs_a5_get_base_triangle_vertex(1u), 4u - min(vertexIndex, 4u));
|
|
5158
|
+
}
|
|
5159
|
+
|
|
5160
|
+
fn dggs_a5_get_triangle_vertex(quintant : u32, vertexIndex : u32) -> vec2f {
|
|
5161
|
+
return dggs_a5_rotate_face_point(dggs_a5_get_base_triangle_vertex(vertexIndex), quintant);
|
|
5162
|
+
}
|
|
5163
|
+
|
|
5164
|
+
fn dggs_a5_get_pentagon_vertex(
|
|
5165
|
+
anchor : DggsA5Anchor,
|
|
5166
|
+
hilbertResolution : u32,
|
|
5167
|
+
vertexIndex : u32
|
|
5168
|
+
) -> vec2f {
|
|
5169
|
+
let flipSum = anchor.flips.x + anchor.flips.y;
|
|
5170
|
+
let reflectsY = ((flipSum == -2 || flipSum == 2) && anchor.q > 1u) ||
|
|
5171
|
+
(flipSum == 0 && (anchor.q == 0u || anchor.q == 3u));
|
|
5172
|
+
let sourceIndex = select(vertexIndex, 4u - vertexIndex, reflectsY);
|
|
5173
|
+
var point = dggs_a5_get_base_pentagon_vertex(sourceIndex);
|
|
5174
|
+
|
|
5175
|
+
if (anchor.flips.x == 1 && anchor.flips.y == -1) {
|
|
5176
|
+
point = -point;
|
|
5177
|
+
}
|
|
5178
|
+
if (reflectsY) {
|
|
5179
|
+
point.y = -point.y;
|
|
5180
|
+
}
|
|
5181
|
+
if (anchor.flips.x == -1 && anchor.flips.y == -1) {
|
|
5182
|
+
point = -point;
|
|
5183
|
+
} else if (anchor.flips.x == -1) {
|
|
5184
|
+
point += vec2f(-0.618033988750, 0.449027976580);
|
|
5185
|
+
} else if (anchor.flips.y == -1) {
|
|
5186
|
+
point += vec2f(0.618033988750, -0.449027976580);
|
|
5187
|
+
}
|
|
5188
|
+
|
|
5189
|
+
let translation = vec2f(
|
|
5190
|
+
f32(anchor.offset.x) * 0.618033988750 + f32(anchor.offset.y) * 0.618033988750,
|
|
5191
|
+
f32(anchor.offset.x) * 0.449027976580 + f32(anchor.offset.y) * -0.449027976580
|
|
5192
|
+
);
|
|
5193
|
+
point = (point + translation) / f32(1u << hilbertResolution);
|
|
5194
|
+
return dggs_a5_rotate_face_point(point, anchor.quintant);
|
|
5195
|
+
}
|
|
5196
|
+
|
|
5197
|
+
fn dggs_a5_get_shape_vertex_count(cell : DggsA5Cell) -> u32 {
|
|
5198
|
+
return select(5u, 3u, cell.resolution == 1u);
|
|
5199
|
+
}
|
|
5200
|
+
|
|
5201
|
+
fn dggs_a5_get_reversed_shape_index(vertexIndex : u32, shapeVertexCount : u32) -> u32 {
|
|
5202
|
+
if (vertexIndex == 0u || vertexIndex >= shapeVertexCount) {
|
|
5203
|
+
return 0u;
|
|
5204
|
+
}
|
|
5205
|
+
return shapeVertexCount - vertexIndex;
|
|
5206
|
+
}
|
|
5207
|
+
|
|
5208
|
+
fn dggs_a5_get_cell_shape_face_point(index : vec2u, cell : DggsA5Cell, shapeIndex : u32) -> vec2f {
|
|
5209
|
+
let anchorInfo = dggs_a5_segment_to_anchor_info(cell);
|
|
5210
|
+
if (cell.resolution == 0u) {
|
|
5211
|
+
return dggs_a5_get_face_vertex(shapeIndex);
|
|
5212
|
+
}
|
|
5213
|
+
if (cell.resolution == 1u) {
|
|
5214
|
+
return dggs_a5_get_triangle_vertex(anchorInfo.quintant, shapeIndex);
|
|
5215
|
+
}
|
|
5216
|
+
let anchor = dggs_a5_make_anchor(index, cell, anchorInfo);
|
|
5217
|
+
return dggs_a5_get_pentagon_vertex(anchor, cell.hilbertResolution, shapeIndex);
|
|
5218
|
+
}
|
|
5219
|
+
|
|
5220
|
+
fn dggs_a5_get_cell_center_face_point(index : vec2u, cell : DggsA5Cell) -> vec2f {
|
|
5221
|
+
let shapeVertexCount = dggs_a5_get_shape_vertex_count(cell);
|
|
5222
|
+
var center = vec2f(0.0);
|
|
5223
|
+
var vertexIndex = 0u;
|
|
5224
|
+
loop {
|
|
5225
|
+
if (vertexIndex >= shapeVertexCount) {
|
|
5226
|
+
break;
|
|
5227
|
+
}
|
|
5228
|
+
center += dggs_a5_get_cell_shape_face_point(index, cell, vertexIndex);
|
|
5229
|
+
vertexIndex += 1u;
|
|
5230
|
+
}
|
|
5231
|
+
return center / f32(shapeVertexCount);
|
|
5232
|
+
}
|
|
5233
|
+
|
|
5234
|
+
fn dggs_a5_to_polar(point : vec2f) -> vec2f {
|
|
5235
|
+
return vec2f(length(point), atan2(point.y, point.x));
|
|
5236
|
+
}
|
|
5237
|
+
|
|
5238
|
+
fn dggs_a5_to_cartesian(thetaPhi : vec2f) -> vec3f {
|
|
5239
|
+
let sinPhi = sin(thetaPhi.y);
|
|
5240
|
+
return vec3f(sinPhi * cos(thetaPhi.x), sinPhi * sin(thetaPhi.x), cos(thetaPhi.y));
|
|
5241
|
+
}
|
|
5242
|
+
|
|
5243
|
+
fn dggs_a5_normalize_vec3(point : vec3f) -> vec3f {
|
|
5244
|
+
let magnitude = length(point);
|
|
5245
|
+
if (magnitude < 1.0e-12) {
|
|
5246
|
+
return vec3f(0.0, 0.0, 1.0);
|
|
5247
|
+
}
|
|
5248
|
+
return point / magnitude;
|
|
5249
|
+
}
|
|
5250
|
+
|
|
5251
|
+
fn dggs_a5_get_face_triangle_index(polar : vec2f) -> u32 {
|
|
5252
|
+
return u32(dggs_a5_positive_mod_i32(i32(floor(polar.y / DGGS_PI_OVER_5)), 10));
|
|
5253
|
+
}
|
|
5254
|
+
|
|
5255
|
+
fn dggs_a5_normalize_gamma(gamma : f32) -> f32 {
|
|
5256
|
+
let segment = gamma / DGGS_TWO_PI_OVER_5;
|
|
5257
|
+
return (segment - round(segment)) * DGGS_TWO_PI_OVER_5;
|
|
5258
|
+
}
|
|
5259
|
+
|
|
5260
|
+
fn dggs_a5_should_reflect(polar : vec2f) -> bool {
|
|
5261
|
+
return polar.x * cos(dggs_a5_normalize_gamma(polar.y)) > DGGS_A5_DISTANCE_TO_EDGE;
|
|
5262
|
+
}
|
|
5263
|
+
|
|
5264
|
+
fn dggs_a5_get_base_face_triangle(faceTriangleIndex : u32) -> DggsA5FaceTriangle {
|
|
5265
|
+
let quintant = ((faceTriangleIndex + 1u) / 2u) % 5u;
|
|
5266
|
+
let center = dggs_a5_get_triangle_vertex(quintant, 0u);
|
|
5267
|
+
let corner1 = dggs_a5_get_triangle_vertex(quintant, 1u);
|
|
5268
|
+
let corner2 = dggs_a5_get_triangle_vertex(quintant, 2u);
|
|
5269
|
+
let edgeMidpoint = (corner1 + corner2) * 0.5;
|
|
5270
|
+
if ((faceTriangleIndex & 1u) == 0u) {
|
|
5271
|
+
return DggsA5FaceTriangle(center, edgeMidpoint, corner1);
|
|
5272
|
+
}
|
|
5273
|
+
return DggsA5FaceTriangle(center, corner2, edgeMidpoint);
|
|
5274
|
+
}
|
|
5275
|
+
|
|
5276
|
+
fn dggs_a5_get_face_triangle_vertex(triangle : DggsA5FaceTriangle, vertexIndex : u32) -> vec2f {
|
|
5277
|
+
if (vertexIndex == 0u) {
|
|
5278
|
+
return triangle.a;
|
|
5279
|
+
}
|
|
5280
|
+
if (vertexIndex == 1u) {
|
|
5281
|
+
return triangle.b;
|
|
5282
|
+
}
|
|
5283
|
+
return triangle.c;
|
|
5284
|
+
}
|
|
5285
|
+
|
|
5286
|
+
fn dggs_a5_get_reflected_face_triangle(
|
|
5287
|
+
faceTriangleIndex : u32,
|
|
5288
|
+
squashed : bool
|
|
5289
|
+
) -> DggsA5FaceTriangle {
|
|
5290
|
+
let baseTriangle = dggs_a5_get_base_face_triangle(faceTriangleIndex);
|
|
5291
|
+
let even = (faceTriangleIndex & 1u) == 0u;
|
|
5292
|
+
let midpoint = select(baseTriangle.c, baseTriangle.b, even);
|
|
5293
|
+
let scale = select(2.0, DGGS_A5_REFLECTED_TRIANGLE_SCALE, squashed);
|
|
5294
|
+
let reflectedA = -baseTriangle.a + midpoint * scale;
|
|
5295
|
+
return DggsA5FaceTriangle(reflectedA, baseTriangle.c, baseTriangle.b);
|
|
5296
|
+
}
|
|
5297
|
+
|
|
5298
|
+
fn dggs_a5_get_face_triangle(
|
|
5299
|
+
faceTriangleIndex : u32,
|
|
5300
|
+
reflected : bool,
|
|
5301
|
+
squashed : bool
|
|
5302
|
+
) -> DggsA5FaceTriangle {
|
|
5303
|
+
if (reflected) {
|
|
5304
|
+
return dggs_a5_get_reflected_face_triangle(faceTriangleIndex, squashed);
|
|
5305
|
+
}
|
|
5306
|
+
return dggs_a5_get_base_face_triangle(faceTriangleIndex);
|
|
5307
|
+
}
|
|
5308
|
+
|
|
5309
|
+
fn dggs_a5_face_triangle_to_spherical_triangle(
|
|
5310
|
+
faceTriangleIndex : u32,
|
|
5311
|
+
origin : u32,
|
|
5312
|
+
reflected : bool
|
|
5313
|
+
) -> DggsA5SphericalTriangle {
|
|
5314
|
+
let faceTriangle = dggs_a5_get_face_triangle(faceTriangleIndex, reflected, true);
|
|
5315
|
+
let originAngle = dggs_a5_get_origin_angle(origin);
|
|
5316
|
+
let quaternion = dggs_a5_get_origin_quaternion(origin);
|
|
5317
|
+
|
|
5318
|
+
let polarA = dggs_a5_to_polar(faceTriangle.a);
|
|
5319
|
+
let polarB = dggs_a5_to_polar(faceTriangle.b);
|
|
5320
|
+
let polarC = dggs_a5_to_polar(faceTriangle.c);
|
|
5321
|
+
let sphericalA = dggs_a5_quaternion_rotate(
|
|
5322
|
+
dggs_a5_to_cartesian(vec2f(polarA.y + originAngle, atan(polarA.x))),
|
|
5323
|
+
quaternion
|
|
5324
|
+
);
|
|
5325
|
+
let sphericalB = dggs_a5_quaternion_rotate(
|
|
5326
|
+
dggs_a5_to_cartesian(vec2f(polarB.y + originAngle, atan(polarB.x))),
|
|
5327
|
+
quaternion
|
|
5328
|
+
);
|
|
5329
|
+
let sphericalC = dggs_a5_quaternion_rotate(
|
|
5330
|
+
dggs_a5_to_cartesian(vec2f(polarC.y + originAngle, atan(polarC.x))),
|
|
5331
|
+
quaternion
|
|
5332
|
+
);
|
|
5333
|
+
return DggsA5SphericalTriangle(
|
|
5334
|
+
dggs_a5_normalize_vec3(sphericalA),
|
|
5335
|
+
dggs_a5_normalize_vec3(sphericalB),
|
|
5336
|
+
dggs_a5_normalize_vec3(sphericalC)
|
|
5337
|
+
);
|
|
5338
|
+
}
|
|
5339
|
+
|
|
5340
|
+
fn dggs_a5_face_to_barycentric(point : vec2f, triangle : DggsA5FaceTriangle) -> vec3f {
|
|
5341
|
+
let d31 = triangle.a - triangle.c;
|
|
5342
|
+
let d23 = triangle.c - triangle.b;
|
|
5343
|
+
let d3p = point - triangle.c;
|
|
5344
|
+
let determinant = d23.x * d31.y - d23.y * d31.x;
|
|
5345
|
+
if (abs(determinant) < 1.0e-12) {
|
|
5346
|
+
return vec3f(1.0, 0.0, 0.0);
|
|
5347
|
+
}
|
|
5348
|
+
let b0 = (d23.x * d3p.y - d23.y * d3p.x) / determinant;
|
|
5349
|
+
let b1 = (d31.x * d3p.y - d31.y * d3p.x) / determinant;
|
|
5350
|
+
return vec3f(b0, b1, 1.0 - (b0 + b1));
|
|
5351
|
+
}
|
|
5352
|
+
|
|
5353
|
+
fn dggs_a5_triangle_area(a : vec3f, b : vec3f, c : vec3f) -> f32 {
|
|
5354
|
+
let midA = dggs_a5_normalize_vec3((b + c) * 0.5);
|
|
5355
|
+
let midB = dggs_a5_normalize_vec3((c + a) * 0.5);
|
|
5356
|
+
let midC = dggs_a5_normalize_vec3((a + b) * 0.5);
|
|
5357
|
+
let tripleProduct = dot(midA, cross(midB, midC));
|
|
5358
|
+
let clamped = clamp(tripleProduct, -1.0, 1.0);
|
|
5359
|
+
if (abs(clamped) < 1.0e-8) {
|
|
5360
|
+
return 2.0 * clamped;
|
|
5361
|
+
}
|
|
5362
|
+
return asin(clamped) * 2.0;
|
|
5363
|
+
}
|
|
5364
|
+
|
|
5365
|
+
fn dggs_a5_spherical_triangle_area(triangle : DggsA5SphericalTriangle) -> f32 {
|
|
5366
|
+
return dggs_a5_triangle_area(triangle.a, triangle.b, triangle.c);
|
|
5367
|
+
}
|
|
5368
|
+
|
|
5369
|
+
fn dggs_a5_vector_difference(a : vec3f, b : vec3f) -> f32 {
|
|
5370
|
+
let midpoint = dggs_a5_normalize_vec3((a + b) * 0.5);
|
|
5371
|
+
let crossProduct = cross(a, midpoint);
|
|
5372
|
+
let distance = length(crossProduct);
|
|
5373
|
+
if (distance < 1.0e-8) {
|
|
5374
|
+
return 0.5 * length(a - b);
|
|
5375
|
+
}
|
|
5376
|
+
return distance;
|
|
5377
|
+
}
|
|
5378
|
+
|
|
5379
|
+
fn dggs_a5_slerp(a : vec3f, b : vec3f, t : f32) -> vec3f {
|
|
5380
|
+
let cosineGamma = clamp(dot(a, b), -1.0, 1.0);
|
|
5381
|
+
let gamma = acos(cosineGamma);
|
|
5382
|
+
if (gamma < 1.0e-8) {
|
|
5383
|
+
return dggs_a5_normalize_vec3(mix(a, b, t));
|
|
5384
|
+
}
|
|
5385
|
+
let sinGamma = sin(gamma);
|
|
5386
|
+
if (abs(sinGamma) < 1.0e-8) {
|
|
5387
|
+
return dggs_a5_normalize_vec3(mix(a, b, t));
|
|
5388
|
+
}
|
|
5389
|
+
let weightA = sin((1.0 - t) * gamma) / sinGamma;
|
|
5390
|
+
let weightB = sin(t * gamma) / sinGamma;
|
|
5391
|
+
return dggs_a5_normalize_vec3(weightA * a + weightB * b);
|
|
5392
|
+
}
|
|
5393
|
+
|
|
5394
|
+
fn dggs_a5_safe_acos(value : f32) -> f32 {
|
|
5395
|
+
if (value < 1.0e-3) {
|
|
5396
|
+
return 2.0 * value + value * value * value / 3.0;
|
|
5397
|
+
}
|
|
5398
|
+
return acos(clamp(1.0 - 2.0 * value * value, -1.0, 1.0));
|
|
5399
|
+
}
|
|
5400
|
+
|
|
5401
|
+
fn dggs_a5_polyhedral_inverse_edge(a : vec3f, b : vec3f, edgeHeight : f32) -> vec3f {
|
|
5402
|
+
let difference = dggs_a5_vector_difference(a, b);
|
|
5403
|
+
let denominator = max(dggs_a5_safe_acos(difference), 1.0e-8);
|
|
5404
|
+
let interpolation = dggs_a5_safe_acos(clamp(edgeHeight, 0.0, 1.0) * difference) / denominator;
|
|
5405
|
+
return dggs_a5_slerp(a, b, clamp(interpolation, 0.0, 1.0));
|
|
5406
|
+
}
|
|
5407
|
+
|
|
5408
|
+
fn dggs_a5_polyhedral_inverse(
|
|
5409
|
+
facePoint : vec2f,
|
|
5410
|
+
faceTriangle : DggsA5FaceTriangle,
|
|
5411
|
+
sphericalTriangle : DggsA5SphericalTriangle
|
|
5412
|
+
) -> vec3f {
|
|
5413
|
+
let barycentric = dggs_a5_face_to_barycentric(facePoint, faceTriangle);
|
|
5414
|
+
if (barycentric.x > 0.9999999) {
|
|
5415
|
+
return sphericalTriangle.a;
|
|
5416
|
+
}
|
|
5417
|
+
if (barycentric.y > 0.9999999) {
|
|
5418
|
+
return sphericalTriangle.b;
|
|
5419
|
+
}
|
|
5420
|
+
if (barycentric.z > 0.9999999) {
|
|
5421
|
+
return sphericalTriangle.c;
|
|
5422
|
+
}
|
|
5423
|
+
if (abs(barycentric.z) < 1.0e-6) {
|
|
5424
|
+
return dggs_a5_polyhedral_inverse_edge(
|
|
5425
|
+
sphericalTriangle.a,
|
|
5426
|
+
sphericalTriangle.b,
|
|
5427
|
+
1.0 - barycentric.x
|
|
5428
|
+
);
|
|
5429
|
+
}
|
|
5430
|
+
if (abs(barycentric.y) < 1.0e-6) {
|
|
5431
|
+
return dggs_a5_polyhedral_inverse_edge(
|
|
5432
|
+
sphericalTriangle.a,
|
|
5433
|
+
sphericalTriangle.c,
|
|
5434
|
+
1.0 - barycentric.x
|
|
5435
|
+
);
|
|
5436
|
+
}
|
|
5437
|
+
|
|
5438
|
+
let crossBC = cross(sphericalTriangle.b, sphericalTriangle.c);
|
|
5439
|
+
let areaABC = dggs_a5_spherical_triangle_area(sphericalTriangle);
|
|
5440
|
+
let h = max(1.0 - barycentric.x, 1.0e-8);
|
|
5441
|
+
let areaRatio = barycentric.z / h;
|
|
5442
|
+
let alpha = areaRatio * areaABC;
|
|
5443
|
+
let sineAlpha = sin(alpha);
|
|
5444
|
+
let halfSineAlpha = sin(alpha * 0.5);
|
|
5445
|
+
let chordCoefficient = 2.0 * halfSineAlpha * halfSineAlpha;
|
|
5446
|
+
let dotAB = dot(sphericalTriangle.a, sphericalTriangle.b);
|
|
5447
|
+
let dotBC = dot(sphericalTriangle.b, sphericalTriangle.c);
|
|
5448
|
+
let dotCA = dot(sphericalTriangle.c, sphericalTriangle.a);
|
|
5449
|
+
let lengthBC = length(crossBC);
|
|
5450
|
+
let volume = dot(sphericalTriangle.a, crossBC);
|
|
5451
|
+
let f = sineAlpha * volume + chordCoefficient * (dotAB * dotBC - dotCA);
|
|
5452
|
+
let g = chordCoefficient * lengthBC * (1.0 + dotAB);
|
|
5453
|
+
let edgeAngle = max(acos(clamp(dotBC, -1.0, 1.0)), 1.0e-8);
|
|
5454
|
+
let q = 2.0 / edgeAngle * atan2(g, f);
|
|
5455
|
+
let pointOnBC = dggs_a5_slerp(sphericalTriangle.b, sphericalTriangle.c, q);
|
|
5456
|
+
let k = dggs_a5_vector_difference(sphericalTriangle.a, pointOnBC);
|
|
5457
|
+
let denominator = max(dggs_a5_safe_acos(k), 1.0e-8);
|
|
5458
|
+
let t = dggs_a5_safe_acos(h * k) / denominator;
|
|
5459
|
+
return dggs_a5_slerp(sphericalTriangle.a, pointOnBC, t);
|
|
5460
|
+
}
|
|
5461
|
+
|
|
5462
|
+
fn dggs_a5_authalic_inverse(phi : f32) -> f32 {
|
|
5463
|
+
let sinPhi = sin(phi);
|
|
5464
|
+
let cosPhi = cos(phi);
|
|
5465
|
+
let coefficientX = 2.0 * (cosPhi - sinPhi) * (cosPhi + sinPhi);
|
|
5466
|
+
var u0 = coefficientX * 4.92842354825238055e-17 + 2.19128723067677184e-14;
|
|
5467
|
+
var u1 = coefficientX * u0 + 1.02018123778161003e-11;
|
|
5468
|
+
u0 = coefficientX * u1 - u0 + 5.08622073997266026e-9;
|
|
5469
|
+
u1 = coefficientX * u0 - u1 + 0.00000288319780486075558;
|
|
5470
|
+
u0 = coefficientX * u1 - u0 + 0.00223920899635416575;
|
|
5471
|
+
return phi + 2.0 * sinPhi * cosPhi * u0;
|
|
5472
|
+
}
|
|
5473
|
+
|
|
5474
|
+
fn dggs_a5_normalize_longitude(longitude : f32) -> f32 {
|
|
5475
|
+
var result = longitude;
|
|
5476
|
+
loop {
|
|
5477
|
+
if (result < -180.0) {
|
|
5478
|
+
result += 360.0;
|
|
5479
|
+
} else {
|
|
5480
|
+
break;
|
|
5481
|
+
}
|
|
5482
|
+
}
|
|
5483
|
+
loop {
|
|
5484
|
+
if (result >= 180.0) {
|
|
5485
|
+
result -= 360.0;
|
|
5486
|
+
} else {
|
|
5487
|
+
break;
|
|
5488
|
+
}
|
|
5489
|
+
}
|
|
5490
|
+
return result;
|
|
5491
|
+
}
|
|
5492
|
+
|
|
5493
|
+
fn dggs_a5_normalize_longitude_to_center(longitude : f32, centerLongitude : f32) -> f32 {
|
|
5494
|
+
var result = longitude;
|
|
5495
|
+
loop {
|
|
5496
|
+
if (result - centerLongitude > 180.0) {
|
|
5497
|
+
result -= 360.0;
|
|
5498
|
+
} else {
|
|
5499
|
+
break;
|
|
5500
|
+
}
|
|
5501
|
+
}
|
|
5502
|
+
loop {
|
|
5503
|
+
if (result - centerLongitude < -180.0) {
|
|
5504
|
+
result += 360.0;
|
|
5505
|
+
} else {
|
|
5506
|
+
break;
|
|
5507
|
+
}
|
|
5508
|
+
}
|
|
5509
|
+
return result;
|
|
5510
|
+
}
|
|
5511
|
+
|
|
5512
|
+
fn dggs_a5_sphere_to_lnglat(cartesian : vec3f) -> vec2f {
|
|
5513
|
+
let point = dggs_a5_normalize_vec3(cartesian);
|
|
5514
|
+
let theta = atan2(point.y, point.x);
|
|
5515
|
+
let phi = acos(clamp(point.z, -1.0, 1.0));
|
|
5516
|
+
let longitude = dggs_a5_normalize_longitude(theta * DGGS_RADIANS_TO_DEGREES - DGGS_A5_LONGITUDE_OFFSET);
|
|
5517
|
+
let authalicLatitude = DGGS_PI_OVER_2 - phi;
|
|
5518
|
+
let latitude = dggs_a5_authalic_inverse(authalicLatitude) * DGGS_RADIANS_TO_DEGREES;
|
|
5519
|
+
return vec2f(longitude, latitude);
|
|
5520
|
+
}
|
|
5521
|
+
|
|
5522
|
+
fn dggs_a5_face_to_lnglat(facePoint : vec2f, origin : u32) -> vec2f {
|
|
5523
|
+
let polar = dggs_a5_to_polar(facePoint);
|
|
5524
|
+
let faceTriangleIndex = dggs_a5_get_face_triangle_index(polar);
|
|
5525
|
+
let reflected = dggs_a5_should_reflect(polar);
|
|
5526
|
+
let faceTriangle = dggs_a5_get_face_triangle(faceTriangleIndex, reflected, false);
|
|
5527
|
+
let sphericalTriangle = dggs_a5_face_triangle_to_spherical_triangle(
|
|
5528
|
+
faceTriangleIndex,
|
|
5529
|
+
origin,
|
|
5530
|
+
reflected
|
|
5531
|
+
);
|
|
5532
|
+
return dggs_a5_sphere_to_lnglat(
|
|
5533
|
+
dggs_a5_polyhedral_inverse(facePoint, faceTriangle, sphericalTriangle)
|
|
5534
|
+
);
|
|
5535
|
+
}
|
|
5536
|
+
|
|
5537
|
+
fn dggs_a5_get_boundary_point(index : vec2u, vertexIndex : u32) -> vec2f {
|
|
5538
|
+
let cell = dggs_a5_deserialize(index);
|
|
5539
|
+
if (cell.valid == 0u || dggs_u64_is_zero(index)) {
|
|
5540
|
+
return vec2f(0.0);
|
|
5541
|
+
}
|
|
5542
|
+
|
|
5543
|
+
let shapeVertexCount = dggs_a5_get_shape_vertex_count(cell);
|
|
5544
|
+
let shapeIndex = dggs_a5_get_reversed_shape_index(vertexIndex, shapeVertexCount);
|
|
5545
|
+
let facePoint = dggs_a5_get_cell_shape_face_point(index, cell, shapeIndex);
|
|
5546
|
+
let centerPoint = dggs_a5_get_cell_center_face_point(index, cell);
|
|
5547
|
+
var lngLat = dggs_a5_face_to_lnglat(facePoint, cell.origin);
|
|
5548
|
+
let centerLngLat = dggs_a5_face_to_lnglat(centerPoint, cell.origin);
|
|
5549
|
+
lngLat.x = dggs_a5_normalize_longitude_to_center(lngLat.x, centerLngLat.x);
|
|
5550
|
+
return lngLat;
|
|
5551
|
+
}
|
|
5552
|
+
|
|
5553
|
+
fn dggs_a5_get_boundary_point_fp64_split(index : vec2u, vertexIndex : u32) -> vec4f {
|
|
5554
|
+
return dggs_boundary_point_to_fp64_split(dggs_a5_get_boundary_point(index, vertexIndex));
|
|
5555
|
+
}
|
|
5556
|
+
|
|
5557
|
+
fn dggs_h3_get_mode(index: vec2u) -> u32 {
|
|
5558
|
+
return dggs_u64_extract_bits(index, 59u, 4u);
|
|
5559
|
+
}
|
|
5560
|
+
|
|
5561
|
+
fn dggs_h3_is_cell_mode(index: vec2u) -> bool {
|
|
5562
|
+
return dggs_h3_get_mode(index) == DGGS_H3_CELL_MODE;
|
|
5563
|
+
}
|
|
5564
|
+
|
|
5565
|
+
fn dggs_h3_get_resolution(index: vec2u) -> u32 {
|
|
5566
|
+
return dggs_u64_extract_bits(index, 52u, 4u);
|
|
5567
|
+
}
|
|
5568
|
+
|
|
5569
|
+
fn dggs_h3_get_base_cell(index: vec2u) -> u32 {
|
|
5570
|
+
return dggs_u64_extract_bits(index, 45u, 7u);
|
|
5571
|
+
}
|
|
5572
|
+
|
|
5573
|
+
fn dggs_h3_digit_bit_offset(resolution: u32) -> u32 {
|
|
5574
|
+
return 3u * (DGGS_H3_MAX_RESOLUTION - resolution);
|
|
5575
|
+
}
|
|
5576
|
+
|
|
5577
|
+
fn dggs_h3_get_digit(index: vec2u, resolution: u32) -> u32 {
|
|
5578
|
+
if (resolution == 0u || resolution > DGGS_H3_MAX_RESOLUTION) {
|
|
5579
|
+
return DGGS_H3_UNUSED_DIGIT;
|
|
5580
|
+
}
|
|
5581
|
+
return dggs_u64_extract_bits(index, dggs_h3_digit_bit_offset(resolution), 3u);
|
|
5582
|
+
}
|
|
5583
|
+
|
|
5584
|
+
fn dggs_h3_is_valid_cell_id(index: vec2u) -> bool {
|
|
5585
|
+
let cellResolution = dggs_h3_get_resolution(index);
|
|
5586
|
+
if (
|
|
5587
|
+
!dggs_h3_is_cell_mode(index) ||
|
|
5588
|
+
cellResolution > DGGS_H3_MAX_RESOLUTION ||
|
|
5589
|
+
dggs_h3_get_base_cell(index) > DGGS_H3_MAX_BASE_CELL
|
|
5590
|
+
) {
|
|
5591
|
+
return false;
|
|
5592
|
+
}
|
|
5593
|
+
|
|
5594
|
+
var digitResolution = 1u;
|
|
5595
|
+
loop {
|
|
5596
|
+
if (digitResolution > DGGS_H3_MAX_RESOLUTION) {
|
|
5597
|
+
break;
|
|
5598
|
+
}
|
|
5599
|
+
|
|
5600
|
+
let digit = dggs_h3_get_digit(index, digitResolution);
|
|
5601
|
+
if (digitResolution <= cellResolution) {
|
|
5602
|
+
if (digit == DGGS_H3_UNUSED_DIGIT) {
|
|
5603
|
+
return false;
|
|
5604
|
+
}
|
|
5605
|
+
} else if (digit != DGGS_H3_UNUSED_DIGIT) {
|
|
5606
|
+
return false;
|
|
5607
|
+
}
|
|
5608
|
+
digitResolution += 1u;
|
|
5609
|
+
}
|
|
5610
|
+
return true;
|
|
5611
|
+
}
|
|
5612
|
+
|
|
5613
|
+
fn dggs_h3_get_parent(index: vec2u, parentResolution: u32) -> vec2u {
|
|
5614
|
+
let currentResolution = dggs_h3_get_resolution(index);
|
|
5615
|
+
let targetResolution = min(parentResolution, currentResolution);
|
|
5616
|
+
var parent = dggs_u64_set_bits(index, 52u, 4u, targetResolution);
|
|
5617
|
+
var resolution = targetResolution + 1u;
|
|
5618
|
+
loop {
|
|
5619
|
+
if (resolution > DGGS_H3_MAX_RESOLUTION) {
|
|
5620
|
+
break;
|
|
5621
|
+
}
|
|
5622
|
+
parent = dggs_u64_set_bits(
|
|
5623
|
+
parent,
|
|
5624
|
+
dggs_h3_digit_bit_offset(resolution),
|
|
5625
|
+
3u,
|
|
5626
|
+
DGGS_H3_UNUSED_DIGIT
|
|
5627
|
+
);
|
|
5628
|
+
resolution += 1u;
|
|
5629
|
+
}
|
|
5630
|
+
return parent;
|
|
5631
|
+
}
|
|
5632
|
+
|
|
5633
|
+
fn dggs_h3_positive_angle_rads(angle: f32) -> f32 {
|
|
5634
|
+
var result = angle;
|
|
5635
|
+
if (result < 0.0) {
|
|
5636
|
+
result += DGGS_TWO_PI;
|
|
5637
|
+
}
|
|
5638
|
+
if (result >= DGGS_TWO_PI) {
|
|
5639
|
+
result -= DGGS_TWO_PI;
|
|
5640
|
+
}
|
|
5641
|
+
return result;
|
|
5642
|
+
}
|
|
5643
|
+
|
|
5644
|
+
fn dggs_h3_constrain_longitude(longitude: f32) -> f32 {
|
|
5645
|
+
var result = longitude;
|
|
5646
|
+
loop {
|
|
5647
|
+
if (result <= DGGS_PI) {
|
|
5648
|
+
break;
|
|
5649
|
+
}
|
|
5650
|
+
result -= DGGS_TWO_PI;
|
|
5651
|
+
}
|
|
5652
|
+
loop {
|
|
5653
|
+
if (result >= -DGGS_PI) {
|
|
5654
|
+
break;
|
|
5655
|
+
}
|
|
5656
|
+
result += DGGS_TWO_PI;
|
|
5657
|
+
}
|
|
5658
|
+
return result;
|
|
5659
|
+
}
|
|
5660
|
+
|
|
5661
|
+
fn dggs_h3_is_resolution_class_iii(resolution: u32) -> bool {
|
|
5662
|
+
return (resolution & 1u) != 0u;
|
|
5663
|
+
}
|
|
5664
|
+
|
|
5665
|
+
fn dggs_h3_is_base_cell_pentagon(baseCell: u32) -> bool {
|
|
5666
|
+
return baseCell == 4u ||
|
|
5667
|
+
baseCell == 14u ||
|
|
5668
|
+
baseCell == 24u ||
|
|
5669
|
+
baseCell == 38u ||
|
|
5670
|
+
baseCell == 49u ||
|
|
5671
|
+
baseCell == 58u ||
|
|
5672
|
+
baseCell == 63u ||
|
|
5673
|
+
baseCell == 72u ||
|
|
5674
|
+
baseCell == 83u ||
|
|
5675
|
+
baseCell == 97u ||
|
|
5676
|
+
baseCell == 107u ||
|
|
5677
|
+
baseCell == 117u;
|
|
5678
|
+
}
|
|
5679
|
+
|
|
5680
|
+
fn dggs_h3_get_base_cell_home(baseCell: u32) -> DggsH3FaceIJK {
|
|
5681
|
+
let values = array<vec4i, 122>(
|
|
5682
|
+
vec4i(1, 1, 0, 0),
|
|
5683
|
+
vec4i(2, 1, 1, 0),
|
|
5684
|
+
vec4i(1, 0, 0, 0),
|
|
5685
|
+
vec4i(2, 1, 0, 0),
|
|
5686
|
+
vec4i(0, 2, 0, 0),
|
|
5687
|
+
vec4i(1, 1, 1, 0),
|
|
5688
|
+
vec4i(1, 0, 0, 1),
|
|
5689
|
+
vec4i(2, 0, 0, 0),
|
|
5690
|
+
vec4i(0, 1, 0, 0),
|
|
5691
|
+
vec4i(2, 0, 1, 0),
|
|
5692
|
+
vec4i(1, 0, 1, 0),
|
|
5693
|
+
vec4i(1, 0, 1, 1),
|
|
5694
|
+
vec4i(3, 1, 0, 0),
|
|
5695
|
+
vec4i(3, 1, 1, 0),
|
|
5696
|
+
vec4i(11, 2, 0, 0),
|
|
5697
|
+
vec4i(4, 1, 0, 0),
|
|
5698
|
+
vec4i(0, 0, 0, 0),
|
|
5699
|
+
vec4i(6, 0, 1, 0),
|
|
5700
|
+
vec4i(0, 0, 0, 1),
|
|
5701
|
+
vec4i(2, 0, 1, 1),
|
|
5702
|
+
vec4i(7, 0, 0, 1),
|
|
5703
|
+
vec4i(2, 0, 0, 1),
|
|
5704
|
+
vec4i(0, 1, 1, 0),
|
|
5705
|
+
vec4i(6, 0, 0, 1),
|
|
5706
|
+
vec4i(10, 2, 0, 0),
|
|
5707
|
+
vec4i(6, 0, 0, 0),
|
|
5708
|
+
vec4i(3, 0, 0, 0),
|
|
5709
|
+
vec4i(11, 1, 0, 0),
|
|
5710
|
+
vec4i(4, 1, 1, 0),
|
|
5711
|
+
vec4i(3, 0, 1, 0),
|
|
5712
|
+
vec4i(0, 0, 1, 1),
|
|
5713
|
+
vec4i(4, 0, 0, 0),
|
|
5714
|
+
vec4i(5, 0, 1, 0),
|
|
5715
|
+
vec4i(0, 0, 1, 0),
|
|
5716
|
+
vec4i(7, 0, 1, 0),
|
|
5717
|
+
vec4i(11, 1, 1, 0),
|
|
5718
|
+
vec4i(7, 0, 0, 0),
|
|
5719
|
+
vec4i(10, 1, 0, 0),
|
|
5720
|
+
vec4i(12, 2, 0, 0),
|
|
5721
|
+
vec4i(6, 1, 0, 1),
|
|
5722
|
+
vec4i(7, 1, 0, 1),
|
|
5723
|
+
vec4i(4, 0, 0, 1),
|
|
5724
|
+
vec4i(3, 0, 0, 1),
|
|
5725
|
+
vec4i(3, 0, 1, 1),
|
|
5726
|
+
vec4i(4, 0, 1, 0),
|
|
5727
|
+
vec4i(6, 1, 0, 0),
|
|
5728
|
+
vec4i(11, 0, 0, 0),
|
|
5729
|
+
vec4i(8, 0, 0, 1),
|
|
5730
|
+
vec4i(5, 0, 0, 1),
|
|
5731
|
+
vec4i(14, 2, 0, 0),
|
|
5732
|
+
vec4i(5, 0, 0, 0),
|
|
5733
|
+
vec4i(12, 1, 0, 0),
|
|
5734
|
+
vec4i(10, 1, 1, 0),
|
|
5735
|
+
vec4i(4, 0, 1, 1),
|
|
5736
|
+
vec4i(12, 1, 1, 0),
|
|
5737
|
+
vec4i(7, 1, 0, 0),
|
|
5738
|
+
vec4i(11, 0, 1, 0),
|
|
5739
|
+
vec4i(10, 0, 0, 0),
|
|
5740
|
+
vec4i(13, 2, 0, 0),
|
|
5741
|
+
vec4i(10, 0, 0, 1),
|
|
5742
|
+
vec4i(11, 0, 0, 1),
|
|
5743
|
+
vec4i(9, 0, 1, 0),
|
|
5744
|
+
vec4i(8, 0, 1, 0),
|
|
5745
|
+
vec4i(6, 2, 0, 0),
|
|
5746
|
+
vec4i(8, 0, 0, 0),
|
|
5747
|
+
vec4i(9, 0, 0, 1),
|
|
5748
|
+
vec4i(14, 1, 0, 0),
|
|
5749
|
+
vec4i(5, 1, 0, 1),
|
|
5750
|
+
vec4i(16, 0, 1, 1),
|
|
5751
|
+
vec4i(8, 1, 0, 1),
|
|
5752
|
+
vec4i(5, 1, 0, 0),
|
|
5753
|
+
vec4i(12, 0, 0, 0),
|
|
5754
|
+
vec4i(7, 2, 0, 0),
|
|
5755
|
+
vec4i(12, 0, 1, 0),
|
|
5756
|
+
vec4i(10, 0, 1, 0),
|
|
5757
|
+
vec4i(9, 0, 0, 0),
|
|
5758
|
+
vec4i(13, 1, 0, 0),
|
|
5759
|
+
vec4i(16, 0, 0, 1),
|
|
5760
|
+
vec4i(15, 0, 1, 1),
|
|
5761
|
+
vec4i(15, 0, 1, 0),
|
|
5762
|
+
vec4i(16, 0, 1, 0),
|
|
5763
|
+
vec4i(14, 1, 1, 0),
|
|
5764
|
+
vec4i(13, 1, 1, 0),
|
|
5765
|
+
vec4i(5, 2, 0, 0),
|
|
5766
|
+
vec4i(8, 1, 0, 0),
|
|
5767
|
+
vec4i(14, 0, 0, 0),
|
|
5768
|
+
vec4i(9, 1, 0, 1),
|
|
5769
|
+
vec4i(14, 0, 0, 1),
|
|
5770
|
+
vec4i(17, 0, 0, 1),
|
|
5771
|
+
vec4i(12, 0, 0, 1),
|
|
5772
|
+
vec4i(16, 0, 0, 0),
|
|
5773
|
+
vec4i(17, 0, 1, 1),
|
|
5774
|
+
vec4i(15, 0, 0, 1),
|
|
5775
|
+
vec4i(16, 1, 0, 1),
|
|
5776
|
+
vec4i(9, 1, 0, 0),
|
|
5777
|
+
vec4i(15, 0, 0, 0),
|
|
5778
|
+
vec4i(13, 0, 0, 0),
|
|
5779
|
+
vec4i(8, 2, 0, 0),
|
|
5780
|
+
vec4i(13, 0, 1, 0),
|
|
5781
|
+
vec4i(17, 1, 0, 1),
|
|
5782
|
+
vec4i(19, 0, 1, 0),
|
|
5783
|
+
vec4i(14, 0, 1, 0),
|
|
5784
|
+
vec4i(19, 0, 1, 1),
|
|
5785
|
+
vec4i(17, 0, 1, 0),
|
|
5786
|
+
vec4i(13, 0, 0, 1),
|
|
5787
|
+
vec4i(17, 0, 0, 0),
|
|
5788
|
+
vec4i(16, 1, 0, 0),
|
|
5789
|
+
vec4i(9, 2, 0, 0),
|
|
5790
|
+
vec4i(15, 1, 0, 1),
|
|
5791
|
+
vec4i(15, 1, 0, 0),
|
|
5792
|
+
vec4i(18, 0, 1, 1),
|
|
5793
|
+
vec4i(18, 0, 0, 1),
|
|
5794
|
+
vec4i(19, 0, 0, 1),
|
|
5795
|
+
vec4i(17, 1, 0, 0),
|
|
5796
|
+
vec4i(19, 0, 0, 0),
|
|
5797
|
+
vec4i(18, 0, 1, 0),
|
|
5798
|
+
vec4i(18, 1, 0, 1),
|
|
5799
|
+
vec4i(19, 2, 0, 0),
|
|
5800
|
+
vec4i(19, 1, 0, 0),
|
|
5801
|
+
vec4i(18, 0, 0, 0),
|
|
5802
|
+
vec4i(19, 1, 0, 1),
|
|
5803
|
+
vec4i(18, 1, 0, 0)
|
|
5804
|
+
);
|
|
5805
|
+
let value = values[min(baseCell, DGGS_H3_MAX_BASE_CELL)];
|
|
5806
|
+
return DggsH3FaceIJK(
|
|
5807
|
+
u32(value.x),
|
|
5808
|
+
value.yzw,
|
|
5809
|
+
select(1u, 0u, baseCell > DGGS_H3_MAX_BASE_CELL)
|
|
5810
|
+
);
|
|
5811
|
+
}
|
|
5812
|
+
|
|
5813
|
+
fn dggs_h3_get_face_center_geo(face: u32) -> vec2f {
|
|
5814
|
+
let values = array<vec2f, 20>(
|
|
5815
|
+
vec2f(0.803582649718989942, 1.248397419617396099),
|
|
5816
|
+
vec2f(1.307747883455638156, 2.536945009877921159),
|
|
5817
|
+
vec2f(1.054751253523952054, -1.347517358900396623),
|
|
5818
|
+
vec2f(0.600191595538186799, -0.450603909469755746),
|
|
5819
|
+
vec2f(0.491715428198773866, 0.401988202911306943),
|
|
5820
|
+
vec2f(0.172745327415618701, 1.678146885280433686),
|
|
5821
|
+
vec2f(0.605929321571350690, 2.953923329812411617),
|
|
5822
|
+
vec2f(0.427370518328979641, -1.888876200336285401),
|
|
5823
|
+
vec2f(-0.079066118549212831, -0.733429513380867741),
|
|
5824
|
+
vec2f(-0.230961644455383637, 0.506495587332349035),
|
|
5825
|
+
vec2f(0.079066118549212831, 2.408163140208925497),
|
|
5826
|
+
vec2f(0.230961644455383637, -2.635097066257444203),
|
|
5827
|
+
vec2f(-0.172745327415618701, -1.463445768309359553),
|
|
5828
|
+
vec2f(-0.605929321571350690, -0.187669323777381622),
|
|
5829
|
+
vec2f(-0.427370518328979641, 1.252716453253507838),
|
|
5830
|
+
vec2f(-0.600191595538186799, 2.690988744120037492),
|
|
5831
|
+
vec2f(-0.491715428198773866, -2.739604450678486295),
|
|
5832
|
+
vec2f(-0.803582649718989942, -1.893195233972397139),
|
|
5833
|
+
vec2f(-1.307747883455638156, -0.604647643711872080),
|
|
5834
|
+
vec2f(-1.054751253523952054, 1.794075294689396615)
|
|
5835
|
+
);
|
|
5836
|
+
return values[min(face, 19u)];
|
|
5837
|
+
}
|
|
5838
|
+
|
|
5839
|
+
fn dggs_h3_get_face_axis_azimuths(face: u32) -> vec3f {
|
|
5840
|
+
let values = array<vec3f, 20>(
|
|
5841
|
+
vec3f(5.619958268523939882, 3.525563166130744542, 1.431168063737548730),
|
|
5842
|
+
vec3f(5.760339081714187279, 3.665943979320991689, 1.571548876927796127),
|
|
5843
|
+
vec3f(0.780213654393430055, 4.969003859179821079, 2.874608756786625655),
|
|
5844
|
+
vec3f(0.430469363979999913, 4.619259568766391033, 2.524864466373195467),
|
|
5845
|
+
vec3f(6.130269123335111400, 4.035874020941915804, 1.941478918548720291),
|
|
5846
|
+
vec3f(2.692877706530642877, 0.598482604137447119, 4.787272808923838195),
|
|
5847
|
+
vec3f(2.982963003477243874, 0.888567901084048369, 5.077358105870439581),
|
|
5848
|
+
vec3f(3.532912002790141181, 1.438516900396945656, 5.627307105183336758),
|
|
5849
|
+
vec3f(3.494305004259568154, 1.399909901866372864, 5.588700106652763840),
|
|
5850
|
+
vec3f(3.003214169499538391, 0.908819067106342928, 5.097609271892733906),
|
|
5851
|
+
vec3f(5.930472956509811562, 3.836077854116615875, 1.741682751723420374),
|
|
5852
|
+
vec3f(0.138378484090254847, 4.327168688876645809, 2.232773586483450311),
|
|
5853
|
+
vec3f(0.448714947059150361, 4.637505151845541521, 2.543110049452346120),
|
|
5854
|
+
vec3f(0.158629650112549365, 4.347419854898940135, 2.253024752505744869),
|
|
5855
|
+
vec3f(5.891865957979238535, 3.797470855586042958, 1.703075753192847583),
|
|
5856
|
+
vec3f(2.711123289609793325, 0.616728187216597771, 4.805518392002988683),
|
|
5857
|
+
vec3f(3.294508837434268316, 1.200113735041072948, 5.388903939827463911),
|
|
5858
|
+
vec3f(3.804819692245439833, 1.710424589852244509, 5.899214794638635174),
|
|
5859
|
+
vec3f(3.664438879055192436, 1.570043776661997111, 5.758833981448388027),
|
|
5860
|
+
vec3f(2.361378999196363184, 0.266983896803167583, 4.455774101589558636)
|
|
5861
|
+
);
|
|
5862
|
+
return values[min(face, 19u)];
|
|
5863
|
+
}
|
|
5864
|
+
|
|
5865
|
+
fn dggs_h3_get_max_dim_by_cii_resolution(resolution: u32) -> i32 {
|
|
5866
|
+
let values = array<i32, 17>(
|
|
5867
|
+
2, -1, 14, -1, 98, -1, 686, -1, 4802, -1, 33614, -1, 235298, -1, 1647086, -1, 11529602
|
|
5868
|
+
);
|
|
5869
|
+
return values[min(resolution, 16u)];
|
|
5870
|
+
}
|
|
5871
|
+
|
|
5872
|
+
fn dggs_h3_get_unit_vector(digit: u32) -> vec3i {
|
|
5873
|
+
if (digit == 1u) {
|
|
5874
|
+
return vec3i(0, 0, 1);
|
|
5875
|
+
}
|
|
5876
|
+
if (digit == 2u) {
|
|
5877
|
+
return vec3i(0, 1, 0);
|
|
5878
|
+
}
|
|
5879
|
+
if (digit == 3u) {
|
|
5880
|
+
return vec3i(0, 1, 1);
|
|
5881
|
+
}
|
|
5882
|
+
if (digit == 4u) {
|
|
5883
|
+
return vec3i(1, 0, 0);
|
|
5884
|
+
}
|
|
5885
|
+
if (digit == 5u) {
|
|
5886
|
+
return vec3i(1, 0, 1);
|
|
5887
|
+
}
|
|
5888
|
+
if (digit == 6u) {
|
|
5889
|
+
return vec3i(1, 1, 0);
|
|
5890
|
+
}
|
|
5891
|
+
return vec3i(0);
|
|
5892
|
+
}
|
|
5893
|
+
|
|
5894
|
+
fn dggs_h3_ijk_normalize(coord: vec3i) -> vec3i {
|
|
5895
|
+
var normalized = coord;
|
|
5896
|
+
if (normalized.x < 0) {
|
|
5897
|
+
normalized.y -= normalized.x;
|
|
5898
|
+
normalized.z -= normalized.x;
|
|
5899
|
+
normalized.x = 0;
|
|
5900
|
+
}
|
|
5901
|
+
if (normalized.y < 0) {
|
|
5902
|
+
normalized.x -= normalized.y;
|
|
5903
|
+
normalized.z -= normalized.y;
|
|
5904
|
+
normalized.y = 0;
|
|
5905
|
+
}
|
|
5906
|
+
if (normalized.z < 0) {
|
|
5907
|
+
normalized.x -= normalized.z;
|
|
5908
|
+
normalized.y -= normalized.z;
|
|
5909
|
+
normalized.z = 0;
|
|
5910
|
+
}
|
|
5911
|
+
|
|
5912
|
+
let minimumValue = min(normalized.x, min(normalized.y, normalized.z));
|
|
5913
|
+
if (minimumValue > 0) {
|
|
5914
|
+
normalized -= vec3i(minimumValue);
|
|
5915
|
+
}
|
|
5916
|
+
return normalized;
|
|
5917
|
+
}
|
|
5918
|
+
|
|
5919
|
+
fn dggs_h3_neighbor(coord: vec3i, digit: u32) -> vec3i {
|
|
5920
|
+
if (digit > 0u && digit < DGGS_H3_UNUSED_DIGIT) {
|
|
5921
|
+
return dggs_h3_ijk_normalize(coord + dggs_h3_get_unit_vector(digit));
|
|
5922
|
+
}
|
|
5923
|
+
return coord;
|
|
5924
|
+
}
|
|
5925
|
+
|
|
5926
|
+
fn dggs_h3_down_ap3(coord: vec3i) -> vec3i {
|
|
5927
|
+
let iVector = vec3i(2, 0, 1) * coord.x;
|
|
5928
|
+
let jVector = vec3i(1, 2, 0) * coord.y;
|
|
5929
|
+
let kVector = vec3i(0, 1, 2) * coord.z;
|
|
5930
|
+
return dggs_h3_ijk_normalize(iVector + jVector + kVector);
|
|
5931
|
+
}
|
|
5932
|
+
|
|
5933
|
+
fn dggs_h3_down_ap3r(coord: vec3i) -> vec3i {
|
|
5934
|
+
let iVector = vec3i(2, 1, 0) * coord.x;
|
|
5935
|
+
let jVector = vec3i(0, 2, 1) * coord.y;
|
|
5936
|
+
let kVector = vec3i(1, 0, 2) * coord.z;
|
|
5937
|
+
return dggs_h3_ijk_normalize(iVector + jVector + kVector);
|
|
5938
|
+
}
|
|
5939
|
+
|
|
5940
|
+
fn dggs_h3_down_ap7(coord: vec3i) -> vec3i {
|
|
5941
|
+
let iVector = vec3i(3, 0, 1) * coord.x;
|
|
5942
|
+
let jVector = vec3i(1, 3, 0) * coord.y;
|
|
5943
|
+
let kVector = vec3i(0, 1, 3) * coord.z;
|
|
5944
|
+
return dggs_h3_ijk_normalize(iVector + jVector + kVector);
|
|
5945
|
+
}
|
|
5946
|
+
|
|
5947
|
+
fn dggs_h3_down_ap7r(coord: vec3i) -> vec3i {
|
|
5948
|
+
let iVector = vec3i(3, 1, 0) * coord.x;
|
|
5949
|
+
let jVector = vec3i(0, 3, 1) * coord.y;
|
|
5950
|
+
let kVector = vec3i(1, 0, 3) * coord.z;
|
|
5951
|
+
return dggs_h3_ijk_normalize(iVector + jVector + kVector);
|
|
5952
|
+
}
|
|
5953
|
+
|
|
5954
|
+
fn dggs_h3_get_center_face_ijk(index: vec2u) -> DggsH3FaceIJK {
|
|
5955
|
+
if (!dggs_h3_is_valid_cell_id(index)) {
|
|
5956
|
+
return DggsH3FaceIJK(0u, vec3i(0), 0u);
|
|
5957
|
+
}
|
|
5958
|
+
|
|
5959
|
+
let baseCell = dggs_h3_get_base_cell(index);
|
|
5960
|
+
if (dggs_h3_is_base_cell_pentagon(baseCell)) {
|
|
5961
|
+
return DggsH3FaceIJK(0u, vec3i(0), 0u);
|
|
5962
|
+
}
|
|
5963
|
+
|
|
5964
|
+
var faceIJK = dggs_h3_get_base_cell_home(baseCell);
|
|
5965
|
+
let cellResolution = dggs_h3_get_resolution(index);
|
|
5966
|
+
var resolution = 1u;
|
|
5967
|
+
loop {
|
|
5968
|
+
if (resolution > cellResolution) {
|
|
5969
|
+
break;
|
|
5970
|
+
}
|
|
5971
|
+
|
|
5972
|
+
if (dggs_h3_is_resolution_class_iii(resolution)) {
|
|
5973
|
+
faceIJK.coord = dggs_h3_down_ap7(faceIJK.coord);
|
|
5974
|
+
} else {
|
|
5975
|
+
faceIJK.coord = dggs_h3_down_ap7r(faceIJK.coord);
|
|
5976
|
+
}
|
|
5977
|
+
faceIJK.coord = dggs_h3_neighbor(faceIJK.coord, dggs_h3_get_digit(index, resolution));
|
|
5978
|
+
resolution += 1u;
|
|
5979
|
+
}
|
|
5980
|
+
|
|
5981
|
+
return faceIJK;
|
|
5982
|
+
}
|
|
5983
|
+
|
|
5984
|
+
fn dggs_h3_get_vertex_offset(resolution: u32, vertexIndex: u32) -> vec3i {
|
|
5985
|
+
let pointIndex = vertexIndex % 6u;
|
|
5986
|
+
if (dggs_h3_is_resolution_class_iii(resolution)) {
|
|
5987
|
+
let vertices = array<vec3i, 6>(
|
|
5988
|
+
vec3i(5, 4, 0),
|
|
5989
|
+
vec3i(1, 5, 0),
|
|
5990
|
+
vec3i(0, 5, 4),
|
|
5991
|
+
vec3i(0, 1, 5),
|
|
5992
|
+
vec3i(4, 0, 5),
|
|
5993
|
+
vec3i(5, 0, 1)
|
|
5994
|
+
);
|
|
5995
|
+
return vertices[pointIndex];
|
|
5996
|
+
}
|
|
5997
|
+
|
|
5998
|
+
let vertices = array<vec3i, 6>(
|
|
5999
|
+
vec3i(2, 1, 0),
|
|
6000
|
+
vec3i(1, 2, 0),
|
|
6001
|
+
vec3i(0, 2, 1),
|
|
6002
|
+
vec3i(0, 1, 2),
|
|
6003
|
+
vec3i(1, 0, 2),
|
|
6004
|
+
vec3i(2, 0, 1)
|
|
6005
|
+
);
|
|
6006
|
+
return vertices[pointIndex];
|
|
6007
|
+
}
|
|
6008
|
+
|
|
6009
|
+
fn dggs_h3_get_boundary_vertex(index: vec2u, vertexIndex: u32) -> DggsH3BoundaryVertex {
|
|
6010
|
+
let center = dggs_h3_get_center_face_ijk(index);
|
|
6011
|
+
if (center.valid == 0u) {
|
|
6012
|
+
return DggsH3BoundaryVertex(0u, vec3i(0), 0u, 0u);
|
|
6013
|
+
}
|
|
6014
|
+
|
|
6015
|
+
let cellResolution = dggs_h3_get_resolution(index);
|
|
6016
|
+
var adjustedResolution = cellResolution;
|
|
6017
|
+
var centerCoord = dggs_h3_down_ap3r(dggs_h3_down_ap3(center.coord));
|
|
6018
|
+
if (dggs_h3_is_resolution_class_iii(cellResolution)) {
|
|
6019
|
+
centerCoord = dggs_h3_down_ap7r(centerCoord);
|
|
6020
|
+
adjustedResolution += 1u;
|
|
6021
|
+
}
|
|
6022
|
+
|
|
6023
|
+
let vertexCoord = dggs_h3_ijk_normalize(
|
|
6024
|
+
centerCoord + dggs_h3_get_vertex_offset(cellResolution, vertexIndex)
|
|
6025
|
+
);
|
|
6026
|
+
let maximumDimension = dggs_h3_get_max_dim_by_cii_resolution(adjustedResolution) * 3;
|
|
6027
|
+
let vertexDimension = vertexCoord.x + vertexCoord.y + vertexCoord.z;
|
|
6028
|
+
if (vertexDimension >= maximumDimension) {
|
|
6029
|
+
return DggsH3BoundaryVertex(center.face, vertexCoord, adjustedResolution, 0u);
|
|
6030
|
+
}
|
|
6031
|
+
|
|
6032
|
+
return DggsH3BoundaryVertex(center.face, vertexCoord, adjustedResolution, 1u);
|
|
6033
|
+
}
|
|
6034
|
+
|
|
6035
|
+
fn dggs_h3_is_single_face_boundary(index: vec2u) -> bool {
|
|
6036
|
+
var vertexIndex = 0u;
|
|
6037
|
+
loop {
|
|
6038
|
+
if (vertexIndex >= 6u) {
|
|
6039
|
+
break;
|
|
6040
|
+
}
|
|
6041
|
+
if (dggs_h3_get_boundary_vertex(index, vertexIndex).valid == 0u) {
|
|
6042
|
+
return false;
|
|
6043
|
+
}
|
|
6044
|
+
vertexIndex += 1u;
|
|
6045
|
+
}
|
|
6046
|
+
return true;
|
|
6047
|
+
}
|
|
6048
|
+
|
|
6049
|
+
fn dggs_h3_ijk_to_hex2d(coord: vec3i) -> vec2f {
|
|
6050
|
+
let i = f32(coord.x - coord.z);
|
|
6051
|
+
let j = f32(coord.y - coord.z);
|
|
6052
|
+
return vec2f(i - 0.5 * j, j * DGGS_H3_SQRT3_2);
|
|
6053
|
+
}
|
|
6054
|
+
|
|
6055
|
+
fn dggs_h3_geo_az_distance_rads(center: vec2f, azimuth: f32, distance: f32) -> vec2f {
|
|
6056
|
+
if (distance < 1.0e-7) {
|
|
6057
|
+
return center;
|
|
6058
|
+
}
|
|
6059
|
+
|
|
6060
|
+
let positiveAzimuth = dggs_h3_positive_angle_rads(azimuth);
|
|
6061
|
+
let latitude = asin(clamp(
|
|
6062
|
+
sin(center.x) * cos(distance) + cos(center.x) * sin(distance) * cos(positiveAzimuth),
|
|
6063
|
+
-1.0,
|
|
6064
|
+
1.0
|
|
6065
|
+
));
|
|
6066
|
+
var longitude = 0.0;
|
|
6067
|
+
if (abs(latitude - DGGS_PI_OVER_2) < 1.0e-7) {
|
|
6068
|
+
return vec2f(DGGS_PI_OVER_2, 0.0);
|
|
6069
|
+
}
|
|
6070
|
+
if (abs(latitude + DGGS_PI_OVER_2) < 1.0e-7) {
|
|
6071
|
+
return vec2f(-DGGS_PI_OVER_2, 0.0);
|
|
6072
|
+
}
|
|
6073
|
+
|
|
6074
|
+
let inverseCosLatitude = 1.0 / max(cos(latitude), 1.0e-8);
|
|
6075
|
+
let sinLongitude = clamp(
|
|
6076
|
+
sin(positiveAzimuth) * sin(distance) * inverseCosLatitude,
|
|
6077
|
+
-1.0,
|
|
6078
|
+
1.0
|
|
6079
|
+
);
|
|
6080
|
+
let cosLongitude = clamp(
|
|
6081
|
+
(cos(distance) - sin(center.x) * sin(latitude)) / max(cos(center.x), 1.0e-8) *
|
|
6082
|
+
inverseCosLatitude,
|
|
6083
|
+
-1.0,
|
|
6084
|
+
1.0
|
|
6085
|
+
);
|
|
6086
|
+
longitude = dggs_h3_constrain_longitude(center.y + atan2(sinLongitude, cosLongitude));
|
|
6087
|
+
return vec2f(latitude, longitude);
|
|
6088
|
+
}
|
|
6089
|
+
|
|
6090
|
+
fn dggs_h3_hex2d_to_lnglat(point: vec2f, face: u32, resolution: u32, substrate: bool) -> vec2f {
|
|
6091
|
+
var radius = length(point);
|
|
6092
|
+
let center = dggs_h3_get_face_center_geo(face);
|
|
6093
|
+
if (radius < 1.0e-7) {
|
|
6094
|
+
return vec2f(center.y * DGGS_RADIANS_TO_DEGREES, center.x * DGGS_RADIANS_TO_DEGREES);
|
|
6095
|
+
}
|
|
6096
|
+
|
|
6097
|
+
var theta = atan2(point.y, point.x);
|
|
6098
|
+
var resolutionIndex = 0u;
|
|
6099
|
+
loop {
|
|
6100
|
+
if (resolutionIndex >= resolution) {
|
|
6101
|
+
break;
|
|
6102
|
+
}
|
|
6103
|
+
radius *= DGGS_H3_RSQRT7;
|
|
6104
|
+
resolutionIndex += 1u;
|
|
6105
|
+
}
|
|
6106
|
+
|
|
6107
|
+
if (substrate) {
|
|
6108
|
+
radius *= DGGS_H3_ONETHIRD;
|
|
6109
|
+
if (dggs_h3_is_resolution_class_iii(resolution)) {
|
|
6110
|
+
radius *= DGGS_H3_RSQRT7;
|
|
6111
|
+
}
|
|
6112
|
+
} else if (dggs_h3_is_resolution_class_iii(resolution)) {
|
|
6113
|
+
theta = dggs_h3_positive_angle_rads(theta + DGGS_H3_AP7_ROT_RADS);
|
|
6114
|
+
}
|
|
6115
|
+
|
|
6116
|
+
radius = atan(radius * DGGS_H3_RES0_U_GNOMONIC);
|
|
6117
|
+
theta = dggs_h3_positive_angle_rads(dggs_h3_get_face_axis_azimuths(face).x - theta);
|
|
6118
|
+
let latitudeLongitude = dggs_h3_geo_az_distance_rads(center, theta, radius);
|
|
6119
|
+
return vec2f(
|
|
6120
|
+
latitudeLongitude.y * DGGS_RADIANS_TO_DEGREES,
|
|
6121
|
+
latitudeLongitude.x * DGGS_RADIANS_TO_DEGREES
|
|
6122
|
+
);
|
|
6123
|
+
}
|
|
6124
|
+
|
|
6125
|
+
fn dggs_h3_get_boundary_point(index: vec2u, vertexIndex: u32) -> vec2f {
|
|
6126
|
+
if (!dggs_h3_is_single_face_boundary(index)) {
|
|
6127
|
+
return vec2f(0.0);
|
|
6128
|
+
}
|
|
6129
|
+
|
|
6130
|
+
let vertex = dggs_h3_get_boundary_vertex(index, vertexIndex % 6u);
|
|
6131
|
+
let hexPoint = dggs_h3_ijk_to_hex2d(vertex.coord);
|
|
6132
|
+
return dggs_h3_hex2d_to_lnglat(hexPoint, vertex.face, vertex.resolution, true);
|
|
6133
|
+
}
|
|
6134
|
+
|
|
6135
|
+
fn dggs_h3_get_boundary_point_fp64_split(index: vec2u, vertexIndex: u32) -> vec4f {
|
|
6136
|
+
return dggs_boundary_point_to_fp64_split(dggs_h3_get_boundary_point(index, vertexIndex));
|
|
6137
|
+
}
|
|
6138
|
+
|
|
6139
|
+
fn dggs_s2_get_face(index: vec2u) -> u32 {
|
|
6140
|
+
return dggs_u64_extract_bits(index, 61u, 3u);
|
|
6141
|
+
}
|
|
6142
|
+
|
|
6143
|
+
fn dggs_s2_get_level(index: vec2u) -> u32 {
|
|
6144
|
+
let trailingZeros = dggs_u64_count_trailing_zeros(index);
|
|
6145
|
+
if (trailingZeros > 60u) {
|
|
6146
|
+
return 0u;
|
|
6147
|
+
}
|
|
6148
|
+
return DGGS_S2_MAX_LEVEL - trailingZeros / 2u;
|
|
6149
|
+
}
|
|
6150
|
+
|
|
6151
|
+
fn dggs_s2_is_valid_cell_id(index: vec2u) -> bool {
|
|
6152
|
+
let trailingZeros = dggs_u64_count_trailing_zeros(index);
|
|
6153
|
+
return !dggs_u64_is_zero(index) &&
|
|
6154
|
+
dggs_s2_get_face(index) <= 5u &&
|
|
6155
|
+
trailingZeros <= 60u &&
|
|
6156
|
+
trailingZeros % 2u == 0u;
|
|
6157
|
+
}
|
|
6158
|
+
|
|
6159
|
+
fn dggs_s2_get_child_position(index: vec2u, level: u32) -> u32 {
|
|
6160
|
+
if (level == 0u || level > DGGS_S2_MAX_LEVEL) {
|
|
6161
|
+
return 0u;
|
|
6162
|
+
}
|
|
6163
|
+
return dggs_u64_extract_bits(index, 2u * (DGGS_S2_MAX_LEVEL - level) + 1u, 2u);
|
|
6164
|
+
}
|
|
6165
|
+
|
|
6166
|
+
// Packed geohash keys store the geohash length in bits 60..63 and right-align
|
|
6167
|
+
// the base32 character codes in the lower 60 bits, first character first.
|
|
6168
|
+
fn dggs_geohash_get_length(index: vec2u) -> u32 {
|
|
6169
|
+
return min(
|
|
6170
|
+
dggs_u64_extract_bits(index, DGGS_GEOHASH_LENGTH_BIT_OFFSET, 4u),
|
|
6171
|
+
DGGS_GEOHASH_MAX_LENGTH
|
|
6172
|
+
);
|
|
6173
|
+
}
|
|
6174
|
+
|
|
6175
|
+
fn dggs_geohash_get_character(index: vec2u, characterIndex: u32) -> u32 {
|
|
6176
|
+
let length = dggs_geohash_get_length(index);
|
|
6177
|
+
if (characterIndex >= length) {
|
|
6178
|
+
return 0u;
|
|
6179
|
+
}
|
|
6180
|
+
return dggs_u64_extract_bits(index, 5u * (length - characterIndex - 1u), 5u);
|
|
6181
|
+
}
|
|
6182
|
+
|
|
6183
|
+
// Returns vec4(west, south, east, north) in longitude/latitude degrees.
|
|
6184
|
+
fn dggs_geohash_get_bounds(index: vec2u) -> vec4f {
|
|
6185
|
+
let length = dggs_geohash_get_length(index);
|
|
6186
|
+
var west = -180.0;
|
|
6187
|
+
var east = 180.0;
|
|
6188
|
+
var south = -90.0;
|
|
6189
|
+
var north = 90.0;
|
|
6190
|
+
var isLongitude = true;
|
|
6191
|
+
var characterIndex = 0u;
|
|
6192
|
+
loop {
|
|
6193
|
+
if (characterIndex >= length) {
|
|
6194
|
+
break;
|
|
6195
|
+
}
|
|
6196
|
+
|
|
6197
|
+
let character = dggs_geohash_get_character(index, characterIndex);
|
|
6198
|
+
var bitIndex = 0u;
|
|
6199
|
+
loop {
|
|
6200
|
+
if (bitIndex >= 5u) {
|
|
6201
|
+
break;
|
|
6202
|
+
}
|
|
6203
|
+
|
|
6204
|
+
let bit = (character >> (4u - bitIndex)) & 1u;
|
|
6205
|
+
if (isLongitude) {
|
|
6206
|
+
let midpoint = (west + east) * 0.5;
|
|
6207
|
+
if (bit == 0u) {
|
|
6208
|
+
east = midpoint;
|
|
6209
|
+
} else {
|
|
6210
|
+
west = midpoint;
|
|
6211
|
+
}
|
|
6212
|
+
} else {
|
|
6213
|
+
let midpoint = (south + north) * 0.5;
|
|
6214
|
+
if (bit == 0u) {
|
|
6215
|
+
north = midpoint;
|
|
6216
|
+
} else {
|
|
6217
|
+
south = midpoint;
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
isLongitude = !isLongitude;
|
|
6221
|
+
bitIndex += 1u;
|
|
6222
|
+
}
|
|
6223
|
+
characterIndex += 1u;
|
|
6224
|
+
}
|
|
6225
|
+
|
|
6226
|
+
return vec4f(west, south, east, north);
|
|
6227
|
+
}
|
|
6228
|
+
|
|
6229
|
+
fn dggs_bounds_get_boundary_point(bounds: vec4f, vertexIndex: u32) -> vec2f {
|
|
6230
|
+
let pointIndex = vertexIndex % 4u;
|
|
6231
|
+
if (pointIndex == 0u) {
|
|
6232
|
+
return vec2f(bounds.x, bounds.w);
|
|
6233
|
+
}
|
|
6234
|
+
if (pointIndex == 1u) {
|
|
6235
|
+
return vec2f(bounds.z, bounds.w);
|
|
6236
|
+
}
|
|
6237
|
+
if (pointIndex == 2u) {
|
|
6238
|
+
return vec2f(bounds.z, bounds.y);
|
|
6239
|
+
}
|
|
6240
|
+
return vec2f(bounds.x, bounds.y);
|
|
6241
|
+
}
|
|
6242
|
+
|
|
6243
|
+
fn dggs_geohash_get_boundary_point(index: vec2u, vertexIndex: u32) -> vec2f {
|
|
6244
|
+
return dggs_bounds_get_boundary_point(dggs_geohash_get_bounds(index), vertexIndex);
|
|
6245
|
+
}
|
|
6246
|
+
|
|
6247
|
+
fn dggs_geohash_get_boundary_point_fp64_split(index: vec2u, vertexIndex: u32) -> vec4f {
|
|
6248
|
+
return dggs_boundary_point_to_fp64_split(dggs_geohash_get_boundary_point(index, vertexIndex));
|
|
6249
|
+
}
|
|
6250
|
+
|
|
6251
|
+
// Packed quadkey keys store the quadkey length in bits 58..63 and right-align
|
|
6252
|
+
// the base4 digits in the lower 58 bits, first digit first.
|
|
6253
|
+
fn dggs_quadkey_get_length(index: vec2u) -> u32 {
|
|
6254
|
+
return min(
|
|
6255
|
+
dggs_u64_extract_bits(index, DGGS_QUADKEY_LENGTH_BIT_OFFSET, 6u),
|
|
6256
|
+
DGGS_QUADKEY_MAX_LENGTH
|
|
6257
|
+
);
|
|
6258
|
+
}
|
|
6259
|
+
|
|
6260
|
+
fn dggs_quadkey_get_digit(index: vec2u, digitIndex: u32) -> u32 {
|
|
6261
|
+
let length = dggs_quadkey_get_length(index);
|
|
6262
|
+
if (digitIndex >= length) {
|
|
6263
|
+
return 0u;
|
|
6264
|
+
}
|
|
6265
|
+
return dggs_u64_extract_bits(index, 2u * (length - digitIndex - 1u), 2u);
|
|
6266
|
+
}
|
|
6267
|
+
|
|
6268
|
+
fn dggs_quadkey_get_tile(index: vec2u) -> vec3u {
|
|
6269
|
+
let length = dggs_quadkey_get_length(index);
|
|
6270
|
+
var tileX = 0u;
|
|
6271
|
+
var tileY = 0u;
|
|
6272
|
+
var digitIndex = 0u;
|
|
6273
|
+
loop {
|
|
6274
|
+
if (digitIndex >= length) {
|
|
6275
|
+
break;
|
|
6276
|
+
}
|
|
6277
|
+
|
|
6278
|
+
let digit = dggs_quadkey_get_digit(index, digitIndex);
|
|
6279
|
+
let mask = 1u << (length - digitIndex - 1u);
|
|
6280
|
+
if ((digit & 1u) != 0u) {
|
|
6281
|
+
tileX |= mask;
|
|
6282
|
+
}
|
|
6283
|
+
if ((digit & 2u) != 0u) {
|
|
6284
|
+
tileY |= mask;
|
|
6285
|
+
}
|
|
6286
|
+
digitIndex += 1u;
|
|
6287
|
+
}
|
|
6288
|
+
return vec3u(tileX, tileY, length);
|
|
6289
|
+
}
|
|
6290
|
+
|
|
6291
|
+
fn dggs_web_mercator_tile_y_to_latitude(tileY: f32, tileScale: f32) -> f32 {
|
|
6292
|
+
let mercatorY = DGGS_PI * (1.0 - 2.0 * tileY / tileScale);
|
|
6293
|
+
return (2.0 * atan(exp(mercatorY)) - DGGS_PI * 0.5) * DGGS_RADIANS_TO_DEGREES;
|
|
6294
|
+
}
|
|
6295
|
+
|
|
6296
|
+
// Returns vec4(west, south, east, north) in longitude/latitude degrees.
|
|
6297
|
+
fn dggs_quadkey_get_bounds(index: vec2u) -> vec4f {
|
|
6298
|
+
let tile = dggs_quadkey_get_tile(index);
|
|
6299
|
+
let tileScale = f32(1u << tile.z);
|
|
6300
|
+
let west = f32(tile.x) / tileScale * 360.0 - 180.0;
|
|
6301
|
+
let east = f32(tile.x + 1u) / tileScale * 360.0 - 180.0;
|
|
6302
|
+
let north = dggs_web_mercator_tile_y_to_latitude(f32(tile.y), tileScale);
|
|
6303
|
+
let south = dggs_web_mercator_tile_y_to_latitude(f32(tile.y + 1u), tileScale);
|
|
6304
|
+
return vec4f(west, south, east, north);
|
|
6305
|
+
}
|
|
6306
|
+
|
|
6307
|
+
fn dggs_quadkey_get_boundary_point(index: vec2u, vertexIndex: u32) -> vec2f {
|
|
6308
|
+
return dggs_bounds_get_boundary_point(dggs_quadkey_get_bounds(index), vertexIndex);
|
|
6309
|
+
}
|
|
6310
|
+
|
|
6311
|
+
fn dggs_quadkey_get_boundary_point_fp64_split(index: vec2u, vertexIndex: u32) -> vec4f {
|
|
6312
|
+
return dggs_boundary_point_to_fp64_split(dggs_quadkey_get_boundary_point(index, vertexIndex));
|
|
6313
|
+
}
|
|
6314
|
+
|
|
6315
|
+
fn dggs_s2_digit_to_xy(digit: u32) -> vec2u {
|
|
6316
|
+
if (digit == 1u) {
|
|
6317
|
+
return vec2u(0u, 1u);
|
|
6318
|
+
}
|
|
6319
|
+
if (digit == 2u) {
|
|
6320
|
+
return vec2u(1u, 1u);
|
|
6321
|
+
}
|
|
6322
|
+
if (digit == 3u) {
|
|
6323
|
+
return vec2u(1u, 0u);
|
|
6324
|
+
}
|
|
6325
|
+
return vec2u(0u, 0u);
|
|
6326
|
+
}
|
|
6327
|
+
|
|
6328
|
+
fn dggs_s2_rotate_and_flip_quadrant(size: u32, point: vec2u, digitXY: vec2u) -> vec2u {
|
|
6329
|
+
var result = point;
|
|
6330
|
+
if (digitXY.y == 0u) {
|
|
6331
|
+
if (digitXY.x == 1u) {
|
|
6332
|
+
result = vec2u(size - 1u - result.x, size - 1u - result.y);
|
|
6333
|
+
}
|
|
6334
|
+
result = result.yx;
|
|
6335
|
+
}
|
|
6336
|
+
return result;
|
|
6337
|
+
}
|
|
6338
|
+
|
|
6339
|
+
fn dggs_s2_get_ij(index: vec2u) -> vec2u {
|
|
6340
|
+
let level = dggs_s2_get_level(index);
|
|
6341
|
+
var point = vec2u(0u);
|
|
6342
|
+
var hilbertLevel = 1u;
|
|
6343
|
+
loop {
|
|
6344
|
+
if (hilbertLevel > level) {
|
|
6345
|
+
break;
|
|
6346
|
+
}
|
|
6347
|
+
let digitLevel = level - hilbertLevel + 1u;
|
|
6348
|
+
let digitXY = dggs_s2_digit_to_xy(dggs_s2_get_child_position(index, digitLevel));
|
|
6349
|
+
let size = 1u << (hilbertLevel - 1u);
|
|
6350
|
+
point = dggs_s2_rotate_and_flip_quadrant(size, point, digitXY);
|
|
6351
|
+
point += size * digitXY;
|
|
6352
|
+
hilbertLevel += 1u;
|
|
6353
|
+
}
|
|
6354
|
+
if ((dggs_s2_get_face(index) & 1u) != 0u) {
|
|
6355
|
+
point = point.yx;
|
|
6356
|
+
}
|
|
6357
|
+
return point;
|
|
6358
|
+
}
|
|
6359
|
+
|
|
6360
|
+
fn dggs_s2_single_st_to_uv(st: f32) -> f32 {
|
|
6361
|
+
if (st >= 0.5) {
|
|
6362
|
+
return (4.0 * st * st - 1.0) / 3.0;
|
|
6363
|
+
}
|
|
6364
|
+
return (1.0 - 4.0 * (1.0 - st) * (1.0 - st)) / 3.0;
|
|
6365
|
+
}
|
|
6366
|
+
|
|
6367
|
+
fn dggs_s2_ij_to_st(ij: vec2u, level: u32, offset: vec2f) -> vec2f {
|
|
6368
|
+
let maxSize = f32(1u << level);
|
|
6369
|
+
return (vec2f(f32(ij.x), f32(ij.y)) + offset) / maxSize;
|
|
6370
|
+
}
|
|
6371
|
+
|
|
6372
|
+
fn dggs_s2_st_to_uv(st: vec2f) -> vec2f {
|
|
6373
|
+
return vec2f(dggs_s2_single_st_to_uv(st.x), dggs_s2_single_st_to_uv(st.y));
|
|
6374
|
+
}
|
|
6375
|
+
|
|
6376
|
+
fn dggs_s2_face_uv_to_xyz(face: u32, uv: vec2f) -> vec3f {
|
|
6377
|
+
if (face == 0u) {
|
|
6378
|
+
return vec3f(1.0, uv.x, uv.y);
|
|
6379
|
+
}
|
|
6380
|
+
if (face == 1u) {
|
|
6381
|
+
return vec3f(-uv.x, 1.0, uv.y);
|
|
6382
|
+
}
|
|
6383
|
+
if (face == 2u) {
|
|
6384
|
+
return vec3f(-uv.x, -uv.y, 1.0);
|
|
6385
|
+
}
|
|
6386
|
+
if (face == 3u) {
|
|
6387
|
+
return vec3f(-1.0, -uv.y, -uv.x);
|
|
6388
|
+
}
|
|
6389
|
+
if (face == 4u) {
|
|
6390
|
+
return vec3f(uv.y, -1.0, -uv.x);
|
|
6391
|
+
}
|
|
6392
|
+
return vec3f(uv.y, uv.x, -1.0);
|
|
6393
|
+
}
|
|
6394
|
+
|
|
6395
|
+
fn dggs_s2_xyz_to_lnglat(xyz: vec3f) -> vec2f {
|
|
6396
|
+
let latitude = atan2(xyz.z, length(xyz.xy)) * DGGS_RADIANS_TO_DEGREES;
|
|
6397
|
+
let longitude = atan2(xyz.y, xyz.x) * DGGS_RADIANS_TO_DEGREES;
|
|
6398
|
+
return vec2f(longitude, latitude);
|
|
6399
|
+
}
|
|
6400
|
+
|
|
6401
|
+
fn dggs_s2_get_boundary_offset(vertexIndex: u32) -> vec2f {
|
|
6402
|
+
let pointIndex = vertexIndex % 4u;
|
|
6403
|
+
if (pointIndex == 1u) {
|
|
6404
|
+
return vec2f(0.0, 1.0);
|
|
6405
|
+
}
|
|
6406
|
+
if (pointIndex == 2u) {
|
|
6407
|
+
return vec2f(1.0, 1.0);
|
|
6408
|
+
}
|
|
6409
|
+
if (pointIndex == 3u) {
|
|
6410
|
+
return vec2f(1.0, 0.0);
|
|
6411
|
+
}
|
|
6412
|
+
return vec2f(0.0, 0.0);
|
|
6413
|
+
}
|
|
6414
|
+
|
|
6415
|
+
fn dggs_s2_get_boundary_point(index: vec2u, vertexIndex: u32) -> vec2f {
|
|
6416
|
+
let level = dggs_s2_get_level(index);
|
|
6417
|
+
let ij = dggs_s2_get_ij(index);
|
|
6418
|
+
let st = dggs_s2_ij_to_st(ij, level, dggs_s2_get_boundary_offset(vertexIndex));
|
|
6419
|
+
let uv = dggs_s2_st_to_uv(st);
|
|
6420
|
+
let xyz = dggs_s2_face_uv_to_xyz(dggs_s2_get_face(index), uv);
|
|
6421
|
+
return dggs_s2_xyz_to_lnglat(xyz);
|
|
6422
|
+
}
|
|
6423
|
+
|
|
6424
|
+
fn dggs_s2_get_boundary_point_fp64_split(index: vec2u, vertexIndex: u32) -> vec4f {
|
|
6425
|
+
return dggs_boundary_point_to_fp64_split(dggs_s2_get_boundary_point(index, vertexIndex));
|
|
6426
|
+
}
|
|
6427
|
+
`
|
|
6428
|
+
);
|
|
6429
|
+
|
|
6430
|
+
// dist/modules/geospatial/dggs/dggs.js
|
|
6431
|
+
var dggs = {
|
|
6432
|
+
name: "dggs",
|
|
6433
|
+
source: dggsWGSL
|
|
6434
|
+
};
|
|
6435
|
+
|
|
6436
|
+
// dist/modules/color/float-colors.js
|
|
6437
|
+
var STORAGE_COLOR_FORMAT = {
|
|
6438
|
+
RGBA8UNORM: 0,
|
|
6439
|
+
RGBA16FLOAT: 1,
|
|
6440
|
+
RGBA32FLOAT: 2
|
|
6441
|
+
};
|
|
6442
|
+
var STORAGE_COLOR_FORMAT_BYTE_LENGTHS = {
|
|
6443
|
+
rgba8unorm: 4,
|
|
6444
|
+
rgba16float: 8,
|
|
6445
|
+
rgba32float: 16
|
|
6446
|
+
};
|
|
6447
|
+
var STORAGE_COLOR_DEFAULT_BYTE_STRIDES = {
|
|
6448
|
+
...STORAGE_COLOR_FORMAT_BYTE_LENGTHS
|
|
6449
|
+
};
|
|
6450
|
+
var STORAGE_COLOR_FORMAT_BY_NAME = {
|
|
6451
|
+
rgba8unorm: STORAGE_COLOR_FORMAT.RGBA8UNORM,
|
|
6452
|
+
rgba16float: STORAGE_COLOR_FORMAT.RGBA16FLOAT,
|
|
6453
|
+
rgba32float: STORAGE_COLOR_FORMAT.RGBA32FLOAT
|
|
6454
|
+
};
|
|
6455
|
+
var STORAGE_COLOR_FORMAT_NAME_BY_VALUE = {
|
|
6456
|
+
[STORAGE_COLOR_FORMAT.RGBA8UNORM]: "rgba8unorm",
|
|
6457
|
+
[STORAGE_COLOR_FORMAT.RGBA16FLOAT]: "rgba16float",
|
|
6458
|
+
[STORAGE_COLOR_FORMAT.RGBA32FLOAT]: "rgba32float"
|
|
6459
|
+
};
|
|
6460
|
+
var COLORS_UNIFORM_TYPES = {
|
|
6461
|
+
useByteColors: "f32"
|
|
6462
|
+
};
|
|
6463
|
+
var COLORS_DEFAULT_UNIFORMS = {
|
|
6464
|
+
useByteColors: true
|
|
6465
|
+
};
|
|
6466
|
+
var STORAGE_COLORS_UNIFORM_TYPES = {
|
|
6467
|
+
format: "u32",
|
|
6468
|
+
wordStride: "u32",
|
|
6469
|
+
wordOffset: "u32",
|
|
6470
|
+
_padding: "u32"
|
|
6471
|
+
};
|
|
6472
|
+
var STORAGE_COLORS_DEFAULT_UNIFORMS = {
|
|
6473
|
+
format: STORAGE_COLOR_FORMAT.RGBA8UNORM,
|
|
6474
|
+
wordStride: STORAGE_COLOR_DEFAULT_BYTE_STRIDES.rgba8unorm / Uint32Array.BYTES_PER_ELEMENT,
|
|
6475
|
+
wordOffset: 0,
|
|
6476
|
+
_padding: 0
|
|
6477
|
+
};
|
|
6478
|
+
var COLORS_GLSL = buildGLSLColorModuleSource("colors");
|
|
6479
|
+
var FLOAT_COLORS_GLSL = buildGLSLColorModuleSource("floatColors");
|
|
6480
|
+
var COLORS_WGSL = buildWGSLColorModuleSource("colors");
|
|
6481
|
+
var FLOAT_COLORS_WGSL = buildWGSLColorModuleSource("floatColors");
|
|
6482
|
+
var STORAGE_COLORS_WGSL = (
|
|
6483
|
+
/* wgsl */
|
|
6484
|
+
`struct storageColorsUniforms {
|
|
6485
|
+
format: u32,
|
|
6486
|
+
wordStride: u32,
|
|
6487
|
+
wordOffset: u32,
|
|
6488
|
+
_padding: u32
|
|
6489
|
+
};
|
|
6490
|
+
|
|
6491
|
+
@group(0) @binding(auto) var<uniform> storageColors : storageColorsUniforms;
|
|
6492
|
+
@group(0) @binding(auto) var<storage, read> storageColorsBuffer : array<u32>;
|
|
6493
|
+
|
|
6494
|
+
const STORAGE_COLOR_FORMAT_RGBA8UNORM : u32 = ${STORAGE_COLOR_FORMAT.RGBA8UNORM}u;
|
|
6495
|
+
const STORAGE_COLOR_FORMAT_RGBA16FLOAT : u32 = ${STORAGE_COLOR_FORMAT.RGBA16FLOAT}u;
|
|
6496
|
+
|
|
6497
|
+
fn storageColors_getWordIndex(rowIndex: u32) -> u32 {
|
|
6498
|
+
return storageColors.wordOffset + rowIndex * storageColors.wordStride;
|
|
6499
|
+
}
|
|
6500
|
+
|
|
6501
|
+
fn storageColors_readRgba8UnormColor(wordIndex: u32) -> vec4<f32> {
|
|
6502
|
+
return unpack4x8unorm(storageColorsBuffer[wordIndex]);
|
|
6503
|
+
}
|
|
6504
|
+
|
|
6505
|
+
fn storageColors_readRgba16FloatColor(wordIndex: u32) -> vec4<f32> {
|
|
6506
|
+
let redGreen = unpack2x16float(storageColorsBuffer[wordIndex]);
|
|
6507
|
+
let blueAlpha = unpack2x16float(storageColorsBuffer[wordIndex + 1u]);
|
|
6508
|
+
return vec4<f32>(redGreen.x, redGreen.y, blueAlpha.x, blueAlpha.y);
|
|
6509
|
+
}
|
|
6510
|
+
|
|
6511
|
+
fn storageColors_readRgba32FloatColor(wordIndex: u32) -> vec4<f32> {
|
|
6512
|
+
return vec4<f32>(
|
|
6513
|
+
bitcast<f32>(storageColorsBuffer[wordIndex]),
|
|
6514
|
+
bitcast<f32>(storageColorsBuffer[wordIndex + 1u]),
|
|
6515
|
+
bitcast<f32>(storageColorsBuffer[wordIndex + 2u]),
|
|
6516
|
+
bitcast<f32>(storageColorsBuffer[wordIndex + 3u])
|
|
6517
|
+
);
|
|
6518
|
+
}
|
|
6519
|
+
|
|
6520
|
+
fn storageColors_readColor(rowIndex: u32) -> vec4<f32> {
|
|
6521
|
+
let wordIndex = storageColors_getWordIndex(rowIndex);
|
|
6522
|
+
if (storageColors.format == STORAGE_COLOR_FORMAT_RGBA8UNORM) {
|
|
6523
|
+
return storageColors_readRgba8UnormColor(wordIndex);
|
|
6524
|
+
}
|
|
6525
|
+
if (storageColors.format == STORAGE_COLOR_FORMAT_RGBA16FLOAT) {
|
|
6526
|
+
return storageColors_readRgba16FloatColor(wordIndex);
|
|
6527
|
+
}
|
|
6528
|
+
return storageColors_readRgba32FloatColor(wordIndex);
|
|
6529
|
+
}
|
|
6530
|
+
`
|
|
6531
|
+
);
|
|
6532
|
+
function buildGLSLColorModuleSource(primaryPrefix) {
|
|
6533
|
+
return (
|
|
6534
|
+
/* glsl */
|
|
6535
|
+
`layout(std140) uniform ${primaryPrefix}Uniforms {
|
|
3349
6536
|
float useByteColors;
|
|
3350
|
-
}
|
|
6537
|
+
} ${primaryPrefix};
|
|
3351
6538
|
|
|
3352
|
-
vec3
|
|
3353
|
-
return
|
|
6539
|
+
vec3 ${primaryPrefix}_normalize(vec3 inputColor) {
|
|
6540
|
+
return ${primaryPrefix}.useByteColors > 0.5 ? inputColor / 255.0 : inputColor;
|
|
3354
6541
|
}
|
|
3355
6542
|
|
|
3356
|
-
vec4
|
|
3357
|
-
return
|
|
6543
|
+
vec4 ${primaryPrefix}_normalize(vec4 inputColor) {
|
|
6544
|
+
return ${primaryPrefix}.useByteColors > 0.5 ? inputColor / 255.0 : inputColor;
|
|
3358
6545
|
}
|
|
3359
6546
|
|
|
3360
|
-
vec4
|
|
6547
|
+
vec4 ${primaryPrefix}_premultiplyAlpha(vec4 inputColor) {
|
|
3361
6548
|
return vec4(inputColor.rgb * inputColor.a, inputColor.a);
|
|
3362
6549
|
}
|
|
3363
6550
|
|
|
3364
|
-
vec4
|
|
6551
|
+
vec4 ${primaryPrefix}_unpremultiplyAlpha(vec4 inputColor) {
|
|
3365
6552
|
return inputColor.a > 0.0 ? vec4(inputColor.rgb / inputColor.a, inputColor.a) : vec4(0.0);
|
|
3366
6553
|
}
|
|
3367
6554
|
|
|
3368
|
-
vec4
|
|
3369
|
-
return
|
|
6555
|
+
vec4 ${primaryPrefix}_premultiply_alpha(vec4 inputColor) {
|
|
6556
|
+
return ${primaryPrefix}_premultiplyAlpha(inputColor);
|
|
3370
6557
|
}
|
|
3371
6558
|
|
|
3372
|
-
vec4
|
|
3373
|
-
return
|
|
6559
|
+
vec4 ${primaryPrefix}_unpremultiply_alpha(vec4 inputColor) {
|
|
6560
|
+
return ${primaryPrefix}_unpremultiplyAlpha(inputColor);
|
|
3374
6561
|
}
|
|
3375
6562
|
`
|
|
3376
|
-
);
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
6563
|
+
);
|
|
6564
|
+
}
|
|
6565
|
+
function buildWGSLColorModuleSource(primaryPrefix) {
|
|
6566
|
+
return (
|
|
6567
|
+
/* wgsl */
|
|
6568
|
+
`struct ${primaryPrefix}Uniforms {
|
|
3380
6569
|
useByteColors: f32
|
|
3381
6570
|
};
|
|
3382
6571
|
|
|
3383
|
-
@group(0) @binding(auto) var<uniform>
|
|
6572
|
+
@group(0) @binding(auto) var<uniform> ${primaryPrefix} : ${primaryPrefix}Uniforms;
|
|
3384
6573
|
|
|
3385
|
-
fn
|
|
3386
|
-
return select(inputColor, inputColor / 255.0,
|
|
6574
|
+
fn ${primaryPrefix}_normalize(inputColor: vec3<f32>) -> vec3<f32> {
|
|
6575
|
+
return select(inputColor, inputColor / 255.0, ${primaryPrefix}.useByteColors > 0.5);
|
|
3387
6576
|
}
|
|
3388
6577
|
|
|
3389
|
-
fn
|
|
3390
|
-
return select(inputColor, inputColor / 255.0,
|
|
6578
|
+
fn ${primaryPrefix}_normalize4(inputColor: vec4<f32>) -> vec4<f32> {
|
|
6579
|
+
return select(inputColor, inputColor / 255.0, ${primaryPrefix}.useByteColors > 0.5);
|
|
3391
6580
|
}
|
|
3392
6581
|
|
|
3393
|
-
fn
|
|
6582
|
+
fn ${primaryPrefix}_premultiplyAlpha(inputColor: vec4<f32>) -> vec4<f32> {
|
|
3394
6583
|
return vec4<f32>(inputColor.rgb * inputColor.a, inputColor.a);
|
|
3395
6584
|
}
|
|
3396
6585
|
|
|
3397
|
-
fn
|
|
6586
|
+
fn ${primaryPrefix}_unpremultiplyAlpha(inputColor: vec4<f32>) -> vec4<f32> {
|
|
3398
6587
|
return select(
|
|
3399
6588
|
vec4<f32>(0.0),
|
|
3400
6589
|
vec4<f32>(inputColor.rgb / inputColor.a, inputColor.a),
|
|
@@ -3402,27 +6591,86 @@ fn floatColors_unpremultiplyAlpha(inputColor: vec4<f32>) -> vec4<f32> {
|
|
|
3402
6591
|
);
|
|
3403
6592
|
}
|
|
3404
6593
|
|
|
3405
|
-
fn
|
|
3406
|
-
return
|
|
6594
|
+
fn ${primaryPrefix}_premultiply_alpha(inputColor: vec4<f32>) -> vec4<f32> {
|
|
6595
|
+
return ${primaryPrefix}_premultiplyAlpha(inputColor);
|
|
3407
6596
|
}
|
|
3408
6597
|
|
|
3409
|
-
fn
|
|
3410
|
-
return
|
|
6598
|
+
fn ${primaryPrefix}_unpremultiply_alpha(inputColor: vec4<f32>) -> vec4<f32> {
|
|
6599
|
+
return ${primaryPrefix}_unpremultiplyAlpha(inputColor);
|
|
3411
6600
|
}
|
|
3412
6601
|
`
|
|
3413
|
-
);
|
|
6602
|
+
);
|
|
6603
|
+
}
|
|
6604
|
+
function getStorageColorsUniforms(props = {}) {
|
|
6605
|
+
const format = resolveStorageColorFormat(props.format);
|
|
6606
|
+
const formatName = STORAGE_COLOR_FORMAT_NAME_BY_VALUE[format];
|
|
6607
|
+
const byteStride = props.byteStride ?? STORAGE_COLOR_DEFAULT_BYTE_STRIDES[formatName];
|
|
6608
|
+
const byteOffset = props.byteOffset ?? 0;
|
|
6609
|
+
const minimumByteStride = STORAGE_COLOR_FORMAT_BYTE_LENGTHS[formatName];
|
|
6610
|
+
validateStorageColorByteAlignment("byteStride", byteStride);
|
|
6611
|
+
validateStorageColorByteAlignment("byteOffset", byteOffset);
|
|
6612
|
+
if (byteStride < minimumByteStride) {
|
|
6613
|
+
throw new Error(`storageColors byteStride must be at least ${minimumByteStride} for ${formatName}`);
|
|
6614
|
+
}
|
|
6615
|
+
return {
|
|
6616
|
+
format,
|
|
6617
|
+
wordStride: byteStride / Uint32Array.BYTES_PER_ELEMENT,
|
|
6618
|
+
wordOffset: byteOffset / Uint32Array.BYTES_PER_ELEMENT,
|
|
6619
|
+
_padding: 0
|
|
6620
|
+
};
|
|
6621
|
+
}
|
|
6622
|
+
function resolveStorageColorFormat(format = "rgba8unorm") {
|
|
6623
|
+
if (typeof format === "number") {
|
|
6624
|
+
if (format in STORAGE_COLOR_FORMAT_NAME_BY_VALUE) {
|
|
6625
|
+
return format;
|
|
6626
|
+
}
|
|
6627
|
+
} else if (format in STORAGE_COLOR_FORMAT_BY_NAME) {
|
|
6628
|
+
return STORAGE_COLOR_FORMAT_BY_NAME[format];
|
|
6629
|
+
}
|
|
6630
|
+
throw new Error(`storageColors format must be one of ${Object.keys(STORAGE_COLOR_FORMAT_BY_NAME).join(", ")}`);
|
|
6631
|
+
}
|
|
6632
|
+
function validateStorageColorByteAlignment(name, value) {
|
|
6633
|
+
if (!Number.isInteger(value) || value < 0 || value % Uint32Array.BYTES_PER_ELEMENT !== 0) {
|
|
6634
|
+
throw new Error(`storageColors ${name} must be a non-negative 4-byte aligned integer`);
|
|
6635
|
+
}
|
|
6636
|
+
}
|
|
6637
|
+
var colors = {
|
|
6638
|
+
name: "colors",
|
|
6639
|
+
props: {},
|
|
6640
|
+
uniforms: {},
|
|
6641
|
+
vs: COLORS_GLSL,
|
|
6642
|
+
fs: COLORS_GLSL,
|
|
6643
|
+
source: COLORS_WGSL,
|
|
6644
|
+
uniformTypes: COLORS_UNIFORM_TYPES,
|
|
6645
|
+
defaultUniforms: COLORS_DEFAULT_UNIFORMS
|
|
6646
|
+
};
|
|
3414
6647
|
var floatColors = {
|
|
3415
6648
|
name: "floatColors",
|
|
3416
6649
|
props: {},
|
|
3417
6650
|
uniforms: {},
|
|
3418
|
-
vs:
|
|
3419
|
-
fs:
|
|
3420
|
-
source:
|
|
3421
|
-
uniformTypes:
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
6651
|
+
vs: FLOAT_COLORS_GLSL,
|
|
6652
|
+
fs: FLOAT_COLORS_GLSL,
|
|
6653
|
+
source: FLOAT_COLORS_WGSL,
|
|
6654
|
+
uniformTypes: COLORS_UNIFORM_TYPES,
|
|
6655
|
+
defaultUniforms: COLORS_DEFAULT_UNIFORMS
|
|
6656
|
+
};
|
|
6657
|
+
var storageColors = {
|
|
6658
|
+
name: "storageColors",
|
|
6659
|
+
props: {},
|
|
6660
|
+
uniforms: {},
|
|
6661
|
+
bindings: {},
|
|
6662
|
+
source: STORAGE_COLORS_WGSL,
|
|
6663
|
+
uniformTypes: STORAGE_COLORS_UNIFORM_TYPES,
|
|
6664
|
+
defaultUniforms: STORAGE_COLORS_DEFAULT_UNIFORMS,
|
|
6665
|
+
bindingLayout: [
|
|
6666
|
+
{ name: "storageColors", group: 0 },
|
|
6667
|
+
{ name: "storageColorsBuffer", group: 0 }
|
|
6668
|
+
],
|
|
6669
|
+
getUniforms(props = {}) {
|
|
6670
|
+
return {
|
|
6671
|
+
...getStorageColorsUniforms(props),
|
|
6672
|
+
...props.colorBuffer ? { storageColorsBuffer: props.colorBuffer } : {}
|
|
6673
|
+
};
|
|
3426
6674
|
}
|
|
3427
6675
|
};
|
|
3428
6676
|
|
|
@@ -3611,8 +6859,223 @@ function getUniforms(opts = {}, prevUniforms) {
|
|
|
3611
6859
|
return uniforms;
|
|
3612
6860
|
}
|
|
3613
6861
|
|
|
6862
|
+
// dist/modules/engine/filter/filter.js
|
|
6863
|
+
var filterShaderModule = {
|
|
6864
|
+
name: "filter",
|
|
6865
|
+
props: {},
|
|
6866
|
+
uniforms: {},
|
|
6867
|
+
bindingLayout: [{ name: "filter", group: 2 }],
|
|
6868
|
+
uniformTypes: {
|
|
6869
|
+
enabled: "i32",
|
|
6870
|
+
min: "f32",
|
|
6871
|
+
max: "f32"
|
|
6872
|
+
},
|
|
6873
|
+
defaultUniforms: {
|
|
6874
|
+
enabled: 1,
|
|
6875
|
+
min: 0,
|
|
6876
|
+
max: 1
|
|
6877
|
+
},
|
|
6878
|
+
vs: (
|
|
6879
|
+
/* glsl */
|
|
6880
|
+
`layout(std140) uniform filterUniforms {
|
|
6881
|
+
int enabled;
|
|
6882
|
+
float min;
|
|
6883
|
+
float max;
|
|
6884
|
+
} filterState;
|
|
6885
|
+
|
|
6886
|
+
bool filter_isVisible(float value) {
|
|
6887
|
+
return filterState.enabled == 0 || (value >= filterState.min && value <= filterState.max);
|
|
6888
|
+
}
|
|
6889
|
+
`
|
|
6890
|
+
),
|
|
6891
|
+
source: (
|
|
6892
|
+
/* wgsl */
|
|
6893
|
+
`struct FilterUniforms {
|
|
6894
|
+
enabled: i32,
|
|
6895
|
+
min: f32,
|
|
6896
|
+
max: f32,
|
|
6897
|
+
};
|
|
6898
|
+
|
|
6899
|
+
@group(2) @binding(auto) var<uniform> filterUniforms: FilterUniforms;
|
|
6900
|
+
|
|
6901
|
+
fn filter_isVisible(value: f32) -> bool {
|
|
6902
|
+
return filterUniforms.enabled == 0 ||
|
|
6903
|
+
(value >= filterUniforms.min && value <= filterUniforms.max);
|
|
6904
|
+
}
|
|
6905
|
+
`
|
|
6906
|
+
),
|
|
6907
|
+
getUniforms(props = {}) {
|
|
6908
|
+
const uniforms = {};
|
|
6909
|
+
if (props.enabled !== void 0) {
|
|
6910
|
+
uniforms.enabled = Number(props.enabled);
|
|
6911
|
+
}
|
|
6912
|
+
if (props.min !== void 0) {
|
|
6913
|
+
uniforms.min = props.min;
|
|
6914
|
+
}
|
|
6915
|
+
if (props.max !== void 0) {
|
|
6916
|
+
uniforms.max = props.max;
|
|
6917
|
+
}
|
|
6918
|
+
return uniforms;
|
|
6919
|
+
}
|
|
6920
|
+
};
|
|
6921
|
+
var filterShaderPlugin = {
|
|
6922
|
+
name: "filter",
|
|
6923
|
+
modules: [filterShaderModule],
|
|
6924
|
+
vertexInputs: {
|
|
6925
|
+
filterValues: "f32"
|
|
6926
|
+
},
|
|
6927
|
+
glsl: {
|
|
6928
|
+
injections: [
|
|
6929
|
+
{
|
|
6930
|
+
target: "vs:FILTER_POSITION",
|
|
6931
|
+
injection: `if (!filter_isVisible(filterValues)) {
|
|
6932
|
+
position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
6933
|
+
}`
|
|
6934
|
+
}
|
|
6935
|
+
]
|
|
6936
|
+
},
|
|
6937
|
+
wgsl: {
|
|
6938
|
+
injections: [
|
|
6939
|
+
{
|
|
6940
|
+
target: "vs:FILTER_POSITION",
|
|
6941
|
+
injection: `if (!filter_isVisible(filterValues)) {
|
|
6942
|
+
*position = vec4<f32>(2.0, 2.0, 2.0, 1.0);
|
|
6943
|
+
}`
|
|
6944
|
+
}
|
|
6945
|
+
]
|
|
6946
|
+
}
|
|
6947
|
+
};
|
|
6948
|
+
|
|
6949
|
+
// dist/modules/engine/clip/clip.js
|
|
6950
|
+
var CLIP_MODE_GEOMETRY = 0;
|
|
6951
|
+
var CLIP_MODE_INSTANCE = 1;
|
|
6952
|
+
var clipShaderModule = {
|
|
6953
|
+
name: "clip",
|
|
6954
|
+
props: {},
|
|
6955
|
+
uniforms: {},
|
|
6956
|
+
bindingLayout: [{ name: "clip", group: 2 }],
|
|
6957
|
+
uniformTypes: {
|
|
6958
|
+
enabled: "i32",
|
|
6959
|
+
mode: "i32",
|
|
6960
|
+
bounds: "vec4<f32>"
|
|
6961
|
+
},
|
|
6962
|
+
defaultUniforms: {
|
|
6963
|
+
enabled: 1,
|
|
6964
|
+
mode: CLIP_MODE_GEOMETRY,
|
|
6965
|
+
bounds: [0, 0, 1, 1]
|
|
6966
|
+
},
|
|
6967
|
+
vs: (
|
|
6968
|
+
/* glsl */
|
|
6969
|
+
`layout(std140) uniform clipUniforms {
|
|
6970
|
+
highp int enabled;
|
|
6971
|
+
highp int mode;
|
|
6972
|
+
highp vec4 bounds;
|
|
6973
|
+
} clipState;
|
|
6974
|
+
|
|
6975
|
+
bool clip_isInBounds(vec2 coordinates) {
|
|
6976
|
+
return coordinates.x >= clipState.bounds.x &&
|
|
6977
|
+
coordinates.y >= clipState.bounds.y &&
|
|
6978
|
+
coordinates.x < clipState.bounds.z &&
|
|
6979
|
+
coordinates.y < clipState.bounds.w;
|
|
6980
|
+
}
|
|
6981
|
+
`
|
|
6982
|
+
),
|
|
6983
|
+
fs: (
|
|
6984
|
+
/* glsl */
|
|
6985
|
+
`layout(std140) uniform clipUniforms {
|
|
6986
|
+
highp int enabled;
|
|
6987
|
+
highp int mode;
|
|
6988
|
+
highp vec4 bounds;
|
|
6989
|
+
} clipState;
|
|
6990
|
+
|
|
6991
|
+
bool clip_isInBounds(vec2 coordinates) {
|
|
6992
|
+
return coordinates.x >= clipState.bounds.x &&
|
|
6993
|
+
coordinates.y >= clipState.bounds.y &&
|
|
6994
|
+
coordinates.x < clipState.bounds.z &&
|
|
6995
|
+
coordinates.y < clipState.bounds.w;
|
|
6996
|
+
}
|
|
6997
|
+
`
|
|
6998
|
+
),
|
|
6999
|
+
source: (
|
|
7000
|
+
/* wgsl */
|
|
7001
|
+
`struct ClipUniforms {
|
|
7002
|
+
enabled: i32,
|
|
7003
|
+
mode: i32,
|
|
7004
|
+
bounds: vec4<f32>,
|
|
7005
|
+
};
|
|
7006
|
+
|
|
7007
|
+
@group(2) @binding(auto) var<uniform> clipUniforms: ClipUniforms;
|
|
7008
|
+
|
|
7009
|
+
fn clip_isInBounds(coordinates: vec2<f32>) -> bool {
|
|
7010
|
+
return coordinates.x >= clipUniforms.bounds.x &&
|
|
7011
|
+
coordinates.y >= clipUniforms.bounds.y &&
|
|
7012
|
+
coordinates.x < clipUniforms.bounds.z &&
|
|
7013
|
+
coordinates.y < clipUniforms.bounds.w;
|
|
7014
|
+
}
|
|
7015
|
+
`
|
|
7016
|
+
),
|
|
7017
|
+
getUniforms(props = {}) {
|
|
7018
|
+
const uniforms = {};
|
|
7019
|
+
if (props.enabled !== void 0) {
|
|
7020
|
+
uniforms.enabled = Number(props.enabled);
|
|
7021
|
+
}
|
|
7022
|
+
if (props.mode !== void 0) {
|
|
7023
|
+
uniforms.mode = props.mode === "instance" ? CLIP_MODE_INSTANCE : CLIP_MODE_GEOMETRY;
|
|
7024
|
+
}
|
|
7025
|
+
if (props.bounds !== void 0) {
|
|
7026
|
+
uniforms.bounds = props.bounds;
|
|
7027
|
+
}
|
|
7028
|
+
return uniforms;
|
|
7029
|
+
}
|
|
7030
|
+
};
|
|
7031
|
+
var clipShaderPlugin = {
|
|
7032
|
+
name: "clip",
|
|
7033
|
+
modules: [clipShaderModule],
|
|
7034
|
+
varyings: {
|
|
7035
|
+
clipCoordinates: { type: "vec2<f32>", interpolation: "smooth" }
|
|
7036
|
+
},
|
|
7037
|
+
glsl: {
|
|
7038
|
+
injections: [
|
|
7039
|
+
{
|
|
7040
|
+
target: "vs:CLIP_POSITION",
|
|
7041
|
+
injection: `clipCoordinates = geometryCoordinates;
|
|
7042
|
+
if (clipState.enabled != 0 && clipState.mode == ${CLIP_MODE_INSTANCE} &&
|
|
7043
|
+
!clip_isInBounds(instanceCoordinates)) {
|
|
7044
|
+
position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
7045
|
+
}`
|
|
7046
|
+
},
|
|
7047
|
+
{
|
|
7048
|
+
target: "fs:CLIP_COLOR",
|
|
7049
|
+
injection: `if (clipState.enabled != 0 && clipState.mode == ${CLIP_MODE_GEOMETRY} &&
|
|
7050
|
+
!clip_isInBounds(clipCoordinates)) {
|
|
7051
|
+
discard;
|
|
7052
|
+
}`
|
|
7053
|
+
}
|
|
7054
|
+
]
|
|
7055
|
+
},
|
|
7056
|
+
wgsl: {
|
|
7057
|
+
injections: [
|
|
7058
|
+
{
|
|
7059
|
+
target: "vs:CLIP_POSITION",
|
|
7060
|
+
injection: `clipCoordinates = geometryCoordinates;
|
|
7061
|
+
if (clipUniforms.enabled != 0 && clipUniforms.mode == ${CLIP_MODE_INSTANCE} &&
|
|
7062
|
+
!clip_isInBounds(instanceCoordinates)) {
|
|
7063
|
+
*position = vec4<f32>(2.0, 2.0, 2.0, 1.0);
|
|
7064
|
+
}`
|
|
7065
|
+
},
|
|
7066
|
+
{
|
|
7067
|
+
target: "fs:CLIP_COLOR",
|
|
7068
|
+
injection: `if (clipUniforms.enabled != 0 && clipUniforms.mode == ${CLIP_MODE_GEOMETRY} &&
|
|
7069
|
+
!clip_isInBounds(clipCoordinates)) {
|
|
7070
|
+
discard;
|
|
7071
|
+
}`
|
|
7072
|
+
}
|
|
7073
|
+
]
|
|
7074
|
+
}
|
|
7075
|
+
};
|
|
7076
|
+
|
|
3614
7077
|
// dist/modules/engine/skin/skin.js
|
|
3615
|
-
var
|
|
7078
|
+
var import_core5 = require("@math.gl/core");
|
|
3616
7079
|
var SKIN_MAX_JOINTS = 20;
|
|
3617
7080
|
var source2 = (
|
|
3618
7081
|
/* wgsl */
|
|
@@ -3674,7 +7137,7 @@ var skin = {
|
|
|
3674
7137
|
const countib = inverseBindMatrices.value.length / 16;
|
|
3675
7138
|
for (let i = 0; i < countib; i++) {
|
|
3676
7139
|
const slice = inverseBindMatrices.value.subarray(i * 16, i * 16 + 16);
|
|
3677
|
-
matsib.push(new
|
|
7140
|
+
matsib.push(new import_core5.Matrix4(Array.from(slice)));
|
|
3678
7141
|
}
|
|
3679
7142
|
const top = scenegraphsFromGLTF.gltfNodeIndexToNodeMap.get(skeleton);
|
|
3680
7143
|
const matrices = {};
|
|
@@ -3688,7 +7151,7 @@ var skin = {
|
|
|
3688
7151
|
break;
|
|
3689
7152
|
const worldMat = matrices[scenegraphsFromGLTF.gltfNodeIndexToNodeMap.get(nodeIndex).id];
|
|
3690
7153
|
const invBindMat = matsib[i];
|
|
3691
|
-
const Z = new
|
|
7154
|
+
const Z = new import_core5.Matrix4().copy(worldMat).multiplyRight(invBindMat);
|
|
3692
7155
|
const off = i * 16;
|
|
3693
7156
|
for (let j = 0; j < 16; j++) {
|
|
3694
7157
|
mats[off + j] = Z[j];
|
|
@@ -3704,7 +7167,7 @@ var skin = {
|
|
|
3704
7167
|
};
|
|
3705
7168
|
|
|
3706
7169
|
// dist/modules/lighting/lights/lighting.js
|
|
3707
|
-
var
|
|
7170
|
+
var import_core6 = require("@luma.gl/core");
|
|
3708
7171
|
|
|
3709
7172
|
// dist/modules/lighting/lights/lighting-glsl.js
|
|
3710
7173
|
var lightingUniformsGLSL = (
|
|
@@ -3987,7 +7450,7 @@ function getLightSourceUniforms({ useByteColors, ambientLight, pointLights = [],
|
|
|
3987
7450
|
directionalLightCount++;
|
|
3988
7451
|
}
|
|
3989
7452
|
if (pointLights.length + spotLights.length + directionalLights.length > MAX_LIGHTS) {
|
|
3990
|
-
|
|
7453
|
+
import_core6.log.warn(`MAX_LIGHTS exceeded, truncating to ${MAX_LIGHTS}`)();
|
|
3991
7454
|
}
|
|
3992
7455
|
return {
|
|
3993
7456
|
ambientColor: convertColor(ambientLight, useByteColors),
|
|
@@ -4604,6 +8067,631 @@ var phongMaterial = {
|
|
|
4604
8067
|
}
|
|
4605
8068
|
};
|
|
4606
8069
|
|
|
8070
|
+
// dist/modules/lighting/water-material/water-shaders-glsl.js
|
|
8071
|
+
var WATER_VS = (
|
|
8072
|
+
/* glsl */
|
|
8073
|
+
`layout(std140) uniform waterMaterialUniforms {
|
|
8074
|
+
uniform float time;
|
|
8075
|
+
uniform vec3 baseColor;
|
|
8076
|
+
uniform float opacity;
|
|
8077
|
+
uniform vec3 fresnelColor;
|
|
8078
|
+
uniform float fresnelPower;
|
|
8079
|
+
uniform float specularIntensity;
|
|
8080
|
+
uniform float normalStrength;
|
|
8081
|
+
uniform int mappingMode;
|
|
8082
|
+
uniform vec2 coordinateScale;
|
|
8083
|
+
uniform vec2 coordinateOffset;
|
|
8084
|
+
uniform vec2 waveADirection;
|
|
8085
|
+
uniform float waveASpeed;
|
|
8086
|
+
uniform float waveAFrequency;
|
|
8087
|
+
uniform float waveAAmplitude;
|
|
8088
|
+
uniform vec2 waveBDirection;
|
|
8089
|
+
uniform float waveBSpeed;
|
|
8090
|
+
uniform float waveBFrequency;
|
|
8091
|
+
uniform float waveBAmplitude;
|
|
8092
|
+
} waterMaterial;
|
|
8093
|
+
`
|
|
8094
|
+
);
|
|
8095
|
+
var WATER_FS = (
|
|
8096
|
+
/* glsl */
|
|
8097
|
+
`layout(std140) uniform waterMaterialUniforms {
|
|
8098
|
+
uniform float time;
|
|
8099
|
+
uniform vec3 baseColor;
|
|
8100
|
+
uniform float opacity;
|
|
8101
|
+
uniform vec3 fresnelColor;
|
|
8102
|
+
uniform float fresnelPower;
|
|
8103
|
+
uniform float specularIntensity;
|
|
8104
|
+
uniform float normalStrength;
|
|
8105
|
+
uniform int mappingMode;
|
|
8106
|
+
uniform vec2 coordinateScale;
|
|
8107
|
+
uniform vec2 coordinateOffset;
|
|
8108
|
+
uniform vec2 waveADirection;
|
|
8109
|
+
uniform float waveASpeed;
|
|
8110
|
+
uniform float waveAFrequency;
|
|
8111
|
+
uniform float waveAAmplitude;
|
|
8112
|
+
uniform vec2 waveBDirection;
|
|
8113
|
+
uniform float waveBSpeed;
|
|
8114
|
+
uniform float waveBFrequency;
|
|
8115
|
+
uniform float waveBAmplitude;
|
|
8116
|
+
} waterMaterial;
|
|
8117
|
+
|
|
8118
|
+
vec2 water_getDirection(vec2 direction) {
|
|
8119
|
+
float directionLength = length(direction);
|
|
8120
|
+
return directionLength > 0.0 ? direction / directionLength : vec2(1.0, 0.0);
|
|
8121
|
+
}
|
|
8122
|
+
|
|
8123
|
+
vec2 water_getCoordinates(vec3 position_worldspace, vec3 position_objectspace, vec2 uv) {
|
|
8124
|
+
vec2 baseCoordinates = uv;
|
|
8125
|
+
if (waterMaterial.mappingMode == 1) {
|
|
8126
|
+
baseCoordinates = position_worldspace.xz;
|
|
8127
|
+
} else if (waterMaterial.mappingMode == 2) {
|
|
8128
|
+
vec3 globeDirection = normalize(position_objectspace);
|
|
8129
|
+
float longitude = atan(globeDirection.x, globeDirection.z);
|
|
8130
|
+
float latitude = asin(clamp(globeDirection.y, -1.0, 1.0));
|
|
8131
|
+
baseCoordinates = vec2(longitude, latitude);
|
|
8132
|
+
}
|
|
8133
|
+
return baseCoordinates * waterMaterial.coordinateScale + waterMaterial.coordinateOffset;
|
|
8134
|
+
}
|
|
8135
|
+
|
|
8136
|
+
vec2 water_getWaveGradient(
|
|
8137
|
+
vec2 coordinates,
|
|
8138
|
+
vec2 direction,
|
|
8139
|
+
float speed,
|
|
8140
|
+
float frequency,
|
|
8141
|
+
float amplitude
|
|
8142
|
+
) {
|
|
8143
|
+
vec2 normalizedDirection = water_getDirection(direction);
|
|
8144
|
+
float phase = dot(coordinates * frequency, normalizedDirection) + waterMaterial.time * speed;
|
|
8145
|
+
return cos(phase) * normalizedDirection * frequency * amplitude;
|
|
8146
|
+
}
|
|
8147
|
+
|
|
8148
|
+
vec3 water_getTangent(vec3 normal_worldspace) {
|
|
8149
|
+
vec3 referenceAxis = abs(normal_worldspace.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
|
|
8150
|
+
return normalize(cross(referenceAxis, normal_worldspace));
|
|
8151
|
+
}
|
|
8152
|
+
|
|
8153
|
+
vec3 water_getNormal(
|
|
8154
|
+
vec3 position_worldspace,
|
|
8155
|
+
vec3 position_objectspace,
|
|
8156
|
+
vec3 normal_worldspace,
|
|
8157
|
+
vec2 uv
|
|
8158
|
+
) {
|
|
8159
|
+
vec2 coordinates = water_getCoordinates(position_worldspace, position_objectspace, uv);
|
|
8160
|
+
vec2 gradient =
|
|
8161
|
+
water_getWaveGradient(
|
|
8162
|
+
coordinates,
|
|
8163
|
+
waterMaterial.waveADirection,
|
|
8164
|
+
waterMaterial.waveASpeed,
|
|
8165
|
+
waterMaterial.waveAFrequency,
|
|
8166
|
+
waterMaterial.waveAAmplitude
|
|
8167
|
+
) +
|
|
8168
|
+
water_getWaveGradient(
|
|
8169
|
+
coordinates,
|
|
8170
|
+
waterMaterial.waveBDirection,
|
|
8171
|
+
waterMaterial.waveBSpeed,
|
|
8172
|
+
waterMaterial.waveBFrequency,
|
|
8173
|
+
waterMaterial.waveBAmplitude
|
|
8174
|
+
);
|
|
8175
|
+
|
|
8176
|
+
vec3 tangent = water_getTangent(normal_worldspace);
|
|
8177
|
+
vec3 bitangent = normalize(cross(normal_worldspace, tangent));
|
|
8178
|
+
vec3 perturbation =
|
|
8179
|
+
waterMaterial.normalStrength * (gradient.x * tangent + gradient.y * bitangent);
|
|
8180
|
+
|
|
8181
|
+
return normalize(normal_worldspace + perturbation);
|
|
8182
|
+
}
|
|
8183
|
+
|
|
8184
|
+
vec3 water_getSpecularContribution(
|
|
8185
|
+
vec3 light_direction,
|
|
8186
|
+
vec3 view_direction,
|
|
8187
|
+
vec3 normal_worldspace,
|
|
8188
|
+
vec3 light_color,
|
|
8189
|
+
float fresnel
|
|
8190
|
+
) {
|
|
8191
|
+
vec3 halfway_direction = normalize(light_direction + view_direction);
|
|
8192
|
+
float specular =
|
|
8193
|
+
pow(max(dot(normal_worldspace, halfway_direction), 0.0), 72.0) *
|
|
8194
|
+
waterMaterial.specularIntensity *
|
|
8195
|
+
(0.25 + 0.75 * fresnel);
|
|
8196
|
+
|
|
8197
|
+
return waterMaterial.fresnelColor * light_color * specular;
|
|
8198
|
+
}
|
|
8199
|
+
|
|
8200
|
+
vec4 water_getColorMapped(
|
|
8201
|
+
vec3 cameraPosition,
|
|
8202
|
+
vec3 position_worldspace,
|
|
8203
|
+
vec3 position_objectspace,
|
|
8204
|
+
vec3 normal_worldspace,
|
|
8205
|
+
vec2 uv
|
|
8206
|
+
) {
|
|
8207
|
+
vec3 waterNormal = water_getNormal(
|
|
8208
|
+
position_worldspace,
|
|
8209
|
+
position_objectspace,
|
|
8210
|
+
normalize(normal_worldspace),
|
|
8211
|
+
uv
|
|
8212
|
+
);
|
|
8213
|
+
vec3 viewDirection = normalize(cameraPosition - position_worldspace);
|
|
8214
|
+
float fresnel =
|
|
8215
|
+
pow(
|
|
8216
|
+
1.0 - max(dot(viewDirection, waterNormal), 0.0),
|
|
8217
|
+
max(waterMaterial.fresnelPower, 0.0001)
|
|
8218
|
+
);
|
|
8219
|
+
vec3 surfaceColor = mix(
|
|
8220
|
+
waterMaterial.baseColor,
|
|
8221
|
+
waterMaterial.fresnelColor,
|
|
8222
|
+
clamp(fresnel * 0.6, 0.0, 1.0)
|
|
8223
|
+
);
|
|
8224
|
+
|
|
8225
|
+
if (lighting.enabled == 0) {
|
|
8226
|
+
return vec4(surfaceColor, waterMaterial.opacity);
|
|
8227
|
+
}
|
|
8228
|
+
|
|
8229
|
+
vec3 lightColor = surfaceColor * (0.15 + 0.85 * lighting.ambientColor);
|
|
8230
|
+
|
|
8231
|
+
for (int i = 0; i < lighting.pointLightCount; i++) {
|
|
8232
|
+
PointLight pointLight = lighting_getPointLight(i);
|
|
8233
|
+
vec3 lightPosition = pointLight.position;
|
|
8234
|
+
vec3 lightDirection = normalize(lightPosition - position_worldspace);
|
|
8235
|
+
float attenuation =
|
|
8236
|
+
getPointLightAttenuation(pointLight, distance(lightPosition, position_worldspace));
|
|
8237
|
+
vec3 incidentLight = pointLight.color / attenuation;
|
|
8238
|
+
float diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
8239
|
+
|
|
8240
|
+
lightColor += surfaceColor * incidentLight * diffuse;
|
|
8241
|
+
lightColor += water_getSpecularContribution(
|
|
8242
|
+
lightDirection,
|
|
8243
|
+
viewDirection,
|
|
8244
|
+
waterNormal,
|
|
8245
|
+
incidentLight,
|
|
8246
|
+
fresnel
|
|
8247
|
+
);
|
|
8248
|
+
}
|
|
8249
|
+
|
|
8250
|
+
for (int i = 0; i < lighting.spotLightCount; i++) {
|
|
8251
|
+
SpotLight spotLight = lighting_getSpotLight(i);
|
|
8252
|
+
vec3 lightPosition = spotLight.position;
|
|
8253
|
+
vec3 lightDirection = normalize(lightPosition - position_worldspace);
|
|
8254
|
+
float attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
|
|
8255
|
+
vec3 incidentLight = spotLight.color / attenuation;
|
|
8256
|
+
float diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
8257
|
+
|
|
8258
|
+
lightColor += surfaceColor * incidentLight * diffuse;
|
|
8259
|
+
lightColor += water_getSpecularContribution(
|
|
8260
|
+
lightDirection,
|
|
8261
|
+
viewDirection,
|
|
8262
|
+
waterNormal,
|
|
8263
|
+
incidentLight,
|
|
8264
|
+
fresnel
|
|
8265
|
+
);
|
|
8266
|
+
}
|
|
8267
|
+
|
|
8268
|
+
for (int i = 0; i < lighting.directionalLightCount; i++) {
|
|
8269
|
+
DirectionalLight directionalLight = lighting_getDirectionalLight(i);
|
|
8270
|
+
vec3 lightDirection = normalize(-directionalLight.direction);
|
|
8271
|
+
float diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
8272
|
+
|
|
8273
|
+
lightColor += surfaceColor * directionalLight.color * diffuse;
|
|
8274
|
+
lightColor += water_getSpecularContribution(
|
|
8275
|
+
lightDirection,
|
|
8276
|
+
viewDirection,
|
|
8277
|
+
waterNormal,
|
|
8278
|
+
directionalLight.color,
|
|
8279
|
+
fresnel
|
|
8280
|
+
);
|
|
8281
|
+
}
|
|
8282
|
+
|
|
8283
|
+
lightColor = mix(lightColor, waterMaterial.fresnelColor, clamp(fresnel, 0.0, 1.0) * 0.35);
|
|
8284
|
+
return vec4(lightColor, waterMaterial.opacity);
|
|
8285
|
+
}
|
|
8286
|
+
|
|
8287
|
+
vec4 water_getColor(
|
|
8288
|
+
vec3 cameraPosition,
|
|
8289
|
+
vec3 position_worldspace,
|
|
8290
|
+
vec3 normal_worldspace,
|
|
8291
|
+
vec2 uv
|
|
8292
|
+
) {
|
|
8293
|
+
return water_getColorMapped(
|
|
8294
|
+
cameraPosition,
|
|
8295
|
+
position_worldspace,
|
|
8296
|
+
position_worldspace,
|
|
8297
|
+
normal_worldspace,
|
|
8298
|
+
uv
|
|
8299
|
+
);
|
|
8300
|
+
}
|
|
8301
|
+
`
|
|
8302
|
+
);
|
|
8303
|
+
|
|
8304
|
+
// dist/modules/lighting/water-material/water-shaders-wgsl.js
|
|
8305
|
+
var WATER_WGSL = (
|
|
8306
|
+
/* wgsl */
|
|
8307
|
+
`struct waterMaterialUniforms {
|
|
8308
|
+
time: f32,
|
|
8309
|
+
baseColor: vec3<f32>,
|
|
8310
|
+
opacity: f32,
|
|
8311
|
+
fresnelColor: vec3<f32>,
|
|
8312
|
+
fresnelPower: f32,
|
|
8313
|
+
specularIntensity: f32,
|
|
8314
|
+
normalStrength: f32,
|
|
8315
|
+
mappingMode: i32,
|
|
8316
|
+
coordinateScale: vec2<f32>,
|
|
8317
|
+
coordinateOffset: vec2<f32>,
|
|
8318
|
+
waveADirection: vec2<f32>,
|
|
8319
|
+
waveASpeed: f32,
|
|
8320
|
+
waveAFrequency: f32,
|
|
8321
|
+
waveAAmplitude: f32,
|
|
8322
|
+
waveBDirection: vec2<f32>,
|
|
8323
|
+
waveBSpeed: f32,
|
|
8324
|
+
waveBFrequency: f32,
|
|
8325
|
+
waveBAmplitude: f32,
|
|
8326
|
+
};
|
|
8327
|
+
|
|
8328
|
+
@group(3) @binding(auto) var<uniform> waterMaterial : waterMaterialUniforms;
|
|
8329
|
+
|
|
8330
|
+
fn water_getDirection(direction: vec2<f32>) -> vec2<f32> {
|
|
8331
|
+
let directionLength = length(direction);
|
|
8332
|
+
if (directionLength > 0.0) {
|
|
8333
|
+
return direction / directionLength;
|
|
8334
|
+
}
|
|
8335
|
+
|
|
8336
|
+
return vec2<f32>(1.0, 0.0);
|
|
8337
|
+
}
|
|
8338
|
+
|
|
8339
|
+
fn water_getCoordinates(
|
|
8340
|
+
position_worldspace: vec3<f32>,
|
|
8341
|
+
position_objectspace: vec3<f32>,
|
|
8342
|
+
uv: vec2<f32>
|
|
8343
|
+
) -> vec2<f32> {
|
|
8344
|
+
var baseCoordinates = uv;
|
|
8345
|
+
if (waterMaterial.mappingMode == 1) {
|
|
8346
|
+
baseCoordinates = position_worldspace.xz;
|
|
8347
|
+
} else if (waterMaterial.mappingMode == 2) {
|
|
8348
|
+
let globeDirection = normalize(position_objectspace);
|
|
8349
|
+
let longitude = atan2(globeDirection.x, globeDirection.z);
|
|
8350
|
+
let latitude = asin(clamp(globeDirection.y, -1.0, 1.0));
|
|
8351
|
+
baseCoordinates = vec2<f32>(longitude, latitude);
|
|
8352
|
+
}
|
|
8353
|
+
|
|
8354
|
+
return baseCoordinates * waterMaterial.coordinateScale + waterMaterial.coordinateOffset;
|
|
8355
|
+
}
|
|
8356
|
+
|
|
8357
|
+
fn water_getWaveGradient(
|
|
8358
|
+
coordinates: vec2<f32>,
|
|
8359
|
+
direction: vec2<f32>,
|
|
8360
|
+
speed: f32,
|
|
8361
|
+
frequency: f32,
|
|
8362
|
+
amplitude: f32
|
|
8363
|
+
) -> vec2<f32> {
|
|
8364
|
+
let normalizedDirection = water_getDirection(direction);
|
|
8365
|
+
let phase = dot(coordinates * frequency, normalizedDirection) + waterMaterial.time * speed;
|
|
8366
|
+
return cos(phase) * normalizedDirection * frequency * amplitude;
|
|
8367
|
+
}
|
|
8368
|
+
|
|
8369
|
+
fn water_getTangent(normal_worldspace: vec3<f32>) -> vec3<f32> {
|
|
8370
|
+
var referenceAxis = vec3<f32>(0.0, 0.0, 1.0);
|
|
8371
|
+
if (abs(normal_worldspace.z) >= 0.999) {
|
|
8372
|
+
referenceAxis = vec3<f32>(0.0, 1.0, 0.0);
|
|
8373
|
+
}
|
|
8374
|
+
|
|
8375
|
+
return normalize(cross(referenceAxis, normal_worldspace));
|
|
8376
|
+
}
|
|
8377
|
+
|
|
8378
|
+
fn water_getNormal(
|
|
8379
|
+
position_worldspace: vec3<f32>,
|
|
8380
|
+
position_objectspace: vec3<f32>,
|
|
8381
|
+
normal_worldspace: vec3<f32>,
|
|
8382
|
+
uv: vec2<f32>
|
|
8383
|
+
) -> vec3<f32> {
|
|
8384
|
+
let coordinates = water_getCoordinates(position_worldspace, position_objectspace, uv);
|
|
8385
|
+
let gradient =
|
|
8386
|
+
water_getWaveGradient(
|
|
8387
|
+
coordinates,
|
|
8388
|
+
waterMaterial.waveADirection,
|
|
8389
|
+
waterMaterial.waveASpeed,
|
|
8390
|
+
waterMaterial.waveAFrequency,
|
|
8391
|
+
waterMaterial.waveAAmplitude
|
|
8392
|
+
) +
|
|
8393
|
+
water_getWaveGradient(
|
|
8394
|
+
coordinates,
|
|
8395
|
+
waterMaterial.waveBDirection,
|
|
8396
|
+
waterMaterial.waveBSpeed,
|
|
8397
|
+
waterMaterial.waveBFrequency,
|
|
8398
|
+
waterMaterial.waveBAmplitude
|
|
8399
|
+
);
|
|
8400
|
+
let tangent = water_getTangent(normal_worldspace);
|
|
8401
|
+
let bitangent = normalize(cross(normal_worldspace, tangent));
|
|
8402
|
+
let perturbation =
|
|
8403
|
+
waterMaterial.normalStrength * (gradient.x * tangent + gradient.y * bitangent);
|
|
8404
|
+
|
|
8405
|
+
return normalize(normal_worldspace + perturbation);
|
|
8406
|
+
}
|
|
8407
|
+
|
|
8408
|
+
fn water_getSpecularContribution(
|
|
8409
|
+
light_direction: vec3<f32>,
|
|
8410
|
+
view_direction: vec3<f32>,
|
|
8411
|
+
normal_worldspace: vec3<f32>,
|
|
8412
|
+
light_color: vec3<f32>,
|
|
8413
|
+
fresnel: f32
|
|
8414
|
+
) -> vec3<f32> {
|
|
8415
|
+
let halfwayDirection = normalize(light_direction + view_direction);
|
|
8416
|
+
let specular =
|
|
8417
|
+
pow(max(dot(normal_worldspace, halfwayDirection), 0.0), 72.0) *
|
|
8418
|
+
waterMaterial.specularIntensity *
|
|
8419
|
+
(0.25 + 0.75 * fresnel);
|
|
8420
|
+
|
|
8421
|
+
return waterMaterial.fresnelColor * light_color * specular;
|
|
8422
|
+
}
|
|
8423
|
+
|
|
8424
|
+
fn water_getColorMapped(
|
|
8425
|
+
cameraPosition: vec3<f32>,
|
|
8426
|
+
position_worldspace: vec3<f32>,
|
|
8427
|
+
position_objectspace: vec3<f32>,
|
|
8428
|
+
normal_worldspace: vec3<f32>,
|
|
8429
|
+
uv: vec2<f32>
|
|
8430
|
+
) -> vec4<f32> {
|
|
8431
|
+
let waterNormal = water_getNormal(
|
|
8432
|
+
position_worldspace,
|
|
8433
|
+
position_objectspace,
|
|
8434
|
+
normalize(normal_worldspace),
|
|
8435
|
+
uv
|
|
8436
|
+
);
|
|
8437
|
+
let viewDirection = normalize(cameraPosition - position_worldspace);
|
|
8438
|
+
let fresnel =
|
|
8439
|
+
pow(
|
|
8440
|
+
1.0 - max(dot(viewDirection, waterNormal), 0.0),
|
|
8441
|
+
max(waterMaterial.fresnelPower, 0.0001)
|
|
8442
|
+
);
|
|
8443
|
+
let surfaceColor = mix(
|
|
8444
|
+
waterMaterial.baseColor,
|
|
8445
|
+
waterMaterial.fresnelColor,
|
|
8446
|
+
clamp(fresnel * 0.6, 0.0, 1.0)
|
|
8447
|
+
);
|
|
8448
|
+
|
|
8449
|
+
if (lighting.enabled == 0) {
|
|
8450
|
+
return vec4<f32>(surfaceColor, waterMaterial.opacity);
|
|
8451
|
+
}
|
|
8452
|
+
|
|
8453
|
+
var lightColor = surfaceColor * (0.15 + 0.85 * lighting.ambientColor);
|
|
8454
|
+
|
|
8455
|
+
for (var i: i32 = 0; i < lighting.pointLightCount; i++) {
|
|
8456
|
+
let pointLight = lighting_getPointLight(i);
|
|
8457
|
+
let lightPosition = pointLight.position;
|
|
8458
|
+
let lightDirection = normalize(lightPosition - position_worldspace);
|
|
8459
|
+
let attenuation = getPointLightAttenuation(
|
|
8460
|
+
pointLight,
|
|
8461
|
+
distance(lightPosition, position_worldspace)
|
|
8462
|
+
);
|
|
8463
|
+
let incidentLight = pointLight.color / attenuation;
|
|
8464
|
+
let diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
8465
|
+
|
|
8466
|
+
lightColor += surfaceColor * incidentLight * diffuse;
|
|
8467
|
+
lightColor += water_getSpecularContribution(
|
|
8468
|
+
lightDirection,
|
|
8469
|
+
viewDirection,
|
|
8470
|
+
waterNormal,
|
|
8471
|
+
incidentLight,
|
|
8472
|
+
fresnel
|
|
8473
|
+
);
|
|
8474
|
+
}
|
|
8475
|
+
|
|
8476
|
+
for (var i: i32 = 0; i < lighting.spotLightCount; i++) {
|
|
8477
|
+
let spotLight = lighting_getSpotLight(i);
|
|
8478
|
+
let lightPosition = spotLight.position;
|
|
8479
|
+
let lightDirection = normalize(lightPosition - position_worldspace);
|
|
8480
|
+
let attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
|
|
8481
|
+
let incidentLight = spotLight.color / attenuation;
|
|
8482
|
+
let diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
8483
|
+
|
|
8484
|
+
lightColor += surfaceColor * incidentLight * diffuse;
|
|
8485
|
+
lightColor += water_getSpecularContribution(
|
|
8486
|
+
lightDirection,
|
|
8487
|
+
viewDirection,
|
|
8488
|
+
waterNormal,
|
|
8489
|
+
incidentLight,
|
|
8490
|
+
fresnel
|
|
8491
|
+
);
|
|
8492
|
+
}
|
|
8493
|
+
|
|
8494
|
+
for (var i: i32 = 0; i < lighting.directionalLightCount; i++) {
|
|
8495
|
+
let directionalLight = lighting_getDirectionalLight(i);
|
|
8496
|
+
let lightDirection = normalize(-directionalLight.direction);
|
|
8497
|
+
let diffuse = max(dot(waterNormal, lightDirection), 0.0);
|
|
8498
|
+
|
|
8499
|
+
lightColor += surfaceColor * directionalLight.color * diffuse;
|
|
8500
|
+
lightColor += water_getSpecularContribution(
|
|
8501
|
+
lightDirection,
|
|
8502
|
+
viewDirection,
|
|
8503
|
+
waterNormal,
|
|
8504
|
+
directionalLight.color,
|
|
8505
|
+
fresnel
|
|
8506
|
+
);
|
|
8507
|
+
}
|
|
8508
|
+
|
|
8509
|
+
lightColor = mix(
|
|
8510
|
+
lightColor,
|
|
8511
|
+
waterMaterial.fresnelColor,
|
|
8512
|
+
clamp(fresnel, 0.0, 1.0) * 0.35
|
|
8513
|
+
);
|
|
8514
|
+
return vec4<f32>(lightColor, waterMaterial.opacity);
|
|
8515
|
+
}
|
|
8516
|
+
|
|
8517
|
+
fn water_getColor(
|
|
8518
|
+
cameraPosition: vec3<f32>,
|
|
8519
|
+
position_worldspace: vec3<f32>,
|
|
8520
|
+
normal_worldspace: vec3<f32>,
|
|
8521
|
+
uv: vec2<f32>
|
|
8522
|
+
) -> vec4<f32> {
|
|
8523
|
+
return water_getColorMapped(
|
|
8524
|
+
cameraPosition,
|
|
8525
|
+
position_worldspace,
|
|
8526
|
+
position_worldspace,
|
|
8527
|
+
normal_worldspace,
|
|
8528
|
+
uv
|
|
8529
|
+
);
|
|
8530
|
+
}
|
|
8531
|
+
`
|
|
8532
|
+
);
|
|
8533
|
+
|
|
8534
|
+
// dist/modules/lighting/water-material/water-material.js
|
|
8535
|
+
var DEFAULT_WATER_MATERIAL_UNIFORMS = {
|
|
8536
|
+
time: 0,
|
|
8537
|
+
baseColor: [0.04, 0.18, 0.31],
|
|
8538
|
+
opacity: 0.82,
|
|
8539
|
+
fresnelColor: [0.86, 0.95, 1],
|
|
8540
|
+
fresnelPower: 5,
|
|
8541
|
+
specularIntensity: 1.4,
|
|
8542
|
+
normalStrength: 0.35,
|
|
8543
|
+
mappingMode: 0,
|
|
8544
|
+
coordinateScale: [1, 1],
|
|
8545
|
+
coordinateOffset: [0, 0],
|
|
8546
|
+
waveADirection: [0.9805806756909201, 0.19611613513818402],
|
|
8547
|
+
waveASpeed: 0.6,
|
|
8548
|
+
waveAFrequency: 4,
|
|
8549
|
+
waveAAmplitude: 0.08,
|
|
8550
|
+
waveBDirection: [0.09950371902099893, 0.9950371902099893],
|
|
8551
|
+
waveBSpeed: -0.45,
|
|
8552
|
+
waveBFrequency: 7,
|
|
8553
|
+
waveBAmplitude: 0.04
|
|
8554
|
+
};
|
|
8555
|
+
var waterMaterial = {
|
|
8556
|
+
name: "waterMaterial",
|
|
8557
|
+
firstBindingSlot: 0,
|
|
8558
|
+
bindingLayout: [{ name: "waterMaterial", group: 3 }],
|
|
8559
|
+
dependencies: [lighting],
|
|
8560
|
+
source: WATER_WGSL,
|
|
8561
|
+
vs: WATER_VS,
|
|
8562
|
+
fs: WATER_FS,
|
|
8563
|
+
defines: {
|
|
8564
|
+
LIGHTING_FRAGMENT: true
|
|
8565
|
+
},
|
|
8566
|
+
uniformTypes: {
|
|
8567
|
+
time: "f32",
|
|
8568
|
+
baseColor: "vec3<f32>",
|
|
8569
|
+
opacity: "f32",
|
|
8570
|
+
fresnelColor: "vec3<f32>",
|
|
8571
|
+
fresnelPower: "f32",
|
|
8572
|
+
specularIntensity: "f32",
|
|
8573
|
+
normalStrength: "f32",
|
|
8574
|
+
mappingMode: "i32",
|
|
8575
|
+
coordinateScale: "vec2<f32>",
|
|
8576
|
+
coordinateOffset: "vec2<f32>",
|
|
8577
|
+
waveADirection: "vec2<f32>",
|
|
8578
|
+
waveASpeed: "f32",
|
|
8579
|
+
waveAFrequency: "f32",
|
|
8580
|
+
waveAAmplitude: "f32",
|
|
8581
|
+
waveBDirection: "vec2<f32>",
|
|
8582
|
+
waveBSpeed: "f32",
|
|
8583
|
+
waveBFrequency: "f32",
|
|
8584
|
+
waveBAmplitude: "f32"
|
|
8585
|
+
},
|
|
8586
|
+
defaultUniforms: DEFAULT_WATER_MATERIAL_UNIFORMS,
|
|
8587
|
+
getUniforms(props, previousUniforms = DEFAULT_WATER_MATERIAL_UNIFORMS) {
|
|
8588
|
+
const { mapping, ...uniformProps } = props || {};
|
|
8589
|
+
const uniforms = mergeWaterMaterialUniforms(previousUniforms);
|
|
8590
|
+
if (uniformProps.time !== void 0) {
|
|
8591
|
+
uniforms.time = uniformProps.time;
|
|
8592
|
+
}
|
|
8593
|
+
if (uniformProps.opacity !== void 0) {
|
|
8594
|
+
uniforms.opacity = uniformProps.opacity;
|
|
8595
|
+
}
|
|
8596
|
+
if (uniformProps.fresnelPower !== void 0) {
|
|
8597
|
+
uniforms.fresnelPower = uniformProps.fresnelPower;
|
|
8598
|
+
}
|
|
8599
|
+
if (uniformProps.specularIntensity !== void 0) {
|
|
8600
|
+
uniforms.specularIntensity = uniformProps.specularIntensity;
|
|
8601
|
+
}
|
|
8602
|
+
if (uniformProps.normalStrength !== void 0) {
|
|
8603
|
+
uniforms.normalStrength = uniformProps.normalStrength;
|
|
8604
|
+
}
|
|
8605
|
+
if (uniformProps.coordinateScale !== void 0) {
|
|
8606
|
+
uniforms.coordinateScale = [
|
|
8607
|
+
Number(uniformProps.coordinateScale[0]),
|
|
8608
|
+
Number(uniformProps.coordinateScale[1])
|
|
8609
|
+
];
|
|
8610
|
+
}
|
|
8611
|
+
if (uniformProps.coordinateOffset !== void 0) {
|
|
8612
|
+
uniforms.coordinateOffset = [
|
|
8613
|
+
Number(uniformProps.coordinateOffset[0]),
|
|
8614
|
+
Number(uniformProps.coordinateOffset[1])
|
|
8615
|
+
];
|
|
8616
|
+
}
|
|
8617
|
+
if (uniformProps.waveASpeed !== void 0) {
|
|
8618
|
+
uniforms.waveASpeed = uniformProps.waveASpeed;
|
|
8619
|
+
}
|
|
8620
|
+
if (uniformProps.waveAFrequency !== void 0) {
|
|
8621
|
+
uniforms.waveAFrequency = uniformProps.waveAFrequency;
|
|
8622
|
+
}
|
|
8623
|
+
if (uniformProps.waveAAmplitude !== void 0) {
|
|
8624
|
+
uniforms.waveAAmplitude = uniformProps.waveAAmplitude;
|
|
8625
|
+
}
|
|
8626
|
+
if (uniformProps.waveBSpeed !== void 0) {
|
|
8627
|
+
uniforms.waveBSpeed = uniformProps.waveBSpeed;
|
|
8628
|
+
}
|
|
8629
|
+
if (uniformProps.waveBFrequency !== void 0) {
|
|
8630
|
+
uniforms.waveBFrequency = uniformProps.waveBFrequency;
|
|
8631
|
+
}
|
|
8632
|
+
if (uniformProps.waveBAmplitude !== void 0) {
|
|
8633
|
+
uniforms.waveBAmplitude = uniformProps.waveBAmplitude;
|
|
8634
|
+
}
|
|
8635
|
+
if (uniformProps.baseColor) {
|
|
8636
|
+
uniforms.baseColor = normalizeColor3(uniformProps.baseColor);
|
|
8637
|
+
}
|
|
8638
|
+
if (uniformProps.fresnelColor) {
|
|
8639
|
+
uniforms.fresnelColor = normalizeColor3(uniformProps.fresnelColor);
|
|
8640
|
+
}
|
|
8641
|
+
if (uniformProps.waveADirection) {
|
|
8642
|
+
uniforms.waveADirection = normalizeDirection2(uniformProps.waveADirection);
|
|
8643
|
+
}
|
|
8644
|
+
if (uniformProps.waveBDirection) {
|
|
8645
|
+
uniforms.waveBDirection = normalizeDirection2(uniformProps.waveBDirection);
|
|
8646
|
+
}
|
|
8647
|
+
if (mapping !== void 0) {
|
|
8648
|
+
uniforms.mappingMode = mapping === "world" ? 1 : mapping === "object" ? 2 : 0;
|
|
8649
|
+
}
|
|
8650
|
+
return uniforms;
|
|
8651
|
+
}
|
|
8652
|
+
};
|
|
8653
|
+
function mergeWaterMaterialUniforms(previousUniforms) {
|
|
8654
|
+
return {
|
|
8655
|
+
time: previousUniforms.time ?? DEFAULT_WATER_MATERIAL_UNIFORMS.time,
|
|
8656
|
+
baseColor: previousUniforms.baseColor ? normalizeColor3(previousUniforms.baseColor) : DEFAULT_WATER_MATERIAL_UNIFORMS.baseColor,
|
|
8657
|
+
opacity: previousUniforms.opacity ?? DEFAULT_WATER_MATERIAL_UNIFORMS.opacity,
|
|
8658
|
+
fresnelColor: previousUniforms.fresnelColor ? normalizeColor3(previousUniforms.fresnelColor) : DEFAULT_WATER_MATERIAL_UNIFORMS.fresnelColor,
|
|
8659
|
+
fresnelPower: previousUniforms.fresnelPower ?? DEFAULT_WATER_MATERIAL_UNIFORMS.fresnelPower,
|
|
8660
|
+
specularIntensity: previousUniforms.specularIntensity ?? DEFAULT_WATER_MATERIAL_UNIFORMS.specularIntensity,
|
|
8661
|
+
normalStrength: previousUniforms.normalStrength ?? DEFAULT_WATER_MATERIAL_UNIFORMS.normalStrength,
|
|
8662
|
+
mappingMode: previousUniforms.mappingMode ?? DEFAULT_WATER_MATERIAL_UNIFORMS.mappingMode,
|
|
8663
|
+
coordinateScale: previousUniforms.coordinateScale ? [Number(previousUniforms.coordinateScale[0]), Number(previousUniforms.coordinateScale[1])] : DEFAULT_WATER_MATERIAL_UNIFORMS.coordinateScale,
|
|
8664
|
+
coordinateOffset: previousUniforms.coordinateOffset ? [Number(previousUniforms.coordinateOffset[0]), Number(previousUniforms.coordinateOffset[1])] : DEFAULT_WATER_MATERIAL_UNIFORMS.coordinateOffset,
|
|
8665
|
+
waveADirection: previousUniforms.waveADirection ? normalizeDirection2(previousUniforms.waveADirection) : DEFAULT_WATER_MATERIAL_UNIFORMS.waveADirection,
|
|
8666
|
+
waveASpeed: previousUniforms.waveASpeed ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveASpeed,
|
|
8667
|
+
waveAFrequency: previousUniforms.waveAFrequency ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveAFrequency,
|
|
8668
|
+
waveAAmplitude: previousUniforms.waveAAmplitude ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveAAmplitude,
|
|
8669
|
+
waveBDirection: previousUniforms.waveBDirection ? normalizeDirection2(previousUniforms.waveBDirection) : DEFAULT_WATER_MATERIAL_UNIFORMS.waveBDirection,
|
|
8670
|
+
waveBSpeed: previousUniforms.waveBSpeed ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBSpeed,
|
|
8671
|
+
waveBFrequency: previousUniforms.waveBFrequency ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBFrequency,
|
|
8672
|
+
waveBAmplitude: previousUniforms.waveBAmplitude ?? DEFAULT_WATER_MATERIAL_UNIFORMS.waveBAmplitude
|
|
8673
|
+
};
|
|
8674
|
+
}
|
|
8675
|
+
function normalizeColor3(color) {
|
|
8676
|
+
const normalizedColor = [Number(color[0]), Number(color[1]), Number(color[2])];
|
|
8677
|
+
const maxChannel = Math.max(...normalizedColor.map((channel) => Math.abs(channel)));
|
|
8678
|
+
if (maxChannel > 1) {
|
|
8679
|
+
normalizedColor[0] /= 255;
|
|
8680
|
+
normalizedColor[1] /= 255;
|
|
8681
|
+
normalizedColor[2] /= 255;
|
|
8682
|
+
}
|
|
8683
|
+
return normalizedColor;
|
|
8684
|
+
}
|
|
8685
|
+
function normalizeDirection2(direction) {
|
|
8686
|
+
const x = Number(direction[0]);
|
|
8687
|
+
const y = Number(direction[1]);
|
|
8688
|
+
const length = Math.hypot(x, y);
|
|
8689
|
+
if (length === 0) {
|
|
8690
|
+
return [1, 0];
|
|
8691
|
+
}
|
|
8692
|
+
return [x / length, y / length];
|
|
8693
|
+
}
|
|
8694
|
+
|
|
4607
8695
|
// dist/modules/lighting/pbr-material/pbr-material-glsl.js
|
|
4608
8696
|
var vs3 = (
|
|
4609
8697
|
/* glsl */
|