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

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 (157) hide show
  1. package/dist/dist.dev.js +4657 -523
  2. package/dist/dist.min.js +1952 -301
  3. package/dist/index.cjs +2804 -406
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +10 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +4 -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 +35 -8
  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 +20 -3
  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 +112 -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 +12 -6
  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 +30 -0
  43. package/dist/modules/engine/skin/skin.d.ts.map +1 -0
  44. package/dist/modules/engine/skin/skin.js +86 -0
  45. package/dist/modules/engine/skin/skin.js.map +1 -0
  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 -37
  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 +46 -18
  73. package/dist/modules/lighting/lights/lighting-wgsl.js.map +1 -1
  74. package/dist/modules/lighting/lights/lighting.d.ts +104 -62
  75. package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
  76. package/dist/modules/lighting/lights/lighting.js +107 -68
  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 +784 -101
  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 -45
  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 +13 -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 -40
  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 +71 -76
  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/dist/modules/math/random/random.d.ts +1 -1
  122. package/dist/modules/math/random/random.d.ts.map +1 -1
  123. package/dist/modules/math/random/random.js +2 -3
  124. package/dist/modules/math/random/random.js.map +1 -1
  125. package/package.json +3 -3
  126. package/src/index.ts +20 -2
  127. package/src/lib/preprocessor/preprocessor.ts +44 -8
  128. package/src/lib/shader-assembler.ts +25 -3
  129. package/src/lib/shader-assembly/assemble-shaders.ts +377 -12
  130. package/src/lib/shader-assembly/wgsl-binding-debug.ts +216 -0
  131. package/src/lib/shader-generator/glsl/generate-glsl.ts +7 -1
  132. package/src/lib/shader-generator/wgsl/generate-wgsl.ts +6 -0
  133. package/src/lib/shader-module/shader-module-uniform-layout.ts +194 -0
  134. package/src/lib/shader-module/shader-module.ts +17 -7
  135. package/src/lib/utils/uniform-types.ts +24 -9
  136. package/src/modules/engine/picking/picking.ts +3 -0
  137. package/src/modules/engine/skin/skin.ts +114 -0
  138. package/src/modules/lighting/gouraud-material/gouraud-material.ts +4 -0
  139. package/src/modules/lighting/ibl/ibl.ts +44 -0
  140. package/src/modules/lighting/lambert-material/lambert-material.ts +42 -0
  141. package/src/modules/lighting/lambert-material/lambert-shaders-glsl.ts +61 -0
  142. package/src/modules/lighting/lambert-material/lambert-shaders-wgsl.ts +73 -0
  143. package/src/modules/lighting/lights/lighting-glsl.ts +43 -37
  144. package/src/modules/lighting/lights/lighting-wgsl.ts +46 -18
  145. package/src/modules/lighting/lights/lighting.ts +198 -99
  146. package/src/modules/lighting/no-material/dirlight.ts +3 -1
  147. package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +524 -28
  148. package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +784 -101
  149. package/src/modules/lighting/pbr-material/pbr-material.ts +111 -18
  150. package/src/modules/lighting/pbr-material/pbr-projection.ts +14 -1
  151. package/src/modules/lighting/phong-material/phong-material.ts +5 -0
  152. package/src/modules/lighting/phong-material/phong-shaders-glsl.ts +15 -4
  153. package/src/modules/lighting/phong-material/phong-shaders-wgsl.ts +71 -77
  154. package/src/modules/math/fp64/fp64-arithmetic-glsl.ts +41 -10
  155. package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +212 -0
  156. package/src/modules/math/fp64/fp64.ts +9 -3
  157. package/src/modules/math/random/random.ts +2 -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 pt=Object.create;var O=Object.defineProperty;var _t=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var gt=Object.getPrototypeOf,dt=Object.prototype.hasOwnProperty;var ht=(e,t,o)=>t in e?O(e,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[t]=o;var vt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),bt=(e,t)=>{for(var o in t)O(e,o,{get:t[o],enumerable:!0})},z=(e,t,o,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of mt(t))!dt.call(e,n)&&n!==o&&O(e,n,{get:()=>t[n],enumerable:!(i=_t(t,n))||i.enumerable});return e},q=(e,t,o)=>(z(e,t,"default"),o&&z(o,t,"default")),de=(e,t,o)=>(o=e!=null?pt(gt(e)):{},z(t||!e||!e.__esModule?O(o,"default",{value:e,enumerable:!0}):o,e)),At=e=>z(O({},"__esModule",{value:!0}),e);var he=(e,t,o)=>(ht(e,typeof t!="symbol"?t+"":t,o),o);var te=vt((fo,ve)=>{ve.exports=globalThis.luma});var H={};bt(H,{ShaderAssembler:()=>w,_getDependencyGraph:()=>D,_resolveModules:()=>Ne,assembleGLSLShaderPair:()=>K,capitalize:()=>E,checkShaderModuleDeprecations:()=>F,combineInjects:()=>Ce,convertToVec4:()=>le,dirlight:()=>pe,fp32:()=>Qe,fp64:()=>ot,fp64LowPart:()=>B,fp64arithmetic:()=>ce,fp64ify:()=>R,fp64ifyMatrix4:()=>U,fromHalfFloat:()=>Ye,generateShaderForModule:()=>ze,getPassthroughFS:()=>ke,getQualifierDetails:()=>Ue,getShaderInfo:()=>$,getShaderModuleDependencies:()=>y,getShaderModuleSource:()=>X,getShaderModuleUniforms:()=>Re,gouraudMaterial:()=>_e,initializeShaderModule:()=>W,initializeShaderModules:()=>v,lighting:()=>g,pbrMaterial:()=>ut,phongMaterial:()=>me,picking:()=>it,preprocess:()=>Y,random:()=>Ze,toHalfFloat:()=>Xe,typeToChannelCount:()=>Ge,typeToChannelSuffix:()=>He});q(H,de(te(),1));function b(e,t){if(!e){let o=new Error(t||"shadertools: assertion failed.");throw Error.captureStackTrace?.(o,b),o}}var oe={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 Ae(e){let t={};for(let[o,i]of Object.entries(e))t[o]=St(i);return t}function Se(e,t,o){let i={};for(let[n,r]of Object.entries(t))e&&n in e&&!r.private?(r.validate&&b(r.validate(e[n],r),`${o}: invalid ${n}`),i[n]=e[n]):i[n]=r.value;return i}function St(e){let t=be(e);if(t!=="object")return{value:e,...oe[t],type:t};if(typeof e=="object")return e?e.type!==void 0?{...e,...oe[e.type],type:e.type}:e.value===void 0?{type:"object",value:e}:(t=be(e.value),{...e,...oe[t],type:t}):{type:"object",value:null};throw new Error("props")}function be(e){return Array.isArray(e)||ArrayBuffer.isView(e)?"array":typeof e}var Ie=`#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((go,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
- `,Le=`#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 It={vertex:Ie,fragment:Le},Ee=/void\s+main\s*\([^)]*\)\s*\{\n?/,xe=/}\n?[^{}]*$/,ie=[],M="__LUMA_INJECT_DECLARATIONS__";function Pe(e){let t={vertex:{},fragment:{}};for(let o in e){let i=e[o],n=Lt(o);typeof i=="string"&&(i={order:0,injection:i}),t[n][o]=i}return t}function Lt(e){let t=e.slice(0,2);switch(t){case"vs":return"vertex";case"fs":return"fragment";default:throw new Error(t)}}function T(e,t,o,i=!1){let n=t==="vertex";for(let r in o){let a=o[r];a.sort((l,f)=>l.order-f.order),ie.length=a.length;for(let l=0,f=a.length;l<f;++l)ie[l]=a[l].injection;let s=`${ie.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(r){case"vs:#decl":n&&(e=e.replace(M,s));break;case"vs:#main-start":n&&(e=e.replace(Ee,l=>l+s));break;case"vs:#main-end":n&&(e=e.replace(xe,l=>s+l));break;case"fs:#decl":n||(e=e.replace(M,s));break;case"fs:#main-start":n||(e=e.replace(Ee,l=>l+s));break;case"fs:#main-end":n||(e=e.replace(xe,l=>s+l));break;default:e=e.replace(r,l=>l+s)}}return e=e.replace(M,""),i&&(e=e.replace(/\}\s*$/,r=>r+It[t])),e}function Ce(e){let t={};return b(Array.isArray(e)&&e.length>1),e.forEach(o=>{for(let i in o)t[i]=t[i]?`${t[i]}
33
- ${o[i]}`:o[i]}),t}function v(e){e.map(t=>W(t))}function W(e){if(e.instance)return;v(e.dependencies||[]);let{propTypes:t={},deprecations:o=[],inject:i={}}=e,n={normalizedInjections:Pe(i),parsedDeprecations:Et(o)};t&&(n.propValidators=Ae(t)),e.instance=n;let r={};t&&(r=Object.entries(t).reduce((a,[s,l])=>{let f=l?.value;return f&&(a[s]=f),a},{})),e.defaultUniforms={...e.defaultUniforms,...r}}function Re(e,t,o){W(e);let i=o||{...e.defaultUniforms};return t&&e.getUniforms?e.getUniforms(t,i):Se(t,e.instance?.propValidators,e.name)}function F(e,t,o){e.deprecations?.forEach(i=>{i.regex?.test(t)&&(i.deprecated?o.deprecated(i.old,i.new)():o.removed(i.old,i.new)())})}function Et(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){v(e);let t={},o={};D({modules:e,level:0,moduleMap:t,moduleDepth:o});let i=Object.keys(o).sort((n,r)=>o[r]-o[n]).map(n=>t[n]);return v(i),i}function D(e){let{modules:t,level:o,moduleMap:i,moduleDepth:n}=e;if(o>=5)throw new Error("Possible loop in shader dependency graph");for(let r of t)i[r.name]=r,(n[r.name]===void 0||n[r.name]<o)&&(n[r.name]=o);for(let r of t)r.dependencies&&D({modules:r.dependencies,level:o+1,moduleMap:i,moduleDepth:n})}function xt(e){v(e);let t={},o={};return D({modules:e,level:0,moduleMap:t,moduleDepth:o}),e=Object.keys(o).sort((i,n)=>o[n]-o[i]).map(i=>t[i]),v(e),e}function Ne(e){return xt(e)}function Oe(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)}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 Wn(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:qn(n,r)}:null}function se(e,t,n={}){let r=ye(e,t);if(!r||r.matches)return r;let o=Kn(r);return n.log?.error?.(o,r)(),n.throwOnError!==!1&&O(!1,o),r}function Wn(e,t,n){let r=t==="wgsl"?jn(e,n):$n(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(/^(?:uniform\s+)?[A-Za-z0-9_]+(?:<[^>]+>)?\s+([A-Za-z0-9_]+)(?:\s*\[[^\]]+\])?\s*;/);s&&o.push(s[1])}return o}function jn(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 $n(e,t){return e.match(new RegExp(`uniform\\s+${t}\\s*\\{([\\s\\S]*?)\\}\\s*[A-Za-z0-9_]+\\s*;`,"m"))?.[1]||null}function qn(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 Kn(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,56 +57,58 @@ ${o[i]}`:o[i]}),t}function v(e){e.map(t=>W(t))}function W(e){if(e.instance)retur
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 Te(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=Me(e,Pt),e;case"fragment":return e=Me(e,Ct),e;default:throw new Error(t)}}var Fe=[[/^(#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("]],Pt=[...Fe,[re("attribute"),"in $1"],[re("varying"),"out $1"]],Ct=[...Fe,[re("varying"),"in $1"]];function Me(e,t){for(let[o,i]of t)e=e.replace(o,i);return e}function re(e){return new RegExp(`\\b${e}[ \\t]+(\\w+[ \\t]+\\w+(\\[\\w+\\])?;)`,"g")}function ne(e,t){let o="";for(let i in e){let n=e[i];if(o+=`void ${n.signature} {
59
- `,n.header&&(o+=` ${n.header}`),t[i]){let r=t[i];r.sort((a,s)=>a.order-s.order);for(let a of r)o+=` ${a.injection}
60
- `}n.footer&&(o+=` ${n.footer}`),o+=`}
61
- `}return o}function ae(e){let t={vertex:{},fragment:{}};for(let o of e){let i,n;typeof o!="string"?(i=o,n=i.hook):(i={},n=o),n=n.trim();let[r,a]=n.split(":"),s=n.replace(/\(.+/,""),l=Object.assign(i,{signature:a});switch(r){case"vs":t.vertex[s]=l;break;case"fs":t.fragment[s]=l;break;default:throw new Error(r)}}return t}function $(e,t){return{name:Rt(e,t),language:"glsl",version:Nt(e)}}function Rt(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 Nt(e){let t=100,o=e.match(/[^\s]+/g);if(o&&o.length>=2&&o[0]==="#version"){let i=parseInt(o[1],10);Number.isFinite(i)&&(t=i)}if(t!==100&&t!==300)throw new Error(`Invalid GLSL version ${t}`);return t}var De=`
62
-
63
- ${M}
64
- `,Ot=`precision highp float;
65
- `;function we(e){let t=y(e.modules||[]);return{source:Mt(e.platformInfo,{...e,source:e.source,stage:"vertex",modules:t}),getUniforms:Be(t)}}function K(e){let{vs:t,fs:o}=e,i=y(e.modules||[]);return{vs:ye(e.platformInfo,{...e,source:t,stage:"vertex",modules:i}),fs:ye(e.platformInfo,{...e,source:o,stage:"fragment",modules:i}),getUniforms:Be(i)}}function Mt(e,t){let{source:o,stage:i,modules:n,hookFunctions:r=[],inject:a={},log:s}=t;b(typeof o=="string","shader source must be a string");let l=o,f="",G=ae(r),A={},N={},I={};for(let u in a){let d=typeof a[u]=="string"?{injection:a[u],order:0}:a[u],c=/^(v|f)s:(#)?([\w-]+)$/.exec(u);if(c){let _=c[2],h=c[3];_?h==="decl"?N[u]=[d]:I[u]=[d]:A[u]=[d]}else I[u]=[d]}let ge=n;for(let u of ge){s&&F(u,l,s);let d=X(u,"wgsl");f+=d;let c=u.injections?.[i]||{};for(let _ in c){let h=/^(v|f)s:#([\w-]+)$/.exec(_);if(h){let S=h[2]==="decl"?N:I;S[_]=S[_]||[],S[_].push(c[_])}else A[_]=A[_]||[],A[_].push(c[_])}}return f+=De,f=T(f,i,N),f+=ne(G[i],A),f+=l,f=T(f,i,I),f}function ye(e,t){let{source:o,stage:i,language:n="glsl",modules:r,defines:a={},hookFunctions:s=[],inject:l={},prologue:f=!0,log:G}=t;b(typeof o=="string","shader source must be a string");let A=n==="glsl"?$(o).version:-1,N=e.shaderLanguageVersion,I=A===100?"#version 100":"#version 300 es",u=o.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,Yn),e;case"fragment":return e=ht(e,Xn),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("]],Yn=[...gt,[Oe("attribute"),"in $1"],[Oe("varying"),"out $1"]],Xn=[...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:Zn(e,t),language:"glsl",version:Jn(e)}}function Zn(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 Jn(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(Qn({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 Qn(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:tr(e.resourceType),viewDimension:_t(e.resourceType)}:e.resourceType.startsWith("texture_")?{...t,kind:"texture",viewDimension:_t(e.resourceType),sampleType:er(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 er(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 tr(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,nr=`precision highp float;
68
+ `;function At(e){let t=Y(e.modules||[]),{source:n,bindingAssignments:r}=rr(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 rr(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=ir(c),x=cr(_,t._bindingRegistry,m),d=[];for(let M of _){s&&K(M,c,s);let b=ar(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+=ur(d),l+=c,l=q(l,r,g),hr(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={};r.forEach(p=>{Object.assign(d,p.defines)}),Object.assign(d,a);let c="";switch(n){case"wgsl":break;case"glsl":c=f?`${I}
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
- ${Oe(e)}
73
- ${i==="fragment"?Ot:""}
75
+ ${pt(e)}
76
+ ${r==="fragment"?nr:""}
74
77
 
75
78
  // ----- APPLICATION DEFINES -------------------------
76
79
 
77
- ${Tt(d)}
80
+ ${or(x)}
78
81
 
79
- `:`${I}
80
- `;break}let _=ae(s),h={},V={},S={};for(let p in l){let P=typeof l[p]=="string"?{injection:l[p],order:0}:l[p],L=/^(v|f)s:(#)?([\w-]+)$/.exec(p);if(L){let m=L[2],j=L[3];m?j==="decl"?V[p]=[P]:S[p]=[P]:h[p]=[P]}else S[p]=[P]}for(let p of r){G&&F(p,u,G);let P=X(p,i);c+=P;let L=p.instance?.normalizedInjections[i]||{};for(let m in L){let j=/^(v|f)s:#([\w-]+)$/.exec(m);if(j){let ee=j[2]==="decl"?V:S;ee[m]=ee[m]||[],ee[m].push(L[m])}else h[m]=h[m]||[],h[m].push(L[m])}}return c+="// ----- MAIN SHADER SOURCE -------------------------",c+=De,c=T(c,i,V),c+=ne(_[i],h),c+=u,c=T(c,i,S),n==="glsl"&&A!==N&&(c=Te(c,i)),c.trim()}function Be(e){return function(o){let i={};for(let n of e){let r=n.getUniforms?.(o,i);Object.assign(i,r)}return i}}function Tt(e={}){let t="";for(let o in e){let i=e[o];(i||Number.isFinite(i))&&(t+=`#define ${o.toUpperCase()} ${e[o]}
81
- `)}return t}function X(e,t){let o;switch(t){case"vertex":o=e.vs||"";break;case"fragment":o=e.fs||"";break;case"wgsl":o=e.source||"";break;default:b(!1)}if(!e.name)throw new Error("Shader module must have a name");let i=e.name.toUpperCase().replace(/[^0-9a-z]/gi,"_"),n=`// ----- 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 or(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"&&(n+=`#define MODULE_${i}
84
- `),n+=`${o}
85
- `,n}var Ft=/^\s*\#\s*ifdef\s*([a-zA-Z_]+)\s*$/,yt=/^\s*\#\s*endif\s*$/;function Y(e,t){let o=e.split(`
86
- `),i=[],n=!0,r=null;for(let a of o){let s=a.match(Ft),l=a.match(yt);s?(r=s[1],n=Boolean(t?.defines?.[r])):l?n=!0:n&&i.push(a)}return i.join(`
87
- `)}var C=class{_hookFunctions=[];_defaultModules=[];static getDefaultShaderAssembler(){return C.defaultShaderAssembler=C.defaultShaderAssembler||new C,C.defaultShaderAssembler}addDefaultModule(t){this._defaultModules.find(o=>o.name===(typeof t=="string"?t:t.name))||this._defaultModules.push(t)}removeDefaultModule(t){let o=typeof t=="string"?t:t.name;this._defaultModules=this._defaultModules.filter(i=>i.name!==o)}addShaderHook(t,o){o&&(t=Object.assign(o,{hook:t})),this._hookFunctions.push(t)}assembleWGSLShader(t){let o=this._getModuleList(t.modules),i=this._hookFunctions,{source:n,getUniforms:r}=we({...t,source:t.source,modules:o,hookFunctions:i});return{source:t.platformInfo.shaderLanguage==="wgsl"?Y(n):n,getUniforms:r,modules:o}}assembleGLSLShaderPair(t){let o=this._getModuleList(t.modules),i=this._hookFunctions;return{...K({...t,vs:t.vs,fs:t.fs,modules:o,hookFunctions:i}),modules:o}}_getModuleList(t=[]){let o=new Array(this._defaultModules.length+t.length),i={},n=0;for(let r=0,a=this._defaultModules.length;r<a;++r){let s=this._defaultModules[r],l=s.name;o[n++]=s,i[l]=!0}for(let r=0,a=t.length;r<a;++r){let s=t[r],l=s.name;i[l]||(o[n++]=s,i[l]=!0)}return o.length=n,v(o),o}},w=C;he(w,"defaultShaderAssembler");var Dt=`out vec4 transform_output;
86
+ `;return t!=="wgsl"&&(i+=`#define MODULE_${o}
87
+ `),i+=`${r}
88
+ `,i}function ir(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];pr(a,i,s),pe(t,a,i,`application binding "${s}"`)}}return t}function ar(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)=>sr(r,n))}function sr(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&&lr(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 cr(e,t,n){let r=new Map;if(!t)return r;for(let o of e)for(let i of fr(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 lr(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 fr(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 pr(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 hr(e){if(/@binding\(\s*auto\s*\)/.test(e))throw new Error("Unresolved @binding(auto) remained in assembled WGSL source.")}function ur(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_]*)",gr=new RegExp(`^\\s*\\#\\s*ifdef\\s*${we}\\s*$`),mr=new RegExp(`^\\s*\\#\\s*ifndef\\s*${we}\\s*(?:\\/\\/.*)?$`),dr=/^\s*\#\s*else\s*(?:\/\/.*)?$/,_r=/^\s*\#\s*endif\s*$/,br=new RegExp(`^\\s*\\#\\s*ifdef\\s*${we}\\s*(?:\\/\\/.*)?$`),vr=/^\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(br)||a.match(gr),c=a.match(mr),l=a.match(dr),p=a.match(vr)||a.match(_r);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 Sr=`out vec4 transform_output;
88
94
  void main() {
89
95
  transform_output = vec4(0);
90
- }`,wt=`#version 300 es
91
- ${Dt}`;function Ue(e,t){t=Array.isArray(t)?t:[t];let o=e.replace(/^\s+/,"").split(/\s+/),[i,n,r]=o;if(!t.includes(i)||!n||!r)return null;let a=r.split(";")[0];return{qualifier:i,type:n,name:a}}function ke(e){let{input:t,inputChannels:o,output:i}=e||{};if(!t)return wt;if(!o)throw new Error("inputChannels");let n=Bt(o),r=le(t,o);return`#version 300 es
92
- in ${n} ${t};
93
- out vec4 ${i};
96
+ }`,xr=`#version 300 es
97
+ ${Sr}`;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 xr;if(!n)throw new Error("inputChannels");let o=Mr(n),i=Be(t,n);return`#version 300 es
98
+ in ${o} ${t};
99
+ out vec4 ${r};
94
100
  void main() {
95
- ${i} = ${r};
96
- }`}function He(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 Ge(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 Bt(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 le(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 E(e){return typeof e=="string"?e.charAt(0).toUpperCase()+e.slice(1):e}function Ve(e,t){return Ut(e,t)}function Ut(e,t){let o=[];switch(t.uniforms){case"scoped-interface-blocks":case"unscoped-interface-blocks":o.push(`uniform ${E(e.name)} {`);break;case"uniforms":}for(let[i,n]of Object.entries(e.uniformTypes||{})){let r=kt(n);switch(t.uniforms){case"scoped-interface-blocks":o.push(` ${r} ${i};`);break;case"unscoped-interface-blocks":o.push(` ${r} ${e.name}_${i};`);break;case"uniforms":o.push(`uniform ${r} ${e.name}_${i};`)}}switch(t.uniforms){case"scoped-interface-blocks":o.push(`} ${e.name};`);break;case"unscoped-interface-blocks":o.push("};");break;case"uniforms":}return o.push(""),o.join(`
97
- `)}function kt(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 je(e,t){return Ht(e,t)}function Ht(e,t){let o=[];o.push(`struct ${E(e.name)} {`);for(let[i,n]of Object.entries(e?.uniformTypes||{})){let r=n;o.push(` ${i} : ${r};`)}return o.push("};"),o.push(`var<uniform> ${e.name} : ${E(e.name)};`),o.join(`
98
- `)}function ze(e,t){switch(t.shaderLanguage){case"glsl":return Ve(e,t);case"wgsl":return je(e,t)}}var Zo=1/Math.PI*180,Qo=1/180*Math.PI,Gt={EPSILON:1e-12,debug:!1,precision:4,printTypes:!1,printDegrees:!1,printRowMajor:!0,_cartographicRadians:!1};globalThis.mathgl=globalThis.mathgl||{config:{...Gt}};var Vt=globalThis.mathgl.config;function qe(e){return Array.isArray(e)||ArrayBuffer.isView(e)&&!(e instanceof DataView)}function se(e,t,o){return zt(e,i=>Math.max(t,Math.min(o,i)))}function jt(e){return e.clone?e.clone():new Array(e.length)}function zt(e,t,o){if(qe(e)){let i=e;o=o||jt(i);for(let n=0;n<o.length&&n<i.length;++n){let r=typeof e=="number"?e:e[n];o[n]=t(r,n,o)}return o}return t(e)}var x=null,We=new ArrayBuffer(4),$e=new Float32Array(We),Ke=new Uint32Array(We);function Xe(e){x||=Je(),e=se(e,-65504,65504),$e[0]=e;let t=Ke[0],o=t>>23&511;return x.baseTable[o]+((t&8388607)>>x.shiftTable[o])}function Ye(e){x||=Je();let t=e>>10;return Ke[0]=x.mantissaTable[x.offsetTable[t]+(e&1023)]+x.exponentTable[t],$e[0]}function Je(){let e=new Uint32Array(512),t=new Uint32Array(512);for(let r=0;r<256;++r){let a=r-127;a<-27?(e[r]=0,e[r|256]=32768,t[r]=24,t[r|256]=24):a<-14?(e[r]=1024>>-a-14,e[r|256]=1024>>-a-14|32768,t[r]=-a-1,t[r|256]=-a-1):a<=15?(e[r]=a+15<<10,e[r|256]=a+15<<10|32768,t[r]=13,t[r|256]=13):a<128?(e[r]=31744,e[r|256]=64512,t[r]=24,t[r|256]=24):(e[r]=31744,e[r|256]=64512,t[r]=13,t[r|256]=13)}let o=new Uint32Array(2048),i=new Uint32Array(64),n=new Uint32Array(64);for(let r=1;r<1024;++r){let a=r<<13,s=0;for(;!(a&8388608);)a<<=1,s-=8388608;a&=-8388609,s+=947912704,o[r]=a|s}for(let r=1024;r<2048;++r)o[r]=939524096+(r-1024<<13);for(let r=1;r<31;++r)i[r]=r<<23;i[31]=1199570944,i[32]=2147483648;for(let r=33;r<63;++r)i[r]=2147483648+(r-32<<23);i[63]=3347054592;for(let r=1;r<64;++r)r!==32&&(n[r]=1024);return{baseTable:e,shiftTable:t,mantissaTable:o,exponentTable:i,offsetTable:n}}function R(e,t=[],o=0){let i=Math.fround(e),n=e-i;return t[o]=i,t[o+1]=n,t}function B(e){return e-Math.fround(e)}function U(e){let t=new Float32Array(32);for(let o=0;o<4;++o)for(let i=0;i<4;++i){let n=o*4+i;R(e[i*4+o],t,n*2)}return t}var qt=`fn random(scale: vec3f, seed: float) -> f32 {
99
- /* use the fragment position for a different seed per-pixel */
100
- return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
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 Mr(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 Lr(e,t)}function Lr(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=Ar(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 Ar(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 Er(e,t)}function Er(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 ci=1/Math.PI*180,li=1/180*Math.PI,Rr={EPSILON:1e-12,debug:!1,precision:4,printTypes:!1,printDegrees:!1,printRowMajor:!0,_cartographicRadians:!1};globalThis.mathgl=globalThis.mathgl||{config:{...Rr}};var P=globalThis.mathgl.config;function ke(e,{precision:t=P.precision}={}){return e=Ir(e),`${parseFloat(e.toPrecision(t))}`}function H(e){return Array.isArray(e)||ArrayBuffer.isView(e)&&!(e instanceof DataView)}function De(e,t,n){return Pr(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 Ir(e){return Math.round(e/P.EPSILON)*P.EPSILON}function Cr(e){return e.clone?e.clone():new Array(e.length)}function Pr(e,t,n){if(H(e)){let r=e;n=n||Cr(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 Nr(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&&!Nr(e,t))throw new Error(`math.gl: ${n} some fields set to invalid numbers'`);return e}var w=typeof Float32Array<"u"?Float32Array:Array;var mi=Math.PI/180;function yr(){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 di=function(){let e=yr();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 Or(){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 vi=function(){let e=Or();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 Tr(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 Fr(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=Fr;function wr(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=wr;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?Tr(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 Br(){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 Ri=function(){let e=Br();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 kr=45*Math.PI/180,Dr=1,He=.1,Ge=500,Ur=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 Hr()}static get ZERO(){return zr()}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(Ur)}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?Gr(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=kr,aspect:r=Dr,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 zr(){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 Hr(){return Se||(Se=new B,Object.freeze(Se)),Se}function nn(e){if(e>Math.PI*2)throw Error("expected radians")}function Gr(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 Vr=`fn random(scale: vec3f, seed: f32) -> f32 {
105
+ return fract(sin(dot(scale + vec3f(seed), vec3f(12.9898, 78.233, 151.7182))) * 43758.5453 + seed);
101
106
  }
102
- `,Wt=`float random(vec3 scale, float seed) {
107
+ `,Wr=`float random(vec3 scale, float seed) {
103
108
  /* use the fragment position for a different seed per-pixel */
104
109
  return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
105
110
  }
106
- `,Ze={name:"random",source:qt,fs:Wt};var $t=`#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND
111
+ `,fn={name:"random",source:Vr,fs:Wr};var jr=`#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND
107
112
 
108
113
  // All these functions are for substituting tan() function from Intel GPU only
109
114
  const float TWO_PI = 6.2831854820251465;
@@ -253,9 +258,10 @@ float tan_fp32(float a) {
253
258
  return tan(a);
254
259
  #endif
255
260
  }
256
- `,Qe={name:"fp32",vs:$t};var et=`
261
+ `,pn={name:"fp32",vs:jr};var We=`
257
262
  uniform fp64arithmeticUniforms {
258
263
  uniform float ONE;
264
+ uniform float SPLIT;
259
265
  } fp64;
260
266
 
261
267
  /*
@@ -265,6 +271,12 @@ The purpose of this workaround is to prevent shader compilers from
265
271
  optimizing away necessary arithmetic operations by swapping their sequences
266
272
  or transform the equation to some 'equivalent' form.
267
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
+
268
280
  The method is to multiply an artifical variable, ONE, which will be known to
269
281
  the compiler to be 1 only at runtime. The whole expression is then represented
270
282
  as a polynomial with respective to ONE. In the coefficients of all terms, only one a
@@ -273,17 +285,23 @@ and one b should appear
273
285
  err = (a + b) * ONE^6 - a * ONE^5 - (a + b) * ONE^4 + a * ONE^3 - b - (a + b) * ONE^2 + a * ONE
274
286
  */
275
287
 
276
- // Divide float number to high and low floats to extend fraction bits
277
- vec2 split(float a) {
278
- const float SPLIT = 4097.0;
279
- float t = a * SPLIT;
288
+ float prevent_fp64_optimization(float value) {
280
289
  #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
281
- float a_hi = t * fp64.ONE - (t - a);
282
- float a_lo = a * fp64.ONE - a_hi;
290
+ return value + fp64.ONE * 0.0;
283
291
  #else
284
- float a_hi = t - (t - a);
285
- float a_lo = a - a_hi;
292
+ return value;
286
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;
287
305
  return vec2(a_hi, a_lo);
288
306
  }
289
307
 
@@ -347,8 +365,26 @@ vec2 twoProd(float a, float b) {
347
365
  float prod = a * b;
348
366
  vec2 a_fp64 = split(a);
349
367
  vec2 b_fp64 = split(b);
350
- float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y +
351
- 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;
352
388
  return vec2(prod, err);
353
389
  }
354
390
 
@@ -421,7 +457,213 @@ vec2 sqrt_fp64(vec2 a) {
421
457
  return sum_fp64(vec2(yn, 0.0), prod);
422
458
  #endif
423
459
  }
424
- `;var tt=`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);
425
667
  const vec2 LOG2_FP64 = vec2(0.6931471824645996e+00, -1.9046542121259336e-09);
426
668
  const vec2 PI_FP64 = vec2(3.1415927410125732, -8.742278012618954e-8);
427
669
  const vec2 TWO_PI_FP64 = vec2(6.2831854820251465, -1.7484556025237907e-7);
@@ -1090,7 +1332,7 @@ void mat4_vec4_mul_fp64(vec2 b[16], vec2 a[4], out vec2 out_val[4]) {
1090
1332
  vec4_dot_fp64(a, tmp, out_val[i]);
1091
1333
  }
1092
1334
  }
1093
- `;var Kt={ONE:1},ce={name:"fp64arithmetic",vs:et,defaultUniforms:Kt,uniformTypes:{ONE:"f32"},fp64ify:R,fp64LowPart:B,fp64ifyMatrix4:U},ot={name:"fp64",vs:tt,dependencies:[ce],fp64ify:R,fp64LowPart:B,fp64ifyMatrix4:U};var Xt=[0,1,1,1],Yt=`uniform pickingUniforms {
1335
+ `;var $r={ONE:1,SPLIT:4097},je={name:"fp64arithmetic",source:hn,fs:We,vs:We,defaultUniforms:$r,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 qr=[0,1,1,1],Kr=`uniform pickingUniforms {
1094
1336
  float isActive;
1095
1337
  float isAttribute;
1096
1338
  float isHighlightActive;
@@ -1161,7 +1403,7 @@ void picking_setPickingAttribute(vec3 value) {
1161
1403
  picking_vRGBcolor_Avalid.rgb = value;
1162
1404
  }
1163
1405
  }
1164
- `,Jt=`uniform pickingUniforms {
1406
+ `,Yr=`uniform pickingUniforms {
1165
1407
  float isActive;
1166
1408
  float isAttribute;
1167
1409
  float isHighlightActive;
@@ -1217,7 +1459,32 @@ vec4 picking_filterColor(vec4 color) {
1217
1459
  vec4 highlightColor = picking_filterHighlightColor(color);
1218
1460
  return picking_filterPickingColor(highlightColor);
1219
1461
  }
1220
- `,it={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:Xt},vs:Yt,fs:Jt,getUniforms:Zt};function Zt(e={},t){let o={};if(e.highlightedObjectColor!==void 0)if(e.highlightedObjectColor===null)o.isHighlightActive=!1;else{o.isHighlightActive=!0;let i=e.highlightedObjectColor.slice(0,3);o.highlightedObjectColor=i}if(e.highlightColor){let i=Array.from(e.highlightColor,n=>n/255);Number.isFinite(i[3])||(i[3]=1),o.highlightColor=i}return e.isActive!==void 0&&(o.isActive=Boolean(e.isActive),o.isAttribute=Boolean(e.isAttribute)),e.useFloatColors!==void 0&&(o.useFloatColors=Boolean(e.useFloatColors)),o}var nt=de(te(),1);var fe=`precision highp int;
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:qr},vs:Kr,fs:Yr,getUniforms:Xr};function Xr(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,Zr=`
1463
+ struct skinUniforms {
1464
+ jointMatrix: array<mat4x4<f32>, ${te}>,
1465
+ };
1466
+
1467
+ @group(0) @binding(auto) var<uniform> skin: skinUniforms;
1468
+
1469
+ fn getSkinMatrix(weights: vec4f, joints: vec4u) -> mat4x4<f32> {
1470
+ return (weights.x * skin.jointMatrix[joints.x])
1471
+ + (weights.y * skin.jointMatrix[joints.y])
1472
+ + (weights.z * skin.jointMatrix[joints.z])
1473
+ + (weights.w * skin.jointMatrix[joints.w]);
1474
+ }
1475
+ `,Jr=`
1476
+ uniform skinUniforms {
1477
+ mat4 jointMatrix[SKIN_MAX_JOINTS];
1478
+ } skin;
1479
+
1480
+ mat4 getSkinMatrix(vec4 weights, uvec4 joints) {
1481
+ return (weights.x * skin.jointMatrix[joints.x])
1482
+ + (weights.y * skin.jointMatrix[joints.y])
1483
+ + (weights.z * skin.jointMatrix[joints.z])
1484
+ + (weights.w * skin.jointMatrix[joints.w]);
1485
+ }
1486
+
1487
+ `,Qr="",dn={props:{},uniforms:{},name:"skin",bindingLayout:[{name:"skin",group:0}],dependencies:[],source:Zr,vs:Jr,fs:Qr,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;
1221
1488
 
1222
1489
  // #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
1223
1490
  struct AmbientLight {
@@ -1230,59 +1497,51 @@ struct PointLight {
1230
1497
  vec3 attenuation; // 2nd order x:Constant-y:Linear-z:Exponential
1231
1498
  };
1232
1499
 
1500
+ struct SpotLight {
1501
+ vec3 color;
1502
+ vec3 position;
1503
+ vec3 direction;
1504
+ vec3 attenuation;
1505
+ vec2 coneCos;
1506
+ };
1507
+
1233
1508
  struct DirectionalLight {
1234
1509
  vec3 color;
1235
1510
  vec3 direction;
1236
1511
  };
1237
1512
 
1513
+ struct UniformLight {
1514
+ vec3 color;
1515
+ vec3 position;
1516
+ vec3 direction;
1517
+ vec3 attenuation;
1518
+ vec2 coneCos;
1519
+ };
1520
+
1238
1521
  uniform lightingUniforms {
1239
1522
  int enabled;
1240
- int lightType;
1241
-
1242
1523
  int directionalLightCount;
1243
1524
  int pointLightCount;
1244
-
1525
+ int spotLightCount;
1245
1526
  vec3 ambientColor;
1246
-
1247
- vec3 lightColor0;
1248
- vec3 lightPosition0;
1249
- vec3 lightDirection0;
1250
- vec3 lightAttenuation0;
1251
-
1252
- vec3 lightColor1;
1253
- vec3 lightPosition1;
1254
- vec3 lightDirection1;
1255
- vec3 lightAttenuation1;
1256
-
1257
- vec3 lightColor2;
1258
- vec3 lightPosition2;
1259
- vec3 lightDirection2;
1260
- vec3 lightAttenuation2;
1527
+ UniformLight lights[5];
1261
1528
  } lighting;
1262
1529
 
1263
1530
  PointLight lighting_getPointLight(int index) {
1264
- switch (index) {
1265
- case 0:
1266
- return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0);
1267
- case 1:
1268
- return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
1269
- case 2:
1270
- default:
1271
- return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
1272
- }
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);
1273
1538
  }
1274
1539
 
1275
1540
  DirectionalLight lighting_getDirectionalLight(int index) {
1276
- switch (index) {
1277
- case 0:
1278
- return DirectionalLight(lighting.lightColor0, lighting.lightDirection0);
1279
- case 1:
1280
- return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
1281
- case 2:
1282
- default:
1283
- return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
1284
- }
1285
- }
1541
+ UniformLight light =
1542
+ lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];
1543
+ return DirectionalLight(light.color, light.direction);
1544
+ }
1286
1545
 
1287
1546
  float getPointLightAttenuation(PointLight pointLight, float distance) {
1288
1547
  return pointLight.attenuation.x
@@ -1290,8 +1549,24 @@ float getPointLightAttenuation(PointLight pointLight, float distance) {
1290
1549
  + pointLight.attenuation.z * distance * distance;
1291
1550
  }
1292
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
+
1293
1566
  // #endif
1294
- `;var rt=`// #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))
1568
+ const MAX_LIGHTS: i32 = 5;
1569
+
1295
1570
  struct AmbientLight {
1296
1571
  color: vec3<f32>,
1297
1572
  };
@@ -1302,47 +1577,86 @@ struct PointLight {
1302
1577
  attenuation: vec3<f32>, // 2nd order x:Constant-y:Linear-z:Exponential
1303
1578
  };
1304
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
+
1305
1588
  struct DirectionalLight {
1306
1589
  color: vec3<f32>,
1307
1590
  direction: vec3<f32>,
1308
1591
  };
1309
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
+
1310
1601
  struct lightingUniforms {
1311
1602
  enabled: i32,
1312
- pointLightCount: i32,
1313
1603
  directionalLightCount: i32,
1314
-
1604
+ pointLightCount: i32,
1605
+ spotLightCount: i32,
1315
1606
  ambientColor: vec3<f32>,
1316
-
1317
- // TODO - support multiple lights by uncommenting arrays below
1318
- lightType: i32,
1319
- lightColor: vec3<f32>,
1320
- lightDirection: vec3<f32>,
1321
- lightPosition: vec3<f32>,
1322
- lightAttenuation: vec3<f32>,
1323
-
1324
- // AmbientLight ambientLight;
1325
- // PointLight pointLight[MAX_LIGHTS];
1326
- // DirectionalLight directionalLight[MAX_LIGHTS];
1607
+ lights: array<UniformLight, 5>,
1327
1608
  };
1328
1609
 
1329
- // Binding 0:1 is reserved for lighting (Note: could go into separate bind group as it is stable across draw calls)
1330
- @binding(1) @group(0) var<uniform> lighting : lightingUniforms;
1610
+ @group(2) @binding(auto) var<uniform> lighting : lightingUniforms;
1331
1611
 
1332
1612
  fn lighting_getPointLight(index: i32) -> PointLight {
1333
- return PointLight(lighting.lightColor, lighting.lightPosition, lighting.lightAttenuation);
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);
1334
1620
  }
1335
1621
 
1336
1622
  fn lighting_getDirectionalLight(index: i32) -> DirectionalLight {
1337
- return DirectionalLight(lighting.lightColor, lighting.lightDirection);
1338
- }
1623
+ let light = lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];
1624
+ return DirectionalLight(light.color, light.direction);
1625
+ }
1339
1626
 
1340
1627
  fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
1341
1628
  return pointLight.attenuation.x
1342
1629
  + pointLight.attenuation.y * distance
1343
1630
  + pointLight.attenuation.z * distance * distance;
1344
1631
  }
1345
- `;var Qt=5,eo=255,k;(function(e){e[e.POINT=0]="POINT",e[e.DIRECTIONAL=1]="DIRECTIONAL"})(k||(k={}));var g={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>"},defaultUniforms:{enabled:1,lightType:k.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]},source:rt,vs:fe,fs:fe,getUniforms:to};function to(e,t={}){if(e=e&&{...e},!e)return{...g.defaultUniforms};e.lights&&(e={...e,...io(e.lights),lights:void 0});let{ambientLight:o,pointLights:i,directionalLights:n}=e||{};if(!(o||i&&i.length>0||n&&n.length>0))return{...g.defaultUniforms,enabled:0};let a={...g.defaultUniforms,...t,...oo({ambientLight:o,pointLights:i,directionalLights:n})};return e.enabled!==void 0&&(a.enabled=e.enabled?1:0),a}function oo({ambientLight:e,pointLights:t=[],directionalLights:o=[]}){let i={};i.ambientColor=ue(e);let n=0;for(let r of t){i.lightType=k.POINT;let a=n;i[`lightColor${a}`]=ue(r),i[`lightPosition${a}`]=r.position,i[`lightAttenuation${a}`]=r.attenuation||[1,0,0],n++}for(let r of o){i.lightType=k.DIRECTIONAL;let a=n;i[`lightColor${a}`]=ue(r),i[`lightDirection${a}`]=r.direction,n++}return n>Qt&&nt.log.warn("MAX_LIGHTS exceeded")(),i.directionalLightCount=o.length,i.pointLightCount=t.length,i}function io(e){let t={pointLights:[],directionalLights:[]};for(let o of e||[])switch(o.type){case"ambient":t.ambientLight=o;break;case"directional":t.directionalLights?.push(o);break;case"point":t.pointLights?.push(o);break;default:}return t}function ue(e={}){let{color:t=[0,0,0],intensity:o=1}=e;return t.map(i=>i*o/eo)}var ro=`
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,eo=255,to={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:[to,U]},defaultUniforms:Me(),bindingLayout:[{name:"lighting",group:2}],firstBindingSlot:0,source:_n,vs:$e,fs:$e,getUniforms:no};function no(e,t={}){if(e=e&&{...e},!e)return Me();e.lights&&(e={...e,...oo(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(),...ro({ambientLight:n,pointLights:r,spotLights:o,directionalLights:i})};return e.enabled!==void 0&&(s.enabled=e.enabled?1:0),s}function ro({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:ao(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 oo(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/eo)}function Me(){return{enabled:1,directionalLightCount:0,pointLightCount:0,spotLightCount:0,ambientColor:[.1,.1,.1],lights:vn()}}function vn(){return Array.from({length:U},()=>io())}function io(){return{color:[1,1,1],position:[1,1,2],direction:[1,1,1],attenuation:[1,0,0],coneCos:[1,0]}}function ao(e){let t=e.innerConeAngle??0,n=e.outerConeAngle??Math.PI/4;return[Math.cos(t),Math.cos(n)]}var so=`#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:so,vs:Sn,fs:Sn};var co=`
1346
1660
  struct dirlightUniforms {
1347
1661
  lightDirection: vec3<f32>,
1348
1662
  };
@@ -1353,7 +1667,7 @@ struct DirlightInputs {
1353
1667
  normal: DirlightNormal,
1354
1668
  };
1355
1669
 
1356
- @binding(1) @group(0) var<uniform> dirlight : dirlightUniforms;
1670
+ @group(2) @binding(auto) var<uniform> dirlight : dirlightUniforms;
1357
1671
 
1358
1672
  // For vertex
1359
1673
  fn dirlight_setNormal(normal: vec3<f32>) -> DirlightNormal {
@@ -1368,12 +1682,12 @@ fn dirlight_filterColor(color: vec4<f32>, inputs: DirlightInputs) -> vec4<f32> {
1368
1682
  let d: f32 = abs(dot(inputs.normal, normalize(lightDirection)));
1369
1683
  return vec4<f32>(color.rgb * d, color.a);
1370
1684
  }
1371
- `,no=`out vec3 dirlight_vNormal;
1685
+ `,lo=`out vec3 dirlight_vNormal;
1372
1686
 
1373
1687
  void dirlight_setNormal(vec3 normal) {
1374
1688
  dirlight_vNormal = normalize(normal);
1375
1689
  }
1376
- `,ao=`uniform dirlightUniforms {
1690
+ `,fo=`uniform dirlightUniforms {
1377
1691
  vec3 lightDirection;
1378
1692
  } dirlight;
1379
1693
 
@@ -1384,15 +1698,134 @@ vec4 dirlight_filterColor(vec4 color) {
1384
1698
  float d = abs(dot(dirlight_vNormal, normalize(dirlight.lightDirection)));
1385
1699
  return vec4(color.rgb * d, color.a);
1386
1700
  }
1387
- `,pe={props:{},uniforms:{},name:"dirlight",dependencies:[],source:ro,vs:no,fs:ao,uniformTypes:{lightDirection:"vec3<f32>"},defaultUniforms:{lightDirection:[1,1,2]},getUniforms:lo};function lo(e=pe.defaultUniforms){let t={};return e.lightDirection&&(t.lightDirection=e.lightDirection),t}var J=`uniform phongMaterialUniforms {
1701
+ `,qe={props:{},uniforms:{},name:"dirlight",bindingLayout:[{name:"dirlight",group:2}],firstBindingSlot:16,dependencies:[],source:co,vs:lo,fs:fo,uniformTypes:{lightDirection:"vec3<f32>"},defaultUniforms:{lightDirection:[1,1,2]},getUniforms:po};function po(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;
1388
1822
  uniform float ambient;
1389
1823
  uniform float diffuse;
1390
1824
  uniform float shininess;
1391
1825
  uniform vec3 specularColor;
1392
1826
  } material;
1393
- `,Z=`#define MAX_LIGHTS 3
1394
-
1395
- uniform phongMaterialUniforms {
1827
+ `,Ee=`uniform phongMaterialUniforms {
1828
+ uniform bool unlit;
1396
1829
  uniform float ambient;
1397
1830
  uniform float diffuse;
1398
1831
  uniform float shininess;
@@ -1414,6 +1847,10 @@ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 light_direction, vec3 view_d
1414
1847
  vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 position_worldspace, vec3 normal_worldspace) {
1415
1848
  vec3 lightColor = surfaceColor;
1416
1849
 
1850
+ if (material.unlit) {
1851
+ return surfaceColor;
1852
+ }
1853
+
1417
1854
  if (lighting.enabled == 0) {
1418
1855
  return lightColor;
1419
1856
  }
@@ -1429,22 +1866,30 @@ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 positio
1429
1866
  lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color / light_attenuation);
1430
1867
  }
1431
1868
 
1432
- int totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount);
1433
- 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++) {
1434
1878
  DirectionalLight directionalLight = lighting_getDirectionalLight(i);
1435
1879
  lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
1436
1880
  }
1437
1881
 
1438
1882
  return lightColor;
1439
1883
  }
1440
- `;var Q=`struct phongMaterialUniforms {
1884
+ `;var Re=`struct phongMaterialUniforms {
1885
+ unlit: u32,
1441
1886
  ambient: f32,
1442
1887
  diffuse: f32,
1443
1888
  shininess: f32,
1444
1889
  specularColor: vec3<f32>,
1445
1890
  };
1446
1891
 
1447
- @binding(2) @group(0) var<uniform> phongMaterial : phongMaterialUniforms;
1892
+ @group(3) @binding(auto) var<uniform> phongMaterial : phongMaterialUniforms;
1448
1893
 
1449
1894
  fn lighting_getLightColor(surfaceColor: vec3<f32>, light_direction: vec3<f32>, view_direction: vec3<f32>, normal_worldspace: vec3<f32>, color: vec3<f32>) -> vec3<f32> {
1450
1895
  let halfway_direction: vec3<f32> = normalize(light_direction + view_direction);
@@ -1461,6 +1906,10 @@ fn lighting_getLightColor(surfaceColor: vec3<f32>, light_direction: vec3<f32>, v
1461
1906
  fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32> {
1462
1907
  var lightColor: vec3<f32> = surfaceColor;
1463
1908
 
1909
+ if (phongMaterial.unlit != 0u) {
1910
+ return surfaceColor;
1911
+ }
1912
+
1464
1913
  if (lighting.enabled == 0) {
1465
1914
  return lightColor;
1466
1915
  }
@@ -1468,61 +1917,91 @@ fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, p
1468
1917
  let view_direction: vec3<f32> = normalize(cameraPosition - position_worldspace);
1469
1918
  lightColor = phongMaterial.ambient * surfaceColor * lighting.ambientColor;
1470
1919
 
1471
- if (lighting.lightType == 0) {
1472
- let pointLight: PointLight = lighting_getPointLight(0);
1920
+ for (var i: i32 = 0; i < lighting.pointLightCount; i++) {
1921
+ let pointLight: PointLight = lighting_getPointLight(i);
1473
1922
  let light_position_worldspace: vec3<f32> = pointLight.position;
1474
1923
  let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
1475
- lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
1476
- } else if (lighting.lightType == 1) {
1477
- var directionalLight: DirectionalLight = lighting_getDirectionalLight(0);
1478
- lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
1924
+ let light_attenuation = getPointLightAttenuation(
1925
+ pointLight,
1926
+ distance(light_position_worldspace, position_worldspace)
1927
+ );
1928
+ lightColor += lighting_getLightColor(
1929
+ surfaceColor,
1930
+ light_direction,
1931
+ view_direction,
1932
+ normal_worldspace,
1933
+ pointLight.color / light_attenuation
1934
+ );
1479
1935
  }
1480
-
1481
- return lightColor;
1482
- /*
1483
- for (int i = 0; i < MAX_LIGHTS; i++) {
1484
- if (i >= lighting.pointLightCount) {
1485
- break;
1486
- }
1487
- PointLight pointLight = lighting.pointLight[i];
1488
- vec3 light_position_worldspace = pointLight.position;
1489
- vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
1490
- lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
1936
+
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
+ );
1491
1949
  }
1492
1950
 
1493
- for (int i = 0; i < MAX_LIGHTS; i++) {
1494
- if (i >= lighting.directionalLightCount) {
1495
- break;
1496
- }
1497
- DirectionalLight directionalLight = lighting.directionalLight[i];
1951
+ for (var i: i32 = 0; i < lighting.directionalLightCount; i++) {
1952
+ let directionalLight: DirectionalLight = lighting_getDirectionalLight(i);
1498
1953
  lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
1499
- }
1500
- */
1954
+ }
1955
+
1956
+ return lightColor;
1501
1957
  }
1502
1958
 
1503
1959
  fn lighting_getSpecularLightColor(cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32>{
1504
1960
  var lightColor = vec3<f32>(0, 0, 0);
1505
1961
  let surfaceColor = vec3<f32>(0, 0, 0);
1506
1962
 
1507
- if (lighting.enabled == 0) {
1963
+ if (lighting.enabled != 0) {
1508
1964
  let view_direction = normalize(cameraPosition - position_worldspace);
1509
1965
 
1510
- switch (lighting.lightType) {
1511
- case 0, default: {
1512
- let pointLight: PointLight = lighting_getPointLight(0);
1513
- let light_position_worldspace: vec3<f32> = pointLight.position;
1514
- let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
1515
- lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
1516
- }
1517
- case 1: {
1518
- let directionalLight: DirectionalLight = lighting_getDirectionalLight(0);
1966
+ for (var i: i32 = 0; i < lighting.pointLightCount; i++) {
1967
+ let pointLight: PointLight = lighting_getPointLight(i);
1968
+ let light_position_worldspace: vec3<f32> = pointLight.position;
1969
+ let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
1970
+ let light_attenuation = getPointLightAttenuation(
1971
+ pointLight,
1972
+ distance(light_position_worldspace, position_worldspace)
1973
+ );
1974
+ lightColor += lighting_getLightColor(
1975
+ surfaceColor,
1976
+ light_direction,
1977
+ view_direction,
1978
+ normal_worldspace,
1979
+ pointLight.color / light_attenuation
1980
+ );
1981
+ }
1982
+
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++) {
1998
+ let directionalLight: DirectionalLight = lighting_getDirectionalLight(i);
1519
1999
  lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
1520
- }
1521
2000
  }
1522
2001
  }
1523
2002
  return lightColor;
1524
2003
  }
1525
- `;var _e={props:{},name:"gouraudMaterial",vs:Z.replace("phongMaterial","gouraudMaterial"),fs:J.replace("phongMaterial","gouraudMaterial"),source:Q.replaceAll("phongMaterial","gouraudMaterial"),defines:{LIGHTING_VERTEX:!0},dependencies:[g],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(o=>o/255)),{..._e.defaultUniforms,...t}}};var me={name:"phongMaterial",dependencies:[g],source:Q,vs:J,fs:Z,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(o=>o/255)),{...me.defaultUniforms,...t}}};var at=`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;
1526
2005
  out vec2 pbr_vUV;
1527
2006
 
1528
2007
  #ifdef HAS_NORMALS
@@ -1555,7 +2034,7 @@ void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, ve
1555
2034
  pbr_vUV = vec2(0.,0.);
1556
2035
  #endif
1557
2036
  }
1558
- `,lt=`precision highp float;
2037
+ `,En=`precision highp float;
1559
2038
 
1560
2039
  uniform pbrMaterialUniforms {
1561
2040
  // Material is unlit
@@ -1597,10 +2076,12 @@ uniform pbrMaterialUniforms {
1597
2076
  float clearcoatFactor;
1598
2077
  float clearcoatRoughnessFactor;
1599
2078
  bool clearcoatMapEnabled;
2079
+ bool clearcoatRoughnessMapEnabled;
1600
2080
 
1601
2081
  vec3 sheenColorFactor;
1602
2082
  float sheenRoughnessFactor;
1603
2083
  bool sheenColorMapEnabled;
2084
+ bool sheenRoughnessMapEnabled;
1604
2085
 
1605
2086
  float iridescenceFactor;
1606
2087
  float iridescenceIor;
@@ -1650,26 +2131,33 @@ uniform sampler2D pbr_specularIntensitySampler;
1650
2131
  #ifdef HAS_TRANSMISSIONMAP
1651
2132
  uniform sampler2D pbr_transmissionSampler;
1652
2133
  #endif
2134
+ #ifdef HAS_THICKNESSMAP
2135
+ uniform sampler2D pbr_thicknessSampler;
2136
+ #endif
1653
2137
  #ifdef HAS_CLEARCOATMAP
1654
2138
  uniform sampler2D pbr_clearcoatSampler;
2139
+ #endif
2140
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
1655
2141
  uniform sampler2D pbr_clearcoatRoughnessSampler;
1656
2142
  #endif
2143
+ #ifdef HAS_CLEARCOATNORMALMAP
2144
+ uniform sampler2D pbr_clearcoatNormalSampler;
2145
+ #endif
1657
2146
  #ifdef HAS_SHEENCOLORMAP
1658
2147
  uniform sampler2D pbr_sheenColorSampler;
2148
+ #endif
2149
+ #ifdef HAS_SHEENROUGHNESSMAP
1659
2150
  uniform sampler2D pbr_sheenRoughnessSampler;
1660
2151
  #endif
1661
2152
  #ifdef HAS_IRIDESCENCEMAP
1662
2153
  uniform sampler2D pbr_iridescenceSampler;
1663
2154
  #endif
2155
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
2156
+ uniform sampler2D pbr_iridescenceThicknessSampler;
2157
+ #endif
1664
2158
  #ifdef HAS_ANISOTROPYMAP
1665
2159
  uniform sampler2D pbr_anisotropySampler;
1666
2160
  #endif
1667
- #ifdef USE_IBL
1668
- uniform samplerCube pbr_diffuseEnvSampler;
1669
- uniform samplerCube pbr_specularEnvSampler;
1670
- uniform sampler2D pbr_brdfLUT;
1671
- #endif
1672
-
1673
2161
  // Inputs from vertex shader
1674
2162
 
1675
2163
  in vec3 pbr_vPosition;
@@ -1706,6 +2194,8 @@ struct PBRInfo {
1706
2194
  const float M_PI = 3.141592653589793;
1707
2195
  const float c_MinRoughness = 0.04;
1708
2196
 
2197
+ vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor);
2198
+
1709
2199
  vec4 SRGBtoLINEAR(vec4 srgbIn)
1710
2200
  {
1711
2201
  #ifdef MANUAL_SRGB
@@ -1721,11 +2211,9 @@ vec4 SRGBtoLINEAR(vec4 srgbIn)
1721
2211
  #endif //MANUAL_SRGB
1722
2212
  }
1723
2213
 
1724
- // Find the normal for this fragment, pulling either from a predefined normal map
1725
- // or from the interpolated mesh normal and tangent attributes.
1726
- vec3 getNormal()
2214
+ // Build the tangent basis from interpolated attributes or screen-space derivatives.
2215
+ mat3 getTBN()
1727
2216
  {
1728
- // Retrieve the tangent space matrix
1729
2217
  #ifndef HAS_TANGENTS
1730
2218
  vec3 pos_dx = dFdx(pbr_vPosition);
1731
2219
  vec3 pos_dy = dFdy(pbr_vPosition);
@@ -1746,9 +2234,21 @@ vec3 getNormal()
1746
2234
  mat3 tbn = pbr_vTBN;
1747
2235
  #endif
1748
2236
 
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
+ {
1749
2250
  #ifdef HAS_NORMALMAP
1750
- vec3 n = texture(pbr_normalSampler, pbr_vUV).rgb;
1751
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
2251
+ vec3 n = getMappedNormal(pbr_normalSampler, tbn, pbrMaterial.normalScale);
1752
2252
  #else
1753
2253
  // The tbn matrix is linearly interpolated, so we need to re-normalize
1754
2254
  vec3 n = normalize(tbn[2].xyz);
@@ -1757,6 +2257,15 @@ vec3 getNormal()
1757
2257
  return n;
1758
2258
  }
1759
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
+
1760
2269
  // Calculation of the lighting contribution from an optional Image Based Light source.
1761
2270
  // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
1762
2271
  // See our README.md on Environment Maps [3] for additional discussion.
@@ -1832,18 +2341,181 @@ float microfacetDistribution(PBRInfo pbrInfo)
1832
2341
  return roughnessSq / (M_PI * f * f);
1833
2342
  }
1834
2343
 
1835
- void PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) {
1836
- pbrInfo.NdotL = 1.0;
1837
- pbrInfo.NdotH = 0.0;
1838
- pbrInfo.LdotH = 0.0;
1839
- pbrInfo.VdotH = 1.0;
2344
+ float maxComponent(vec3 value)
2345
+ {
2346
+ return max(max(value.r, value.g), value.b);
1840
2347
  }
1841
2348
 
1842
- void PBRInfo_setDirectionalLight(inout PBRInfo pbrInfo, vec3 lightDirection) {
1843
- vec3 n = pbrInfo.n;
1844
- vec3 v = pbrInfo.v;
1845
- vec3 l = normalize(lightDirection); // Vector from surface point to light
1846
- vec3 h = normalize(l+v); // Half vector between both l and v
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
+
2507
+ void PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) {
2508
+ pbrInfo.NdotL = 1.0;
2509
+ pbrInfo.NdotH = 0.0;
2510
+ pbrInfo.LdotH = 0.0;
2511
+ pbrInfo.VdotH = 1.0;
2512
+ }
2513
+
2514
+ void PBRInfo_setDirectionalLight(inout PBRInfo pbrInfo, vec3 lightDirection) {
2515
+ vec3 n = pbrInfo.n;
2516
+ vec3 v = pbrInfo.v;
2517
+ vec3 l = normalize(lightDirection); // Vector from surface point to light
2518
+ vec3 h = normalize(l+v); // Half vector between both l and v
1847
2519
 
1848
2520
  pbrInfo.NdotL = clamp(dot(n, l), 0.001, 1.0);
1849
2521
  pbrInfo.NdotH = clamp(dot(n, h), 0.0, 1.0);
@@ -1856,6 +2528,11 @@ void PBRInfo_setPointLight(inout PBRInfo pbrInfo, PointLight pointLight) {
1856
2528
  PBRInfo_setDirectionalLight(pbrInfo, light_direction);
1857
2529
  }
1858
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
+
1859
2536
  vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
1860
2537
  // Calculate the shading terms for the microfacet specular shading model
1861
2538
  vec3 F = specularReflection(pbrInfo);
@@ -1886,6 +2563,8 @@ vec4 pbr_filterColor(vec4 colorUnused)
1886
2563
 
1887
2564
  vec3 color = vec3(0, 0, 0);
1888
2565
 
2566
+ float transmission = 0.0;
2567
+
1889
2568
  if(pbrMaterial.unlit){
1890
2569
  color.rgb = baseColor.rgb;
1891
2570
  }
@@ -1904,14 +2583,252 @@ vec4 pbr_filterColor(vec4 colorUnused)
1904
2583
  #endif
1905
2584
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
1906
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
+
1907
2810
  // Roughness is authored as perceptual roughness; as is convention,
1908
2811
  // convert to material roughness by squaring the perceptual roughness [2].
1909
2812
  float alphaRoughness = perceptualRoughness * perceptualRoughness;
1910
2813
 
1911
- vec3 f0 = vec3(0.04);
1912
- vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
1913
- diffuseColor *= 1.0 - metallic;
1914
- 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;
1915
2832
 
1916
2833
  // Compute reflectance.
1917
2834
  float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
@@ -1923,11 +2840,6 @@ vec4 pbr_filterColor(vec4 colorUnused)
1923
2840
  float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
1924
2841
  vec3 specularEnvironmentR0 = specularColor.rgb;
1925
2842
  vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
1926
-
1927
- vec3 n = getNormal(); // normal at surface point
1928
- vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
1929
-
1930
- float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
1931
2843
  vec3 reflection = -normalize(reflect(v, n));
1932
2844
 
1933
2845
  PBRInfo pbrInfo = PBRInfo(
@@ -1951,13 +2863,33 @@ vec4 pbr_filterColor(vec4 colorUnused)
1951
2863
  #ifdef USE_LIGHTS
1952
2864
  // Apply ambient light
1953
2865
  PBRInfo_setAmbientLight(pbrInfo);
1954
- 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
+ );
1955
2877
 
1956
2878
  // Apply directional light
1957
2879
  for(int i = 0; i < lighting.directionalLightCount; i++) {
1958
2880
  if (i < lighting.directionalLightCount) {
1959
2881
  PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
1960
- 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
+ );
1961
2893
  }
1962
2894
  }
1963
2895
 
@@ -1966,7 +2898,35 @@ vec4 pbr_filterColor(vec4 colorUnused)
1966
2898
  if (i < lighting.pointLightCount) {
1967
2899
  PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
1968
2900
  float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
1969
- 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
+ );
1970
2930
  }
1971
2931
  }
1972
2932
  #endif
@@ -1974,7 +2934,16 @@ vec4 pbr_filterColor(vec4 colorUnused)
1974
2934
  // Calculate lighting contribution from image based lighting source (IBL)
1975
2935
  #ifdef USE_IBL
1976
2936
  if (pbrMaterial.IBLenabled) {
1977
- 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;
1978
2947
  }
1979
2948
  #endif
1980
2949
 
@@ -1986,12 +2955,17 @@ vec4 pbr_filterColor(vec4 colorUnused)
1986
2955
  }
1987
2956
  #endif
1988
2957
 
2958
+ vec3 emissive = pbrMaterial.emissiveFactor;
1989
2959
  #ifdef HAS_EMISSIVEMAP
1990
2960
  if (pbrMaterial.emissiveMapEnabled) {
1991
- vec3 emissive = SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
1992
- color += emissive;
2961
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
1993
2962
  }
1994
2963
  #endif
2964
+ color += emissive * pbrMaterial.emissiveStrength;
2965
+
2966
+ if (transmission > 0.0) {
2967
+ color = mix(color, color * getVolumeAttenuation(thickness), transmission);
2968
+ }
1995
2969
 
1996
2970
  // This section uses mix to override final color for reference app visualization
1997
2971
  // of various parameters in the lighting equation.
@@ -2011,62 +2985,103 @@ vec4 pbr_filterColor(vec4 colorUnused)
2011
2985
 
2012
2986
  }
2013
2987
 
2014
- 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);
2015
2990
  }
2016
- `;var st=`struct PBRFragmentInputs {
2991
+ `;var Rn=`struct PBRFragmentInputs {
2017
2992
  pbr_vPosition: vec3f,
2018
2993
  pbr_vUV: vec2f,
2019
- pbr_vTBN: mat3f,
2994
+ pbr_vTBN: mat3x3f,
2020
2995
  pbr_vNormal: vec3f
2021
2996
  };
2022
2997
 
2023
- var fragmentInputs: PBRFragmentInputs;
2998
+ var<private> fragmentInputs: PBRFragmentInputs;
2024
2999
 
2025
3000
  fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f, uv: vec2f)
2026
3001
  {
2027
3002
  var pos: vec4f = pbrProjection.modelMatrix * position;
2028
- fragmentInputs.pbr_vPosition = vec3(pos.xyz) / pos.w;
3003
+ fragmentInputs.pbr_vPosition = pos.xyz / pos.w;
3004
+ fragmentInputs.pbr_vNormal = vec3f(0.0, 0.0, 1.0);
3005
+ fragmentInputs.pbr_vTBN = mat3x3f(
3006
+ vec3f(1.0, 0.0, 0.0),
3007
+ vec3f(0.0, 1.0, 0.0),
3008
+ vec3f(0.0, 0.0, 1.0)
3009
+ );
3010
+ fragmentInputs.pbr_vUV = vec2f(0.0, 0.0);
2029
3011
 
2030
3012
  #ifdef HAS_NORMALS
3013
+ let normalW: vec3f = normalize((pbrProjection.normalMatrix * vec4f(normal.xyz, 0.0)).xyz);
3014
+ fragmentInputs.pbr_vNormal = normalW;
2031
3015
  #ifdef HAS_TANGENTS
2032
- let normalW: vec3f = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));
2033
- let tangentW: vec3f = normalize(vec3(pbrProjection.modelMatrix * vec4(tangent.xyz, 0.0)));
3016
+ let tangentW: vec3f = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);
2034
3017
  let bitangentW: vec3f = cross(normalW, tangentW) * tangent.w;
2035
- fragmentInputs.pbr_vTBN = mat3(tangentW, bitangentW, normalW);
2036
- #else // HAS_TANGENTS != 1
2037
- fragmentInputs.pbr_vNormal = normalize(vec3(pbrProjection.modelMatrix * vec4(normal.xyz, 0.0)));
3018
+ fragmentInputs.pbr_vTBN = mat3x3f(tangentW, bitangentW, normalW);
2038
3019
  #endif
2039
3020
  #endif
2040
3021
 
2041
3022
  #ifdef HAS_UV
2042
3023
  fragmentInputs.pbr_vUV = uv;
2043
- #else
2044
- fragmentInputs.pbr_vUV = vec2(0.,0.);
2045
3024
  #endif
2046
3025
  }
2047
3026
 
2048
3027
  struct pbrMaterialUniforms {
2049
3028
  // Material is unlit
2050
- unlit: uint32,
3029
+ unlit: u32,
2051
3030
 
2052
3031
  // Base color map
2053
- baseColorMapEnabled: uint32,
3032
+ baseColorMapEnabled: u32,
2054
3033
  baseColorFactor: vec4f,
2055
3034
 
2056
- normalMapEnabled : uint32,
3035
+ normalMapEnabled : u32,
2057
3036
  normalScale: f32, // #ifdef HAS_NORMALMAP
2058
3037
 
2059
- emissiveMapEnabled: uint32,
3038
+ emissiveMapEnabled: u32,
2060
3039
  emissiveFactor: vec3f, // #ifdef HAS_EMISSIVEMAP
2061
3040
 
2062
3041
  metallicRoughnessValues: vec2f,
2063
- metallicRoughnessMapEnabled: uint32,
3042
+ metallicRoughnessMapEnabled: u32,
2064
3043
 
2065
3044
  occlusionMapEnabled: i32,
2066
3045
  occlusionStrength: f32, // #ifdef HAS_OCCLUSIONMAP
2067
3046
 
2068
3047
  alphaCutoffEnabled: i32,
2069
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,
2070
3085
 
2071
3086
  // IBL
2072
3087
  IBLenabled: i32,
@@ -2075,34 +3090,81 @@ struct pbrMaterialUniforms {
2075
3090
  // debugging flags used for shader output of intermediate PBR variables
2076
3091
  // #ifdef PBR_DEBUG
2077
3092
  scaleDiffBaseMR: vec4f,
2078
- scaleFGDSpec: vec4f
3093
+ scaleFGDSpec: vec4f,
2079
3094
  // #endif
2080
3095
  }
2081
3096
 
2082
- @binding(2) @group(0) var<uniform> pbrMaterial : pbrMaterialUniforms;
3097
+ @group(3) @binding(auto) var<uniform> pbrMaterial : pbrMaterialUniforms;
2083
3098
 
2084
3099
  // Samplers
2085
3100
  #ifdef HAS_BASECOLORMAP
2086
- uniform sampler2D pbr_baseColorSampler;
3101
+ @group(3) @binding(auto) var pbr_baseColorSampler: texture_2d<f32>;
3102
+ @group(3) @binding(auto) var pbr_baseColorSamplerSampler: sampler;
2087
3103
  #endif
2088
3104
  #ifdef HAS_NORMALMAP
2089
- uniform sampler2D pbr_normalSampler;
3105
+ @group(3) @binding(auto) var pbr_normalSampler: texture_2d<f32>;
3106
+ @group(3) @binding(auto) var pbr_normalSamplerSampler: sampler;
2090
3107
  #endif
2091
3108
  #ifdef HAS_EMISSIVEMAP
2092
- uniform sampler2D pbr_emissiveSampler;
3109
+ @group(3) @binding(auto) var pbr_emissiveSampler: texture_2d<f32>;
3110
+ @group(3) @binding(auto) var pbr_emissiveSamplerSampler: sampler;
2093
3111
  #endif
2094
3112
  #ifdef HAS_METALROUGHNESSMAP
2095
- uniform sampler2D pbr_metallicRoughnessSampler;
3113
+ @group(3) @binding(auto) var pbr_metallicRoughnessSampler: texture_2d<f32>;
3114
+ @group(3) @binding(auto) var pbr_metallicRoughnessSamplerSampler: sampler;
2096
3115
  #endif
2097
3116
  #ifdef HAS_OCCLUSIONMAP
2098
- uniform sampler2D pbr_occlusionSampler;
3117
+ @group(3) @binding(auto) var pbr_occlusionSampler: texture_2d<f32>;
3118
+ @group(3) @binding(auto) var pbr_occlusionSamplerSampler: sampler;
2099
3119
  #endif
2100
- #ifdef USE_IBL
2101
- uniform samplerCube pbr_diffuseEnvSampler;
2102
- uniform samplerCube pbr_specularEnvSampler;
2103
- uniform sampler2D pbr_brdfLUT;
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;
2104
3167
  #endif
2105
-
2106
3168
  // Encapsulate the various inputs used by the various functions in the shading equation
2107
3169
  // We store values in this struct to simplify the integration of alternative implementations
2108
3170
  // of the shading terms, outlined in the Readme.MD Appendix.
@@ -2128,80 +3190,130 @@ const c_MinRoughness = 0.04;
2128
3190
 
2129
3191
  fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
2130
3192
  {
3193
+ var linOut: vec3f = srgbIn.xyz;
2131
3194
  #ifdef MANUAL_SRGB
3195
+ let bLess: vec3f = step(vec3f(0.04045), srgbIn.xyz);
3196
+ linOut = mix(
3197
+ srgbIn.xyz / vec3f(12.92),
3198
+ pow((srgbIn.xyz + vec3f(0.055)) / vec3f(1.055), vec3f(2.4)),
3199
+ bLess
3200
+ );
2132
3201
  #ifdef SRGB_FAST_APPROXIMATION
2133
- var linOut: vec3f = pow(srgbIn.xyz,vec3(2.2));
2134
- #else // SRGB_FAST_APPROXIMATION
2135
- var bLess: vec3f = step(vec3(0.04045),srgbIn.xyz);
2136
- var linOut: vec3f = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
2137
- #endif //SRGB_FAST_APPROXIMATION
2138
- return vec4f(linOut,srgbIn.w);;
2139
- #else //MANUAL_SRGB
2140
- return srgbIn;
2141
- #endif //MANUAL_SRGB
3202
+ linOut = pow(srgbIn.xyz, vec3f(2.2));
3203
+ #endif
3204
+ #endif
3205
+ return vec4f(linOut, srgbIn.w);
2142
3206
  }
2143
3207
 
2144
- // Find the normal for this fragment, pulling either from a predefined normal map
2145
- // or from the interpolated mesh normal and tangent attributes.
2146
- fn getNormal() -> vec3f
3208
+ // Build the tangent basis from interpolated attributes or screen-space derivatives.
3209
+ fn getTBN() -> mat3x3f
2147
3210
  {
2148
- // Retrieve the tangent space matrix
2149
- #ifndef HAS_TANGENTS
2150
- var pos_dx: vec3f = dFdx(fragmentInputs.pbr_vPosition);
2151
- var pos_dy: vec3f = dFdy(fragmentInputs.pbr_vPosition);
2152
- var tex_dx: vec3f = dFdx(vec3(fragmentInputs.pbr_vUV, 0.0));
2153
- var tex_dy: vec3f = dFdy(vec3(fragmentInputs.pbr_vUV, 0.0));
2154
- var t: vec3f = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
3211
+ let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);
3212
+ let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);
3213
+ let tex_dx: vec3f = dpdx(vec3f(fragmentInputs.pbr_vUV, 0.0));
3214
+ let tex_dy: vec3f = dpdy(vec3f(fragmentInputs.pbr_vUV, 0.0));
3215
+ var t: vec3f = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y);
2155
3216
 
2156
- #ifdef HAS_NORMALS
2157
- var ng: vec3f = normalize(fragmentInputs.pbr_vNormal);
2158
- #else
2159
3217
  var ng: vec3f = cross(pos_dx, pos_dy);
3218
+ #ifdef HAS_NORMALS
3219
+ ng = normalize(fragmentInputs.pbr_vNormal);
2160
3220
  #endif
2161
-
2162
3221
  t = normalize(t - ng * dot(ng, t));
2163
3222
  var b: vec3f = normalize(cross(ng, t));
2164
- var tbn: mat3f = mat3f(t, b, ng);
2165
- #else // HAS_TANGENTS
2166
- var tbn: mat3f = fragmentInputs.pbr_vTBN;
3223
+ var tbn: mat3x3f = mat3x3f(t, b, ng);
3224
+ #ifdef HAS_TANGENTS
3225
+ tbn = fragmentInputs.pbr_vTBN;
2167
3226
  #endif
2168
3227
 
2169
- #ifdef HAS_NORMALMAP
2170
- vec3 n = texture(pbr_normalSampler, fragmentInputs.pbr_vUV).rgb;
2171
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
2172
- #else
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
+ {
2173
3246
  // The tbn matrix is linearly interpolated, so we need to re-normalize
2174
- vec3 n = normalize(tbn[2].xyz);
3247
+ var n: vec3f = normalize(tbn[2].xyz);
3248
+ #ifdef HAS_NORMALMAP
3249
+ n = getMappedNormal(
3250
+ pbr_normalSampler,
3251
+ pbr_normalSamplerSampler,
3252
+ tbn,
3253
+ pbrMaterial.normalScale
3254
+ );
2175
3255
  #endif
2176
3256
 
2177
3257
  return n;
2178
3258
  }
2179
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
+
2180
3274
  // Calculation of the lighting contribution from an optional Image Based Light source.
2181
3275
  // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
2182
3276
  // See our README.md on Environment Maps [3] for additional discussion.
2183
3277
  #ifdef USE_IBL
2184
- fn getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection) -> vec3f
3278
+ fn getIBLContribution(pbrInfo: PBRInfo, n: vec3f, reflection: vec3f) -> vec3f
2185
3279
  {
2186
- float mipCount = 9.0; // resolution of 512x512
2187
- float lod = (pbrInfo.perceptualRoughness * mipCount);
3280
+ let mipCount: f32 = 9.0; // resolution of 512x512
3281
+ let lod: f32 = pbrInfo.perceptualRoughness * mipCount;
2188
3282
  // retrieve a scale and bias to F0. See [1], Figure 3
2189
- vec3 brdf = SRGBtoLINEAR(texture(pbr_brdfLUT,
2190
- vec2(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness))).rgb;
2191
- vec3 diffuseLight = SRGBtoLINEAR(texture(pbr_diffuseEnvSampler, n)).rgb;
2192
-
3283
+ let brdf = SRGBtoLINEAR(
3284
+ textureSampleLevel(
3285
+ pbr_brdfLUT,
3286
+ pbr_brdfLUTSampler,
3287
+ vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness),
3288
+ 0.0
3289
+ )
3290
+ ).rgb;
3291
+ let diffuseLight =
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;
2193
3303
  #ifdef USE_TEX_LOD
2194
- vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection, lod)).rgb;
2195
- #else
2196
- vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection)).rgb;
3304
+ specularLight = SRGBtoLINEAR(
3305
+ textureSampleLevel(
3306
+ pbr_specularEnvSampler,
3307
+ pbr_specularEnvSamplerSampler,
3308
+ reflection,
3309
+ lod
3310
+ )
3311
+ ).rgb;
2197
3312
  #endif
2198
3313
 
2199
- vec3 diffuse = diffuseLight * pbrInfo.diffuseColor;
2200
- vec3 specular = specularLight * (pbrInfo.specularColor * brdf.x + brdf.y);
2201
-
2202
- // For presentation, this allows us to disable IBL terms
2203
- diffuse *= pbrMaterial.scaleIBLAmbient.x;
2204
- specular *= pbrMaterial.scaleIBLAmbient.y;
3314
+ let diffuse = diffuseLight * pbrInfo.diffuseColor * pbrMaterial.scaleIBLAmbient.x;
3315
+ let specular =
3316
+ specularLight * (pbrInfo.specularColor * brdf.x + brdf.y) * pbrMaterial.scaleIBLAmbient.y;
2205
3317
 
2206
3318
  return diffuse + specular;
2207
3319
  }
@@ -2245,7 +3357,173 @@ fn geometricOcclusion(pbrInfo: PBRInfo) -> f32 {
2245
3357
  fn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {
2246
3358
  let roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;
2247
3359
  let f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;
2248
- return roughnessSq / (PI * f * f);
3360
+ return roughnessSq / (M_PI * f * f);
3361
+ }
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;
2249
3527
  }
2250
3528
 
2251
3529
  fn PBRInfo_setAmbientLight(pbrInfo: ptr<function, PBRInfo>) {
@@ -2272,6 +3550,11 @@ fn PBRInfo_setPointLight(pbrInfo: ptr<function, PBRInfo>, pointLight: PointLight
2272
3550
  PBRInfo_setDirectionalLight(pbrInfo, light_direction);
2273
3551
  }
2274
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
+
2275
3558
  fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
2276
3559
  // Calculate the shading terms for the microfacet specular shading model
2277
3560
  let F = specularReflection(pbrInfo);
@@ -2287,11 +3570,11 @@ fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
2287
3570
 
2288
3571
  fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2289
3572
  // The albedo may be defined from a base texture or a flat color
2290
- var baseColor: vec4<f32>;
3573
+ var baseColor: vec4<f32> = pbrMaterial.baseColorFactor;
2291
3574
  #ifdef HAS_BASECOLORMAP
2292
- baseColor = SRGBtoLINEAR(textureSample(pbr_baseColorSampler, pbr_baseColorSampler, fragmentInputs.pbr_vUV)) * pbrMaterial.baseColorFactor;
2293
- #else
2294
- baseColor = pbrMaterial.baseColorFactor;
3575
+ baseColor = SRGBtoLINEAR(
3576
+ textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, fragmentInputs.pbr_vUV)
3577
+ ) * pbrMaterial.baseColorFactor;
2295
3578
  #endif
2296
3579
 
2297
3580
  #ifdef ALPHA_CUTOFF
@@ -2301,8 +3584,9 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2301
3584
  #endif
2302
3585
 
2303
3586
  var color = vec3<f32>(0.0, 0.0, 0.0);
3587
+ var transmission = 0.0;
2304
3588
 
2305
- if (pbrMaterial.unlit) {
3589
+ if (pbrMaterial.unlit != 0u) {
2306
3590
  color = baseColor.rgb;
2307
3591
  } else {
2308
3592
  // Metallic and Roughness material properties are packed together
@@ -2313,20 +3597,318 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2313
3597
  #ifdef HAS_METALROUGHNESSMAP
2314
3598
  // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
2315
3599
  // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
2316
- let mrSample = textureSample(pbr_metallicRoughnessSampler, pbr_metallicRoughnessSampler, fragmentInputs.pbr_vUV);
3600
+ let mrSample = textureSample(
3601
+ pbr_metallicRoughnessSampler,
3602
+ pbr_metallicRoughnessSamplerSampler,
3603
+ fragmentInputs.pbr_vUV
3604
+ );
2317
3605
  perceptualRoughness = mrSample.g * perceptualRoughness;
2318
3606
  metallic = mrSample.b * metallic;
2319
3607
  #endif
2320
3608
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
2321
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
+
2322
3890
  // Roughness is authored as perceptual roughness; as is convention,
2323
3891
  // convert to material roughness by squaring the perceptual roughness [2].
2324
3892
  let alphaRoughness = perceptualRoughness * perceptualRoughness;
2325
3893
 
2326
- let f0 = vec3<f32>(0.04);
2327
- var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);
2328
- diffuseColor *= 1.0 - metallic;
2329
- 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;
2330
3912
 
2331
3913
  // Compute reflectance.
2332
3914
  let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
@@ -2338,11 +3920,6 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2338
3920
  let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
2339
3921
  let specularEnvironmentR0 = specularColor;
2340
3922
  let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;
2341
-
2342
- let n = getNormal(); // normal at surface point
2343
- let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera
2344
-
2345
- let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
2346
3923
  let reflection = -normalize(reflect(v, n));
2347
3924
 
2348
3925
  var pbrInfo = PBRInfo(
@@ -2365,13 +3942,33 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2365
3942
  #ifdef USE_LIGHTS
2366
3943
  // Apply ambient light
2367
3944
  PBRInfo_setAmbientLight(&pbrInfo);
2368
- 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
+ );
2369
3956
 
2370
3957
  // Apply directional light
2371
3958
  for (var i = 0; i < lighting.directionalLightCount; i++) {
2372
3959
  if (i < lighting.directionalLightCount) {
2373
3960
  PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
2374
- 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
+ );
2375
3972
  }
2376
3973
  }
2377
3974
 
@@ -2383,32 +3980,77 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2383
3980
  lighting_getPointLight(i),
2384
3981
  distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
2385
3982
  );
2386
- 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
+ );
2387
4012
  }
2388
4013
  }
2389
4014
  #endif
2390
4015
 
2391
4016
  // Calculate lighting contribution from image based lighting source (IBL)
2392
4017
  #ifdef USE_IBL
2393
- if (pbrMaterial.IBLenabled) {
2394
- color += getIBLContribution(pbrInfo, n, reflection);
4018
+ if (pbrMaterial.IBLenabled != 0) {
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;
2395
4029
  }
2396
4030
  #endif
2397
4031
 
2398
4032
  // Apply optional PBR terms for additional (optional) shading
2399
4033
  #ifdef HAS_OCCLUSIONMAP
2400
- if (pbrMaterial.occlusionMapEnabled) {
2401
- let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSampler, fragmentInputs.pbr_vUV).r;
4034
+ if (pbrMaterial.occlusionMapEnabled != 0) {
4035
+ let ao =
4036
+ textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, fragmentInputs.pbr_vUV).r;
2402
4037
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
2403
4038
  }
2404
4039
  #endif
2405
4040
 
4041
+ var emissive = pbrMaterial.emissiveFactor;
2406
4042
  #ifdef HAS_EMISSIVEMAP
2407
- if (pbrMaterial.emissiveMapEnabled) {
2408
- let emissive = SRGBtoLINEAR(textureSample(pbr_emissiveSampler, pbr_emissiveSampler, fragmentInputs.pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
2409
- color += emissive;
4043
+ if (pbrMaterial.emissiveMapEnabled != 0u) {
4044
+ emissive *= SRGBtoLINEAR(
4045
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
4046
+ ).rgb;
2410
4047
  }
2411
4048
  #endif
4049
+ color += emissive * pbrMaterial.emissiveStrength;
4050
+
4051
+ if (transmission > 0.0) {
4052
+ color = mix(color, color * getVolumeAttenuation(thickness), transmission);
4053
+ }
2412
4054
 
2413
4055
  // This section uses mix to override final color for reference app visualization
2414
4056
  // of various parameters in the lighting equation.
@@ -2427,14 +4069,23 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
2427
4069
  #endif
2428
4070
  }
2429
4071
 
2430
- 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);
2431
4074
  }
2432
- `;var ct=`uniform pbrProjectionUniforms {
4075
+ `;var In=`uniform pbrProjectionUniforms {
2433
4076
  mat4 modelViewProjectionMatrix;
2434
4077
  mat4 modelMatrix;
2435
4078
  mat4 normalMatrix;
2436
4079
  vec3 camera;
2437
4080
  } pbrProjection;
2438
- `,ft={name:"pbrProjection",vs:ct,fs:ct,getUniforms:e=>e,uniformTypes:{modelViewProjectionMatrix:"mat4x4<f32>",modelMatrix:"mat4x4<f32>",normalMatrix:"mat4x4<f32>",camera:"vec3<i32>"}};var ut={props:{},uniforms:{},name:"pbrMaterial",dependencies:[g,ft],source:st,vs:at,fs:lt,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 At(H);})();
4081
+ `,ho=`struct pbrProjectionUniforms {
4082
+ modelViewProjectionMatrix: mat4x4<f32>,
4083
+ modelMatrix: mat4x4<f32>,
4084
+ normalMatrix: mat4x4<f32>,
4085
+ camera: vec3<f32>
4086
+ };
4087
+
4088
+ @group(0) @binding(auto) var<uniform> pbrProjection: pbrProjectionUniforms;
4089
+ `,Cn={name:"pbrProjection",bindingLayout:[{name:"pbrProjection",group:0}],source:ho,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);})();
2439
4090
  return __exports__;
2440
4091
  });