@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/dist.dev.js CHANGED
@@ -62,6 +62,7 @@ var __exports__ = (() => {
62
62
  combineInjects: () => combineInjects,
63
63
  convertToVec4: () => convertToVec4,
64
64
  dirlight: () => dirlight,
65
+ floatColors: () => floatColors,
65
66
  fp32: () => fp32,
66
67
  fp64: () => fp64,
67
68
  fp64LowPart: () => fp64LowPart,
@@ -70,6 +71,7 @@ var __exports__ = (() => {
70
71
  fp64ifyMatrix4: () => fp64ifyMatrix4,
71
72
  fromHalfFloat: () => fromHalfFloat,
72
73
  generateShaderForModule: () => generateShaderForModule,
74
+ getGLSLUniformBlocks: () => getGLSLUniformBlocks,
73
75
  getPassthroughFS: () => getPassthroughFS,
74
76
  getQualifierDetails: () => getQualifierDetails,
75
77
  getShaderInfo: () => getShaderInfo,
@@ -85,16 +87,21 @@ var __exports__ = (() => {
85
87
  initializeShaderModules: () => initializeShaderModules,
86
88
  lambertMaterial: () => lambertMaterial,
87
89
  lighting: () => lighting,
90
+ normalizeByteColor3: () => normalizeByteColor3,
91
+ normalizeByteColor4: () => normalizeByteColor4,
88
92
  pbrMaterial: () => pbrMaterial,
93
+ pbrScene: () => pbrScene,
89
94
  phongMaterial: () => phongMaterial,
90
95
  picking: () => picking,
91
96
  preprocess: () => preprocess,
92
97
  random: () => random,
98
+ resolveUseByteColors: () => resolveUseByteColors,
93
99
  skin: () => skin,
94
100
  toHalfFloat: () => toHalfFloat,
95
101
  typeToChannelCount: () => typeToChannelCount,
96
102
  typeToChannelSuffix: () => typeToChannelSuffix,
97
- validateShaderModuleUniformLayout: () => validateShaderModuleUniformLayout
103
+ validateShaderModuleUniformLayout: () => validateShaderModuleUniformLayout,
104
+ warnIfGLSLUniformBlocksAreNotStd140: () => warnIfGLSLUniformBlocksAreNotStd140
98
105
  });
99
106
  __reExport(bundle_exports, __toESM(require_core(), 1));
100
107
 
@@ -416,6 +423,8 @@ ${inject[key]}` : inject[key];
416
423
  }
417
424
 
418
425
  // src/lib/shader-module/shader-module-uniform-layout.ts
426
+ var GLSL_UNIFORM_BLOCK_FIELD_REGEXP = /^(?:uniform\s+)?(?:(?:lowp|mediump|highp)\s+)?[A-Za-z0-9_]+(?:<[^>]+>)?\s+([A-Za-z0-9_]+)(?:\s*\[[^\]]+\])?\s*;/;
427
+ 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;
419
428
  function getShaderModuleUniformBlockName(module) {
420
429
  return `${module.name}Uniforms`;
421
430
  }
@@ -461,6 +470,39 @@ ${inject[key]}` : inject[key];
461
470
  }
462
471
  return validationResult;
463
472
  }
473
+ function getGLSLUniformBlocks(shaderSource) {
474
+ const blocks = [];
475
+ const uncommentedSource = stripShaderComments(shaderSource);
476
+ for (const sourceMatch of uncommentedSource.matchAll(GLSL_UNIFORM_BLOCK_REGEXP)) {
477
+ const layoutQualifier = sourceMatch[1]?.trim() || null;
478
+ blocks.push({
479
+ blockName: sourceMatch[2],
480
+ body: sourceMatch[3],
481
+ instanceName: sourceMatch[4] || null,
482
+ layoutQualifier,
483
+ hasLayoutQualifier: Boolean(layoutQualifier),
484
+ isStd140: Boolean(
485
+ layoutQualifier && /\blayout\s*\([^)]*\bstd140\b[^)]*\)/.exec(layoutQualifier)
486
+ )
487
+ });
488
+ }
489
+ return blocks;
490
+ }
491
+ function warnIfGLSLUniformBlocksAreNotStd140(shaderSource, stage, log2, context) {
492
+ const nonStd140Blocks = getGLSLUniformBlocks(shaderSource).filter((block) => !block.isStd140);
493
+ const seenBlockNames = /* @__PURE__ */ new Set();
494
+ for (const block of nonStd140Blocks) {
495
+ if (seenBlockNames.has(block.blockName)) {
496
+ continue;
497
+ }
498
+ seenBlockNames.add(block.blockName);
499
+ const shaderLabel = context?.label ? `${context.label} ` : "";
500
+ const actualLayout = block.hasLayoutQualifier ? `declares ${normalizeWhitespace(block.layoutQualifier)} instead of layout(std140)` : "does not declare layout(std140)";
501
+ 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.`;
502
+ log2?.warn?.(message, block)();
503
+ }
504
+ return nonStd140Blocks;
505
+ }
464
506
  function extractShaderUniformBlockFieldNames(shaderSource, language, uniformBlockName) {
465
507
  const sourceBody = language === "wgsl" ? extractWGSLStructBody(shaderSource, uniformBlockName) : extractGLSLUniformBlockBody(shaderSource, uniformBlockName);
466
508
  if (!sourceBody) {
@@ -472,9 +514,7 @@ ${inject[key]}` : inject[key];
472
514
  if (!line || line.startsWith("#")) {
473
515
  continue;
474
516
  }
475
- const fieldMatch = language === "wgsl" ? line.match(/^([A-Za-z0-9_]+)\s*:/) : line.match(
476
- /^(?:uniform\s+)?[A-Za-z0-9_]+(?:<[^>]+>)?\s+([A-Za-z0-9_]+)(?:\s*\[[^\]]+\])?\s*;/
477
- );
517
+ const fieldMatch = language === "wgsl" ? line.match(/^([A-Za-z0-9_]+)\s*:/) : line.match(GLSL_UNIFORM_BLOCK_FIELD_REGEXP);
478
518
  if (fieldMatch) {
479
519
  fieldNames.push(fieldMatch[1]);
480
520
  }
@@ -508,10 +548,10 @@ ${inject[key]}` : inject[key];
508
548
  return null;
509
549
  }
510
550
  function extractGLSLUniformBlockBody(shaderSource, uniformBlockName) {
511
- const sourceMatch = shaderSource.match(
512
- new RegExp(`uniform\\s+${uniformBlockName}\\s*\\{([\\s\\S]*?)\\}\\s*[A-Za-z0-9_]+\\s*;`, "m")
551
+ const block = getGLSLUniformBlocks(shaderSource).find(
552
+ (candidate) => candidate.blockName === uniformBlockName
513
553
  );
514
- return sourceMatch?.[1] || null;
554
+ return block?.body || null;
515
555
  }
516
556
  function areStringArraysEqual(leftValues, rightValues) {
517
557
  if (leftValues.length !== rightValues.length) {
@@ -525,11 +565,70 @@ ${inject[key]}` : inject[key];
525
565
  return true;
526
566
  }
527
567
  function formatShaderModuleUniformLayoutError(validationResult) {
528
- return `${validationResult.moduleName}: ${validationResult.stage} shader uniform block ${validationResult.uniformBlockName} does not match module.uniformTypes.
529
- Expected: ${validationResult.expectedUniformNames.join(
530
- ", "
531
- )}
532
- Actual: ${validationResult.actualUniformNames.join(", ")}`;
568
+ const { expectedUniformNames, actualUniformNames } = validationResult;
569
+ const missingUniformNames = expectedUniformNames.filter(
570
+ (uniformName) => !actualUniformNames.includes(uniformName)
571
+ );
572
+ const unexpectedUniformNames = actualUniformNames.filter(
573
+ (uniformName) => !expectedUniformNames.includes(uniformName)
574
+ );
575
+ const mismatchDetails = [
576
+ `Expected ${expectedUniformNames.length} fields, found ${actualUniformNames.length}.`
577
+ ];
578
+ const firstMismatchDescription = getFirstUniformMismatchDescription(
579
+ expectedUniformNames,
580
+ actualUniformNames
581
+ );
582
+ if (firstMismatchDescription) {
583
+ mismatchDetails.push(firstMismatchDescription);
584
+ }
585
+ if (missingUniformNames.length) {
586
+ mismatchDetails.push(
587
+ `Missing from shader block (${missingUniformNames.length}): ${formatUniformNameList(
588
+ missingUniformNames
589
+ )}.`
590
+ );
591
+ }
592
+ if (unexpectedUniformNames.length) {
593
+ mismatchDetails.push(
594
+ `Unexpected in shader block (${unexpectedUniformNames.length}): ${formatUniformNameList(
595
+ unexpectedUniformNames
596
+ )}.`
597
+ );
598
+ }
599
+ if (expectedUniformNames.length <= 12 && actualUniformNames.length <= 12 && (missingUniformNames.length || unexpectedUniformNames.length)) {
600
+ mismatchDetails.push(`Expected: ${expectedUniformNames.join(", ")}.`);
601
+ mismatchDetails.push(`Actual: ${actualUniformNames.join(", ")}.`);
602
+ }
603
+ return `${validationResult.moduleName}: ${validationResult.stage} shader uniform block ${validationResult.uniformBlockName} does not match module.uniformTypes. ${mismatchDetails.join(" ")}`;
604
+ }
605
+ function stripShaderComments(shaderSource) {
606
+ return shaderSource.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
607
+ }
608
+ function normalizeWhitespace(value) {
609
+ return value.replace(/\s+/g, " ").trim();
610
+ }
611
+ function getFirstUniformMismatchDescription(expectedUniformNames, actualUniformNames) {
612
+ const minimumLength = Math.min(expectedUniformNames.length, actualUniformNames.length);
613
+ for (let index = 0; index < minimumLength; index++) {
614
+ if (expectedUniformNames[index] !== actualUniformNames[index]) {
615
+ return `First mismatch at field ${index + 1}: expected ${expectedUniformNames[index]}, found ${actualUniformNames[index]}.`;
616
+ }
617
+ }
618
+ if (expectedUniformNames.length > actualUniformNames.length) {
619
+ return `Shader block ends after field ${actualUniformNames.length}; expected next field ${expectedUniformNames[actualUniformNames.length]}.`;
620
+ }
621
+ if (actualUniformNames.length > expectedUniformNames.length) {
622
+ return `Shader block has extra field ${actualUniformNames.length}: ${actualUniformNames[expectedUniformNames.length]}.`;
623
+ }
624
+ return null;
625
+ }
626
+ function formatUniformNameList(uniformNames, maxNames = 8) {
627
+ if (uniformNames.length <= maxNames) {
628
+ return uniformNames.join(", ");
629
+ }
630
+ const remainingCount = uniformNames.length - maxNames;
631
+ return `${uniformNames.slice(0, maxNames).join(", ")}, ... (${remainingCount} more)`;
533
632
  }
534
633
 
535
634
  // src/lib/shader-assembly/platform-defines.ts
@@ -716,12 +815,194 @@ Actual: ${validationResult.actualUniformNames.join(", ")}`;
716
815
  return version;
717
816
  }
718
817
 
818
+ // src/lib/shader-assembly/wgsl-binding-scan.ts
819
+ 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_]*)";
820
+ var WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN = "\\s*";
821
+ var MODULE_WGSL_BINDING_DECLARATION_REGEXES = [
822
+ new RegExp(
823
+ `@binding\\(\\s*(auto|\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`,
824
+ "g"
825
+ ),
826
+ new RegExp(
827
+ `@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@binding\\(\\s*(auto|\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`,
828
+ "g"
829
+ )
830
+ ];
831
+ var WGSL_BINDING_DECLARATION_REGEXES = [
832
+ new RegExp(
833
+ `@binding\\(\\s*(auto|\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`,
834
+ "g"
835
+ ),
836
+ new RegExp(
837
+ `@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@binding\\(\\s*(auto|\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`,
838
+ "g"
839
+ )
840
+ ];
841
+ var WGSL_EXPLICIT_BINDING_DECLARATION_REGEXES = [
842
+ new RegExp(
843
+ `@binding\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`,
844
+ "g"
845
+ ),
846
+ new RegExp(
847
+ `@group\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}@binding\\(\\s*(\\d+)\\s*\\)${WGSL_BINDING_DECLARATION_SEPARATOR_PATTERN}${WGSL_BINDABLE_VARIABLE_PATTERN}`,
848
+ "g"
849
+ )
850
+ ];
851
+ var WGSL_AUTO_BINDING_DECLARATION_REGEXES = [
852
+ new RegExp(
853
+ `@binding\\(\\s*(auto)\\s*\\)\\s*@group\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}`,
854
+ "g"
855
+ ),
856
+ new RegExp(
857
+ `@group\\(\\s*(\\d+)\\s*\\)\\s*@binding\\(\\s*(auto)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}`,
858
+ "g"
859
+ ),
860
+ new RegExp(
861
+ `@binding\\(\\s*(auto)\\s*\\)\\s*@group\\(\\s*(\\d+)\\s*\\)(?:[\\s\\n\\r]*@[A-Za-z_][^\\n\\r]*)*[\\s\\n\\r]*${WGSL_BINDABLE_VARIABLE_PATTERN}`,
862
+ "g"
863
+ ),
864
+ new RegExp(
865
+ `@group\\(\\s*(\\d+)\\s*\\)\\s*@binding\\(\\s*(auto)\\s*\\)(?:[\\s\\n\\r]*@[A-Za-z_][^\\n\\r]*)*[\\s\\n\\r]*${WGSL_BINDABLE_VARIABLE_PATTERN}`,
866
+ "g"
867
+ )
868
+ ];
869
+ function maskWGSLComments(source4) {
870
+ const maskedCharacters = source4.split("");
871
+ let index = 0;
872
+ let blockCommentDepth = 0;
873
+ let inLineComment = false;
874
+ let inString = false;
875
+ let isEscaped = false;
876
+ while (index < source4.length) {
877
+ const character = source4[index];
878
+ const nextCharacter = source4[index + 1];
879
+ if (inString) {
880
+ if (isEscaped) {
881
+ isEscaped = false;
882
+ } else if (character === "\\") {
883
+ isEscaped = true;
884
+ } else if (character === '"') {
885
+ inString = false;
886
+ }
887
+ index++;
888
+ continue;
889
+ }
890
+ if (inLineComment) {
891
+ if (character === "\n" || character === "\r") {
892
+ inLineComment = false;
893
+ } else {
894
+ maskedCharacters[index] = " ";
895
+ }
896
+ index++;
897
+ continue;
898
+ }
899
+ if (blockCommentDepth > 0) {
900
+ if (character === "/" && nextCharacter === "*") {
901
+ maskedCharacters[index] = " ";
902
+ maskedCharacters[index + 1] = " ";
903
+ blockCommentDepth++;
904
+ index += 2;
905
+ continue;
906
+ }
907
+ if (character === "*" && nextCharacter === "/") {
908
+ maskedCharacters[index] = " ";
909
+ maskedCharacters[index + 1] = " ";
910
+ blockCommentDepth--;
911
+ index += 2;
912
+ continue;
913
+ }
914
+ if (character !== "\n" && character !== "\r") {
915
+ maskedCharacters[index] = " ";
916
+ }
917
+ index++;
918
+ continue;
919
+ }
920
+ if (character === '"') {
921
+ inString = true;
922
+ index++;
923
+ continue;
924
+ }
925
+ if (character === "/" && nextCharacter === "/") {
926
+ maskedCharacters[index] = " ";
927
+ maskedCharacters[index + 1] = " ";
928
+ inLineComment = true;
929
+ index += 2;
930
+ continue;
931
+ }
932
+ if (character === "/" && nextCharacter === "*") {
933
+ maskedCharacters[index] = " ";
934
+ maskedCharacters[index + 1] = " ";
935
+ blockCommentDepth = 1;
936
+ index += 2;
937
+ continue;
938
+ }
939
+ index++;
940
+ }
941
+ return maskedCharacters.join("");
942
+ }
943
+ function getWGSLBindingDeclarationMatches(source4, regexes) {
944
+ const maskedSource = maskWGSLComments(source4);
945
+ const matches = [];
946
+ for (const regex of regexes) {
947
+ regex.lastIndex = 0;
948
+ let match;
949
+ match = regex.exec(maskedSource);
950
+ while (match) {
951
+ const isBindingFirst = regex === regexes[0];
952
+ const index = match.index;
953
+ const length = match[0].length;
954
+ matches.push({
955
+ match: source4.slice(index, index + length),
956
+ index,
957
+ length,
958
+ bindingToken: match[isBindingFirst ? 1 : 2],
959
+ groupToken: match[isBindingFirst ? 2 : 1],
960
+ accessDeclaration: match[3]?.trim(),
961
+ name: match[4]
962
+ });
963
+ match = regex.exec(maskedSource);
964
+ }
965
+ }
966
+ return matches.sort((left, right) => left.index - right.index);
967
+ }
968
+ function replaceWGSLBindingDeclarationMatches(source4, regexes, replacer) {
969
+ const matches = getWGSLBindingDeclarationMatches(source4, regexes);
970
+ if (!matches.length) {
971
+ return source4;
972
+ }
973
+ let relocatedSource = "";
974
+ let lastIndex = 0;
975
+ for (const match of matches) {
976
+ relocatedSource += source4.slice(lastIndex, match.index);
977
+ relocatedSource += replacer(match);
978
+ lastIndex = match.index + match.length;
979
+ }
980
+ relocatedSource += source4.slice(lastIndex);
981
+ return relocatedSource;
982
+ }
983
+ function hasWGSLAutoBinding(source4) {
984
+ return /@binding\(\s*auto\s*\)/.test(maskWGSLComments(source4));
985
+ }
986
+ function getFirstWGSLAutoBindingDeclarationMatch(source4, regexes) {
987
+ const autoBindingRegexes = regexes === MODULE_WGSL_BINDING_DECLARATION_REGEXES || regexes === WGSL_BINDING_DECLARATION_REGEXES ? WGSL_AUTO_BINDING_DECLARATION_REGEXES : regexes;
988
+ return getWGSLBindingDeclarationMatches(source4, autoBindingRegexes).find(
989
+ (declarationMatch) => declarationMatch.bindingToken === "auto"
990
+ );
991
+ }
992
+
719
993
  // src/lib/shader-assembly/wgsl-binding-debug.ts
720
994
  var WGSL_BINDING_DEBUG_REGEXES = [
721
- /@binding\(\s*(\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*var(?:<([^>]+)>)?\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^;]+);/g,
722
- /@group\(\s*(\d+)\s*\)\s*@binding\(\s*(\d+)\s*\)\s*var(?:<([^>]+)>)?\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^;]+);/g
995
+ new RegExp(
996
+ `@binding\\(\\s*(\\d+)\\s*\\)\\s*@group\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}\\s*:\\s*([^;]+);`,
997
+ "g"
998
+ ),
999
+ new RegExp(
1000
+ `@group\\(\\s*(\\d+)\\s*\\)\\s*@binding\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}\\s*:\\s*([^;]+);`,
1001
+ "g"
1002
+ )
723
1003
  ];
724
1004
  function getShaderBindingDebugRowsFromWGSL(source4, bindingAssignments = []) {
1005
+ const maskedSource = maskWGSLComments(source4);
725
1006
  const assignmentMap = /* @__PURE__ */ new Map();
726
1007
  for (const bindingAssignment of bindingAssignments) {
727
1008
  assignmentMap.set(
@@ -737,7 +1018,8 @@ Actual: ${validationResult.actualUniformNames.join(", ")}`;
737
1018
  for (const regex of WGSL_BINDING_DEBUG_REGEXES) {
738
1019
  regex.lastIndex = 0;
739
1020
  let match;
740
- while (match = regex.exec(source4)) {
1021
+ match = regex.exec(maskedSource);
1022
+ while (match) {
741
1023
  const isBindingFirst = regex === WGSL_BINDING_DEBUG_REGEXES[0];
742
1024
  const binding = Number(match[isBindingFirst ? 1 : 2]);
743
1025
  const group = Number(match[isBindingFirst ? 2 : 1]);
@@ -756,6 +1038,7 @@ Actual: ${validationResult.actualUniformNames.join(", ")}`;
756
1038
  resourceType
757
1039
  })
758
1040
  );
1041
+ match = regex.exec(maskedSource);
759
1042
  }
760
1043
  }
761
1044
  return rows.sort((left, right) => {
@@ -867,14 +1150,6 @@ Actual: ${validationResult.actualUniformNames.join(", ")}`;
867
1150
 
868
1151
  ${DECLARATION_INJECT_MARKER}
869
1152
  `;
870
- var MODULE_WGSL_BINDING_DECLARATION_REGEXES = [
871
- /@binding\(\s*(auto|\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g,
872
- /@group\(\s*(\d+)\s*\)\s*@binding\(\s*(auto|\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g
873
- ];
874
- var WGSL_BINDING_DECLARATION_REGEXES = [
875
- /@binding\(\s*(\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g,
876
- /@group\(\s*(\d+)\s*\)\s*@binding\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g
877
- ];
878
1153
  var RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT = 100;
879
1154
  var FRAGMENT_SHADER_PROLOGUE = (
880
1155
  /* glsl */
@@ -954,7 +1229,10 @@ ${DECLARATION_INJECT_MARKER}
954
1229
  }
955
1230
  }
956
1231
  const modulesToInject = modules;
957
- const usedBindingsByGroup = getUsedBindingsByGroupFromApplicationWGSL(coreSource);
1232
+ const applicationRelocation = relocateWGSLApplicationBindings(coreSource);
1233
+ const usedBindingsByGroup = getUsedBindingsByGroupFromApplicationWGSL(
1234
+ applicationRelocation.source
1235
+ );
958
1236
  const reservedBindingKeysByGroup = reserveRegisteredModuleBindings(
959
1237
  modulesToInject,
960
1238
  options._bindingRegistry,
@@ -995,7 +1273,7 @@ ${DECLARATION_INJECT_MARKER}
995
1273
  assembledSource = injectShader(assembledSource, stage, declInjections);
996
1274
  assembledSource += getShaderHooks(hookFunctionMap[stage], hookInjections);
997
1275
  assembledSource += formatWGSLBindingAssignmentComments(bindingAssignments);
998
- assembledSource += coreSource;
1276
+ assembledSource += applicationRelocation.source;
999
1277
  assembledSource = injectShader(assembledSource, stage, mainInjections);
1000
1278
  assertNoUnresolvedAutoBindings(assembledSource);
1001
1279
  return { source: assembledSource, bindingAssignments };
@@ -1096,6 +1374,9 @@ ${getApplicationDefines(allDefines)}
1096
1374
  if (language === "glsl" && sourceVersion !== targetVersion) {
1097
1375
  assembledSource = transpileGLSLShader(assembledSource, stage);
1098
1376
  }
1377
+ if (language === "glsl") {
1378
+ warnIfGLSLUniformBlocksAreNotStd140(assembledSource, stage, log2);
1379
+ }
1099
1380
  return assembledSource.trim();
1100
1381
  }
1101
1382
  function assembleGetUniforms(modules) {
@@ -1152,61 +1433,87 @@ ${getApplicationDefines(allDefines)}
1152
1433
  }
1153
1434
  function getUsedBindingsByGroupFromApplicationWGSL(source4) {
1154
1435
  const usedBindingsByGroup = /* @__PURE__ */ new Map();
1155
- for (const regex of WGSL_BINDING_DECLARATION_REGEXES) {
1156
- regex.lastIndex = 0;
1157
- let match;
1158
- while (match = regex.exec(source4)) {
1159
- const isBindingFirst = regex === WGSL_BINDING_DECLARATION_REGEXES[0];
1160
- const location = Number(match[isBindingFirst ? 1 : 2]);
1161
- const group = Number(match[isBindingFirst ? 2 : 1]);
1162
- const name = match[4];
1163
- validateApplicationWGSLBinding(group, location, name);
1164
- registerUsedBindingLocation(
1165
- usedBindingsByGroup,
1166
- group,
1167
- location,
1168
- `application binding "${name}"`
1169
- );
1170
- }
1436
+ for (const match of getWGSLBindingDeclarationMatches(
1437
+ source4,
1438
+ WGSL_EXPLICIT_BINDING_DECLARATION_REGEXES
1439
+ )) {
1440
+ const location = Number(match.bindingToken);
1441
+ const group = Number(match.groupToken);
1442
+ validateApplicationWGSLBinding(group, location, match.name);
1443
+ registerUsedBindingLocation(
1444
+ usedBindingsByGroup,
1445
+ group,
1446
+ location,
1447
+ `application binding "${match.name}"`
1448
+ );
1171
1449
  }
1172
1450
  return usedBindingsByGroup;
1173
1451
  }
1452
+ function relocateWGSLApplicationBindings(source4) {
1453
+ const declarationMatches = getWGSLBindingDeclarationMatches(
1454
+ source4,
1455
+ WGSL_BINDING_DECLARATION_REGEXES
1456
+ );
1457
+ const usedBindingsByGroup = /* @__PURE__ */ new Map();
1458
+ for (const declarationMatch of declarationMatches) {
1459
+ if (declarationMatch.bindingToken === "auto") {
1460
+ continue;
1461
+ }
1462
+ const location = Number(declarationMatch.bindingToken);
1463
+ const group = Number(declarationMatch.groupToken);
1464
+ validateApplicationWGSLBinding(group, location, declarationMatch.name);
1465
+ registerUsedBindingLocation(
1466
+ usedBindingsByGroup,
1467
+ group,
1468
+ location,
1469
+ `application binding "${declarationMatch.name}"`
1470
+ );
1471
+ }
1472
+ const relocationState = {
1473
+ sawSupportedBindingDeclaration: declarationMatches.length > 0
1474
+ };
1475
+ const relocatedSource = replaceWGSLBindingDeclarationMatches(
1476
+ source4,
1477
+ WGSL_BINDING_DECLARATION_REGEXES,
1478
+ (declarationMatch) => relocateWGSLApplicationBindingMatch(declarationMatch, usedBindingsByGroup, relocationState)
1479
+ );
1480
+ if (hasWGSLAutoBinding(source4) && !relocationState.sawSupportedBindingDeclaration) {
1481
+ throw new Error(
1482
+ 'Unsupported @binding(auto) declaration form in application WGSL. Use adjacent "@group(N)" and "@binding(auto)" decorators followed by a bindable "var" declaration.'
1483
+ );
1484
+ }
1485
+ return { source: relocatedSource };
1486
+ }
1174
1487
  function relocateWGSLModuleBindings(moduleSource, module, context) {
1175
1488
  const bindingAssignments = [];
1489
+ const declarationMatches = getWGSLBindingDeclarationMatches(
1490
+ moduleSource,
1491
+ MODULE_WGSL_BINDING_DECLARATION_REGEXES
1492
+ );
1176
1493
  const relocationState = {
1177
- sawSupportedBindingDeclaration: false,
1494
+ sawSupportedBindingDeclaration: declarationMatches.length > 0,
1178
1495
  nextHintedBindingLocation: typeof module.firstBindingSlot === "number" ? module.firstBindingSlot : null
1179
1496
  };
1180
- let relocatedSource = relocateWGSLModuleBindingsWithRegex(
1497
+ const relocatedSource = replaceWGSLBindingDeclarationMatches(
1181
1498
  moduleSource,
1182
- MODULE_WGSL_BINDING_DECLARATION_REGEXES[0],
1183
- { isBindingFirst: true, module, context, bindingAssignments, relocationState }
1184
- );
1185
- relocatedSource = relocateWGSLModuleBindingsWithRegex(
1186
- relocatedSource,
1187
- MODULE_WGSL_BINDING_DECLARATION_REGEXES[1],
1188
- { isBindingFirst: false, module, context, bindingAssignments, relocationState }
1499
+ MODULE_WGSL_BINDING_DECLARATION_REGEXES,
1500
+ (declarationMatch) => relocateWGSLModuleBindingMatch(declarationMatch, {
1501
+ module,
1502
+ context,
1503
+ bindingAssignments,
1504
+ relocationState
1505
+ })
1189
1506
  );
1190
- if (moduleSource.includes("@binding(auto)") && !relocationState.sawSupportedBindingDeclaration) {
1507
+ if (hasWGSLAutoBinding(moduleSource) && !relocationState.sawSupportedBindingDeclaration) {
1191
1508
  throw new Error(
1192
- `Unsupported @binding(auto) declaration form in module "${module.name}". Use "@group(N) @binding(auto) var ..." or "@binding(auto) @group(N) var ..." on a single line.`
1509
+ `Unsupported @binding(auto) declaration form in module "${module.name}". Use adjacent "@group(N)" and "@binding(auto)" decorators followed by a bindable "var" declaration.`
1193
1510
  );
1194
1511
  }
1195
1512
  return { source: relocatedSource, bindingAssignments };
1196
1513
  }
1197
- function relocateWGSLModuleBindingsWithRegex(source4, regex, params) {
1198
- return source4.replace(
1199
- regex,
1200
- (...replaceArguments) => relocateWGSLModuleBindingMatch(replaceArguments, params)
1201
- );
1202
- }
1203
- function relocateWGSLModuleBindingMatch(replaceArguments, params) {
1204
- const { isBindingFirst, module, context, bindingAssignments, relocationState } = params;
1205
- relocationState.sawSupportedBindingDeclaration = true;
1206
- const match = replaceArguments[0];
1207
- const bindingToken = replaceArguments[isBindingFirst ? 1 : 2];
1208
- const groupToken = replaceArguments[isBindingFirst ? 2 : 1];
1209
- const name = replaceArguments[4];
1514
+ function relocateWGSLModuleBindingMatch(declarationMatch, params) {
1515
+ const { module, context, bindingAssignments, relocationState } = params;
1516
+ const { match, bindingToken, groupToken, name } = declarationMatch;
1210
1517
  const group = Number(groupToken);
1211
1518
  if (bindingToken === "auto") {
1212
1519
  const registryKey = getBindingRegistryKey(group, module.name, name);
@@ -1245,6 +1552,23 @@ ${getApplicationDefines(allDefines)}
1245
1552
  bindingAssignments.push({ moduleName: module.name, name, group, location });
1246
1553
  return match;
1247
1554
  }
1555
+ function relocateWGSLApplicationBindingMatch(declarationMatch, usedBindingsByGroup, relocationState) {
1556
+ const { match, bindingToken, groupToken, name } = declarationMatch;
1557
+ const group = Number(groupToken);
1558
+ if (bindingToken === "auto") {
1559
+ const location = allocateApplicationAutoBindingLocation(group, usedBindingsByGroup);
1560
+ validateApplicationWGSLBinding(group, location, name);
1561
+ registerUsedBindingLocation(
1562
+ usedBindingsByGroup,
1563
+ group,
1564
+ location,
1565
+ `application binding "${name}"`
1566
+ );
1567
+ return match.replace(/@binding\(\s*auto\s*\)/, `@binding(${location})`);
1568
+ }
1569
+ relocationState.sawSupportedBindingDeclaration = true;
1570
+ return match;
1571
+ }
1248
1572
  function reserveRegisteredModuleBindings(modules, bindingRegistry, usedBindingsByGroup) {
1249
1573
  const reservedBindingKeysByGroup = /* @__PURE__ */ new Map();
1250
1574
  if (!bindingRegistry) {
@@ -1294,16 +1618,14 @@ ${getApplicationDefines(allDefines)}
1294
1618
  function getModuleWGSLBindingDeclarations(module) {
1295
1619
  const declarations = [];
1296
1620
  const moduleSource = module.source || "";
1297
- for (const regex of MODULE_WGSL_BINDING_DECLARATION_REGEXES) {
1298
- regex.lastIndex = 0;
1299
- let match;
1300
- while (match = regex.exec(moduleSource)) {
1301
- const isBindingFirst = regex === MODULE_WGSL_BINDING_DECLARATION_REGEXES[0];
1302
- declarations.push({
1303
- name: match[4],
1304
- group: Number(match[isBindingFirst ? 2 : 1])
1305
- });
1306
- }
1621
+ for (const match of getWGSLBindingDeclarationMatches(
1622
+ moduleSource,
1623
+ MODULE_WGSL_BINDING_DECLARATION_REGEXES
1624
+ )) {
1625
+ declarations.push({
1626
+ name: match.name,
1627
+ group: Number(match.groupToken)
1628
+ });
1307
1629
  }
1308
1630
  return declarations;
1309
1631
  }
@@ -1339,10 +1661,36 @@ ${getApplicationDefines(allDefines)}
1339
1661
  }
1340
1662
  return nextBinding;
1341
1663
  }
1664
+ function allocateApplicationAutoBindingLocation(group, usedBindingsByGroup) {
1665
+ const usedBindings = usedBindingsByGroup.get(group) || /* @__PURE__ */ new Set();
1666
+ let nextBinding = 0;
1667
+ while (usedBindings.has(nextBinding)) {
1668
+ nextBinding++;
1669
+ }
1670
+ return nextBinding;
1671
+ }
1342
1672
  function assertNoUnresolvedAutoBindings(source4) {
1343
- if (/@binding\(\s*auto\s*\)/.test(source4)) {
1344
- throw new Error("Unresolved @binding(auto) remained in assembled WGSL source.");
1673
+ const unresolvedBinding = getFirstWGSLAutoBindingDeclarationMatch(
1674
+ source4,
1675
+ MODULE_WGSL_BINDING_DECLARATION_REGEXES
1676
+ );
1677
+ if (!unresolvedBinding) {
1678
+ return;
1679
+ }
1680
+ const moduleName = getWGSLModuleNameAtIndex(source4, unresolvedBinding.index);
1681
+ if (moduleName) {
1682
+ throw new Error(
1683
+ `Unresolved @binding(auto) for module "${moduleName}" binding "${unresolvedBinding.name}" remained in assembled WGSL source.`
1684
+ );
1685
+ }
1686
+ if (isInApplicationWGSLSection(source4, unresolvedBinding.index)) {
1687
+ throw new Error(
1688
+ `Unresolved @binding(auto) for application binding "${unresolvedBinding.name}" remained in assembled WGSL source.`
1689
+ );
1345
1690
  }
1691
+ throw new Error(
1692
+ `Unresolved @binding(auto) remained in assembled WGSL source near "${formatWGSLSourceSnippet(unresolvedBinding.match)}".`
1693
+ );
1346
1694
  }
1347
1695
  function formatWGSLBindingAssignmentComments(bindingAssignments) {
1348
1696
  if (bindingAssignments.length === 0) {
@@ -1359,6 +1707,24 @@ ${getApplicationDefines(allDefines)}
1359
1707
  function getBindingRegistryKey(group, moduleName, bindingName) {
1360
1708
  return `${group}:${moduleName}:${bindingName}`;
1361
1709
  }
1710
+ function getWGSLModuleNameAtIndex(source4, index) {
1711
+ const moduleHeaderRegex = /^\/\/ ----- MODULE ([^\n]+) ---------------$/gm;
1712
+ let moduleName;
1713
+ let match;
1714
+ match = moduleHeaderRegex.exec(source4);
1715
+ while (match && match.index <= index) {
1716
+ moduleName = match[1];
1717
+ match = moduleHeaderRegex.exec(source4);
1718
+ }
1719
+ return moduleName;
1720
+ }
1721
+ function isInApplicationWGSLSection(source4, index) {
1722
+ const injectionMarkerIndex = source4.indexOf(INJECT_SHADER_DECLARATIONS);
1723
+ return injectionMarkerIndex >= 0 ? index > injectionMarkerIndex : true;
1724
+ }
1725
+ function formatWGSLSourceSnippet(source4) {
1726
+ return source4.replace(/\s+/g, " ").trim();
1727
+ }
1362
1728
 
1363
1729
  // src/lib/preprocessor/preprocessor.ts
1364
1730
  var DEFINE_NAME_PATTERN = "([a-zA-Z_][a-zA-Z0-9_]*)";
@@ -1643,7 +2009,7 @@ void main() {
1643
2009
  switch (options.uniforms) {
1644
2010
  case "scoped-interface-blocks":
1645
2011
  case "unscoped-interface-blocks":
1646
- glsl.push(`uniform ${capitalize(module.name)} {`);
2012
+ glsl.push(`layout(std140) uniform ${capitalize(module.name)} {`);
1647
2013
  break;
1648
2014
  case "uniforms":
1649
2015
  }
@@ -3534,6 +3900,28 @@ void main() {
3534
3900
  return matrixFP64;
3535
3901
  }
3536
3902
 
3903
+ // src/lib/color/normalize-byte-colors.ts
3904
+ function resolveUseByteColors(useByteColors, defaultUseByteColors = true) {
3905
+ return useByteColors ?? defaultUseByteColors;
3906
+ }
3907
+ function normalizeByteColor3(color = [0, 0, 0], useByteColors = true) {
3908
+ if (!useByteColors) {
3909
+ return [...color];
3910
+ }
3911
+ return color.map((component) => component / 255);
3912
+ }
3913
+ function normalizeByteColor4(color, useByteColors = true) {
3914
+ const normalizedColor = normalizeByteColor3(color.slice(0, 3), useByteColors);
3915
+ const hasAlpha = Number.isFinite(color[3]);
3916
+ const alpha = hasAlpha ? color[3] : 1;
3917
+ return [
3918
+ normalizedColor[0],
3919
+ normalizedColor[1],
3920
+ normalizedColor[2],
3921
+ useByteColors && hasAlpha ? alpha / 255 : alpha
3922
+ ];
3923
+ }
3924
+
3537
3925
  // src/modules/math/random/random.ts
3538
3926
  var source = (
3539
3927
  /* wgsl */
@@ -3720,7 +4108,7 @@ float tan_fp32(float a) {
3720
4108
  var fp64arithmeticShader = (
3721
4109
  /* glsl */
3722
4110
  `
3723
- uniform fp64arithmeticUniforms {
4111
+ layout(std140) uniform fp64arithmeticUniforms {
3724
4112
  uniform float ONE;
3725
4113
  uniform float SPLIT;
3726
4114
  } fp64;
@@ -4838,15 +5226,99 @@ void mat4_vec4_mul_fp64(vec2 b[16], vec2 a[4], out vec2 out_val[4]) {
4838
5226
  fp64ifyMatrix4
4839
5227
  };
4840
5228
 
5229
+ // src/modules/color/float-colors.ts
5230
+ var GLSL_UNIFORMS = (
5231
+ /* glsl */
5232
+ `layout(std140) uniform floatColorsUniforms {
5233
+ float useByteColors;
5234
+ } floatColors;
5235
+
5236
+ vec3 floatColors_normalize(vec3 inputColor) {
5237
+ return floatColors.useByteColors > 0.5 ? inputColor / 255.0 : inputColor;
5238
+ }
5239
+
5240
+ vec4 floatColors_normalize(vec4 inputColor) {
5241
+ return floatColors.useByteColors > 0.5 ? inputColor / 255.0 : inputColor;
5242
+ }
5243
+
5244
+ vec4 floatColors_premultiplyAlpha(vec4 inputColor) {
5245
+ return vec4(inputColor.rgb * inputColor.a, inputColor.a);
5246
+ }
5247
+
5248
+ vec4 floatColors_unpremultiplyAlpha(vec4 inputColor) {
5249
+ return inputColor.a > 0.0 ? vec4(inputColor.rgb / inputColor.a, inputColor.a) : vec4(0.0);
5250
+ }
5251
+
5252
+ vec4 floatColors_premultiply_alpha(vec4 inputColor) {
5253
+ return floatColors_premultiplyAlpha(inputColor);
5254
+ }
5255
+
5256
+ vec4 floatColors_unpremultiply_alpha(vec4 inputColor) {
5257
+ return floatColors_unpremultiplyAlpha(inputColor);
5258
+ }
5259
+ `
5260
+ );
5261
+ var WGSL_UNIFORMS = (
5262
+ /* wgsl */
5263
+ `struct floatColorsUniforms {
5264
+ useByteColors: f32
5265
+ };
5266
+
5267
+ @group(0) @binding(auto) var<uniform> floatColors : floatColorsUniforms;
5268
+
5269
+ fn floatColors_normalize(inputColor: vec3<f32>) -> vec3<f32> {
5270
+ return select(inputColor, inputColor / 255.0, floatColors.useByteColors > 0.5);
5271
+ }
5272
+
5273
+ fn floatColors_normalize4(inputColor: vec4<f32>) -> vec4<f32> {
5274
+ return select(inputColor, inputColor / 255.0, floatColors.useByteColors > 0.5);
5275
+ }
5276
+
5277
+ fn floatColors_premultiplyAlpha(inputColor: vec4<f32>) -> vec4<f32> {
5278
+ return vec4<f32>(inputColor.rgb * inputColor.a, inputColor.a);
5279
+ }
5280
+
5281
+ fn floatColors_unpremultiplyAlpha(inputColor: vec4<f32>) -> vec4<f32> {
5282
+ return select(
5283
+ vec4<f32>(0.0),
5284
+ vec4<f32>(inputColor.rgb / inputColor.a, inputColor.a),
5285
+ inputColor.a > 0.0
5286
+ );
5287
+ }
5288
+
5289
+ fn floatColors_premultiply_alpha(inputColor: vec4<f32>) -> vec4<f32> {
5290
+ return floatColors_premultiplyAlpha(inputColor);
5291
+ }
5292
+
5293
+ fn floatColors_unpremultiply_alpha(inputColor: vec4<f32>) -> vec4<f32> {
5294
+ return floatColors_unpremultiplyAlpha(inputColor);
5295
+ }
5296
+ `
5297
+ );
5298
+ var floatColors = {
5299
+ name: "floatColors",
5300
+ props: {},
5301
+ uniforms: {},
5302
+ vs: GLSL_UNIFORMS,
5303
+ fs: GLSL_UNIFORMS,
5304
+ source: WGSL_UNIFORMS,
5305
+ uniformTypes: {
5306
+ useByteColors: "f32"
5307
+ },
5308
+ defaultUniforms: {
5309
+ useByteColors: true
5310
+ }
5311
+ };
5312
+
4841
5313
  // src/modules/engine/picking/picking.ts
4842
5314
  var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
4843
5315
  var vs = (
4844
5316
  /* glsl */
4845
- `uniform pickingUniforms {
5317
+ `layout(std140) uniform pickingUniforms {
4846
5318
  float isActive;
4847
5319
  float isAttribute;
4848
5320
  float isHighlightActive;
4849
- float useFloatColors;
5321
+ float useByteColors;
4850
5322
  vec3 highlightedObjectColor;
4851
5323
  vec4 highlightColor;
4852
5324
  } picking;
@@ -4855,12 +5327,12 @@ out vec4 picking_vRGBcolor_Avalid;
4855
5327
 
4856
5328
  // Normalize unsigned byte color to 0-1 range
4857
5329
  vec3 picking_normalizeColor(vec3 color) {
4858
- return picking.useFloatColors > 0.5 ? color : color / 255.0;
5330
+ return picking.useByteColors > 0.5 ? color / 255.0 : color;
4859
5331
  }
4860
5332
 
4861
5333
  // Normalize unsigned byte color to 0-1 range
4862
5334
  vec4 picking_normalizeColor(vec4 color) {
4863
- return picking.useFloatColors > 0.5 ? color : color / 255.0;
5335
+ return picking.useByteColors > 0.5 ? color / 255.0 : color;
4864
5336
  }
4865
5337
 
4866
5338
  bool picking_isColorZero(vec3 color) {
@@ -4917,11 +5389,11 @@ void picking_setPickingAttribute(vec3 value) {
4917
5389
  );
4918
5390
  var fs2 = (
4919
5391
  /* glsl */
4920
- `uniform pickingUniforms {
5392
+ `layout(std140) uniform pickingUniforms {
4921
5393
  float isActive;
4922
5394
  float isAttribute;
4923
5395
  float isHighlightActive;
4924
- float useFloatColors;
5396
+ float useByteColors;
4925
5397
  vec3 highlightedObjectColor;
4926
5398
  vec4 highlightColor;
4927
5399
  } picking;
@@ -4983,7 +5455,7 @@ vec4 picking_filterColor(vec4 color) {
4983
5455
  isActive: "f32",
4984
5456
  isAttribute: "f32",
4985
5457
  isHighlightActive: "f32",
4986
- useFloatColors: "f32",
5458
+ useByteColors: "f32",
4987
5459
  highlightedObjectColor: "vec3<f32>",
4988
5460
  highlightColor: "vec4<f32>"
4989
5461
  },
@@ -4991,7 +5463,7 @@ vec4 picking_filterColor(vec4 color) {
4991
5463
  isActive: false,
4992
5464
  isAttribute: false,
4993
5465
  isHighlightActive: false,
4994
- useFloatColors: true,
5466
+ useByteColors: true,
4995
5467
  highlightedObjectColor: [0, 0, 0],
4996
5468
  highlightColor: DEFAULT_HIGHLIGHT_COLOR
4997
5469
  },
@@ -5001,6 +5473,7 @@ vec4 picking_filterColor(vec4 color) {
5001
5473
  };
5002
5474
  function getUniforms(opts = {}, prevUniforms) {
5003
5475
  const uniforms = {};
5476
+ const useByteColors = resolveUseByteColors(opts.useByteColors, true);
5004
5477
  if (opts.highlightedObjectColor === void 0) {
5005
5478
  } else if (opts.highlightedObjectColor === null) {
5006
5479
  uniforms.isHighlightActive = false;
@@ -5010,18 +5483,14 @@ vec4 picking_filterColor(vec4 color) {
5010
5483
  uniforms.highlightedObjectColor = highlightedObjectColor;
5011
5484
  }
5012
5485
  if (opts.highlightColor) {
5013
- const color = Array.from(opts.highlightColor, (x) => x / 255);
5014
- if (!Number.isFinite(color[3])) {
5015
- color[3] = 1;
5016
- }
5017
- uniforms.highlightColor = color;
5486
+ uniforms.highlightColor = normalizeByteColor4(opts.highlightColor, useByteColors);
5018
5487
  }
5019
5488
  if (opts.isActive !== void 0) {
5020
5489
  uniforms.isActive = Boolean(opts.isActive);
5021
5490
  uniforms.isAttribute = Boolean(opts.isAttribute);
5022
5491
  }
5023
- if (opts.useFloatColors !== void 0) {
5024
- uniforms.useFloatColors = Boolean(opts.useFloatColors);
5492
+ if (opts.useByteColors !== void 0) {
5493
+ uniforms.useByteColors = Boolean(opts.useByteColors);
5025
5494
  }
5026
5495
  return uniforms;
5027
5496
  }
@@ -5048,7 +5517,7 @@ fn getSkinMatrix(weights: vec4f, joints: vec4u) -> mat4x4<f32> {
5048
5517
  var vs2 = (
5049
5518
  /* glsl */
5050
5519
  `
5051
- uniform skinUniforms {
5520
+ layout(std140) uniform skinUniforms {
5052
5521
  mat4 jointMatrix[SKIN_MAX_JOINTS];
5053
5522
  } skin;
5054
5523
 
@@ -5156,7 +5625,7 @@ struct UniformLight {
5156
5625
  vec2 coneCos;
5157
5626
  };
5158
5627
 
5159
- uniform lightingUniforms {
5628
+ layout(std140) uniform lightingUniforms {
5160
5629
  int enabled;
5161
5630
  int directionalLightCount;
5162
5631
  int pointLightCount;
@@ -5292,7 +5761,6 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5292
5761
 
5293
5762
  // src/modules/lighting/lights/lighting.ts
5294
5763
  var MAX_LIGHTS = 5;
5295
- var COLOR_FACTOR = 255;
5296
5764
  var LIGHT_UNIFORM_TYPE = {
5297
5765
  color: "vec3<f32>",
5298
5766
  position: "vec3<f32>",
@@ -5331,7 +5799,7 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5331
5799
  if (props.lights) {
5332
5800
  props = { ...props, ...extractLightTypes(props.lights), lights: void 0 };
5333
5801
  }
5334
- const { ambientLight, pointLights, spotLights, directionalLights } = props || {};
5802
+ const { useByteColors, ambientLight, pointLights, spotLights, directionalLights } = props || {};
5335
5803
  const hasLights = ambientLight || pointLights && pointLights.length > 0 || spotLights && spotLights.length > 0 || directionalLights && directionalLights.length > 0;
5336
5804
  if (!hasLights) {
5337
5805
  return {
@@ -5341,7 +5809,13 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5341
5809
  }
5342
5810
  const uniforms = {
5343
5811
  ...createDefaultLightingUniforms(),
5344
- ...getLightSourceUniforms({ ambientLight, pointLights, spotLights, directionalLights })
5812
+ ...getLightSourceUniforms({
5813
+ useByteColors,
5814
+ ambientLight,
5815
+ pointLights,
5816
+ spotLights,
5817
+ directionalLights
5818
+ })
5345
5819
  };
5346
5820
  if (props.enabled !== void 0) {
5347
5821
  uniforms.enabled = props.enabled ? 1 : 0;
@@ -5349,6 +5823,7 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5349
5823
  return uniforms;
5350
5824
  }
5351
5825
  function getLightSourceUniforms({
5826
+ useByteColors,
5352
5827
  ambientLight,
5353
5828
  pointLights = [],
5354
5829
  spotLights = [],
@@ -5365,7 +5840,7 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5365
5840
  }
5366
5841
  lights[currentLight] = {
5367
5842
  ...lights[currentLight],
5368
- color: convertColor(pointLight),
5843
+ color: convertColor(pointLight, useByteColors),
5369
5844
  position: pointLight.position,
5370
5845
  attenuation: pointLight.attenuation || [1, 0, 0]
5371
5846
  };
@@ -5378,7 +5853,7 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5378
5853
  }
5379
5854
  lights[currentLight] = {
5380
5855
  ...lights[currentLight],
5381
- color: convertColor(spotLight),
5856
+ color: convertColor(spotLight, useByteColors),
5382
5857
  position: spotLight.position,
5383
5858
  direction: spotLight.direction,
5384
5859
  attenuation: spotLight.attenuation || [1, 0, 0],
@@ -5393,7 +5868,7 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5393
5868
  }
5394
5869
  lights[currentLight] = {
5395
5870
  ...lights[currentLight],
5396
- color: convertColor(directionalLight),
5871
+ color: convertColor(directionalLight, useByteColors),
5397
5872
  direction: directionalLight.direction
5398
5873
  };
5399
5874
  currentLight++;
@@ -5403,7 +5878,7 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5403
5878
  import_core3.log.warn(`MAX_LIGHTS exceeded, truncating to ${MAX_LIGHTS}`)();
5404
5879
  }
5405
5880
  return {
5406
- ambientColor: convertColor(ambientLight),
5881
+ ambientColor: convertColor(ambientLight, useByteColors),
5407
5882
  directionalLightCount,
5408
5883
  pointLightCount,
5409
5884
  spotLightCount,
@@ -5431,9 +5906,10 @@ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>)
5431
5906
  }
5432
5907
  return lightSources;
5433
5908
  }
5434
- function convertColor(colorDef = {}) {
5909
+ function convertColor(colorDef = {}, useByteColors) {
5435
5910
  const { color = [0, 0, 0], intensity = 1 } = colorDef;
5436
- return color.map((component) => component * intensity / COLOR_FACTOR);
5911
+ const normalizedColor = normalizeByteColor3(color, resolveUseByteColors(useByteColors, true));
5912
+ return normalizedColor.map((component) => component * intensity);
5437
5913
  }
5438
5914
  function createDefaultLightingUniforms() {
5439
5915
  return {
@@ -5501,8 +5977,7 @@ uniform sampler2D pbr_brdfLUT;
5501
5977
  // src/modules/lighting/no-material/dirlight.ts
5502
5978
  var SOURCE_WGSL = (
5503
5979
  /* WGSL */
5504
- `
5505
- struct dirlightUniforms {
5980
+ `struct dirlightUniforms {
5506
5981
  lightDirection: vec3<f32>,
5507
5982
  };
5508
5983
 
@@ -5540,7 +6015,7 @@ void dirlight_setNormal(vec3 normal) {
5540
6015
  );
5541
6016
  var FS_GLSL = (
5542
6017
  /* glsl */
5543
- `uniform dirlightUniforms {
6018
+ `layout(std140) uniform dirlightUniforms {
5544
6019
  vec3 lightDirection;
5545
6020
  } dirlight;
5546
6021
 
@@ -5661,7 +6136,7 @@ fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, p
5661
6136
  // src/modules/lighting/lambert-material/lambert-shaders-glsl.ts
5662
6137
  var LAMBERT_VS = (
5663
6138
  /* glsl */
5664
- `uniform lambertMaterialUniforms {
6139
+ `layout(std140) uniform lambertMaterialUniforms {
5665
6140
  uniform bool unlit;
5666
6141
  uniform float ambient;
5667
6142
  uniform float diffuse;
@@ -5670,7 +6145,7 @@ fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, p
5670
6145
  );
5671
6146
  var LAMBERT_FS = (
5672
6147
  /* glsl */
5673
- `uniform lambertMaterialUniforms {
6148
+ `layout(std140) uniform lambertMaterialUniforms {
5674
6149
  uniform bool unlit;
5675
6150
  uniform float ambient;
5676
6151
  uniform float diffuse;
@@ -5750,7 +6225,7 @@ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 positio
5750
6225
  // src/modules/lighting/phong-material/phong-shaders-glsl.ts
5751
6226
  var PHONG_VS = (
5752
6227
  /* glsl */
5753
- `uniform phongMaterialUniforms {
6228
+ `layout(std140) uniform phongMaterialUniforms {
5754
6229
  uniform bool unlit;
5755
6230
  uniform float ambient;
5756
6231
  uniform float diffuse;
@@ -5761,7 +6236,7 @@ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 positio
5761
6236
  );
5762
6237
  var PHONG_FS = (
5763
6238
  /* glsl */
5764
- `uniform phongMaterialUniforms {
6239
+ `layout(std140) uniform phongMaterialUniforms {
5765
6240
  uniform bool unlit;
5766
6241
  uniform float ambient;
5767
6242
  uniform float diffuse;
@@ -5965,19 +6440,24 @@ fn lighting_getSpecularLightColor(cameraPosition: vec3<f32>, position_worldspace
5965
6440
  ambient: "f32",
5966
6441
  diffuse: "f32",
5967
6442
  shininess: "f32",
5968
- specularColor: "vec3<f32>"
6443
+ specularColor: "vec3<f32>",
6444
+ useByteColors: "i32"
5969
6445
  },
5970
6446
  defaultUniforms: {
5971
6447
  unlit: false,
5972
6448
  ambient: 0.35,
5973
6449
  diffuse: 0.6,
5974
6450
  shininess: 32,
5975
- specularColor: [0.15, 0.15, 0.15]
6451
+ specularColor: [0.15, 0.15, 0.15],
6452
+ useByteColors: true
5976
6453
  },
5977
6454
  getUniforms(props) {
5978
6455
  const uniforms = { ...props };
5979
6456
  if (uniforms.specularColor) {
5980
- uniforms.specularColor = uniforms.specularColor.map((x) => x / 255);
6457
+ uniforms.specularColor = normalizeByteColor3(
6458
+ uniforms.specularColor,
6459
+ resolveUseByteColors(uniforms.useByteColors, true)
6460
+ );
5981
6461
  }
5982
6462
  return { ...gouraudMaterial.defaultUniforms, ...uniforms };
5983
6463
  }
@@ -6001,19 +6481,24 @@ fn lighting_getSpecularLightColor(cameraPosition: vec3<f32>, position_worldspace
6001
6481
  ambient: "f32",
6002
6482
  diffuse: "f32",
6003
6483
  shininess: "f32",
6004
- specularColor: "vec3<f32>"
6484
+ specularColor: "vec3<f32>",
6485
+ useByteColors: "i32"
6005
6486
  },
6006
6487
  defaultUniforms: {
6007
6488
  unlit: false,
6008
6489
  ambient: 0.35,
6009
6490
  diffuse: 0.6,
6010
6491
  shininess: 32,
6011
- specularColor: [0.15, 0.15, 0.15]
6492
+ specularColor: [0.15, 0.15, 0.15],
6493
+ useByteColors: true
6012
6494
  },
6013
6495
  getUniforms(props) {
6014
6496
  const uniforms = { ...props };
6015
6497
  if (uniforms.specularColor) {
6016
- uniforms.specularColor = uniforms.specularColor.map((x) => x / 255);
6498
+ uniforms.specularColor = normalizeByteColor3(
6499
+ uniforms.specularColor,
6500
+ resolveUseByteColors(uniforms.useByteColors, true)
6501
+ );
6017
6502
  }
6018
6503
  return { ...phongMaterial.defaultUniforms, ...uniforms };
6019
6504
  }
@@ -6023,7 +6508,8 @@ fn lighting_getSpecularLightColor(cameraPosition: vec3<f32>, position_worldspace
6023
6508
  var vs3 = (
6024
6509
  /* glsl */
6025
6510
  `out vec3 pbr_vPosition;
6026
- out vec2 pbr_vUV;
6511
+ out vec2 pbr_vUV0;
6512
+ out vec2 pbr_vUV1;
6027
6513
 
6028
6514
  #ifdef HAS_NORMALS
6029
6515
  # ifdef HAS_TANGENTS
@@ -6033,7 +6519,13 @@ out vec3 pbr_vNormal;
6033
6519
  # endif
6034
6520
  #endif
6035
6521
 
6036
- void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv)
6522
+ void pbr_setPositionNormalTangentUV(
6523
+ vec4 position,
6524
+ vec4 normal,
6525
+ vec4 tangent,
6526
+ vec2 uv0,
6527
+ vec2 uv1
6528
+ )
6037
6529
  {
6038
6530
  vec4 pos = pbrProjection.modelMatrix * position;
6039
6531
  pbr_vPosition = vec3(pos.xyz) / pos.w;
@@ -6050,10 +6542,12 @@ void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, ve
6050
6542
  #endif
6051
6543
 
6052
6544
  #ifdef HAS_UV
6053
- pbr_vUV = uv;
6545
+ pbr_vUV0 = uv0;
6054
6546
  #else
6055
- pbr_vUV = vec2(0.,0.);
6547
+ pbr_vUV0 = vec2(0.,0.);
6056
6548
  #endif
6549
+
6550
+ pbr_vUV1 = uv1;
6057
6551
  }
6058
6552
  `
6059
6553
  );
@@ -6061,7 +6555,7 @@ void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, ve
6061
6555
  /* glsl */
6062
6556
  `precision highp float;
6063
6557
 
6064
- uniform pbrMaterialUniforms {
6558
+ layout(std140) uniform pbrMaterialUniforms {
6065
6559
  // Material is unlit
6066
6560
  bool unlit;
6067
6561
 
@@ -6129,6 +6623,41 @@ uniform pbrMaterialUniforms {
6129
6623
  vec4 scaleDiffBaseMR;
6130
6624
  vec4 scaleFGDSpec;
6131
6625
  // #endif
6626
+
6627
+ int baseColorUVSet;
6628
+ mat3 baseColorUVTransform;
6629
+ int metallicRoughnessUVSet;
6630
+ mat3 metallicRoughnessUVTransform;
6631
+ int normalUVSet;
6632
+ mat3 normalUVTransform;
6633
+ int occlusionUVSet;
6634
+ mat3 occlusionUVTransform;
6635
+ int emissiveUVSet;
6636
+ mat3 emissiveUVTransform;
6637
+ int specularColorUVSet;
6638
+ mat3 specularColorUVTransform;
6639
+ int specularIntensityUVSet;
6640
+ mat3 specularIntensityUVTransform;
6641
+ int transmissionUVSet;
6642
+ mat3 transmissionUVTransform;
6643
+ int thicknessUVSet;
6644
+ mat3 thicknessUVTransform;
6645
+ int clearcoatUVSet;
6646
+ mat3 clearcoatUVTransform;
6647
+ int clearcoatRoughnessUVSet;
6648
+ mat3 clearcoatRoughnessUVTransform;
6649
+ int clearcoatNormalUVSet;
6650
+ mat3 clearcoatNormalUVTransform;
6651
+ int sheenColorUVSet;
6652
+ mat3 sheenColorUVTransform;
6653
+ int sheenRoughnessUVSet;
6654
+ mat3 sheenRoughnessUVTransform;
6655
+ int iridescenceUVSet;
6656
+ mat3 iridescenceUVTransform;
6657
+ int iridescenceThicknessUVSet;
6658
+ mat3 iridescenceThicknessUVTransform;
6659
+ int anisotropyUVSet;
6660
+ mat3 anisotropyUVTransform;
6132
6661
  } pbrMaterial;
6133
6662
 
6134
6663
  // Samplers
@@ -6186,7 +6715,8 @@ uniform sampler2D pbr_anisotropySampler;
6186
6715
  // Inputs from vertex shader
6187
6716
 
6188
6717
  in vec3 pbr_vPosition;
6189
- in vec2 pbr_vUV;
6718
+ in vec2 pbr_vUV0;
6719
+ in vec2 pbr_vUV1;
6190
6720
 
6191
6721
  #ifdef HAS_NORMALS
6192
6722
  #ifdef HAS_TANGENTS
@@ -6236,14 +6766,20 @@ vec4 SRGBtoLINEAR(vec4 srgbIn)
6236
6766
  #endif //MANUAL_SRGB
6237
6767
  }
6238
6768
 
6769
+ vec2 getMaterialUV(int uvSet, mat3 uvTransform)
6770
+ {
6771
+ vec2 baseUV = uvSet == 1 ? pbr_vUV1 : pbr_vUV0;
6772
+ return (uvTransform * vec3(baseUV, 1.0)).xy;
6773
+ }
6774
+
6239
6775
  // Build the tangent basis from interpolated attributes or screen-space derivatives.
6240
- mat3 getTBN()
6776
+ mat3 getTBN(vec2 uv)
6241
6777
  {
6242
6778
  #ifndef HAS_TANGENTS
6243
6779
  vec3 pos_dx = dFdx(pbr_vPosition);
6244
6780
  vec3 pos_dy = dFdy(pbr_vPosition);
6245
- vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0));
6246
- vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0));
6781
+ vec3 tex_dx = dFdx(vec3(uv, 0.0));
6782
+ vec3 tex_dy = dFdy(vec3(uv, 0.0));
6247
6783
  vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
6248
6784
 
6249
6785
  #ifdef HAS_NORMALS
@@ -6264,16 +6800,16 @@ mat3 getTBN()
6264
6800
 
6265
6801
  // Find the normal for this fragment, pulling either from a predefined normal map
6266
6802
  // or from the interpolated mesh normal and tangent attributes.
6267
- vec3 getMappedNormal(sampler2D normalSampler, mat3 tbn, float normalScale)
6803
+ vec3 getMappedNormal(sampler2D normalSampler, mat3 tbn, float normalScale, vec2 uv)
6268
6804
  {
6269
- vec3 n = texture(normalSampler, pbr_vUV).rgb;
6805
+ vec3 n = texture(normalSampler, uv).rgb;
6270
6806
  return normalize(tbn * ((2.0 * n - 1.0) * vec3(normalScale, normalScale, 1.0)));
6271
6807
  }
6272
6808
 
6273
- vec3 getNormal(mat3 tbn)
6809
+ vec3 getNormal(mat3 tbn, vec2 uv)
6274
6810
  {
6275
6811
  #ifdef HAS_NORMALMAP
6276
- vec3 n = getMappedNormal(pbr_normalSampler, tbn, pbrMaterial.normalScale);
6812
+ vec3 n = getMappedNormal(pbr_normalSampler, tbn, pbrMaterial.normalScale, uv);
6277
6813
  #else
6278
6814
  // The tbn matrix is linearly interpolated, so we need to re-normalize
6279
6815
  vec3 n = normalize(tbn[2].xyz);
@@ -6282,10 +6818,10 @@ vec3 getNormal(mat3 tbn)
6282
6818
  return n;
6283
6819
  }
6284
6820
 
6285
- vec3 getClearcoatNormal(mat3 tbn, vec3 baseNormal)
6821
+ vec3 getClearcoatNormal(mat3 tbn, vec3 baseNormal, vec2 uv)
6286
6822
  {
6287
6823
  #ifdef HAS_CLEARCOATNORMALMAP
6288
- return getMappedNormal(pbr_clearcoatNormalSampler, tbn, 1.0);
6824
+ return getMappedNormal(pbr_clearcoatNormalSampler, tbn, 1.0, uv);
6289
6825
  #else
6290
6826
  return baseNormal;
6291
6827
  #endif
@@ -6573,9 +7109,61 @@ vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
6573
7109
 
6574
7110
  vec4 pbr_filterColor(vec4 colorUnused)
6575
7111
  {
7112
+ vec2 baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
7113
+ vec2 metallicRoughnessUV = getMaterialUV(
7114
+ pbrMaterial.metallicRoughnessUVSet,
7115
+ pbrMaterial.metallicRoughnessUVTransform
7116
+ );
7117
+ vec2 normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
7118
+ vec2 occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);
7119
+ vec2 emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);
7120
+ vec2 specularColorUV = getMaterialUV(
7121
+ pbrMaterial.specularColorUVSet,
7122
+ pbrMaterial.specularColorUVTransform
7123
+ );
7124
+ vec2 specularIntensityUV = getMaterialUV(
7125
+ pbrMaterial.specularIntensityUVSet,
7126
+ pbrMaterial.specularIntensityUVTransform
7127
+ );
7128
+ vec2 transmissionUV = getMaterialUV(
7129
+ pbrMaterial.transmissionUVSet,
7130
+ pbrMaterial.transmissionUVTransform
7131
+ );
7132
+ vec2 thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);
7133
+ vec2 clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);
7134
+ vec2 clearcoatRoughnessUV = getMaterialUV(
7135
+ pbrMaterial.clearcoatRoughnessUVSet,
7136
+ pbrMaterial.clearcoatRoughnessUVTransform
7137
+ );
7138
+ vec2 clearcoatNormalUV = getMaterialUV(
7139
+ pbrMaterial.clearcoatNormalUVSet,
7140
+ pbrMaterial.clearcoatNormalUVTransform
7141
+ );
7142
+ vec2 sheenColorUV = getMaterialUV(
7143
+ pbrMaterial.sheenColorUVSet,
7144
+ pbrMaterial.sheenColorUVTransform
7145
+ );
7146
+ vec2 sheenRoughnessUV = getMaterialUV(
7147
+ pbrMaterial.sheenRoughnessUVSet,
7148
+ pbrMaterial.sheenRoughnessUVTransform
7149
+ );
7150
+ vec2 iridescenceUV = getMaterialUV(
7151
+ pbrMaterial.iridescenceUVSet,
7152
+ pbrMaterial.iridescenceUVTransform
7153
+ );
7154
+ vec2 iridescenceThicknessUV = getMaterialUV(
7155
+ pbrMaterial.iridescenceThicknessUVSet,
7156
+ pbrMaterial.iridescenceThicknessUVTransform
7157
+ );
7158
+ vec2 anisotropyUV = getMaterialUV(
7159
+ pbrMaterial.anisotropyUVSet,
7160
+ pbrMaterial.anisotropyUVTransform
7161
+ );
7162
+
6576
7163
  // The albedo may be defined from a base texture or a flat color
6577
7164
  #ifdef HAS_BASECOLORMAP
6578
- vec4 baseColor = SRGBtoLINEAR(texture(pbr_baseColorSampler, pbr_vUV)) * pbrMaterial.baseColorFactor;
7165
+ vec4 baseColor =
7166
+ SRGBtoLINEAR(texture(pbr_baseColorSampler, baseColorUV)) * pbrMaterial.baseColorFactor;
6579
7167
  #else
6580
7168
  vec4 baseColor = pbrMaterial.baseColorFactor;
6581
7169
  #endif
@@ -6602,14 +7190,14 @@ vec4 pbr_filterColor(vec4 colorUnused)
6602
7190
  #ifdef HAS_METALROUGHNESSMAP
6603
7191
  // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
6604
7192
  // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
6605
- vec4 mrSample = texture(pbr_metallicRoughnessSampler, pbr_vUV);
7193
+ vec4 mrSample = texture(pbr_metallicRoughnessSampler, metallicRoughnessUV);
6606
7194
  perceptualRoughness = mrSample.g * perceptualRoughness;
6607
7195
  metallic = mrSample.b * metallic;
6608
7196
  #endif
6609
7197
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
6610
7198
  metallic = clamp(metallic, 0.0, 1.0);
6611
- mat3 tbn = getTBN();
6612
- vec3 n = getNormal(tbn); // normal at surface point
7199
+ mat3 tbn = getTBN(normalUV);
7200
+ vec3 n = getNormal(tbn, normalUV); // normal at surface point
6613
7201
  vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
6614
7202
  float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
6615
7203
  #ifdef USE_MATERIAL_EXTENSIONS
@@ -6710,7 +7298,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
6710
7298
 
6711
7299
  #ifdef HAS_OCCLUSIONMAP
6712
7300
  if (pbrMaterial.occlusionMapEnabled) {
6713
- float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
7301
+ float ao = texture(pbr_occlusionSampler, occlusionUV).r;
6714
7302
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
6715
7303
  }
6716
7304
  #endif
@@ -6718,7 +7306,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
6718
7306
  vec3 emissive = pbrMaterial.emissiveFactor;
6719
7307
  #ifdef HAS_EMISSIVEMAP
6720
7308
  if (pbrMaterial.emissiveMapEnabled) {
6721
- emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
7309
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, emissiveUV)).rgb;
6722
7310
  }
6723
7311
  #endif
6724
7312
  color += emissive * pbrMaterial.emissiveStrength;
@@ -6735,55 +7323,55 @@ vec4 pbr_filterColor(vec4 colorUnused)
6735
7323
  float specularIntensity = pbrMaterial.specularIntensityFactor;
6736
7324
  #ifdef HAS_SPECULARINTENSITYMAP
6737
7325
  if (pbrMaterial.specularIntensityMapEnabled) {
6738
- specularIntensity *= texture(pbr_specularIntensitySampler, pbr_vUV).a;
7326
+ specularIntensity *= texture(pbr_specularIntensitySampler, specularIntensityUV).a;
6739
7327
  }
6740
7328
  #endif
6741
7329
 
6742
7330
  vec3 specularFactor = pbrMaterial.specularColorFactor;
6743
7331
  #ifdef HAS_SPECULARCOLORMAP
6744
7332
  if (pbrMaterial.specularColorMapEnabled) {
6745
- specularFactor *= SRGBtoLINEAR(texture(pbr_specularColorSampler, pbr_vUV)).rgb;
7333
+ specularFactor *= SRGBtoLINEAR(texture(pbr_specularColorSampler, specularColorUV)).rgb;
6746
7334
  }
6747
7335
  #endif
6748
7336
 
6749
7337
  transmission = pbrMaterial.transmissionFactor;
6750
7338
  #ifdef HAS_TRANSMISSIONMAP
6751
7339
  if (pbrMaterial.transmissionMapEnabled) {
6752
- transmission *= texture(pbr_transmissionSampler, pbr_vUV).r;
7340
+ transmission *= texture(pbr_transmissionSampler, transmissionUV).r;
6753
7341
  }
6754
7342
  #endif
6755
7343
  transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);
6756
7344
  float thickness = max(pbrMaterial.thicknessFactor, 0.0);
6757
7345
  #ifdef HAS_THICKNESSMAP
6758
- thickness *= texture(pbr_thicknessSampler, pbr_vUV).g;
7346
+ thickness *= texture(pbr_thicknessSampler, thicknessUV).g;
6759
7347
  #endif
6760
7348
 
6761
7349
  float clearcoatFactor = pbrMaterial.clearcoatFactor;
6762
7350
  float clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;
6763
7351
  #ifdef HAS_CLEARCOATMAP
6764
7352
  if (pbrMaterial.clearcoatMapEnabled) {
6765
- clearcoatFactor *= texture(pbr_clearcoatSampler, pbr_vUV).r;
7353
+ clearcoatFactor *= texture(pbr_clearcoatSampler, clearcoatUV).r;
6766
7354
  }
6767
7355
  #endif
6768
7356
  #ifdef HAS_CLEARCOATROUGHNESSMAP
6769
7357
  if (pbrMaterial.clearcoatRoughnessMapEnabled) {
6770
- clearcoatRoughness *= texture(pbr_clearcoatRoughnessSampler, pbr_vUV).g;
7358
+ clearcoatRoughness *= texture(pbr_clearcoatRoughnessSampler, clearcoatRoughnessUV).g;
6771
7359
  }
6772
7360
  #endif
6773
7361
  clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
6774
7362
  clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
6775
- vec3 clearcoatNormal = getClearcoatNormal(tbn, n);
7363
+ vec3 clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);
6776
7364
 
6777
7365
  vec3 sheenColor = pbrMaterial.sheenColorFactor;
6778
7366
  float sheenRoughness = pbrMaterial.sheenRoughnessFactor;
6779
7367
  #ifdef HAS_SHEENCOLORMAP
6780
7368
  if (pbrMaterial.sheenColorMapEnabled) {
6781
- sheenColor *= SRGBtoLINEAR(texture(pbr_sheenColorSampler, pbr_vUV)).rgb;
7369
+ sheenColor *= SRGBtoLINEAR(texture(pbr_sheenColorSampler, sheenColorUV)).rgb;
6782
7370
  }
6783
7371
  #endif
6784
7372
  #ifdef HAS_SHEENROUGHNESSMAP
6785
7373
  if (pbrMaterial.sheenRoughnessMapEnabled) {
6786
- sheenRoughness *= texture(pbr_sheenRoughnessSampler, pbr_vUV).a;
7374
+ sheenRoughness *= texture(pbr_sheenRoughnessSampler, sheenRoughnessUV).a;
6787
7375
  }
6788
7376
  #endif
6789
7377
  sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);
@@ -6791,7 +7379,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
6791
7379
  float iridescence = pbrMaterial.iridescenceFactor;
6792
7380
  #ifdef HAS_IRIDESCENCEMAP
6793
7381
  if (pbrMaterial.iridescenceMapEnabled) {
6794
- iridescence *= texture(pbr_iridescenceSampler, pbr_vUV).r;
7382
+ iridescence *= texture(pbr_iridescenceSampler, iridescenceUV).r;
6795
7383
  }
6796
7384
  #endif
6797
7385
  iridescence = clamp(iridescence, 0.0, 1.0);
@@ -6804,7 +7392,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
6804
7392
  iridescenceThickness = mix(
6805
7393
  pbrMaterial.iridescenceThicknessRange.x,
6806
7394
  pbrMaterial.iridescenceThicknessRange.y,
6807
- texture(pbr_iridescenceThicknessSampler, pbr_vUV).g
7395
+ texture(pbr_iridescenceThicknessSampler, iridescenceThicknessUV).g
6808
7396
  );
6809
7397
  #endif
6810
7398
 
@@ -6812,7 +7400,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
6812
7400
  vec2 anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);
6813
7401
  #ifdef HAS_ANISOTROPYMAP
6814
7402
  if (pbrMaterial.anisotropyMapEnabled) {
6815
- vec3 anisotropySample = texture(pbr_anisotropySampler, pbr_vUV).rgb;
7403
+ vec3 anisotropySample = texture(pbr_anisotropySampler, anisotropyUV).rgb;
6816
7404
  anisotropyStrength *= anisotropySample.b;
6817
7405
  vec2 mappedDirection = anisotropySample.rg * 2.0 - 1.0;
6818
7406
  if (length(mappedDirection) > 0.0001) {
@@ -6975,7 +7563,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
6975
7563
  // Apply optional PBR terms for additional (optional) shading
6976
7564
  #ifdef HAS_OCCLUSIONMAP
6977
7565
  if (pbrMaterial.occlusionMapEnabled) {
6978
- float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
7566
+ float ao = texture(pbr_occlusionSampler, occlusionUV).r;
6979
7567
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
6980
7568
  }
6981
7569
  #endif
@@ -6983,7 +7571,7 @@ vec4 pbr_filterColor(vec4 colorUnused)
6983
7571
  vec3 emissive = pbrMaterial.emissiveFactor;
6984
7572
  #ifdef HAS_EMISSIVEMAP
6985
7573
  if (pbrMaterial.emissiveMapEnabled) {
6986
- emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
7574
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, emissiveUV)).rgb;
6987
7575
  }
6988
7576
  #endif
6989
7577
  color += emissive * pbrMaterial.emissiveStrength;
@@ -7021,14 +7609,21 @@ vec4 pbr_filterColor(vec4 colorUnused)
7021
7609
  /* wgsl */
7022
7610
  `struct PBRFragmentInputs {
7023
7611
  pbr_vPosition: vec3f,
7024
- pbr_vUV: vec2f,
7612
+ pbr_vUV0: vec2f,
7613
+ pbr_vUV1: vec2f,
7025
7614
  pbr_vTBN: mat3x3f,
7026
7615
  pbr_vNormal: vec3f
7027
7616
  };
7028
7617
 
7029
7618
  var<private> fragmentInputs: PBRFragmentInputs;
7030
7619
 
7031
- fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f, uv: vec2f)
7620
+ fn pbr_setPositionNormalTangentUV(
7621
+ position: vec4f,
7622
+ normal: vec4f,
7623
+ tangent: vec4f,
7624
+ uv0: vec2f,
7625
+ uv1: vec2f
7626
+ )
7032
7627
  {
7033
7628
  var pos: vec4f = pbrProjection.modelMatrix * position;
7034
7629
  fragmentInputs.pbr_vPosition = pos.xyz / pos.w;
@@ -7038,7 +7633,8 @@ fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f
7038
7633
  vec3f(0.0, 1.0, 0.0),
7039
7634
  vec3f(0.0, 0.0, 1.0)
7040
7635
  );
7041
- fragmentInputs.pbr_vUV = vec2f(0.0, 0.0);
7636
+ fragmentInputs.pbr_vUV0 = vec2f(0.0, 0.0);
7637
+ fragmentInputs.pbr_vUV1 = uv1;
7042
7638
 
7043
7639
  #ifdef HAS_NORMALS
7044
7640
  let normalW: vec3f = normalize((pbrProjection.normalMatrix * vec4f(normal.xyz, 0.0)).xyz);
@@ -7051,7 +7647,7 @@ fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f
7051
7647
  #endif
7052
7648
 
7053
7649
  #ifdef HAS_UV
7054
- fragmentInputs.pbr_vUV = uv;
7650
+ fragmentInputs.pbr_vUV0 = uv0;
7055
7651
  #endif
7056
7652
  }
7057
7653
 
@@ -7123,6 +7719,41 @@ struct pbrMaterialUniforms {
7123
7719
  scaleDiffBaseMR: vec4f,
7124
7720
  scaleFGDSpec: vec4f,
7125
7721
  // #endif
7722
+
7723
+ baseColorUVSet: i32,
7724
+ baseColorUVTransform: mat3x3f,
7725
+ metallicRoughnessUVSet: i32,
7726
+ metallicRoughnessUVTransform: mat3x3f,
7727
+ normalUVSet: i32,
7728
+ normalUVTransform: mat3x3f,
7729
+ occlusionUVSet: i32,
7730
+ occlusionUVTransform: mat3x3f,
7731
+ emissiveUVSet: i32,
7732
+ emissiveUVTransform: mat3x3f,
7733
+ specularColorUVSet: i32,
7734
+ specularColorUVTransform: mat3x3f,
7735
+ specularIntensityUVSet: i32,
7736
+ specularIntensityUVTransform: mat3x3f,
7737
+ transmissionUVSet: i32,
7738
+ transmissionUVTransform: mat3x3f,
7739
+ thicknessUVSet: i32,
7740
+ thicknessUVTransform: mat3x3f,
7741
+ clearcoatUVSet: i32,
7742
+ clearcoatUVTransform: mat3x3f,
7743
+ clearcoatRoughnessUVSet: i32,
7744
+ clearcoatRoughnessUVTransform: mat3x3f,
7745
+ clearcoatNormalUVSet: i32,
7746
+ clearcoatNormalUVTransform: mat3x3f,
7747
+ sheenColorUVSet: i32,
7748
+ sheenColorUVTransform: mat3x3f,
7749
+ sheenRoughnessUVSet: i32,
7750
+ sheenRoughnessUVTransform: mat3x3f,
7751
+ iridescenceUVSet: i32,
7752
+ iridescenceUVTransform: mat3x3f,
7753
+ iridescenceThicknessUVSet: i32,
7754
+ iridescenceThicknessUVTransform: mat3x3f,
7755
+ anisotropyUVSet: i32,
7756
+ anisotropyUVTransform: mat3x3f,
7126
7757
  }
7127
7758
 
7128
7759
  @group(3) @binding(auto) var<uniform> pbrMaterial : pbrMaterialUniforms;
@@ -7236,13 +7867,22 @@ fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
7236
7867
  return vec4f(linOut, srgbIn.w);
7237
7868
  }
7238
7869
 
7870
+ fn getMaterialUV(uvSet: i32, uvTransform: mat3x3f) -> vec2f
7871
+ {
7872
+ var baseUV = fragmentInputs.pbr_vUV0;
7873
+ if (uvSet == 1) {
7874
+ baseUV = fragmentInputs.pbr_vUV1;
7875
+ }
7876
+ return (uvTransform * vec3f(baseUV, 1.0)).xy;
7877
+ }
7878
+
7239
7879
  // Build the tangent basis from interpolated attributes or screen-space derivatives.
7240
- fn getTBN() -> mat3x3f
7880
+ fn getTBN(uv: vec2f) -> mat3x3f
7241
7881
  {
7242
7882
  let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);
7243
7883
  let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);
7244
- let tex_dx: vec3f = dpdx(vec3f(fragmentInputs.pbr_vUV, 0.0));
7245
- let tex_dy: vec3f = dpdy(vec3f(fragmentInputs.pbr_vUV, 0.0));
7884
+ let tex_dx: vec3f = dpdx(vec3f(uv, 0.0));
7885
+ let tex_dy: vec3f = dpdy(vec3f(uv, 0.0));
7246
7886
  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);
7247
7887
 
7248
7888
  var ng: vec3f = cross(pos_dx, pos_dy);
@@ -7265,14 +7905,15 @@ fn getMappedNormal(
7265
7905
  normalSampler: texture_2d<f32>,
7266
7906
  normalSamplerBinding: sampler,
7267
7907
  tbn: mat3x3f,
7268
- normalScale: f32
7908
+ normalScale: f32,
7909
+ uv: vec2f
7269
7910
  ) -> vec3f
7270
7911
  {
7271
- let n = textureSample(normalSampler, normalSamplerBinding, fragmentInputs.pbr_vUV).rgb;
7912
+ let n = textureSample(normalSampler, normalSamplerBinding, uv).rgb;
7272
7913
  return normalize(tbn * ((2.0 * n - 1.0) * vec3f(normalScale, normalScale, 1.0)));
7273
7914
  }
7274
7915
 
7275
- fn getNormal(tbn: mat3x3f) -> vec3f
7916
+ fn getNormal(tbn: mat3x3f, uv: vec2f) -> vec3f
7276
7917
  {
7277
7918
  // The tbn matrix is linearly interpolated, so we need to re-normalize
7278
7919
  var n: vec3f = normalize(tbn[2].xyz);
@@ -7281,21 +7922,23 @@ fn getNormal(tbn: mat3x3f) -> vec3f
7281
7922
  pbr_normalSampler,
7282
7923
  pbr_normalSamplerSampler,
7283
7924
  tbn,
7284
- pbrMaterial.normalScale
7925
+ pbrMaterial.normalScale,
7926
+ uv
7285
7927
  );
7286
7928
  #endif
7287
7929
 
7288
7930
  return n;
7289
7931
  }
7290
7932
 
7291
- fn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f) -> vec3f
7933
+ fn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f, uv: vec2f) -> vec3f
7292
7934
  {
7293
7935
  #ifdef HAS_CLEARCOATNORMALMAP
7294
7936
  return getMappedNormal(
7295
7937
  pbr_clearcoatNormalSampler,
7296
7938
  pbr_clearcoatNormalSamplerSampler,
7297
7939
  tbn,
7298
- 1.0
7940
+ 1.0,
7941
+ uv
7299
7942
  );
7300
7943
  #else
7301
7944
  return baseNormal;
@@ -7600,11 +8243,62 @@ fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
7600
8243
  }
7601
8244
 
7602
8245
  fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
8246
+ let baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
8247
+ let metallicRoughnessUV = getMaterialUV(
8248
+ pbrMaterial.metallicRoughnessUVSet,
8249
+ pbrMaterial.metallicRoughnessUVTransform
8250
+ );
8251
+ let normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
8252
+ let occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);
8253
+ let emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);
8254
+ let specularColorUV = getMaterialUV(
8255
+ pbrMaterial.specularColorUVSet,
8256
+ pbrMaterial.specularColorUVTransform
8257
+ );
8258
+ let specularIntensityUV = getMaterialUV(
8259
+ pbrMaterial.specularIntensityUVSet,
8260
+ pbrMaterial.specularIntensityUVTransform
8261
+ );
8262
+ let transmissionUV = getMaterialUV(
8263
+ pbrMaterial.transmissionUVSet,
8264
+ pbrMaterial.transmissionUVTransform
8265
+ );
8266
+ let thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);
8267
+ let clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);
8268
+ let clearcoatRoughnessUV = getMaterialUV(
8269
+ pbrMaterial.clearcoatRoughnessUVSet,
8270
+ pbrMaterial.clearcoatRoughnessUVTransform
8271
+ );
8272
+ let clearcoatNormalUV = getMaterialUV(
8273
+ pbrMaterial.clearcoatNormalUVSet,
8274
+ pbrMaterial.clearcoatNormalUVTransform
8275
+ );
8276
+ let sheenColorUV = getMaterialUV(
8277
+ pbrMaterial.sheenColorUVSet,
8278
+ pbrMaterial.sheenColorUVTransform
8279
+ );
8280
+ let sheenRoughnessUV = getMaterialUV(
8281
+ pbrMaterial.sheenRoughnessUVSet,
8282
+ pbrMaterial.sheenRoughnessUVTransform
8283
+ );
8284
+ let iridescenceUV = getMaterialUV(
8285
+ pbrMaterial.iridescenceUVSet,
8286
+ pbrMaterial.iridescenceUVTransform
8287
+ );
8288
+ let iridescenceThicknessUV = getMaterialUV(
8289
+ pbrMaterial.iridescenceThicknessUVSet,
8290
+ pbrMaterial.iridescenceThicknessUVTransform
8291
+ );
8292
+ let anisotropyUV = getMaterialUV(
8293
+ pbrMaterial.anisotropyUVSet,
8294
+ pbrMaterial.anisotropyUVTransform
8295
+ );
8296
+
7603
8297
  // The albedo may be defined from a base texture or a flat color
7604
8298
  var baseColor: vec4<f32> = pbrMaterial.baseColorFactor;
7605
8299
  #ifdef HAS_BASECOLORMAP
7606
8300
  baseColor = SRGBtoLINEAR(
7607
- textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, fragmentInputs.pbr_vUV)
8301
+ textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, baseColorUV)
7608
8302
  ) * pbrMaterial.baseColorFactor;
7609
8303
  #endif
7610
8304
 
@@ -7631,15 +8325,15 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7631
8325
  let mrSample = textureSample(
7632
8326
  pbr_metallicRoughnessSampler,
7633
8327
  pbr_metallicRoughnessSamplerSampler,
7634
- fragmentInputs.pbr_vUV
8328
+ metallicRoughnessUV
7635
8329
  );
7636
8330
  perceptualRoughness = mrSample.g * perceptualRoughness;
7637
8331
  metallic = mrSample.b * metallic;
7638
8332
  #endif
7639
8333
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
7640
8334
  metallic = clamp(metallic, 0.0, 1.0);
7641
- let tbn = getTBN();
7642
- let n = getNormal(tbn); // normal at surface point
8335
+ let tbn = getTBN(normalUV);
8336
+ let n = getNormal(tbn, normalUV); // normal at surface point
7643
8337
  let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera
7644
8338
  let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
7645
8339
  var useExtendedPBR = false;
@@ -7744,8 +8438,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7744
8438
 
7745
8439
  #ifdef HAS_OCCLUSIONMAP
7746
8440
  if (pbrMaterial.occlusionMapEnabled != 0) {
7747
- let ao =
7748
- textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, fragmentInputs.pbr_vUV).r;
8441
+ let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;
7749
8442
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
7750
8443
  }
7751
8444
  #endif
@@ -7754,7 +8447,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7754
8447
  #ifdef HAS_EMISSIVEMAP
7755
8448
  if (pbrMaterial.emissiveMapEnabled != 0u) {
7756
8449
  emissive *= SRGBtoLINEAR(
7757
- textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
8450
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)
7758
8451
  ).rgb;
7759
8452
  }
7760
8453
  #endif
@@ -7775,7 +8468,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7775
8468
  specularIntensity *= textureSample(
7776
8469
  pbr_specularIntensitySampler,
7777
8470
  pbr_specularIntensitySamplerSampler,
7778
- fragmentInputs.pbr_vUV
8471
+ specularIntensityUV
7779
8472
  ).a;
7780
8473
  }
7781
8474
  #endif
@@ -7787,7 +8480,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7787
8480
  textureSample(
7788
8481
  pbr_specularColorSampler,
7789
8482
  pbr_specularColorSamplerSampler,
7790
- fragmentInputs.pbr_vUV
8483
+ specularColorUV
7791
8484
  )
7792
8485
  ).rgb;
7793
8486
  }
@@ -7799,7 +8492,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7799
8492
  transmission *= textureSample(
7800
8493
  pbr_transmissionSampler,
7801
8494
  pbr_transmissionSamplerSampler,
7802
- fragmentInputs.pbr_vUV
8495
+ transmissionUV
7803
8496
  ).r;
7804
8497
  }
7805
8498
  #endif
@@ -7809,7 +8502,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7809
8502
  thickness *= textureSample(
7810
8503
  pbr_thicknessSampler,
7811
8504
  pbr_thicknessSamplerSampler,
7812
- fragmentInputs.pbr_vUV
8505
+ thicknessUV
7813
8506
  ).g;
7814
8507
  #endif
7815
8508
 
@@ -7820,7 +8513,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7820
8513
  clearcoatFactor *= textureSample(
7821
8514
  pbr_clearcoatSampler,
7822
8515
  pbr_clearcoatSamplerSampler,
7823
- fragmentInputs.pbr_vUV
8516
+ clearcoatUV
7824
8517
  ).r;
7825
8518
  }
7826
8519
  #endif
@@ -7829,13 +8522,13 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7829
8522
  clearcoatRoughness *= textureSample(
7830
8523
  pbr_clearcoatRoughnessSampler,
7831
8524
  pbr_clearcoatRoughnessSamplerSampler,
7832
- fragmentInputs.pbr_vUV
8525
+ clearcoatRoughnessUV
7833
8526
  ).g;
7834
8527
  }
7835
8528
  #endif
7836
8529
  clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
7837
8530
  clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
7838
- let clearcoatNormal = getClearcoatNormal(tbn, n);
8531
+ let clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);
7839
8532
 
7840
8533
  var sheenColor = pbrMaterial.sheenColorFactor;
7841
8534
  var sheenRoughness = pbrMaterial.sheenRoughnessFactor;
@@ -7845,7 +8538,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7845
8538
  textureSample(
7846
8539
  pbr_sheenColorSampler,
7847
8540
  pbr_sheenColorSamplerSampler,
7848
- fragmentInputs.pbr_vUV
8541
+ sheenColorUV
7849
8542
  )
7850
8543
  ).rgb;
7851
8544
  }
@@ -7855,7 +8548,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7855
8548
  sheenRoughness *= textureSample(
7856
8549
  pbr_sheenRoughnessSampler,
7857
8550
  pbr_sheenRoughnessSamplerSampler,
7858
- fragmentInputs.pbr_vUV
8551
+ sheenRoughnessUV
7859
8552
  ).a;
7860
8553
  }
7861
8554
  #endif
@@ -7867,7 +8560,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7867
8560
  iridescence *= textureSample(
7868
8561
  pbr_iridescenceSampler,
7869
8562
  pbr_iridescenceSamplerSampler,
7870
- fragmentInputs.pbr_vUV
8563
+ iridescenceUV
7871
8564
  ).r;
7872
8565
  }
7873
8566
  #endif
@@ -7884,7 +8577,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7884
8577
  textureSample(
7885
8578
  pbr_iridescenceThicknessSampler,
7886
8579
  pbr_iridescenceThicknessSamplerSampler,
7887
- fragmentInputs.pbr_vUV
8580
+ iridescenceThicknessUV
7888
8581
  ).g
7889
8582
  );
7890
8583
  #endif
@@ -7896,7 +8589,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
7896
8589
  let anisotropySample = textureSample(
7897
8590
  pbr_anisotropySampler,
7898
8591
  pbr_anisotropySamplerSampler,
7899
- fragmentInputs.pbr_vUV
8592
+ anisotropyUV
7900
8593
  ).rgb;
7901
8594
  anisotropyStrength *= anisotropySample.b;
7902
8595
  let mappedDirection = anisotropySample.rg * 2.0 - 1.0;
@@ -8063,8 +8756,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
8063
8756
  // Apply optional PBR terms for additional (optional) shading
8064
8757
  #ifdef HAS_OCCLUSIONMAP
8065
8758
  if (pbrMaterial.occlusionMapEnabled != 0) {
8066
- let ao =
8067
- textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, fragmentInputs.pbr_vUV).r;
8759
+ let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;
8068
8760
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
8069
8761
  }
8070
8762
  #endif
@@ -8073,7 +8765,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
8073
8765
  #ifdef HAS_EMISSIVEMAP
8074
8766
  if (pbrMaterial.emissiveMapEnabled != 0u) {
8075
8767
  emissive *= SRGBtoLINEAR(
8076
- textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
8768
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)
8077
8769
  ).rgb;
8078
8770
  }
8079
8771
  #endif
@@ -8109,7 +8801,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
8109
8801
  // src/modules/lighting/pbr-material/pbr-projection.ts
8110
8802
  var uniformBlock = (
8111
8803
  /* glsl */
8112
- `uniform pbrProjectionUniforms {
8804
+ `layout(std140) uniform pbrProjectionUniforms {
8113
8805
  mat4 modelViewProjectionMatrix;
8114
8806
  mat4 modelMatrix;
8115
8807
  mat4 normalMatrix;
@@ -8193,7 +8885,41 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
8193
8885
  anisotropyRotation: 0,
8194
8886
  anisotropyDirection: [1, 0],
8195
8887
  anisotropyMapEnabled: false,
8196
- emissiveStrength: 1
8888
+ emissiveStrength: 1,
8889
+ baseColorUVSet: 0,
8890
+ baseColorUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8891
+ metallicRoughnessUVSet: 0,
8892
+ metallicRoughnessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8893
+ normalUVSet: 0,
8894
+ normalUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8895
+ occlusionUVSet: 0,
8896
+ occlusionUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8897
+ emissiveUVSet: 0,
8898
+ emissiveUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8899
+ specularColorUVSet: 0,
8900
+ specularColorUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8901
+ specularIntensityUVSet: 0,
8902
+ specularIntensityUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8903
+ transmissionUVSet: 0,
8904
+ transmissionUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8905
+ thicknessUVSet: 0,
8906
+ thicknessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8907
+ clearcoatUVSet: 0,
8908
+ clearcoatUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8909
+ clearcoatRoughnessUVSet: 0,
8910
+ clearcoatRoughnessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8911
+ clearcoatNormalUVSet: 0,
8912
+ clearcoatNormalUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8913
+ sheenColorUVSet: 0,
8914
+ sheenColorUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8915
+ sheenRoughnessUVSet: 0,
8916
+ sheenRoughnessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8917
+ iridescenceUVSet: 0,
8918
+ iridescenceUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8919
+ iridescenceThicknessUVSet: 0,
8920
+ iridescenceThicknessUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1],
8921
+ anisotropyUVSet: 0,
8922
+ anisotropyUVTransform: [1, 0, 0, 0, 1, 0, 0, 0, 1]
8197
8923
  },
8198
8924
  name: "pbrMaterial",
8199
8925
  firstBindingSlot: 0,
@@ -8300,7 +9026,110 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
8300
9026
  // debugging flags used for shader output of intermediate PBR variables
8301
9027
  // #ifdef PBR_DEBUG
8302
9028
  scaleDiffBaseMR: "vec4<f32>",
8303
- scaleFGDSpec: "vec4<f32>"
9029
+ scaleFGDSpec: "vec4<f32>",
9030
+ baseColorUVSet: "i32",
9031
+ baseColorUVTransform: "mat3x3<f32>",
9032
+ metallicRoughnessUVSet: "i32",
9033
+ metallicRoughnessUVTransform: "mat3x3<f32>",
9034
+ normalUVSet: "i32",
9035
+ normalUVTransform: "mat3x3<f32>",
9036
+ occlusionUVSet: "i32",
9037
+ occlusionUVTransform: "mat3x3<f32>",
9038
+ emissiveUVSet: "i32",
9039
+ emissiveUVTransform: "mat3x3<f32>",
9040
+ specularColorUVSet: "i32",
9041
+ specularColorUVTransform: "mat3x3<f32>",
9042
+ specularIntensityUVSet: "i32",
9043
+ specularIntensityUVTransform: "mat3x3<f32>",
9044
+ transmissionUVSet: "i32",
9045
+ transmissionUVTransform: "mat3x3<f32>",
9046
+ thicknessUVSet: "i32",
9047
+ thicknessUVTransform: "mat3x3<f32>",
9048
+ clearcoatUVSet: "i32",
9049
+ clearcoatUVTransform: "mat3x3<f32>",
9050
+ clearcoatRoughnessUVSet: "i32",
9051
+ clearcoatRoughnessUVTransform: "mat3x3<f32>",
9052
+ clearcoatNormalUVSet: "i32",
9053
+ clearcoatNormalUVTransform: "mat3x3<f32>",
9054
+ sheenColorUVSet: "i32",
9055
+ sheenColorUVTransform: "mat3x3<f32>",
9056
+ sheenRoughnessUVSet: "i32",
9057
+ sheenRoughnessUVTransform: "mat3x3<f32>",
9058
+ iridescenceUVSet: "i32",
9059
+ iridescenceUVTransform: "mat3x3<f32>",
9060
+ iridescenceThicknessUVSet: "i32",
9061
+ iridescenceThicknessUVTransform: "mat3x3<f32>",
9062
+ anisotropyUVSet: "i32",
9063
+ anisotropyUVTransform: "mat3x3<f32>"
9064
+ }
9065
+ };
9066
+
9067
+ // src/modules/lighting/pbr-material/pbr-scene.ts
9068
+ var IDENTITY_MATRIX2 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
9069
+ var uniformBlock2 = (
9070
+ /* glsl */
9071
+ `layout(std140) uniform pbrSceneUniforms {
9072
+ float exposure;
9073
+ int toneMapMode;
9074
+ float environmentIntensity;
9075
+ float environmentRotation;
9076
+ vec2 framebufferSize;
9077
+ mat4 viewMatrix;
9078
+ mat4 projectionMatrix;
9079
+ } pbrScene;
9080
+
9081
+ #ifdef USE_TRANSMISSION_FRAMEBUFFER
9082
+ uniform sampler2D pbr_transmissionFramebufferSampler;
9083
+ #endif
9084
+ `
9085
+ );
9086
+ var wgslUniformBlock2 = (
9087
+ /* wgsl */
9088
+ `struct pbrSceneUniforms {
9089
+ exposure: f32,
9090
+ toneMapMode: i32,
9091
+ environmentIntensity: f32,
9092
+ environmentRotation: f32,
9093
+ framebufferSize: vec2<f32>,
9094
+ viewMatrix: mat4x4<f32>,
9095
+ projectionMatrix: mat4x4<f32>
9096
+ };
9097
+
9098
+ @group(1) @binding(auto) var<uniform> pbrScene: pbrSceneUniforms;
9099
+
9100
+ #ifdef USE_TRANSMISSION_FRAMEBUFFER
9101
+ @group(1) @binding(auto) var pbr_transmissionFramebufferSampler: texture_2d<f32>;
9102
+ @group(1) @binding(auto) var pbr_transmissionFramebufferSamplerSampler: sampler;
9103
+ #endif
9104
+ `
9105
+ );
9106
+ var pbrScene = {
9107
+ name: "pbrScene",
9108
+ bindingLayout: [
9109
+ { name: "pbrScene", group: 1 },
9110
+ { name: "pbr_transmissionFramebufferSampler", group: 1 }
9111
+ ],
9112
+ source: wgslUniformBlock2,
9113
+ vs: uniformBlock2,
9114
+ fs: uniformBlock2,
9115
+ getUniforms: (props) => props,
9116
+ uniformTypes: {
9117
+ exposure: "f32",
9118
+ toneMapMode: "i32",
9119
+ environmentIntensity: "f32",
9120
+ environmentRotation: "f32",
9121
+ framebufferSize: "vec2<f32>",
9122
+ viewMatrix: "mat4x4<f32>",
9123
+ projectionMatrix: "mat4x4<f32>"
9124
+ },
9125
+ defaultUniforms: {
9126
+ exposure: 1,
9127
+ toneMapMode: 2,
9128
+ environmentIntensity: 1,
9129
+ environmentRotation: Math.PI * 0.5,
9130
+ framebufferSize: [1, 1],
9131
+ viewMatrix: IDENTITY_MATRIX2,
9132
+ projectionMatrix: IDENTITY_MATRIX2
8304
9133
  }
8305
9134
  };
8306
9135
  return __toCommonJS(bundle_exports);