@luma.gl/shadertools 9.3.0-alpha.8 → 9.3.0

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.
Files changed (113) hide show
  1. package/dist/dist.dev.js +1020 -191
  2. package/dist/dist.min.js +440 -145
  3. package/dist/index.cjs +915 -173
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +7 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +4 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/color/normalize-byte-colors.d.ts +23 -0
  10. package/dist/lib/color/normalize-byte-colors.d.ts.map +1 -0
  11. package/dist/lib/color/normalize-byte-colors.js +42 -0
  12. package/dist/lib/color/normalize-byte-colors.js.map +1 -0
  13. package/dist/lib/glsl-utils/shader-utils.js +4 -4
  14. package/dist/lib/glsl-utils/shader-utils.js.map +1 -1
  15. package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
  16. package/dist/lib/shader-assembly/assemble-shaders.js +102 -49
  17. package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
  18. package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts.map +1 -1
  19. package/dist/lib/shader-assembly/wgsl-binding-debug.js +7 -3
  20. package/dist/lib/shader-assembly/wgsl-binding-debug.js.map +1 -1
  21. package/dist/lib/shader-assembly/wgsl-binding-scan.d.ts +19 -0
  22. package/dist/lib/shader-assembly/wgsl-binding-scan.d.ts.map +1 -0
  23. package/dist/lib/shader-assembly/wgsl-binding-scan.js +151 -0
  24. package/dist/lib/shader-assembly/wgsl-binding-scan.js.map +1 -0
  25. package/dist/lib/shader-generator/glsl/generate-glsl.js +4 -4
  26. package/dist/lib/shader-generator/glsl/generate-glsl.js.map +1 -1
  27. package/dist/lib/shader-module/shader-module-uniform-layout.d.ts +69 -0
  28. package/dist/lib/shader-module/shader-module-uniform-layout.d.ts.map +1 -1
  29. package/dist/lib/shader-module/shader-module-uniform-layout.js +145 -4
  30. package/dist/lib/shader-module/shader-module-uniform-layout.js.map +1 -1
  31. package/dist/modules/color/float-colors.d.ts +26 -0
  32. package/dist/modules/color/float-colors.d.ts.map +1 -0
  33. package/dist/modules/color/float-colors.js +82 -0
  34. package/dist/modules/color/float-colors.js.map +1 -0
  35. package/dist/modules/engine/picking/picking.d.ts +8 -8
  36. package/dist/modules/engine/picking/picking.d.ts.map +1 -1
  37. package/dist/modules/engine/picking/picking.js +13 -15
  38. package/dist/modules/engine/picking/picking.js.map +1 -1
  39. package/dist/modules/engine/project/project.d.ts +1 -1
  40. package/dist/modules/engine/project/project.js +1 -1
  41. package/dist/modules/engine/skin/skin.d.ts +2 -2
  42. package/dist/modules/engine/skin/skin.d.ts.map +1 -1
  43. package/dist/modules/engine/skin/skin.js +1 -1
  44. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts +1 -0
  45. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts.map +1 -1
  46. package/dist/modules/lighting/gouraud-material/gouraud-material.js +6 -3
  47. package/dist/modules/lighting/gouraud-material/gouraud-material.js.map +1 -1
  48. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts +2 -2
  49. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts.map +1 -1
  50. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js +2 -2
  51. package/dist/modules/lighting/lights/lighting-glsl.d.ts +1 -1
  52. package/dist/modules/lighting/lights/lighting-glsl.d.ts.map +1 -1
  53. package/dist/modules/lighting/lights/lighting-glsl.js +1 -1
  54. package/dist/modules/lighting/lights/lighting.d.ts +4 -2
  55. package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
  56. package/dist/modules/lighting/lights/lighting.js +17 -11
  57. package/dist/modules/lighting/lights/lighting.js.map +1 -1
  58. package/dist/modules/lighting/no-material/dirlight.d.ts +3 -3
  59. package/dist/modules/lighting/no-material/dirlight.d.ts.map +1 -1
  60. package/dist/modules/lighting/no-material/dirlight.js +2 -2
  61. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts +2 -2
  62. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts.map +1 -1
  63. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js +138 -35
  64. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js.map +1 -1
  65. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts +1 -1
  66. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts.map +1 -1
  67. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js +139 -35
  68. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js.map +1 -1
  69. package/dist/modules/lighting/pbr-material/pbr-material.d.ts +74 -6
  70. package/dist/modules/lighting/pbr-material/pbr-material.d.ts.map +1 -1
  71. package/dist/modules/lighting/pbr-material/pbr-material.js +70 -2
  72. package/dist/modules/lighting/pbr-material/pbr-material.js.map +1 -1
  73. package/dist/modules/lighting/pbr-material/pbr-projection.js +1 -1
  74. package/dist/modules/lighting/pbr-material/pbr-scene.d.ts +40 -0
  75. package/dist/modules/lighting/pbr-material/pbr-scene.d.ts.map +1 -0
  76. package/dist/modules/lighting/pbr-material/pbr-scene.js +67 -0
  77. package/dist/modules/lighting/pbr-material/pbr-scene.js.map +1 -0
  78. package/dist/modules/lighting/phong-material/phong-material.d.ts +1 -0
  79. package/dist/modules/lighting/phong-material/phong-material.d.ts.map +1 -1
  80. package/dist/modules/lighting/phong-material/phong-material.js +6 -3
  81. package/dist/modules/lighting/phong-material/phong-material.js.map +1 -1
  82. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts +2 -2
  83. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts.map +1 -1
  84. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js +2 -2
  85. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts +1 -1
  86. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts.map +1 -1
  87. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js +1 -1
  88. package/package.json +2 -2
  89. package/src/index.ts +17 -1
  90. package/src/lib/color/normalize-byte-colors.ts +57 -0
  91. package/src/lib/glsl-utils/shader-utils.ts +4 -4
  92. package/src/lib/shader-assembly/assemble-shaders.ts +197 -69
  93. package/src/lib/shader-assembly/wgsl-binding-debug.ts +14 -3
  94. package/src/lib/shader-assembly/wgsl-binding-scan.ts +228 -0
  95. package/src/lib/shader-generator/glsl/generate-glsl.ts +4 -4
  96. package/src/lib/shader-module/shader-module-uniform-layout.ts +236 -10
  97. package/src/modules/color/float-colors.ts +99 -0
  98. package/src/modules/engine/picking/picking.ts +17 -19
  99. package/src/modules/engine/project/project.ts +1 -1
  100. package/src/modules/engine/skin/skin.ts +1 -1
  101. package/src/modules/lighting/gouraud-material/gouraud-material.ts +10 -3
  102. package/src/modules/lighting/lambert-material/lambert-shaders-glsl.ts +2 -2
  103. package/src/modules/lighting/lights/lighting-glsl.ts +1 -1
  104. package/src/modules/lighting/lights/lighting.ts +20 -11
  105. package/src/modules/lighting/no-material/dirlight.ts +2 -2
  106. package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +138 -35
  107. package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +139 -35
  108. package/src/modules/lighting/pbr-material/pbr-material.ts +110 -3
  109. package/src/modules/lighting/pbr-material/pbr-projection.ts +1 -1
  110. package/src/modules/lighting/pbr-material/pbr-scene.ts +91 -0
  111. package/src/modules/lighting/phong-material/phong-material.ts +10 -3
  112. package/src/modules/lighting/phong-material/phong-shaders-glsl.ts +2 -2
  113. package/src/modules/math/fp64/fp64-arithmetic-glsl.ts +1 -1
package/dist/index.cjs CHANGED
@@ -34,6 +34,7 @@ __export(dist_exports, {
34
34
  combineInjects: () => combineInjects,
35
35
  convertToVec4: () => convertToVec4,
36
36
  dirlight: () => dirlight,
37
+ floatColors: () => floatColors,
37
38
  fp32: () => fp32,
38
39
  fp64: () => fp64,
39
40
  fp64LowPart: () => fp64LowPart,
@@ -42,6 +43,7 @@ __export(dist_exports, {
42
43
  fp64ifyMatrix4: () => fp64ifyMatrix4,
43
44
  fromHalfFloat: () => fromHalfFloat,
44
45
  generateShaderForModule: () => generateShaderForModule,
46
+ getGLSLUniformBlocks: () => getGLSLUniformBlocks,
45
47
  getPassthroughFS: () => getPassthroughFS,
46
48
  getQualifierDetails: () => getQualifierDetails,
47
49
  getShaderInfo: () => getShaderInfo,
@@ -57,16 +59,21 @@ __export(dist_exports, {
57
59
  initializeShaderModules: () => initializeShaderModules,
58
60
  lambertMaterial: () => lambertMaterial,
59
61
  lighting: () => lighting,
62
+ normalizeByteColor3: () => normalizeByteColor3,
63
+ normalizeByteColor4: () => normalizeByteColor4,
60
64
  pbrMaterial: () => pbrMaterial,
65
+ pbrScene: () => pbrScene,
61
66
  phongMaterial: () => phongMaterial,
62
67
  picking: () => picking,
63
68
  preprocess: () => preprocess,
64
69
  random: () => random,
70
+ resolveUseByteColors: () => resolveUseByteColors,
65
71
  skin: () => skin,
66
72
  toHalfFloat: () => toHalfFloat,
67
73
  typeToChannelCount: () => typeToChannelCount,
68
74
  typeToChannelSuffix: () => typeToChannelSuffix,
69
- validateShaderModuleUniformLayout: () => validateShaderModuleUniformLayout
75
+ validateShaderModuleUniformLayout: () => validateShaderModuleUniformLayout,
76
+ warnIfGLSLUniformBlocksAreNotStd140: () => warnIfGLSLUniformBlocksAreNotStd140
70
77
  });
71
78
  module.exports = __toCommonJS(dist_exports);
72
79
 
@@ -386,6 +393,8 @@ function resolveModules(modules) {
386
393
  }
387
394
 
388
395
  // dist/lib/shader-module/shader-module-uniform-layout.js
396
+ var GLSL_UNIFORM_BLOCK_FIELD_REGEXP = /^(?:uniform\s+)?(?:(?:lowp|mediump|highp)\s+)?[A-Za-z0-9_]+(?:<[^>]+>)?\s+([A-Za-z0-9_]+)(?:\s*\[[^\]]+\])?\s*;/;
397
+ 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;
389
398
  function getShaderModuleUniformBlockName(module2) {
390
399
  return `${module2.name}Uniforms`;
391
400
  }
@@ -428,6 +437,39 @@ function validateShaderModuleUniformLayout(module2, stage, options = {}) {
428
437
  }
429
438
  return validationResult;
430
439
  }
440
+ function getGLSLUniformBlocks(shaderSource) {
441
+ var _a;
442
+ const blocks = [];
443
+ const uncommentedSource = stripShaderComments(shaderSource);
444
+ for (const sourceMatch of uncommentedSource.matchAll(GLSL_UNIFORM_BLOCK_REGEXP)) {
445
+ const layoutQualifier = ((_a = sourceMatch[1]) == null ? void 0 : _a.trim()) || null;
446
+ blocks.push({
447
+ blockName: sourceMatch[2],
448
+ body: sourceMatch[3],
449
+ instanceName: sourceMatch[4] || null,
450
+ layoutQualifier,
451
+ hasLayoutQualifier: Boolean(layoutQualifier),
452
+ isStd140: Boolean(layoutQualifier && /\blayout\s*\([^)]*\bstd140\b[^)]*\)/.exec(layoutQualifier))
453
+ });
454
+ }
455
+ return blocks;
456
+ }
457
+ function warnIfGLSLUniformBlocksAreNotStd140(shaderSource, stage, log2, context) {
458
+ var _a;
459
+ const nonStd140Blocks = getGLSLUniformBlocks(shaderSource).filter((block) => !block.isStd140);
460
+ const seenBlockNames = /* @__PURE__ */ new Set();
461
+ for (const block of nonStd140Blocks) {
462
+ if (seenBlockNames.has(block.blockName)) {
463
+ continue;
464
+ }
465
+ seenBlockNames.add(block.blockName);
466
+ const shaderLabel = (context == null ? void 0 : context.label) ? `${context.label} ` : "";
467
+ const actualLayout = block.hasLayoutQualifier ? `declares ${normalizeWhitespace(block.layoutQualifier)} instead of layout(std140)` : "does not declare layout(std140)";
468
+ const message = `${shaderLabel}${stage} shader uniform block ${block.blockName} ${actualLayout}. luma.gl host-side shader block packing assumes explicit layout(std140) for GLSL uniform blocks. Add \`layout(std140)\` to the block declaration.`;
469
+ (_a = log2 == null ? void 0 : log2.warn) == null ? void 0 : _a.call(log2, message, block)();
470
+ }
471
+ return nonStd140Blocks;
472
+ }
431
473
  function extractShaderUniformBlockFieldNames(shaderSource, language, uniformBlockName) {
432
474
  const sourceBody = language === "wgsl" ? extractWGSLStructBody(shaderSource, uniformBlockName) : extractGLSLUniformBlockBody(shaderSource, uniformBlockName);
433
475
  if (!sourceBody) {
@@ -439,7 +481,7 @@ function extractShaderUniformBlockFieldNames(shaderSource, language, uniformBloc
439
481
  if (!line || line.startsWith("#")) {
440
482
  continue;
441
483
  }
442
- const fieldMatch = language === "wgsl" ? line.match(/^([A-Za-z0-9_]+)\s*:/) : line.match(/^(?:uniform\s+)?[A-Za-z0-9_]+(?:<[^>]+>)?\s+([A-Za-z0-9_]+)(?:\s*\[[^\]]+\])?\s*;/);
484
+ const fieldMatch = language === "wgsl" ? line.match(/^([A-Za-z0-9_]+)\s*:/) : line.match(GLSL_UNIFORM_BLOCK_FIELD_REGEXP);
443
485
  if (fieldMatch) {
444
486
  fieldNames.push(fieldMatch[1]);
445
487
  }
@@ -473,8 +515,8 @@ function extractWGSLStructBody(shaderSource, uniformBlockName) {
473
515
  return null;
474
516
  }
475
517
  function extractGLSLUniformBlockBody(shaderSource, uniformBlockName) {
476
- const sourceMatch = shaderSource.match(new RegExp(`uniform\\s+${uniformBlockName}\\s*\\{([\\s\\S]*?)\\}\\s*[A-Za-z0-9_]+\\s*;`, "m"));
477
- return (sourceMatch == null ? void 0 : sourceMatch[1]) || null;
518
+ const block = getGLSLUniformBlocks(shaderSource).find((candidate) => candidate.blockName === uniformBlockName);
519
+ return (block == null ? void 0 : block.body) || null;
478
520
  }
479
521
  function areStringArraysEqual(leftValues, rightValues) {
480
522
  if (leftValues.length !== rightValues.length) {
@@ -488,9 +530,55 @@ function areStringArraysEqual(leftValues, rightValues) {
488
530
  return true;
489
531
  }
490
532
  function formatShaderModuleUniformLayoutError(validationResult) {
491
- return `${validationResult.moduleName}: ${validationResult.stage} shader uniform block ${validationResult.uniformBlockName} does not match module.uniformTypes.
492
- Expected: ${validationResult.expectedUniformNames.join(", ")}
493
- Actual: ${validationResult.actualUniformNames.join(", ")}`;
533
+ const { expectedUniformNames, actualUniformNames } = validationResult;
534
+ const missingUniformNames = expectedUniformNames.filter((uniformName) => !actualUniformNames.includes(uniformName));
535
+ const unexpectedUniformNames = actualUniformNames.filter((uniformName) => !expectedUniformNames.includes(uniformName));
536
+ const mismatchDetails = [
537
+ `Expected ${expectedUniformNames.length} fields, found ${actualUniformNames.length}.`
538
+ ];
539
+ const firstMismatchDescription = getFirstUniformMismatchDescription(expectedUniformNames, actualUniformNames);
540
+ if (firstMismatchDescription) {
541
+ mismatchDetails.push(firstMismatchDescription);
542
+ }
543
+ if (missingUniformNames.length) {
544
+ mismatchDetails.push(`Missing from shader block (${missingUniformNames.length}): ${formatUniformNameList(missingUniformNames)}.`);
545
+ }
546
+ if (unexpectedUniformNames.length) {
547
+ mismatchDetails.push(`Unexpected in shader block (${unexpectedUniformNames.length}): ${formatUniformNameList(unexpectedUniformNames)}.`);
548
+ }
549
+ if (expectedUniformNames.length <= 12 && actualUniformNames.length <= 12 && (missingUniformNames.length || unexpectedUniformNames.length)) {
550
+ mismatchDetails.push(`Expected: ${expectedUniformNames.join(", ")}.`);
551
+ mismatchDetails.push(`Actual: ${actualUniformNames.join(", ")}.`);
552
+ }
553
+ return `${validationResult.moduleName}: ${validationResult.stage} shader uniform block ${validationResult.uniformBlockName} does not match module.uniformTypes. ${mismatchDetails.join(" ")}`;
554
+ }
555
+ function stripShaderComments(shaderSource) {
556
+ return shaderSource.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
557
+ }
558
+ function normalizeWhitespace(value) {
559
+ return value.replace(/\s+/g, " ").trim();
560
+ }
561
+ function getFirstUniformMismatchDescription(expectedUniformNames, actualUniformNames) {
562
+ const minimumLength = Math.min(expectedUniformNames.length, actualUniformNames.length);
563
+ for (let index = 0; index < minimumLength; index++) {
564
+ if (expectedUniformNames[index] !== actualUniformNames[index]) {
565
+ return `First mismatch at field ${index + 1}: expected ${expectedUniformNames[index]}, found ${actualUniformNames[index]}.`;
566
+ }
567
+ }
568
+ if (expectedUniformNames.length > actualUniformNames.length) {
569
+ return `Shader block ends after field ${actualUniformNames.length}; expected next field ${expectedUniformNames[actualUniformNames.length]}.`;
570
+ }
571
+ if (actualUniformNames.length > expectedUniformNames.length) {
572
+ return `Shader block has extra field ${actualUniformNames.length}: ${actualUniformNames[expectedUniformNames.length]}.`;
573
+ }
574
+ return null;
575
+ }
576
+ function formatUniformNameList(uniformNames, maxNames = 8) {
577
+ if (uniformNames.length <= maxNames) {
578
+ return uniformNames.join(", ");
579
+ }
580
+ const remainingCount = uniformNames.length - maxNames;
581
+ return `${uniformNames.slice(0, maxNames).join(", ")}, ... (${remainingCount} more)`;
494
582
  }
495
583
 
496
584
  // dist/lib/shader-assembly/platform-defines.js
@@ -678,13 +766,158 @@ function getShaderVersion(source4) {
678
766
  return version;
679
767
  }
680
768
 
769
+ // dist/lib/shader-assembly/wgsl-binding-scan.js
770
+ var WGSL_BINDABLE_VARIABLE_PATTERN = "(?:var<\\s*(uniform|storage(?:\\s*,\\s*[A-Za-z_][A-Za-z0-9_]*)?)\\s*>|var)\\s+([A-Za-z_][A-Za-z0-9_]*)";
771
+ var WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN = "\\s*";
772
+ var MODULE_WGSL_BINDING_DECLARATION_REGEXES = [
773
+ new RegExp(`@binding\\(\\s*(auto|\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g"),
774
+ new RegExp(`@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@binding\\(\\s*(auto|\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g")
775
+ ];
776
+ var WGSL_BINDING_DECLARATION_REGEXES = [
777
+ new RegExp(`@binding\\(\\s*(auto|\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g"),
778
+ new RegExp(`@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@binding\\(\\s*(auto|\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g")
779
+ ];
780
+ var WGSL_EXPLICIT_BINDING_DECLARATION_REGEXES = [
781
+ new RegExp(`@binding\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g"),
782
+ new RegExp(`@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@binding\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g")
783
+ ];
784
+ var WGSL_AUTO_BINDING_DECLARATION_REGEXES = [
785
+ new RegExp(`@binding\\(\\s*(auto)\\s*\\)\\s*@group\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g"),
786
+ new RegExp(`@group\\(\\s*(\\d+)\\s*\\)\\s*@binding\\(\\s*(auto)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g"),
787
+ new RegExp(`@binding\\(\\s*(auto)\\s*\\)\\s*@group\\(\\s*(\\d+)\\s*\\)(?:[\\s\\n\\r]*@[A-Za-z_][^\\n\\r]*)*[\\s\\n\\r]*${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g"),
788
+ new RegExp(`@group\\(\\s*(\\d+)\\s*\\)\\s*@binding\\(\\s*(auto)\\s*\\)(?:[\\s\\n\\r]*@[A-Za-z_][^\\n\\r]*)*[\\s\\n\\r]*${WGSL_BINDABLE_VARIABLE_PATTERN}`, "g")
789
+ ];
790
+ function maskWGSLComments(source4) {
791
+ const maskedCharacters = source4.split("");
792
+ let index = 0;
793
+ let blockCommentDepth = 0;
794
+ let inLineComment = false;
795
+ let inString = false;
796
+ let isEscaped = false;
797
+ while (index < source4.length) {
798
+ const character = source4[index];
799
+ const nextCharacter = source4[index + 1];
800
+ if (inString) {
801
+ if (isEscaped) {
802
+ isEscaped = false;
803
+ } else if (character === "\\") {
804
+ isEscaped = true;
805
+ } else if (character === '"') {
806
+ inString = false;
807
+ }
808
+ index++;
809
+ continue;
810
+ }
811
+ if (inLineComment) {
812
+ if (character === "\n" || character === "\r") {
813
+ inLineComment = false;
814
+ } else {
815
+ maskedCharacters[index] = " ";
816
+ }
817
+ index++;
818
+ continue;
819
+ }
820
+ if (blockCommentDepth > 0) {
821
+ if (character === "/" && nextCharacter === "*") {
822
+ maskedCharacters[index] = " ";
823
+ maskedCharacters[index + 1] = " ";
824
+ blockCommentDepth++;
825
+ index += 2;
826
+ continue;
827
+ }
828
+ if (character === "*" && nextCharacter === "/") {
829
+ maskedCharacters[index] = " ";
830
+ maskedCharacters[index + 1] = " ";
831
+ blockCommentDepth--;
832
+ index += 2;
833
+ continue;
834
+ }
835
+ if (character !== "\n" && character !== "\r") {
836
+ maskedCharacters[index] = " ";
837
+ }
838
+ index++;
839
+ continue;
840
+ }
841
+ if (character === '"') {
842
+ inString = true;
843
+ index++;
844
+ continue;
845
+ }
846
+ if (character === "/" && nextCharacter === "/") {
847
+ maskedCharacters[index] = " ";
848
+ maskedCharacters[index + 1] = " ";
849
+ inLineComment = true;
850
+ index += 2;
851
+ continue;
852
+ }
853
+ if (character === "/" && nextCharacter === "*") {
854
+ maskedCharacters[index] = " ";
855
+ maskedCharacters[index + 1] = " ";
856
+ blockCommentDepth = 1;
857
+ index += 2;
858
+ continue;
859
+ }
860
+ index++;
861
+ }
862
+ return maskedCharacters.join("");
863
+ }
864
+ function getWGSLBindingDeclarationMatches(source4, regexes) {
865
+ var _a;
866
+ const maskedSource = maskWGSLComments(source4);
867
+ const matches = [];
868
+ for (const regex of regexes) {
869
+ regex.lastIndex = 0;
870
+ let match;
871
+ match = regex.exec(maskedSource);
872
+ while (match) {
873
+ const isBindingFirst = regex === regexes[0];
874
+ const index = match.index;
875
+ const length = match[0].length;
876
+ matches.push({
877
+ match: source4.slice(index, index + length),
878
+ index,
879
+ length,
880
+ bindingToken: match[isBindingFirst ? 1 : 2],
881
+ groupToken: match[isBindingFirst ? 2 : 1],
882
+ accessDeclaration: (_a = match[3]) == null ? void 0 : _a.trim(),
883
+ name: match[4]
884
+ });
885
+ match = regex.exec(maskedSource);
886
+ }
887
+ }
888
+ return matches.sort((left, right) => left.index - right.index);
889
+ }
890
+ function replaceWGSLBindingDeclarationMatches(source4, regexes, replacer) {
891
+ const matches = getWGSLBindingDeclarationMatches(source4, regexes);
892
+ if (!matches.length) {
893
+ return source4;
894
+ }
895
+ let relocatedSource = "";
896
+ let lastIndex = 0;
897
+ for (const match of matches) {
898
+ relocatedSource += source4.slice(lastIndex, match.index);
899
+ relocatedSource += replacer(match);
900
+ lastIndex = match.index + match.length;
901
+ }
902
+ relocatedSource += source4.slice(lastIndex);
903
+ return relocatedSource;
904
+ }
905
+ function hasWGSLAutoBinding(source4) {
906
+ return /@binding\(\s*auto\s*\)/.test(maskWGSLComments(source4));
907
+ }
908
+ function getFirstWGSLAutoBindingDeclarationMatch(source4, regexes) {
909
+ const autoBindingRegexes = regexes === MODULE_WGSL_BINDING_DECLARATION_REGEXES || regexes === WGSL_BINDING_DECLARATION_REGEXES ? WGSL_AUTO_BINDING_DECLARATION_REGEXES : regexes;
910
+ return getWGSLBindingDeclarationMatches(source4, autoBindingRegexes).find((declarationMatch) => declarationMatch.bindingToken === "auto");
911
+ }
912
+
681
913
  // dist/lib/shader-assembly/wgsl-binding-debug.js
682
914
  var WGSL_BINDING_DEBUG_REGEXES = [
683
- /@binding\(\s*(\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*var(?:<([^>]+)>)?\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^;]+);/g,
684
- /@group\(\s*(\d+)\s*\)\s*@binding\(\s*(\d+)\s*\)\s*var(?:<([^>]+)>)?\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^;]+);/g
915
+ new RegExp(`@binding\\(\\s*(\\d+)\\s*\\)\\s*@group\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}\\s*:\\s*([^;]+);`, "g"),
916
+ new RegExp(`@group\\(\\s*(\\d+)\\s*\\)\\s*@binding\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}\\s*:\\s*([^;]+);`, "g")
685
917
  ];
686
918
  function getShaderBindingDebugRowsFromWGSL(source4, bindingAssignments = []) {
687
919
  var _a;
920
+ const maskedSource = maskWGSLComments(source4);
688
921
  const assignmentMap = /* @__PURE__ */ new Map();
689
922
  for (const bindingAssignment of bindingAssignments) {
690
923
  assignmentMap.set(getBindingAssignmentKey(bindingAssignment.name, bindingAssignment.group, bindingAssignment.location), bindingAssignment.moduleName);
@@ -693,7 +926,8 @@ function getShaderBindingDebugRowsFromWGSL(source4, bindingAssignments = []) {
693
926
  for (const regex of WGSL_BINDING_DEBUG_REGEXES) {
694
927
  regex.lastIndex = 0;
695
928
  let match;
696
- while (match = regex.exec(source4)) {
929
+ match = regex.exec(maskedSource);
930
+ while (match) {
697
931
  const isBindingFirst = regex === WGSL_BINDING_DEBUG_REGEXES[0];
698
932
  const binding = Number(match[isBindingFirst ? 1 : 2]);
699
933
  const group = Number(match[isBindingFirst ? 2 : 1]);
@@ -710,6 +944,7 @@ function getShaderBindingDebugRowsFromWGSL(source4, bindingAssignments = []) {
710
944
  accessDeclaration,
711
945
  resourceType
712
946
  }));
947
+ match = regex.exec(maskedSource);
713
948
  }
714
949
  }
715
950
  return rows.sort((left, right) => {
@@ -821,14 +1056,6 @@ var INJECT_SHADER_DECLARATIONS = `
821
1056
 
822
1057
  ${DECLARATION_INJECT_MARKER}
823
1058
  `;
824
- var MODULE_WGSL_BINDING_DECLARATION_REGEXES = [
825
- /@binding\(\s*(auto|\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g,
826
- /@group\(\s*(\d+)\s*\)\s*@binding\(\s*(auto|\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g
827
- ];
828
- var WGSL_BINDING_DECLARATION_REGEXES = [
829
- /@binding\(\s*(\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g,
830
- /@group\(\s*(\d+)\s*\)\s*@binding\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g
831
- ];
832
1059
  var RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT = 100;
833
1060
  var FRAGMENT_SHADER_PROLOGUE = (
834
1061
  /* glsl */
@@ -909,7 +1136,8 @@ function assembleShaderWGSL(platformInfo, options) {
909
1136
  }
910
1137
  }
911
1138
  const modulesToInject = modules;
912
- const usedBindingsByGroup = getUsedBindingsByGroupFromApplicationWGSL(coreSource);
1139
+ const applicationRelocation = relocateWGSLApplicationBindings(coreSource);
1140
+ const usedBindingsByGroup = getUsedBindingsByGroupFromApplicationWGSL(applicationRelocation.source);
913
1141
  const reservedBindingKeysByGroup = reserveRegisteredModuleBindings(modulesToInject, options._bindingRegistry, usedBindingsByGroup);
914
1142
  const bindingAssignments = [];
915
1143
  for (const module2 of modulesToInject) {
@@ -942,7 +1170,7 @@ function assembleShaderWGSL(platformInfo, options) {
942
1170
  assembledSource = injectShader(assembledSource, stage, declInjections);
943
1171
  assembledSource += getShaderHooks(hookFunctionMap[stage], hookInjections);
944
1172
  assembledSource += formatWGSLBindingAssignmentComments(bindingAssignments);
945
- assembledSource += coreSource;
1173
+ assembledSource += applicationRelocation.source;
946
1174
  assembledSource = injectShader(assembledSource, stage, mainInjections);
947
1175
  assertNoUnresolvedAutoBindings(assembledSource);
948
1176
  return { source: assembledSource, bindingAssignments };
@@ -1034,6 +1262,9 @@ ${getApplicationDefines(allDefines)}
1034
1262
  if (language === "glsl" && sourceVersion !== targetVersion) {
1035
1263
  assembledSource = transpileGLSLShader(assembledSource, stage);
1036
1264
  }
1265
+ if (language === "glsl") {
1266
+ warnIfGLSLUniformBlocksAreNotStd140(assembledSource, stage, log2);
1267
+ }
1037
1268
  return assembledSource.trim();
1038
1269
  }
1039
1270
  function assembleGetUniforms(modules) {
@@ -1091,44 +1322,57 @@ function getShaderModuleSource(module2, stage, log2) {
1091
1322
  }
1092
1323
  function getUsedBindingsByGroupFromApplicationWGSL(source4) {
1093
1324
  const usedBindingsByGroup = /* @__PURE__ */ new Map();
1094
- for (const regex of WGSL_BINDING_DECLARATION_REGEXES) {
1095
- regex.lastIndex = 0;
1096
- let match;
1097
- while (match = regex.exec(source4)) {
1098
- const isBindingFirst = regex === WGSL_BINDING_DECLARATION_REGEXES[0];
1099
- const location = Number(match[isBindingFirst ? 1 : 2]);
1100
- const group = Number(match[isBindingFirst ? 2 : 1]);
1101
- const name = match[4];
1102
- validateApplicationWGSLBinding(group, location, name);
1103
- registerUsedBindingLocation(usedBindingsByGroup, group, location, `application binding "${name}"`);
1104
- }
1325
+ for (const match of getWGSLBindingDeclarationMatches(source4, WGSL_EXPLICIT_BINDING_DECLARATION_REGEXES)) {
1326
+ const location = Number(match.bindingToken);
1327
+ const group = Number(match.groupToken);
1328
+ validateApplicationWGSLBinding(group, location, match.name);
1329
+ registerUsedBindingLocation(usedBindingsByGroup, group, location, `application binding "${match.name}"`);
1105
1330
  }
1106
1331
  return usedBindingsByGroup;
1107
1332
  }
1333
+ function relocateWGSLApplicationBindings(source4) {
1334
+ const declarationMatches = getWGSLBindingDeclarationMatches(source4, WGSL_BINDING_DECLARATION_REGEXES);
1335
+ const usedBindingsByGroup = /* @__PURE__ */ new Map();
1336
+ for (const declarationMatch of declarationMatches) {
1337
+ if (declarationMatch.bindingToken === "auto") {
1338
+ continue;
1339
+ }
1340
+ const location = Number(declarationMatch.bindingToken);
1341
+ const group = Number(declarationMatch.groupToken);
1342
+ validateApplicationWGSLBinding(group, location, declarationMatch.name);
1343
+ registerUsedBindingLocation(usedBindingsByGroup, group, location, `application binding "${declarationMatch.name}"`);
1344
+ }
1345
+ const relocationState = {
1346
+ sawSupportedBindingDeclaration: declarationMatches.length > 0
1347
+ };
1348
+ const relocatedSource = replaceWGSLBindingDeclarationMatches(source4, WGSL_BINDING_DECLARATION_REGEXES, (declarationMatch) => relocateWGSLApplicationBindingMatch(declarationMatch, usedBindingsByGroup, relocationState));
1349
+ if (hasWGSLAutoBinding(source4) && !relocationState.sawSupportedBindingDeclaration) {
1350
+ throw new Error('Unsupported @binding(auto) declaration form in application WGSL. Use adjacent "@group(N)" and "@binding(auto)" decorators followed by a bindable "var" declaration.');
1351
+ }
1352
+ return { source: relocatedSource };
1353
+ }
1108
1354
  function relocateWGSLModuleBindings(moduleSource, module2, context) {
1109
1355
  const bindingAssignments = [];
1356
+ const declarationMatches = getWGSLBindingDeclarationMatches(moduleSource, MODULE_WGSL_BINDING_DECLARATION_REGEXES);
1110
1357
  const relocationState = {
1111
- sawSupportedBindingDeclaration: false,
1358
+ sawSupportedBindingDeclaration: declarationMatches.length > 0,
1112
1359
  nextHintedBindingLocation: typeof module2.firstBindingSlot === "number" ? module2.firstBindingSlot : null
1113
1360
  };
1114
- let relocatedSource = relocateWGSLModuleBindingsWithRegex(moduleSource, MODULE_WGSL_BINDING_DECLARATION_REGEXES[0], { isBindingFirst: true, module: module2, context, bindingAssignments, relocationState });
1115
- relocatedSource = relocateWGSLModuleBindingsWithRegex(relocatedSource, MODULE_WGSL_BINDING_DECLARATION_REGEXES[1], { isBindingFirst: false, module: module2, context, bindingAssignments, relocationState });
1116
- if (moduleSource.includes("@binding(auto)") && !relocationState.sawSupportedBindingDeclaration) {
1117
- throw new Error(`Unsupported @binding(auto) declaration form in module "${module2.name}". Use "@group(N) @binding(auto) var ..." or "@binding(auto) @group(N) var ..." on a single line.`);
1361
+ const relocatedSource = replaceWGSLBindingDeclarationMatches(moduleSource, MODULE_WGSL_BINDING_DECLARATION_REGEXES, (declarationMatch) => relocateWGSLModuleBindingMatch(declarationMatch, {
1362
+ module: module2,
1363
+ context,
1364
+ bindingAssignments,
1365
+ relocationState
1366
+ }));
1367
+ if (hasWGSLAutoBinding(moduleSource) && !relocationState.sawSupportedBindingDeclaration) {
1368
+ throw new Error(`Unsupported @binding(auto) declaration form in module "${module2.name}". Use adjacent "@group(N)" and "@binding(auto)" decorators followed by a bindable "var" declaration.`);
1118
1369
  }
1119
1370
  return { source: relocatedSource, bindingAssignments };
1120
1371
  }
1121
- function relocateWGSLModuleBindingsWithRegex(source4, regex, params) {
1122
- return source4.replace(regex, (...replaceArguments) => relocateWGSLModuleBindingMatch(replaceArguments, params));
1123
- }
1124
- function relocateWGSLModuleBindingMatch(replaceArguments, params) {
1372
+ function relocateWGSLModuleBindingMatch(declarationMatch, params) {
1125
1373
  var _a, _b;
1126
- const { isBindingFirst, module: module2, context, bindingAssignments, relocationState } = params;
1127
- relocationState.sawSupportedBindingDeclaration = true;
1128
- const match = replaceArguments[0];
1129
- const bindingToken = replaceArguments[isBindingFirst ? 1 : 2];
1130
- const groupToken = replaceArguments[isBindingFirst ? 2 : 1];
1131
- const name = replaceArguments[4];
1374
+ const { module: module2, context, bindingAssignments, relocationState } = params;
1375
+ const { match, bindingToken, groupToken, name } = declarationMatch;
1132
1376
  const group = Number(groupToken);
1133
1377
  if (bindingToken === "auto") {
1134
1378
  const registryKey = getBindingRegistryKey(group, module2.name, name);
@@ -1153,6 +1397,18 @@ function relocateWGSLModuleBindingMatch(replaceArguments, params) {
1153
1397
  bindingAssignments.push({ moduleName: module2.name, name, group, location });
1154
1398
  return match;
1155
1399
  }
1400
+ function relocateWGSLApplicationBindingMatch(declarationMatch, usedBindingsByGroup, relocationState) {
1401
+ const { match, bindingToken, groupToken, name } = declarationMatch;
1402
+ const group = Number(groupToken);
1403
+ if (bindingToken === "auto") {
1404
+ const location = allocateApplicationAutoBindingLocation(group, usedBindingsByGroup);
1405
+ validateApplicationWGSLBinding(group, location, name);
1406
+ registerUsedBindingLocation(usedBindingsByGroup, group, location, `application binding "${name}"`);
1407
+ return match.replace(/@binding\(\s*auto\s*\)/, `@binding(${location})`);
1408
+ }
1409
+ relocationState.sawSupportedBindingDeclaration = true;
1410
+ return match;
1411
+ }
1156
1412
  function reserveRegisteredModuleBindings(modules, bindingRegistry, usedBindingsByGroup) {
1157
1413
  const reservedBindingKeysByGroup = /* @__PURE__ */ new Map();
1158
1414
  if (!bindingRegistry) {
@@ -1193,16 +1449,11 @@ function claimReservedBindingLocation(reservedBindingKeysByGroup, group, locatio
1193
1449
  function getModuleWGSLBindingDeclarations(module2) {
1194
1450
  const declarations = [];
1195
1451
  const moduleSource = module2.source || "";
1196
- for (const regex of MODULE_WGSL_BINDING_DECLARATION_REGEXES) {
1197
- regex.lastIndex = 0;
1198
- let match;
1199
- while (match = regex.exec(moduleSource)) {
1200
- const isBindingFirst = regex === MODULE_WGSL_BINDING_DECLARATION_REGEXES[0];
1201
- declarations.push({
1202
- name: match[4],
1203
- group: Number(match[isBindingFirst ? 2 : 1])
1204
- });
1205
- }
1452
+ for (const match of getWGSLBindingDeclarationMatches(moduleSource, MODULE_WGSL_BINDING_DECLARATION_REGEXES)) {
1453
+ declarations.push({
1454
+ name: match.name,
1455
+ group: Number(match.groupToken)
1456
+ });
1206
1457
  }
1207
1458
  return declarations;
1208
1459
  }
@@ -1232,10 +1483,27 @@ function allocateAutoBindingLocation(group, usedBindingsByGroup, preferredBindin
1232
1483
  }
1233
1484
  return nextBinding;
1234
1485
  }
1486
+ function allocateApplicationAutoBindingLocation(group, usedBindingsByGroup) {
1487
+ const usedBindings = usedBindingsByGroup.get(group) || /* @__PURE__ */ new Set();
1488
+ let nextBinding = 0;
1489
+ while (usedBindings.has(nextBinding)) {
1490
+ nextBinding++;
1491
+ }
1492
+ return nextBinding;
1493
+ }
1235
1494
  function assertNoUnresolvedAutoBindings(source4) {
1236
- if (/@binding\(\s*auto\s*\)/.test(source4)) {
1237
- throw new Error("Unresolved @binding(auto) remained in assembled WGSL source.");
1495
+ const unresolvedBinding = getFirstWGSLAutoBindingDeclarationMatch(source4, MODULE_WGSL_BINDING_DECLARATION_REGEXES);
1496
+ if (!unresolvedBinding) {
1497
+ return;
1238
1498
  }
1499
+ const moduleName = getWGSLModuleNameAtIndex(source4, unresolvedBinding.index);
1500
+ if (moduleName) {
1501
+ throw new Error(`Unresolved @binding(auto) for module "${moduleName}" binding "${unresolvedBinding.name}" remained in assembled WGSL source.`);
1502
+ }
1503
+ if (isInApplicationWGSLSection(source4, unresolvedBinding.index)) {
1504
+ throw new Error(`Unresolved @binding(auto) for application binding "${unresolvedBinding.name}" remained in assembled WGSL source.`);
1505
+ }
1506
+ throw new Error(`Unresolved @binding(auto) remained in assembled WGSL source near "${formatWGSLSourceSnippet(unresolvedBinding.match)}".`);
1239
1507
  }
1240
1508
  function formatWGSLBindingAssignmentComments(bindingAssignments) {
1241
1509
  if (bindingAssignments.length === 0) {
@@ -1252,6 +1520,24 @@ function formatWGSLBindingAssignmentComments(bindingAssignments) {
1252
1520
  function getBindingRegistryKey(group, moduleName, bindingName) {
1253
1521
  return `${group}:${moduleName}:${bindingName}`;
1254
1522
  }
1523
+ function getWGSLModuleNameAtIndex(source4, index) {
1524
+ const moduleHeaderRegex = /^\/\/ ----- MODULE ([^\n]+) ---------------$/gm;
1525
+ let moduleName;
1526
+ let match;
1527
+ match = moduleHeaderRegex.exec(source4);
1528
+ while (match && match.index <= index) {
1529
+ moduleName = match[1];
1530
+ match = moduleHeaderRegex.exec(source4);
1531
+ }
1532
+ return moduleName;
1533
+ }
1534
+ function isInApplicationWGSLSection(source4, index) {
1535
+ const injectionMarkerIndex = source4.indexOf(INJECT_SHADER_DECLARATIONS);
1536
+ return injectionMarkerIndex >= 0 ? index > injectionMarkerIndex : true;
1537
+ }
1538
+ function formatWGSLSourceSnippet(source4) {
1539
+ return source4.replace(/\s+/g, " ").trim();
1540
+ }
1255
1541
 
1256
1542
  // dist/lib/preprocessor/preprocessor.js
1257
1543
  var DEFINE_NAME_PATTERN = "([a-zA-Z_][a-zA-Z0-9_]*)";
@@ -1533,7 +1819,7 @@ function generateGLSLUniformDeclarations(module2, options) {
1533
1819
  switch (options.uniforms) {
1534
1820
  case "scoped-interface-blocks":
1535
1821
  case "unscoped-interface-blocks":
1536
- glsl.push(`uniform ${capitalize(module2.name)} {`);
1822
+ glsl.push(`layout(std140) uniform ${capitalize(module2.name)} {`);
1537
1823
  break;
1538
1824
  case "uniforms":
1539
1825
  }
@@ -1730,6 +2016,28 @@ function fp64ifyMatrix4(matrix) {
1730
2016
  return matrixFP64;
1731
2017
  }
1732
2018
 
2019
+ // dist/lib/color/normalize-byte-colors.js
2020
+ function resolveUseByteColors(useByteColors, defaultUseByteColors = true) {
2021
+ return useByteColors ?? defaultUseByteColors;
2022
+ }
2023
+ function normalizeByteColor3(color = [0, 0, 0], useByteColors = true) {
2024
+ if (!useByteColors) {
2025
+ return [...color];
2026
+ }
2027
+ return color.map((component) => component / 255);
2028
+ }
2029
+ function normalizeByteColor4(color, useByteColors = true) {
2030
+ const normalizedColor = normalizeByteColor3(color.slice(0, 3), useByteColors);
2031
+ const hasAlpha = Number.isFinite(color[3]);
2032
+ const alpha = hasAlpha ? color[3] : 1;
2033
+ return [
2034
+ normalizedColor[0],
2035
+ normalizedColor[1],
2036
+ normalizedColor[2],
2037
+ useByteColors && hasAlpha ? alpha / 255 : alpha
2038
+ ];
2039
+ }
2040
+
1733
2041
  // dist/modules/math/random/random.js
1734
2042
  var source = (
1735
2043
  /* wgsl */
@@ -1916,7 +2224,7 @@ var fp32 = {
1916
2224
  var fp64arithmeticShader = (
1917
2225
  /* glsl */
1918
2226
  `
1919
- uniform fp64arithmeticUniforms {
2227
+ layout(std140) uniform fp64arithmeticUniforms {
1920
2228
  uniform float ONE;
1921
2229
  uniform float SPLIT;
1922
2230
  } fp64;
@@ -3034,15 +3342,99 @@ var fp64 = {
3034
3342
  fp64ifyMatrix4
3035
3343
  };
3036
3344
 
3345
+ // dist/modules/color/float-colors.js
3346
+ var GLSL_UNIFORMS = (
3347
+ /* glsl */
3348
+ `layout(std140) uniform floatColorsUniforms {
3349
+ float useByteColors;
3350
+ } floatColors;
3351
+
3352
+ vec3 floatColors_normalize(vec3 inputColor) {
3353
+ return floatColors.useByteColors > 0.5 ? inputColor / 255.0 : inputColor;
3354
+ }
3355
+
3356
+ vec4 floatColors_normalize(vec4 inputColor) {
3357
+ return floatColors.useByteColors > 0.5 ? inputColor / 255.0 : inputColor;
3358
+ }
3359
+
3360
+ vec4 floatColors_premultiplyAlpha(vec4 inputColor) {
3361
+ return vec4(inputColor.rgb * inputColor.a, inputColor.a);
3362
+ }
3363
+
3364
+ vec4 floatColors_unpremultiplyAlpha(vec4 inputColor) {
3365
+ return inputColor.a > 0.0 ? vec4(inputColor.rgb / inputColor.a, inputColor.a) : vec4(0.0);
3366
+ }
3367
+
3368
+ vec4 floatColors_premultiply_alpha(vec4 inputColor) {
3369
+ return floatColors_premultiplyAlpha(inputColor);
3370
+ }
3371
+
3372
+ vec4 floatColors_unpremultiply_alpha(vec4 inputColor) {
3373
+ return floatColors_unpremultiplyAlpha(inputColor);
3374
+ }
3375
+ `
3376
+ );
3377
+ var WGSL_UNIFORMS = (
3378
+ /* wgsl */
3379
+ `struct floatColorsUniforms {
3380
+ useByteColors: f32
3381
+ };
3382
+
3383
+ @group(0) @binding(auto) var<uniform> floatColors : floatColorsUniforms;
3384
+
3385
+ fn floatColors_normalize(inputColor: vec3<f32>) -> vec3<f32> {
3386
+ return select(inputColor, inputColor / 255.0, floatColors.useByteColors > 0.5);
3387
+ }
3388
+
3389
+ fn floatColors_normalize4(inputColor: vec4<f32>) -> vec4<f32> {
3390
+ return select(inputColor, inputColor / 255.0, floatColors.useByteColors > 0.5);
3391
+ }
3392
+
3393
+ fn floatColors_premultiplyAlpha(inputColor: vec4<f32>) -> vec4<f32> {
3394
+ return vec4<f32>(inputColor.rgb * inputColor.a, inputColor.a);
3395
+ }
3396
+
3397
+ fn floatColors_unpremultiplyAlpha(inputColor: vec4<f32>) -> vec4<f32> {
3398
+ return select(
3399
+ vec4<f32>(0.0),
3400
+ vec4<f32>(inputColor.rgb / inputColor.a, inputColor.a),
3401
+ inputColor.a > 0.0
3402
+ );
3403
+ }
3404
+
3405
+ fn floatColors_premultiply_alpha(inputColor: vec4<f32>) -> vec4<f32> {
3406
+ return floatColors_premultiplyAlpha(inputColor);
3407
+ }
3408
+
3409
+ fn floatColors_unpremultiply_alpha(inputColor: vec4<f32>) -> vec4<f32> {
3410
+ return floatColors_unpremultiplyAlpha(inputColor);
3411
+ }
3412
+ `
3413
+ );
3414
+ var floatColors = {
3415
+ name: "floatColors",
3416
+ props: {},
3417
+ uniforms: {},
3418
+ vs: GLSL_UNIFORMS,
3419
+ fs: GLSL_UNIFORMS,
3420
+ source: WGSL_UNIFORMS,
3421
+ uniformTypes: {
3422
+ useByteColors: "f32"
3423
+ },
3424
+ defaultUniforms: {
3425
+ useByteColors: true
3426
+ }
3427
+ };
3428
+
3037
3429
  // dist/modules/engine/picking/picking.js
3038
3430
  var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
3039
3431
  var vs = (
3040
3432
  /* glsl */
3041
- `uniform pickingUniforms {
3433
+ `layout(std140) uniform pickingUniforms {
3042
3434
  float isActive;
3043
3435
  float isAttribute;
3044
3436
  float isHighlightActive;
3045
- float useFloatColors;
3437
+ float useByteColors;
3046
3438
  vec3 highlightedObjectColor;
3047
3439
  vec4 highlightColor;
3048
3440
  } picking;
@@ -3051,12 +3443,12 @@ out vec4 picking_vRGBcolor_Avalid;
3051
3443
 
3052
3444
  // Normalize unsigned byte color to 0-1 range
3053
3445
  vec3 picking_normalizeColor(vec3 color) {
3054
- return picking.useFloatColors > 0.5 ? color : color / 255.0;
3446
+ return picking.useByteColors > 0.5 ? color / 255.0 : color;
3055
3447
  }
3056
3448
 
3057
3449
  // Normalize unsigned byte color to 0-1 range
3058
3450
  vec4 picking_normalizeColor(vec4 color) {
3059
- return picking.useFloatColors > 0.5 ? color : color / 255.0;
3451
+ return picking.useByteColors > 0.5 ? color / 255.0 : color;
3060
3452
  }
3061
3453
 
3062
3454
  bool picking_isColorZero(vec3 color) {
@@ -3113,11 +3505,11 @@ void picking_setPickingAttribute(vec3 value) {
3113
3505
  );
3114
3506
  var fs2 = (
3115
3507
  /* glsl */
3116
- `uniform pickingUniforms {
3508
+ `layout(std140) uniform pickingUniforms {
3117
3509
  float isActive;
3118
3510
  float isAttribute;
3119
3511
  float isHighlightActive;
3120
- float useFloatColors;
3512
+ float useByteColors;
3121
3513
  vec3 highlightedObjectColor;
3122
3514
  vec4 highlightColor;
3123
3515
  } picking;
@@ -3179,7 +3571,7 @@ var picking = {
3179
3571
  isActive: "f32",
3180
3572
  isAttribute: "f32",
3181
3573
  isHighlightActive: "f32",
3182
- useFloatColors: "f32",
3574
+ useByteColors: "f32",
3183
3575
  highlightedObjectColor: "vec3<f32>",
3184
3576
  highlightColor: "vec4<f32>"
3185
3577
  },
@@ -3187,7 +3579,7 @@ var picking = {
3187
3579
  isActive: false,
3188
3580
  isAttribute: false,
3189
3581
  isHighlightActive: false,
3190
- useFloatColors: true,
3582
+ useByteColors: true,
3191
3583
  highlightedObjectColor: [0, 0, 0],
3192
3584
  highlightColor: DEFAULT_HIGHLIGHT_COLOR
3193
3585
  },
@@ -3197,6 +3589,7 @@ var picking = {
3197
3589
  };
3198
3590
  function getUniforms(opts = {}, prevUniforms) {
3199
3591
  const uniforms = {};
3592
+ const useByteColors = resolveUseByteColors(opts.useByteColors, true);
3200
3593
  if (opts.highlightedObjectColor === void 0) {
3201
3594
  } else if (opts.highlightedObjectColor === null) {
3202
3595
  uniforms.isHighlightActive = false;
@@ -3206,18 +3599,14 @@ function getUniforms(opts = {}, prevUniforms) {
3206
3599
  uniforms.highlightedObjectColor = highlightedObjectColor;
3207
3600
  }
3208
3601
  if (opts.highlightColor) {
3209
- const color = Array.from(opts.highlightColor, (x) => x / 255);
3210
- if (!Number.isFinite(color[3])) {
3211
- color[3] = 1;
3212
- }
3213
- uniforms.highlightColor = color;
3602
+ uniforms.highlightColor = normalizeByteColor4(opts.highlightColor, useByteColors);
3214
3603
  }
3215
3604
  if (opts.isActive !== void 0) {
3216
3605
  uniforms.isActive = Boolean(opts.isActive);
3217
3606
  uniforms.isAttribute = Boolean(opts.isAttribute);
3218
3607
  }
3219
- if (opts.useFloatColors !== void 0) {
3220
- uniforms.useFloatColors = Boolean(opts.useFloatColors);
3608
+ if (opts.useByteColors !== void 0) {
3609
+ uniforms.useByteColors = Boolean(opts.useByteColors);
3221
3610
  }
3222
3611
  return uniforms;
3223
3612
  }
@@ -3245,7 +3634,7 @@ fn getSkinMatrix(weights: vec4f, joints: vec4u) -> mat4x4<f32> {
3245
3634
  var vs2 = (
3246
3635
  /* glsl */
3247
3636
  `
3248
- uniform skinUniforms {
3637
+ layout(std140) uniform skinUniforms {
3249
3638
  mat4 jointMatrix[SKIN_MAX_JOINTS];
3250
3639
  } skin;
3251
3640
 
@@ -3354,7 +3743,7 @@ struct UniformLight {
3354
3743
  vec2 coneCos;
3355
3744
  };
3356
3745
 
3357
- uniform lightingUniforms {
3746
+ layout(std140) uniform lightingUniforms {
3358
3747
  int enabled;
3359
3748
  int directionalLightCount;
3360
3749
  int pointLightCount;
@@ -3490,7 +3879,6 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
3490
3879
 
3491
3880
  // dist/modules/lighting/lights/lighting.js
3492
3881
  var MAX_LIGHTS = 5;
3493
- var COLOR_FACTOR = 255;
3494
3882
  var LIGHT_UNIFORM_TYPE = {
3495
3883
  color: "vec3<f32>",
3496
3884
  position: "vec3<f32>",
@@ -3529,7 +3917,7 @@ function getUniforms2(props, _prevUniforms = {}) {
3529
3917
  if (props.lights) {
3530
3918
  props = { ...props, ...extractLightTypes(props.lights), lights: void 0 };
3531
3919
  }
3532
- const { ambientLight, pointLights, spotLights, directionalLights } = props || {};
3920
+ const { useByteColors, ambientLight, pointLights, spotLights, directionalLights } = props || {};
3533
3921
  const hasLights = ambientLight || pointLights && pointLights.length > 0 || spotLights && spotLights.length > 0 || directionalLights && directionalLights.length > 0;
3534
3922
  if (!hasLights) {
3535
3923
  return {
@@ -3539,14 +3927,20 @@ function getUniforms2(props, _prevUniforms = {}) {
3539
3927
  }
3540
3928
  const uniforms = {
3541
3929
  ...createDefaultLightingUniforms(),
3542
- ...getLightSourceUniforms({ ambientLight, pointLights, spotLights, directionalLights })
3930
+ ...getLightSourceUniforms({
3931
+ useByteColors,
3932
+ ambientLight,
3933
+ pointLights,
3934
+ spotLights,
3935
+ directionalLights
3936
+ })
3543
3937
  };
3544
3938
  if (props.enabled !== void 0) {
3545
3939
  uniforms.enabled = props.enabled ? 1 : 0;
3546
3940
  }
3547
3941
  return uniforms;
3548
3942
  }
3549
- function getLightSourceUniforms({ ambientLight, pointLights = [], spotLights = [], directionalLights = [] }) {
3943
+ function getLightSourceUniforms({ useByteColors, ambientLight, pointLights = [], spotLights = [], directionalLights = [] }) {
3550
3944
  const lights = createDefaultLightUniforms();
3551
3945
  let currentLight = 0;
3552
3946
  let pointLightCount = 0;
@@ -3558,7 +3952,7 @@ function getLightSourceUniforms({ ambientLight, pointLights = [], spotLights = [
3558
3952
  }
3559
3953
  lights[currentLight] = {
3560
3954
  ...lights[currentLight],
3561
- color: convertColor(pointLight),
3955
+ color: convertColor(pointLight, useByteColors),
3562
3956
  position: pointLight.position,
3563
3957
  attenuation: pointLight.attenuation || [1, 0, 0]
3564
3958
  };
@@ -3571,7 +3965,7 @@ function getLightSourceUniforms({ ambientLight, pointLights = [], spotLights = [
3571
3965
  }
3572
3966
  lights[currentLight] = {
3573
3967
  ...lights[currentLight],
3574
- color: convertColor(spotLight),
3968
+ color: convertColor(spotLight, useByteColors),
3575
3969
  position: spotLight.position,
3576
3970
  direction: spotLight.direction,
3577
3971
  attenuation: spotLight.attenuation || [1, 0, 0],
@@ -3586,7 +3980,7 @@ function getLightSourceUniforms({ ambientLight, pointLights = [], spotLights = [
3586
3980
  }
3587
3981
  lights[currentLight] = {
3588
3982
  ...lights[currentLight],
3589
- color: convertColor(directionalLight),
3983
+ color: convertColor(directionalLight, useByteColors),
3590
3984
  direction: directionalLight.direction
3591
3985
  };
3592
3986
  currentLight++;
@@ -3596,7 +3990,7 @@ function getLightSourceUniforms({ ambientLight, pointLights = [], spotLights = [
3596
3990
  import_core3.log.warn(`MAX_LIGHTS exceeded, truncating to ${MAX_LIGHTS}`)();
3597
3991
  }
3598
3992
  return {
3599
- ambientColor: convertColor(ambientLight),
3993
+ ambientColor: convertColor(ambientLight, useByteColors),
3600
3994
  directionalLightCount,
3601
3995
  pointLightCount,
3602
3996
  spotLightCount,
@@ -3625,9 +4019,10 @@ function extractLightTypes(lights) {
3625
4019
  }
3626
4020
  return lightSources;
3627
4021
  }
3628
- function convertColor(colorDef = {}) {
4022
+ function convertColor(colorDef = {}, useByteColors) {
3629
4023
  const { color = [0, 0, 0], intensity = 1 } = colorDef;
3630
- return color.map((component) => component * intensity / COLOR_FACTOR);
4024
+ const normalizedColor = normalizeByteColor3(color, resolveUseByteColors(useByteColors, true));
4025
+ return normalizedColor.map((component) => component * intensity);
3631
4026
  }
3632
4027
  function createDefaultLightingUniforms() {
3633
4028
  return {
@@ -3695,8 +4090,7 @@ var ibl = {
3695
4090
  // dist/modules/lighting/no-material/dirlight.js
3696
4091
  var SOURCE_WGSL = (
3697
4092
  /* WGSL */
3698
- `
3699
- struct dirlightUniforms {
4093
+ `struct dirlightUniforms {
3700
4094
  lightDirection: vec3<f32>,
3701
4095
  };
3702
4096
 
@@ -3734,7 +4128,7 @@ void dirlight_setNormal(vec3 normal) {
3734
4128
  );
3735
4129
  var FS_GLSL = (
3736
4130
  /* glsl */
3737
- `uniform dirlightUniforms {
4131
+ `layout(std140) uniform dirlightUniforms {
3738
4132
  vec3 lightDirection;
3739
4133
  } dirlight;
3740
4134
 
@@ -3855,7 +4249,7 @@ fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, p
3855
4249
  // dist/modules/lighting/lambert-material/lambert-shaders-glsl.js
3856
4250
  var LAMBERT_VS = (
3857
4251
  /* glsl */
3858
- `uniform lambertMaterialUniforms {
4252
+ `layout(std140) uniform lambertMaterialUniforms {
3859
4253
  uniform bool unlit;
3860
4254
  uniform float ambient;
3861
4255
  uniform float diffuse;
@@ -3864,7 +4258,7 @@ var LAMBERT_VS = (
3864
4258
  );
3865
4259
  var LAMBERT_FS = (
3866
4260
  /* glsl */
3867
- `uniform lambertMaterialUniforms {
4261
+ `layout(std140) uniform lambertMaterialUniforms {
3868
4262
  uniform bool unlit;
3869
4263
  uniform float ambient;
3870
4264
  uniform float diffuse;
@@ -3944,7 +4338,7 @@ var lambertMaterial = {
3944
4338
  // dist/modules/lighting/phong-material/phong-shaders-glsl.js
3945
4339
  var PHONG_VS = (
3946
4340
  /* glsl */
3947
- `uniform phongMaterialUniforms {
4341
+ `layout(std140) uniform phongMaterialUniforms {
3948
4342
  uniform bool unlit;
3949
4343
  uniform float ambient;
3950
4344
  uniform float diffuse;
@@ -3955,7 +4349,7 @@ var PHONG_VS = (
3955
4349
  );
3956
4350
  var PHONG_FS = (
3957
4351
  /* glsl */
3958
- `uniform phongMaterialUniforms {
4352
+ `layout(std140) uniform phongMaterialUniforms {
3959
4353
  uniform bool unlit;
3960
4354
  uniform float ambient;
3961
4355
  uniform float diffuse;
@@ -4159,19 +4553,21 @@ var gouraudMaterial = {
4159
4553
  ambient: "f32",
4160
4554
  diffuse: "f32",
4161
4555
  shininess: "f32",
4162
- specularColor: "vec3<f32>"
4556
+ specularColor: "vec3<f32>",
4557
+ useByteColors: "i32"
4163
4558
  },
4164
4559
  defaultUniforms: {
4165
4560
  unlit: false,
4166
4561
  ambient: 0.35,
4167
4562
  diffuse: 0.6,
4168
4563
  shininess: 32,
4169
- specularColor: [0.15, 0.15, 0.15]
4564
+ specularColor: [0.15, 0.15, 0.15],
4565
+ useByteColors: true
4170
4566
  },
4171
4567
  getUniforms(props) {
4172
4568
  const uniforms = { ...props };
4173
4569
  if (uniforms.specularColor) {
4174
- uniforms.specularColor = uniforms.specularColor.map((x) => x / 255);
4570
+ uniforms.specularColor = normalizeByteColor3(uniforms.specularColor, resolveUseByteColors(uniforms.useByteColors, true));
4175
4571
  }
4176
4572
  return { ...gouraudMaterial.defaultUniforms, ...uniforms };
4177
4573
  }
@@ -4195,19 +4591,21 @@ var phongMaterial = {
4195
4591
  ambient: "f32",
4196
4592
  diffuse: "f32",
4197
4593
  shininess: "f32",
4198
- specularColor: "vec3<f32>"
4594
+ specularColor: "vec3<f32>",
4595
+ useByteColors: "i32"
4199
4596
  },
4200
4597
  defaultUniforms: {
4201
4598
  unlit: false,
4202
4599
  ambient: 0.35,
4203
4600
  diffuse: 0.6,
4204
4601
  shininess: 32,
4205
- specularColor: [0.15, 0.15, 0.15]
4602
+ specularColor: [0.15, 0.15, 0.15],
4603
+ useByteColors: true
4206
4604
  },
4207
4605
  getUniforms(props) {
4208
4606
  const uniforms = { ...props };
4209
4607
  if (uniforms.specularColor) {
4210
- uniforms.specularColor = uniforms.specularColor.map((x) => x / 255);
4608
+ uniforms.specularColor = normalizeByteColor3(uniforms.specularColor, resolveUseByteColors(uniforms.useByteColors, true));
4211
4609
  }
4212
4610
  return { ...phongMaterial.defaultUniforms, ...uniforms };
4213
4611
  }
@@ -4217,7 +4615,8 @@ var phongMaterial = {
4217
4615
  var vs3 = (
4218
4616
  /* glsl */
4219
4617
  `out vec3 pbr_vPosition;
4220
- out vec2 pbr_vUV;
4618
+ out vec2 pbr_vUV0;
4619
+ out vec2 pbr_vUV1;
4221
4620
 
4222
4621
  #ifdef HAS_NORMALS
4223
4622
  # ifdef HAS_TANGENTS
@@ -4227,7 +4626,13 @@ out vec3 pbr_vNormal;
4227
4626
  # endif
4228
4627
  #endif
4229
4628
 
4230
- void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv)
4629
+ void pbr_setPositionNormalTangentUV(
4630
+ vec4 position,
4631
+ vec4 normal,
4632
+ vec4 tangent,
4633
+ vec2 uv0,
4634
+ vec2 uv1
4635
+ )
4231
4636
  {
4232
4637
  vec4 pos = pbrProjection.modelMatrix * position;
4233
4638
  pbr_vPosition = vec3(pos.xyz) / pos.w;
@@ -4244,10 +4649,12 @@ void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, ve
4244
4649
  #endif
4245
4650
 
4246
4651
  #ifdef HAS_UV
4247
- pbr_vUV = uv;
4652
+ pbr_vUV0 = uv0;
4248
4653
  #else
4249
- pbr_vUV = vec2(0.,0.);
4654
+ pbr_vUV0 = vec2(0.,0.);
4250
4655
  #endif
4656
+
4657
+ pbr_vUV1 = uv1;
4251
4658
  }
4252
4659
  `
4253
4660
  );
@@ -4255,7 +4662,7 @@ var fs4 = (
4255
4662
  /* glsl */
4256
4663
  `precision highp float;
4257
4664
 
4258
- uniform pbrMaterialUniforms {
4665
+ layout(std140) uniform pbrMaterialUniforms {
4259
4666
  // Material is unlit
4260
4667
  bool unlit;
4261
4668
 
@@ -4323,6 +4730,41 @@ uniform pbrMaterialUniforms {
4323
4730
  vec4 scaleDiffBaseMR;
4324
4731
  vec4 scaleFGDSpec;
4325
4732
  // #endif
4733
+
4734
+ int baseColorUVSet;
4735
+ mat3 baseColorUVTransform;
4736
+ int metallicRoughnessUVSet;
4737
+ mat3 metallicRoughnessUVTransform;
4738
+ int normalUVSet;
4739
+ mat3 normalUVTransform;
4740
+ int occlusionUVSet;
4741
+ mat3 occlusionUVTransform;
4742
+ int emissiveUVSet;
4743
+ mat3 emissiveUVTransform;
4744
+ int specularColorUVSet;
4745
+ mat3 specularColorUVTransform;
4746
+ int specularIntensityUVSet;
4747
+ mat3 specularIntensityUVTransform;
4748
+ int transmissionUVSet;
4749
+ mat3 transmissionUVTransform;
4750
+ int thicknessUVSet;
4751
+ mat3 thicknessUVTransform;
4752
+ int clearcoatUVSet;
4753
+ mat3 clearcoatUVTransform;
4754
+ int clearcoatRoughnessUVSet;
4755
+ mat3 clearcoatRoughnessUVTransform;
4756
+ int clearcoatNormalUVSet;
4757
+ mat3 clearcoatNormalUVTransform;
4758
+ int sheenColorUVSet;
4759
+ mat3 sheenColorUVTransform;
4760
+ int sheenRoughnessUVSet;
4761
+ mat3 sheenRoughnessUVTransform;
4762
+ int iridescenceUVSet;
4763
+ mat3 iridescenceUVTransform;
4764
+ int iridescenceThicknessUVSet;
4765
+ mat3 iridescenceThicknessUVTransform;
4766
+ int anisotropyUVSet;
4767
+ mat3 anisotropyUVTransform;
4326
4768
  } pbrMaterial;
4327
4769
 
4328
4770
  // Samplers
@@ -4380,7 +4822,8 @@ uniform sampler2D pbr_anisotropySampler;
4380
4822
  // Inputs from vertex shader
4381
4823
 
4382
4824
  in vec3 pbr_vPosition;
4383
- in vec2 pbr_vUV;
4825
+ in vec2 pbr_vUV0;
4826
+ in vec2 pbr_vUV1;
4384
4827
 
4385
4828
  #ifdef HAS_NORMALS
4386
4829
  #ifdef HAS_TANGENTS
@@ -4430,14 +4873,20 @@ vec4 SRGBtoLINEAR(vec4 srgbIn)
4430
4873
  #endif //MANUAL_SRGB
4431
4874
  }
4432
4875
 
4876
+ vec2 getMaterialUV(int uvSet, mat3 uvTransform)
4877
+ {
4878
+ vec2 baseUV = uvSet == 1 ? pbr_vUV1 : pbr_vUV0;
4879
+ return (uvTransform * vec3(baseUV, 1.0)).xy;
4880
+ }
4881
+
4433
4882
  // Build the tangent basis from interpolated attributes or screen-space derivatives.
4434
- mat3 getTBN()
4883
+ mat3 getTBN(vec2 uv)
4435
4884
  {
4436
4885
  #ifndef HAS_TANGENTS
4437
4886
  vec3 pos_dx = dFdx(pbr_vPosition);
4438
4887
  vec3 pos_dy = dFdy(pbr_vPosition);
4439
- vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0));
4440
- vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0));
4888
+ vec3 tex_dx = dFdx(vec3(uv, 0.0));
4889
+ vec3 tex_dy = dFdy(vec3(uv, 0.0));
4441
4890
  vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
4442
4891
 
4443
4892
  #ifdef HAS_NORMALS
@@ -4458,16 +4907,16 @@ mat3 getTBN()
4458
4907
 
4459
4908
  // Find the normal for this fragment, pulling either from a predefined normal map
4460
4909
  // or from the interpolated mesh normal and tangent attributes.
4461
- vec3 getMappedNormal(sampler2D normalSampler, mat3 tbn, float normalScale)
4910
+ vec3 getMappedNormal(sampler2D normalSampler, mat3 tbn, float normalScale, vec2 uv)
4462
4911
  {
4463
- vec3 n = texture(normalSampler, pbr_vUV).rgb;
4912
+ vec3 n = texture(normalSampler, uv).rgb;
4464
4913
  return normalize(tbn * ((2.0 * n - 1.0) * vec3(normalScale, normalScale, 1.0)));
4465
4914
  }
4466
4915
 
4467
- vec3 getNormal(mat3 tbn)
4916
+ vec3 getNormal(mat3 tbn, vec2 uv)
4468
4917
  {
4469
4918
  #ifdef HAS_NORMALMAP
4470
- vec3 n = getMappedNormal(pbr_normalSampler, tbn, pbrMaterial.normalScale);
4919
+ vec3 n = getMappedNormal(pbr_normalSampler, tbn, pbrMaterial.normalScale, uv);
4471
4920
  #else
4472
4921
  // The tbn matrix is linearly interpolated, so we need to re-normalize
4473
4922
  vec3 n = normalize(tbn[2].xyz);
@@ -4476,10 +4925,10 @@ vec3 getNormal(mat3 tbn)
4476
4925
  return n;
4477
4926
  }
4478
4927
 
4479
- vec3 getClearcoatNormal(mat3 tbn, vec3 baseNormal)
4928
+ vec3 getClearcoatNormal(mat3 tbn, vec3 baseNormal, vec2 uv)
4480
4929
  {
4481
4930
  #ifdef HAS_CLEARCOATNORMALMAP
4482
- return getMappedNormal(pbr_clearcoatNormalSampler, tbn, 1.0);
4931
+ return getMappedNormal(pbr_clearcoatNormalSampler, tbn, 1.0, uv);
4483
4932
  #else
4484
4933
  return baseNormal;
4485
4934
  #endif
@@ -4767,9 +5216,61 @@ vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
4767
5216
 
4768
5217
  vec4 pbr_filterColor(vec4 colorUnused)
4769
5218
  {
5219
+ vec2 baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
5220
+ vec2 metallicRoughnessUV = getMaterialUV(
5221
+ pbrMaterial.metallicRoughnessUVSet,
5222
+ pbrMaterial.metallicRoughnessUVTransform
5223
+ );
5224
+ vec2 normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
5225
+ vec2 occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);
5226
+ vec2 emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);
5227
+ vec2 specularColorUV = getMaterialUV(
5228
+ pbrMaterial.specularColorUVSet,
5229
+ pbrMaterial.specularColorUVTransform
5230
+ );
5231
+ vec2 specularIntensityUV = getMaterialUV(
5232
+ pbrMaterial.specularIntensityUVSet,
5233
+ pbrMaterial.specularIntensityUVTransform
5234
+ );
5235
+ vec2 transmissionUV = getMaterialUV(
5236
+ pbrMaterial.transmissionUVSet,
5237
+ pbrMaterial.transmissionUVTransform
5238
+ );
5239
+ vec2 thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);
5240
+ vec2 clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);
5241
+ vec2 clearcoatRoughnessUV = getMaterialUV(
5242
+ pbrMaterial.clearcoatRoughnessUVSet,
5243
+ pbrMaterial.clearcoatRoughnessUVTransform
5244
+ );
5245
+ vec2 clearcoatNormalUV = getMaterialUV(
5246
+ pbrMaterial.clearcoatNormalUVSet,
5247
+ pbrMaterial.clearcoatNormalUVTransform
5248
+ );
5249
+ vec2 sheenColorUV = getMaterialUV(
5250
+ pbrMaterial.sheenColorUVSet,
5251
+ pbrMaterial.sheenColorUVTransform
5252
+ );
5253
+ vec2 sheenRoughnessUV = getMaterialUV(
5254
+ pbrMaterial.sheenRoughnessUVSet,
5255
+ pbrMaterial.sheenRoughnessUVTransform
5256
+ );
5257
+ vec2 iridescenceUV = getMaterialUV(
5258
+ pbrMaterial.iridescenceUVSet,
5259
+ pbrMaterial.iridescenceUVTransform
5260
+ );
5261
+ vec2 iridescenceThicknessUV = getMaterialUV(
5262
+ pbrMaterial.iridescenceThicknessUVSet,
5263
+ pbrMaterial.iridescenceThicknessUVTransform
5264
+ );
5265
+ vec2 anisotropyUV = getMaterialUV(
5266
+ pbrMaterial.anisotropyUVSet,
5267
+ pbrMaterial.anisotropyUVTransform
5268
+ );
5269
+
4770
5270
  // The albedo may be defined from a base texture or a flat color
4771
5271
  #ifdef HAS_BASECOLORMAP
4772
- vec4 baseColor = SRGBtoLINEAR(texture(pbr_baseColorSampler, pbr_vUV)) * pbrMaterial.baseColorFactor;
5272
+ vec4 baseColor =
5273
+ SRGBtoLINEAR(texture(pbr_baseColorSampler, baseColorUV)) * pbrMaterial.baseColorFactor;
4773
5274
  #else
4774
5275
  vec4 baseColor = pbrMaterial.baseColorFactor;
4775
5276
  #endif
@@ -4796,14 +5297,14 @@ vec4 pbr_filterColor(vec4 colorUnused)
4796
5297
  #ifdef HAS_METALROUGHNESSMAP
4797
5298
  // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
4798
5299
  // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
4799
- vec4 mrSample = texture(pbr_metallicRoughnessSampler, pbr_vUV);
5300
+ vec4 mrSample = texture(pbr_metallicRoughnessSampler, metallicRoughnessUV);
4800
5301
  perceptualRoughness = mrSample.g * perceptualRoughness;
4801
5302
  metallic = mrSample.b * metallic;
4802
5303
  #endif
4803
5304
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
4804
5305
  metallic = clamp(metallic, 0.0, 1.0);
4805
- mat3 tbn = getTBN();
4806
- vec3 n = getNormal(tbn); // normal at surface point
5306
+ mat3 tbn = getTBN(normalUV);
5307
+ vec3 n = getNormal(tbn, normalUV); // normal at surface point
4807
5308
  vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
4808
5309
  float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
4809
5310
  #ifdef USE_MATERIAL_EXTENSIONS
@@ -4904,7 +5405,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
4904
5405
 
4905
5406
  #ifdef HAS_OCCLUSIONMAP
4906
5407
  if (pbrMaterial.occlusionMapEnabled) {
4907
- float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
5408
+ float ao = texture(pbr_occlusionSampler, occlusionUV).r;
4908
5409
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
4909
5410
  }
4910
5411
  #endif
@@ -4912,7 +5413,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
4912
5413
  vec3 emissive = pbrMaterial.emissiveFactor;
4913
5414
  #ifdef HAS_EMISSIVEMAP
4914
5415
  if (pbrMaterial.emissiveMapEnabled) {
4915
- emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
5416
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, emissiveUV)).rgb;
4916
5417
  }
4917
5418
  #endif
4918
5419
  color += emissive * pbrMaterial.emissiveStrength;
@@ -4929,55 +5430,55 @@ vec4 pbr_filterColor(vec4 colorUnused)
4929
5430
  float specularIntensity = pbrMaterial.specularIntensityFactor;
4930
5431
  #ifdef HAS_SPECULARINTENSITYMAP
4931
5432
  if (pbrMaterial.specularIntensityMapEnabled) {
4932
- specularIntensity *= texture(pbr_specularIntensitySampler, pbr_vUV).a;
5433
+ specularIntensity *= texture(pbr_specularIntensitySampler, specularIntensityUV).a;
4933
5434
  }
4934
5435
  #endif
4935
5436
 
4936
5437
  vec3 specularFactor = pbrMaterial.specularColorFactor;
4937
5438
  #ifdef HAS_SPECULARCOLORMAP
4938
5439
  if (pbrMaterial.specularColorMapEnabled) {
4939
- specularFactor *= SRGBtoLINEAR(texture(pbr_specularColorSampler, pbr_vUV)).rgb;
5440
+ specularFactor *= SRGBtoLINEAR(texture(pbr_specularColorSampler, specularColorUV)).rgb;
4940
5441
  }
4941
5442
  #endif
4942
5443
 
4943
5444
  transmission = pbrMaterial.transmissionFactor;
4944
5445
  #ifdef HAS_TRANSMISSIONMAP
4945
5446
  if (pbrMaterial.transmissionMapEnabled) {
4946
- transmission *= texture(pbr_transmissionSampler, pbr_vUV).r;
5447
+ transmission *= texture(pbr_transmissionSampler, transmissionUV).r;
4947
5448
  }
4948
5449
  #endif
4949
5450
  transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);
4950
5451
  float thickness = max(pbrMaterial.thicknessFactor, 0.0);
4951
5452
  #ifdef HAS_THICKNESSMAP
4952
- thickness *= texture(pbr_thicknessSampler, pbr_vUV).g;
5453
+ thickness *= texture(pbr_thicknessSampler, thicknessUV).g;
4953
5454
  #endif
4954
5455
 
4955
5456
  float clearcoatFactor = pbrMaterial.clearcoatFactor;
4956
5457
  float clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;
4957
5458
  #ifdef HAS_CLEARCOATMAP
4958
5459
  if (pbrMaterial.clearcoatMapEnabled) {
4959
- clearcoatFactor *= texture(pbr_clearcoatSampler, pbr_vUV).r;
5460
+ clearcoatFactor *= texture(pbr_clearcoatSampler, clearcoatUV).r;
4960
5461
  }
4961
5462
  #endif
4962
5463
  #ifdef HAS_CLEARCOATROUGHNESSMAP
4963
5464
  if (pbrMaterial.clearcoatRoughnessMapEnabled) {
4964
- clearcoatRoughness *= texture(pbr_clearcoatRoughnessSampler, pbr_vUV).g;
5465
+ clearcoatRoughness *= texture(pbr_clearcoatRoughnessSampler, clearcoatRoughnessUV).g;
4965
5466
  }
4966
5467
  #endif
4967
5468
  clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
4968
5469
  clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
4969
- vec3 clearcoatNormal = getClearcoatNormal(tbn, n);
5470
+ vec3 clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);
4970
5471
 
4971
5472
  vec3 sheenColor = pbrMaterial.sheenColorFactor;
4972
5473
  float sheenRoughness = pbrMaterial.sheenRoughnessFactor;
4973
5474
  #ifdef HAS_SHEENCOLORMAP
4974
5475
  if (pbrMaterial.sheenColorMapEnabled) {
4975
- sheenColor *= SRGBtoLINEAR(texture(pbr_sheenColorSampler, pbr_vUV)).rgb;
5476
+ sheenColor *= SRGBtoLINEAR(texture(pbr_sheenColorSampler, sheenColorUV)).rgb;
4976
5477
  }
4977
5478
  #endif
4978
5479
  #ifdef HAS_SHEENROUGHNESSMAP
4979
5480
  if (pbrMaterial.sheenRoughnessMapEnabled) {
4980
- sheenRoughness *= texture(pbr_sheenRoughnessSampler, pbr_vUV).a;
5481
+ sheenRoughness *= texture(pbr_sheenRoughnessSampler, sheenRoughnessUV).a;
4981
5482
  }
4982
5483
  #endif
4983
5484
  sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);
@@ -4985,7 +5486,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
4985
5486
  float iridescence = pbrMaterial.iridescenceFactor;
4986
5487
  #ifdef HAS_IRIDESCENCEMAP
4987
5488
  if (pbrMaterial.iridescenceMapEnabled) {
4988
- iridescence *= texture(pbr_iridescenceSampler, pbr_vUV).r;
5489
+ iridescence *= texture(pbr_iridescenceSampler, iridescenceUV).r;
4989
5490
  }
4990
5491
  #endif
4991
5492
  iridescence = clamp(iridescence, 0.0, 1.0);
@@ -4998,7 +5499,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
4998
5499
  iridescenceThickness = mix(
4999
5500
  pbrMaterial.iridescenceThicknessRange.x,
5000
5501
  pbrMaterial.iridescenceThicknessRange.y,
5001
- texture(pbr_iridescenceThicknessSampler, pbr_vUV).g
5502
+ texture(pbr_iridescenceThicknessSampler, iridescenceThicknessUV).g
5002
5503
  );
5003
5504
  #endif
5004
5505
 
@@ -5006,7 +5507,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
5006
5507
  vec2 anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);
5007
5508
  #ifdef HAS_ANISOTROPYMAP
5008
5509
  if (pbrMaterial.anisotropyMapEnabled) {
5009
- vec3 anisotropySample = texture(pbr_anisotropySampler, pbr_vUV).rgb;
5510
+ vec3 anisotropySample = texture(pbr_anisotropySampler, anisotropyUV).rgb;
5010
5511
  anisotropyStrength *= anisotropySample.b;
5011
5512
  vec2 mappedDirection = anisotropySample.rg * 2.0 - 1.0;
5012
5513
  if (length(mappedDirection) > 0.0001) {
@@ -5169,7 +5670,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
5169
5670
  // Apply optional PBR terms for additional (optional) shading
5170
5671
  #ifdef HAS_OCCLUSIONMAP
5171
5672
  if (pbrMaterial.occlusionMapEnabled) {
5172
- float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
5673
+ float ao = texture(pbr_occlusionSampler, occlusionUV).r;
5173
5674
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
5174
5675
  }
5175
5676
  #endif
@@ -5177,7 +5678,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
5177
5678
  vec3 emissive = pbrMaterial.emissiveFactor;
5178
5679
  #ifdef HAS_EMISSIVEMAP
5179
5680
  if (pbrMaterial.emissiveMapEnabled) {
5180
- emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
5681
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, emissiveUV)).rgb;
5181
5682
  }
5182
5683
  #endif
5183
5684
  color += emissive * pbrMaterial.emissiveStrength;
@@ -5215,14 +5716,21 @@ var source3 = (
5215
5716
  /* wgsl */
5216
5717
  `struct PBRFragmentInputs {
5217
5718
  pbr_vPosition: vec3f,
5218
- pbr_vUV: vec2f,
5719
+ pbr_vUV0: vec2f,
5720
+ pbr_vUV1: vec2f,
5219
5721
  pbr_vTBN: mat3x3f,
5220
5722
  pbr_vNormal: vec3f
5221
5723
  };
5222
5724
 
5223
5725
  var<private> fragmentInputs: PBRFragmentInputs;
5224
5726
 
5225
- fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f, uv: vec2f)
5727
+ fn pbr_setPositionNormalTangentUV(
5728
+ position: vec4f,
5729
+ normal: vec4f,
5730
+ tangent: vec4f,
5731
+ uv0: vec2f,
5732
+ uv1: vec2f
5733
+ )
5226
5734
  {
5227
5735
  var pos: vec4f = pbrProjection.modelMatrix * position;
5228
5736
  fragmentInputs.pbr_vPosition = pos.xyz / pos.w;
@@ -5232,7 +5740,8 @@ fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f
5232
5740
  vec3f(0.0, 1.0, 0.0),
5233
5741
  vec3f(0.0, 0.0, 1.0)
5234
5742
  );
5235
- fragmentInputs.pbr_vUV = vec2f(0.0, 0.0);
5743
+ fragmentInputs.pbr_vUV0 = vec2f(0.0, 0.0);
5744
+ fragmentInputs.pbr_vUV1 = uv1;
5236
5745
 
5237
5746
  #ifdef HAS_NORMALS
5238
5747
  let normalW: vec3f = normalize((pbrProjection.normalMatrix * vec4f(normal.xyz, 0.0)).xyz);
@@ -5245,7 +5754,7 @@ fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f
5245
5754
  #endif
5246
5755
 
5247
5756
  #ifdef HAS_UV
5248
- fragmentInputs.pbr_vUV = uv;
5757
+ fragmentInputs.pbr_vUV0 = uv0;
5249
5758
  #endif
5250
5759
  }
5251
5760
 
@@ -5317,6 +5826,41 @@ struct pbrMaterialUniforms {
5317
5826
  scaleDiffBaseMR: vec4f,
5318
5827
  scaleFGDSpec: vec4f,
5319
5828
  // #endif
5829
+
5830
+ baseColorUVSet: i32,
5831
+ baseColorUVTransform: mat3x3f,
5832
+ metallicRoughnessUVSet: i32,
5833
+ metallicRoughnessUVTransform: mat3x3f,
5834
+ normalUVSet: i32,
5835
+ normalUVTransform: mat3x3f,
5836
+ occlusionUVSet: i32,
5837
+ occlusionUVTransform: mat3x3f,
5838
+ emissiveUVSet: i32,
5839
+ emissiveUVTransform: mat3x3f,
5840
+ specularColorUVSet: i32,
5841
+ specularColorUVTransform: mat3x3f,
5842
+ specularIntensityUVSet: i32,
5843
+ specularIntensityUVTransform: mat3x3f,
5844
+ transmissionUVSet: i32,
5845
+ transmissionUVTransform: mat3x3f,
5846
+ thicknessUVSet: i32,
5847
+ thicknessUVTransform: mat3x3f,
5848
+ clearcoatUVSet: i32,
5849
+ clearcoatUVTransform: mat3x3f,
5850
+ clearcoatRoughnessUVSet: i32,
5851
+ clearcoatRoughnessUVTransform: mat3x3f,
5852
+ clearcoatNormalUVSet: i32,
5853
+ clearcoatNormalUVTransform: mat3x3f,
5854
+ sheenColorUVSet: i32,
5855
+ sheenColorUVTransform: mat3x3f,
5856
+ sheenRoughnessUVSet: i32,
5857
+ sheenRoughnessUVTransform: mat3x3f,
5858
+ iridescenceUVSet: i32,
5859
+ iridescenceUVTransform: mat3x3f,
5860
+ iridescenceThicknessUVSet: i32,
5861
+ iridescenceThicknessUVTransform: mat3x3f,
5862
+ anisotropyUVSet: i32,
5863
+ anisotropyUVTransform: mat3x3f,
5320
5864
  }
5321
5865
 
5322
5866
  @group(3) @binding(auto) var<uniform> pbrMaterial : pbrMaterialUniforms;
@@ -5430,13 +5974,22 @@ fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
5430
5974
  return vec4f(linOut, srgbIn.w);
5431
5975
  }
5432
5976
 
5977
+ fn getMaterialUV(uvSet: i32, uvTransform: mat3x3f) -> vec2f
5978
+ {
5979
+ var baseUV = fragmentInputs.pbr_vUV0;
5980
+ if (uvSet == 1) {
5981
+ baseUV = fragmentInputs.pbr_vUV1;
5982
+ }
5983
+ return (uvTransform * vec3f(baseUV, 1.0)).xy;
5984
+ }
5985
+
5433
5986
  // Build the tangent basis from interpolated attributes or screen-space derivatives.
5434
- fn getTBN() -> mat3x3f
5987
+ fn getTBN(uv: vec2f) -> mat3x3f
5435
5988
  {
5436
5989
  let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);
5437
5990
  let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);
5438
- let tex_dx: vec3f = dpdx(vec3f(fragmentInputs.pbr_vUV, 0.0));
5439
- let tex_dy: vec3f = dpdy(vec3f(fragmentInputs.pbr_vUV, 0.0));
5991
+ let tex_dx: vec3f = dpdx(vec3f(uv, 0.0));
5992
+ let tex_dy: vec3f = dpdy(vec3f(uv, 0.0));
5440
5993
  var t: vec3f = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y);
5441
5994
 
5442
5995
  var ng: vec3f = cross(pos_dx, pos_dy);
@@ -5459,14 +6012,15 @@ fn getMappedNormal(
5459
6012
  normalSampler: texture_2d<f32>,
5460
6013
  normalSamplerBinding: sampler,
5461
6014
  tbn: mat3x3f,
5462
- normalScale: f32
6015
+ normalScale: f32,
6016
+ uv: vec2f
5463
6017
  ) -> vec3f
5464
6018
  {
5465
- let n = textureSample(normalSampler, normalSamplerBinding, fragmentInputs.pbr_vUV).rgb;
6019
+ let n = textureSample(normalSampler, normalSamplerBinding, uv).rgb;
5466
6020
  return normalize(tbn * ((2.0 * n - 1.0) * vec3f(normalScale, normalScale, 1.0)));
5467
6021
  }
5468
6022
 
5469
- fn getNormal(tbn: mat3x3f) -> vec3f
6023
+ fn getNormal(tbn: mat3x3f, uv: vec2f) -> vec3f
5470
6024
  {
5471
6025
  // The tbn matrix is linearly interpolated, so we need to re-normalize
5472
6026
  var n: vec3f = normalize(tbn[2].xyz);
@@ -5475,21 +6029,23 @@ fn getNormal(tbn: mat3x3f) -> vec3f
5475
6029
  pbr_normalSampler,
5476
6030
  pbr_normalSamplerSampler,
5477
6031
  tbn,
5478
- pbrMaterial.normalScale
6032
+ pbrMaterial.normalScale,
6033
+ uv
5479
6034
  );
5480
6035
  #endif
5481
6036
 
5482
6037
  return n;
5483
6038
  }
5484
6039
 
5485
- fn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f) -> vec3f
6040
+ fn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f, uv: vec2f) -> vec3f
5486
6041
  {
5487
6042
  #ifdef HAS_CLEARCOATNORMALMAP
5488
6043
  return getMappedNormal(
5489
6044
  pbr_clearcoatNormalSampler,
5490
6045
  pbr_clearcoatNormalSamplerSampler,
5491
6046
  tbn,
5492
- 1.0
6047
+ 1.0,
6048
+ uv
5493
6049
  );
5494
6050
  #else
5495
6051
  return baseNormal;
@@ -5794,11 +6350,62 @@ fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
5794
6350
  }
5795
6351
 
5796
6352
  fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6353
+ let baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
6354
+ let metallicRoughnessUV = getMaterialUV(
6355
+ pbrMaterial.metallicRoughnessUVSet,
6356
+ pbrMaterial.metallicRoughnessUVTransform
6357
+ );
6358
+ let normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
6359
+ let occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);
6360
+ let emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);
6361
+ let specularColorUV = getMaterialUV(
6362
+ pbrMaterial.specularColorUVSet,
6363
+ pbrMaterial.specularColorUVTransform
6364
+ );
6365
+ let specularIntensityUV = getMaterialUV(
6366
+ pbrMaterial.specularIntensityUVSet,
6367
+ pbrMaterial.specularIntensityUVTransform
6368
+ );
6369
+ let transmissionUV = getMaterialUV(
6370
+ pbrMaterial.transmissionUVSet,
6371
+ pbrMaterial.transmissionUVTransform
6372
+ );
6373
+ let thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);
6374
+ let clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);
6375
+ let clearcoatRoughnessUV = getMaterialUV(
6376
+ pbrMaterial.clearcoatRoughnessUVSet,
6377
+ pbrMaterial.clearcoatRoughnessUVTransform
6378
+ );
6379
+ let clearcoatNormalUV = getMaterialUV(
6380
+ pbrMaterial.clearcoatNormalUVSet,
6381
+ pbrMaterial.clearcoatNormalUVTransform
6382
+ );
6383
+ let sheenColorUV = getMaterialUV(
6384
+ pbrMaterial.sheenColorUVSet,
6385
+ pbrMaterial.sheenColorUVTransform
6386
+ );
6387
+ let sheenRoughnessUV = getMaterialUV(
6388
+ pbrMaterial.sheenRoughnessUVSet,
6389
+ pbrMaterial.sheenRoughnessUVTransform
6390
+ );
6391
+ let iridescenceUV = getMaterialUV(
6392
+ pbrMaterial.iridescenceUVSet,
6393
+ pbrMaterial.iridescenceUVTransform
6394
+ );
6395
+ let iridescenceThicknessUV = getMaterialUV(
6396
+ pbrMaterial.iridescenceThicknessUVSet,
6397
+ pbrMaterial.iridescenceThicknessUVTransform
6398
+ );
6399
+ let anisotropyUV = getMaterialUV(
6400
+ pbrMaterial.anisotropyUVSet,
6401
+ pbrMaterial.anisotropyUVTransform
6402
+ );
6403
+
5797
6404
  // The albedo may be defined from a base texture or a flat color
5798
6405
  var baseColor: vec4<f32> = pbrMaterial.baseColorFactor;
5799
6406
  #ifdef HAS_BASECOLORMAP
5800
6407
  baseColor = SRGBtoLINEAR(
5801
- textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, fragmentInputs.pbr_vUV)
6408
+ textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, baseColorUV)
5802
6409
  ) * pbrMaterial.baseColorFactor;
5803
6410
  #endif
5804
6411
 
@@ -5825,15 +6432,15 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
5825
6432
  let mrSample = textureSample(
5826
6433
  pbr_metallicRoughnessSampler,
5827
6434
  pbr_metallicRoughnessSamplerSampler,
5828
- fragmentInputs.pbr_vUV
6435
+ metallicRoughnessUV
5829
6436
  );
5830
6437
  perceptualRoughness = mrSample.g * perceptualRoughness;
5831
6438
  metallic = mrSample.b * metallic;
5832
6439
  #endif
5833
6440
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
5834
6441
  metallic = clamp(metallic, 0.0, 1.0);
5835
- let tbn = getTBN();
5836
- let n = getNormal(tbn); // normal at surface point
6442
+ let tbn = getTBN(normalUV);
6443
+ let n = getNormal(tbn, normalUV); // normal at surface point
5837
6444
  let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera
5838
6445
  let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
5839
6446
  var useExtendedPBR = false;
@@ -5938,8 +6545,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
5938
6545
 
5939
6546
  #ifdef HAS_OCCLUSIONMAP
5940
6547
  if (pbrMaterial.occlusionMapEnabled != 0) {
5941
- let ao =
5942
- textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, fragmentInputs.pbr_vUV).r;
6548
+ let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;
5943
6549
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
5944
6550
  }
5945
6551
  #endif
@@ -5948,7 +6554,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
5948
6554
  #ifdef HAS_EMISSIVEMAP
5949
6555
  if (pbrMaterial.emissiveMapEnabled != 0u) {
5950
6556
  emissive *= SRGBtoLINEAR(
5951
- textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
6557
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)
5952
6558
  ).rgb;
5953
6559
  }
5954
6560
  #endif
@@ -5969,7 +6575,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
5969
6575
  specularIntensity *= textureSample(
5970
6576
  pbr_specularIntensitySampler,
5971
6577
  pbr_specularIntensitySamplerSampler,
5972
- fragmentInputs.pbr_vUV
6578
+ specularIntensityUV
5973
6579
  ).a;
5974
6580
  }
5975
6581
  #endif
@@ -5981,7 +6587,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
5981
6587
  textureSample(
5982
6588
  pbr_specularColorSampler,
5983
6589
  pbr_specularColorSamplerSampler,
5984
- fragmentInputs.pbr_vUV
6590
+ specularColorUV
5985
6591
  )
5986
6592
  ).rgb;
5987
6593
  }
@@ -5993,7 +6599,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
5993
6599
  transmission *= textureSample(
5994
6600
  pbr_transmissionSampler,
5995
6601
  pbr_transmissionSamplerSampler,
5996
- fragmentInputs.pbr_vUV
6602
+ transmissionUV
5997
6603
  ).r;
5998
6604
  }
5999
6605
  #endif
@@ -6003,7 +6609,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6003
6609
  thickness *= textureSample(
6004
6610
  pbr_thicknessSampler,
6005
6611
  pbr_thicknessSamplerSampler,
6006
- fragmentInputs.pbr_vUV
6612
+ thicknessUV
6007
6613
  ).g;
6008
6614
  #endif
6009
6615
 
@@ -6014,7 +6620,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6014
6620
  clearcoatFactor *= textureSample(
6015
6621
  pbr_clearcoatSampler,
6016
6622
  pbr_clearcoatSamplerSampler,
6017
- fragmentInputs.pbr_vUV
6623
+ clearcoatUV
6018
6624
  ).r;
6019
6625
  }
6020
6626
  #endif
@@ -6023,13 +6629,13 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6023
6629
  clearcoatRoughness *= textureSample(
6024
6630
  pbr_clearcoatRoughnessSampler,
6025
6631
  pbr_clearcoatRoughnessSamplerSampler,
6026
- fragmentInputs.pbr_vUV
6632
+ clearcoatRoughnessUV
6027
6633
  ).g;
6028
6634
  }
6029
6635
  #endif
6030
6636
  clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
6031
6637
  clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
6032
- let clearcoatNormal = getClearcoatNormal(tbn, n);
6638
+ let clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);
6033
6639
 
6034
6640
  var sheenColor = pbrMaterial.sheenColorFactor;
6035
6641
  var sheenRoughness = pbrMaterial.sheenRoughnessFactor;
@@ -6039,7 +6645,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6039
6645
  textureSample(
6040
6646
  pbr_sheenColorSampler,
6041
6647
  pbr_sheenColorSamplerSampler,
6042
- fragmentInputs.pbr_vUV
6648
+ sheenColorUV
6043
6649
  )
6044
6650
  ).rgb;
6045
6651
  }
@@ -6049,7 +6655,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6049
6655
  sheenRoughness *= textureSample(
6050
6656
  pbr_sheenRoughnessSampler,
6051
6657
  pbr_sheenRoughnessSamplerSampler,
6052
- fragmentInputs.pbr_vUV
6658
+ sheenRoughnessUV
6053
6659
  ).a;
6054
6660
  }
6055
6661
  #endif
@@ -6061,7 +6667,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6061
6667
  iridescence *= textureSample(
6062
6668
  pbr_iridescenceSampler,
6063
6669
  pbr_iridescenceSamplerSampler,
6064
- fragmentInputs.pbr_vUV
6670
+ iridescenceUV
6065
6671
  ).r;
6066
6672
  }
6067
6673
  #endif
@@ -6078,7 +6684,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6078
6684
  textureSample(
6079
6685
  pbr_iridescenceThicknessSampler,
6080
6686
  pbr_iridescenceThicknessSamplerSampler,
6081
- fragmentInputs.pbr_vUV
6687
+ iridescenceThicknessUV
6082
6688
  ).g
6083
6689
  );
6084
6690
  #endif
@@ -6090,7 +6696,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6090
6696
  let anisotropySample = textureSample(
6091
6697
  pbr_anisotropySampler,
6092
6698
  pbr_anisotropySamplerSampler,
6093
- fragmentInputs.pbr_vUV
6699
+ anisotropyUV
6094
6700
  ).rgb;
6095
6701
  anisotropyStrength *= anisotropySample.b;
6096
6702
  let mappedDirection = anisotropySample.rg * 2.0 - 1.0;
@@ -6257,8 +6863,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6257
6863
  // Apply optional PBR terms for additional (optional) shading
6258
6864
  #ifdef HAS_OCCLUSIONMAP
6259
6865
  if (pbrMaterial.occlusionMapEnabled != 0) {
6260
- let ao =
6261
- textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, fragmentInputs.pbr_vUV).r;
6866
+ let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;
6262
6867
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
6263
6868
  }
6264
6869
  #endif
@@ -6267,7 +6872,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6267
6872
  #ifdef HAS_EMISSIVEMAP
6268
6873
  if (pbrMaterial.emissiveMapEnabled != 0u) {
6269
6874
  emissive *= SRGBtoLINEAR(
6270
- textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
6875
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)
6271
6876
  ).rgb;
6272
6877
  }
6273
6878
  #endif
@@ -6303,7 +6908,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
6303
6908
  // dist/modules/lighting/pbr-material/pbr-projection.js
6304
6909
  var uniformBlock = (
6305
6910
  /* glsl */
6306
- `uniform pbrProjectionUniforms {
6911
+ `layout(std140) uniform pbrProjectionUniforms {
6307
6912
  mat4 modelViewProjectionMatrix;
6308
6913
  mat4 modelMatrix;
6309
6914
  mat4 normalMatrix;
@@ -6387,7 +6992,41 @@ var pbrMaterial = {
6387
6992
  anisotropyRotation: 0,
6388
6993
  anisotropyDirection: [1, 0],
6389
6994
  anisotropyMapEnabled: false,
6390
- emissiveStrength: 1
6995
+ emissiveStrength: 1,
6996
+ baseColorUVSet: 0,
6997
+ baseColorUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
6998
+ metallicRoughnessUVSet: 0,
6999
+ metallicRoughnessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7000
+ normalUVSet: 0,
7001
+ normalUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7002
+ occlusionUVSet: 0,
7003
+ occlusionUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7004
+ emissiveUVSet: 0,
7005
+ emissiveUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7006
+ specularColorUVSet: 0,
7007
+ specularColorUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7008
+ specularIntensityUVSet: 0,
7009
+ specularIntensityUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7010
+ transmissionUVSet: 0,
7011
+ transmissionUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7012
+ thicknessUVSet: 0,
7013
+ thicknessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7014
+ clearcoatUVSet: 0,
7015
+ clearcoatUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7016
+ clearcoatRoughnessUVSet: 0,
7017
+ clearcoatRoughnessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7018
+ clearcoatNormalUVSet: 0,
7019
+ clearcoatNormalUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7020
+ sheenColorUVSet: 0,
7021
+ sheenColorUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7022
+ sheenRoughnessUVSet: 0,
7023
+ sheenRoughnessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7024
+ iridescenceUVSet: 0,
7025
+ iridescenceUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7026
+ iridescenceThicknessUVSet: 0,
7027
+ iridescenceThicknessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
7028
+ anisotropyUVSet: 0,
7029
+ anisotropyUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1]
6391
7030
  },
6392
7031
  name: "pbrMaterial",
6393
7032
  firstBindingSlot: 0,
@@ -6494,7 +7133,110 @@ var pbrMaterial = {
6494
7133
  // debugging flags used for shader output of intermediate PBR variables
6495
7134
  // #ifdef PBR_DEBUG
6496
7135
  scaleDiffBaseMR: "vec4<f32>",
6497
- scaleFGDSpec: "vec4<f32>"
7136
+ scaleFGDSpec: "vec4<f32>",
7137
+ baseColorUVSet: "i32",
7138
+ baseColorUVTransform: "mat3x3<f32>",
7139
+ metallicRoughnessUVSet: "i32",
7140
+ metallicRoughnessUVTransform: "mat3x3<f32>",
7141
+ normalUVSet: "i32",
7142
+ normalUVTransform: "mat3x3<f32>",
7143
+ occlusionUVSet: "i32",
7144
+ occlusionUVTransform: "mat3x3<f32>",
7145
+ emissiveUVSet: "i32",
7146
+ emissiveUVTransform: "mat3x3<f32>",
7147
+ specularColorUVSet: "i32",
7148
+ specularColorUVTransform: "mat3x3<f32>",
7149
+ specularIntensityUVSet: "i32",
7150
+ specularIntensityUVTransform: "mat3x3<f32>",
7151
+ transmissionUVSet: "i32",
7152
+ transmissionUVTransform: "mat3x3<f32>",
7153
+ thicknessUVSet: "i32",
7154
+ thicknessUVTransform: "mat3x3<f32>",
7155
+ clearcoatUVSet: "i32",
7156
+ clearcoatUVTransform: "mat3x3<f32>",
7157
+ clearcoatRoughnessUVSet: "i32",
7158
+ clearcoatRoughnessUVTransform: "mat3x3<f32>",
7159
+ clearcoatNormalUVSet: "i32",
7160
+ clearcoatNormalUVTransform: "mat3x3<f32>",
7161
+ sheenColorUVSet: "i32",
7162
+ sheenColorUVTransform: "mat3x3<f32>",
7163
+ sheenRoughnessUVSet: "i32",
7164
+ sheenRoughnessUVTransform: "mat3x3<f32>",
7165
+ iridescenceUVSet: "i32",
7166
+ iridescenceUVTransform: "mat3x3<f32>",
7167
+ iridescenceThicknessUVSet: "i32",
7168
+ iridescenceThicknessUVTransform: "mat3x3<f32>",
7169
+ anisotropyUVSet: "i32",
7170
+ anisotropyUVTransform: "mat3x3<f32>"
7171
+ }
7172
+ };
7173
+
7174
+ // dist/modules/lighting/pbr-material/pbr-scene.js
7175
+ var IDENTITY_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
7176
+ var uniformBlock2 = (
7177
+ /* glsl */
7178
+ `layout(std140) uniform pbrSceneUniforms {
7179
+ float exposure;
7180
+ int toneMapMode;
7181
+ float environmentIntensity;
7182
+ float environmentRotation;
7183
+ vec2 framebufferSize;
7184
+ mat4 viewMatrix;
7185
+ mat4 projectionMatrix;
7186
+ } pbrScene;
7187
+
7188
+ #ifdef USE_TRANSMISSION_FRAMEBUFFER
7189
+ uniform sampler2D pbr_transmissionFramebufferSampler;
7190
+ #endif
7191
+ `
7192
+ );
7193
+ var wgslUniformBlock2 = (
7194
+ /* wgsl */
7195
+ `struct pbrSceneUniforms {
7196
+ exposure: f32,
7197
+ toneMapMode: i32,
7198
+ environmentIntensity: f32,
7199
+ environmentRotation: f32,
7200
+ framebufferSize: vec2<f32>,
7201
+ viewMatrix: mat4x4<f32>,
7202
+ projectionMatrix: mat4x4<f32>
7203
+ };
7204
+
7205
+ @group(1) @binding(auto) var<uniform> pbrScene: pbrSceneUniforms;
7206
+
7207
+ #ifdef USE_TRANSMISSION_FRAMEBUFFER
7208
+ @group(1) @binding(auto) var pbr_transmissionFramebufferSampler: texture_2d<f32>;
7209
+ @group(1) @binding(auto) var pbr_transmissionFramebufferSamplerSampler: sampler;
7210
+ #endif
7211
+ `
7212
+ );
7213
+ var pbrScene = {
7214
+ name: "pbrScene",
7215
+ bindingLayout: [
7216
+ { name: "pbrScene", group: 1 },
7217
+ { name: "pbr_transmissionFramebufferSampler", group: 1 }
7218
+ ],
7219
+ source: wgslUniformBlock2,
7220
+ vs: uniformBlock2,
7221
+ fs: uniformBlock2,
7222
+ getUniforms: (props) => props,
7223
+ uniformTypes: {
7224
+ exposure: "f32",
7225
+ toneMapMode: "i32",
7226
+ environmentIntensity: "f32",
7227
+ environmentRotation: "f32",
7228
+ framebufferSize: "vec2<f32>",
7229
+ viewMatrix: "mat4x4<f32>",
7230
+ projectionMatrix: "mat4x4<f32>"
7231
+ },
7232
+ defaultUniforms: {
7233
+ exposure: 1,
7234
+ toneMapMode: 2,
7235
+ environmentIntensity: 1,
7236
+ environmentRotation: Math.PI * 0.5,
7237
+ framebufferSize: [1, 1],
7238
+ viewMatrix: IDENTITY_MATRIX,
7239
+ projectionMatrix: IDENTITY_MATRIX
6498
7240
  }
6499
7241
  };
6500
7242
  //# sourceMappingURL=index.cjs.map