@luma.gl/shadertools 9.3.0-alpha.6 → 9.3.0-alpha.9

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 (152) hide show
  1. package/dist/dist.dev.js +2550 -331
  2. package/dist/dist.min.js +1803 -283
  3. package/dist/index.cjs +2496 -358
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +9 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
  10. package/dist/lib/preprocessor/preprocessor.js +4 -3
  11. package/dist/lib/preprocessor/preprocessor.js.map +1 -1
  12. package/dist/lib/shader-assembler.d.ts +10 -0
  13. package/dist/lib/shader-assembler.d.ts.map +1 -1
  14. package/dist/lib/shader-assembler.js +12 -2
  15. package/dist/lib/shader-assembler.js.map +1 -1
  16. package/dist/lib/shader-assembly/assemble-shaders.d.ts +23 -2
  17. package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
  18. package/dist/lib/shader-assembly/assemble-shaders.js +211 -11
  19. package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
  20. package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts +37 -0
  21. package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts.map +1 -0
  22. package/dist/lib/shader-assembly/wgsl-binding-debug.js +140 -0
  23. package/dist/lib/shader-assembly/wgsl-binding-debug.js.map +1 -0
  24. package/dist/lib/shader-generator/glsl/generate-glsl.js +3 -0
  25. package/dist/lib/shader-generator/glsl/generate-glsl.js.map +1 -1
  26. package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts.map +1 -1
  27. package/dist/lib/shader-generator/wgsl/generate-wgsl.js +3 -0
  28. package/dist/lib/shader-generator/wgsl/generate-wgsl.js.map +1 -1
  29. package/dist/lib/shader-module/shader-module-uniform-layout.d.ts +22 -0
  30. package/dist/lib/shader-module/shader-module-uniform-layout.d.ts.map +1 -0
  31. package/dist/lib/shader-module/shader-module-uniform-layout.js +113 -0
  32. package/dist/lib/shader-module/shader-module-uniform-layout.js.map +1 -0
  33. package/dist/lib/shader-module/shader-module.d.ts +11 -5
  34. package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
  35. package/dist/lib/shader-module/shader-module.js.map +1 -1
  36. package/dist/lib/utils/uniform-types.d.ts +11 -7
  37. package/dist/lib/utils/uniform-types.d.ts.map +1 -1
  38. package/dist/modules/engine/picking/picking.d.ts +3 -0
  39. package/dist/modules/engine/picking/picking.d.ts.map +1 -1
  40. package/dist/modules/engine/picking/picking.js +3 -0
  41. package/dist/modules/engine/picking/picking.js.map +1 -1
  42. package/dist/modules/engine/skin/skin.d.ts +7 -6
  43. package/dist/modules/engine/skin/skin.d.ts.map +1 -1
  44. package/dist/modules/engine/skin/skin.js +3 -5
  45. package/dist/modules/engine/skin/skin.js.map +1 -1
  46. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts +1 -0
  47. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts.map +1 -1
  48. package/dist/modules/lighting/gouraud-material/gouraud-material.js +3 -0
  49. package/dist/modules/lighting/gouraud-material/gouraud-material.js.map +1 -1
  50. package/dist/modules/lighting/ibl/ibl.d.ts +26 -0
  51. package/dist/modules/lighting/ibl/ibl.d.ts.map +1 -0
  52. package/dist/modules/lighting/ibl/ibl.js +33 -0
  53. package/dist/modules/lighting/ibl/ibl.js.map +1 -0
  54. package/dist/modules/lighting/lambert-material/lambert-material.d.ts +10 -0
  55. package/dist/modules/lighting/lambert-material/lambert-material.d.ts.map +1 -0
  56. package/dist/modules/lighting/lambert-material/lambert-material.js +33 -0
  57. package/dist/modules/lighting/lambert-material/lambert-material.js.map +1 -0
  58. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts +3 -0
  59. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts.map +1 -0
  60. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js +60 -0
  61. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js.map +1 -0
  62. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts +2 -0
  63. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts.map +1 -0
  64. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js +73 -0
  65. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js.map +1 -0
  66. package/dist/modules/lighting/lights/lighting-glsl.d.ts +1 -1
  67. package/dist/modules/lighting/lights/lighting-glsl.d.ts.map +1 -1
  68. package/dist/modules/lighting/lights/lighting-glsl.js +43 -55
  69. package/dist/modules/lighting/lights/lighting-glsl.js.map +1 -1
  70. package/dist/modules/lighting/lights/lighting-wgsl.d.ts +1 -1
  71. package/dist/modules/lighting/lights/lighting-wgsl.d.ts.map +1 -1
  72. package/dist/modules/lighting/lights/lighting-wgsl.js +43 -65
  73. package/dist/modules/lighting/lights/lighting-wgsl.js.map +1 -1
  74. package/dist/modules/lighting/lights/lighting.d.ts +104 -86
  75. package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
  76. package/dist/modules/lighting/lights/lighting.js +96 -83
  77. package/dist/modules/lighting/lights/lighting.js.map +1 -1
  78. package/dist/modules/lighting/no-material/dirlight.d.ts +7 -2
  79. package/dist/modules/lighting/no-material/dirlight.d.ts.map +1 -1
  80. package/dist/modules/lighting/no-material/dirlight.js +3 -1
  81. package/dist/modules/lighting/no-material/dirlight.js.map +1 -1
  82. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts +1 -1
  83. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts.map +1 -1
  84. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js +524 -28
  85. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js.map +1 -1
  86. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts +2 -2
  87. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts.map +1 -1
  88. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js +706 -50
  89. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js.map +1 -1
  90. package/dist/modules/lighting/pbr-material/pbr-material.d.ts +110 -61
  91. package/dist/modules/lighting/pbr-material/pbr-material.d.ts.map +1 -1
  92. package/dist/modules/lighting/pbr-material/pbr-material.js +85 -9
  93. package/dist/modules/lighting/pbr-material/pbr-material.js.map +1 -1
  94. package/dist/modules/lighting/pbr-material/pbr-projection.d.ts.map +1 -1
  95. package/dist/modules/lighting/pbr-material/pbr-projection.js +2 -1
  96. package/dist/modules/lighting/pbr-material/pbr-projection.js.map +1 -1
  97. package/dist/modules/lighting/phong-material/phong-material.d.ts +1 -0
  98. package/dist/modules/lighting/phong-material/phong-material.d.ts.map +1 -1
  99. package/dist/modules/lighting/phong-material/phong-material.js +4 -0
  100. package/dist/modules/lighting/phong-material/phong-material.js.map +1 -1
  101. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts +2 -2
  102. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts.map +1 -1
  103. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js +15 -4
  104. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js.map +1 -1
  105. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts +1 -1
  106. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts.map +1 -1
  107. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js +36 -5
  108. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js.map +1 -1
  109. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts +1 -1
  110. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts.map +1 -1
  111. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js +41 -10
  112. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js.map +1 -1
  113. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -0
  114. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -0
  115. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +212 -0
  116. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -0
  117. package/dist/modules/math/fp64/fp64.d.ts +1 -0
  118. package/dist/modules/math/fp64/fp64.d.ts.map +1 -1
  119. package/dist/modules/math/fp64/fp64.js +8 -2
  120. package/dist/modules/math/fp64/fp64.js.map +1 -1
  121. package/package.json +3 -3
  122. package/src/index.ts +19 -2
  123. package/src/lib/preprocessor/preprocessor.ts +6 -3
  124. package/src/lib/shader-assembler.ts +17 -2
  125. package/src/lib/shader-assembly/assemble-shaders.ts +377 -12
  126. package/src/lib/shader-assembly/wgsl-binding-debug.ts +216 -0
  127. package/src/lib/shader-generator/glsl/generate-glsl.ts +7 -1
  128. package/src/lib/shader-generator/wgsl/generate-wgsl.ts +6 -0
  129. package/src/lib/shader-module/shader-module-uniform-layout.ts +195 -0
  130. package/src/lib/shader-module/shader-module.ts +16 -6
  131. package/src/lib/utils/uniform-types.ts +24 -9
  132. package/src/modules/engine/picking/picking.ts +3 -0
  133. package/src/modules/engine/skin/skin.ts +3 -5
  134. package/src/modules/lighting/gouraud-material/gouraud-material.ts +4 -0
  135. package/src/modules/lighting/ibl/ibl.ts +44 -0
  136. package/src/modules/lighting/lambert-material/lambert-material.ts +42 -0
  137. package/src/modules/lighting/lambert-material/lambert-shaders-glsl.ts +61 -0
  138. package/src/modules/lighting/lambert-material/lambert-shaders-wgsl.ts +73 -0
  139. package/src/modules/lighting/lights/lighting-glsl.ts +43 -55
  140. package/src/modules/lighting/lights/lighting-wgsl.ts +43 -65
  141. package/src/modules/lighting/lights/lighting.ts +186 -123
  142. package/src/modules/lighting/no-material/dirlight.ts +3 -1
  143. package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +524 -28
  144. package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +706 -50
  145. package/src/modules/lighting/pbr-material/pbr-material.ts +111 -18
  146. package/src/modules/lighting/pbr-material/pbr-projection.ts +2 -1
  147. package/src/modules/lighting/phong-material/phong-material.ts +5 -0
  148. package/src/modules/lighting/phong-material/phong-shaders-glsl.ts +15 -4
  149. package/src/modules/lighting/phong-material/phong-shaders-wgsl.ts +36 -5
  150. package/src/modules/math/fp64/fp64-arithmetic-glsl.ts +41 -10
  151. package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +212 -0
  152. package/src/modules/math/fp64/fp64.ts +9 -3
package/dist/dist.min.js CHANGED
@@ -4,10 +4,10 @@
4
4
  else if (typeof define === 'function' && define.amd) define([], factory);
5
5
  else if (typeof exports === 'object') exports['luma'] = factory();
6
6
  else root['luma'] = factory();})(globalThis, function () {
7
- "use strict";var __exports__=(()=>{var on=Object.create;var j=Object.defineProperty;var sn=Object.getOwnPropertyDescriptor;var cn=Object.getOwnPropertyNames;var an=Object.getPrototypeOf,ln=Object.prototype.hasOwnProperty;var fn=(e,t,n)=>t in e?j(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var pn=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),hn=(e,t)=>{for(var n in t)j(e,n,{get:t[n],enumerable:!0})},ne=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of cn(t))!ln.call(e,r)&&r!==n&&j(e,r,{get:()=>t[r],enumerable:!(i=sn(t,r))||i.enumerable});return e},ie=(e,t,n)=>(ne(e,t,"default"),n&&ne(n,t,"default")),Be=(e,t,n)=>(n=e!=null?on(an(e)):{},ne(t||!e||!e.__esModule?j(n,"default",{value:e,enumerable:!0}):n,e)),gn=e=>ne(j({},"__esModule",{value:!0}),e);var ze=(e,t,n)=>(fn(e,typeof t!="symbol"?t+"":t,n),n);var xe=pn((Ai,He)=>{He.exports=globalThis.luma});var te={};hn(te,{ShaderAssembler:()=>X,_getDependencyGraph:()=>K,_resolveModules:()=>Je,assembleGLSLShaderPair:()=>se,capitalize:()=>D,checkShaderModuleDeprecations:()=>$,combineInjects:()=>Xe,convertToVec4:()=>Ee,dirlight:()=>ke,fp32:()=>jt,fp64:()=>$t,fp64LowPart:()=>Z,fp64arithmetic:()=>Te,fp64ify:()=>G,fp64ifyMatrix4:()=>J,fromHalfFloat:()=>Ht,generateShaderForModule:()=>gt,getPassthroughFS:()=>at,getQualifierDetails:()=>ct,getShaderInfo:()=>oe,getShaderModuleDependencies:()=>Y,getShaderModuleSource:()=>ce,getShaderModuleUniforms:()=>Ze,gouraudMaterial:()=>De,initializeShaderModule:()=>re,initializeShaderModules:()=>T,lighting:()=>y,pbrMaterial:()=>rn,phongMaterial:()=>Ue,picking:()=>Yt,preprocess:()=>ae,random:()=>Vt,skin:()=>Kt,toHalfFloat:()=>zt,typeToChannelCount:()=>ft,typeToChannelSuffix:()=>lt});ie(te,Be(xe(),1));function F(e,t){if(!e){let n=new Error(t||"shadertools: assertion failed.");throw Error.captureStackTrace?.(n,F),n}}var be={number:{type:"number",validate(e,t){return Number.isFinite(e)&&typeof t=="object"&&(t.max===void 0||e<=t.max)&&(t.min===void 0||e>=t.min)}},array:{type:"array",validate(e,t){return Array.isArray(e)||ArrayBuffer.isView(e)}}};function Ve(e){let t={};for(let[n,i]of Object.entries(e))t[n]=mn(i);return t}function je(e,t,n){let i={};for(let[r,o]of Object.entries(t))e&&r in e&&!o.private?(o.validate&&F(o.validate(e[r],o),`${n}: invalid ${r}`),i[r]=e[r]):i[r]=o.value;return i}function mn(e){let t=Ge(e);if(t!=="object")return{value:e,...be[t],type:t};if(typeof e=="object")return e?e.type!==void 0?{...e,...be[e.type],type:e.type}:e.value===void 0?{type:"object",value:e}:(t=Ge(e.value),{...e,...be[t],type:t}):{type:"object",value:null};throw new Error("props")}function Ge(e){return Array.isArray(e)||ArrayBuffer.isView(e)?"array":typeof e}var qe=`#ifdef MODULE_LOGDEPTH
7
+ "use strict";var __exports__=(()=>{var Nn=Object.create;var j=Object.defineProperty;var yn=Object.getOwnPropertyDescriptor;var On=Object.getOwnPropertyNames;var Tn=Object.getPrototypeOf,Fn=Object.prototype.hasOwnProperty;var wn=(e,t,n)=>t in e?j(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Bn=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),kn=(e,t)=>{for(var n in t)j(e,n,{get:t[n],enumerable:!0})},re=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of On(t))!Fn.call(e,o)&&o!==n&&j(e,o,{get:()=>t[o],enumerable:!(r=yn(t,o))||r.enumerable});return e},oe=(e,t,n)=>(re(e,t,"default"),n&&re(n,t,"default")),Ze=(e,t,n)=>(n=e!=null?Nn(Tn(e)):{},re(t||!e||!e.__esModule?j(n,"default",{value:e,enumerable:!0}):n,e)),Dn=e=>re(j({},"__esModule",{value:!0}),e);var Je=(e,t,n)=>(wn(e,typeof t!="symbol"?t+"":t,n),n);var Ie=Bn((mo,Qe)=>{Qe.exports=globalThis.luma});var ne={};kn(ne,{ShaderAssembler:()=>J,_getDependencyGraph:()=>X,_resolveModules:()=>ft,assembleGLSLShaderPair:()=>he,capitalize:()=>k,checkShaderModuleDeprecations:()=>K,combineInjects:()=>ct,convertToVec4:()=>Be,dirlight:()=>qe,fp32:()=>pn,fp64:()=>gn,fp64LowPart:()=>Q,fp64arithmetic:()=>je,fp64ify:()=>V,fp64ifyMatrix4:()=>ee,fromHalfFloat:()=>cn,generateShaderForModule:()=>Tt,getPassthroughFS:()=>Ct,getQualifierDetails:()=>It,getShaderInfo:()=>ce,getShaderModuleDependencies:()=>Y,getShaderModuleSource:()=>ue,getShaderModuleUniformBlockFields:()=>Ne,getShaderModuleUniformBlockName:()=>ae,getShaderModuleUniformLayoutValidationResult:()=>ye,getShaderModuleUniforms:()=>lt,gouraudMaterial:()=>Ye,ibl:()=>Le,initializeShaderModule:()=>ie,initializeShaderModules:()=>T,lambertMaterial:()=>Ke,lighting:()=>F,pbrMaterial:()=>Pn,phongMaterial:()=>Xe,picking:()=>mn,preprocess:()=>ge,random:()=>fn,skin:()=>dn,toHalfFloat:()=>sn,typeToChannelCount:()=>Nt,typeToChannelSuffix:()=>Pt,validateShaderModuleUniformLayout:()=>se});oe(ne,Ze(Ie(),1));function O(e,t){if(!e){let n=new Error(t||"shadertools: assertion failed.");throw Error.captureStackTrace?.(n,O),n}}var Ce={number:{type:"number",validate(e,t){return Number.isFinite(e)&&typeof t=="object"&&(t.max===void 0||e<=t.max)&&(t.min===void 0||e>=t.min)}},array:{type:"array",validate(e,t){return Array.isArray(e)||ArrayBuffer.isView(e)}}};function tt(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Un(r);return t}function nt(e,t,n){let r={};for(let[o,i]of Object.entries(t))e&&o in e&&!i.private?(i.validate&&O(i.validate(e[o],i),`${n}: invalid ${o}`),r[o]=e[o]):r[o]=i.value;return r}function Un(e){let t=et(e);if(t!=="object")return{value:e,...Ce[t],type:t};if(typeof e=="object")return e?e.type!==void 0?{...e,...Ce[e.type],type:e.type}:e.value===void 0?{type:"object",value:e}:(t=et(e.value),{...e,...Ce[t],type:t}):{type:"object",value:null};throw new Error("props")}function et(e){return Array.isArray(e)||ArrayBuffer.isView(e)?"array":typeof e}var rt=`#ifdef MODULE_LOGDEPTH
8
8
  logdepth_adjustPosition(gl_Position);
9
9
  #endif
10
- `,We=`#ifdef MODULE_MATERIAL
10
+ `,ot=`#ifdef MODULE_MATERIAL
11
11
  fragColor = material_filterColor(fragColor);
12
12
  #endif
13
13
 
@@ -27,10 +27,13 @@
27
27
  #ifdef MODULE_LOGDEPTH
28
28
  logdepth_setFragDepth();
29
29
  #endif
30
- `;var _n={vertex:qe,fragment:We},$e=/void\s+main\s*\([^)]*\)\s*\{\n?/,Ye=/}\n?[^{}]*$/,Me=[],q="__LUMA_INJECT_DECLARATIONS__";function Ke(e){let t={vertex:{},fragment:{}};for(let n in e){let i=e[n],r=un(n);typeof i=="string"&&(i={order:0,injection:i}),t[r][n]=i}return t}function un(e){let t=e.slice(0,2);switch(t){case"vs":return"vertex";case"fs":return"fragment";default:throw new Error(t)}}function W(e,t,n,i=!1){let r=t==="vertex";for(let o in n){let s=n[o];s.sort((a,l)=>a.order-l.order),Me.length=s.length;for(let a=0,l=s.length;a<l;++a)Me[a]=s[a].injection;let c=`${Me.join(`
30
+ `;var zn={vertex:rt,fragment:ot},it=/void\s+main\s*\([^)]*\)\s*\{\n?/,at=/}\n?[^{}]*$/,Pe=[],$="__LUMA_INJECT_DECLARATIONS__";function st(e){let t={vertex:{},fragment:{}};for(let n in e){let r=e[n],o=Hn(n);typeof r=="string"&&(r={order:0,injection:r}),t[o][n]=r}return t}function Hn(e){let t=e.slice(0,2);switch(t){case"vs":return"vertex";case"fs":return"fragment";default:throw new Error(t)}}function q(e,t,n,r=!1){let o=t==="vertex";for(let i in n){let a=n[i];a.sort((c,l)=>c.order-l.order),Pe.length=a.length;for(let c=0,l=a.length;c<l;++c)Pe[c]=a[c].injection;let s=`${Pe.join(`
31
31
  `)}
32
- `;switch(o){case"vs:#decl":r&&(e=e.replace(q,c));break;case"vs:#main-start":r&&(e=e.replace($e,a=>a+c));break;case"vs:#main-end":r&&(e=e.replace(Ye,a=>c+a));break;case"fs:#decl":r||(e=e.replace(q,c));break;case"fs:#main-start":r||(e=e.replace($e,a=>a+c));break;case"fs:#main-end":r||(e=e.replace(Ye,a=>c+a));break;default:e=e.replace(o,a=>a+c)}}return e=e.replace(q,""),i&&(e=e.replace(/\}\s*$/,o=>o+_n[t])),e}function Xe(e){let t={};return F(Array.isArray(e)&&e.length>1),e.forEach(n=>{for(let i in n)t[i]=t[i]?`${t[i]}
33
- ${n[i]}`:n[i]}),t}function T(e){e.map(t=>re(t))}function re(e){if(e.instance)return;T(e.dependencies||[]);let{propTypes:t={},deprecations:n=[],inject:i={}}=e,r={normalizedInjections:Ke(i),parsedDeprecations:dn(n)};t&&(r.propValidators=Ve(t)),e.instance=r;let o={};t&&(o=Object.entries(t).reduce((s,[c,a])=>{let l=a?.value;return l&&(s[c]=l),s},{})),e.defaultUniforms={...e.defaultUniforms,...o}}function Ze(e,t,n){re(e);let i=n||{...e.defaultUniforms};return t&&e.getUniforms?e.getUniforms(t,i):je(t,e.instance?.propValidators,e.name)}function $(e,t,n){e.deprecations?.forEach(i=>{i.regex?.test(t)&&(i.deprecated?n.deprecated(i.old,i.new)():n.removed(i.old,i.new)())})}function dn(e){return e.forEach(t=>{switch(t.type){case"function":t.regex=new RegExp(`\\b${t.old}\\(`);break;default:t.regex=new RegExp(`${t.type} ${t.old};`)}}),e}function Y(e){T(e);let t={},n={};K({modules:e,level:0,moduleMap:t,moduleDepth:n});let i=Object.keys(n).sort((r,o)=>n[o]-n[r]).map(r=>t[r]);return T(i),i}function K(e){let{modules:t,level:n,moduleMap:i,moduleDepth:r}=e;if(n>=5)throw new Error("Possible loop in shader dependency graph");for(let o of t)i[o.name]=o,(r[o.name]===void 0||r[o.name]<n)&&(r[o.name]=n);for(let o of t)o.dependencies&&K({modules:o.dependencies,level:n+1,moduleMap:i,moduleDepth:r})}function vn(e){T(e);let t={},n={};return K({modules:e,level:0,moduleMap:t,moduleDepth:n}),e=Object.keys(n).sort((i,r)=>n[r]-n[i]).map(i=>t[i]),T(e),e}function Je(e){return vn(e)}function Qe(e){switch(e?.gpu.toLowerCase()){case"apple":return`#define APPLE_GPU
32
+ `;switch(i){case"vs:#decl":o&&(e=e.replace($,s));break;case"vs:#main-start":o&&(e=e.replace(it,c=>c+s));break;case"vs:#main-end":o&&(e=e.replace(at,c=>s+c));break;case"fs:#decl":o||(e=e.replace($,s));break;case"fs:#main-start":o||(e=e.replace(it,c=>c+s));break;case"fs:#main-end":o||(e=e.replace(at,c=>s+c));break;default:e=e.replace(i,c=>c+s)}}return e=e.replace($,""),r&&(e=e.replace(/\}\s*$/,i=>i+zn[t])),e}function ct(e){let t={};return O(Array.isArray(e)&&e.length>1),e.forEach(n=>{for(let r in n)t[r]=t[r]?`${t[r]}
33
+ ${n[r]}`:n[r]}),t}function T(e){e.map(t=>ie(t))}function ie(e){if(e.instance)return;T(e.dependencies||[]);let{propTypes:t={},deprecations:n=[],inject:r={}}=e,o={normalizedInjections:st(r),parsedDeprecations:Gn(n)};t&&(o.propValidators=tt(t)),e.instance=o;let i={};t&&(i=Object.entries(t).reduce((a,[s,c])=>{let l=c?.value;return l&&(a[s]=l),a},{})),e.defaultUniforms={...e.defaultUniforms,...i}}function lt(e,t,n){ie(e);let r=n||{...e.defaultUniforms};return t&&e.getUniforms?e.getUniforms(t,r):nt(t,e.instance?.propValidators,e.name)}function K(e,t,n){e.deprecations?.forEach(r=>{r.regex?.test(t)&&(r.deprecated?n.deprecated(r.old,r.new)():n.removed(r.old,r.new)())})}function Gn(e){return e.forEach(t=>{switch(t.type){case"function":t.regex=new RegExp(`\\b${t.old}\\(`);break;default:t.regex=new RegExp(`${t.type} ${t.old};`)}}),e}function Y(e){T(e);let t={},n={};X({modules:e,level:0,moduleMap:t,moduleDepth:n});let r=Object.keys(n).sort((o,i)=>n[i]-n[o]).map(o=>t[o]);return T(r),r}function X(e){let{modules:t,level:n,moduleMap:r,moduleDepth:o}=e;if(n>=5)throw new Error("Possible loop in shader dependency graph");for(let i of t)r[i.name]=i,(o[i.name]===void 0||o[i.name]<n)&&(o[i.name]=n);for(let i of t)i.dependencies&&X({modules:i.dependencies,level:n+1,moduleMap:r,moduleDepth:o})}function Vn(e){T(e);let t={},n={};return X({modules:e,level:0,moduleMap:t,moduleDepth:n}),e=Object.keys(n).sort((r,o)=>n[o]-n[r]).map(r=>t[r]),T(e),e}function ft(e){return Vn(e)}var Wn=/^(?:uniform\s+)?(?:(?:lowp|mediump|highp)\s+)?[A-Za-z0-9_]+(?:<[^>]+>)?\s+([A-Za-z0-9_]+)(?:\s*\[[^\]]+\])?\s*;/;function ae(e){return`${e.name}Uniforms`}function Ne(e,t){let n=t==="wgsl"?e.source:t==="vertex"?e.vs:e.fs;if(!n)return null;let r=ae(e);return jn(n,t==="wgsl"?"wgsl":"glsl",r)}function ye(e,t){let n=Object.keys(e.uniformTypes||{});if(!n.length)return null;let r=Ne(e,t);return r?{moduleName:e.name,uniformBlockName:ae(e),stage:t,expectedUniformNames:n,actualUniformNames:r,matches:Kn(n,r)}:null}function se(e,t,n={}){let r=ye(e,t);if(!r||r.matches)return r;let o=Yn(r);return n.log?.error?.(o,r)(),n.throwOnError!==!1&&O(!1,o),r}function jn(e,t,n){let r=t==="wgsl"?$n(e,n):qn(e,n);if(!r)return null;let o=[];for(let i of r.split(`
34
+ `)){let a=i.replace(/\/\/.*$/,"").trim();if(!a||a.startsWith("#"))continue;let s=t==="wgsl"?a.match(/^([A-Za-z0-9_]+)\s*:/):a.match(Wn);s&&o.push(s[1])}return o}function $n(e,t){let n=new RegExp(`\\bstruct\\s+${t}\\b`,"m").exec(e);if(!n)return null;let r=e.indexOf("{",n.index);if(r<0)return null;let o=0;for(let i=r;i<e.length;i++){let a=e[i];if(a==="{"){o++;continue}if(a==="}"&&(o--,o===0))return e.slice(r+1,i)}return null}function qn(e,t){return e.match(new RegExp(`uniform\\s+${t}\\s*\\{([\\s\\S]*?)\\}\\s*[A-Za-z0-9_]+\\s*;`,"m"))?.[1]||null}function Kn(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function Yn(e){return`${e.moduleName}: ${e.stage} shader uniform block ${e.uniformBlockName} does not match module.uniformTypes.
35
+ Expected: ${e.expectedUniformNames.join(", ")}
36
+ Actual: ${e.actualUniformNames.join(", ")}`}function pt(e){switch(e?.gpu.toLowerCase()){case"apple":return`#define APPLE_GPU
34
37
  // Apple optimizes away the calculation necessary for emulated fp64
35
38
  #define LUMA_FP64_CODE_ELIMINATION_WORKAROUND 1
36
39
  #define LUMA_FP32_TAN_PRECISION_WORKAROUND 1
@@ -54,55 +57,58 @@ ${n[i]}`:n[i]}),t}function T(e){e.map(t=>re(t))}function re(e){if(e.instance)ret
54
57
  #define LUMA_FP32_TAN_PRECISION_WORKAROUND 1
55
58
  // If the GPU doesn't have full 32 bits precision, will causes overflow
56
59
  #define LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND 1
57
- `}}function tt(e,t){if(Number(e.match(/^#version[ \t]+(\d+)/m)?.[1]||100)!==300)throw new Error("luma.gl v9 only supports GLSL 3.00 shader sources");switch(t){case"vertex":return e=et(e,xn),e;case"fragment":return e=et(e,bn),e;default:throw new Error(t)}}var nt=[[/^(#version[ \t]+(100|300[ \t]+es))?[ \t]*\n/,`#version 300 es
58
- `],[/\btexture(2D|2DProj|Cube)Lod(EXT)?\(/g,"textureLod("],[/\btexture(2D|2DProj|Cube)(EXT)?\(/g,"texture("]],xn=[...nt,[Ae("attribute"),"in $1"],[Ae("varying"),"out $1"]],bn=[...nt,[Ae("varying"),"in $1"]];function et(e,t){for(let[n,i]of t)e=e.replace(n,i);return e}function Ae(e){return new RegExp(`\\b${e}[ \\t]+(\\w+[ \\t]+\\w+(\\[\\w+\\])?;)`,"g")}function Le(e,t){let n="";for(let i in e){let r=e[i];if(n+=`void ${r.signature} {
59
- `,r.header&&(n+=` ${r.header}`),t[i]){let o=t[i];o.sort((s,c)=>s.order-c.order);for(let s of o)n+=` ${s.injection}
60
- `}r.footer&&(n+=` ${r.footer}`),n+=`}
61
- `}return n}function Se(e){let t={vertex:{},fragment:{}};for(let n of e){let i,r;typeof n!="string"?(i=n,r=i.hook):(i={},r=n),r=r.trim();let[o,s]=r.split(":"),c=r.replace(/\(.+/,""),a=Object.assign(i,{signature:s});switch(o){case"vs":t.vertex[c]=a;break;case"fs":t.fragment[c]=a;break;default:throw new Error(o)}}return t}function oe(e,t){return{name:Mn(e,t),language:"glsl",version:An(e)}}function Mn(e,t="unnamed"){let i=/#define[^\S\r\n]*SHADER_NAME[^\S\r\n]*([A-Za-z0-9_-]+)\s*/.exec(e);return i?i[1]:t}function An(e){let t=100,n=e.match(/[^\s]+/g);if(n&&n.length>=2&&n[0]==="#version"){let i=parseInt(n[1],10);Number.isFinite(i)&&(t=i)}if(t!==100&&t!==300)throw new Error(`Invalid GLSL version ${t}`);return t}var rt=`
62
-
63
- ${q}
64
- `,Ln=`precision highp float;
65
- `;function ot(e){let t=Y(e.modules||[]);return{source:Sn(e.platformInfo,{...e,source:e.source,stage:"vertex",modules:t}),getUniforms:st(t)}}function se(e){let{vs:t,fs:n}=e,i=Y(e.modules||[]);return{vs:it(e.platformInfo,{...e,source:t,stage:"vertex",modules:i}),fs:it(e.platformInfo,{...e,source:n,stage:"fragment",modules:i}),getUniforms:st(i)}}function Sn(e,t){let{source:n,stage:i,modules:r,hookFunctions:o=[],inject:s={},log:c}=t;F(typeof n=="string","shader source must be a string");let a=n,l="",h=Se(o),f={},p={},m={};for(let _ in s){let d=typeof s[_]=="string"?{injection:s[_],order:0}:s[_],g=/^(v|f)s:(#)?([\w-]+)$/.exec(_);if(g){let A=g[2],v=g[3];A?v==="decl"?p[_]=[d]:m[_]=[d]:f[_]=[d]}else m[_]=[d]}let x=r;for(let _ of x){c&&$(_,a,c);let d=ce(_,"wgsl");l+=d;let g=_.injections?.[i]||{};for(let A in g){let v=/^(v|f)s:#([\w-]+)$/.exec(A);if(v){let b=v[2]==="decl"?p:m;b[A]=b[A]||[],b[A].push(g[A])}else f[A]=f[A]||[],f[A].push(g[A])}}return l+=rt,l=W(l,i,p),l+=Le(h[i],f),l+=a,l=W(l,i,m),l}function it(e,t){let{source:n,stage:i,language:r="glsl",modules:o,defines:s={},hookFunctions:c=[],inject:a={},prologue:l=!0,log:h}=t;F(typeof n=="string","shader source must be a string");let f=r==="glsl"?oe(n).version:-1,p=e.shaderLanguageVersion,m=f===100?"#version 100":"#version 300 es",_=n.split(`
60
+ `}}function ut(e,t){if(Number(e.match(/^#version[ \t]+(\d+)/m)?.[1]||100)!==300)throw new Error("luma.gl v9 only supports GLSL 3.00 shader sources");switch(t){case"vertex":return e=ht(e,Xn),e;case"fragment":return e=ht(e,Zn),e;default:throw new Error(t)}}var gt=[[/^(#version[ \t]+(100|300[ \t]+es))?[ \t]*\n/,`#version 300 es
61
+ `],[/\btexture(2D|2DProj|Cube)Lod(EXT)?\(/g,"textureLod("],[/\btexture(2D|2DProj|Cube)(EXT)?\(/g,"texture("]],Xn=[...gt,[Oe("attribute"),"in $1"],[Oe("varying"),"out $1"]],Zn=[...gt,[Oe("varying"),"in $1"]];function ht(e,t){for(let[n,r]of t)e=e.replace(n,r);return e}function Oe(e){return new RegExp(`\\b${e}[ \\t]+(\\w+[ \\t]+\\w+(\\[\\w+\\])?;)`,"g")}function Te(e,t){let n="";for(let r in e){let o=e[r];if(n+=`void ${o.signature} {
62
+ `,o.header&&(n+=` ${o.header}`),t[r]){let i=t[r];i.sort((a,s)=>a.order-s.order);for(let a of i)n+=` ${a.injection}
63
+ `}o.footer&&(n+=` ${o.footer}`),n+=`}
64
+ `}return n}function Fe(e){let t={vertex:{},fragment:{}};for(let n of e){let r,o;typeof n!="string"?(r=n,o=r.hook):(r={},o=n),o=o.trim();let[i,a]=o.split(":"),s=o.replace(/\(.+/,""),c=Object.assign(r,{signature:a});switch(i){case"vs":t.vertex[s]=c;break;case"fs":t.fragment[s]=c;break;default:throw new Error(i)}}return t}function ce(e,t){return{name:Jn(e,t),language:"glsl",version:Qn(e)}}function Jn(e,t="unnamed"){let r=/#define[^\S\r\n]*SHADER_NAME[^\S\r\n]*([A-Za-z0-9_-]+)\s*/.exec(e);return r?r[1]:t}function Qn(e){let t=100,n=e.match(/[^\s]+/g);if(n&&n.length>=2&&n[0]==="#version"){let r=parseInt(n[1],10);Number.isFinite(r)&&(t=r)}if(t!==100&&t!==300)throw new Error(`Invalid GLSL version ${t}`);return t}var mt=[/@binding\(\s*(\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*var(?:<([^>]+)>)?\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^;]+);/g,/@group\(\s*(\d+)\s*\)\s*@binding\(\s*(\d+)\s*\)\s*var(?:<([^>]+)>)?\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^;]+);/g];function le(e,t=[]){let n=new Map;for(let o of t)n.set(dt(o.name,o.group,o.location),o.moduleName);let r=[];for(let o of mt){o.lastIndex=0;let i;for(;i=o.exec(e);){let a=o===mt[0],s=Number(i[a?1:2]),c=Number(i[a?2:1]),l=i[3]?.trim(),p=i[4],f=i[5].trim(),h=n.get(dt(p,c,s));r.push(er({name:p,group:c,binding:s,owner:h?"module":"application",moduleName:h,accessDeclaration:l,resourceType:f}))}}return r.sort((o,i)=>o.group!==i.group?o.group-i.group:o.binding!==i.binding?o.binding-i.binding:o.name.localeCompare(i.name))}function er(e){let t={name:e.name,group:e.group,binding:e.binding,owner:e.owner,kind:"unknown",moduleName:e.moduleName,resourceType:e.resourceType};if(e.accessDeclaration){let n=e.accessDeclaration.split(",").map(r=>r.trim());if(n[0]==="uniform")return{...t,kind:"uniform",access:"uniform"};if(n[0]==="storage"){let r=n[1]||"read_write";return{...t,kind:r==="read"?"read-only-storage":"storage",access:r}}}return e.resourceType==="sampler"||e.resourceType==="sampler_comparison"?{...t,kind:"sampler",samplerKind:e.resourceType==="sampler_comparison"?"comparison":"filtering"}:e.resourceType.startsWith("texture_storage_")?{...t,kind:"storage-texture",access:nr(e.resourceType),viewDimension:_t(e.resourceType)}:e.resourceType.startsWith("texture_")?{...t,kind:"texture",viewDimension:_t(e.resourceType),sampleType:tr(e.resourceType),multisampled:e.resourceType.startsWith("texture_multisampled_")}:t}function dt(e,t,n){return`${t}:${n}:${e}`}function _t(e){if(e.includes("cube_array"))return"cube-array";if(e.includes("2d_array"))return"2d-array";if(e.includes("cube"))return"cube";if(e.includes("3d"))return"3d";if(e.includes("2d"))return"2d";if(e.includes("1d"))return"1d"}function tr(e){if(e.startsWith("texture_depth_"))return"depth";if(e.includes("<i32>"))return"sint";if(e.includes("<u32>"))return"uint";if(e.includes("<f32>"))return"float"}function nr(e){return/,\s*([A-Za-z_][A-Za-z0-9_]*)\s*>$/.exec(e)?.[1]}var Lt=`
65
+
66
+ ${$}
67
+ `,fe=[/@binding\(\s*(auto|\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g,/@group\(\s*(\d+)\s*\)\s*@binding\(\s*(auto|\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g],bt=[/@binding\(\s*(\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g,/@group\(\s*(\d+)\s*\)\s*@binding\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g],Z=100,rr=`precision highp float;
68
+ `;function At(e){let t=Y(e.modules||[]),{source:n,bindingAssignments:r}=or(e.platformInfo,{...e,source:e.source,stage:"vertex",modules:t});return{source:n,getUniforms:Et(t),bindingAssignments:r,bindingTable:le(n,r)}}function he(e){let{vs:t,fs:n}=e,r=Y(e.modules||[]);return{vs:vt(e.platformInfo,{...e,source:t,stage:"vertex",modules:r}),fs:vt(e.platformInfo,{...e,source:n,stage:"fragment",modules:r}),getUniforms:Et(r)}}function or(e,t){let{source:n,stage:r,modules:o,hookFunctions:i=[],inject:a={},log:s}=t;O(typeof n=="string","shader source must be a string");let c=n,l="",p=Fe(i),f={},h={},g={};for(let M in a){let b=typeof a[M]=="string"?{injection:a[M],order:0}:a[M],S=/^(v|f)s:(#)?([\w-]+)$/.exec(M);if(S){let v=S[2],u=S[3];v?u==="decl"?h[M]=[b]:g[M]=[b]:f[M]=[b]}else g[M]=[b]}let _=o,m=ar(c),x=lr(_,t._bindingRegistry,m),d=[];for(let M of _){s&&K(M,c,s);let b=sr(ue(M,"wgsl",s),M,{usedBindingsByGroup:m,bindingRegistry:t._bindingRegistry,reservedBindingKeysByGroup:x});d.push(...b.bindingAssignments);let S=b.source;l+=S;let v=M.injections?.[r]||{};for(let u in v){let E=/^(v|f)s:#([\w-]+)$/.exec(u);if(E){let L=E[2]==="decl"?h:g;L[u]=L[u]||[],L[u].push(v[u])}else f[u]=f[u]||[],f[u].push(v[u])}}return l+=Lt,l=q(l,r,h),l+=Te(p[r],f),l+=gr(d),l+=c,l=q(l,r,g),ur(l),{source:l,bindingAssignments:d}}function vt(e,t){let{source:n,stage:r,language:o="glsl",modules:i,defines:a={},hookFunctions:s=[],inject:c={},prologue:l=!0,log:p}=t;O(typeof n=="string","shader source must be a string");let f=o==="glsl"?ce(n).version:-1,h=e.shaderLanguageVersion,g=f===100?"#version 100":"#version 300 es",m=n.split(`
66
69
  `).slice(1).join(`
67
- `),d={};o.forEach(u=>{Object.assign(d,u.defines)}),Object.assign(d,s);let g="";switch(r){case"wgsl":break;case"glsl":g=l?`${m}
70
+ `),x={};i.forEach(u=>{Object.assign(x,u.defines)}),Object.assign(x,a);let d="";switch(o){case"wgsl":break;case"glsl":d=l?`${g}
68
71
 
69
72
  // ----- PROLOGUE -------------------------
70
- ${`#define SHADER_TYPE_${i.toUpperCase()}`}
73
+ ${`#define SHADER_TYPE_${r.toUpperCase()}`}
71
74
 
72
- ${Qe(e)}
73
- ${i==="fragment"?Ln:""}
75
+ ${pt(e)}
76
+ ${r==="fragment"?rr:""}
74
77
 
75
78
  // ----- APPLICATION DEFINES -------------------------
76
79
 
77
- ${En(d)}
80
+ ${ir(x)}
78
81
 
79
- `:`${m}
80
- `;break}let A=Se(c),v={},M={},b={};for(let u in a){let I=typeof a[u]=="string"?{injection:a[u],order:0}:a[u],E=/^(v|f)s:(#)?([\w-]+)$/.exec(u);if(E){let L=E[2],P=E[3];L?P==="decl"?M[u]=[I]:b[u]=[I]:v[u]=[I]}else b[u]=[I]}for(let u of o){h&&$(u,_,h);let I=ce(u,i);g+=I;let E=u.instance?.normalizedInjections[i]||{};for(let L in E){let P=/^(v|f)s:#([\w-]+)$/.exec(L);if(P){let R=P[2]==="decl"?M:b;R[L]=R[L]||[],R[L].push(E[L])}else v[L]=v[L]||[],v[L].push(E[L])}}return g+="// ----- MAIN SHADER SOURCE -------------------------",g+=rt,g=W(g,i,M),g+=Le(A[i],v),g+=_,g=W(g,i,b),r==="glsl"&&f!==p&&(g=tt(g,i)),g.trim()}function st(e){return function(n){let i={};for(let r of e){let o=r.getUniforms?.(n,i);Object.assign(i,o)}return i}}function En(e={}){let t="";for(let n in e){let i=e[n];(i||Number.isFinite(i))&&(t+=`#define ${n.toUpperCase()} ${e[n]}
81
- `)}return t}function ce(e,t){let n;switch(t){case"vertex":n=e.vs||"";break;case"fragment":n=e.fs||"";break;case"wgsl":n=e.source||"";break;default:F(!1)}if(!e.name)throw new Error("Shader module must have a name");let i=e.name.toUpperCase().replace(/[^0-9a-z]/gi,"_"),r=`// ----- MODULE ${e.name} ---------------
82
+ `:`${g}
83
+ `;break}let M=Fe(s),b={},S={},v={};for(let u in c){let E=typeof c[u]=="string"?{injection:c[u],order:0}:c[u],R=/^(v|f)s:(#)?([\w-]+)$/.exec(u);if(R){let L=R[2],I=R[3];L?I==="decl"?S[u]=[E]:v[u]=[E]:b[u]=[E]}else v[u]=[E]}for(let u of i){p&&K(u,m,p);let E=ue(u,r,p);d+=E;let R=u.instance?.normalizedInjections[r]||{};for(let L in R){let I=/^(v|f)s:#([\w-]+)$/.exec(L);if(I){let C=I[2]==="decl"?S:v;C[L]=C[L]||[],C[L].push(R[L])}else b[L]=b[L]||[],b[L].push(R[L])}}return d+="// ----- MAIN SHADER SOURCE -------------------------",d+=Lt,d=q(d,r,S),d+=Te(M[r],b),d+=m,d=q(d,r,v),o==="glsl"&&f!==h&&(d=ut(d,r)),d.trim()}function Et(e){return function(n){let r={};for(let o of e){let i=o.getUniforms?.(n,r);Object.assign(r,i)}return r}}function ir(e={}){let t="";for(let n in e){let r=e[n];(r||Number.isFinite(r))&&(t+=`#define ${n.toUpperCase()} ${e[n]}
84
+ `)}return t}function ue(e,t,n){let r;switch(t){case"vertex":r=e.vs||"";break;case"fragment":r=e.fs||"";break;case"wgsl":r=e.source||"";break;default:O(!1)}if(!e.name)throw new Error("Shader module must have a name");se(e,t,{log:n});let o=e.name.toUpperCase().replace(/[^0-9a-z]/gi,"_"),i=`// ----- MODULE ${e.name} ---------------
82
85
 
83
- `;return t!=="wgsl"&&(r+=`#define MODULE_${i}
84
- `),r+=`${n}
85
- `,r}var In=/^\s*\#\s*ifdef\s*([a-zA-Z_]+)\s*$/,Pn=/^\s*\#\s*ifndef\s*([a-zA-Z_]+)\s*(?:\/\/.*)?$/,Rn=/^\s*\#\s*else\s*(?:\/\/.*)?$/,Cn=/^\s*\#\s*endif\s*$/,On=/^\s*\#\s*ifdef\s*([a-zA-Z_]+)\s*(?:\/\/.*)?$/,Nn=/^\s*\#\s*endif\s*(?:\/\/.*)?$/;function ae(e,t){let n=e.split(`
86
- `),i=[],r=[],o=!0;for(let s of n){let c=s.match(On)||s.match(In),a=s.match(Pn),l=s.match(Rn),h=s.match(Nn)||s.match(Cn);if(c||a){let f=(c||a)?.[1],p=Boolean(t?.defines?.[f]),m=c?p:!p,x=o&&m;r.push({parentActive:o,branchTaken:m,active:x}),o=x}else if(l){let f=r[r.length-1];if(!f)throw new Error("Encountered #else without matching #ifdef or #ifndef");f.active=f.parentActive&&!f.branchTaken,f.branchTaken=!0,o=f.active}else h?(r.pop(),o=r.length?r[r.length-1].active:!0):o&&i.push(s)}if(r.length>0)throw new Error("Unterminated conditional block in shader source");return i.join(`
87
- `)}var B=class{_hookFunctions=[];_defaultModules=[];static getDefaultShaderAssembler(){return B.defaultShaderAssembler=B.defaultShaderAssembler||new B,B.defaultShaderAssembler}addDefaultModule(t){this._defaultModules.find(n=>n.name===(typeof t=="string"?t:t.name))||this._defaultModules.push(t)}removeDefaultModule(t){let n=typeof t=="string"?t:t.name;this._defaultModules=this._defaultModules.filter(i=>i.name!==n)}addShaderHook(t,n){n&&(t=Object.assign(n,{hook:t})),this._hookFunctions.push(t)}assembleWGSLShader(t){let n=this._getModuleList(t.modules),i=this._hookFunctions,{source:r,getUniforms:o}=ot({...t,source:t.source,modules:n,hookFunctions:i}),s={...n.reduce((a,l)=>(Object.assign(a,l.defines),a),{}),...t.defines};return{source:t.platformInfo.shaderLanguage==="wgsl"?ae(r,{defines:s}):r,getUniforms:o,modules:n}}assembleGLSLShaderPair(t){let n=this._getModuleList(t.modules),i=this._hookFunctions;return{...se({...t,vs:t.vs,fs:t.fs,modules:n,hookFunctions:i}),modules:n}}_getModuleList(t=[]){let n=new Array(this._defaultModules.length+t.length),i={},r=0;for(let o=0,s=this._defaultModules.length;o<s;++o){let c=this._defaultModules[o],a=c.name;n[r++]=c,i[a]=!0}for(let o=0,s=t.length;o<s;++o){let c=t[o],a=c.name;i[a]||(n[r++]=c,i[a]=!0)}return n.length=r,T(n),n}},X=B;ze(X,"defaultShaderAssembler");var yn=`out vec4 transform_output;
86
+ `;return t!=="wgsl"&&(i+=`#define MODULE_${o}
87
+ `),i+=`${r}
88
+ `,i}function ar(e){let t=new Map;for(let n of bt){n.lastIndex=0;let r;for(;r=n.exec(e);){let o=n===bt[0],i=Number(r[o?1:2]),a=Number(r[o?2:1]),s=r[4];hr(a,i,s),pe(t,a,i,`application binding "${s}"`)}}return t}function sr(e,t,n){let r=[],o={sawSupportedBindingDeclaration:!1,nextHintedBindingLocation:typeof t.firstBindingSlot=="number"?t.firstBindingSlot:null},i=St(e,fe[0],{isBindingFirst:!0,module:t,context:n,bindingAssignments:r,relocationState:o});if(i=St(i,fe[1],{isBindingFirst:!1,module:t,context:n,bindingAssignments:r,relocationState:o}),e.includes("@binding(auto)")&&!o.sawSupportedBindingDeclaration)throw new Error(`Unsupported @binding(auto) declaration form in module "${t.name}". Use "@group(N) @binding(auto) var ..." or "@binding(auto) @group(N) var ..." on a single line.`);return{source:i,bindingAssignments:r}}function St(e,t,n){return e.replace(t,(...r)=>cr(r,n))}function cr(e,t){let{isBindingFirst:n,module:r,context:o,bindingAssignments:i,relocationState:a}=t;a.sawSupportedBindingDeclaration=!0;let s=e[0],c=e[n?1:2],l=e[n?2:1],p=e[4],f=Number(l);if(c==="auto"){let g=Rt(f,r.name,p),_=o.bindingRegistry?.get(g),m=_!==void 0?_:a.nextHintedBindingLocation===null?Mt(f,o.usedBindingsByGroup):Mt(f,o.usedBindingsByGroup,a.nextHintedBindingLocation);return xt(r.name,f,m,p),_!==void 0&&fr(o.reservedBindingKeysByGroup,f,m,g)?(i.push({moduleName:r.name,name:p,group:f,location:m}),s.replace(/@binding\(\s*auto\s*\)/,`@binding(${m})`)):(pe(o.usedBindingsByGroup,f,m,`module "${r.name}" binding "${p}"`),o.bindingRegistry?.set(g,m),i.push({moduleName:r.name,name:p,group:f,location:m}),a.nextHintedBindingLocation!==null&&_===void 0&&(a.nextHintedBindingLocation=m+1),s.replace(/@binding\(\s*auto\s*\)/,`@binding(${m})`))}let h=Number(c);return xt(r.name,f,h,p),pe(o.usedBindingsByGroup,f,h,`module "${r.name}" binding "${p}"`),i.push({moduleName:r.name,name:p,group:f,location:h}),s}function lr(e,t,n){let r=new Map;if(!t)return r;for(let o of e)for(let i of pr(o)){let a=Rt(i.group,o.name,i.name),s=t.get(a);if(s!==void 0){let c=r.get(i.group)||new Map,l=c.get(s);if(l&&l!==a)throw new Error(`Duplicate WGSL binding reservation for modules "${l}" and "${a}": group ${i.group}, binding ${s}.`);pe(n,i.group,s,`registered module binding "${a}"`),c.set(s,a),r.set(i.group,c)}}return r}function fr(e,t,n,r){let o=e.get(t);if(!o)return!1;let i=o.get(n);if(!i)return!1;if(i!==r)throw new Error(`Registered module binding "${r}" collided with "${i}": group ${t}, binding ${n}.`);return!0}function pr(e){let t=[],n=e.source||"";for(let r of fe){r.lastIndex=0;let o;for(;o=r.exec(n);){let i=r===fe[0];t.push({name:o[4],group:Number(o[i?2:1])})}}return t}function hr(e,t,n){if(e===0&&t>=Z)throw new Error(`Application binding "${n}" in group 0 uses reserved binding ${t}. Application-owned explicit group-0 bindings must stay below ${Z}.`)}function xt(e,t,n,r){if(t===0&&n<Z)throw new Error(`Module "${e}" binding "${r}" in group 0 uses reserved application binding ${n}. Module-owned explicit group-0 bindings must be ${Z} or higher.`)}function pe(e,t,n,r){let o=e.get(t)||new Set;if(o.has(n))throw new Error(`Duplicate WGSL binding assignment for ${r}: group ${t}, binding ${n}.`);o.add(n),e.set(t,o)}function Mt(e,t,n){let r=t.get(e)||new Set,o=n??(e===0?Z:r.size>0?Math.max(...r)+1:0);for(;r.has(o);)o++;return o}function ur(e){if(/@binding\(\s*auto\s*\)/.test(e))throw new Error("Unresolved @binding(auto) remained in assembled WGSL source.")}function gr(e){if(e.length===0)return"";let t=`// ----- MODULE WGSL BINDING ASSIGNMENTS ---------------
89
+ `;for(let n of e)t+=`// ${n.moduleName}.${n.name} -> @group(${n.group}) @binding(${n.location})
90
+ `;return t+=`
91
+ `,t}function Rt(e,t,n){return`${e}:${t}:${n}`}var we="([a-zA-Z_][a-zA-Z0-9_]*)",mr=new RegExp(`^\\s*\\#\\s*ifdef\\s*${we}\\s*$`),dr=new RegExp(`^\\s*\\#\\s*ifndef\\s*${we}\\s*(?:\\/\\/.*)?$`),_r=/^\s*\#\s*else\s*(?:\/\/.*)?$/,br=/^\s*\#\s*endif\s*$/,vr=new RegExp(`^\\s*\\#\\s*ifdef\\s*${we}\\s*(?:\\/\\/.*)?$`),Sr=/^\s*\#\s*endif\s*(?:\/\/.*)?$/;function ge(e,t){let n=e.split(`
92
+ `),r=[],o=[],i=!0;for(let a of n){let s=a.match(vr)||a.match(mr),c=a.match(dr),l=a.match(_r),p=a.match(Sr)||a.match(br);if(s||c){let f=(s||c)?.[1],h=Boolean(t?.defines?.[f]),g=s?h:!h,_=i&&g;o.push({parentActive:i,branchTaken:g,active:_}),i=_}else if(l){let f=o[o.length-1];if(!f)throw new Error("Encountered #else without matching #ifdef or #ifndef");f.active=f.parentActive&&!f.branchTaken,f.branchTaken=!0,i=f.active}else p?(o.pop(),i=o.length?o[o.length-1].active:!0):i&&r.push(a)}if(o.length>0)throw new Error("Unterminated conditional block in shader source");return r.join(`
93
+ `)}var z=class{_hookFunctions=[];_defaultModules=[];_wgslBindingRegistry=new Map;static getDefaultShaderAssembler(){return z.defaultShaderAssembler=z.defaultShaderAssembler||new z,z.defaultShaderAssembler}addDefaultModule(t){this._defaultModules.find(n=>n.name===(typeof t=="string"?t:t.name))||this._defaultModules.push(t)}removeDefaultModule(t){let n=typeof t=="string"?t:t.name;this._defaultModules=this._defaultModules.filter(r=>r.name!==n)}addShaderHook(t,n){n&&(t=Object.assign(n,{hook:t})),this._hookFunctions.push(t)}assembleWGSLShader(t){let n=this._getModuleList(t.modules),r=this._hookFunctions,{source:o,getUniforms:i,bindingAssignments:a}=At({...t,source:t.source,_bindingRegistry:this._wgslBindingRegistry,modules:n,hookFunctions:r}),s={...n.reduce((l,p)=>(Object.assign(l,p.defines),l),{}),...t.defines},c=t.platformInfo.shaderLanguage==="wgsl"?ge(o,{defines:s}):o;return{source:c,getUniforms:i,modules:n,bindingAssignments:a,bindingTable:le(c,a)}}assembleGLSLShaderPair(t){let n=this._getModuleList(t.modules),r=this._hookFunctions;return{...he({...t,vs:t.vs,fs:t.fs,modules:n,hookFunctions:r}),modules:n}}_getModuleList(t=[]){let n=new Array(this._defaultModules.length+t.length),r={},o=0;for(let i=0,a=this._defaultModules.length;i<a;++i){let s=this._defaultModules[i],c=s.name;n[o++]=s,r[c]=!0}for(let i=0,a=t.length;i<a;++i){let s=t[i],c=s.name;r[c]||(n[o++]=s,r[c]=!0)}return n.length=o,T(n),n}},J=z;Je(J,"defaultShaderAssembler");var xr=`out vec4 transform_output;
88
94
  void main() {
89
95
  transform_output = vec4(0);
90
- }`,Tn=`#version 300 es
91
- ${yn}`;function ct(e,t){t=Array.isArray(t)?t:[t];let n=e.replace(/^\s+/,"").split(/\s+/),[i,r,o]=n;if(!t.includes(i)||!r||!o)return null;let s=o.split(";")[0];return{qualifier:i,type:r,name:s}}function at(e){let{input:t,inputChannels:n,output:i}=e||{};if(!t)return Tn;if(!n)throw new Error("inputChannels");let r=Fn(n),o=Ee(t,n);return`#version 300 es
92
- in ${r} ${t};
93
- out vec4 ${i};
96
+ }`,Mr=`#version 300 es
97
+ ${xr}`;function It(e,t){t=Array.isArray(t)?t:[t];let n=e.replace(/^\s+/,"").split(/\s+/),[r,o,i]=n;if(!t.includes(r)||!o||!i)return null;let a=i.split(";")[0];return{qualifier:r,type:o,name:a}}function Ct(e){let{input:t,inputChannels:n,output:r}=e||{};if(!t)return Mr;if(!n)throw new Error("inputChannels");let o=Lr(n),i=Be(t,n);return`#version 300 es
98
+ in ${o} ${t};
99
+ out vec4 ${r};
94
100
  void main() {
95
- ${i} = ${o};
96
- }`}function lt(e){switch(e){case"float":return"x";case"vec2":return"xy";case"vec3":return"xyz";case"vec4":return"xyzw";default:throw new Error(e)}}function ft(e){switch(e){case"float":return 1;case"vec2":return 2;case"vec3":return 3;case"vec4":return 4;default:throw new Error(e)}}function Fn(e){switch(e){case 1:return"float";case 2:return"vec2";case 3:return"vec3";case 4:return"vec4";default:throw new Error(`invalid channels: ${e}`)}}function Ee(e,t){switch(t){case 1:return`vec4(${e}, 0.0, 0.0, 1.0)`;case 2:return`vec4(${e}, 0.0, 1.0)`;case 3:return`vec4(${e}, 1.0)`;case 4:return e;default:throw new Error(`invalid channels: ${t}`)}}function D(e){return typeof e=="string"?e.charAt(0).toUpperCase()+e.slice(1):e}function pt(e,t){return wn(e,t)}function wn(e,t){let n=[];switch(t.uniforms){case"scoped-interface-blocks":case"unscoped-interface-blocks":n.push(`uniform ${D(e.name)} {`);break;case"uniforms":}for(let[i,r]of Object.entries(e.uniformTypes||{})){let o=kn(r);switch(t.uniforms){case"scoped-interface-blocks":n.push(` ${o} ${i};`);break;case"unscoped-interface-blocks":n.push(` ${o} ${e.name}_${i};`);break;case"uniforms":n.push(`uniform ${o} ${e.name}_${i};`)}}switch(t.uniforms){case"scoped-interface-blocks":n.push(`} ${e.name};`);break;case"unscoped-interface-blocks":n.push("};");break;case"uniforms":}return n.push(""),n.join(`
97
- `)}function kn(e){return{f32:"float",i32:"int",u32:"uint","vec2<f32>":"vec2","vec3<f32>":"vec3","vec4<f32>":"vec4","vec2<i32>":"ivec2","vec3<i32>":"ivec3","vec4<i32>":"ivec4","vec2<u32>":"uvec2","vec3<u32>":"uvec3","vec4<u32>":"uvec4","mat2x2<f32>":"mat2","mat2x3<f32>":"mat2x3","mat2x4<f32>":"mat2x4","mat3x2<f32>":"mat3x2","mat3x3<f32>":"mat3","mat3x4<f32>":"mat3x4","mat4x2<f32>":"mat4x2","mat4x3<f32>":"mat4x3","mat4x4<f32>":"mat4"}[e]}function ht(e,t){return Dn(e,t)}function Dn(e,t){let n=[];n.push(`struct ${D(e.name)} {`);for(let[i,r]of Object.entries(e?.uniformTypes||{})){let o=r;n.push(` ${i} : ${o};`)}return n.push("};"),n.push(`var<uniform> ${e.name} : ${D(e.name)};`),n.join(`
98
- `)}function gt(e,t){switch(t.shaderLanguage){case"glsl":return pt(e,t);case"wgsl":return ht(e,t)}}var lr=1/Math.PI*180,fr=1/180*Math.PI,Un={EPSILON:1e-12,debug:!1,precision:4,printTypes:!1,printDegrees:!1,printRowMajor:!0,_cartographicRadians:!1};globalThis.mathgl=globalThis.mathgl||{config:{...Un}};var C=globalThis.mathgl.config;function Ie(e,{precision:t=C.precision}={}){return e=Bn(e),`${parseFloat(e.toPrecision(t))}`}function z(e){return Array.isArray(e)||ArrayBuffer.isView(e)&&!(e instanceof DataView)}function Pe(e,t,n){return Hn(e,i=>Math.max(t,Math.min(n,i)))}function le(e,t,n){let i=C.EPSILON;n&&(C.EPSILON=n);try{if(e===t)return!0;if(z(e)&&z(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;++r)if(!le(e[r],t[r]))return!1;return!0}return e&&e.equals?e.equals(t):t&&t.equals?t.equals(e):typeof e=="number"&&typeof t=="number"?Math.abs(e-t)<=C.EPSILON*Math.max(1,Math.abs(e),Math.abs(t)):!1}finally{C.EPSILON=i}}function Bn(e){return Math.round(e/C.EPSILON)*C.EPSILON}function zn(e){return e.clone?e.clone():new Array(e.length)}function Hn(e,t,n){if(z(e)){let i=e;n=n||zn(i);for(let r=0;r<n.length&&r<i.length;++r){let o=typeof e=="number"?e:e[r];n[r]=t(o,r,n)}return n}return t(e)}var fe=class extends Array{clone(){return new this.constructor().copy(this)}fromArray(t,n=0){for(let i=0;i<this.ELEMENTS;++i)this[i]=t[i+n];return this.check()}toArray(t=[],n=0){for(let i=0;i<this.ELEMENTS;++i)t[n+i]=this[i];return t}toObject(t){return t}from(t){return Array.isArray(t)?this.copy(t):this.fromObject(t)}to(t){return t===this?this:z(t)?this.toArray(t):this.toObject(t)}toTarget(t){return t?this.to(t):this}toFloat32Array(){return new Float32Array(this)}toString(){return this.formatString(C)}formatString(t){let n="";for(let i=0;i<this.ELEMENTS;++i)n+=(i>0?", ":"")+Ie(this[i],t);return`${t.printTypes?this.constructor.name:""}[${n}]`}equals(t){if(!t||this.length!==t.length)return!1;for(let n=0;n<this.ELEMENTS;++n)if(!le(this[n],t[n]))return!1;return!0}exactEquals(t){if(!t||this.length!==t.length)return!1;for(let n=0;n<this.ELEMENTS;++n)if(this[n]!==t[n])return!1;return!0}negate(){for(let t=0;t<this.ELEMENTS;++t)this[t]=-this[t];return this.check()}lerp(t,n,i){if(i===void 0)return this.lerp(this,t,n);for(let r=0;r<this.ELEMENTS;++r){let o=t[r],s=typeof n=="number"?n:n[r];this[r]=o+i*(s-o)}return this.check()}min(t){for(let n=0;n<this.ELEMENTS;++n)this[n]=Math.min(t[n],this[n]);return this.check()}max(t){for(let n=0;n<this.ELEMENTS;++n)this[n]=Math.max(t[n],this[n]);return this.check()}clamp(t,n){for(let i=0;i<this.ELEMENTS;++i)this[i]=Math.min(Math.max(this[i],t[i]),n[i]);return this.check()}add(...t){for(let n of t)for(let i=0;i<this.ELEMENTS;++i)this[i]+=n[i];return this.check()}subtract(...t){for(let n of t)for(let i=0;i<this.ELEMENTS;++i)this[i]-=n[i];return this.check()}scale(t){if(typeof t=="number")for(let n=0;n<this.ELEMENTS;++n)this[n]*=t;else for(let n=0;n<this.ELEMENTS&&n<t.length;++n)this[n]*=t[n];return this.check()}multiplyByScalar(t){for(let n=0;n<this.ELEMENTS;++n)this[n]*=t;return this.check()}check(){if(C.debug&&!this.validate())throw new Error(`math.gl: ${this.constructor.name} some fields set to invalid numbers'`);return this}validate(){let t=this.length===this.ELEMENTS;for(let n=0;n<this.ELEMENTS;++n)t=t&&Number.isFinite(this[n]);return t}sub(t){return this.subtract(t)}setScalar(t){for(let n=0;n<this.ELEMENTS;++n)this[n]=t;return this.check()}addScalar(t){for(let n=0;n<this.ELEMENTS;++n)this[n]+=t;return this.check()}subScalar(t){return this.addScalar(-t)}multiplyScalar(t){for(let n=0;n<this.ELEMENTS;++n)this[n]*=t;return this.check()}divideScalar(t){return this.multiplyByScalar(1/t)}clampScalar(t,n){for(let i=0;i<this.ELEMENTS;++i)this[i]=Math.min(Math.max(this[i],t),n);return this.check()}get elements(){return this}};function Gn(e,t){if(e.length!==t)return!1;for(let n=0;n<e.length;++n)if(!Number.isFinite(e[n]))return!1;return!0}function mt(e){if(!Number.isFinite(e))throw new Error(`Invalid number ${JSON.stringify(e)}`);return e}function pe(e,t,n=""){if(C.debug&&!Gn(e,t))throw new Error(`math.gl: ${n} some fields set to invalid numbers'`);return e}var w=typeof Float32Array<"u"?Float32Array:Array;var ur=Math.PI/180;function Vn(){let e=new w(2);return w!=Float32Array&&(e[0]=0,e[1]=0),e}function dt(e,t,n){let i=t[0],r=t[1];return e[0]=n[0]*i+n[4]*r+n[12],e[1]=n[1]*i+n[5]*r+n[13],e}var dr=function(){let e=Vn();return function(t,n,i,r,o,s){let c,a;for(n||(n=2),i||(i=0),r?a=Math.min(r*n+i,t.length):a=t.length,c=i;c<a;c+=n)e[0]=t[c],e[1]=t[c+1],o(e,e,s),t[c]=e[0],t[c+1]=e[1];return t}}();function vt(e,t,n){let i=t[0],r=t[1],o=n[3]*i+n[7]*r||1;return e[0]=(n[0]*i+n[4]*r)/o,e[1]=(n[1]*i+n[5]*r)/o,e}function xt(e,t,n){let i=t[0],r=t[1],o=t[2],s=n[3]*i+n[7]*r+n[11]*o||1;return e[0]=(n[0]*i+n[4]*r+n[8]*o)/s,e[1]=(n[1]*i+n[5]*r+n[9]*o)/s,e[2]=(n[2]*i+n[6]*r+n[10]*o)/s,e}function jn(){let e=new w(3);return w!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0),e}function bt(e,t,n){let i=t[0],r=t[1],o=t[2],s=n[3]*i+n[7]*r+n[11]*o+n[15];return s=s||1,e[0]=(n[0]*i+n[4]*r+n[8]*o+n[12])/s,e[1]=(n[1]*i+n[5]*r+n[9]*o+n[13])/s,e[2]=(n[2]*i+n[6]*r+n[10]*o+n[14])/s,e}var br=function(){let e=jn();return function(t,n,i,r,o,s){let c,a;for(n||(n=3),i||(i=0),r?a=Math.min(r*n+i,t.length):a=t.length,c=i;c<a;c+=n)e[0]=t[c],e[1]=t[c+1],e[2]=t[c+2],o(e,e,s),t[c]=e[0],t[c+1]=e[1],t[c+2]=e[2];return t}}();var he=class extends fe{toString(){let t="[";if(C.printRowMajor){t+="row-major:";for(let n=0;n<this.RANK;++n)for(let i=0;i<this.RANK;++i)t+=` ${this[i*this.RANK+n]}`}else{t+="column-major:";for(let n=0;n<this.ELEMENTS;++n)t+=` ${this[n]}`}return t+="]",t}getElementIndex(t,n){return n*this.RANK+t}getElement(t,n){return this[n*this.RANK+t]}setElement(t,n,i){return this[n*this.RANK+t]=mt(i),this}getColumn(t,n=new Array(this.RANK).fill(-0)){let i=t*this.RANK;for(let r=0;r<this.RANK;++r)n[r]=this[i+r];return n}setColumn(t,n){let i=t*this.RANK;for(let r=0;r<this.RANK;++r)this[i+r]=n[r];return this}};function qn(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}function Mt(e,t){if(e===t){let n=t[1],i=t[2],r=t[3],o=t[6],s=t[7],c=t[11];e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=n,e[6]=t[9],e[7]=t[13],e[8]=i,e[9]=o,e[11]=t[14],e[12]=r,e[13]=s,e[14]=c}else e[0]=t[0],e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=t[1],e[5]=t[5],e[6]=t[9],e[7]=t[13],e[8]=t[2],e[9]=t[6],e[10]=t[10],e[11]=t[14],e[12]=t[3],e[13]=t[7],e[14]=t[11],e[15]=t[15];return e}function At(e,t){let n=t[0],i=t[1],r=t[2],o=t[3],s=t[4],c=t[5],a=t[6],l=t[7],h=t[8],f=t[9],p=t[10],m=t[11],x=t[12],_=t[13],d=t[14],g=t[15],A=n*c-i*s,v=n*a-r*s,M=n*l-o*s,b=i*a-r*c,u=i*l-o*c,I=r*l-o*a,E=h*_-f*x,L=h*d-p*x,P=h*g-m*x,O=f*d-p*_,R=f*g-m*_,N=p*g-m*d,S=A*N-v*R+M*O+b*P-u*L+I*E;return S?(S=1/S,e[0]=(c*N-a*R+l*O)*S,e[1]=(r*R-i*N-o*O)*S,e[2]=(_*I-d*u+g*b)*S,e[3]=(p*u-f*I-m*b)*S,e[4]=(a*P-s*N-l*L)*S,e[5]=(n*N-r*P+o*L)*S,e[6]=(d*M-x*I-g*v)*S,e[7]=(h*I-p*M+m*v)*S,e[8]=(s*R-c*P+l*E)*S,e[9]=(i*P-n*R-o*E)*S,e[10]=(x*u-_*M+g*A)*S,e[11]=(f*M-h*u-m*A)*S,e[12]=(c*L-s*O-a*E)*S,e[13]=(n*O-i*L+r*E)*S,e[14]=(_*v-x*b-d*A)*S,e[15]=(h*b-f*v+p*A)*S,e):null}function Lt(e){let t=e[0],n=e[1],i=e[2],r=e[3],o=e[4],s=e[5],c=e[6],a=e[7],l=e[8],h=e[9],f=e[10],p=e[11],m=e[12],x=e[13],_=e[14],d=e[15],g=t*s-n*o,A=t*c-i*o,v=n*c-i*s,M=l*x-h*m,b=l*_-f*m,u=h*_-f*x,I=t*u-n*b+i*M,E=o*u-s*b+c*M,L=l*v-h*A+f*g,P=m*v-x*A+_*g;return a*I-r*E+d*L-p*P}function Ce(e,t,n){let i=t[0],r=t[1],o=t[2],s=t[3],c=t[4],a=t[5],l=t[6],h=t[7],f=t[8],p=t[9],m=t[10],x=t[11],_=t[12],d=t[13],g=t[14],A=t[15],v=n[0],M=n[1],b=n[2],u=n[3];return e[0]=v*i+M*c+b*f+u*_,e[1]=v*r+M*a+b*p+u*d,e[2]=v*o+M*l+b*m+u*g,e[3]=v*s+M*h+b*x+u*A,v=n[4],M=n[5],b=n[6],u=n[7],e[4]=v*i+M*c+b*f+u*_,e[5]=v*r+M*a+b*p+u*d,e[6]=v*o+M*l+b*m+u*g,e[7]=v*s+M*h+b*x+u*A,v=n[8],M=n[9],b=n[10],u=n[11],e[8]=v*i+M*c+b*f+u*_,e[9]=v*r+M*a+b*p+u*d,e[10]=v*o+M*l+b*m+u*g,e[11]=v*s+M*h+b*x+u*A,v=n[12],M=n[13],b=n[14],u=n[15],e[12]=v*i+M*c+b*f+u*_,e[13]=v*r+M*a+b*p+u*d,e[14]=v*o+M*l+b*m+u*g,e[15]=v*s+M*h+b*x+u*A,e}function St(e,t,n){let i=n[0],r=n[1],o=n[2],s,c,a,l,h,f,p,m,x,_,d,g;return t===e?(e[12]=t[0]*i+t[4]*r+t[8]*o+t[12],e[13]=t[1]*i+t[5]*r+t[9]*o+t[13],e[14]=t[2]*i+t[6]*r+t[10]*o+t[14],e[15]=t[3]*i+t[7]*r+t[11]*o+t[15]):(s=t[0],c=t[1],a=t[2],l=t[3],h=t[4],f=t[5],p=t[6],m=t[7],x=t[8],_=t[9],d=t[10],g=t[11],e[0]=s,e[1]=c,e[2]=a,e[3]=l,e[4]=h,e[5]=f,e[6]=p,e[7]=m,e[8]=x,e[9]=_,e[10]=d,e[11]=g,e[12]=s*i+h*r+x*o+t[12],e[13]=c*i+f*r+_*o+t[13],e[14]=a*i+p*r+d*o+t[14],e[15]=l*i+m*r+g*o+t[15]),e}function Et(e,t,n){let i=n[0],r=n[1],o=n[2];return e[0]=t[0]*i,e[1]=t[1]*i,e[2]=t[2]*i,e[3]=t[3]*i,e[4]=t[4]*r,e[5]=t[5]*r,e[6]=t[6]*r,e[7]=t[7]*r,e[8]=t[8]*o,e[9]=t[9]*o,e[10]=t[10]*o,e[11]=t[11]*o,e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e}function It(e,t,n,i){let r=i[0],o=i[1],s=i[2],c=Math.sqrt(r*r+o*o+s*s),a,l,h,f,p,m,x,_,d,g,A,v,M,b,u,I,E,L,P,O,R,N,S,V;return c<1e-6?null:(c=1/c,r*=c,o*=c,s*=c,l=Math.sin(n),a=Math.cos(n),h=1-a,f=t[0],p=t[1],m=t[2],x=t[3],_=t[4],d=t[5],g=t[6],A=t[7],v=t[8],M=t[9],b=t[10],u=t[11],I=r*r*h+a,E=o*r*h+s*l,L=s*r*h-o*l,P=r*o*h-s*l,O=o*o*h+a,R=s*o*h+r*l,N=r*s*h+o*l,S=o*s*h-r*l,V=s*s*h+a,e[0]=f*I+_*E+v*L,e[1]=p*I+d*E+M*L,e[2]=m*I+g*E+b*L,e[3]=x*I+A*E+u*L,e[4]=f*P+_*O+v*R,e[5]=p*P+d*O+M*R,e[6]=m*P+g*O+b*R,e[7]=x*P+A*O+u*R,e[8]=f*N+_*S+v*V,e[9]=p*N+d*S+M*V,e[10]=m*N+g*S+b*V,e[11]=x*N+A*S+u*V,t!==e&&(e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e)}function Pt(e,t,n){let i=Math.sin(n),r=Math.cos(n),o=t[4],s=t[5],c=t[6],a=t[7],l=t[8],h=t[9],f=t[10],p=t[11];return t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[4]=o*r+l*i,e[5]=s*r+h*i,e[6]=c*r+f*i,e[7]=a*r+p*i,e[8]=l*r-o*i,e[9]=h*r-s*i,e[10]=f*r-c*i,e[11]=p*r-a*i,e}function Rt(e,t,n){let i=Math.sin(n),r=Math.cos(n),o=t[0],s=t[1],c=t[2],a=t[3],l=t[8],h=t[9],f=t[10],p=t[11];return t!==e&&(e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=o*r-l*i,e[1]=s*r-h*i,e[2]=c*r-f*i,e[3]=a*r-p*i,e[8]=o*i+l*r,e[9]=s*i+h*r,e[10]=c*i+f*r,e[11]=a*i+p*r,e}function Ct(e,t,n){let i=Math.sin(n),r=Math.cos(n),o=t[0],s=t[1],c=t[2],a=t[3],l=t[4],h=t[5],f=t[6],p=t[7];return t!==e&&(e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=o*r+l*i,e[1]=s*r+h*i,e[2]=c*r+f*i,e[3]=a*r+p*i,e[4]=l*r-o*i,e[5]=h*r-s*i,e[6]=f*r-c*i,e[7]=p*r-a*i,e}function Ot(e,t){let n=t[0],i=t[1],r=t[2],o=t[3],s=n+n,c=i+i,a=r+r,l=n*s,h=i*s,f=i*c,p=r*s,m=r*c,x=r*a,_=o*s,d=o*c,g=o*a;return e[0]=1-f-x,e[1]=h+g,e[2]=p-d,e[3]=0,e[4]=h-g,e[5]=1-l-x,e[6]=m+_,e[7]=0,e[8]=p+d,e[9]=m-_,e[10]=1-l-f,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}function Nt(e,t,n,i,r,o,s){let c=1/(n-t),a=1/(r-i),l=1/(o-s);return e[0]=o*2*c,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=o*2*a,e[6]=0,e[7]=0,e[8]=(n+t)*c,e[9]=(r+i)*a,e[10]=(s+o)*l,e[11]=-1,e[12]=0,e[13]=0,e[14]=s*o*2*l,e[15]=0,e}function Wn(e,t,n,i,r){let o=1/Math.tan(t/2);if(e[0]=o/n,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=o,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[11]=-1,e[12]=0,e[13]=0,e[15]=0,r!=null&&r!==1/0){let s=1/(i-r);e[10]=(r+i)*s,e[14]=2*r*i*s}else e[10]=-1,e[14]=-2*i;return e}var yt=Wn;function $n(e,t,n,i,r,o,s){let c=1/(t-n),a=1/(i-r),l=1/(o-s);return e[0]=-2*c,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=-2*a,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=2*l,e[11]=0,e[12]=(t+n)*c,e[13]=(r+i)*a,e[14]=(s+o)*l,e[15]=1,e}var Tt=$n;function Ft(e,t,n,i){let r,o,s,c,a,l,h,f,p,m,x=t[0],_=t[1],d=t[2],g=i[0],A=i[1],v=i[2],M=n[0],b=n[1],u=n[2];return Math.abs(x-M)<1e-6&&Math.abs(_-b)<1e-6&&Math.abs(d-u)<1e-6?qn(e):(f=x-M,p=_-b,m=d-u,r=1/Math.sqrt(f*f+p*p+m*m),f*=r,p*=r,m*=r,o=A*m-v*p,s=v*f-g*m,c=g*p-A*f,r=Math.sqrt(o*o+s*s+c*c),r?(r=1/r,o*=r,s*=r,c*=r):(o=0,s=0,c=0),a=p*c-m*s,l=m*o-f*c,h=f*s-p*o,r=Math.sqrt(a*a+l*l+h*h),r?(r=1/r,a*=r,l*=r,h*=r):(a=0,l=0,h=0),e[0]=o,e[1]=a,e[2]=f,e[3]=0,e[4]=s,e[5]=l,e[6]=p,e[7]=0,e[8]=c,e[9]=h,e[10]=m,e[11]=0,e[12]=-(o*x+s*_+c*d),e[13]=-(a*x+l*_+h*d),e[14]=-(f*x+p*_+m*d),e[15]=1,e)}function Yn(){let e=new w(4);return w!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0,e[3]=0),e}function wt(e,t,n){let i=t[0],r=t[1],o=t[2],s=t[3];return e[0]=n[0]*i+n[4]*r+n[8]*o+n[12]*s,e[1]=n[1]*i+n[5]*r+n[9]*o+n[13]*s,e[2]=n[2]*i+n[6]*r+n[10]*o+n[14]*s,e[3]=n[3]*i+n[7]*r+n[11]*o+n[15]*s,e}var Pr=function(){let e=Yn();return function(t,n,i,r,o,s){let c,a;for(n||(n=4),i||(i=0),r?a=Math.min(r*n+i,t.length):a=t.length,c=i;c<a;c+=n)e[0]=t[c],e[1]=t[c+1],e[2]=t[c+2],e[3]=t[c+3],o(e,e,s),t[c]=e[0],t[c+1]=e[1],t[c+2]=e[2],t[c+3]=e[3];return t}}();var ye;(function(e){e[e.COL0ROW0=0]="COL0ROW0",e[e.COL0ROW1=1]="COL0ROW1",e[e.COL0ROW2=2]="COL0ROW2",e[e.COL0ROW3=3]="COL0ROW3",e[e.COL1ROW0=4]="COL1ROW0",e[e.COL1ROW1=5]="COL1ROW1",e[e.COL1ROW2=6]="COL1ROW2",e[e.COL1ROW3=7]="COL1ROW3",e[e.COL2ROW0=8]="COL2ROW0",e[e.COL2ROW1=9]="COL2ROW1",e[e.COL2ROW2=10]="COL2ROW2",e[e.COL2ROW3=11]="COL2ROW3",e[e.COL3ROW0=12]="COL3ROW0",e[e.COL3ROW1=13]="COL3ROW1",e[e.COL3ROW2=14]="COL3ROW2",e[e.COL3ROW3=15]="COL3ROW3"})(ye||(ye={}));var Kn=45*Math.PI/180,Xn=1,Oe=.1,Ne=500,Zn=Object.freeze([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),k=class extends he{static get IDENTITY(){return Qn()}static get ZERO(){return Jn()}get ELEMENTS(){return 16}get RANK(){return 4}get INDICES(){return ye}constructor(t){super(-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0),arguments.length===1&&Array.isArray(t)?this.copy(t):this.identity()}copy(t){return this[0]=t[0],this[1]=t[1],this[2]=t[2],this[3]=t[3],this[4]=t[4],this[5]=t[5],this[6]=t[6],this[7]=t[7],this[8]=t[8],this[9]=t[9],this[10]=t[10],this[11]=t[11],this[12]=t[12],this[13]=t[13],this[14]=t[14],this[15]=t[15],this.check()}set(t,n,i,r,o,s,c,a,l,h,f,p,m,x,_,d){return this[0]=t,this[1]=n,this[2]=i,this[3]=r,this[4]=o,this[5]=s,this[6]=c,this[7]=a,this[8]=l,this[9]=h,this[10]=f,this[11]=p,this[12]=m,this[13]=x,this[14]=_,this[15]=d,this.check()}setRowMajor(t,n,i,r,o,s,c,a,l,h,f,p,m,x,_,d){return this[0]=t,this[1]=o,this[2]=l,this[3]=m,this[4]=n,this[5]=s,this[6]=h,this[7]=x,this[8]=i,this[9]=c,this[10]=f,this[11]=_,this[12]=r,this[13]=a,this[14]=p,this[15]=d,this.check()}toRowMajor(t){return t[0]=this[0],t[1]=this[4],t[2]=this[8],t[3]=this[12],t[4]=this[1],t[5]=this[5],t[6]=this[9],t[7]=this[13],t[8]=this[2],t[9]=this[6],t[10]=this[10],t[11]=this[14],t[12]=this[3],t[13]=this[7],t[14]=this[11],t[15]=this[15],t}identity(){return this.copy(Zn)}fromObject(t){return this.check()}fromQuaternion(t){return Ot(this,t),this.check()}frustum(t){let{left:n,right:i,bottom:r,top:o,near:s=Oe,far:c=Ne}=t;return c===1/0?ei(this,n,i,r,o,s):Nt(this,n,i,r,o,s,c),this.check()}lookAt(t){let{eye:n,center:i=[0,0,0],up:r=[0,1,0]}=t;return Ft(this,n,i,r),this.check()}ortho(t){let{left:n,right:i,bottom:r,top:o,near:s=Oe,far:c=Ne}=t;return Tt(this,n,i,r,o,s,c),this.check()}orthographic(t){let{fovy:n=Kn,aspect:i=Xn,focalDistance:r=1,near:o=Oe,far:s=Ne}=t;kt(n);let c=n/2,a=r*Math.tan(c),l=a*i;return this.ortho({left:-l,right:l,bottom:-a,top:a,near:o,far:s})}perspective(t){let{fovy:n=45*Math.PI/180,aspect:i=1,near:r=.1,far:o=500}=t;return kt(n),yt(this,n,i,r,o),this.check()}determinant(){return Lt(this)}getScale(t=[-0,-0,-0]){return t[0]=Math.sqrt(this[0]*this[0]+this[1]*this[1]+this[2]*this[2]),t[1]=Math.sqrt(this[4]*this[4]+this[5]*this[5]+this[6]*this[6]),t[2]=Math.sqrt(this[8]*this[8]+this[9]*this[9]+this[10]*this[10]),t}getTranslation(t=[-0,-0,-0]){return t[0]=this[12],t[1]=this[13],t[2]=this[14],t}getRotation(t,n){t=t||[-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0],n=n||[-0,-0,-0];let i=this.getScale(n),r=1/i[0],o=1/i[1],s=1/i[2];return t[0]=this[0]*r,t[1]=this[1]*o,t[2]=this[2]*s,t[3]=0,t[4]=this[4]*r,t[5]=this[5]*o,t[6]=this[6]*s,t[7]=0,t[8]=this[8]*r,t[9]=this[9]*o,t[10]=this[10]*s,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}getRotationMatrix3(t,n){t=t||[-0,-0,-0,-0,-0,-0,-0,-0,-0],n=n||[-0,-0,-0];let i=this.getScale(n),r=1/i[0],o=1/i[1],s=1/i[2];return t[0]=this[0]*r,t[1]=this[1]*o,t[2]=this[2]*s,t[3]=this[4]*r,t[4]=this[5]*o,t[5]=this[6]*s,t[6]=this[8]*r,t[7]=this[9]*o,t[8]=this[10]*s,t}transpose(){return Mt(this,this),this.check()}invert(){return At(this,this),this.check()}multiplyLeft(t){return Ce(this,t,this),this.check()}multiplyRight(t){return Ce(this,this,t),this.check()}rotateX(t){return Pt(this,this,t),this.check()}rotateY(t){return Rt(this,this,t),this.check()}rotateZ(t){return Ct(this,this,t),this.check()}rotateXYZ(t){return this.rotateX(t[0]).rotateY(t[1]).rotateZ(t[2])}rotateAxis(t,n){return It(this,this,t,n),this.check()}scale(t){return Et(this,this,Array.isArray(t)?t:[t,t,t]),this.check()}translate(t){return St(this,this,t),this.check()}transform(t,n){return t.length===4?(n=wt(n||[-0,-0,-0,-0],t,this),pe(n,4),n):this.transformAsPoint(t,n)}transformAsPoint(t,n){let{length:i}=t,r;switch(i){case 2:r=dt(n||[-0,-0],t,this);break;case 3:r=bt(n||[-0,-0,-0],t,this);break;default:throw new Error("Illegal vector")}return pe(r,t.length),r}transformAsVector(t,n){let i;switch(t.length){case 2:i=vt(n||[-0,-0],t,this);break;case 3:i=xt(n||[-0,-0,-0],t,this);break;default:throw new Error("Illegal vector")}return pe(i,t.length),i}transformPoint(t,n){return this.transformAsPoint(t,n)}transformVector(t,n){return this.transformAsPoint(t,n)}transformDirection(t,n){return this.transformAsVector(t,n)}makeRotationX(t){return this.identity().rotateX(t)}makeTranslation(t,n,i){return this.identity().translate([t,n,i])}},ge,me;function Jn(){return ge||(ge=new k([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),Object.freeze(ge)),ge}function Qn(){return me||(me=new k,Object.freeze(me)),me}function kt(e){if(e>Math.PI*2)throw Error("expected radians")}function ei(e,t,n,i,r,o){let s=2*o/(n-t),c=2*o/(r-i),a=(n+t)/(n-t),l=(r+i)/(r-i),h=-1,f=-1,p=-2*o;return e[0]=s,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=c,e[6]=0,e[7]=0,e[8]=a,e[9]=l,e[10]=h,e[11]=f,e[12]=0,e[13]=0,e[14]=p,e[15]=0,e}var U=null,Dt=new ArrayBuffer(4),Ut=new Float32Array(Dt),Bt=new Uint32Array(Dt);function zt(e){U||=Gt(),e=Pe(e,-65504,65504),Ut[0]=e;let t=Bt[0],n=t>>23&511;return U.baseTable[n]+((t&8388607)>>U.shiftTable[n])}function Ht(e){U||=Gt();let t=e>>10;return Bt[0]=U.mantissaTable[U.offsetTable[t]+(e&1023)]+U.exponentTable[t],Ut[0]}function Gt(){let e=new Uint32Array(512),t=new Uint32Array(512);for(let o=0;o<256;++o){let s=o-127;s<-27?(e[o]=0,e[o|256]=32768,t[o]=24,t[o|256]=24):s<-14?(e[o]=1024>>-s-14,e[o|256]=1024>>-s-14|32768,t[o]=-s-1,t[o|256]=-s-1):s<=15?(e[o]=s+15<<10,e[o|256]=s+15<<10|32768,t[o]=13,t[o|256]=13):s<128?(e[o]=31744,e[o|256]=64512,t[o]=24,t[o|256]=24):(e[o]=31744,e[o|256]=64512,t[o]=13,t[o|256]=13)}let n=new Uint32Array(2048),i=new Uint32Array(64),r=new Uint32Array(64);for(let o=1;o<1024;++o){let s=o<<13,c=0;for(;!(s&8388608);)s<<=1,c-=8388608;s&=-8388609,c+=947912704,n[o]=s|c}for(let o=1024;o<2048;++o)n[o]=939524096+(o-1024<<13);for(let o=1;o<31;++o)i[o]=o<<23;i[31]=1199570944,i[32]=2147483648;for(let o=33;o<63;++o)i[o]=2147483648+(o-32<<23);i[63]=3347054592;for(let o=1;o<64;++o)o!==32&&(r[o]=1024);return{baseTable:e,shiftTable:t,mantissaTable:n,exponentTable:i,offsetTable:r}}function G(e,t=[],n=0){let i=Math.fround(e),r=e-i;return t[n]=i,t[n+1]=r,t}function Z(e){return e-Math.fround(e)}function J(e){let t=new Float32Array(32);for(let n=0;n<4;++n)for(let i=0;i<4;++i){let r=n*4+i;G(e[i*4+n],t,r*2)}return t}var ti=`fn random(scale: vec3f, seed: f32) -> f32 {
101
+ ${r} = ${i};
102
+ }`}function Pt(e){switch(e){case"float":return"x";case"vec2":return"xy";case"vec3":return"xyz";case"vec4":return"xyzw";default:throw new Error(e)}}function Nt(e){switch(e){case"float":return 1;case"vec2":return 2;case"vec3":return 3;case"vec4":return 4;default:throw new Error(e)}}function Lr(e){switch(e){case 1:return"float";case 2:return"vec2";case 3:return"vec3";case 4:return"vec4";default:throw new Error(`invalid channels: ${e}`)}}function Be(e,t){switch(t){case 1:return`vec4(${e}, 0.0, 0.0, 1.0)`;case 2:return`vec4(${e}, 0.0, 1.0)`;case 3:return`vec4(${e}, 1.0)`;case 4:return e;default:throw new Error(`invalid channels: ${t}`)}}function k(e){return typeof e=="string"?e.charAt(0).toUpperCase()+e.slice(1):e}function yt(e,t){return Ar(e,t)}function Ar(e,t){let n=[];switch(t.uniforms){case"scoped-interface-blocks":case"unscoped-interface-blocks":n.push(`uniform ${k(e.name)} {`);break;case"uniforms":}for(let[r,o]of Object.entries(e.uniformTypes||{})){if(typeof o!="string")throw new Error(`Composite uniform types are not supported by GLSL shader generation: ${e.name}.${r}`);let i=Er(o);switch(t.uniforms){case"scoped-interface-blocks":n.push(` ${i} ${r};`);break;case"unscoped-interface-blocks":n.push(` ${i} ${e.name}_${r};`);break;case"uniforms":n.push(`uniform ${i} ${e.name}_${r};`)}}switch(t.uniforms){case"scoped-interface-blocks":n.push(`} ${e.name};`);break;case"unscoped-interface-blocks":n.push("};");break;case"uniforms":}return n.push(""),n.join(`
103
+ `)}function Er(e){return{f32:"float",i32:"int",u32:"uint","vec2<f32>":"vec2","vec3<f32>":"vec3","vec4<f32>":"vec4","vec2<i32>":"ivec2","vec3<i32>":"ivec3","vec4<i32>":"ivec4","vec2<u32>":"uvec2","vec3<u32>":"uvec3","vec4<u32>":"uvec4","mat2x2<f32>":"mat2","mat2x3<f32>":"mat2x3","mat2x4<f32>":"mat2x4","mat3x2<f32>":"mat3x2","mat3x3<f32>":"mat3","mat3x4<f32>":"mat3x4","mat4x2<f32>":"mat4x2","mat4x3<f32>":"mat4x3","mat4x4<f32>":"mat4"}[e]}function Ot(e,t){return Rr(e,t)}function Rr(e,t){let n=[];n.push(`struct ${k(e.name)} {`);for(let[r,o]of Object.entries(e?.uniformTypes||{})){if(typeof o!="string")throw new Error(`Composite uniform types are not supported by WGSL shader generation: ${e.name}.${r}`);let i=o;n.push(` ${r} : ${i};`)}return n.push("};"),n.push(`var<uniform> ${e.name} : ${k(e.name)};`),n.join(`
104
+ `)}function Tt(e,t){switch(t.shaderLanguage){case"glsl":return yt(e,t);case"wgsl":return Ot(e,t)}}var li=1/Math.PI*180,fi=1/180*Math.PI,Ir={EPSILON:1e-12,debug:!1,precision:4,printTypes:!1,printDegrees:!1,printRowMajor:!0,_cartographicRadians:!1};globalThis.mathgl=globalThis.mathgl||{config:{...Ir}};var P=globalThis.mathgl.config;function ke(e,{precision:t=P.precision}={}){return e=Cr(e),`${parseFloat(e.toPrecision(t))}`}function H(e){return Array.isArray(e)||ArrayBuffer.isView(e)&&!(e instanceof DataView)}function De(e,t,n){return Nr(e,r=>Math.max(t,Math.min(n,r)))}function me(e,t,n){let r=P.EPSILON;n&&(P.EPSILON=n);try{if(e===t)return!0;if(H(e)&&H(t)){if(e.length!==t.length)return!1;for(let o=0;o<e.length;++o)if(!me(e[o],t[o]))return!1;return!0}return e&&e.equals?e.equals(t):t&&t.equals?t.equals(e):typeof e=="number"&&typeof t=="number"?Math.abs(e-t)<=P.EPSILON*Math.max(1,Math.abs(e),Math.abs(t)):!1}finally{P.EPSILON=r}}function Cr(e){return Math.round(e/P.EPSILON)*P.EPSILON}function Pr(e){return e.clone?e.clone():new Array(e.length)}function Nr(e,t,n){if(H(e)){let r=e;n=n||Pr(r);for(let o=0;o<n.length&&o<r.length;++o){let i=typeof e=="number"?e:e[o];n[o]=t(i,o,n)}return n}return t(e)}var de=class extends Array{clone(){return new this.constructor().copy(this)}fromArray(t,n=0){for(let r=0;r<this.ELEMENTS;++r)this[r]=t[r+n];return this.check()}toArray(t=[],n=0){for(let r=0;r<this.ELEMENTS;++r)t[n+r]=this[r];return t}toObject(t){return t}from(t){return Array.isArray(t)?this.copy(t):this.fromObject(t)}to(t){return t===this?this:H(t)?this.toArray(t):this.toObject(t)}toTarget(t){return t?this.to(t):this}toFloat32Array(){return new Float32Array(this)}toString(){return this.formatString(P)}formatString(t){let n="";for(let r=0;r<this.ELEMENTS;++r)n+=(r>0?", ":"")+ke(this[r],t);return`${t.printTypes?this.constructor.name:""}[${n}]`}equals(t){if(!t||this.length!==t.length)return!1;for(let n=0;n<this.ELEMENTS;++n)if(!me(this[n],t[n]))return!1;return!0}exactEquals(t){if(!t||this.length!==t.length)return!1;for(let n=0;n<this.ELEMENTS;++n)if(this[n]!==t[n])return!1;return!0}negate(){for(let t=0;t<this.ELEMENTS;++t)this[t]=-this[t];return this.check()}lerp(t,n,r){if(r===void 0)return this.lerp(this,t,n);for(let o=0;o<this.ELEMENTS;++o){let i=t[o],a=typeof n=="number"?n:n[o];this[o]=i+r*(a-i)}return this.check()}min(t){for(let n=0;n<this.ELEMENTS;++n)this[n]=Math.min(t[n],this[n]);return this.check()}max(t){for(let n=0;n<this.ELEMENTS;++n)this[n]=Math.max(t[n],this[n]);return this.check()}clamp(t,n){for(let r=0;r<this.ELEMENTS;++r)this[r]=Math.min(Math.max(this[r],t[r]),n[r]);return this.check()}add(...t){for(let n of t)for(let r=0;r<this.ELEMENTS;++r)this[r]+=n[r];return this.check()}subtract(...t){for(let n of t)for(let r=0;r<this.ELEMENTS;++r)this[r]-=n[r];return this.check()}scale(t){if(typeof t=="number")for(let n=0;n<this.ELEMENTS;++n)this[n]*=t;else for(let n=0;n<this.ELEMENTS&&n<t.length;++n)this[n]*=t[n];return this.check()}multiplyByScalar(t){for(let n=0;n<this.ELEMENTS;++n)this[n]*=t;return this.check()}check(){if(P.debug&&!this.validate())throw new Error(`math.gl: ${this.constructor.name} some fields set to invalid numbers'`);return this}validate(){let t=this.length===this.ELEMENTS;for(let n=0;n<this.ELEMENTS;++n)t=t&&Number.isFinite(this[n]);return t}sub(t){return this.subtract(t)}setScalar(t){for(let n=0;n<this.ELEMENTS;++n)this[n]=t;return this.check()}addScalar(t){for(let n=0;n<this.ELEMENTS;++n)this[n]+=t;return this.check()}subScalar(t){return this.addScalar(-t)}multiplyScalar(t){for(let n=0;n<this.ELEMENTS;++n)this[n]*=t;return this.check()}divideScalar(t){return this.multiplyByScalar(1/t)}clampScalar(t,n){for(let r=0;r<this.ELEMENTS;++r)this[r]=Math.min(Math.max(this[r],t),n);return this.check()}get elements(){return this}};function yr(e,t){if(e.length!==t)return!1;for(let n=0;n<e.length;++n)if(!Number.isFinite(e[n]))return!1;return!0}function Ft(e){if(!Number.isFinite(e))throw new Error(`Invalid number ${JSON.stringify(e)}`);return e}function _e(e,t,n=""){if(P.debug&&!yr(e,t))throw new Error(`math.gl: ${n} some fields set to invalid numbers'`);return e}var w=typeof Float32Array<"u"?Float32Array:Array;var di=Math.PI/180;function Or(){let e=new w(2);return w!=Float32Array&&(e[0]=0,e[1]=0),e}function kt(e,t,n){let r=t[0],o=t[1];return e[0]=n[0]*r+n[4]*o+n[12],e[1]=n[1]*r+n[5]*o+n[13],e}var _i=function(){let e=Or();return function(t,n,r,o,i,a){let s,c;for(n||(n=2),r||(r=0),o?c=Math.min(o*n+r,t.length):c=t.length,s=r;s<c;s+=n)e[0]=t[s],e[1]=t[s+1],i(e,e,a),t[s]=e[0],t[s+1]=e[1];return t}}();function Dt(e,t,n){let r=t[0],o=t[1],i=n[3]*r+n[7]*o||1;return e[0]=(n[0]*r+n[4]*o)/i,e[1]=(n[1]*r+n[5]*o)/i,e}function Ut(e,t,n){let r=t[0],o=t[1],i=t[2],a=n[3]*r+n[7]*o+n[11]*i||1;return e[0]=(n[0]*r+n[4]*o+n[8]*i)/a,e[1]=(n[1]*r+n[5]*o+n[9]*i)/a,e[2]=(n[2]*r+n[6]*o+n[10]*i)/a,e}function Tr(){let e=new w(3);return w!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0),e}function zt(e,t,n){let r=t[0],o=t[1],i=t[2],a=n[3]*r+n[7]*o+n[11]*i+n[15];return a=a||1,e[0]=(n[0]*r+n[4]*o+n[8]*i+n[12])/a,e[1]=(n[1]*r+n[5]*o+n[9]*i+n[13])/a,e[2]=(n[2]*r+n[6]*o+n[10]*i+n[14])/a,e}var Si=function(){let e=Tr();return function(t,n,r,o,i,a){let s,c;for(n||(n=3),r||(r=0),o?c=Math.min(o*n+r,t.length):c=t.length,s=r;s<c;s+=n)e[0]=t[s],e[1]=t[s+1],e[2]=t[s+2],i(e,e,a),t[s]=e[0],t[s+1]=e[1],t[s+2]=e[2];return t}}();var be=class extends de{toString(){let t="[";if(P.printRowMajor){t+="row-major:";for(let n=0;n<this.RANK;++n)for(let r=0;r<this.RANK;++r)t+=` ${this[r*this.RANK+n]}`}else{t+="column-major:";for(let n=0;n<this.ELEMENTS;++n)t+=` ${this[n]}`}return t+="]",t}getElementIndex(t,n){return n*this.RANK+t}getElement(t,n){return this[n*this.RANK+t]}setElement(t,n,r){return this[n*this.RANK+t]=Ft(r),this}getColumn(t,n=new Array(this.RANK).fill(-0)){let r=t*this.RANK;for(let o=0;o<this.RANK;++o)n[o]=this[r+o];return n}setColumn(t,n){let r=t*this.RANK;for(let o=0;o<this.RANK;++o)this[r+o]=n[o];return this}};function Fr(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}function Ht(e,t){if(e===t){let n=t[1],r=t[2],o=t[3],i=t[6],a=t[7],s=t[11];e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=n,e[6]=t[9],e[7]=t[13],e[8]=r,e[9]=i,e[11]=t[14],e[12]=o,e[13]=a,e[14]=s}else e[0]=t[0],e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=t[1],e[5]=t[5],e[6]=t[9],e[7]=t[13],e[8]=t[2],e[9]=t[6],e[10]=t[10],e[11]=t[14],e[12]=t[3],e[13]=t[7],e[14]=t[11],e[15]=t[15];return e}function Gt(e,t){let n=t[0],r=t[1],o=t[2],i=t[3],a=t[4],s=t[5],c=t[6],l=t[7],p=t[8],f=t[9],h=t[10],g=t[11],_=t[12],m=t[13],x=t[14],d=t[15],M=n*s-r*a,b=n*c-o*a,S=n*l-i*a,v=r*c-o*s,u=r*l-i*s,E=o*l-i*c,R=p*m-f*_,L=p*x-h*_,I=p*d-g*_,N=f*x-h*m,C=f*d-g*m,y=h*d-g*x,A=M*y-b*C+S*N+v*I-u*L+E*R;return A?(A=1/A,e[0]=(s*y-c*C+l*N)*A,e[1]=(o*C-r*y-i*N)*A,e[2]=(m*E-x*u+d*v)*A,e[3]=(h*u-f*E-g*v)*A,e[4]=(c*I-a*y-l*L)*A,e[5]=(n*y-o*I+i*L)*A,e[6]=(x*S-_*E-d*b)*A,e[7]=(p*E-h*S+g*b)*A,e[8]=(a*C-s*I+l*R)*A,e[9]=(r*I-n*C-i*R)*A,e[10]=(_*u-m*S+d*M)*A,e[11]=(f*S-p*u-g*M)*A,e[12]=(s*L-a*N-c*R)*A,e[13]=(n*N-r*L+o*R)*A,e[14]=(m*b-_*v-x*M)*A,e[15]=(p*v-f*b+h*M)*A,e):null}function Vt(e){let t=e[0],n=e[1],r=e[2],o=e[3],i=e[4],a=e[5],s=e[6],c=e[7],l=e[8],p=e[9],f=e[10],h=e[11],g=e[12],_=e[13],m=e[14],x=e[15],d=t*a-n*i,M=t*s-r*i,b=n*s-r*a,S=l*_-p*g,v=l*m-f*g,u=p*m-f*_,E=t*u-n*v+r*S,R=i*u-a*v+s*S,L=l*b-p*M+f*d,I=g*b-_*M+m*d;return c*E-o*R+x*L-h*I}function ze(e,t,n){let r=t[0],o=t[1],i=t[2],a=t[3],s=t[4],c=t[5],l=t[6],p=t[7],f=t[8],h=t[9],g=t[10],_=t[11],m=t[12],x=t[13],d=t[14],M=t[15],b=n[0],S=n[1],v=n[2],u=n[3];return e[0]=b*r+S*s+v*f+u*m,e[1]=b*o+S*c+v*h+u*x,e[2]=b*i+S*l+v*g+u*d,e[3]=b*a+S*p+v*_+u*M,b=n[4],S=n[5],v=n[6],u=n[7],e[4]=b*r+S*s+v*f+u*m,e[5]=b*o+S*c+v*h+u*x,e[6]=b*i+S*l+v*g+u*d,e[7]=b*a+S*p+v*_+u*M,b=n[8],S=n[9],v=n[10],u=n[11],e[8]=b*r+S*s+v*f+u*m,e[9]=b*o+S*c+v*h+u*x,e[10]=b*i+S*l+v*g+u*d,e[11]=b*a+S*p+v*_+u*M,b=n[12],S=n[13],v=n[14],u=n[15],e[12]=b*r+S*s+v*f+u*m,e[13]=b*o+S*c+v*h+u*x,e[14]=b*i+S*l+v*g+u*d,e[15]=b*a+S*p+v*_+u*M,e}function Wt(e,t,n){let r=n[0],o=n[1],i=n[2],a,s,c,l,p,f,h,g,_,m,x,d;return t===e?(e[12]=t[0]*r+t[4]*o+t[8]*i+t[12],e[13]=t[1]*r+t[5]*o+t[9]*i+t[13],e[14]=t[2]*r+t[6]*o+t[10]*i+t[14],e[15]=t[3]*r+t[7]*o+t[11]*i+t[15]):(a=t[0],s=t[1],c=t[2],l=t[3],p=t[4],f=t[5],h=t[6],g=t[7],_=t[8],m=t[9],x=t[10],d=t[11],e[0]=a,e[1]=s,e[2]=c,e[3]=l,e[4]=p,e[5]=f,e[6]=h,e[7]=g,e[8]=_,e[9]=m,e[10]=x,e[11]=d,e[12]=a*r+p*o+_*i+t[12],e[13]=s*r+f*o+m*i+t[13],e[14]=c*r+h*o+x*i+t[14],e[15]=l*r+g*o+d*i+t[15]),e}function jt(e,t,n){let r=n[0],o=n[1],i=n[2];return e[0]=t[0]*r,e[1]=t[1]*r,e[2]=t[2]*r,e[3]=t[3]*r,e[4]=t[4]*o,e[5]=t[5]*o,e[6]=t[6]*o,e[7]=t[7]*o,e[8]=t[8]*i,e[9]=t[9]*i,e[10]=t[10]*i,e[11]=t[11]*i,e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e}function $t(e,t,n,r){let o=r[0],i=r[1],a=r[2],s=Math.sqrt(o*o+i*i+a*a),c,l,p,f,h,g,_,m,x,d,M,b,S,v,u,E,R,L,I,N,C,y,A,W;return s<1e-6?null:(s=1/s,o*=s,i*=s,a*=s,l=Math.sin(n),c=Math.cos(n),p=1-c,f=t[0],h=t[1],g=t[2],_=t[3],m=t[4],x=t[5],d=t[6],M=t[7],b=t[8],S=t[9],v=t[10],u=t[11],E=o*o*p+c,R=i*o*p+a*l,L=a*o*p-i*l,I=o*i*p-a*l,N=i*i*p+c,C=a*i*p+o*l,y=o*a*p+i*l,A=i*a*p-o*l,W=a*a*p+c,e[0]=f*E+m*R+b*L,e[1]=h*E+x*R+S*L,e[2]=g*E+d*R+v*L,e[3]=_*E+M*R+u*L,e[4]=f*I+m*N+b*C,e[5]=h*I+x*N+S*C,e[6]=g*I+d*N+v*C,e[7]=_*I+M*N+u*C,e[8]=f*y+m*A+b*W,e[9]=h*y+x*A+S*W,e[10]=g*y+d*A+v*W,e[11]=_*y+M*A+u*W,t!==e&&(e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e)}function qt(e,t,n){let r=Math.sin(n),o=Math.cos(n),i=t[4],a=t[5],s=t[6],c=t[7],l=t[8],p=t[9],f=t[10],h=t[11];return t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[4]=i*o+l*r,e[5]=a*o+p*r,e[6]=s*o+f*r,e[7]=c*o+h*r,e[8]=l*o-i*r,e[9]=p*o-a*r,e[10]=f*o-s*r,e[11]=h*o-c*r,e}function Kt(e,t,n){let r=Math.sin(n),o=Math.cos(n),i=t[0],a=t[1],s=t[2],c=t[3],l=t[8],p=t[9],f=t[10],h=t[11];return t!==e&&(e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=i*o-l*r,e[1]=a*o-p*r,e[2]=s*o-f*r,e[3]=c*o-h*r,e[8]=i*r+l*o,e[9]=a*r+p*o,e[10]=s*r+f*o,e[11]=c*r+h*o,e}function Yt(e,t,n){let r=Math.sin(n),o=Math.cos(n),i=t[0],a=t[1],s=t[2],c=t[3],l=t[4],p=t[5],f=t[6],h=t[7];return t!==e&&(e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=i*o+l*r,e[1]=a*o+p*r,e[2]=s*o+f*r,e[3]=c*o+h*r,e[4]=l*o-i*r,e[5]=p*o-a*r,e[6]=f*o-s*r,e[7]=h*o-c*r,e}function Xt(e,t){let n=t[0],r=t[1],o=t[2],i=t[3],a=n+n,s=r+r,c=o+o,l=n*a,p=r*a,f=r*s,h=o*a,g=o*s,_=o*c,m=i*a,x=i*s,d=i*c;return e[0]=1-f-_,e[1]=p+d,e[2]=h-x,e[3]=0,e[4]=p-d,e[5]=1-l-_,e[6]=g+m,e[7]=0,e[8]=h+x,e[9]=g-m,e[10]=1-l-f,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}function Zt(e,t,n,r,o,i,a){let s=1/(n-t),c=1/(o-r),l=1/(i-a);return e[0]=i*2*s,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=i*2*c,e[6]=0,e[7]=0,e[8]=(n+t)*s,e[9]=(o+r)*c,e[10]=(a+i)*l,e[11]=-1,e[12]=0,e[13]=0,e[14]=a*i*2*l,e[15]=0,e}function wr(e,t,n,r,o){let i=1/Math.tan(t/2);if(e[0]=i/n,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=i,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[11]=-1,e[12]=0,e[13]=0,e[15]=0,o!=null&&o!==1/0){let a=1/(r-o);e[10]=(o+r)*a,e[14]=2*o*r*a}else e[10]=-1,e[14]=-2*r;return e}var Jt=wr;function Br(e,t,n,r,o,i,a){let s=1/(t-n),c=1/(r-o),l=1/(i-a);return e[0]=-2*s,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=-2*c,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=2*l,e[11]=0,e[12]=(t+n)*s,e[13]=(o+r)*c,e[14]=(a+i)*l,e[15]=1,e}var Qt=Br;function en(e,t,n,r){let o,i,a,s,c,l,p,f,h,g,_=t[0],m=t[1],x=t[2],d=r[0],M=r[1],b=r[2],S=n[0],v=n[1],u=n[2];return Math.abs(_-S)<1e-6&&Math.abs(m-v)<1e-6&&Math.abs(x-u)<1e-6?Fr(e):(f=_-S,h=m-v,g=x-u,o=1/Math.sqrt(f*f+h*h+g*g),f*=o,h*=o,g*=o,i=M*g-b*h,a=b*f-d*g,s=d*h-M*f,o=Math.sqrt(i*i+a*a+s*s),o?(o=1/o,i*=o,a*=o,s*=o):(i=0,a=0,s=0),c=h*s-g*a,l=g*i-f*s,p=f*a-h*i,o=Math.sqrt(c*c+l*l+p*p),o?(o=1/o,c*=o,l*=o,p*=o):(c=0,l=0,p=0),e[0]=i,e[1]=c,e[2]=f,e[3]=0,e[4]=a,e[5]=l,e[6]=h,e[7]=0,e[8]=s,e[9]=p,e[10]=g,e[11]=0,e[12]=-(i*_+a*m+s*x),e[13]=-(c*_+l*m+p*x),e[14]=-(f*_+h*m+g*x),e[15]=1,e)}function kr(){let e=new w(4);return w!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0,e[3]=0),e}function tn(e,t,n){let r=t[0],o=t[1],i=t[2],a=t[3];return e[0]=n[0]*r+n[4]*o+n[8]*i+n[12]*a,e[1]=n[1]*r+n[5]*o+n[9]*i+n[13]*a,e[2]=n[2]*r+n[6]*o+n[10]*i+n[14]*a,e[3]=n[3]*r+n[7]*o+n[11]*i+n[15]*a,e}var Ii=function(){let e=kr();return function(t,n,r,o,i,a){let s,c;for(n||(n=4),r||(r=0),o?c=Math.min(o*n+r,t.length):c=t.length,s=r;s<c;s+=n)e[0]=t[s],e[1]=t[s+1],e[2]=t[s+2],e[3]=t[s+3],i(e,e,a),t[s]=e[0],t[s+1]=e[1],t[s+2]=e[2],t[s+3]=e[3];return t}}();var Ve;(function(e){e[e.COL0ROW0=0]="COL0ROW0",e[e.COL0ROW1=1]="COL0ROW1",e[e.COL0ROW2=2]="COL0ROW2",e[e.COL0ROW3=3]="COL0ROW3",e[e.COL1ROW0=4]="COL1ROW0",e[e.COL1ROW1=5]="COL1ROW1",e[e.COL1ROW2=6]="COL1ROW2",e[e.COL1ROW3=7]="COL1ROW3",e[e.COL2ROW0=8]="COL2ROW0",e[e.COL2ROW1=9]="COL2ROW1",e[e.COL2ROW2=10]="COL2ROW2",e[e.COL2ROW3=11]="COL2ROW3",e[e.COL3ROW0=12]="COL3ROW0",e[e.COL3ROW1=13]="COL3ROW1",e[e.COL3ROW2=14]="COL3ROW2",e[e.COL3ROW3=15]="COL3ROW3"})(Ve||(Ve={}));var Dr=45*Math.PI/180,Ur=1,He=.1,Ge=500,zr=Object.freeze([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),B=class extends be{static get IDENTITY(){return Gr()}static get ZERO(){return Hr()}get ELEMENTS(){return 16}get RANK(){return 4}get INDICES(){return Ve}constructor(t){super(-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0),arguments.length===1&&Array.isArray(t)?this.copy(t):this.identity()}copy(t){return this[0]=t[0],this[1]=t[1],this[2]=t[2],this[3]=t[3],this[4]=t[4],this[5]=t[5],this[6]=t[6],this[7]=t[7],this[8]=t[8],this[9]=t[9],this[10]=t[10],this[11]=t[11],this[12]=t[12],this[13]=t[13],this[14]=t[14],this[15]=t[15],this.check()}set(t,n,r,o,i,a,s,c,l,p,f,h,g,_,m,x){return this[0]=t,this[1]=n,this[2]=r,this[3]=o,this[4]=i,this[5]=a,this[6]=s,this[7]=c,this[8]=l,this[9]=p,this[10]=f,this[11]=h,this[12]=g,this[13]=_,this[14]=m,this[15]=x,this.check()}setRowMajor(t,n,r,o,i,a,s,c,l,p,f,h,g,_,m,x){return this[0]=t,this[1]=i,this[2]=l,this[3]=g,this[4]=n,this[5]=a,this[6]=p,this[7]=_,this[8]=r,this[9]=s,this[10]=f,this[11]=m,this[12]=o,this[13]=c,this[14]=h,this[15]=x,this.check()}toRowMajor(t){return t[0]=this[0],t[1]=this[4],t[2]=this[8],t[3]=this[12],t[4]=this[1],t[5]=this[5],t[6]=this[9],t[7]=this[13],t[8]=this[2],t[9]=this[6],t[10]=this[10],t[11]=this[14],t[12]=this[3],t[13]=this[7],t[14]=this[11],t[15]=this[15],t}identity(){return this.copy(zr)}fromObject(t){return this.check()}fromQuaternion(t){return Xt(this,t),this.check()}frustum(t){let{left:n,right:r,bottom:o,top:i,near:a=He,far:s=Ge}=t;return s===1/0?Vr(this,n,r,o,i,a):Zt(this,n,r,o,i,a,s),this.check()}lookAt(t){let{eye:n,center:r=[0,0,0],up:o=[0,1,0]}=t;return en(this,n,r,o),this.check()}ortho(t){let{left:n,right:r,bottom:o,top:i,near:a=He,far:s=Ge}=t;return Qt(this,n,r,o,i,a,s),this.check()}orthographic(t){let{fovy:n=Dr,aspect:r=Ur,focalDistance:o=1,near:i=He,far:a=Ge}=t;nn(n);let s=n/2,c=o*Math.tan(s),l=c*r;return this.ortho({left:-l,right:l,bottom:-c,top:c,near:i,far:a})}perspective(t){let{fovy:n=45*Math.PI/180,aspect:r=1,near:o=.1,far:i=500}=t;return nn(n),Jt(this,n,r,o,i),this.check()}determinant(){return Vt(this)}getScale(t=[-0,-0,-0]){return t[0]=Math.sqrt(this[0]*this[0]+this[1]*this[1]+this[2]*this[2]),t[1]=Math.sqrt(this[4]*this[4]+this[5]*this[5]+this[6]*this[6]),t[2]=Math.sqrt(this[8]*this[8]+this[9]*this[9]+this[10]*this[10]),t}getTranslation(t=[-0,-0,-0]){return t[0]=this[12],t[1]=this[13],t[2]=this[14],t}getRotation(t,n){t=t||[-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0],n=n||[-0,-0,-0];let r=this.getScale(n),o=1/r[0],i=1/r[1],a=1/r[2];return t[0]=this[0]*o,t[1]=this[1]*i,t[2]=this[2]*a,t[3]=0,t[4]=this[4]*o,t[5]=this[5]*i,t[6]=this[6]*a,t[7]=0,t[8]=this[8]*o,t[9]=this[9]*i,t[10]=this[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}getRotationMatrix3(t,n){t=t||[-0,-0,-0,-0,-0,-0,-0,-0,-0],n=n||[-0,-0,-0];let r=this.getScale(n),o=1/r[0],i=1/r[1],a=1/r[2];return t[0]=this[0]*o,t[1]=this[1]*i,t[2]=this[2]*a,t[3]=this[4]*o,t[4]=this[5]*i,t[5]=this[6]*a,t[6]=this[8]*o,t[7]=this[9]*i,t[8]=this[10]*a,t}transpose(){return Ht(this,this),this.check()}invert(){return Gt(this,this),this.check()}multiplyLeft(t){return ze(this,t,this),this.check()}multiplyRight(t){return ze(this,this,t),this.check()}rotateX(t){return qt(this,this,t),this.check()}rotateY(t){return Kt(this,this,t),this.check()}rotateZ(t){return Yt(this,this,t),this.check()}rotateXYZ(t){return this.rotateX(t[0]).rotateY(t[1]).rotateZ(t[2])}rotateAxis(t,n){return $t(this,this,t,n),this.check()}scale(t){return jt(this,this,Array.isArray(t)?t:[t,t,t]),this.check()}translate(t){return Wt(this,this,t),this.check()}transform(t,n){return t.length===4?(n=tn(n||[-0,-0,-0,-0],t,this),_e(n,4),n):this.transformAsPoint(t,n)}transformAsPoint(t,n){let{length:r}=t,o;switch(r){case 2:o=kt(n||[-0,-0],t,this);break;case 3:o=zt(n||[-0,-0,-0],t,this);break;default:throw new Error("Illegal vector")}return _e(o,t.length),o}transformAsVector(t,n){let r;switch(t.length){case 2:r=Dt(n||[-0,-0],t,this);break;case 3:r=Ut(n||[-0,-0,-0],t,this);break;default:throw new Error("Illegal vector")}return _e(r,t.length),r}transformPoint(t,n){return this.transformAsPoint(t,n)}transformVector(t,n){return this.transformAsPoint(t,n)}transformDirection(t,n){return this.transformAsVector(t,n)}makeRotationX(t){return this.identity().rotateX(t)}makeTranslation(t,n,r){return this.identity().translate([t,n,r])}},ve,Se;function Hr(){return ve||(ve=new B([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),Object.freeze(ve)),ve}function Gr(){return Se||(Se=new B,Object.freeze(Se)),Se}function nn(e){if(e>Math.PI*2)throw Error("expected radians")}function Vr(e,t,n,r,o,i){let a=2*i/(n-t),s=2*i/(o-r),c=(n+t)/(n-t),l=(o+r)/(o-r),p=-1,f=-1,h=-2*i;return e[0]=a,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=s,e[6]=0,e[7]=0,e[8]=c,e[9]=l,e[10]=p,e[11]=f,e[12]=0,e[13]=0,e[14]=h,e[15]=0,e}var D=null,rn=new ArrayBuffer(4),on=new Float32Array(rn),an=new Uint32Array(rn);function sn(e){D||=ln(),e=De(e,-65504,65504),on[0]=e;let t=an[0],n=t>>23&511;return D.baseTable[n]+((t&8388607)>>D.shiftTable[n])}function cn(e){D||=ln();let t=e>>10;return an[0]=D.mantissaTable[D.offsetTable[t]+(e&1023)]+D.exponentTable[t],on[0]}function ln(){let e=new Uint32Array(512),t=new Uint32Array(512);for(let i=0;i<256;++i){let a=i-127;a<-27?(e[i]=0,e[i|256]=32768,t[i]=24,t[i|256]=24):a<-14?(e[i]=1024>>-a-14,e[i|256]=1024>>-a-14|32768,t[i]=-a-1,t[i|256]=-a-1):a<=15?(e[i]=a+15<<10,e[i|256]=a+15<<10|32768,t[i]=13,t[i|256]=13):a<128?(e[i]=31744,e[i|256]=64512,t[i]=24,t[i|256]=24):(e[i]=31744,e[i|256]=64512,t[i]=13,t[i|256]=13)}let n=new Uint32Array(2048),r=new Uint32Array(64),o=new Uint32Array(64);for(let i=1;i<1024;++i){let a=i<<13,s=0;for(;!(a&8388608);)a<<=1,s-=8388608;a&=-8388609,s+=947912704,n[i]=a|s}for(let i=1024;i<2048;++i)n[i]=939524096+(i-1024<<13);for(let i=1;i<31;++i)r[i]=i<<23;r[31]=1199570944,r[32]=2147483648;for(let i=33;i<63;++i)r[i]=2147483648+(i-32<<23);r[63]=3347054592;for(let i=1;i<64;++i)i!==32&&(o[i]=1024);return{baseTable:e,shiftTable:t,mantissaTable:n,exponentTable:r,offsetTable:o}}function V(e,t=[],n=0){let r=Math.fround(e),o=e-r;return t[n]=r,t[n+1]=o,t}function Q(e){return e-Math.fround(e)}function ee(e){let t=new Float32Array(32);for(let n=0;n<4;++n)for(let r=0;r<4;++r){let o=n*4+r;V(e[r*4+n],t,o*2)}return t}var Wr=`fn random(scale: vec3f, seed: f32) -> f32 {
99
105
  return fract(sin(dot(scale + vec3f(seed), vec3f(12.9898, 78.233, 151.7182))) * 43758.5453 + seed);
100
106
  }
101
- `,ni=`float random(vec3 scale, float seed) {
107
+ `,jr=`float random(vec3 scale, float seed) {
102
108
  /* use the fragment position for a different seed per-pixel */
103
109
  return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
104
110
  }
105
- `,Vt={name:"random",source:ti,fs:ni};var ii=`#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND
111
+ `,fn={name:"random",source:Wr,fs:jr};var $r=`#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND
106
112
 
107
113
  // All these functions are for substituting tan() function from Intel GPU only
108
114
  const float TWO_PI = 6.2831854820251465;
@@ -252,9 +258,10 @@ float tan_fp32(float a) {
252
258
  return tan(a);
253
259
  #endif
254
260
  }
255
- `,jt={name:"fp32",vs:ii};var qt=`
261
+ `,pn={name:"fp32",vs:$r};var We=`
256
262
  uniform fp64arithmeticUniforms {
257
263
  uniform float ONE;
264
+ uniform float SPLIT;
258
265
  } fp64;
259
266
 
260
267
  /*
@@ -264,6 +271,12 @@ The purpose of this workaround is to prevent shader compilers from
264
271
  optimizing away necessary arithmetic operations by swapping their sequences
265
272
  or transform the equation to some 'equivalent' form.
266
273
 
274
+ These helpers implement Dekker/Veltkamp-style error tracking. If the compiler
275
+ folds constants or reassociates the arithmetic, the high/low split can stop
276
+ tracking the rounding error correctly. That failure mode tends to look fine in
277
+ simple coordinate setup, but then breaks down inside iterative arithmetic such
278
+ as fp64 Mandelbrot loops.
279
+
267
280
  The method is to multiply an artifical variable, ONE, which will be known to
268
281
  the compiler to be 1 only at runtime. The whole expression is then represented
269
282
  as a polynomial with respective to ONE. In the coefficients of all terms, only one a
@@ -272,17 +285,23 @@ and one b should appear
272
285
  err = (a + b) * ONE^6 - a * ONE^5 - (a + b) * ONE^4 + a * ONE^3 - b - (a + b) * ONE^2 + a * ONE
273
286
  */
274
287
 
275
- // Divide float number to high and low floats to extend fraction bits
276
- vec2 split(float a) {
277
- const float SPLIT = 4097.0;
278
- float t = a * SPLIT;
288
+ float prevent_fp64_optimization(float value) {
279
289
  #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
280
- float a_hi = t * fp64.ONE - (t - a);
281
- float a_lo = a * fp64.ONE - a_hi;
290
+ return value + fp64.ONE * 0.0;
282
291
  #else
283
- float a_hi = t - (t - a);
284
- float a_lo = a - a_hi;
292
+ return value;
285
293
  #endif
294
+ }
295
+
296
+ // Divide float number to high and low floats to extend fraction bits
297
+ vec2 split(float a) {
298
+ // Keep SPLIT as a runtime uniform so the compiler cannot fold the Dekker
299
+ // split into a constant expression and reassociate the recovery steps.
300
+ float split = prevent_fp64_optimization(fp64.SPLIT);
301
+ float t = prevent_fp64_optimization(a * split);
302
+ float temp = t - a;
303
+ float a_hi = t - temp;
304
+ float a_lo = a - a_hi;
286
305
  return vec2(a_hi, a_lo);
287
306
  }
288
307
 
@@ -346,8 +365,26 @@ vec2 twoProd(float a, float b) {
346
365
  float prod = a * b;
347
366
  vec2 a_fp64 = split(a);
348
367
  vec2 b_fp64 = split(b);
349
- float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y +
350
- a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y;
368
+ // twoProd is especially sensitive because mul_fp64 and div_fp64 both depend
369
+ // on the split terms and cross terms staying in the original evaluation
370
+ // order. If the compiler folds or reassociates them, the low part tends to
371
+ // collapse to zero or NaN on some drivers.
372
+ float highProduct = prevent_fp64_optimization(a_fp64.x * b_fp64.x);
373
+ float crossProduct1 = prevent_fp64_optimization(a_fp64.x * b_fp64.y);
374
+ float crossProduct2 = prevent_fp64_optimization(a_fp64.y * b_fp64.x);
375
+ float lowProduct = prevent_fp64_optimization(a_fp64.y * b_fp64.y);
376
+ #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
377
+ float err1 = (highProduct - prod) * fp64.ONE;
378
+ float err2 = crossProduct1 * fp64.ONE * fp64.ONE;
379
+ float err3 = crossProduct2 * fp64.ONE * fp64.ONE * fp64.ONE;
380
+ float err4 = lowProduct * fp64.ONE * fp64.ONE * fp64.ONE * fp64.ONE;
381
+ #else
382
+ float err1 = highProduct - prod;
383
+ float err2 = crossProduct1;
384
+ float err3 = crossProduct2;
385
+ float err4 = lowProduct;
386
+ #endif
387
+ float err = ((err1 + err2) + err3) + err4;
351
388
  return vec2(prod, err);
352
389
  }
353
390
 
@@ -420,7 +457,213 @@ vec2 sqrt_fp64(vec2 a) {
420
457
  return sum_fp64(vec2(yn, 0.0), prod);
421
458
  #endif
422
459
  }
423
- `;var Wt=`const vec2 E_FP64 = vec2(2.7182817459106445e+00, 8.254840366817007e-08);
460
+ `;var hn=`struct Fp64ArithmeticUniforms {
461
+ ONE: f32,
462
+ SPLIT: f32,
463
+ };
464
+
465
+ @group(0) @binding(auto) var<uniform> fp64arithmetic : Fp64ArithmeticUniforms;
466
+
467
+ fn fp64_nan(seed: f32) -> f32 {
468
+ let nanBits = 0x7fc00000u | select(0u, 1u, seed < 0.0);
469
+ return bitcast<f32>(nanBits);
470
+ }
471
+
472
+ fn fp64_runtime_zero() -> f32 {
473
+ return fp64arithmetic.ONE * 0.0;
474
+ }
475
+
476
+ fn prevent_fp64_optimization(value: f32) -> f32 {
477
+ #ifdef LUMA_FP64_CODE_ELIMINATION_WORKAROUND
478
+ return value + fp64_runtime_zero();
479
+ #else
480
+ return value;
481
+ #endif
482
+ }
483
+
484
+ fn split(a: f32) -> vec2f {
485
+ let splitValue = prevent_fp64_optimization(fp64arithmetic.SPLIT + fp64_runtime_zero());
486
+ let t = prevent_fp64_optimization(a * splitValue);
487
+ let temp = prevent_fp64_optimization(t - a);
488
+ let aHi = prevent_fp64_optimization(t - temp);
489
+ let aLo = prevent_fp64_optimization(a - aHi);
490
+ return vec2f(aHi, aLo);
491
+ }
492
+
493
+ fn split2(a: vec2f) -> vec2f {
494
+ var b = split(a.x);
495
+ b.y = b.y + a.y;
496
+ return b;
497
+ }
498
+
499
+ fn quickTwoSum(a: f32, b: f32) -> vec2f {
500
+ #ifdef LUMA_FP64_CODE_ELIMINATION_WORKAROUND
501
+ let sum = prevent_fp64_optimization((a + b) * fp64arithmetic.ONE);
502
+ let err = prevent_fp64_optimization(b - (sum - a) * fp64arithmetic.ONE);
503
+ #else
504
+ let sum = prevent_fp64_optimization(a + b);
505
+ let err = prevent_fp64_optimization(b - (sum - a));
506
+ #endif
507
+ return vec2f(sum, err);
508
+ }
509
+
510
+ fn twoSum(a: f32, b: f32) -> vec2f {
511
+ let s = prevent_fp64_optimization(a + b);
512
+ #ifdef LUMA_FP64_CODE_ELIMINATION_WORKAROUND
513
+ let v = prevent_fp64_optimization((s * fp64arithmetic.ONE - a) * fp64arithmetic.ONE);
514
+ let err =
515
+ prevent_fp64_optimization((a - (s - v) * fp64arithmetic.ONE) *
516
+ fp64arithmetic.ONE *
517
+ fp64arithmetic.ONE *
518
+ fp64arithmetic.ONE) +
519
+ prevent_fp64_optimization(b - v);
520
+ #else
521
+ let v = prevent_fp64_optimization(s - a);
522
+ let err = prevent_fp64_optimization(a - (s - v)) + prevent_fp64_optimization(b - v);
523
+ #endif
524
+ return vec2f(s, err);
525
+ }
526
+
527
+ fn twoSub(a: f32, b: f32) -> vec2f {
528
+ let s = prevent_fp64_optimization(a - b);
529
+ #ifdef LUMA_FP64_CODE_ELIMINATION_WORKAROUND
530
+ let v = prevent_fp64_optimization((s * fp64arithmetic.ONE - a) * fp64arithmetic.ONE);
531
+ let err =
532
+ prevent_fp64_optimization((a - (s - v) * fp64arithmetic.ONE) *
533
+ fp64arithmetic.ONE *
534
+ fp64arithmetic.ONE *
535
+ fp64arithmetic.ONE) -
536
+ prevent_fp64_optimization(b + v);
537
+ #else
538
+ let v = prevent_fp64_optimization(s - a);
539
+ let err = prevent_fp64_optimization(a - (s - v)) - prevent_fp64_optimization(b + v);
540
+ #endif
541
+ return vec2f(s, err);
542
+ }
543
+
544
+ fn twoSqr(a: f32) -> vec2f {
545
+ let prod = prevent_fp64_optimization(a * a);
546
+ let aFp64 = split(a);
547
+ let highProduct = prevent_fp64_optimization(aFp64.x * aFp64.x);
548
+ let crossProduct = prevent_fp64_optimization(2.0 * aFp64.x * aFp64.y);
549
+ let lowProduct = prevent_fp64_optimization(aFp64.y * aFp64.y);
550
+ #ifdef LUMA_FP64_CODE_ELIMINATION_WORKAROUND
551
+ let err =
552
+ (prevent_fp64_optimization(highProduct - prod) * fp64arithmetic.ONE +
553
+ crossProduct * fp64arithmetic.ONE * fp64arithmetic.ONE) +
554
+ lowProduct * fp64arithmetic.ONE * fp64arithmetic.ONE * fp64arithmetic.ONE;
555
+ #else
556
+ let err = ((prevent_fp64_optimization(highProduct - prod) + crossProduct) + lowProduct);
557
+ #endif
558
+ return vec2f(prod, err);
559
+ }
560
+
561
+ fn twoProd(a: f32, b: f32) -> vec2f {
562
+ let prod = prevent_fp64_optimization(a * b);
563
+ let aFp64 = split(a);
564
+ let bFp64 = split(b);
565
+ let highProduct = prevent_fp64_optimization(aFp64.x * bFp64.x);
566
+ let crossProduct1 = prevent_fp64_optimization(aFp64.x * bFp64.y);
567
+ let crossProduct2 = prevent_fp64_optimization(aFp64.y * bFp64.x);
568
+ let lowProduct = prevent_fp64_optimization(aFp64.y * bFp64.y);
569
+ #ifdef LUMA_FP64_CODE_ELIMINATION_WORKAROUND
570
+ let err1 = (highProduct - prod) * fp64arithmetic.ONE;
571
+ let err2 = crossProduct1 * fp64arithmetic.ONE * fp64arithmetic.ONE;
572
+ let err3 = crossProduct2 * fp64arithmetic.ONE * fp64arithmetic.ONE * fp64arithmetic.ONE;
573
+ let err4 =
574
+ lowProduct *
575
+ fp64arithmetic.ONE *
576
+ fp64arithmetic.ONE *
577
+ fp64arithmetic.ONE *
578
+ fp64arithmetic.ONE;
579
+ #else
580
+ let err1 = highProduct - prod;
581
+ let err2 = crossProduct1;
582
+ let err3 = crossProduct2;
583
+ let err4 = lowProduct;
584
+ #endif
585
+ let err12InputA = prevent_fp64_optimization(err1);
586
+ let err12InputB = prevent_fp64_optimization(err2);
587
+ let err12 = prevent_fp64_optimization(err12InputA + err12InputB);
588
+ let err123InputA = prevent_fp64_optimization(err12);
589
+ let err123InputB = prevent_fp64_optimization(err3);
590
+ let err123 = prevent_fp64_optimization(err123InputA + err123InputB);
591
+ let err1234InputA = prevent_fp64_optimization(err123);
592
+ let err1234InputB = prevent_fp64_optimization(err4);
593
+ let err = prevent_fp64_optimization(err1234InputA + err1234InputB);
594
+ return vec2f(prod, err);
595
+ }
596
+
597
+ fn sum_fp64(a: vec2f, b: vec2f) -> vec2f {
598
+ var s = twoSum(a.x, b.x);
599
+ let t = twoSum(a.y, b.y);
600
+ s.y = prevent_fp64_optimization(s.y + t.x);
601
+ s = quickTwoSum(s.x, s.y);
602
+ s.y = prevent_fp64_optimization(s.y + t.y);
603
+ s = quickTwoSum(s.x, s.y);
604
+ return s;
605
+ }
606
+
607
+ fn sub_fp64(a: vec2f, b: vec2f) -> vec2f {
608
+ var s = twoSub(a.x, b.x);
609
+ let t = twoSub(a.y, b.y);
610
+ s.y = prevent_fp64_optimization(s.y + t.x);
611
+ s = quickTwoSum(s.x, s.y);
612
+ s.y = prevent_fp64_optimization(s.y + t.y);
613
+ s = quickTwoSum(s.x, s.y);
614
+ return s;
615
+ }
616
+
617
+ fn mul_fp64(a: vec2f, b: vec2f) -> vec2f {
618
+ var prod = twoProd(a.x, b.x);
619
+ let crossProduct1 = prevent_fp64_optimization(a.x * b.y);
620
+ prod.y = prevent_fp64_optimization(prod.y + crossProduct1);
621
+ #ifdef LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND
622
+ prod = split2(prod);
623
+ #endif
624
+ prod = quickTwoSum(prod.x, prod.y);
625
+ let crossProduct2 = prevent_fp64_optimization(a.y * b.x);
626
+ prod.y = prevent_fp64_optimization(prod.y + crossProduct2);
627
+ #ifdef LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND
628
+ prod = split2(prod);
629
+ #endif
630
+ prod = quickTwoSum(prod.x, prod.y);
631
+ return prod;
632
+ }
633
+
634
+ fn div_fp64(a: vec2f, b: vec2f) -> vec2f {
635
+ let xn = prevent_fp64_optimization(1.0 / b.x);
636
+ let yn = mul_fp64(a, vec2f(xn, fp64_runtime_zero()));
637
+ let diff = prevent_fp64_optimization(sub_fp64(a, mul_fp64(b, yn)).x);
638
+ let prod = twoProd(xn, diff);
639
+ return sum_fp64(yn, prod);
640
+ }
641
+
642
+ fn sqrt_fp64(a: vec2f) -> vec2f {
643
+ if (a.x == 0.0 && a.y == 0.0) {
644
+ return vec2f(0.0, 0.0);
645
+ }
646
+ if (a.x < 0.0) {
647
+ let nanValue = fp64_nan(a.x);
648
+ return vec2f(nanValue, nanValue);
649
+ }
650
+
651
+ let x = prevent_fp64_optimization(1.0 / sqrt(a.x));
652
+ let yn = prevent_fp64_optimization(a.x * x);
653
+ #ifdef LUMA_FP64_CODE_ELIMINATION_WORKAROUND
654
+ let ynSqr = twoSqr(yn) * fp64arithmetic.ONE;
655
+ #else
656
+ let ynSqr = twoSqr(yn);
657
+ #endif
658
+ let diff = prevent_fp64_optimization(sub_fp64(a, ynSqr).x);
659
+ let prod = twoProd(prevent_fp64_optimization(x * 0.5), diff);
660
+ #ifdef LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND
661
+ return sum_fp64(split(yn), prod);
662
+ #else
663
+ return sum_fp64(vec2f(yn, 0.0), prod);
664
+ #endif
665
+ }
666
+ `;var un=`const vec2 E_FP64 = vec2(2.7182817459106445e+00, 8.254840366817007e-08);
424
667
  const vec2 LOG2_FP64 = vec2(0.6931471824645996e+00, -1.9046542121259336e-09);
425
668
  const vec2 PI_FP64 = vec2(3.1415927410125732, -8.742278012618954e-8);
426
669
  const vec2 TWO_PI_FP64 = vec2(6.2831854820251465, -1.7484556025237907e-7);
@@ -1089,7 +1332,7 @@ void mat4_vec4_mul_fp64(vec2 b[16], vec2 a[4], out vec2 out_val[4]) {
1089
1332
  vec4_dot_fp64(a, tmp, out_val[i]);
1090
1333
  }
1091
1334
  }
1092
- `;var ri={ONE:1},Te={name:"fp64arithmetic",vs:qt,defaultUniforms:ri,uniformTypes:{ONE:"f32"},fp64ify:G,fp64LowPart:Z,fp64ifyMatrix4:J},$t={name:"fp64",vs:Wt,dependencies:[Te],fp64ify:G,fp64LowPart:Z,fp64ifyMatrix4:J};var oi=[0,1,1,1],si=`uniform pickingUniforms {
1335
+ `;var qr={ONE:1,SPLIT:4097},je={name:"fp64arithmetic",source:hn,fs:We,vs:We,defaultUniforms:qr,uniformTypes:{ONE:"f32",SPLIT:"f32"},fp64ify:V,fp64LowPart:Q,fp64ifyMatrix4:ee},gn={name:"fp64",vs:un,dependencies:[je],fp64ify:V,fp64LowPart:Q,fp64ifyMatrix4:ee};var Kr=[0,1,1,1],Yr=`uniform pickingUniforms {
1093
1336
  float isActive;
1094
1337
  float isAttribute;
1095
1338
  float isHighlightActive;
@@ -1160,7 +1403,7 @@ void picking_setPickingAttribute(vec3 value) {
1160
1403
  picking_vRGBcolor_Avalid.rgb = value;
1161
1404
  }
1162
1405
  }
1163
- `,ci=`uniform pickingUniforms {
1406
+ `,Xr=`uniform pickingUniforms {
1164
1407
  float isActive;
1165
1408
  float isAttribute;
1166
1409
  float isHighlightActive;
@@ -1216,12 +1459,12 @@ vec4 picking_filterColor(vec4 color) {
1216
1459
  vec4 highlightColor = picking_filterHighlightColor(color);
1217
1460
  return picking_filterPickingColor(highlightColor);
1218
1461
  }
1219
- `,Yt={props:{},uniforms:{},name:"picking",uniformTypes:{isActive:"f32",isAttribute:"f32",isHighlightActive:"f32",useFloatColors:"f32",highlightedObjectColor:"vec3<f32>",highlightColor:"vec4<f32>"},defaultUniforms:{isActive:!1,isAttribute:!1,isHighlightActive:!1,useFloatColors:!0,highlightedObjectColor:[0,0,0],highlightColor:oi},vs:si,fs:ci,getUniforms:ai};function ai(e={},t){let n={};if(e.highlightedObjectColor!==void 0)if(e.highlightedObjectColor===null)n.isHighlightActive=!1;else{n.isHighlightActive=!0;let i=e.highlightedObjectColor.slice(0,3);n.highlightedObjectColor=i}if(e.highlightColor){let i=Array.from(e.highlightColor,r=>r/255);Number.isFinite(i[3])||(i[3]=1),n.highlightColor=i}return e.isActive!==void 0&&(n.isActive=Boolean(e.isActive),n.isAttribute=Boolean(e.isAttribute)),e.useFloatColors!==void 0&&(n.useFloatColors=Boolean(e.useFloatColors)),n}var Q=20,li=`
1462
+ `,mn={props:{},uniforms:{},name:"picking",uniformTypes:{isActive:"f32",isAttribute:"f32",isHighlightActive:"f32",useFloatColors:"f32",highlightedObjectColor:"vec3<f32>",highlightColor:"vec4<f32>"},defaultUniforms:{isActive:!1,isAttribute:!1,isHighlightActive:!1,useFloatColors:!0,highlightedObjectColor:[0,0,0],highlightColor:Kr},vs:Yr,fs:Xr,getUniforms:Zr};function Zr(e={},t){let n={};if(e.highlightedObjectColor!==void 0)if(e.highlightedObjectColor===null)n.isHighlightActive=!1;else{n.isHighlightActive=!0;let r=e.highlightedObjectColor.slice(0,3);n.highlightedObjectColor=r}if(e.highlightColor){let r=Array.from(e.highlightColor,o=>o/255);Number.isFinite(r[3])||(r[3]=1),n.highlightColor=r}return e.isActive!==void 0&&(n.isActive=Boolean(e.isActive),n.isAttribute=Boolean(e.isAttribute)),e.useFloatColors!==void 0&&(n.useFloatColors=Boolean(e.useFloatColors)),n}var te=20,Jr=`
1220
1463
  struct skinUniforms {
1221
- jointMatrix: array<mat4x4<f32>, ${Q}>,
1464
+ jointMatrix: array<mat4x4<f32>, ${te}>,
1222
1465
  };
1223
1466
 
1224
- @binding(19) @group(0) var<uniform> skin: skinUniforms;
1467
+ @group(0) @binding(auto) var<uniform> skin: skinUniforms;
1225
1468
 
1226
1469
  fn getSkinMatrix(weights: vec4f, joints: vec4u) -> mat4x4<f32> {
1227
1470
  return (weights.x * skin.jointMatrix[joints.x])
@@ -1229,7 +1472,7 @@ fn getSkinMatrix(weights: vec4f, joints: vec4u) -> mat4x4<f32> {
1229
1472
  + (weights.z * skin.jointMatrix[joints.z])
1230
1473
  + (weights.w * skin.jointMatrix[joints.w]);
1231
1474
  }
1232
- `,fi=`
1475
+ `,Qr=`
1233
1476
  uniform skinUniforms {
1234
1477
  mat4 jointMatrix[SKIN_MAX_JOINTS];
1235
1478
  } skin;
@@ -1241,7 +1484,7 @@ mat4 getSkinMatrix(vec4 weights, uvec4 joints) {
1241
1484
  + (weights.w * skin.jointMatrix[joints.w]);
1242
1485
  }
1243
1486
 
1244
- `,pi="",Kt={props:{},uniforms:{},name:"skin",dependencies:[],source:li,vs:fi,fs:pi,defines:{SKIN_MAX_JOINTS:Q},getUniforms:(e={},t)=>{let{scenegraphsFromGLTF:n}=e;if(!n?.gltf?.skins?.[0])return{jointMatrix:[]};let{inverseBindMatrices:i,joints:r,skeleton:o}=n.gltf.skins[0],s=[],c=i.value.length/16;for(let f=0;f<c;f++){let p=i.value.subarray(f*16,f*16+16);s.push(new k(Array.from(p)))}let a=n.gltfNodeIndexToNodeMap.get(o),l={};a.preorderTraversal((f,{worldMatrix:p})=>{l[f.id]=p});let h=new Float32Array(Q*16);for(let f=0;f<Q;++f){let p=r[f];if(p===void 0)break;let m=l[n.gltfNodeIndexToNodeMap.get(p).id],x=s[f],_=new k().copy(m).multiplyRight(x),d=f*16;for(let g=0;g<16;g++)h[d+g]=_[g]}return{jointMatrix:h}},uniformTypes:{jointMatrix:"mat4x4<f32>"},uniformSizes:{jointMatrix:Q}};var Zt=Be(xe(),1);var Fe=`precision highp int;
1487
+ `,eo="",dn={props:{},uniforms:{},name:"skin",bindingLayout:[{name:"skin",group:0}],dependencies:[],source:Jr,vs:Qr,fs:eo,defines:{SKIN_MAX_JOINTS:te},getUniforms:(e={},t)=>{let{scenegraphsFromGLTF:n}=e;if(!n?.gltf?.skins?.[0])return{jointMatrix:[]};let{inverseBindMatrices:r,joints:o,skeleton:i}=n.gltf.skins[0],a=[],s=r.value.length/16;for(let f=0;f<s;f++){let h=r.value.subarray(f*16,f*16+16);a.push(new B(Array.from(h)))}let c=n.gltfNodeIndexToNodeMap.get(i),l={};c.preorderTraversal((f,{worldMatrix:h})=>{l[f.id]=h});let p=new Float32Array(te*16);for(let f=0;f<te;++f){let h=o[f];if(h===void 0)break;let g=l[n.gltfNodeIndexToNodeMap.get(h).id],_=a[f],m=new B().copy(g).multiplyRight(_),x=f*16;for(let d=0;d<16;d++)p[x+d]=m[d]}return{jointMatrix:p}},uniformTypes:{jointMatrix:["mat4x4<f32>",te]}};var bn=Ze(Ie(),1);var $e=`precision highp int;
1245
1488
 
1246
1489
  // #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
1247
1490
  struct AmbientLight {
@@ -1254,77 +1497,51 @@ struct PointLight {
1254
1497
  vec3 attenuation; // 2nd order x:Constant-y:Linear-z:Exponential
1255
1498
  };
1256
1499
 
1500
+ struct SpotLight {
1501
+ vec3 color;
1502
+ vec3 position;
1503
+ vec3 direction;
1504
+ vec3 attenuation;
1505
+ vec2 coneCos;
1506
+ };
1507
+
1257
1508
  struct DirectionalLight {
1258
1509
  vec3 color;
1259
1510
  vec3 direction;
1260
1511
  };
1261
1512
 
1513
+ struct UniformLight {
1514
+ vec3 color;
1515
+ vec3 position;
1516
+ vec3 direction;
1517
+ vec3 attenuation;
1518
+ vec2 coneCos;
1519
+ };
1520
+
1262
1521
  uniform lightingUniforms {
1263
1522
  int enabled;
1264
- int lightType;
1265
-
1266
1523
  int directionalLightCount;
1267
1524
  int pointLightCount;
1268
-
1525
+ int spotLightCount;
1269
1526
  vec3 ambientColor;
1270
-
1271
- vec3 lightColor0;
1272
- vec3 lightPosition0;
1273
- vec3 lightDirection0;
1274
- vec3 lightAttenuation0;
1275
-
1276
- vec3 lightColor1;
1277
- vec3 lightPosition1;
1278
- vec3 lightDirection1;
1279
- vec3 lightAttenuation1;
1280
-
1281
- vec3 lightColor2;
1282
- vec3 lightPosition2;
1283
- vec3 lightDirection2;
1284
- vec3 lightAttenuation2;
1285
-
1286
- vec3 lightColor3;
1287
- vec3 lightPosition3;
1288
- vec3 lightDirection3;
1289
- vec3 lightAttenuation3;
1290
-
1291
- vec3 lightColor4;
1292
- vec3 lightPosition4;
1293
- vec3 lightDirection4;
1294
- vec3 lightAttenuation4;
1527
+ UniformLight lights[5];
1295
1528
  } lighting;
1296
1529
 
1297
1530
  PointLight lighting_getPointLight(int index) {
1298
- switch (index) {
1299
- case 0:
1300
- return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0);
1301
- case 1:
1302
- return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
1303
- case 2:
1304
- return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
1305
- case 3:
1306
- return PointLight(lighting.lightColor3, lighting.lightPosition3, lighting.lightAttenuation3);
1307
- case 4:
1308
- default:
1309
- return PointLight(lighting.lightColor4, lighting.lightPosition4, lighting.lightAttenuation4);
1310
- }
1531
+ UniformLight light = lighting.lights[index];
1532
+ return PointLight(light.color, light.position, light.attenuation);
1533
+ }
1534
+
1535
+ SpotLight lighting_getSpotLight(int index) {
1536
+ UniformLight light = lighting.lights[lighting.pointLightCount + index];
1537
+ return SpotLight(light.color, light.position, light.direction, light.attenuation, light.coneCos);
1311
1538
  }
1312
1539
 
1313
1540
  DirectionalLight lighting_getDirectionalLight(int index) {
1314
- switch (index) {
1315
- case 0:
1316
- return DirectionalLight(lighting.lightColor0, lighting.lightDirection0);
1317
- case 1:
1318
- return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
1319
- case 2:
1320
- return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
1321
- case 3:
1322
- return DirectionalLight(lighting.lightColor3, lighting.lightDirection3);
1323
- case 4:
1324
- default:
1325
- return DirectionalLight(lighting.lightColor4, lighting.lightDirection4);
1326
- }
1327
- }
1541
+ UniformLight light =
1542
+ lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];
1543
+ return DirectionalLight(light.color, light.direction);
1544
+ }
1328
1545
 
1329
1546
  float getPointLightAttenuation(PointLight pointLight, float distance) {
1330
1547
  return pointLight.attenuation.x
@@ -1332,8 +1549,22 @@ float getPointLightAttenuation(PointLight pointLight, float distance) {
1332
1549
  + pointLight.attenuation.z * distance * distance;
1333
1550
  }
1334
1551
 
1552
+ float getSpotLightAttenuation(SpotLight spotLight, vec3 positionWorldspace) {
1553
+ vec3 light_direction = normalize(positionWorldspace - spotLight.position);
1554
+ float coneFactor = smoothstep(
1555
+ spotLight.coneCos.y,
1556
+ spotLight.coneCos.x,
1557
+ dot(normalize(spotLight.direction), light_direction)
1558
+ );
1559
+ float distanceAttenuation = getPointLightAttenuation(
1560
+ PointLight(spotLight.color, spotLight.position, spotLight.attenuation),
1561
+ distance(spotLight.position, positionWorldspace)
1562
+ );
1563
+ return distanceAttenuation / max(coneFactor, 0.0001);
1564
+ }
1565
+
1335
1566
  // #endif
1336
- `;var Xt=`// #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
1567
+ `;var _n=`// #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
1337
1568
  const MAX_LIGHTS: i32 = 5;
1338
1569
 
1339
1570
  struct AmbientLight {
@@ -1346,95 +1577,86 @@ struct PointLight {
1346
1577
  attenuation: vec3<f32>, // 2nd order x:Constant-y:Linear-z:Exponential
1347
1578
  };
1348
1579
 
1580
+ struct SpotLight {
1581
+ color: vec3<f32>,
1582
+ position: vec3<f32>,
1583
+ direction: vec3<f32>,
1584
+ attenuation: vec3<f32>,
1585
+ coneCos: vec2<f32>,
1586
+ };
1587
+
1349
1588
  struct DirectionalLight {
1350
1589
  color: vec3<f32>,
1351
1590
  direction: vec3<f32>,
1352
1591
  };
1353
1592
 
1593
+ struct UniformLight {
1594
+ color: vec3<f32>,
1595
+ position: vec3<f32>,
1596
+ direction: vec3<f32>,
1597
+ attenuation: vec3<f32>,
1598
+ coneCos: vec2<f32>,
1599
+ };
1600
+
1354
1601
  struct lightingUniforms {
1355
1602
  enabled: i32,
1356
- lightType: i32,
1357
-
1358
1603
  directionalLightCount: i32,
1359
1604
  pointLightCount: i32,
1360
-
1605
+ spotLightCount: i32,
1361
1606
  ambientColor: vec3<f32>,
1362
-
1363
- lightColor0: vec3<f32>,
1364
- lightPosition0: vec3<f32>,
1365
- lightDirection0: vec3<f32>,
1366
- lightAttenuation0: vec3<f32>,
1367
-
1368
- lightColor1: vec3<f32>,
1369
- lightPosition1: vec3<f32>,
1370
- lightDirection1: vec3<f32>,
1371
- lightAttenuation1: vec3<f32>,
1372
-
1373
- lightColor2: vec3<f32>,
1374
- lightPosition2: vec3<f32>,
1375
- lightDirection2: vec3<f32>,
1376
- lightAttenuation2: vec3<f32>,
1377
-
1378
- lightColor3: vec3<f32>,
1379
- lightPosition3: vec3<f32>,
1380
- lightDirection3: vec3<f32>,
1381
- lightAttenuation3: vec3<f32>,
1382
-
1383
- lightColor4: vec3<f32>,
1384
- lightPosition4: vec3<f32>,
1385
- lightDirection4: vec3<f32>,
1386
- lightAttenuation4: vec3<f32>,
1607
+ lights: array<UniformLight, 5>,
1387
1608
  };
1388
1609
 
1389
- // Binding 0:1 is reserved for lighting (Note: could go into separate bind group as it is stable across draw calls)
1390
- @binding(1) @group(0) var<uniform> lighting : lightingUniforms;
1610
+ @group(2) @binding(auto) var<uniform> lighting : lightingUniforms;
1391
1611
 
1392
1612
  fn lighting_getPointLight(index: i32) -> PointLight {
1393
- switch (index) {
1394
- case 0: {
1395
- return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0);
1396
- }
1397
- case 1: {
1398
- return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
1399
- }
1400
- case 2: {
1401
- return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
1402
- }
1403
- case 3: {
1404
- return PointLight(lighting.lightColor3, lighting.lightPosition3, lighting.lightAttenuation3);
1405
- }
1406
- case 4, default: {
1407
- return PointLight(lighting.lightColor4, lighting.lightPosition4, lighting.lightAttenuation4);
1408
- }
1409
- }
1613
+ let light = lighting.lights[index];
1614
+ return PointLight(light.color, light.position, light.attenuation);
1615
+ }
1616
+
1617
+ fn lighting_getSpotLight(index: i32) -> SpotLight {
1618
+ let light = lighting.lights[lighting.pointLightCount + index];
1619
+ return SpotLight(light.color, light.position, light.direction, light.attenuation, light.coneCos);
1410
1620
  }
1411
1621
 
1412
1622
  fn lighting_getDirectionalLight(index: i32) -> DirectionalLight {
1413
- switch (index) {
1414
- case 0: {
1415
- return DirectionalLight(lighting.lightColor0, lighting.lightDirection0);
1416
- }
1417
- case 1: {
1418
- return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
1419
- }
1420
- case 2: {
1421
- return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
1422
- }
1423
- case 3: {
1424
- return DirectionalLight(lighting.lightColor3, lighting.lightDirection3);
1425
- }
1426
- case 4, default: {
1427
- return DirectionalLight(lighting.lightColor4, lighting.lightDirection4);
1428
- }
1429
- }
1430
- }
1623
+ let light = lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];
1624
+ return DirectionalLight(light.color, light.direction);
1625
+ }
1431
1626
 
1432
1627
  fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
1433
1628
  return pointLight.attenuation.x
1434
1629
  + pointLight.attenuation.y * distance
1435
1630
  + pointLight.attenuation.z * distance * distance;
1436
1631
  }
1437
- `;var _e=5,hi=255,ee;(function(e){e[e.POINT=0]="POINT",e[e.DIRECTIONAL=1]="DIRECTIONAL"})(ee||(ee={}));var y={props:{},uniforms:{},name:"lighting",defines:{},uniformTypes:{enabled:"i32",lightType:"i32",directionalLightCount:"i32",pointLightCount:"i32",ambientColor:"vec3<f32>",lightColor0:"vec3<f32>",lightPosition0:"vec3<f32>",lightDirection0:"vec3<f32>",lightAttenuation0:"vec3<f32>",lightColor1:"vec3<f32>",lightPosition1:"vec3<f32>",lightDirection1:"vec3<f32>",lightAttenuation1:"vec3<f32>",lightColor2:"vec3<f32>",lightPosition2:"vec3<f32>",lightDirection2:"vec3<f32>",lightAttenuation2:"vec3<f32>",lightColor3:"vec3<f32>",lightPosition3:"vec3<f32>",lightDirection3:"vec3<f32>",lightAttenuation3:"vec3<f32>",lightColor4:"vec3<f32>",lightPosition4:"vec3<f32>",lightDirection4:"vec3<f32>",lightAttenuation4:"vec3<f32>"},defaultUniforms:{enabled:1,lightType:ee.POINT,directionalLightCount:0,pointLightCount:0,ambientColor:[.1,.1,.1],lightColor0:[1,1,1],lightPosition0:[1,1,2],lightDirection0:[1,1,1],lightAttenuation0:[1,0,0],lightColor1:[1,1,1],lightPosition1:[1,1,2],lightDirection1:[1,1,1],lightAttenuation1:[1,0,0],lightColor2:[1,1,1],lightPosition2:[1,1,2],lightDirection2:[1,1,1],lightAttenuation2:[1,0,0],lightColor3:[1,1,1],lightPosition3:[1,1,2],lightDirection3:[1,1,1],lightAttenuation3:[1,0,0],lightColor4:[1,1,1],lightPosition4:[1,1,2],lightDirection4:[1,1,1],lightAttenuation4:[1,0,0]},source:Xt,vs:Fe,fs:Fe,getUniforms:gi};function gi(e,t={}){if(e=e&&{...e},!e)return{...y.defaultUniforms};e.lights&&(e={...e,..._i(e.lights),lights:void 0});let{ambientLight:n,pointLights:i,directionalLights:r}=e||{};if(!(n||i&&i.length>0||r&&r.length>0))return{...y.defaultUniforms,enabled:0};let s={...y.defaultUniforms,...t,...mi({ambientLight:n,pointLights:i,directionalLights:r})};return e.enabled!==void 0&&(s.enabled=e.enabled?1:0),s}function mi({ambientLight:e,pointLights:t=[],directionalLights:n=[]}){let i={};i.ambientColor=we(e);let r=0,o=0,s=0;for(let c of t){if(r>=_e)break;i.lightType=ee.POINT;let a=r;i[`lightColor${a}`]=we(c),i[`lightPosition${a}`]=c.position,i[`lightAttenuation${a}`]=c.attenuation||[1,0,0],r++,o++}for(let c of n){if(r>=_e)break;i.lightType=ee.DIRECTIONAL;let a=r;i[`lightColor${a}`]=we(c),i[`lightDirection${a}`]=c.direction,r++,s++}return t.length+n.length>_e&&Zt.log.warn(`MAX_LIGHTS exceeded, truncating to ${_e}`)(),i.directionalLightCount=s,i.pointLightCount=o,i}function _i(e){let t={pointLights:[],directionalLights:[]};for(let n of e||[])switch(n.type){case"ambient":t.ambientLight=n;break;case"directional":t.directionalLights?.push(n);break;case"point":t.pointLights?.push(n);break;default:}return t}function we(e={}){let{color:t=[0,0,0],intensity:n=1}=e;return t.map(i=>i*n/hi)}var ui=`
1632
+
1633
+ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>) -> f32 {
1634
+ let lightDirection = normalize(positionWorldspace - spotLight.position);
1635
+ let coneFactor = smoothstep(
1636
+ spotLight.coneCos.y,
1637
+ spotLight.coneCos.x,
1638
+ dot(normalize(spotLight.direction), lightDirection)
1639
+ );
1640
+ let distanceAttenuation = getPointLightAttenuation(
1641
+ PointLight(spotLight.color, spotLight.position, spotLight.attenuation),
1642
+ distance(spotLight.position, positionWorldspace)
1643
+ );
1644
+ return distanceAttenuation / max(coneFactor, 0.0001);
1645
+ }
1646
+ `;var U=5,to=255,no={color:"vec3<f32>",position:"vec3<f32>",direction:"vec3<f32>",attenuation:"vec3<f32>",coneCos:"vec2<f32>"},F={props:{},uniforms:{},name:"lighting",defines:{},uniformTypes:{enabled:"i32",directionalLightCount:"i32",pointLightCount:"i32",spotLightCount:"i32",ambientColor:"vec3<f32>",lights:[no,U]},defaultUniforms:Me(),bindingLayout:[{name:"lighting",group:2}],firstBindingSlot:0,source:_n,vs:$e,fs:$e,getUniforms:ro};function ro(e,t={}){if(e=e&&{...e},!e)return Me();e.lights&&(e={...e,...io(e.lights),lights:void 0});let{ambientLight:n,pointLights:r,spotLights:o,directionalLights:i}=e||{};if(!(n||r&&r.length>0||o&&o.length>0||i&&i.length>0))return{...Me(),enabled:0};let s={...Me(),...oo({ambientLight:n,pointLights:r,spotLights:o,directionalLights:i})};return e.enabled!==void 0&&(s.enabled=e.enabled?1:0),s}function oo({ambientLight:e,pointLights:t=[],spotLights:n=[],directionalLights:r=[]}){let o=vn(),i=0,a=0,s=0,c=0;for(let l of t){if(i>=U)break;o[i]={...o[i],color:xe(l),position:l.position,attenuation:l.attenuation||[1,0,0]},i++,a++}for(let l of n){if(i>=U)break;o[i]={...o[i],color:xe(l),position:l.position,direction:l.direction,attenuation:l.attenuation||[1,0,0],coneCos:so(l)},i++,s++}for(let l of r){if(i>=U)break;o[i]={...o[i],color:xe(l),direction:l.direction},i++,c++}return t.length+n.length+r.length>U&&bn.log.warn(`MAX_LIGHTS exceeded, truncating to ${U}`)(),{ambientColor:xe(e),directionalLightCount:c,pointLightCount:a,spotLightCount:s,lights:o}}function io(e){let t={pointLights:[],spotLights:[],directionalLights:[]};for(let n of e||[])switch(n.type){case"ambient":t.ambientLight=n;break;case"directional":t.directionalLights?.push(n);break;case"point":t.pointLights?.push(n);break;case"spot":t.spotLights?.push(n);break;default:}return t}function xe(e={}){let{color:t=[0,0,0],intensity:n=1}=e;return t.map(r=>r*n/to)}function Me(){return{enabled:1,directionalLightCount:0,pointLightCount:0,spotLightCount:0,ambientColor:[.1,.1,.1],lights:vn()}}function vn(){return Array.from({length:U},()=>ao())}function ao(){return{color:[1,1,1],position:[1,1,2],direction:[1,1,1],attenuation:[1,0,0],coneCos:[1,0]}}function so(e){let t=e.innerConeAngle??0,n=e.outerConeAngle??Math.PI/4;return[Math.cos(t),Math.cos(n)]}var co=`#ifdef USE_IBL
1647
+ @group(2) @binding(auto) var pbr_diffuseEnvSampler: texture_cube<f32>;
1648
+ @group(2) @binding(auto) var pbr_diffuseEnvSamplerSampler: sampler;
1649
+ @group(2) @binding(auto) var pbr_specularEnvSampler: texture_cube<f32>;
1650
+ @group(2) @binding(auto) var pbr_specularEnvSamplerSampler: sampler;
1651
+ @group(2) @binding(auto) var pbr_brdfLUT: texture_2d<f32>;
1652
+ @group(2) @binding(auto) var pbr_brdfLUTSampler: sampler;
1653
+ #endif
1654
+ `,Sn=`#ifdef USE_IBL
1655
+ uniform samplerCube pbr_diffuseEnvSampler;
1656
+ uniform samplerCube pbr_specularEnvSampler;
1657
+ uniform sampler2D pbr_brdfLUT;
1658
+ #endif
1659
+ `,Le={name:"ibl",firstBindingSlot:32,bindingLayout:[{name:"pbr_diffuseEnvSampler",group:2},{name:"pbr_specularEnvSampler",group:2},{name:"pbr_brdfLUT",group:2}],source:co,vs:Sn,fs:Sn};var lo=`
1438
1660
  struct dirlightUniforms {
1439
1661
  lightDirection: vec3<f32>,
1440
1662
  };
@@ -1445,7 +1667,7 @@ struct DirlightInputs {
1445
1667
  normal: DirlightNormal,
1446
1668
  };
1447
1669
 
1448
- @binding(1) @group(0) var<uniform> dirlight : dirlightUniforms;
1670
+ @group(2) @binding(auto) var<uniform> dirlight : dirlightUniforms;
1449
1671
 
1450
1672
  // For vertex
1451
1673
  fn dirlight_setNormal(normal: vec3<f32>) -> DirlightNormal {
@@ -1460,12 +1682,12 @@ fn dirlight_filterColor(color: vec4<f32>, inputs: DirlightInputs) -> vec4<f32> {
1460
1682
  let d: f32 = abs(dot(inputs.normal, normalize(lightDirection)));
1461
1683
  return vec4<f32>(color.rgb * d, color.a);
1462
1684
  }
1463
- `,di=`out vec3 dirlight_vNormal;
1685
+ `,fo=`out vec3 dirlight_vNormal;
1464
1686
 
1465
1687
  void dirlight_setNormal(vec3 normal) {
1466
1688
  dirlight_vNormal = normalize(normal);
1467
1689
  }
1468
- `,vi=`uniform dirlightUniforms {
1690
+ `,po=`uniform dirlightUniforms {
1469
1691
  vec3 lightDirection;
1470
1692
  } dirlight;
1471
1693
 
@@ -1476,15 +1698,134 @@ vec4 dirlight_filterColor(vec4 color) {
1476
1698
  float d = abs(dot(dirlight_vNormal, normalize(dirlight.lightDirection)));
1477
1699
  return vec4(color.rgb * d, color.a);
1478
1700
  }
1479
- `,ke={props:{},uniforms:{},name:"dirlight",dependencies:[],source:ui,vs:di,fs:vi,uniformTypes:{lightDirection:"vec3<f32>"},defaultUniforms:{lightDirection:[1,1,2]},getUniforms:xi};function xi(e=ke.defaultUniforms){let t={};return e.lightDirection&&(t.lightDirection=e.lightDirection),t}var ue=`uniform phongMaterialUniforms {
1701
+ `,qe={props:{},uniforms:{},name:"dirlight",bindingLayout:[{name:"dirlight",group:2}],firstBindingSlot:16,dependencies:[],source:lo,vs:fo,fs:po,uniformTypes:{lightDirection:"vec3<f32>"},defaultUniforms:{lightDirection:[1,1,2]},getUniforms:ho};function ho(e=qe.defaultUniforms){let t={};return e.lightDirection&&(t.lightDirection=e.lightDirection),t}var xn=`struct lambertMaterialUniforms {
1702
+ unlit: u32,
1703
+ ambient: f32,
1704
+ diffuse: f32,
1705
+ };
1706
+
1707
+ @group(3) @binding(auto) var<uniform> lambertMaterial : lambertMaterialUniforms;
1708
+
1709
+ fn lighting_getLightColor(surfaceColor: vec3<f32>, light_direction: vec3<f32>, normal_worldspace: vec3<f32>, color: vec3<f32>) -> vec3<f32> {
1710
+ let lambertian: f32 = max(dot(light_direction, normal_worldspace), 0.0);
1711
+ return lambertian * lambertMaterial.diffuse * surfaceColor * color;
1712
+ }
1713
+
1714
+ fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32> {
1715
+ var lightColor: vec3<f32> = surfaceColor;
1716
+
1717
+ if (lambertMaterial.unlit != 0u) {
1718
+ return surfaceColor;
1719
+ }
1720
+
1721
+ if (lighting.enabled == 0) {
1722
+ return lightColor;
1723
+ }
1724
+
1725
+ lightColor = lambertMaterial.ambient * surfaceColor * lighting.ambientColor;
1726
+
1727
+ for (var i: i32 = 0; i < lighting.pointLightCount; i++) {
1728
+ let pointLight: PointLight = lighting_getPointLight(i);
1729
+ let light_position_worldspace: vec3<f32> = pointLight.position;
1730
+ let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
1731
+ let light_attenuation = getPointLightAttenuation(
1732
+ pointLight,
1733
+ distance(light_position_worldspace, position_worldspace)
1734
+ );
1735
+ lightColor += lighting_getLightColor(
1736
+ surfaceColor,
1737
+ light_direction,
1738
+ normal_worldspace,
1739
+ pointLight.color / light_attenuation
1740
+ );
1741
+ }
1742
+
1743
+ for (var i: i32 = 0; i < lighting.spotLightCount; i++) {
1744
+ let spotLight: SpotLight = lighting_getSpotLight(i);
1745
+ let light_position_worldspace: vec3<f32> = spotLight.position;
1746
+ let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
1747
+ let light_attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
1748
+ lightColor += lighting_getLightColor(
1749
+ surfaceColor,
1750
+ light_direction,
1751
+ normal_worldspace,
1752
+ spotLight.color / light_attenuation
1753
+ );
1754
+ }
1755
+
1756
+ for (var i: i32 = 0; i < lighting.directionalLightCount; i++) {
1757
+ let directionalLight: DirectionalLight = lighting_getDirectionalLight(i);
1758
+ lightColor += lighting_getLightColor(
1759
+ surfaceColor,
1760
+ -directionalLight.direction,
1761
+ normal_worldspace,
1762
+ directionalLight.color
1763
+ );
1764
+ }
1765
+
1766
+ return lightColor;
1767
+ }
1768
+ `;var Mn=`uniform lambertMaterialUniforms {
1769
+ uniform bool unlit;
1770
+ uniform float ambient;
1771
+ uniform float diffuse;
1772
+ } material;
1773
+ `,Ln=`uniform lambertMaterialUniforms {
1774
+ uniform bool unlit;
1775
+ uniform float ambient;
1776
+ uniform float diffuse;
1777
+ } material;
1778
+
1779
+ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 light_direction, vec3 normal_worldspace, vec3 color) {
1780
+ float lambertian = max(dot(light_direction, normal_worldspace), 0.0);
1781
+ return lambertian * material.diffuse * surfaceColor * color;
1782
+ }
1783
+
1784
+ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 position_worldspace, vec3 normal_worldspace) {
1785
+ vec3 lightColor = surfaceColor;
1786
+
1787
+ if (material.unlit) {
1788
+ return surfaceColor;
1789
+ }
1790
+
1791
+ if (lighting.enabled == 0) {
1792
+ return lightColor;
1793
+ }
1794
+
1795
+ lightColor = material.ambient * surfaceColor * lighting.ambientColor;
1796
+
1797
+ for (int i = 0; i < lighting.pointLightCount; i++) {
1798
+ PointLight pointLight = lighting_getPointLight(i);
1799
+ vec3 light_position_worldspace = pointLight.position;
1800
+ vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
1801
+ float light_attenuation = getPointLightAttenuation(pointLight, distance(light_position_worldspace, position_worldspace));
1802
+ lightColor += lighting_getLightColor(surfaceColor, light_direction, normal_worldspace, pointLight.color / light_attenuation);
1803
+ }
1804
+
1805
+ for (int i = 0; i < lighting.spotLightCount; i++) {
1806
+ SpotLight spotLight = lighting_getSpotLight(i);
1807
+ vec3 light_position_worldspace = spotLight.position;
1808
+ vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
1809
+ float light_attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
1810
+ lightColor += lighting_getLightColor(surfaceColor, light_direction, normal_worldspace, spotLight.color / light_attenuation);
1811
+ }
1812
+
1813
+ for (int i = 0; i < lighting.directionalLightCount; i++) {
1814
+ DirectionalLight directionalLight = lighting_getDirectionalLight(i);
1815
+ lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, normal_worldspace, directionalLight.color);
1816
+ }
1817
+
1818
+ return lightColor;
1819
+ }
1820
+ `;var Ke={name:"lambertMaterial",firstBindingSlot:0,bindingLayout:[{name:"lambertMaterial",group:3}],dependencies:[F],source:xn,vs:Mn,fs:Ln,defines:{LIGHTING_FRAGMENT:!0},uniformTypes:{unlit:"i32",ambient:"f32",diffuse:"f32"},defaultUniforms:{unlit:!1,ambient:.35,diffuse:.6},getUniforms(e){return{...Ke.defaultUniforms,...e}}};var Ae=`uniform phongMaterialUniforms {
1821
+ uniform bool unlit;
1480
1822
  uniform float ambient;
1481
1823
  uniform float diffuse;
1482
1824
  uniform float shininess;
1483
1825
  uniform vec3 specularColor;
1484
1826
  } material;
1485
- `,de=`#define MAX_LIGHTS 3
1486
-
1487
- uniform phongMaterialUniforms {
1827
+ `,Ee=`uniform phongMaterialUniforms {
1828
+ uniform bool unlit;
1488
1829
  uniform float ambient;
1489
1830
  uniform float diffuse;
1490
1831
  uniform float shininess;
@@ -1506,6 +1847,10 @@ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 light_direction, vec3 view_d
1506
1847
  vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 position_worldspace, vec3 normal_worldspace) {
1507
1848
  vec3 lightColor = surfaceColor;
1508
1849
 
1850
+ if (material.unlit) {
1851
+ return surfaceColor;
1852
+ }
1853
+
1509
1854
  if (lighting.enabled == 0) {
1510
1855
  return lightColor;
1511
1856
  }
@@ -1521,22 +1866,30 @@ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 positio
1521
1866
  lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color / light_attenuation);
1522
1867
  }
1523
1868
 
1524
- int totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount);
1525
- for (int i = lighting.pointLightCount; i < totalLights; i++) {
1869
+ for (int i = 0; i < lighting.spotLightCount; i++) {
1870
+ SpotLight spotLight = lighting_getSpotLight(i);
1871
+ vec3 light_position_worldspace = spotLight.position;
1872
+ vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
1873
+ float light_attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
1874
+ lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, spotLight.color / light_attenuation);
1875
+ }
1876
+
1877
+ for (int i = 0; i < lighting.directionalLightCount; i++) {
1526
1878
  DirectionalLight directionalLight = lighting_getDirectionalLight(i);
1527
1879
  lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
1528
1880
  }
1529
1881
 
1530
1882
  return lightColor;
1531
1883
  }
1532
- `;var ve=`struct phongMaterialUniforms {
1884
+ `;var Re=`struct phongMaterialUniforms {
1885
+ unlit: u32,
1533
1886
  ambient: f32,
1534
1887
  diffuse: f32,
1535
1888
  shininess: f32,
1536
1889
  specularColor: vec3<f32>,
1537
1890
  };
1538
1891
 
1539
- @binding(2) @group(0) var<uniform> phongMaterial : phongMaterialUniforms;
1892
+ @group(3) @binding(auto) var<uniform> phongMaterial : phongMaterialUniforms;
1540
1893
 
1541
1894
  fn lighting_getLightColor(surfaceColor: vec3<f32>, light_direction: vec3<f32>, view_direction: vec3<f32>, normal_worldspace: vec3<f32>, color: vec3<f32>) -> vec3<f32> {
1542
1895
  let halfway_direction: vec3<f32> = normalize(light_direction + view_direction);
@@ -1553,6 +1906,10 @@ fn lighting_getLightColor(surfaceColor: vec3<f32>, light_direction: vec3<f32>, v
1553
1906
  fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32> {
1554
1907
  var lightColor: vec3<f32> = surfaceColor;
1555
1908
 
1909
+ if (phongMaterial.unlit != 0u) {
1910
+ return surfaceColor;
1911
+ }
1912
+
1556
1913
  if (lighting.enabled == 0) {
1557
1914
  return lightColor;
1558
1915
  }
@@ -1577,8 +1934,21 @@ fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, p
1577
1934
  );
1578
1935
  }
1579
1936
 
1580
- let totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount);
1581
- for (var i: i32 = lighting.pointLightCount; i < totalLights; i++) {
1937
+ for (var i: i32 = 0; i < lighting.spotLightCount; i++) {
1938
+ let spotLight: SpotLight = lighting_getSpotLight(i);
1939
+ let light_position_worldspace: vec3<f32> = spotLight.position;
1940
+ let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
1941
+ let light_attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
1942
+ lightColor += lighting_getLightColor(
1943
+ surfaceColor,
1944
+ light_direction,
1945
+ view_direction,
1946
+ normal_worldspace,
1947
+ spotLight.color / light_attenuation
1948
+ );
1949
+ }
1950
+
1951
+ for (var i: i32 = 0; i < lighting.directionalLightCount; i++) {
1582
1952
  let directionalLight: DirectionalLight = lighting_getDirectionalLight(i);
1583
1953
  lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
1584
1954
  }
@@ -1610,15 +1980,28 @@ fn lighting_getSpecularLightColor(cameraPosition: vec3<f32>, position_worldspace
1610
1980
  );
1611
1981
  }
1612
1982
 
1613
- let totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount);
1614
- for (var i: i32 = lighting.pointLightCount; i < totalLights; i++) {
1983
+ for (var i: i32 = 0; i < lighting.spotLightCount; i++) {
1984
+ let spotLight: SpotLight = lighting_getSpotLight(i);
1985
+ let light_position_worldspace: vec3<f32> = spotLight.position;
1986
+ let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
1987
+ let light_attenuation = getSpotLightAttenuation(spotLight, position_worldspace);
1988
+ lightColor += lighting_getLightColor(
1989
+ surfaceColor,
1990
+ light_direction,
1991
+ view_direction,
1992
+ normal_worldspace,
1993
+ spotLight.color / light_attenuation
1994
+ );
1995
+ }
1996
+
1997
+ for (var i: i32 = 0; i < lighting.directionalLightCount; i++) {
1615
1998
  let directionalLight: DirectionalLight = lighting_getDirectionalLight(i);
1616
1999
  lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
1617
2000
  }
1618
2001
  }
1619
2002
  return lightColor;
1620
2003
  }
1621
- `;var De={props:{},name:"gouraudMaterial",vs:de.replace("phongMaterial","gouraudMaterial"),fs:ue.replace("phongMaterial","gouraudMaterial"),source:ve.replaceAll("phongMaterial","gouraudMaterial"),defines:{LIGHTING_VERTEX:!0},dependencies:[y],uniformTypes:{ambient:"f32",diffuse:"f32",shininess:"f32",specularColor:"vec3<f32>"},defaultUniforms:{ambient:.35,diffuse:.6,shininess:32,specularColor:[.15,.15,.15]},getUniforms(e){let t={...e};return t.specularColor&&(t.specularColor=t.specularColor.map(n=>n/255)),{...De.defaultUniforms,...t}}};var Ue={name:"phongMaterial",dependencies:[y],source:ve,vs:ue,fs:de,defines:{LIGHTING_FRAGMENT:!0},uniformTypes:{ambient:"f32",diffuse:"f32",shininess:"f32",specularColor:"vec3<f32>"},defaultUniforms:{ambient:.35,diffuse:.6,shininess:32,specularColor:[.15,.15,.15]},getUniforms(e){let t={...e};return t.specularColor&&(t.specularColor=t.specularColor.map(n=>n/255)),{...Ue.defaultUniforms,...t}}};var Jt=`out vec3 pbr_vPosition;
2004
+ `;var Ye={props:{},name:"gouraudMaterial",bindingLayout:[{name:"gouraudMaterial",group:3}],vs:Ee.replace("phongMaterial","gouraudMaterial"),fs:Ae.replace("phongMaterial","gouraudMaterial"),source:Re.replaceAll("phongMaterial","gouraudMaterial"),defines:{LIGHTING_VERTEX:!0},dependencies:[F],uniformTypes:{unlit:"i32",ambient:"f32",diffuse:"f32",shininess:"f32",specularColor:"vec3<f32>"},defaultUniforms:{unlit:!1,ambient:.35,diffuse:.6,shininess:32,specularColor:[.15,.15,.15]},getUniforms(e){let t={...e};return t.specularColor&&(t.specularColor=t.specularColor.map(n=>n/255)),{...Ye.defaultUniforms,...t}}};var Xe={name:"phongMaterial",firstBindingSlot:0,bindingLayout:[{name:"phongMaterial",group:3}],dependencies:[F],source:Re,vs:Ae,fs:Ee,defines:{LIGHTING_FRAGMENT:!0},uniformTypes:{unlit:"i32",ambient:"f32",diffuse:"f32",shininess:"f32",specularColor:"vec3<f32>"},defaultUniforms:{unlit:!1,ambient:.35,diffuse:.6,shininess:32,specularColor:[.15,.15,.15]},getUniforms(e){let t={...e};return t.specularColor&&(t.specularColor=t.specularColor.map(n=>n/255)),{...Xe.defaultUniforms,...t}}};var An=`out vec3 pbr_vPosition;
1622
2005
  out vec2 pbr_vUV;
1623
2006
 
1624
2007
  #ifdef HAS_NORMALS
@@ -1651,7 +2034,7 @@ void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, ve
1651
2034
  pbr_vUV = vec2(0.,0.);
1652
2035
  #endif
1653
2036
  }
1654
- `,Qt=`precision highp float;
2037
+ `,En=`precision highp float;
1655
2038
 
1656
2039
  uniform pbrMaterialUniforms {
1657
2040
  // Material is unlit
@@ -1693,10 +2076,12 @@ uniform pbrMaterialUniforms {
1693
2076
  float clearcoatFactor;
1694
2077
  float clearcoatRoughnessFactor;
1695
2078
  bool clearcoatMapEnabled;
2079
+ bool clearcoatRoughnessMapEnabled;
1696
2080
 
1697
2081
  vec3 sheenColorFactor;
1698
2082
  float sheenRoughnessFactor;
1699
2083
  bool sheenColorMapEnabled;
2084
+ bool sheenRoughnessMapEnabled;
1700
2085
 
1701
2086
  float iridescenceFactor;
1702
2087
  float iridescenceIor;
@@ -1746,26 +2131,33 @@ uniform sampler2D pbr_specularIntensitySampler;
1746
2131
  #ifdef HAS_TRANSMISSIONMAP
1747
2132
  uniform sampler2D pbr_transmissionSampler;
1748
2133
  #endif
2134
+ #ifdef HAS_THICKNESSMAP
2135
+ uniform sampler2D pbr_thicknessSampler;
2136
+ #endif
1749
2137
  #ifdef HAS_CLEARCOATMAP
1750
2138
  uniform sampler2D pbr_clearcoatSampler;
2139
+ #endif
2140
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
1751
2141
  uniform sampler2D pbr_clearcoatRoughnessSampler;
1752
2142
  #endif
2143
+ #ifdef HAS_CLEARCOATNORMALMAP
2144
+ uniform sampler2D pbr_clearcoatNormalSampler;
2145
+ #endif
1753
2146
  #ifdef HAS_SHEENCOLORMAP
1754
2147
  uniform sampler2D pbr_sheenColorSampler;
2148
+ #endif
2149
+ #ifdef HAS_SHEENROUGHNESSMAP
1755
2150
  uniform sampler2D pbr_sheenRoughnessSampler;
1756
2151
  #endif
1757
2152
  #ifdef HAS_IRIDESCENCEMAP
1758
2153
  uniform sampler2D pbr_iridescenceSampler;
1759
2154
  #endif
2155
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
2156
+ uniform sampler2D pbr_iridescenceThicknessSampler;
2157
+ #endif
1760
2158
  #ifdef HAS_ANISOTROPYMAP
1761
2159
  uniform sampler2D pbr_anisotropySampler;
1762
2160
  #endif
1763
- #ifdef USE_IBL
1764
- uniform samplerCube pbr_diffuseEnvSampler;
1765
- uniform samplerCube pbr_specularEnvSampler;
1766
- uniform sampler2D pbr_brdfLUT;
1767
- #endif
1768
-
1769
2161
  // Inputs from vertex shader
1770
2162
 
1771
2163
  in vec3 pbr_vPosition;
@@ -1802,6 +2194,8 @@ struct PBRInfo {
1802
2194
  const float M_PI = 3.141592653589793;
1803
2195
  const float c_MinRoughness = 0.04;
1804
2196
 
2197
+ vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor);
2198
+
1805
2199
  vec4 SRGBtoLINEAR(vec4 srgbIn)
1806
2200
  {
1807
2201
  #ifdef MANUAL_SRGB
@@ -1817,11 +2211,9 @@ vec4 SRGBtoLINEAR(vec4 srgbIn)
1817
2211
  #endif //MANUAL_SRGB
1818
2212
  }
1819
2213
 
1820
- // Find the normal for this fragment, pulling either from a predefined normal map
1821
- // or from the interpolated mesh normal and tangent attributes.
1822
- vec3 getNormal()
2214
+ // Build the tangent basis from interpolated attributes or screen-space derivatives.
2215
+ mat3 getTBN()
1823
2216
  {
1824
- // Retrieve the tangent space matrix
1825
2217
  #ifndef HAS_TANGENTS
1826
2218
  vec3 pos_dx = dFdx(pbr_vPosition);
1827
2219
  vec3 pos_dy = dFdy(pbr_vPosition);
@@ -1842,17 +2234,38 @@ vec3 getNormal()
1842
2234
  mat3 tbn = pbr_vTBN;
1843
2235
  #endif
1844
2236
 
1845
- #ifdef HAS_NORMALMAP
1846
- vec3 n = texture(pbr_normalSampler, pbr_vUV).rgb;
1847
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
1848
- #else
1849
- // The tbn matrix is linearly interpolated, so we need to re-normalize
1850
- vec3 n = normalize(tbn[2].xyz);
1851
- #endif
2237
+ return tbn;
2238
+ }
2239
+
2240
+ // Find the normal for this fragment, pulling either from a predefined normal map
2241
+ // or from the interpolated mesh normal and tangent attributes.
2242
+ vec3 getMappedNormal(sampler2D normalSampler, mat3 tbn, float normalScale)
2243
+ {
2244
+ vec3 n = texture(normalSampler, pbr_vUV).rgb;
2245
+ return normalize(tbn * ((2.0 * n - 1.0) * vec3(normalScale, normalScale, 1.0)));
2246
+ }
2247
+
2248
+ vec3 getNormal(mat3 tbn)
2249
+ {
2250
+ #ifdef HAS_NORMALMAP
2251
+ vec3 n = getMappedNormal(pbr_normalSampler, tbn, pbrMaterial.normalScale);
2252
+ #else
2253
+ // The tbn matrix is linearly interpolated, so we need to re-normalize
2254
+ vec3 n = normalize(tbn[2].xyz);
2255
+ #endif
1852
2256
 
1853
2257
  return n;
1854
2258
  }
1855
2259
 
2260
+ vec3 getClearcoatNormal(mat3 tbn, vec3 baseNormal)
2261
+ {
2262
+ #ifdef HAS_CLEARCOATNORMALMAP
2263
+ return getMappedNormal(pbr_clearcoatNormalSampler, tbn, 1.0);
2264
+ #else
2265
+ return baseNormal;
2266
+ #endif
2267
+ }
2268
+
1856
2269
  // Calculation of the lighting contribution from an optional Image Based Light source.
1857
2270
  // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
1858
2271
  // See our README.md on Environment Maps [3] for additional discussion.
@@ -1928,6 +2341,169 @@ float microfacetDistribution(PBRInfo pbrInfo)
1928
2341
  return roughnessSq / (M_PI * f * f);
1929
2342
  }
1930
2343
 
2344
+ float maxComponent(vec3 value)
2345
+ {
2346
+ return max(max(value.r, value.g), value.b);
2347
+ }
2348
+
2349
+ float getDielectricF0(float ior)
2350
+ {
2351
+ float clampedIor = max(ior, 1.0);
2352
+ float ratio = (clampedIor - 1.0) / (clampedIor + 1.0);
2353
+ return ratio * ratio;
2354
+ }
2355
+
2356
+ vec2 normalizeDirection(vec2 direction)
2357
+ {
2358
+ float directionLength = length(direction);
2359
+ return directionLength > 0.0001 ? direction / directionLength : vec2(1.0, 0.0);
2360
+ }
2361
+
2362
+ vec2 rotateDirection(vec2 direction, float rotation)
2363
+ {
2364
+ float s = sin(rotation);
2365
+ float c = cos(rotation);
2366
+ return vec2(direction.x * c - direction.y * s, direction.x * s + direction.y * c);
2367
+ }
2368
+
2369
+ vec3 getIridescenceTint(float iridescence, float thickness, float NdotV)
2370
+ {
2371
+ if (iridescence <= 0.0) {
2372
+ return vec3(1.0);
2373
+ }
2374
+
2375
+ float phase = 0.015 * thickness * pbrMaterial.iridescenceIor + (1.0 - NdotV) * 6.0;
2376
+ vec3 thinFilmTint =
2377
+ 0.5 + 0.5 * cos(vec3(phase, phase + 2.0943951, phase + 4.1887902));
2378
+ return mix(vec3(1.0), thinFilmTint, iridescence);
2379
+ }
2380
+
2381
+ vec3 getVolumeAttenuation(float thickness)
2382
+ {
2383
+ if (thickness <= 0.0) {
2384
+ return vec3(1.0);
2385
+ }
2386
+
2387
+ vec3 attenuationCoefficient =
2388
+ -log(max(pbrMaterial.attenuationColor, vec3(0.0001))) /
2389
+ max(pbrMaterial.attenuationDistance, 0.0001);
2390
+ return exp(-attenuationCoefficient * thickness);
2391
+ }
2392
+
2393
+ PBRInfo createClearcoatPBRInfo(PBRInfo basePBRInfo, vec3 clearcoatNormal, float clearcoatRoughness)
2394
+ {
2395
+ float perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
2396
+ float alphaRoughness = perceptualRoughness * perceptualRoughness;
2397
+ float NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);
2398
+
2399
+ return PBRInfo(
2400
+ basePBRInfo.NdotL,
2401
+ NdotV,
2402
+ basePBRInfo.NdotH,
2403
+ basePBRInfo.LdotH,
2404
+ basePBRInfo.VdotH,
2405
+ perceptualRoughness,
2406
+ 0.0,
2407
+ vec3(0.04),
2408
+ vec3(1.0),
2409
+ alphaRoughness,
2410
+ vec3(0.0),
2411
+ vec3(0.04),
2412
+ clearcoatNormal,
2413
+ basePBRInfo.v
2414
+ );
2415
+ }
2416
+
2417
+ vec3 calculateClearcoatContribution(
2418
+ PBRInfo pbrInfo,
2419
+ vec3 lightColor,
2420
+ vec3 clearcoatNormal,
2421
+ float clearcoatFactor,
2422
+ float clearcoatRoughness
2423
+ ) {
2424
+ if (clearcoatFactor <= 0.0) {
2425
+ return vec3(0.0);
2426
+ }
2427
+
2428
+ PBRInfo clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
2429
+ return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;
2430
+ }
2431
+
2432
+ #ifdef USE_IBL
2433
+ vec3 calculateClearcoatIBLContribution(
2434
+ PBRInfo pbrInfo,
2435
+ vec3 clearcoatNormal,
2436
+ vec3 reflection,
2437
+ float clearcoatFactor,
2438
+ float clearcoatRoughness
2439
+ ) {
2440
+ if (clearcoatFactor <= 0.0) {
2441
+ return vec3(0.0);
2442
+ }
2443
+
2444
+ PBRInfo clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
2445
+ return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;
2446
+ }
2447
+ #endif
2448
+
2449
+ vec3 calculateSheenContribution(
2450
+ PBRInfo pbrInfo,
2451
+ vec3 lightColor,
2452
+ vec3 sheenColor,
2453
+ float sheenRoughness
2454
+ ) {
2455
+ if (maxComponent(sheenColor) <= 0.0) {
2456
+ return vec3(0.0);
2457
+ }
2458
+
2459
+ float sheenFresnel = pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
2460
+ float sheenVisibility = mix(1.0, pbrInfo.NdotL * pbrInfo.NdotV, sheenRoughness);
2461
+ return pbrInfo.NdotL *
2462
+ lightColor *
2463
+ sheenColor *
2464
+ (0.25 + 0.75 * sheenFresnel) *
2465
+ sheenVisibility *
2466
+ (1.0 - pbrInfo.metalness);
2467
+ }
2468
+
2469
+ float calculateAnisotropyBoost(
2470
+ PBRInfo pbrInfo,
2471
+ vec3 anisotropyTangent,
2472
+ float anisotropyStrength
2473
+ ) {
2474
+ if (anisotropyStrength <= 0.0) {
2475
+ return 1.0;
2476
+ }
2477
+
2478
+ vec3 anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));
2479
+ float bitangentViewAlignment = abs(dot(pbrInfo.v, anisotropyBitangent));
2480
+ return mix(1.0, 0.65 + 0.7 * bitangentViewAlignment, anisotropyStrength);
2481
+ }
2482
+
2483
+ vec3 calculateMaterialLightColor(
2484
+ PBRInfo pbrInfo,
2485
+ vec3 lightColor,
2486
+ vec3 clearcoatNormal,
2487
+ float clearcoatFactor,
2488
+ float clearcoatRoughness,
2489
+ vec3 sheenColor,
2490
+ float sheenRoughness,
2491
+ vec3 anisotropyTangent,
2492
+ float anisotropyStrength
2493
+ ) {
2494
+ float anisotropyBoost = calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
2495
+ vec3 color = calculateFinalColor(pbrInfo, lightColor) * anisotropyBoost;
2496
+ color += calculateClearcoatContribution(
2497
+ pbrInfo,
2498
+ lightColor,
2499
+ clearcoatNormal,
2500
+ clearcoatFactor,
2501
+ clearcoatRoughness
2502
+ );
2503
+ color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);
2504
+ return color;
2505
+ }
2506
+
1931
2507
  void PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) {
1932
2508
  pbrInfo.NdotL = 1.0;
1933
2509
  pbrInfo.NdotH = 0.0;
@@ -1952,6 +2528,11 @@ void PBRInfo_setPointLight(inout PBRInfo pbrInfo, PointLight pointLight) {
1952
2528
  PBRInfo_setDirectionalLight(pbrInfo, light_direction);
1953
2529
  }
1954
2530
 
2531
+ void PBRInfo_setSpotLight(inout PBRInfo pbrInfo, SpotLight spotLight) {
2532
+ vec3 light_direction = normalize(spotLight.position - pbr_vPosition);
2533
+ PBRInfo_setDirectionalLight(pbrInfo, light_direction);
2534
+ }
2535
+
1955
2536
  vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
1956
2537
  // Calculate the shading terms for the microfacet specular shading model
1957
2538
  vec3 F = specularReflection(pbrInfo);
@@ -1982,6 +2563,8 @@ vec4 pbr_filterColor(vec4 colorUnused)
1982
2563
 
1983
2564
  vec3 color = vec3(0, 0, 0);
1984
2565
 
2566
+ float transmission = 0.0;
2567
+
1985
2568
  if(pbrMaterial.unlit){
1986
2569
  color.rgb = baseColor.rgb;
1987
2570
  }
@@ -2000,14 +2583,252 @@ vec4 pbr_filterColor(vec4 colorUnused)
2000
2583
  #endif
2001
2584
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
2002
2585
  metallic = clamp(metallic, 0.0, 1.0);
2586
+ mat3 tbn = getTBN();
2587
+ vec3 n = getNormal(tbn); // normal at surface point
2588
+ vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
2589
+ float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
2590
+ #ifdef USE_MATERIAL_EXTENSIONS
2591
+ bool useExtendedPBR =
2592
+ pbrMaterial.specularColorMapEnabled ||
2593
+ pbrMaterial.specularIntensityMapEnabled ||
2594
+ abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||
2595
+ maxComponent(abs(pbrMaterial.specularColorFactor - vec3(1.0))) > 0.0001 ||
2596
+ abs(pbrMaterial.ior - 1.5) > 0.0001 ||
2597
+ pbrMaterial.transmissionMapEnabled ||
2598
+ pbrMaterial.transmissionFactor > 0.0001 ||
2599
+ pbrMaterial.clearcoatMapEnabled ||
2600
+ pbrMaterial.clearcoatRoughnessMapEnabled ||
2601
+ pbrMaterial.clearcoatFactor > 0.0001 ||
2602
+ pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||
2603
+ pbrMaterial.sheenColorMapEnabled ||
2604
+ pbrMaterial.sheenRoughnessMapEnabled ||
2605
+ maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||
2606
+ pbrMaterial.sheenRoughnessFactor > 0.0001 ||
2607
+ pbrMaterial.iridescenceMapEnabled ||
2608
+ pbrMaterial.iridescenceFactor > 0.0001 ||
2609
+ abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||
2610
+ abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||
2611
+ abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||
2612
+ pbrMaterial.anisotropyMapEnabled ||
2613
+ pbrMaterial.anisotropyStrength > 0.0001 ||
2614
+ abs(pbrMaterial.anisotropyRotation) > 0.0001 ||
2615
+ length(pbrMaterial.anisotropyDirection - vec2(1.0, 0.0)) > 0.0001;
2616
+ #else
2617
+ bool useExtendedPBR = false;
2618
+ #endif
2619
+
2620
+ if (!useExtendedPBR) {
2621
+ // Keep the baseline metallic-roughness implementation byte-for-byte equivalent in behavior.
2622
+ float alphaRoughness = perceptualRoughness * perceptualRoughness;
2623
+
2624
+ vec3 f0 = vec3(0.04);
2625
+ vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
2626
+ diffuseColor *= 1.0 - metallic;
2627
+ vec3 specularColor = mix(f0, baseColor.rgb, metallic);
2628
+
2629
+ float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
2630
+ float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
2631
+ vec3 specularEnvironmentR0 = specularColor.rgb;
2632
+ vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
2633
+ vec3 reflection = -normalize(reflect(v, n));
2634
+
2635
+ PBRInfo pbrInfo = PBRInfo(
2636
+ 0.0, // NdotL
2637
+ NdotV,
2638
+ 0.0, // NdotH
2639
+ 0.0, // LdotH
2640
+ 0.0, // VdotH
2641
+ perceptualRoughness,
2642
+ metallic,
2643
+ specularEnvironmentR0,
2644
+ specularEnvironmentR90,
2645
+ alphaRoughness,
2646
+ diffuseColor,
2647
+ specularColor,
2648
+ n,
2649
+ v
2650
+ );
2651
+
2652
+ #ifdef USE_LIGHTS
2653
+ PBRInfo_setAmbientLight(pbrInfo);
2654
+ color += calculateFinalColor(pbrInfo, lighting.ambientColor);
2655
+
2656
+ for(int i = 0; i < lighting.directionalLightCount; i++) {
2657
+ if (i < lighting.directionalLightCount) {
2658
+ PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
2659
+ color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
2660
+ }
2661
+ }
2662
+
2663
+ for(int i = 0; i < lighting.pointLightCount; i++) {
2664
+ if (i < lighting.pointLightCount) {
2665
+ PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
2666
+ float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
2667
+ color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
2668
+ }
2669
+ }
2670
+
2671
+ for(int i = 0; i < lighting.spotLightCount; i++) {
2672
+ if (i < lighting.spotLightCount) {
2673
+ PBRInfo_setSpotLight(pbrInfo, lighting_getSpotLight(i));
2674
+ float attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), pbr_vPosition);
2675
+ color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color / attenuation);
2676
+ }
2677
+ }
2678
+ #endif
2679
+
2680
+ #ifdef USE_IBL
2681
+ if (pbrMaterial.IBLenabled) {
2682
+ color += getIBLContribution(pbrInfo, n, reflection);
2683
+ }
2684
+ #endif
2685
+
2686
+ #ifdef HAS_OCCLUSIONMAP
2687
+ if (pbrMaterial.occlusionMapEnabled) {
2688
+ float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
2689
+ color = mix(color, color * ao, pbrMaterial.occlusionStrength);
2690
+ }
2691
+ #endif
2692
+
2693
+ vec3 emissive = pbrMaterial.emissiveFactor;
2694
+ #ifdef HAS_EMISSIVEMAP
2695
+ if (pbrMaterial.emissiveMapEnabled) {
2696
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
2697
+ }
2698
+ #endif
2699
+ color += emissive * pbrMaterial.emissiveStrength;
2700
+
2701
+ #ifdef PBR_DEBUG
2702
+ color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
2703
+ color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);
2704
+ color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
2705
+ #endif
2706
+
2707
+ return vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a);
2708
+ }
2709
+
2710
+ float specularIntensity = pbrMaterial.specularIntensityFactor;
2711
+ #ifdef HAS_SPECULARINTENSITYMAP
2712
+ if (pbrMaterial.specularIntensityMapEnabled) {
2713
+ specularIntensity *= texture(pbr_specularIntensitySampler, pbr_vUV).a;
2714
+ }
2715
+ #endif
2716
+
2717
+ vec3 specularFactor = pbrMaterial.specularColorFactor;
2718
+ #ifdef HAS_SPECULARCOLORMAP
2719
+ if (pbrMaterial.specularColorMapEnabled) {
2720
+ specularFactor *= SRGBtoLINEAR(texture(pbr_specularColorSampler, pbr_vUV)).rgb;
2721
+ }
2722
+ #endif
2723
+
2724
+ transmission = pbrMaterial.transmissionFactor;
2725
+ #ifdef HAS_TRANSMISSIONMAP
2726
+ if (pbrMaterial.transmissionMapEnabled) {
2727
+ transmission *= texture(pbr_transmissionSampler, pbr_vUV).r;
2728
+ }
2729
+ #endif
2730
+ transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);
2731
+ float thickness = max(pbrMaterial.thicknessFactor, 0.0);
2732
+ #ifdef HAS_THICKNESSMAP
2733
+ thickness *= texture(pbr_thicknessSampler, pbr_vUV).g;
2734
+ #endif
2735
+
2736
+ float clearcoatFactor = pbrMaterial.clearcoatFactor;
2737
+ float clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;
2738
+ #ifdef HAS_CLEARCOATMAP
2739
+ if (pbrMaterial.clearcoatMapEnabled) {
2740
+ clearcoatFactor *= texture(pbr_clearcoatSampler, pbr_vUV).r;
2741
+ }
2742
+ #endif
2743
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
2744
+ if (pbrMaterial.clearcoatRoughnessMapEnabled) {
2745
+ clearcoatRoughness *= texture(pbr_clearcoatRoughnessSampler, pbr_vUV).g;
2746
+ }
2747
+ #endif
2748
+ clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
2749
+ clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
2750
+ vec3 clearcoatNormal = getClearcoatNormal(tbn, n);
2751
+
2752
+ vec3 sheenColor = pbrMaterial.sheenColorFactor;
2753
+ float sheenRoughness = pbrMaterial.sheenRoughnessFactor;
2754
+ #ifdef HAS_SHEENCOLORMAP
2755
+ if (pbrMaterial.sheenColorMapEnabled) {
2756
+ sheenColor *= SRGBtoLINEAR(texture(pbr_sheenColorSampler, pbr_vUV)).rgb;
2757
+ }
2758
+ #endif
2759
+ #ifdef HAS_SHEENROUGHNESSMAP
2760
+ if (pbrMaterial.sheenRoughnessMapEnabled) {
2761
+ sheenRoughness *= texture(pbr_sheenRoughnessSampler, pbr_vUV).a;
2762
+ }
2763
+ #endif
2764
+ sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);
2765
+
2766
+ float iridescence = pbrMaterial.iridescenceFactor;
2767
+ #ifdef HAS_IRIDESCENCEMAP
2768
+ if (pbrMaterial.iridescenceMapEnabled) {
2769
+ iridescence *= texture(pbr_iridescenceSampler, pbr_vUV).r;
2770
+ }
2771
+ #endif
2772
+ iridescence = clamp(iridescence, 0.0, 1.0);
2773
+ float iridescenceThickness = mix(
2774
+ pbrMaterial.iridescenceThicknessRange.x,
2775
+ pbrMaterial.iridescenceThicknessRange.y,
2776
+ 0.5
2777
+ );
2778
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
2779
+ iridescenceThickness = mix(
2780
+ pbrMaterial.iridescenceThicknessRange.x,
2781
+ pbrMaterial.iridescenceThicknessRange.y,
2782
+ texture(pbr_iridescenceThicknessSampler, pbr_vUV).g
2783
+ );
2784
+ #endif
2785
+
2786
+ float anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);
2787
+ vec2 anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);
2788
+ #ifdef HAS_ANISOTROPYMAP
2789
+ if (pbrMaterial.anisotropyMapEnabled) {
2790
+ vec3 anisotropySample = texture(pbr_anisotropySampler, pbr_vUV).rgb;
2791
+ anisotropyStrength *= anisotropySample.b;
2792
+ vec2 mappedDirection = anisotropySample.rg * 2.0 - 1.0;
2793
+ if (length(mappedDirection) > 0.0001) {
2794
+ anisotropyDirection = normalize(mappedDirection);
2795
+ }
2796
+ }
2797
+ #endif
2798
+ anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);
2799
+ vec3 anisotropyTangent = normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);
2800
+ if (length(anisotropyTangent) < 0.0001) {
2801
+ anisotropyTangent = normalize(tbn[0]);
2802
+ }
2803
+ float anisotropyViewAlignment = abs(dot(v, anisotropyTangent));
2804
+ perceptualRoughness = mix(
2805
+ perceptualRoughness,
2806
+ clamp(perceptualRoughness * (1.0 - 0.6 * anisotropyViewAlignment), c_MinRoughness, 1.0),
2807
+ anisotropyStrength
2808
+ );
2809
+
2003
2810
  // Roughness is authored as perceptual roughness; as is convention,
2004
2811
  // convert to material roughness by squaring the perceptual roughness [2].
2005
2812
  float alphaRoughness = perceptualRoughness * perceptualRoughness;
2006
2813
 
2007
- vec3 f0 = vec3(0.04);
2008
- vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
2009
- diffuseColor *= 1.0 - metallic;
2010
- vec3 specularColor = mix(f0, baseColor.rgb, metallic);
2814
+ float dielectricF0 = getDielectricF0(pbrMaterial.ior);
2815
+ vec3 dielectricSpecularF0 = min(
2816
+ vec3(dielectricF0) * specularFactor * specularIntensity,
2817
+ vec3(1.0)
2818
+ );
2819
+ vec3 iridescenceTint = getIridescenceTint(iridescence, iridescenceThickness, NdotV);
2820
+ dielectricSpecularF0 = mix(
2821
+ dielectricSpecularF0,
2822
+ dielectricSpecularF0 * iridescenceTint,
2823
+ iridescence
2824
+ );
2825
+ vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - dielectricSpecularF0);
2826
+ diffuseColor *= (1.0 - metallic) * (1.0 - transmission);
2827
+ vec3 specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);
2828
+
2829
+ float baseLayerEnergy = 1.0 - clearcoatFactor * 0.25;
2830
+ diffuseColor *= baseLayerEnergy;
2831
+ specularColor *= baseLayerEnergy;
2011
2832
 
2012
2833
  // Compute reflectance.
2013
2834
  float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
@@ -2019,11 +2840,6 @@ vec4 pbr_filterColor(vec4 colorUnused)
2019
2840
  float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
2020
2841
  vec3 specularEnvironmentR0 = specularColor.rgb;
2021
2842
  vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
2022
-
2023
- vec3 n = getNormal(); // normal at surface point
2024
- vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
2025
-
2026
- float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
2027
2843
  vec3 reflection = -normalize(reflect(v, n));
2028
2844
 
2029
2845
  PBRInfo pbrInfo = PBRInfo(
@@ -2047,13 +2863,33 @@ vec4 pbr_filterColor(vec4 colorUnused)
2047
2863
  #ifdef USE_LIGHTS
2048
2864
  // Apply ambient light
2049
2865
  PBRInfo_setAmbientLight(pbrInfo);
2050
- color += calculateFinalColor(pbrInfo, lighting.ambientColor);
2866
+ color += calculateMaterialLightColor(
2867
+ pbrInfo,
2868
+ lighting.ambientColor,
2869
+ clearcoatNormal,
2870
+ clearcoatFactor,
2871
+ clearcoatRoughness,
2872
+ sheenColor,
2873
+ sheenRoughness,
2874
+ anisotropyTangent,
2875
+ anisotropyStrength
2876
+ );
2051
2877
 
2052
2878
  // Apply directional light
2053
2879
  for(int i = 0; i < lighting.directionalLightCount; i++) {
2054
2880
  if (i < lighting.directionalLightCount) {
2055
2881
  PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
2056
- color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
2882
+ color += calculateMaterialLightColor(
2883
+ pbrInfo,
2884
+ lighting_getDirectionalLight(i).color,
2885
+ clearcoatNormal,
2886
+ clearcoatFactor,
2887
+ clearcoatRoughness,
2888
+ sheenColor,
2889
+ sheenRoughness,
2890
+ anisotropyTangent,
2891
+ anisotropyStrength
2892
+ );
2057
2893
  }
2058
2894
  }
2059
2895
 
@@ -2062,7 +2898,35 @@ vec4 pbr_filterColor(vec4 colorUnused)
2062
2898
  if (i < lighting.pointLightCount) {
2063
2899
  PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
2064
2900
  float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
2065
- color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
2901
+ color += calculateMaterialLightColor(
2902
+ pbrInfo,
2903
+ lighting_getPointLight(i).color / attenuation,
2904
+ clearcoatNormal,
2905
+ clearcoatFactor,
2906
+ clearcoatRoughness,
2907
+ sheenColor,
2908
+ sheenRoughness,
2909
+ anisotropyTangent,
2910
+ anisotropyStrength
2911
+ );
2912
+ }
2913
+ }
2914
+
2915
+ for(int i = 0; i < lighting.spotLightCount; i++) {
2916
+ if (i < lighting.spotLightCount) {
2917
+ PBRInfo_setSpotLight(pbrInfo, lighting_getSpotLight(i));
2918
+ float attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), pbr_vPosition);
2919
+ color += calculateMaterialLightColor(
2920
+ pbrInfo,
2921
+ lighting_getSpotLight(i).color / attenuation,
2922
+ clearcoatNormal,
2923
+ clearcoatFactor,
2924
+ clearcoatRoughness,
2925
+ sheenColor,
2926
+ sheenRoughness,
2927
+ anisotropyTangent,
2928
+ anisotropyStrength
2929
+ );
2066
2930
  }
2067
2931
  }
2068
2932
  #endif
@@ -2070,7 +2934,16 @@ vec4 pbr_filterColor(vec4 colorUnused)
2070
2934
  // Calculate lighting contribution from image based lighting source (IBL)
2071
2935
  #ifdef USE_IBL
2072
2936
  if (pbrMaterial.IBLenabled) {
2073
- color += getIBLContribution(pbrInfo, n, reflection);
2937
+ color += getIBLContribution(pbrInfo, n, reflection) *
2938
+ calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
2939
+ color += calculateClearcoatIBLContribution(
2940
+ pbrInfo,
2941
+ clearcoatNormal,
2942
+ -normalize(reflect(v, clearcoatNormal)),
2943
+ clearcoatFactor,
2944
+ clearcoatRoughness
2945
+ );
2946
+ color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;
2074
2947
  }
2075
2948
  #endif
2076
2949
 
@@ -2082,12 +2955,17 @@ vec4 pbr_filterColor(vec4 colorUnused)
2082
2955
  }
2083
2956
  #endif
2084
2957
 
2958
+ vec3 emissive = pbrMaterial.emissiveFactor;
2085
2959
  #ifdef HAS_EMISSIVEMAP
2086
2960
  if (pbrMaterial.emissiveMapEnabled) {
2087
- vec3 emissive = SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
2088
- color += emissive;
2961
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
2089
2962
  }
2090
2963
  #endif
2964
+ color += emissive * pbrMaterial.emissiveStrength;
2965
+
2966
+ if (transmission > 0.0) {
2967
+ color = mix(color, color * getVolumeAttenuation(thickness), transmission);
2968
+ }
2091
2969
 
2092
2970
  // This section uses mix to override final color for reference app visualization
2093
2971
  // of various parameters in the lighting equation.
@@ -2107,9 +2985,10 @@ vec4 pbr_filterColor(vec4 colorUnused)
2107
2985
 
2108
2986
  }
2109
2987
 
2110
- return vec4(pow(color,vec3(1.0/2.2)), baseColor.a);
2988
+ float alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);
2989
+ return vec4(pow(color,vec3(1.0/2.2)), alpha);
2111
2990
  }
2112
- `;var en=`struct PBRFragmentInputs {
2991
+ `;var Rn=`struct PBRFragmentInputs {
2113
2992
  pbr_vPosition: vec3f,
2114
2993
  pbr_vUV: vec2f,
2115
2994
  pbr_vTBN: mat3x3f,
@@ -2167,6 +3046,42 @@ struct pbrMaterialUniforms {
2167
3046
 
2168
3047
  alphaCutoffEnabled: i32,
2169
3048
  alphaCutoff: f32, // #ifdef ALPHA_CUTOFF
3049
+
3050
+ specularColorFactor: vec3f,
3051
+ specularIntensityFactor: f32,
3052
+ specularColorMapEnabled: i32,
3053
+ specularIntensityMapEnabled: i32,
3054
+
3055
+ ior: f32,
3056
+
3057
+ transmissionFactor: f32,
3058
+ transmissionMapEnabled: i32,
3059
+
3060
+ thicknessFactor: f32,
3061
+ attenuationDistance: f32,
3062
+ attenuationColor: vec3f,
3063
+
3064
+ clearcoatFactor: f32,
3065
+ clearcoatRoughnessFactor: f32,
3066
+ clearcoatMapEnabled: i32,
3067
+ clearcoatRoughnessMapEnabled: i32,
3068
+
3069
+ sheenColorFactor: vec3f,
3070
+ sheenRoughnessFactor: f32,
3071
+ sheenColorMapEnabled: i32,
3072
+ sheenRoughnessMapEnabled: i32,
3073
+
3074
+ iridescenceFactor: f32,
3075
+ iridescenceIor: f32,
3076
+ iridescenceThicknessRange: vec2f,
3077
+ iridescenceMapEnabled: i32,
3078
+
3079
+ anisotropyStrength: f32,
3080
+ anisotropyRotation: f32,
3081
+ anisotropyDirection: vec2f,
3082
+ anisotropyMapEnabled: i32,
3083
+
3084
+ emissiveStrength: f32,
2170
3085
 
2171
3086
  // IBL
2172
3087
  IBLenabled: i32,
@@ -2179,38 +3094,77 @@ struct pbrMaterialUniforms {
2179
3094
  // #endif
2180
3095
  }
2181
3096
 
2182
- @binding(2) @group(0) var<uniform> pbrMaterial : pbrMaterialUniforms;
3097
+ @group(3) @binding(auto) var<uniform> pbrMaterial : pbrMaterialUniforms;
2183
3098
 
2184
3099
  // Samplers
2185
3100
  #ifdef HAS_BASECOLORMAP
2186
- @binding(3) @group(0) var pbr_baseColorSampler: texture_2d<f32>;
2187
- @binding(4) @group(0) var pbr_baseColorSamplerSampler: sampler;
3101
+ @group(3) @binding(auto) var pbr_baseColorSampler: texture_2d<f32>;
3102
+ @group(3) @binding(auto) var pbr_baseColorSamplerSampler: sampler;
2188
3103
  #endif
2189
3104
  #ifdef HAS_NORMALMAP
2190
- @binding(5) @group(0) var pbr_normalSampler: texture_2d<f32>;
2191
- @binding(6) @group(0) var pbr_normalSamplerSampler: sampler;
3105
+ @group(3) @binding(auto) var pbr_normalSampler: texture_2d<f32>;
3106
+ @group(3) @binding(auto) var pbr_normalSamplerSampler: sampler;
2192
3107
  #endif
2193
3108
  #ifdef HAS_EMISSIVEMAP
2194
- @binding(7) @group(0) var pbr_emissiveSampler: texture_2d<f32>;
2195
- @binding(8) @group(0) var pbr_emissiveSamplerSampler: sampler;
3109
+ @group(3) @binding(auto) var pbr_emissiveSampler: texture_2d<f32>;
3110
+ @group(3) @binding(auto) var pbr_emissiveSamplerSampler: sampler;
2196
3111
  #endif
2197
3112
  #ifdef HAS_METALROUGHNESSMAP
2198
- @binding(9) @group(0) var pbr_metallicRoughnessSampler: texture_2d<f32>;
2199
- @binding(10) @group(0) var pbr_metallicRoughnessSamplerSampler: sampler;
3113
+ @group(3) @binding(auto) var pbr_metallicRoughnessSampler: texture_2d<f32>;
3114
+ @group(3) @binding(auto) var pbr_metallicRoughnessSamplerSampler: sampler;
2200
3115
  #endif
2201
3116
  #ifdef HAS_OCCLUSIONMAP
2202
- @binding(11) @group(0) var pbr_occlusionSampler: texture_2d<f32>;
2203
- @binding(12) @group(0) var pbr_occlusionSamplerSampler: sampler;
3117
+ @group(3) @binding(auto) var pbr_occlusionSampler: texture_2d<f32>;
3118
+ @group(3) @binding(auto) var pbr_occlusionSamplerSampler: sampler;
2204
3119
  #endif
2205
- #ifdef USE_IBL
2206
- @binding(13) @group(0) var pbr_diffuseEnvSampler: texture_cube<f32>;
2207
- @binding(14) @group(0) var pbr_diffuseEnvSamplerSampler: sampler;
2208
- @binding(15) @group(0) var pbr_specularEnvSampler: texture_cube<f32>;
2209
- @binding(16) @group(0) var pbr_specularEnvSamplerSampler: sampler;
2210
- @binding(17) @group(0) var pbr_BrdfLUT: texture_2d<f32>;
2211
- @binding(18) @group(0) var pbr_BrdfLUTSampler: sampler;
3120
+ #ifdef HAS_SPECULARCOLORMAP
3121
+ @group(3) @binding(auto) var pbr_specularColorSampler: texture_2d<f32>;
3122
+ @group(3) @binding(auto) var pbr_specularColorSamplerSampler: sampler;
3123
+ #endif
3124
+ #ifdef HAS_SPECULARINTENSITYMAP
3125
+ @group(3) @binding(auto) var pbr_specularIntensitySampler: texture_2d<f32>;
3126
+ @group(3) @binding(auto) var pbr_specularIntensitySamplerSampler: sampler;
3127
+ #endif
3128
+ #ifdef HAS_TRANSMISSIONMAP
3129
+ @group(3) @binding(auto) var pbr_transmissionSampler: texture_2d<f32>;
3130
+ @group(3) @binding(auto) var pbr_transmissionSamplerSampler: sampler;
3131
+ #endif
3132
+ #ifdef HAS_THICKNESSMAP
3133
+ @group(3) @binding(auto) var pbr_thicknessSampler: texture_2d<f32>;
3134
+ @group(3) @binding(auto) var pbr_thicknessSamplerSampler: sampler;
3135
+ #endif
3136
+ #ifdef HAS_CLEARCOATMAP
3137
+ @group(3) @binding(auto) var pbr_clearcoatSampler: texture_2d<f32>;
3138
+ @group(3) @binding(auto) var pbr_clearcoatSamplerSampler: sampler;
3139
+ #endif
3140
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
3141
+ @group(3) @binding(auto) var pbr_clearcoatRoughnessSampler: texture_2d<f32>;
3142
+ @group(3) @binding(auto) var pbr_clearcoatRoughnessSamplerSampler: sampler;
3143
+ #endif
3144
+ #ifdef HAS_CLEARCOATNORMALMAP
3145
+ @group(3) @binding(auto) var pbr_clearcoatNormalSampler: texture_2d<f32>;
3146
+ @group(3) @binding(auto) var pbr_clearcoatNormalSamplerSampler: sampler;
3147
+ #endif
3148
+ #ifdef HAS_SHEENCOLORMAP
3149
+ @group(3) @binding(auto) var pbr_sheenColorSampler: texture_2d<f32>;
3150
+ @group(3) @binding(auto) var pbr_sheenColorSamplerSampler: sampler;
3151
+ #endif
3152
+ #ifdef HAS_SHEENROUGHNESSMAP
3153
+ @group(3) @binding(auto) var pbr_sheenRoughnessSampler: texture_2d<f32>;
3154
+ @group(3) @binding(auto) var pbr_sheenRoughnessSamplerSampler: sampler;
3155
+ #endif
3156
+ #ifdef HAS_IRIDESCENCEMAP
3157
+ @group(3) @binding(auto) var pbr_iridescenceSampler: texture_2d<f32>;
3158
+ @group(3) @binding(auto) var pbr_iridescenceSamplerSampler: sampler;
3159
+ #endif
3160
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
3161
+ @group(3) @binding(auto) var pbr_iridescenceThicknessSampler: texture_2d<f32>;
3162
+ @group(3) @binding(auto) var pbr_iridescenceThicknessSamplerSampler: sampler;
3163
+ #endif
3164
+ #ifdef HAS_ANISOTROPYMAP
3165
+ @group(3) @binding(auto) var pbr_anisotropySampler: texture_2d<f32>;
3166
+ @group(3) @binding(auto) var pbr_anisotropySamplerSampler: sampler;
2212
3167
  #endif
2213
-
2214
3168
  // Encapsulate the various inputs used by the various functions in the shading equation
2215
3169
  // We store values in this struct to simplify the integration of alternative implementations
2216
3170
  // of the shading terms, outlined in the Readme.MD Appendix.
@@ -2251,11 +3205,9 @@ fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
2251
3205
  return vec4f(linOut, srgbIn.w);
2252
3206
  }
2253
3207
 
2254
- // Find the normal for this fragment, pulling either from a predefined normal map
2255
- // or from the interpolated mesh normal and tangent attributes.
2256
- fn getNormal() -> vec3f
3208
+ // Build the tangent basis from interpolated attributes or screen-space derivatives.
3209
+ fn getTBN() -> mat3x3f
2257
3210
  {
2258
- // Retrieve the tangent space matrix
2259
3211
  let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);
2260
3212
  let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);
2261
3213
  let tex_dx: vec3f = dpdx(vec3f(fragmentInputs.pbr_vUV, 0.0));
@@ -2273,16 +3225,52 @@ fn getNormal() -> vec3f
2273
3225
  tbn = fragmentInputs.pbr_vTBN;
2274
3226
  #endif
2275
3227
 
3228
+ return tbn;
3229
+ }
3230
+
3231
+ // Find the normal for this fragment, pulling either from a predefined normal map
3232
+ // or from the interpolated mesh normal and tangent attributes.
3233
+ fn getMappedNormal(
3234
+ normalSampler: texture_2d<f32>,
3235
+ normalSamplerBinding: sampler,
3236
+ tbn: mat3x3f,
3237
+ normalScale: f32
3238
+ ) -> vec3f
3239
+ {
3240
+ let n = textureSample(normalSampler, normalSamplerBinding, fragmentInputs.pbr_vUV).rgb;
3241
+ return normalize(tbn * ((2.0 * n - 1.0) * vec3f(normalScale, normalScale, 1.0)));
3242
+ }
3243
+
3244
+ fn getNormal(tbn: mat3x3f) -> vec3f
3245
+ {
2276
3246
  // The tbn matrix is linearly interpolated, so we need to re-normalize
2277
3247
  var n: vec3f = normalize(tbn[2].xyz);
2278
3248
  #ifdef HAS_NORMALMAP
2279
- n = textureSample(pbr_normalSampler, pbr_normalSamplerSampler, fragmentInputs.pbr_vUV).rgb;
2280
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3f(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
3249
+ n = getMappedNormal(
3250
+ pbr_normalSampler,
3251
+ pbr_normalSamplerSampler,
3252
+ tbn,
3253
+ pbrMaterial.normalScale
3254
+ );
2281
3255
  #endif
2282
3256
 
2283
3257
  return n;
2284
3258
  }
2285
3259
 
3260
+ fn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f) -> vec3f
3261
+ {
3262
+ #ifdef HAS_CLEARCOATNORMALMAP
3263
+ return getMappedNormal(
3264
+ pbr_clearcoatNormalSampler,
3265
+ pbr_clearcoatNormalSamplerSampler,
3266
+ tbn,
3267
+ 1.0
3268
+ );
3269
+ #else
3270
+ return baseNormal;
3271
+ #endif
3272
+ }
3273
+
2286
3274
  // Calculation of the lighting contribution from an optional Image Based Light source.
2287
3275
  // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
2288
3276
  // See our README.md on Environment Maps [3] for additional discussion.
@@ -2293,17 +3281,25 @@ fn getIBLContribution(pbrInfo: PBRInfo, n: vec3f, reflection: vec3f) -> vec3f
2293
3281
  let lod: f32 = pbrInfo.perceptualRoughness * mipCount;
2294
3282
  // retrieve a scale and bias to F0. See [1], Figure 3
2295
3283
  let brdf = SRGBtoLINEAR(
2296
- textureSample(
2297
- pbr_BrdfLUT,
2298
- pbr_BrdfLUTSampler,
2299
- vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness)
3284
+ textureSampleLevel(
3285
+ pbr_brdfLUT,
3286
+ pbr_brdfLUTSampler,
3287
+ vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness),
3288
+ 0.0
2300
3289
  )
2301
3290
  ).rgb;
2302
3291
  let diffuseLight =
2303
- SRGBtoLINEAR(textureSample(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, n)).rgb;
2304
- let specularLightDefault =
2305
- SRGBtoLINEAR(textureSample(pbr_specularEnvSampler, pbr_specularEnvSamplerSampler, reflection)).rgb;
2306
- var specularLight = specularLightDefault;
3292
+ SRGBtoLINEAR(
3293
+ textureSampleLevel(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, n, 0.0)
3294
+ ).rgb;
3295
+ var specularLight = SRGBtoLINEAR(
3296
+ textureSampleLevel(
3297
+ pbr_specularEnvSampler,
3298
+ pbr_specularEnvSamplerSampler,
3299
+ reflection,
3300
+ 0.0
3301
+ )
3302
+ ).rgb;
2307
3303
  #ifdef USE_TEX_LOD
2308
3304
  specularLight = SRGBtoLINEAR(
2309
3305
  textureSampleLevel(
@@ -2364,6 +3360,172 @@ fn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {
2364
3360
  return roughnessSq / (M_PI * f * f);
2365
3361
  }
2366
3362
 
3363
+ fn maxComponent(value: vec3f) -> f32 {
3364
+ return max(max(value.r, value.g), value.b);
3365
+ }
3366
+
3367
+ fn getDielectricF0(ior: f32) -> f32 {
3368
+ let clampedIor = max(ior, 1.0);
3369
+ let ratio = (clampedIor - 1.0) / (clampedIor + 1.0);
3370
+ return ratio * ratio;
3371
+ }
3372
+
3373
+ fn normalizeDirection(direction: vec2f) -> vec2f {
3374
+ let directionLength = length(direction);
3375
+ if (directionLength > 0.0001) {
3376
+ return direction / directionLength;
3377
+ }
3378
+
3379
+ return vec2f(1.0, 0.0);
3380
+ }
3381
+
3382
+ fn rotateDirection(direction: vec2f, rotation: f32) -> vec2f {
3383
+ let s = sin(rotation);
3384
+ let c = cos(rotation);
3385
+ return vec2f(direction.x * c - direction.y * s, direction.x * s + direction.y * c);
3386
+ }
3387
+
3388
+ fn getIridescenceTint(iridescence: f32, thickness: f32, NdotV: f32) -> vec3f {
3389
+ if (iridescence <= 0.0) {
3390
+ return vec3f(1.0);
3391
+ }
3392
+
3393
+ let phase = 0.015 * thickness * pbrMaterial.iridescenceIor + (1.0 - NdotV) * 6.0;
3394
+ let thinFilmTint =
3395
+ 0.5 +
3396
+ 0.5 *
3397
+ cos(vec3f(phase, phase + 2.0943951, phase + 4.1887902));
3398
+ return mix(vec3f(1.0), thinFilmTint, iridescence);
3399
+ }
3400
+
3401
+ fn getVolumeAttenuation(thickness: f32) -> vec3f {
3402
+ if (thickness <= 0.0) {
3403
+ return vec3f(1.0);
3404
+ }
3405
+
3406
+ let attenuationCoefficient =
3407
+ -log(max(pbrMaterial.attenuationColor, vec3f(0.0001))) /
3408
+ max(pbrMaterial.attenuationDistance, 0.0001);
3409
+ return exp(-attenuationCoefficient * thickness);
3410
+ }
3411
+
3412
+ fn createClearcoatPBRInfo(
3413
+ basePBRInfo: PBRInfo,
3414
+ clearcoatNormal: vec3f,
3415
+ clearcoatRoughness: f32
3416
+ ) -> PBRInfo {
3417
+ let perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
3418
+ let alphaRoughness = perceptualRoughness * perceptualRoughness;
3419
+ let NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);
3420
+
3421
+ return PBRInfo(
3422
+ basePBRInfo.NdotL,
3423
+ NdotV,
3424
+ basePBRInfo.NdotH,
3425
+ basePBRInfo.LdotH,
3426
+ basePBRInfo.VdotH,
3427
+ perceptualRoughness,
3428
+ 0.0,
3429
+ vec3f(0.04),
3430
+ vec3f(1.0),
3431
+ alphaRoughness,
3432
+ vec3f(0.0),
3433
+ vec3f(0.04),
3434
+ clearcoatNormal,
3435
+ basePBRInfo.v
3436
+ );
3437
+ }
3438
+
3439
+ fn calculateClearcoatContribution(
3440
+ pbrInfo: PBRInfo,
3441
+ lightColor: vec3f,
3442
+ clearcoatNormal: vec3f,
3443
+ clearcoatFactor: f32,
3444
+ clearcoatRoughness: f32
3445
+ ) -> vec3f {
3446
+ if (clearcoatFactor <= 0.0) {
3447
+ return vec3f(0.0);
3448
+ }
3449
+
3450
+ let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
3451
+ return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;
3452
+ }
3453
+
3454
+ #ifdef USE_IBL
3455
+ fn calculateClearcoatIBLContribution(
3456
+ pbrInfo: PBRInfo,
3457
+ clearcoatNormal: vec3f,
3458
+ reflection: vec3f,
3459
+ clearcoatFactor: f32,
3460
+ clearcoatRoughness: f32
3461
+ ) -> vec3f {
3462
+ if (clearcoatFactor <= 0.0) {
3463
+ return vec3f(0.0);
3464
+ }
3465
+
3466
+ let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
3467
+ return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;
3468
+ }
3469
+ #endif
3470
+
3471
+ fn calculateSheenContribution(
3472
+ pbrInfo: PBRInfo,
3473
+ lightColor: vec3f,
3474
+ sheenColor: vec3f,
3475
+ sheenRoughness: f32
3476
+ ) -> vec3f {
3477
+ if (maxComponent(sheenColor) <= 0.0) {
3478
+ return vec3f(0.0);
3479
+ }
3480
+
3481
+ let sheenFresnel = pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
3482
+ let sheenVisibility = mix(1.0, pbrInfo.NdotL * pbrInfo.NdotV, sheenRoughness);
3483
+ return pbrInfo.NdotL *
3484
+ lightColor *
3485
+ sheenColor *
3486
+ (0.25 + 0.75 * sheenFresnel) *
3487
+ sheenVisibility *
3488
+ (1.0 - pbrInfo.metalness);
3489
+ }
3490
+
3491
+ fn calculateAnisotropyBoost(
3492
+ pbrInfo: PBRInfo,
3493
+ anisotropyTangent: vec3f,
3494
+ anisotropyStrength: f32
3495
+ ) -> f32 {
3496
+ if (anisotropyStrength <= 0.0) {
3497
+ return 1.0;
3498
+ }
3499
+
3500
+ let anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));
3501
+ let bitangentViewAlignment = abs(dot(pbrInfo.v, anisotropyBitangent));
3502
+ return mix(1.0, 0.65 + 0.7 * bitangentViewAlignment, anisotropyStrength);
3503
+ }
3504
+
3505
+ fn calculateMaterialLightColor(
3506
+ pbrInfo: PBRInfo,
3507
+ lightColor: vec3f,
3508
+ clearcoatNormal: vec3f,
3509
+ clearcoatFactor: f32,
3510
+ clearcoatRoughness: f32,
3511
+ sheenColor: vec3f,
3512
+ sheenRoughness: f32,
3513
+ anisotropyTangent: vec3f,
3514
+ anisotropyStrength: f32
3515
+ ) -> vec3f {
3516
+ let anisotropyBoost = calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
3517
+ var color = calculateFinalColor(pbrInfo, lightColor) * anisotropyBoost;
3518
+ color += calculateClearcoatContribution(
3519
+ pbrInfo,
3520
+ lightColor,
3521
+ clearcoatNormal,
3522
+ clearcoatFactor,
3523
+ clearcoatRoughness
3524
+ );
3525
+ color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);
3526
+ return color;
3527
+ }
3528
+
2367
3529
  fn PBRInfo_setAmbientLight(pbrInfo: ptr<function, PBRInfo>) {
2368
3530
  (*pbrInfo).NdotL = 1.0;
2369
3531
  (*pbrInfo).NdotH = 0.0;
@@ -2388,6 +3550,11 @@ fn PBRInfo_setPointLight(pbrInfo: ptr<function, PBRInfo>, pointLight: PointLight
2388
3550
  PBRInfo_setDirectionalLight(pbrInfo, light_direction);
2389
3551
  }
2390
3552
 
3553
+ fn PBRInfo_setSpotLight(pbrInfo: ptr<function, PBRInfo>, spotLight: SpotLight) {
3554
+ let light_direction = normalize(spotLight.position - fragmentInputs.pbr_vPosition);
3555
+ PBRInfo_setDirectionalLight(pbrInfo, light_direction);
3556
+ }
3557
+
2391
3558
  fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
2392
3559
  // Calculate the shading terms for the microfacet specular shading model
2393
3560
  let F = specularReflection(pbrInfo);
@@ -2417,6 +3584,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2417
3584
  #endif
2418
3585
 
2419
3586
  var color = vec3<f32>(0.0, 0.0, 0.0);
3587
+ var transmission = 0.0;
2420
3588
 
2421
3589
  if (pbrMaterial.unlit != 0u) {
2422
3590
  color = baseColor.rgb;
@@ -2439,14 +3607,308 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2439
3607
  #endif
2440
3608
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
2441
3609
  metallic = clamp(metallic, 0.0, 1.0);
3610
+ let tbn = getTBN();
3611
+ let n = getNormal(tbn); // normal at surface point
3612
+ let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera
3613
+ let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
3614
+ var useExtendedPBR = false;
3615
+ #ifdef USE_MATERIAL_EXTENSIONS
3616
+ useExtendedPBR =
3617
+ pbrMaterial.specularColorMapEnabled != 0 ||
3618
+ pbrMaterial.specularIntensityMapEnabled != 0 ||
3619
+ abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||
3620
+ maxComponent(abs(pbrMaterial.specularColorFactor - vec3f(1.0))) > 0.0001 ||
3621
+ abs(pbrMaterial.ior - 1.5) > 0.0001 ||
3622
+ pbrMaterial.transmissionMapEnabled != 0 ||
3623
+ pbrMaterial.transmissionFactor > 0.0001 ||
3624
+ pbrMaterial.clearcoatMapEnabled != 0 ||
3625
+ pbrMaterial.clearcoatRoughnessMapEnabled != 0 ||
3626
+ pbrMaterial.clearcoatFactor > 0.0001 ||
3627
+ pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||
3628
+ pbrMaterial.sheenColorMapEnabled != 0 ||
3629
+ pbrMaterial.sheenRoughnessMapEnabled != 0 ||
3630
+ maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||
3631
+ pbrMaterial.sheenRoughnessFactor > 0.0001 ||
3632
+ pbrMaterial.iridescenceMapEnabled != 0 ||
3633
+ pbrMaterial.iridescenceFactor > 0.0001 ||
3634
+ abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||
3635
+ abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||
3636
+ abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||
3637
+ pbrMaterial.anisotropyMapEnabled != 0 ||
3638
+ pbrMaterial.anisotropyStrength > 0.0001 ||
3639
+ abs(pbrMaterial.anisotropyRotation) > 0.0001 ||
3640
+ length(pbrMaterial.anisotropyDirection - vec2f(1.0, 0.0)) > 0.0001;
3641
+ #endif
3642
+
3643
+ if (!useExtendedPBR) {
3644
+ let alphaRoughness = perceptualRoughness * perceptualRoughness;
3645
+
3646
+ let f0 = vec3<f32>(0.04);
3647
+ var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);
3648
+ diffuseColor *= 1.0 - metallic;
3649
+ let specularColor = mix(f0, baseColor.rgb, metallic);
3650
+
3651
+ let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
3652
+ let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
3653
+ let specularEnvironmentR0 = specularColor;
3654
+ let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;
3655
+ let reflection = -normalize(reflect(v, n));
3656
+
3657
+ var pbrInfo = PBRInfo(
3658
+ 0.0, // NdotL
3659
+ NdotV,
3660
+ 0.0, // NdotH
3661
+ 0.0, // LdotH
3662
+ 0.0, // VdotH
3663
+ perceptualRoughness,
3664
+ metallic,
3665
+ specularEnvironmentR0,
3666
+ specularEnvironmentR90,
3667
+ alphaRoughness,
3668
+ diffuseColor,
3669
+ specularColor,
3670
+ n,
3671
+ v
3672
+ );
3673
+
3674
+ #ifdef USE_LIGHTS
3675
+ PBRInfo_setAmbientLight(&pbrInfo);
3676
+ color += calculateFinalColor(pbrInfo, lighting.ambientColor);
3677
+
3678
+ for (var i = 0; i < lighting.directionalLightCount; i++) {
3679
+ if (i < lighting.directionalLightCount) {
3680
+ PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
3681
+ color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
3682
+ }
3683
+ }
3684
+
3685
+ for (var i = 0; i < lighting.pointLightCount; i++) {
3686
+ if (i < lighting.pointLightCount) {
3687
+ PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));
3688
+ let attenuation = getPointLightAttenuation(
3689
+ lighting_getPointLight(i),
3690
+ distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
3691
+ );
3692
+ color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
3693
+ }
3694
+ }
3695
+
3696
+ for (var i = 0; i < lighting.spotLightCount; i++) {
3697
+ if (i < lighting.spotLightCount) {
3698
+ PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));
3699
+ let attenuation = getSpotLightAttenuation(
3700
+ lighting_getSpotLight(i),
3701
+ fragmentInputs.pbr_vPosition
3702
+ );
3703
+ color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color / attenuation);
3704
+ }
3705
+ }
3706
+ #endif
3707
+
3708
+ #ifdef USE_IBL
3709
+ if (pbrMaterial.IBLenabled != 0) {
3710
+ color += getIBLContribution(pbrInfo, n, reflection);
3711
+ }
3712
+ #endif
3713
+
3714
+ #ifdef HAS_OCCLUSIONMAP
3715
+ if (pbrMaterial.occlusionMapEnabled != 0) {
3716
+ let ao =
3717
+ textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, fragmentInputs.pbr_vUV).r;
3718
+ color = mix(color, color * ao, pbrMaterial.occlusionStrength);
3719
+ }
3720
+ #endif
3721
+
3722
+ var emissive = pbrMaterial.emissiveFactor;
3723
+ #ifdef HAS_EMISSIVEMAP
3724
+ if (pbrMaterial.emissiveMapEnabled != 0u) {
3725
+ emissive *= SRGBtoLINEAR(
3726
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
3727
+ ).rgb;
3728
+ }
3729
+ #endif
3730
+ color += emissive * pbrMaterial.emissiveStrength;
3731
+
3732
+ #ifdef PBR_DEBUG
3733
+ color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
3734
+ color = mix(color, vec3<f32>(metallic), pbrMaterial.scaleDiffBaseMR.z);
3735
+ color = mix(color, vec3<f32>(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
3736
+ #endif
3737
+
3738
+ return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), baseColor.a);
3739
+ }
3740
+
3741
+ var specularIntensity = pbrMaterial.specularIntensityFactor;
3742
+ #ifdef HAS_SPECULARINTENSITYMAP
3743
+ if (pbrMaterial.specularIntensityMapEnabled != 0) {
3744
+ specularIntensity *= textureSample(
3745
+ pbr_specularIntensitySampler,
3746
+ pbr_specularIntensitySamplerSampler,
3747
+ fragmentInputs.pbr_vUV
3748
+ ).a;
3749
+ }
3750
+ #endif
3751
+
3752
+ var specularFactor = pbrMaterial.specularColorFactor;
3753
+ #ifdef HAS_SPECULARCOLORMAP
3754
+ if (pbrMaterial.specularColorMapEnabled != 0) {
3755
+ specularFactor *= SRGBtoLINEAR(
3756
+ textureSample(
3757
+ pbr_specularColorSampler,
3758
+ pbr_specularColorSamplerSampler,
3759
+ fragmentInputs.pbr_vUV
3760
+ )
3761
+ ).rgb;
3762
+ }
3763
+ #endif
3764
+
3765
+ transmission = pbrMaterial.transmissionFactor;
3766
+ #ifdef HAS_TRANSMISSIONMAP
3767
+ if (pbrMaterial.transmissionMapEnabled != 0) {
3768
+ transmission *= textureSample(
3769
+ pbr_transmissionSampler,
3770
+ pbr_transmissionSamplerSampler,
3771
+ fragmentInputs.pbr_vUV
3772
+ ).r;
3773
+ }
3774
+ #endif
3775
+ transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);
3776
+ var thickness = max(pbrMaterial.thicknessFactor, 0.0);
3777
+ #ifdef HAS_THICKNESSMAP
3778
+ thickness *= textureSample(
3779
+ pbr_thicknessSampler,
3780
+ pbr_thicknessSamplerSampler,
3781
+ fragmentInputs.pbr_vUV
3782
+ ).g;
3783
+ #endif
3784
+
3785
+ var clearcoatFactor = pbrMaterial.clearcoatFactor;
3786
+ var clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;
3787
+ #ifdef HAS_CLEARCOATMAP
3788
+ if (pbrMaterial.clearcoatMapEnabled != 0) {
3789
+ clearcoatFactor *= textureSample(
3790
+ pbr_clearcoatSampler,
3791
+ pbr_clearcoatSamplerSampler,
3792
+ fragmentInputs.pbr_vUV
3793
+ ).r;
3794
+ }
3795
+ #endif
3796
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
3797
+ if (pbrMaterial.clearcoatRoughnessMapEnabled != 0) {
3798
+ clearcoatRoughness *= textureSample(
3799
+ pbr_clearcoatRoughnessSampler,
3800
+ pbr_clearcoatRoughnessSamplerSampler,
3801
+ fragmentInputs.pbr_vUV
3802
+ ).g;
3803
+ }
3804
+ #endif
3805
+ clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
3806
+ clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
3807
+ let clearcoatNormal = getClearcoatNormal(tbn, n);
3808
+
3809
+ var sheenColor = pbrMaterial.sheenColorFactor;
3810
+ var sheenRoughness = pbrMaterial.sheenRoughnessFactor;
3811
+ #ifdef HAS_SHEENCOLORMAP
3812
+ if (pbrMaterial.sheenColorMapEnabled != 0) {
3813
+ sheenColor *= SRGBtoLINEAR(
3814
+ textureSample(
3815
+ pbr_sheenColorSampler,
3816
+ pbr_sheenColorSamplerSampler,
3817
+ fragmentInputs.pbr_vUV
3818
+ )
3819
+ ).rgb;
3820
+ }
3821
+ #endif
3822
+ #ifdef HAS_SHEENROUGHNESSMAP
3823
+ if (pbrMaterial.sheenRoughnessMapEnabled != 0) {
3824
+ sheenRoughness *= textureSample(
3825
+ pbr_sheenRoughnessSampler,
3826
+ pbr_sheenRoughnessSamplerSampler,
3827
+ fragmentInputs.pbr_vUV
3828
+ ).a;
3829
+ }
3830
+ #endif
3831
+ sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);
3832
+
3833
+ var iridescence = pbrMaterial.iridescenceFactor;
3834
+ #ifdef HAS_IRIDESCENCEMAP
3835
+ if (pbrMaterial.iridescenceMapEnabled != 0) {
3836
+ iridescence *= textureSample(
3837
+ pbr_iridescenceSampler,
3838
+ pbr_iridescenceSamplerSampler,
3839
+ fragmentInputs.pbr_vUV
3840
+ ).r;
3841
+ }
3842
+ #endif
3843
+ iridescence = clamp(iridescence, 0.0, 1.0);
3844
+ var iridescenceThickness = mix(
3845
+ pbrMaterial.iridescenceThicknessRange.x,
3846
+ pbrMaterial.iridescenceThicknessRange.y,
3847
+ 0.5
3848
+ );
3849
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
3850
+ iridescenceThickness = mix(
3851
+ pbrMaterial.iridescenceThicknessRange.x,
3852
+ pbrMaterial.iridescenceThicknessRange.y,
3853
+ textureSample(
3854
+ pbr_iridescenceThicknessSampler,
3855
+ pbr_iridescenceThicknessSamplerSampler,
3856
+ fragmentInputs.pbr_vUV
3857
+ ).g
3858
+ );
3859
+ #endif
3860
+
3861
+ var anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);
3862
+ var anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);
3863
+ #ifdef HAS_ANISOTROPYMAP
3864
+ if (pbrMaterial.anisotropyMapEnabled != 0) {
3865
+ let anisotropySample = textureSample(
3866
+ pbr_anisotropySampler,
3867
+ pbr_anisotropySamplerSampler,
3868
+ fragmentInputs.pbr_vUV
3869
+ ).rgb;
3870
+ anisotropyStrength *= anisotropySample.b;
3871
+ let mappedDirection = anisotropySample.rg * 2.0 - 1.0;
3872
+ if (length(mappedDirection) > 0.0001) {
3873
+ anisotropyDirection = normalize(mappedDirection);
3874
+ }
3875
+ }
3876
+ #endif
3877
+ anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);
3878
+ var anisotropyTangent =
3879
+ normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);
3880
+ if (length(anisotropyTangent) < 0.0001) {
3881
+ anisotropyTangent = normalize(tbn[0]);
3882
+ }
3883
+ let anisotropyViewAlignment = abs(dot(v, anisotropyTangent));
3884
+ perceptualRoughness = mix(
3885
+ perceptualRoughness,
3886
+ clamp(perceptualRoughness * (1.0 - 0.6 * anisotropyViewAlignment), c_MinRoughness, 1.0),
3887
+ anisotropyStrength
3888
+ );
3889
+
2442
3890
  // Roughness is authored as perceptual roughness; as is convention,
2443
3891
  // convert to material roughness by squaring the perceptual roughness [2].
2444
3892
  let alphaRoughness = perceptualRoughness * perceptualRoughness;
2445
3893
 
2446
- let f0 = vec3<f32>(0.04);
2447
- var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);
2448
- diffuseColor *= 1.0 - metallic;
2449
- let specularColor = mix(f0, baseColor.rgb, metallic);
3894
+ let dielectricF0 = getDielectricF0(pbrMaterial.ior);
3895
+ var dielectricSpecularF0 = min(
3896
+ vec3f(dielectricF0) * specularFactor * specularIntensity,
3897
+ vec3f(1.0)
3898
+ );
3899
+ let iridescenceTint = getIridescenceTint(iridescence, iridescenceThickness, NdotV);
3900
+ dielectricSpecularF0 = mix(
3901
+ dielectricSpecularF0,
3902
+ dielectricSpecularF0 * iridescenceTint,
3903
+ iridescence
3904
+ );
3905
+ var diffuseColor = baseColor.rgb * (vec3f(1.0) - dielectricSpecularF0);
3906
+ diffuseColor *= (1.0 - metallic) * (1.0 - transmission);
3907
+ var specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);
3908
+
3909
+ let baseLayerEnergy = 1.0 - clearcoatFactor * 0.25;
3910
+ diffuseColor *= baseLayerEnergy;
3911
+ specularColor *= baseLayerEnergy;
2450
3912
 
2451
3913
  // Compute reflectance.
2452
3914
  let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
@@ -2458,11 +3920,6 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2458
3920
  let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
2459
3921
  let specularEnvironmentR0 = specularColor;
2460
3922
  let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;
2461
-
2462
- let n = getNormal(); // normal at surface point
2463
- let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera
2464
-
2465
- let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
2466
3923
  let reflection = -normalize(reflect(v, n));
2467
3924
 
2468
3925
  var pbrInfo = PBRInfo(
@@ -2485,13 +3942,33 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2485
3942
  #ifdef USE_LIGHTS
2486
3943
  // Apply ambient light
2487
3944
  PBRInfo_setAmbientLight(&pbrInfo);
2488
- color += calculateFinalColor(pbrInfo, lighting.ambientColor);
3945
+ color += calculateMaterialLightColor(
3946
+ pbrInfo,
3947
+ lighting.ambientColor,
3948
+ clearcoatNormal,
3949
+ clearcoatFactor,
3950
+ clearcoatRoughness,
3951
+ sheenColor,
3952
+ sheenRoughness,
3953
+ anisotropyTangent,
3954
+ anisotropyStrength
3955
+ );
2489
3956
 
2490
3957
  // Apply directional light
2491
3958
  for (var i = 0; i < lighting.directionalLightCount; i++) {
2492
3959
  if (i < lighting.directionalLightCount) {
2493
3960
  PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
2494
- color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
3961
+ color += calculateMaterialLightColor(
3962
+ pbrInfo,
3963
+ lighting_getDirectionalLight(i).color,
3964
+ clearcoatNormal,
3965
+ clearcoatFactor,
3966
+ clearcoatRoughness,
3967
+ sheenColor,
3968
+ sheenRoughness,
3969
+ anisotropyTangent,
3970
+ anisotropyStrength
3971
+ );
2495
3972
  }
2496
3973
  }
2497
3974
 
@@ -2503,7 +3980,35 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2503
3980
  lighting_getPointLight(i),
2504
3981
  distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
2505
3982
  );
2506
- color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
3983
+ color += calculateMaterialLightColor(
3984
+ pbrInfo,
3985
+ lighting_getPointLight(i).color / attenuation,
3986
+ clearcoatNormal,
3987
+ clearcoatFactor,
3988
+ clearcoatRoughness,
3989
+ sheenColor,
3990
+ sheenRoughness,
3991
+ anisotropyTangent,
3992
+ anisotropyStrength
3993
+ );
3994
+ }
3995
+ }
3996
+
3997
+ for (var i = 0; i < lighting.spotLightCount; i++) {
3998
+ if (i < lighting.spotLightCount) {
3999
+ PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));
4000
+ let attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), fragmentInputs.pbr_vPosition);
4001
+ color += calculateMaterialLightColor(
4002
+ pbrInfo,
4003
+ lighting_getSpotLight(i).color / attenuation,
4004
+ clearcoatNormal,
4005
+ clearcoatFactor,
4006
+ clearcoatRoughness,
4007
+ sheenColor,
4008
+ sheenRoughness,
4009
+ anisotropyTangent,
4010
+ anisotropyStrength
4011
+ );
2507
4012
  }
2508
4013
  }
2509
4014
  #endif
@@ -2511,7 +4016,16 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2511
4016
  // Calculate lighting contribution from image based lighting source (IBL)
2512
4017
  #ifdef USE_IBL
2513
4018
  if (pbrMaterial.IBLenabled != 0) {
2514
- color += getIBLContribution(pbrInfo, n, reflection);
4019
+ color += getIBLContribution(pbrInfo, n, reflection) *
4020
+ calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
4021
+ color += calculateClearcoatIBLContribution(
4022
+ pbrInfo,
4023
+ clearcoatNormal,
4024
+ -normalize(reflect(v, clearcoatNormal)),
4025
+ clearcoatFactor,
4026
+ clearcoatRoughness
4027
+ );
4028
+ color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;
2515
4029
  }
2516
4030
  #endif
2517
4031
 
@@ -2524,14 +4038,19 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2524
4038
  }
2525
4039
  #endif
2526
4040
 
4041
+ var emissive = pbrMaterial.emissiveFactor;
2527
4042
  #ifdef HAS_EMISSIVEMAP
2528
4043
  if (pbrMaterial.emissiveMapEnabled != 0u) {
2529
- let emissive = SRGBtoLINEAR(
4044
+ emissive *= SRGBtoLINEAR(
2530
4045
  textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
2531
- ).rgb * pbrMaterial.emissiveFactor;
2532
- color += emissive;
4046
+ ).rgb;
2533
4047
  }
2534
4048
  #endif
4049
+ color += emissive * pbrMaterial.emissiveStrength;
4050
+
4051
+ if (transmission > 0.0) {
4052
+ color = mix(color, color * getVolumeAttenuation(thickness), transmission);
4053
+ }
2535
4054
 
2536
4055
  // This section uses mix to override final color for reference app visualization
2537
4056
  // of various parameters in the lighting equation.
@@ -2550,22 +4069,23 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2550
4069
  #endif
2551
4070
  }
2552
4071
 
2553
- return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), baseColor.a);
4072
+ let alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);
4073
+ return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), alpha);
2554
4074
  }
2555
- `;var tn=`uniform pbrProjectionUniforms {
4075
+ `;var In=`uniform pbrProjectionUniforms {
2556
4076
  mat4 modelViewProjectionMatrix;
2557
4077
  mat4 modelMatrix;
2558
4078
  mat4 normalMatrix;
2559
4079
  vec3 camera;
2560
4080
  } pbrProjection;
2561
- `,bi=`struct pbrProjectionUniforms {
4081
+ `,uo=`struct pbrProjectionUniforms {
2562
4082
  modelViewProjectionMatrix: mat4x4<f32>,
2563
4083
  modelMatrix: mat4x4<f32>,
2564
4084
  normalMatrix: mat4x4<f32>,
2565
4085
  camera: vec3<f32>
2566
4086
  };
2567
4087
 
2568
- @binding(0) @group(0) var<uniform> pbrProjection: pbrProjectionUniforms;
2569
- `,nn={name:"pbrProjection",source:bi,vs:tn,fs:tn,getUniforms:e=>e,uniformTypes:{modelViewProjectionMatrix:"mat4x4<f32>",modelMatrix:"mat4x4<f32>",normalMatrix:"mat4x4<f32>",camera:"vec3<f32>"}};var rn={props:{},uniforms:{},name:"pbrMaterial",dependencies:[y,nn],source:en,vs:Jt,fs:Qt,defines:{LIGHTING_FRAGMENT:!0,HAS_NORMALMAP:!1,HAS_EMISSIVEMAP:!1,HAS_OCCLUSIONMAP:!1,HAS_BASECOLORMAP:!1,HAS_METALROUGHNESSMAP:!1,HAS_SPECULARCOLORMAP:!1,HAS_SPECULARINTENSITYMAP:!1,HAS_TRANSMISSIONMAP:!1,HAS_CLEARCOATMAP:!1,HAS_SHEENCOLORMAP:!1,HAS_IRIDESCENCEMAP:!1,HAS_ANISOTROPYMAP:!1,ALPHA_CUTOFF:!1,USE_IBL:!1,PBR_DEBUG:!1},getUniforms:e=>e,uniformTypes:{unlit:"i32",baseColorMapEnabled:"i32",baseColorFactor:"vec4<f32>",normalMapEnabled:"i32",normalScale:"f32",emissiveMapEnabled:"i32",emissiveFactor:"vec3<f32>",metallicRoughnessValues:"vec2<f32>",metallicRoughnessMapEnabled:"i32",occlusionMapEnabled:"i32",occlusionStrength:"f32",alphaCutoffEnabled:"i32",alphaCutoff:"f32",IBLenabled:"i32",scaleIBLAmbient:"vec2<f32>",scaleDiffBaseMR:"vec4<f32>",scaleFGDSpec:"vec4<f32>",specularColorFactor:"vec3<f32>",specularIntensityFactor:"f32",specularColorMapEnabled:"i32",specularIntensityMapEnabled:"i32",ior:"f32",transmissionFactor:"f32",transmissionMapEnabled:"i32",thicknessFactor:"f32",attenuationDistance:"f32",attenuationColor:"vec3<f32>",clearcoatFactor:"f32",clearcoatRoughnessFactor:"f32",clearcoatMapEnabled:"i32",sheenColorFactor:"vec3<f32>",sheenRoughnessFactor:"f32",sheenColorMapEnabled:"i32",iridescenceFactor:"f32",iridescenceIor:"f32",iridescenceThicknessRange:"vec2<f32>",iridescenceMapEnabled:"i32",anisotropyStrength:"f32",anisotropyRotation:"f32",anisotropyDirection:"vec2<f32>",anisotropyMapEnabled:"i32",emissiveStrength:"f32"}};return gn(te);})();
4088
+ @group(0) @binding(auto) var<uniform> pbrProjection: pbrProjectionUniforms;
4089
+ `,Cn={name:"pbrProjection",bindingLayout:[{name:"pbrProjection",group:0}],source:uo,vs:In,fs:In,getUniforms:e=>e,uniformTypes:{modelViewProjectionMatrix:"mat4x4<f32>",modelMatrix:"mat4x4<f32>",normalMatrix:"mat4x4<f32>",camera:"vec3<f32>"}};var Pn={props:{},uniforms:{},defaultUniforms:{unlit:!1,baseColorMapEnabled:!1,baseColorFactor:[1,1,1,1],normalMapEnabled:!1,normalScale:1,emissiveMapEnabled:!1,emissiveFactor:[0,0,0],metallicRoughnessValues:[1,1],metallicRoughnessMapEnabled:!1,occlusionMapEnabled:!1,occlusionStrength:1,alphaCutoffEnabled:!1,alphaCutoff:.5,IBLenabled:!1,scaleIBLAmbient:[1,1],scaleDiffBaseMR:[0,0,0,0],scaleFGDSpec:[0,0,0,0],specularColorFactor:[1,1,1],specularIntensityFactor:1,specularColorMapEnabled:!1,specularIntensityMapEnabled:!1,ior:1.5,transmissionFactor:0,transmissionMapEnabled:!1,thicknessFactor:0,attenuationDistance:1e9,attenuationColor:[1,1,1],clearcoatFactor:0,clearcoatRoughnessFactor:0,clearcoatMapEnabled:!1,clearcoatRoughnessMapEnabled:!1,sheenColorFactor:[0,0,0],sheenRoughnessFactor:0,sheenColorMapEnabled:!1,sheenRoughnessMapEnabled:!1,iridescenceFactor:0,iridescenceIor:1.3,iridescenceThicknessRange:[100,400],iridescenceMapEnabled:!1,anisotropyStrength:0,anisotropyRotation:0,anisotropyDirection:[1,0],anisotropyMapEnabled:!1,emissiveStrength:1},name:"pbrMaterial",firstBindingSlot:0,bindingLayout:[{name:"pbrMaterial",group:3},{name:"pbr_baseColorSampler",group:3},{name:"pbr_normalSampler",group:3},{name:"pbr_emissiveSampler",group:3},{name:"pbr_metallicRoughnessSampler",group:3},{name:"pbr_occlusionSampler",group:3},{name:"pbr_specularColorSampler",group:3},{name:"pbr_specularIntensitySampler",group:3},{name:"pbr_transmissionSampler",group:3},{name:"pbr_thicknessSampler",group:3},{name:"pbr_clearcoatSampler",group:3},{name:"pbr_clearcoatRoughnessSampler",group:3},{name:"pbr_clearcoatNormalSampler",group:3},{name:"pbr_sheenColorSampler",group:3},{name:"pbr_sheenRoughnessSampler",group:3},{name:"pbr_iridescenceSampler",group:3},{name:"pbr_iridescenceThicknessSampler",group:3},{name:"pbr_anisotropySampler",group:3}],dependencies:[F,Le,Cn],source:Rn,vs:An,fs:En,defines:{LIGHTING_FRAGMENT:!0,HAS_NORMALMAP:!1,HAS_EMISSIVEMAP:!1,HAS_OCCLUSIONMAP:!1,HAS_BASECOLORMAP:!1,HAS_METALROUGHNESSMAP:!1,HAS_SPECULARCOLORMAP:!1,HAS_SPECULARINTENSITYMAP:!1,HAS_TRANSMISSIONMAP:!1,HAS_THICKNESSMAP:!1,HAS_CLEARCOATMAP:!1,HAS_CLEARCOATROUGHNESSMAP:!1,HAS_CLEARCOATNORMALMAP:!1,HAS_SHEENCOLORMAP:!1,HAS_SHEENROUGHNESSMAP:!1,HAS_IRIDESCENCEMAP:!1,HAS_IRIDESCENCETHICKNESSMAP:!1,HAS_ANISOTROPYMAP:!1,USE_MATERIAL_EXTENSIONS:!1,ALPHA_CUTOFF:!1,USE_IBL:!1,PBR_DEBUG:!1},getUniforms:e=>e,uniformTypes:{unlit:"i32",baseColorMapEnabled:"i32",baseColorFactor:"vec4<f32>",normalMapEnabled:"i32",normalScale:"f32",emissiveMapEnabled:"i32",emissiveFactor:"vec3<f32>",metallicRoughnessValues:"vec2<f32>",metallicRoughnessMapEnabled:"i32",occlusionMapEnabled:"i32",occlusionStrength:"f32",alphaCutoffEnabled:"i32",alphaCutoff:"f32",specularColorFactor:"vec3<f32>",specularIntensityFactor:"f32",specularColorMapEnabled:"i32",specularIntensityMapEnabled:"i32",ior:"f32",transmissionFactor:"f32",transmissionMapEnabled:"i32",thicknessFactor:"f32",attenuationDistance:"f32",attenuationColor:"vec3<f32>",clearcoatFactor:"f32",clearcoatRoughnessFactor:"f32",clearcoatMapEnabled:"i32",clearcoatRoughnessMapEnabled:"i32",sheenColorFactor:"vec3<f32>",sheenRoughnessFactor:"f32",sheenColorMapEnabled:"i32",sheenRoughnessMapEnabled:"i32",iridescenceFactor:"f32",iridescenceIor:"f32",iridescenceThicknessRange:"vec2<f32>",iridescenceMapEnabled:"i32",anisotropyStrength:"f32",anisotropyRotation:"f32",anisotropyDirection:"vec2<f32>",anisotropyMapEnabled:"i32",emissiveStrength:"f32",IBLenabled:"i32",scaleIBLAmbient:"vec2<f32>",scaleDiffBaseMR:"vec4<f32>",scaleFGDSpec:"vec4<f32>"}};return Dn(ne);})();
2570
4090
  return __exports__;
2571
4091
  });