PageSourceSearch

https://www.vzome.com/modules/chunk-PBSMYCQH.js

js vzome.com collected 2026-09-24 20:35:40 UTC 2,002,769 bytes, 56,077 lines download raw bytes

1import {
2  CSS2DObject,
3  CSS2DRenderer,
4  Canvas,
5  GLTFExporter,
6  TrackballControls,
7  createT,
8  createXR,
9  useFrame,
10  useThree
11} from "./chunk-6JQSYMRV.js";
12import {
13  REVISION as REVISION2
14} from "./chunk-YWNSTGG6.js";
15import {
16  CameraProvider,
17  ViewerProvider,
18  WorkerProvider,
19  createStore,
20  reconcile,
21  saveFileAs,
22  saveTextFileAs,
23  unwrap,
24  useCamera,
25  useViewer,
26  useWorkerClient
27} from "./chunk-737R77QV.js";
28import {
29  $TRACK,
30  ACESFilmicToneMapping,
31  AddEquation,
32  AddOperation,
33  AdditiveBlending,
34  AgXToneMapping,
35  AlphaFormat,
36  AlwaysCompare,
37  AlwaysDepth,
38  AlwaysStencilFunc,
39  AmbientLight,
40  ArrayCamera,
41  BackSide,
42  BasicShadowMap,
43  BoxGeometry,
44  BufferAttribute,
45  BufferGeometry,
46  ByteType,
47  CineonToneMapping,
48  ClampToEdgeWrapping,
49  Color,
50  ColorManagement,
51  Compatibility,
52  CubeCamera,
53  CubeDepthTexture,
54  CubeReflectionMapping,
55  CubeRefractionMapping,
56  CubeTexture,
57  CubeUVReflectionMapping,
58  CullFaceBack,
59  CullFaceFront,
60  CullFaceNone,
61  CustomBlending,
62  CylinderGeometry,
63  DEV,
64  DataArrayTexture,
65  DataTexture,
66  DecrementStencilOp,
67  DecrementWrapStencilOp,
68  DepthFormat,
69  DepthStencilFormat,
70  DepthTexture,
71  DirectionalLight,
72  DoubleSide,
73  DstAlphaFactor,
74  DstColorFactor,
75  Dynamic,
76  DynamicDrawUsage,
77  EqualCompare,
78  EqualDepth,
79  EqualStencilFunc,
80  EquirectangularReflectionMapping,
81  EquirectangularRefractionMapping,
82  Euler,
83  EventDispatcher,
84  Float16BufferAttribute,
85  Float32BufferAttribute,
86  FloatType,
87  For,
88  FramebufferTexture,
89  FrontSide,
90  Frustum,
91  FrustumArray,
92  GreaterCompare,
93  GreaterDepth,
94  GreaterEqualCompare,
95  GreaterEqualDepth,
96  GreaterEqualStencilFunc,
97  GreaterStencilFunc,
98  Group,
99  HalfFloatType,
100  HemisphereLight,
101  IncrementStencilOp,
102  IncrementWrapStencilOp,
103  InstancedBufferAttribute,
104  InstancedInterleavedBuffer,
105  InstancedMesh,
106  IntType,
107  InterleavedBuffer,
108  InterleavedBufferAttribute,
109  InvertStencilOp,
110  KeepStencilOp,
111  LessCompare,
112  LessDepth,
113  LessEqualCompare,
114  LessEqualDepth,
115  LessEqualStencilFunc,
116  LessStencilFunc,
117  LightProbe,
118  LineBasicMaterial,
119  LineDashedMaterial,
120  LineSegments,
121  LinearFilter,
122  LinearMipMapLinearFilter,
123  LinearMipmapLinearFilter,
124  LinearMipmapNearestFilter,
125  LinearSRGBColorSpace,
126  LinearToneMapping,
127  LinearTransfer,
128  Material,
129  MaterialBlending,
130  MathUtils,
131  Matrix2,
132  Matrix3,
133  Matrix4,
134  MaxEquation,
135  Mesh,
136  MeshBasicMaterial,
137  MeshLambertMaterial,
138  MeshMatcapMaterial,
139  MeshNormalMaterial,
140  MeshPhongMaterial,
141  MeshPhysicalMaterial,
142  MeshStandardMaterial,
143  MeshToonMaterial,
144  MinEquation,
145  MirroredRepeatWrapping,
146  MixOperation,
147  MultiplyBlending,
148  MultiplyOperation,
149  NearestFilter,
150  NearestMipmapLinearFilter,
151  NearestMipmapNearestFilter,
152  NeutralToneMapping,
153  NeverCompare,
154  NeverDepth,
155  NeverStencilFunc,
156  NoBlending,
157  NoColorSpace,
158  NoNormalPacking,
159  NoToneMapping,
160  NormalBlending,
161  NormalGAPacking,
162  NormalRGPacking,
163  NotEqualCompare,
164  NotEqualDepth,
165  NotEqualStencilFunc,
166  Object3D,
167  ObjectSpaceNormalMap,
168  OneFactor,
169  OneMinusDstAlphaFactor,
170  OneMinusDstColorFactor,
171  OneMinusSrcAlphaFactor,
172  OneMinusSrcColorFactor,
173  OrthographicCamera,
174  PCFShadowMap,
175  PCFSoftShadowMap,
176  PerspectiveCamera,
177  Plane,
178  PlaneGeometry,
179  PointLight,
180  PointsMaterial,
181  Portal,
182  Quaternion,
183  R11_EAC_Format,
184  RAD2DEG,
185  RED_GREEN_RGTC2_Format,
186  RED_RGTC1_Format,
187  REVISION,
188  RG11_EAC_Format,
189  RGBAFormat,
190  RGBAIntegerFormat,
191  RGBA_ASTC_10x10_Format,
192  RGBA_ASTC_10x5_Format,
193  RGBA_ASTC_10x6_Format,
194  RGBA_ASTC_10x8_Format,
195  RGBA_ASTC_12x10_Format,
196  RGBA_ASTC_12x12_Format,
197  RGBA_ASTC_4x4_Format,
198  RGBA_ASTC_5x4_Format,
199  RGBA_ASTC_5x5_Format,
200  RGBA_ASTC_6x5_Format,
201  RGBA_ASTC_6x6_Format,
202  RGBA_ASTC_8x5_Format,
203  RGBA_ASTC_8x6_Format,
204  RGBA_ASTC_8x8_Format,
205  RGBA_BPTC_Format,
206  RGBA_ETC2_EAC_Format,
207  RGBA_PVRTC_2BPPV1_Format,
208  RGBA_PVRTC_4BPPV1_Format,
209  RGBA_S3TC_DXT1_Format,
210  RGBA_S3TC_DXT3_Format,
211  RGBA_S3TC_DXT5_Format,
212  RGBFormat,
213  RGBIntegerFormat,
214  RGB_ETC1_Format,
215  RGB_ETC2_Format,
216  RGB_PVRTC_2BPPV1_Format,
217  RGB_PVRTC_4BPPV1_Format,
218  RGB_S3TC_DXT1_Format,
219  RGFormat,
220  RGIntegerFormat,
221  RectAreaLight,
222  RedFormat,
223  RedIntegerFormat,
224  ReinhardToneMapping,
225  RenderTarget,
226  RepeatWrapping,
227  ReplaceStencilOp,
228  ReverseSubtractEquation,
229  ReversedDepthFuncs,
230  SIGNED_R11_EAC_Format,
231  SIGNED_RED_GREEN_RGTC2_Format,
232  SIGNED_RED_RGTC1_Format,
233  SIGNED_RG11_EAC_Format,
234  SRGBColorSpace,
235  SRGBTransfer,
236  Scene,
237  ShadowMaterial,
238  ShortType,
239  Show,
240  Sphere,
241  SphereGeometry,
242  SpotLight,
243  SpriteMaterial,
244  SrcAlphaFactor,
245  SrcAlphaSaturateFactor,
246  SrcColorFactor,
247  StaticDrawUsage,
248  SubtractEquation,
249  SubtractiveBlending,
250  Suspense,
251  TangentSpaceNormalMap,
252  Texture,
253  TimestampQuery,
254  UVMapping,
255  Uint16BufferAttribute,
256  Uint32BufferAttribute,
257  UnsignedByteType,
258  UnsignedInt101111Type,
259  UnsignedInt248Type,
260  UnsignedInt5999Type,
261  UnsignedIntType,
262  UnsignedShort4444Type,
263  UnsignedShort5551Type,
264  UnsignedShortType,
265  VSMShadowMap,
266  Vector2,
267  Vector3,
268  Vector4,
269  WebGLCoordinateSystem,
270  WebGLRenderer,
271  WebGPUCoordinateSystem,
272  WebXRController,
273  ZeroFactor,
274  ZeroStencilOp,
275  addEventListener,
276  batch,
277  children,
278  createCanvasElement,
279  createComponent,
280  createComputed,
281  createContext,
282  createEffect,
283  createMemo,
284  createRenderEffect,
285  createResource,
286  createRoot,
287  createSignal,
288  createUniqueId,
289  delegateEvents,
290  error,
291  getByteLength,
292  getListener,
293  getOwner,
294  insert,
295  isServer,
296  isTypedArray,
297  lazy,
298  log,
299  memo,
300  mergeProps,
301  on,
302  onCleanup,
303  onMount,
304  render,
305  setAttribute,
306  sharedConfig,
307  splitProps,
308  style,
309  template,
310  untrack,
311  use,
312  useContext,
313  warn,
314  warnOnce,
315  yieldToMain
316} from "./chunk-47C2ISC4.js";
317import {
318  encodeEntities,
319  selectSnapshot
320} from "./chunk-J3RXXGCJ.js";
321
322// src/viewer/urlviewer.css.js
323var urlViewerCSS = `
324
325svg {
326  height: 100%;
327}
328
329.vzome-label {
330  color: var(--vzome-label-color);
331  background-color: var(--vzome-label-background);
332  font-size: var(--vzome-label-size);
333  font-style: var(--vzome-label-style);
334  font-weight: var(--vzome-label-weight);
335}
336
337.scene__select {
338  width: 200px;
339  border-radius: 6px;
340  padding: 0 10px 0 16px;
341  font-size: 16px;
342  line-height: 1;
343  height: 40px;
344  outline: none;
345  background-color: white;
346  border: 1px solid hsl(240 6% 90%);
347  color: hsl(240 4% 16%);
348  transition: border-color 250ms, color 250ms;
349  cursor: pointer;
350}
351.scene__select:hover {
352  border-color: hsl(240 5% 65%);
353}
354.scene__select:focus-visible {
355  outline: 2px solid hsl(200 98% 39%);
356  outline-offset: 2px;
357}
358
359.settings__overlay,
360.progress__overlay {
361  position: fixed;
362  inset: 0;
363  z-index: 50;
364  background-color: rgb(0 0 0 / 0.2);
365  // animation: overlayHide 250ms ease 100ms forwards;
366}
367.settings__overlay[data-expanded],
368.progress__overlay[data-expanded] {
369  // animation: overlayShow 250ms ease;
370}
371.settings__positioner,
372.progress__positioner {
373  position: fixed;
374  inset: 0;
375  z-index: 50;
376  display: flex;
377  align-items: center;
378  justify-content: center;
379}
380.settings__content,
381.progress__content {
382  z-index: 50;
383  max-width: min(calc(100vw - 16px), 500px);
384  border: 1px solid hsl(240 5% 84%);
385  border-radius: 6px;
386  padding: 16px;
387  background-color: white;
388  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
389  // animation: progress__contentHide 300ms ease-in forwards;
390}
391.settings__content[data-expanded],
392.progress__content[data-expanded] {
393  // animation: contentShow_scale 300ms ease-out;
394}
395
396
397.progress {
398  display: flex;
399  flex-direction: column;
400  gap: 2px;
401  width: 300px;
402}
403.progress__label-container {
404  display: flex;
405  justify-content: space-between;
406}
407.progress__label,
408.progress__value-label {
409  color: hsl(240 4% 16%);
410  font-size: 14px;
411}
412.progress__track {
413  height: 10px;
414  background-color: hsl(240 6% 90%);
415}
416.progress__fill {
417  background-color: hsl(200 98% 39%);
418  height: 100%;
419  width: var(--kb-progress-fill-width);
420  transition: width 250ms linear;
421}
422.progress__fill[data-progress="complete"] {
423  background-color: #16a34a;
424}
425
426
427.alert-dialog__trigger {
428  appearance: none;
429  display: inline-flex;
430  justify-content: center;
431  align-items: center;
432  height: 40px;
433  width: auto;
434  outline: none;
435  border-radius: 6px;
436  padding: 0 16px;
437  background-color: hsl(200 98% 39%);
438  color: white;
439  font-size: 16px;
440  line-height: 0;
441  transition: 250ms background-color;
442}
443.alert-dialog__trigger:hover {
444  background-color: hsl(201 96% 32%);
445}
446.alert-dialog__trigger:focus-visible {
447  outline: 2px solid hsl(200 98% 39%);
448  outline-offset: 2px;
449}
450.alert-dialog__trigger:active {
451  background-color: hsl(201 90% 27%);
452}
453.alert-dialog__overlay {
454  position: absolute;
455  inset: 0;
456  z-index: 50;
457  background-color: rgb(0 0 0 / 0.2);
458  animation: overlayHide 250ms ease 100ms forwards;
459}
460.alert-dialog__overlay[data-expanded] {
461  animation: overlayShow 250ms ease;
462}
463.alert-dialog__positioner {
464  position: absolute;
465  inset: 0;
466  z-index: 50;
467  display: flex;
468  align-items: center;
469  justify-content: center;
470}
471.alert-dialog__content {
472  z-index: 50;
473  max-width: min(calc(100vw - 16px), 500px);
474  border: 1px solid hsl(240 5% 84%);
475  border-radius: 6px;
476  padding: 16px;
477  background-color: darkred;
478  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
479  animation: contentHide 300ms ease-in forwards;
480}
481.alert-dialog__content[data-expanded] {
482  animation: alert__contentShow 300ms ease-out;
483}
484.alert-dialog__header {
485  display: flex;
486  align-items: baseline;
487  justify-content: space-between;
488  margin-bottom: 12px;
489}
490.alert-dialog__close-button {
491  display: inline-flex;
492  height: 16px;
493  width: 16px;
494  align-items: center;
495  border: none;
496  padding: unset;
497}
498.alert-dialog__title {
499  font-size: 20px;
500  font-weight: 500;
501  color: white;
502  margin-block: 0px;
503}
504.alert-dialog__description {
505  font-size: 16px;
506  color: white;
507  margin-block: 0px;
508  margin-bottom: 4px;
509}
510
511
512.settings-button {
513  appearance: none;
514  outline: none;
515  background-color: rgba(122, 122, 122, 0.3);
516  color: rgba(90,90,90, 1);
517  fill: currentColor;
518  transition: 250ms background-color;
519  position: absolute;
520  top: 0.5em;
521  right: 0.5em;
522  border-style: none;
523  width: 5em;
524  border-radius: 1.3rem;
525  padding-block: 0.4rem;
526  padding-inline: 0.7rem;
527}
528.settings-button:hover {
529  background-color: rgba(122, 122, 122, 0.7);
530}
531
532.settingsdialog__trigger {
533  appearance: none;
534  display: inline-flex;
535  justify-content: center;
536  align-items: center;
537  height: 40px;
538  width: auto;
539  outline: none;
540  border-radius: 6px;
541  padding: 0 16px;
542  background-color: hsl(200 98% 39%);
543  color: white;
544  font-size: 16px;
545  line-height: 0;
546  transition: 250ms background-color;
547}
548.settingsdialog__trigger:hover {
549  background-color: hsl(201 96% 32%);
550}
551.settingsdialog__trigger:focus-visible {
552  outline: 2px solid hsl(200 98% 39%);
553  outline-offset: 2px;
554}
555.settingsdialog__trigger:active {
556  background-color: hsl(201 90% 27%);
557}
558.settingsdialog__overlay {
559  position: fixed;
560  inset: 0;
561  z-index: 50;
562  background-color: rgb(0 0 0 / 0.2);
563  animation: settings__overlayHide 250ms ease 100ms forwards;
564}
565.settingsdialog__overlay[data-expanded] {
566  animation: settings__overlayShow 250ms ease;
567}
568.settingsdialog__positioner {
569  position: absolute;
570  inset: 0;
571  z-index: 50;
572  display: flex;
573  align-items: center;
574  justify-content: center;
575}
576.settingsdialog__content {
577  z-index: 50;
578  max-width: min(calc(100vw - 16px), 500px);
579  border: 1px solid hsl(240 5% 84%);
580  border-radius: 6px;
581  padding: 16px;
582  background-color: white;
583  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
584  animation: contentHide_scale 300ms ease-in forwards;
585}
586.settingsdialog__content[data-expanded] {
587  animation: contentShow_scale 300ms ease-out;
588}
589
590.settingsdialog__body {
591  display: flex;
592  padding: 1rem;
593  gap: 2rem;
594}
595
596.settingsdialog__header {
597  display: flex;
598  align-items: baseline;
599  justify-content: space-between;
600  margin-bottom: 12px;
601}
602.settingsdialog__close-button {
603  height: 16px;
604  width: 16px;
605  color: hsl(240 5% 34%);
606}
607.settingsdialog__title {
608  font-size: 20px;
609  font-weight: 500;
610  color: hsl(240 6% 10%);
611}
612.settingsdialog__description {
613  font-size: 16px;
614  color: hsl(240 5% 26%);
615}
616@keyframes settings__overlayShow {
617  from {
618    opacity: 0;
619  }
620  to {
621    opacity: 1;
622  }
623}
624@keyframes settings__overlayHide {
625  from {
626    opacity: 1;
627  }
628  to {
629    opacity: 0;
630  }
631}
632
633.corner__icon__button {
634  appearance: none;
635  display: inline-flex;
636  justify-content: center;
637  outline: none;
638  background-color: rgba(122, 122, 122, 0.3);
639  color: rgba(90,90,90, 1);
640  fill: currentColor;
641  font-size: 12px;
642  line-height: 0;
643  transition: 250ms background-color;
644  position: absolute;
645  border-style: none;
646  border-radius: 50%;
647  height: 4rem;
648  width: 4rem;
649  align-items: center;
650  padding: 0.7rem;
651}
652.corner__icon__button:hover {
653  background-color: rgba(122, 122, 122, 0.7);
654}
655.corner__icon__button:focus-visible {
656  outline: 2px solid hsl(200 98% 39%);
657  outline-offset: 2px;
658}
659.corner__icon__button:active {
660  background-color: rgba(0, 0, 0, 0.24);
661}
662
663
664.fullscreen {
665  bottom: 0.5em;
666  right: 0.5em;
667}
668
669.iconbutton__content {
670  z-index: 50;
671  max-width: min(calc(100vw - 16px), 380px);
672  border: 1px solid hsl(240 5% 84%);
673  border-radius: 6px;
674  padding: 8px;
675  background-color: hsl(240 4% 16%);
676  color: white;
677  font-size: 14px;
678  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
679  transform-origin: var(--kb-tooltip-content-transform-origin);
680  animation: contentHide_scale 250ms ease-in forwards;
681}
682.iconbutton__content[data-expanded] {
683  animation: contentShow_scale 250ms ease-out;
684}
685
686
687.exports__trigger {
688  bottom: 0.5em;
689  left: 0.5em;
690}
691.exports__content {
692  min-width: 220px;
693  padding: 8px;
694  background-color: white;
695  border-radius: 6px;
696  border: 1px solid hsl(240 6% 90%);
697  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
698  outline: none;
699  transform-origin: var(--kb-menu-content-transform-origin);
700  animation: contentHide_scale 250ms ease-in forwards;
701}
702.exports__content[data-expanded] {
703  animation: contentShow_scale 250ms ease-out;
704}
705.exports__item {
706  font-size: 16px;
707  line-height: 1;
708  color: hsl(240 4% 16%);
709  border-radius: 4px;
710  display: flex;
711  align-items: center;
712  height: 32px;
713  padding: 0 8px 0 24px;
714  position: relative;
715  user-select: none;
716  outline: none;
717}
718.exports__item[data-disabled] {
719  color: hsl(240 5% 65%);
720  opacity: 0.5;
721  pointer-events: none;
722}
723.exports__item[data-highlighted] {
724  outline: none;
725  background-color: hsl(200 98% 39%);
726  color: white;
727}
728
729@keyframes contentShow_scale {
730  from {
731    opacity: 0;
732    transform: scale(0.96);
733  }
734  to {
735    opacity: 1;
736    transform: scale(1);
737  }
738}
739@keyframes contentHide_scale {
740  from {
741    opacity: 1;
742    transform: scale(1);
743  }
744  to {
745    opacity: 0;
746    transform: scale(0.96);
747  }
748}
749
750
751@keyframes overlayShow {
752  from {
753    opacity: 0;
754  }
755  to {
756    opacity: 1;
757  }
758}
759@keyframes overlayHide {
760  from {
761    opacity: 1;
762  }
763  to {
764    opacity: 0;
765  }
766}
767
768.switch {
769  display: inline-flex;
770  align-items: center;
771}
772.switch__control {
773  display: inline-flex;
774  align-items: center;
775  height: 19px;
776  width: 33px;
777  border: 1px solid hsl(200 98% 39%);
778  border-radius: 12px;
779  padding: 0 2px;
780  background-color: hsl(200deg 38.91% 75%);
781  transition: 250ms background-color;
782}
783.switch__input:focus-visible + .switch__control {
784  outline: 2px solid hsl(200 98% 39%);
785  outline-offset: 2px;
786}
787.switch__control[data-checked] {
788  border-color: hsl(200 98% 39%);
789  background-color: hsl(200 98% 39%);
790}
791.switch__thumb {
792  height: 17px;
793  width: 17px;
794  border-radius: 10px;
795  background-color: white;
796  transition: 250ms transform;
797}
798.switch__thumb[data-checked] {
799  transform: translateX(calc(100% - 1px));
800}
801.switch__label {
802  margin-right: 6px;
803  color: hsl(240 6% 10%);
804  font-size: 14px;
805  user-select: none;
806}
807`;
808
809// src/viewer/context/scene.jsx
810var SceneContext = createContext({
811  scene: () => {
812    console.log("NO SceneProvider");
813  },
814  setSelectionHighlighter: () => {
815  },
816  highlightSelection: () => {
817  }
818});
819var SceneProvider = (props) => {
820  const {
821    labels: showLabels
822  } = props.config || {};
823  const [scene, setScene] = createStore({});
824  const [labels, setLabels] = createSignal(showLabels);
825  const addShape = (shape, id = shape.id) => {
826    if (!id) {
827      console.warn("Ignoring a shape with no id", shape);
828      return false;
829    }
830    if (!scene.shapes) {
831      setScene("shapes", {});
832    }
833    if (!scene?.shapes[id]) {
834      setScene("shapes", id, {
835        ...shape,
836        id
837      });
838      return true;
839    }
840    return false;
841  };
842  const updateShapes = (shapes) => {
843    for (const [id, shape] of Object.entries(shapes)) {
844      if (!addShape(shape, id)) {
845        if (!scene?.shapes?.[id]) continue;
846        setScene("shapes", id, "instances", shape.instances);
847      }
848    }
849    for (const id of Object.keys(scene?.shapes || {})) {
850      if (!(id in shapes)) setScene("shapes", id, "instances", []);
851    }
852  };
853  const resetScene = () => setScene(reconcile({}));
854  let selectionHighlighter = null;
855  const setSelectionHighlighter = (fn) => {
856    selectionHighlighter = fn;
857  };
858  const highlightSelection = (shapeId, id, selected) => selectionHighlighter?.(shapeId, id, selected);
859  const apiObject = {
860    scene,
861    setScene,
862    labels,
863    updateShapes,
864    addShape,
865    resetScene,
866    useViewer,
867    setSelectionHighlighter,
868    highlightSelection
869  };
870  return createComponent(SceneContext.Provider, {
871    value: apiObject,
872    get children() {
873      return props.children;
874    }
875  });
876};
877var useScene = () => {
878  return useContext(SceneContext);
879};
880var SceneIndexingContext = createContext({
881  showIndexedScene: () => {
882    console.log("NO SceneIndexingProvider");
883  }
884});
885var useSceneIndexing = () => {
886  return useContext(SceneIndexingContext);
887};
888var SceneIndexingProvider = (props) => {
889  const {
890    updateShapes,
891    setScene
892  } = useScene();
893  const {
894    postRequest
895  } = useWorkerClient();
896  const {
897    tweenCamera
898  } = useCamera();
899  const {
900    scenes
901  } = useViewer();
902  const [lastSceneIndex, setLastSceneIndex] = createSignal(null);
903  const showIndexedScene = (sceneIndex, config) => {
904    if (scenes.length === 0) return;
905    if (sceneIndex >= scenes.length) sceneIndex = 0;
906    postRequest(selectSnapshot(scenes[sceneIndex].snapshot)).then(({
907      payload: {
908        scene
909      }
910    }) => {
911      setLastSceneIndex(sceneIndex);
912      setScene("embedding", reconcile(scene.embedding));
913      setScene("polygons", scene.polygons);
914      if (scene.orientations) setScene("orientations", scene.orientations);
915      const {
916        camera
917      } = config || {
918        camera: true
919      };
920      setTimeout(() => {
921        (camera ? tweenCamera(scenes[sceneIndex].camera) : Promise.resolve()).then(() => updateShapes(scene.shapes));
922      });
923    });
924  };
925  createEffect(() => {
926    if (props.index !== void 0) {
927      console.log(`SceneIndexingProvider effect showing ${props.index}`);
928      showIndexedScene(props.index);
929    }
930  });
931  return createComponent(SceneIndexingContext.Provider, {
932    value: {
933      showIndexedScene,
934      lastSceneIndex,
935      setLastSceneIndex
936    },
937    get children() {
938      return props.children;
939    }
940  });
941};
942var SceneTitlesContext = createContext({
943  showTitledScene: () => {
944    console.log("NO SceneTitlesProvider");
945  }
946});
947var useSceneTitles = () => {
948  return useContext(SceneTitlesContext);
949};
950var unnamedScene = (scene, index) => !scene.title?.trim() || index === 0 && "default scene" === scene.title;
951var getSceneTitleIndex = (scenes, title) => {
952  if (!title) return 0;
953  title = encodeEntities(title);
954  let index;
955  if (title.startsWith("#")) {
956    const indexStr = title.substring(1);
957    index = parseInt(indexStr);
958    if (isNaN(index) || index < 0 || index > scenes.length) {
959      console.log(`WARNING: ${index} is not a scene index`);
960      index = 0;
961    }
962  } else {
963    index = scenes.map((s) => s.title?.trim()).indexOf(title);
964    if (index < 0) {
965      console.log(`WARNING: no scene titled "${title}"`);
966      index = 0;
967    }
968  }
969  return index;
970};
971var SceneTitlesProvider = (props) => {
972  const {
973    scenes
974  } = useViewer();
975  const {
976    showIndexedScene
977  } = useSceneIndexing();
978  const namedScenes = () => scenes.filter((scene, index) => !unnamedScene(scene, index)).map((scene) => scene.title);
979  const sceneTitles = () => props.show === "given" ? [] : props.show === "titled" ? namedScenes() : scenes.map((scene, index) => scene.title?.trim() || (index === 0 ? "default scene" : `#${index}`));
980  const [sceneTitle, setSceneTitle] = createSignal(props.show === "given" ? props.title : sceneTitles()[0]);
981  if (props.show !== "given") {
982    createEffect(() => {
983      if (sceneTitle() === void 0 && scenes.length > 0) {
984        setSceneTitle(sceneTitles()[0]);
985      }
986    });
987  }
988  const showTitledScene = (name, config) => {
989    const index = getSceneTitleIndex(scenes, name);
990    if (index < scenes.length) {
991      showIndexedScene(index, config);
992    }
993  };
994  return createComponent(SceneTitlesContext.Provider, {
995    value: {
996      showTitledScene,
997      sceneTitle,
998      setSceneTitle,
999      sceneTitles
1000    },
1001    get children() {
1002      return props.children;
1003    }
1004  });
1005};
1006var SceneChangeListener = () => {
1007  const {
1008    scene,
1009    updateShapes,
1010    addShape,
1011    setScene,
1012    highlightSelection
1013  } = useScene();
1014  const {
1015    subscribeFor
1016  } = useWorkerClient();
1017  const storeSceneSymmetryId = () => scene.symmetryId;
1018  subscribeFor("SYMMETRY_CHANGED", ({
1019    orientations,
1020    fieldName,
1021    symmetryName,
1022    embedding
1023  }) => {
1024    const nextSymmetryId = fieldName && symmetryName ? `${fieldName}:${symmetryName}` : void 0;
1025    batch(() => {
1026      const symmetryChanged = nextSymmetryId === void 0 || nextSymmetryId !== scene.symmetryId;
1027      if (symmetryChanged) setScene("shapes", reconcile({}));
1028      if (nextSymmetryId) setScene("symmetryId", nextSymmetryId);
1029      setScene("orientations", orientations);
1030      if (embedding) setScene("embedding", reconcile(embedding));
1031    });
1032  });
1033  subscribeFor("SCENE_RENDERED", ({
1034    scene: scene2
1035  }) => {
1036    if (scene2.symmetryId && storeSceneSymmetryId() && scene2.symmetryId !== storeSceneSymmetryId()) return;
1037    setScene("embedding", reconcile(scene2.embedding));
1038    setScene("polygons", scene2.polygons);
1039    if (scene2.orientations) setScene("orientations", scene2.orientations);
1040    updateShapes(scene2.shapes);
1041  });
1042  subscribeFor("SHAPE_DEFINED", (shape) => {
1043    addShape({
1044      ...shape,
1045      instances: []
1046    });
1047  });
1048  subscribeFor("INSTANCE_ADDED", (instance3) => {
1049    const {
1050      shapeId,
1051      orientation
1052    } = instance3;
1053    const shape = scene.shapes[shapeId];
1054    const rotation = unwrap(scene.orientations[orientation < 0 ? 0 : orientation]);
1055    setScene("shapes", shape.id, "instances", [...shape.instances, {
1056      ...instance3,
1057      rotation
1058    }]);
1059  });
1060  subscribeFor("INSTANCE_REMOVED", ({
1061    shapeId,
1062    id
1063  }) => {
1064    const shape = scene.shapes[shapeId];
1065    const instances = shape.instances.filter((instance3) => instance3.id != id);
1066    setScene("shapes", shape.id, "instances", instances);
1067  });
1068  subscribeFor("SELECTION_TOGGLED", ({
1069    shapeId,
1070    id,
1071    selected
1072  }) => {
1073    highlightSelection(shapeId, id, selected);
1074    const shape = scene.shapes[shapeId];
1075    const index = shape?.instances.findIndex((inst) => inst.id === id);
1076    if (index === void 0 || index < 0) return;
1077    setScene("shapes", shapeId, "instances", index, "selected", selected);
1078  });
1079  return null;
1080};
1081
1082// src/viewer/context/interaction.jsx
1083var InteractionToolContext = createContext([]);
1084var grabTool = {
1085  allowTrackball: true,
1086  // THIS is the reason this component exists
1087  cursor: "grab",
1088  onClick: () => {
1089  },
1090  bkgdClick: () => {
1091  },
1092  onDragStart: () => {
1093  },
1094  onDrag: () => {
1095  },
1096  onDragEnd: () => {
1097  },
1098  onTrackballEnd: () => {
1099  }
1100};
1101var MAX_CLICK_DURATION = 500;
1102var MAX_CLICK_DISTANCE = 2;
1103var InteractionToolProvider = (props) => {
1104  const [tool, setTool] = createSignal(props.defaultTool || grabTool);
1105  let lastPointerDown = null;
1106  let dragStartEmitted = false;
1107  const wrappedTool = {
1108    allowTrackball: () => tool()?.allowTrackball,
1109    cursor: () => tool()?.cursor,
1110    onClick: (id, position, type, selected) => tool()?.onClick(id, position, type, selected),
1111    bkgdClick: () => tool()?.bkgdClick(),
1112    onWheel: (dY) => tool()?.onWheel && tool().onWheel(dY),
1113    onDragStart: (e, id, position, type, selected) => {
1114      lastPointerDown = e;
1115      dragStartEmitted = false;
1116    },
1117    onDrag: (e, id, position, type, selected) => {
1118      if (lastPointerDown) {
1119        const deltaX = e.x - lastPointerDown.x;
1120        const deltaY = e.y - lastPointerDown.y;
1121        if (deltaX > MAX_CLICK_DISTANCE || deltaY > MAX_CLICK_DISTANCE) {
1122          if (!dragStartEmitted) {
1123            tool().onDragStart(lastPointerDown, id, position, type, selected);
1124            dragStartEmitted = true;
1125          }
1126          const handler = tool && tool()?.onDrag;
1127          if (handler) {
1128            handler(e, id, position, type, selected);
1129          }
1130        }
1131      }
1132    },
1133    onDragEnd: (e, id, position, type, selected, label3) => {
1134      if (dragStartEmitted) {
1135        const handler = tool && tool()?.onDragEnd;
1136        if (handler) {
1137          handler(e, id, position, type, selected, label3);
1138        }
1139        dragStartEmitted = false;
1140      } else {
1141        const handler = tool && tool()?.onClick;
1142        const deltaT = e.timeStamp - lastPointerDown?.timeStamp;
1143        if (handler && deltaT < MAX_CLICK_DURATION) {
1144          handler(id, position, type, selected, label3);
1145        }
1146      }
1147      lastPointerDown = null;
1148    },
1149    onTrackballEnd: () => {
1150      const handler = tool && tool()?.onTrackballEnd;
1151      if (handler) {
1152        handler();
1153      }
1154    },
1155    onContextMenu: (id, position, type, selected, label3) => tool()?.onContextMenu && tool().onContextMenu(id, position, type, selected, label3)
1156  };
1157  return createComponent(InteractionToolContext.Provider, {
1158    value: [wrappedTool, setTool],
1159    get children() {
1160      return props.children;
1161    }
1162  });
1163};
1164var useInteractionTool = () => {
1165  return useContext(InteractionToolContext);
1166};
1167
1168// src/viewer/context/export.jsx
1169var GltfExportContext = createContext({
1170  setExporter: () => {
1171  },
1172  exporter: () => {
1173  }
1174});
1175var GltfExportProvider = (props) => {
1176  const [exporter, setExporter] = createSignal({});
1177  return createComponent(GltfExportContext.Provider, {
1178    value: {
1179      exporter,
1180      setExporter
1181    },
1182    get children() {
1183      return props.children;
1184    }
1185  });
1186};
1187var useGltfExporter = () => {
1188  return useContext(GltfExportContext);
1189};
1190var ImageCaptureContext = createContext({
1191  setCapturer: () => {
1192  },
1193  capturer: () => {
1194  }
1195});
1196var ImageCaptureProvider = (props) => {
1197  const [capturer, setCapturer] = createSignal({});
1198  const captureImage = (format, params) => {
1199    return new Promise((resolve, reject) => {
1200      try {
1201        capturer().capture(format, resolve);
1202      } catch (error2) {
1203        reject(error2);
1204      }
1205    });
1206  };
1207  return createComponent(ImageCaptureContext.Provider, {
1208    value: {
1209      setCapturer,
1210      captureImage
1211    },
1212    get children() {
1213      return props.children;
1214    }
1215  });
1216};
1217var useImageCapture = () => {
1218  return useContext(ImageCaptureContext);
1219};
1220
vendor: 1,595,181 bytes, lines 1221-44227
1221// node_modules/three/build/three.webgpu.js
1222var refreshUniforms = [
1223  "alphaMap",
1224  "alphaTest",
1225  "anisotropy",
1226  "anisotropyMap",
1227  "anisotropyRotation",
1228  "aoMap",
1229  "aoMapIntensity",
1230  "attenuationColor",
1231  "attenuationDistance",
1232  "bumpMap",
1233  "clearcoat",
1234  "clearcoatMap",
1235  "clearcoatNormalMap",
1236  "clearcoatNormalScale",
1237  "clearcoatRoughness",
1238  "color",
1239  "dispersion",
1240  "displacementMap",
1241  "emissive",
1242  "emissiveIntensity",
1243  "emissiveMap",
1244  "envMap",
1245  "envMapIntensity",
1246  "gradientMap",
1247  "ior",
1248  "iridescence",
1249  "iridescenceIOR",
1250  "iridescenceMap",
1251  "iridescenceThicknessMap",
1252  "lightMap",
1253  "lightMapIntensity",
1254  "map",
1255  "matcap",
1256  "metalness",
1257  "metalnessMap",
1258  "normalMap",
1259  "normalScale",
1260  "opacity",
1261  "roughness",
1262  "roughnessMap",
1263  "sheen",
1264  "sheenColor",
1265  "sheenColorMap",
1266  "sheenRoughnessMap",
1267  "shininess",
1268  "specular",
1269  "specularColor",
1270  "specularColorMap",
1271  "specularIntensity",
1272  "specularIntensityMap",
1273  "specularMap",
1274  "thickness",
1275  "transmission",
1276  "transmissionMap"
1277];
1278var _lightsCache = /* @__PURE__ */ new WeakMap();
1279var _materialCache = /* @__PURE__ */ new WeakMap();
1280var _geometryCache = /* @__PURE__ */ new WeakMap();
1281var NodeMaterialObserver = class {
1282  /**
1283   * Constructs a new node material observer.
1284   *
1285   * @param {NodeBuilder} builder - The node builder.
1286   */
1287  constructor(builder) {
1288    this.renderObjects = /* @__PURE__ */ new WeakMap();
1289    this.hasNode = this.containsNode(builder);
1290    this.hasAnimation = builder.object.isSkinnedMesh === true;
1291    this.refreshUniforms = refreshUniforms;
1292    this.renderId = 0;
1293  }
1294  /**
1295   * Returns `true` if the given render object is verified for the first time of this observer.
1296   *
1297   * @param {RenderObject} renderObject - The render object.
1298   * @return {boolean} Whether the given render object is verified for the first time of this observer.
1299   */
1300  firstInitialization(renderObject) {
1301    const hasInitialized = this.renderObjects.has(renderObject);
1302    if (hasInitialized === false) {
1303      this.getRenderObjectData(renderObject);
1304      return true;
1305    }
1306    return false;
1307  }
1308  /**
1309   * Returns `true` if the current rendering produces motion vectors.
1310   *
1311   * @param {Renderer} renderer - The renderer.
1312   * @return {boolean} Whether the current rendering produces motion vectors or not.
1313   */
1314  needsVelocity(renderer) {
1315    const mrt3 = renderer.getMRT();
1316    return mrt3 !== null && mrt3.has("velocity");
1317  }
1318  /**
1319   * Returns monitoring data for the given render object.
1320   *
1321   * @param {RenderObject} renderObject - The render object.
1322   * @return {Object} The monitoring data.
1323   */
1324  getRenderObjectData(renderObject) {
1325    let data = this.renderObjects.get(renderObject);
1326    if (data === void 0) {
1327      const { geometry, object } = renderObject;
1328      data = {
1329        geometryId: geometry.id,
1330        worldMatrix: object.matrixWorld.clone()
1331      };
1332      if (object.center) {
1333        data.center = object.center.clone();
1334      }
1335      if (object.morphTargetInfluences) {
1336        data.morphTargetInfluences = object.morphTargetInfluences.slice();
1337      }
1338      if (renderObject.bundle !== null) {
1339        data.version = renderObject.bundle.version;
1340      }
1341      if (renderObject.material.transmission > 0) {
1342        const { width, height } = renderObject.context;
1343        data.bufferWidth = width;
1344        data.bufferHeight = height;
1345      }
1346      data.lights = this.getLightsData(renderObject.lightsNode.getLights());
1347      this.renderObjects.set(renderObject, data);
1348    }
1349    return data;
1350  }
1351  /**
1352   * Returns an attribute data structure holding the attributes versions for
1353   * monitoring.
1354   *
1355   * @param {Object} attributes - The geometry attributes.
1356   * @return {Object} An object for monitoring the versions of attributes.
1357   */
1358  getAttributesData(attributes) {
1359    const attributesData = {};
1360    for (const name in attributes) {
1361      const attribute3 = attributes[name];
1362      attributesData[name] = {
1363        id: attribute3.id,
1364        version: attribute3.version
1365      };
1366    }
1367    return attributesData;
1368  }
1369  /**
1370   * Returns `true` if the node builder's material uses
1371   * node properties.
1372   *
1373   * @param {NodeBuilder} builder - The current node builder.
1374   * @return {boolean} Whether the node builder's material uses node properties or not.
1375   */
1376  containsNode(builder) {
1377    const material = builder.material;
1378    for (const property3 in material) {
1379      if (material[property3] && material[property3].isNode)
1380        return true;
1381    }
1382    if (builder.context.modelViewMatrix || builder.context.modelNormalViewMatrix || builder.context.getAO || builder.context.getShadow)
1383      return true;
1384    return false;
1385  }
1386  /**
1387   * Returns a geometry data structure holding the geometry property values for
1388   * monitoring.
1389   *
1390   * @param {BufferGeometry} geometry - The geometry.
1391   * @return {Object} An object for monitoring geometry properties.
1392   */
1393  getGeometryData(geometry) {
1394    let data = _geometryCache.get(geometry);
1395    if (data === void 0) {
1396      data = {
1397        _renderId: -1,
1398        _equal: false,
1399        attributes: this.getAttributesData(geometry.attributes),
1400        indexId: geometry.index ? geometry.index.id : null,
1401        indexVersion: geometry.index ? geometry.index.version : null,
1402        drawRange: { start: geometry.drawRange.start, count: geometry.drawRange.count }
1403      };
1404      _geometryCache.set(geometry, data);
1405    }
1406    return data;
1407  }
1408  /**
1409   * Returns a material data structure holding the material property values for
1410   * monitoring.
1411   *
1412   * @param {Material} material - The material.
1413   * @return {Object} An object for monitoring material properties.
1414   */
1415  getMaterialData(material) {
1416    let data = _materialCache.get(material);
1417    if (data === void 0) {
1418      data = { _renderId: -1, _equal: false };
1419      for (const property3 of this.refreshUniforms) {
1420        const value = material[property3];
1421        if (value === null || value === void 0) continue;
1422        if (typeof value === "object" && value.clone !== void 0) {
1423          if (value.isTexture === true) {
1424            data[property3] = { id: value.id, version: value.version };
1425          } else {
1426            data[property3] = value.clone();
1427          }
1428        } else {
1429          data[property3] = value;
1430        }
1431      }
1432      _materialCache.set(material, data);
1433    }
1434    return data;
1435  }
1436  /**
1437   * Returns `true` if the given render object has not changed its state.
1438   *
1439   * @param {RenderObject} renderObject - The render object.
1440   * @param {Array<Light>} lightsData - The current material lights.
1441   * @param {number} renderId - The current render ID.
1442   * @return {boolean} Whether the given render object has changed its state or not.
1443   */
1444  equals(renderObject, lightsData, renderId) {
1445    const { object, material, geometry } = renderObject;
1446    const renderObjectData = this.getRenderObjectData(renderObject);
1447    if (renderObjectData.worldMatrix.equals(object.matrixWorld) !== true) {
1448      renderObjectData.worldMatrix.copy(object.matrixWorld);
1449      return false;
1450    }
1451    const materialData = this.getMaterialData(renderObject.material);
1452    if (materialData._renderId !== renderId) {
1453      materialData._renderId = renderId;
1454      for (const property3 in materialData) {
1455        const value = materialData[property3];
1456        const mtlValue = material[property3];
1457        if (property3 === "_renderId") continue;
1458        if (property3 === "_equal") continue;
1459        if (value.equals !== void 0) {
1460          if (value.equals(mtlValue) === false) {
1461            value.copy(mtlValue);
1462            materialData._equal = false;
1463            return false;
1464          }
1465        } else if (mtlValue.isTexture === true) {
1466          if (value.id !== mtlValue.id || value.version !== mtlValue.version) {
1467            value.id = mtlValue.id;
1468            value.version = mtlValue.version;
1469            materialData._equal = false;
1470            return false;
1471          }
1472        } else if (value !== mtlValue) {
1473          materialData[property3] = mtlValue;
1474          materialData._equal = false;
1475          return false;
1476        }
1477      }
1478      if (materialData.transmission > 0) {
1479        const { width, height } = renderObject.context;
1480        if (renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height) {
1481          renderObjectData.bufferWidth = width;
1482          renderObjectData.bufferHeight = height;
1483          materialData._equal = false;
1484          return false;
1485        }
1486      }
1487      materialData._equal = true;
1488    } else {
1489      if (materialData._equal === false) return false;
1490    }
1491    if (renderObjectData.geometryId !== geometry.id) {
1492      renderObjectData.geometryId = geometry.id;
1493      return false;
1494    }
1495    const geometryData = this.getGeometryData(renderObject.geometry);
1496    if (geometryData._renderId !== renderId) {
1497      geometryData._renderId = renderId;
1498      const attributes = geometry.attributes;
1499      const storedAttributes = geometryData.attributes;
1500      let currentAttributeCount = 0;
1501      let storedAttributeCount = 0;
1502      for (const _ in attributes) currentAttributeCount++;
1503      for (const name in storedAttributes) {
1504        storedAttributeCount++;
1505        const storedAttributeData = storedAttributes[name];
1506        const attribute3 = attributes[name];
1507        if (attribute3 === void 0) {
1508          delete storedAttributes[name];
1509          geometryData._equal = false;
1510          return false;
1511        }
1512        if (storedAttributeData.id !== attribute3.id || storedAttributeData.version !== attribute3.version) {
1513          storedAttributeData.id = attribute3.id;
1514          storedAttributeData.version = attribute3.version;
1515          geometryData._equal = false;
1516          return false;
1517        }
1518      }
1519      if (storedAttributeCount !== currentAttributeCount) {
1520        geometryData.attributes = this.getAttributesData(attributes);
1521        geometryData._equal = false;
1522        return false;
1523      }
1524      const index = geometry.index;
1525      const storedIndexId = geometryData.indexId;
1526      const storedIndexVersion = geometryData.indexVersion;
1527      const currentIndexId = index ? index.id : null;
1528      const currentIndexVersion = index ? index.version : null;
1529      if (storedIndexId !== currentIndexId || storedIndexVersion !== currentIndexVersion) {
1530        geometryData.indexId = currentIndexId;
1531        geometryData.indexVersion = currentIndexVersion;
1532        geometryData._equal = false;
1533        return false;
1534      }
1535      if (geometryData.drawRange.start !== geometry.drawRange.start || geometryData.drawRange.count !== geometry.drawRange.count) {
1536        geometryData.drawRange.start = geometry.drawRange.start;
1537        geometryData.drawRange.count = geometry.drawRange.count;
1538        geometryData._equal = false;
1539        return false;
1540      }
1541      geometryData._equal = true;
1542    } else {
1543      if (geometryData._equal === false) return false;
1544    }
1545    if (renderObjectData.morphTargetInfluences) {
1546      let morphChanged = false;
1547      for (let i = 0; i < renderObjectData.morphTargetInfluences.length; i++) {
1548        if (renderObjectData.morphTargetInfluences[i] !== object.morphTargetInfluences[i]) {
1549          renderObjectData.morphTargetInfluences[i] = object.morphTargetInfluences[i];
1550          morphChanged = true;
1551        }
1552      }
1553      if (morphChanged) return false;
1554    }
1555    if (renderObjectData.lights) {
1556      for (let i = 0; i < lightsData.length; i++) {
1557        if (renderObjectData.lights[i].map !== lightsData[i].map) {
1558          return false;
1559        }
1560      }
1561    }
1562    if (renderObjectData.center) {
1563      if (renderObjectData.center.equals(object.center) === false) {
1564        renderObjectData.center.copy(object.center);
1565        return true;
1566      }
1567    }
1568    if (renderObject.bundle !== null) {
1569      renderObjectData.version = renderObject.bundle.version;
1570    }
1571    return true;
1572  }
1573  /**
1574   * Returns the lights data for the given material lights.
1575   *
1576   * @param {Array<Light>} materialLights - The material lights.
1577   * @return {Array<Object>} The lights data for the given material lights.
1578   */
1579  getLightsData(materialLights) {
1580    const lights3 = [];
1581    for (const light of materialLights) {
1582      if (light.isSpotLight === true && light.map !== null) {
1583        lights3.push({ map: light.map.version });
1584      }
1585    }
1586    return lights3;
1587  }
1588  /**
1589   * Returns the lights for the given lights node and render ID.
1590   *
1591   * @param {LightsNode} lightsNode - The lights node.
1592   * @param {number} renderId - The render ID.
1593   * @return {Array<Object>} The lights for the given lights node and render ID.
1594   */
1595  getLights(lightsNode, renderId) {
1596    if (_lightsCache.has(lightsNode)) {
1597      const cached = _lightsCache.get(lightsNode);
1598      if (cached.renderId === renderId) {
1599        return cached.lightsData;
1600      }
1601    }
1602    const lightsData = this.getLightsData(lightsNode.getLights());
1603    _lightsCache.set(lightsNode, { renderId, lightsData });
1604    return lightsData;
1605  }
1606  /**
1607   * Checks if the given render object requires a refresh.
1608   *
1609   * @param {RenderObject} renderObject - The render object.
1610   * @param {NodeFrame} nodeFrame - The current node frame.
1611   * @return {boolean} Whether the given render object requires a refresh or not.
1612   */
1613  needsRefresh(renderObject, nodeFrame) {
1614    if (this.hasNode || this.hasAnimation || this.firstInitialization(renderObject) || this.needsVelocity(nodeFrame.renderer))
1615      return true;
1616    const { renderId } = nodeFrame;
1617    if (this.renderId !== renderId) {
1618      this.renderId = renderId;
1619      return true;
1620    }
1621    const isStatic = renderObject.object.static === true;
1622    const isBundle = renderObject.bundle !== null && renderObject.bundle.static === true && this.getRenderObjectData(renderObject).version === renderObject.bundle.version;
1623    if (isStatic || isBundle)
1624      return false;
1625    const lightsData = this.getLights(renderObject.lightsNode, renderId);
1626    const notEqual3 = this.equals(renderObject, lightsData, renderId) !== true;
1627    return notEqual3;
1628  }
1629};
1630var IGNORED_FILES = [
1631  /^StackTrace\.js$/,
1632  /^TSLCore\.js$/,
1633  /^.*Node\.js$/,
1634  /^three\.webgpu.*\.js$/
1635];
1636function getFilteredStack(stack3) {
1637  const regex = /(?:at\s+(.+?)\s+\()?(?:(.+?)@)?([^@\s()]+):(\d+):(\d+)/;
1638  return stack3.split("\n").map((line) => {
1639    const match = line.match(regex);
1640    if (!match) return null;
1641    const fn = match[1] || match[2] || "";
1642    const file = match[3].split("?")[0];
1643    const lineNum = parseInt(match[4], 10);
1644    const column = parseInt(match[5], 10);
1645    const fileName = file.split("/").pop();
1646    return {
1647      fn,
1648      file: fileName,
1649      line: lineNum,
1650      column
1651    };
1652  }).filter((frame) => {
1653    return frame && !IGNORED_FILES.some((regex2) => regex2.test(frame.file));
1654  });
1655}
1656var StackTrace = class {
1657  /**
1658   * Creates a StackTrace instance by capturing and filtering the current stack trace.
1659   *
1660   * @param {Error|string|null} stackMessage - An optional stack trace to use instead of capturing a new one.
1661   */
1662  constructor(stackMessage = null) {
1663    this.isStackTrace = true;
1664    this.stack = getFilteredStack(stackMessage ? stackMessage : new Error().stack);
1665  }
1666  /**
1667   * Returns a formatted location string of the top stack frame.
1668   *
1669   * @returns {string} The formatted stack trace message.
1670   */
1671  getLocation() {
1672    if (this.stack.length === 0) {
1673      return "[Unknown location]";
1674    }
1675    const mainStack = this.stack[0];
1676    const fn = mainStack.fn;
1677    const fnName = fn ? `"${fn}()" at ` : "";
1678    return `${fnName}"${mainStack.file}:${mainStack.line}"`;
1679  }
1680  /**
1681   * Returns the full error message including the stack trace.
1682   *
1683   * @param {string} message - The error message.
1684   * @returns {string} The full error message with stack trace.
1685   */
1686  getError(message) {
1687    if (this.stack.length === 0) {
1688      return message;
1689    }
1690    const stackString = this.stack.map((frame) => {
1691      const location = `${frame.file}:${frame.line}:${frame.column}`;
1692      if (frame.fn) {
1693        return `    at ${frame.fn} (${location})`;
1694      }
1695      return `    at ${location}`;
1696    }).join("\n");
1697    return `${message}
1698${stackString}`;
1699  }
1700};
1701function cyrb53(value, seed = 0) {
1702  let h12 = 3735928559 ^ seed, h2 = 1103547991 ^ seed;
1703  if (Array.isArray(value)) {
1704    for (let i = 0, val; i < value.length; i++) {
1705      val = value[i];
1706      h12 = Math.imul(h12 ^ val, 2654435761);
1707      h2 = Math.imul(h2 ^ val, 1597334677);
1708    }
1709  } else {
1710    for (let i = 0, ch; i < value.length; i++) {
1711      ch = value.charCodeAt(i);
1712      h12 = Math.imul(h12 ^ ch, 2654435761);
1713      h2 = Math.imul(h2 ^ ch, 1597334677);
1714    }
1715  }
1716  h12 = Math.imul(h12 ^ h12 >>> 16, 2246822507);
1717  h12 ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
1718  h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507);
1719  h2 ^= Math.imul(h12 ^ h12 >>> 13, 3266489909);
1720  return 4294967296 * (2097151 & h2) + (h12 >>> 0);
1721}
1722var hashString = (str) => cyrb53(str);
1723var hashArray = (array3) => cyrb53(array3);
1724var hash$1 = (...params) => cyrb53(params);
1725var typeFromLength = /* @__PURE__ */ new Map([
1726  [1, "float"],
1727  [2, "vec2"],
1728  [3, "vec3"],
1729  [4, "vec4"],
1730  [9, "mat3"],
1731  [16, "mat4"]
1732]);
1733var dataFromObject = /* @__PURE__ */ new WeakMap();
1734function getTypeFromLength(length3) {
1735  return typeFromLength.get(length3);
1736}
1737function getTypedArrayFromType(type) {
1738  if (/[iu]?vec\d/.test(type)) {
1739    if (type.startsWith("ivec")) return Int32Array;
1740    if (type.startsWith("uvec")) return Uint32Array;
1741    return Float32Array;
1742  }
1743  if (/mat\d/.test(type)) return Float32Array;
1744  if (/float/.test(type)) return Float32Array;
1745  if (/uint/.test(type)) return Uint32Array;
1746  if (/int/.test(type)) return Int32Array;
1747  throw new Error(`THREE.NodeUtils: Unsupported type: ${type}`);
1748}
1749function getLengthFromType(type) {
1750  if (/float|int|uint/.test(type)) return 1;
1751  if (/vec2/.test(type)) return 2;
1752  if (/vec3/.test(type)) return 3;
1753  if (/vec4/.test(type)) return 4;
1754  if (/mat2/.test(type)) return 4;
1755  if (/mat3/.test(type)) return 9;
1756  if (/mat4/.test(type)) return 16;
1757  error(`TSL: Unsupported type: ${type}`, new StackTrace());
1758}
1759function getMemoryLengthFromType(type) {
1760  if (/float|int|uint/.test(type)) return 1;
1761  if (/vec2/.test(type)) return 2;
1762  if (/vec3/.test(type)) return 3;
1763  if (/vec4/.test(type)) return 4;
1764  if (/mat2/.test(type)) return 4;
1765  if (/mat3/.test(type)) return 12;
1766  if (/mat4/.test(type)) return 16;
1767  error(`TSL: Unsupported type: ${type}`, new StackTrace());
1768}
1769function getAlignmentFromType(type) {
1770  if (/float|int|uint/.test(type)) return 4;
1771  if (/vec2/.test(type)) return 8;
1772  if (/vec3/.test(type)) return 16;
1773  if (/vec4/.test(type)) return 16;
1774  if (/mat2/.test(type)) return 8;
1775  if (/mat3/.test(type)) return 16;
1776  if (/mat4/.test(type)) return 16;
1777  error(`TSL: Unsupported type: ${type}`, new StackTrace());
1778}
1779function getValueType(value) {
1780  if (value === void 0 || value === null) return null;
1781  const typeOf = typeof value;
1782  if (value.isNode === true) {
1783    return "node";
1784  } else if (typeOf === "number") {
1785    return "float";
1786  } else if (typeOf === "boolean") {
1787    return "bool";
1788  } else if (typeOf === "string") {
1789    return "string";
1790  } else if (typeOf === "function") {
1791    return "shader";
1792  } else if (value.isVector2 === true) {
1793    return "vec2";
1794  } else if (value.isVector3 === true) {
1795    return "vec3";
1796  } else if (value.isVector4 === true) {
1797    return "vec4";
1798  } else if (value.isMatrix2 === true) {
1799    return "mat2";
1800  } else if (value.isMatrix3 === true) {
1801    return "mat3";
1802  } else if (value.isMatrix4 === true) {
1803    return "mat4";
1804  } else if (value.isColor === true) {
1805    return "color";
1806  } else if (value instanceof ArrayBuffer) {
1807    return "ArrayBuffer";
1808  }
1809  return null;
1810}
1811function getValueFromType(type, ...params) {
1812  const last4 = type ? type.slice(-4) : void 0;
1813  if (params.length === 1) {
1814    if (last4 === "vec2") params = [params[0], params[0]];
1815    else if (last4 === "vec3") params = [params[0], params[0], params[0]];
1816    else if (last4 === "vec4") params = [params[0], params[0], params[0], params[0]];
1817  }
1818  if (type === "color") {
1819    return new Color(...params);
1820  } else if (last4 === "vec2") {
1821    return new Vector2(...params);
1822  } else if (last4 === "vec3") {
1823    return new Vector3(...params);
1824  } else if (last4 === "vec4") {
1825    return new Vector4(...params);
1826  } else if (last4 === "mat2") {
1827    return new Matrix2(...params);
1828  } else if (last4 === "mat3") {
1829    return new Matrix3(...params);
1830  } else if (last4 === "mat4") {
1831    return new Matrix4(...params);
1832  } else if (type === "bool") {
1833    return params[0] || false;
1834  } else if (type === "float" || type === "int" || type === "uint") {
1835    return params[0] || 0;
1836  } else if (type === "string") {
1837    return params[0] || "";
1838  } else if (type === "ArrayBuffer") {
1839    return base64ToArrayBuffer(params[0]);
1840  }
1841  return null;
1842}
1843function getDataFromObject(object) {
1844  let data = dataFromObject.get(object);
1845  if (data === void 0) {
1846    data = {};
1847    dataFromObject.set(object, data);
1848  }
1849  return data;
1850}
1851function arrayBufferToBase64(arrayBuffer3) {
1852  let chars = "";
1853  const array3 = new Uint8Array(arrayBuffer3);
1854  for (let i = 0; i < array3.length; i++) {
1855    chars += String.fromCharCode(array3[i]);
1856  }
1857  return btoa(chars);
1858}
1859function base64ToArrayBuffer(base64) {
1860  return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)).buffer;
1861}
1862var NodeShaderStage = {
1863  VERTEX: "vertex",
1864  FRAGMENT: "fragment"
1865};
1866var NodeUpdateType = {
1867  NONE: "none",
1868  FRAME: "frame",
1869  RENDER: "render",
1870  OBJECT: "object"
1871};
1872var NodeType = {
1873  BOOLEAN: "bool",
1874  INTEGER: "int",
1875  FLOAT: "float",
1876  VECTOR2: "vec2",
1877  VECTOR3: "vec3",
1878  VECTOR4: "vec4",
1879  MATRIX2: "mat2",
1880  MATRIX3: "mat3",
1881  MATRIX4: "mat4"
1882};
1883var NodeAccess = {
1884  READ_ONLY: "readOnly",
1885  WRITE_ONLY: "writeOnly",
1886  READ_WRITE: "readWrite"
1887};
1888var defaultShaderStages = ["fragment", "vertex"];
1889var defaultBuildStages = ["setup", "analyze", "generate"];
1890var shaderStages = [...defaultShaderStages, "compute"];
1891var vectorComponents = ["x", "y", "z", "w"];
1892var _parentBuildStage = {
1893  analyze: "setup",
1894  generate: "analyze"
1895};
1896var _nodeId = 0;
1897var Node2 = class _Node extends EventDispatcher {
1898  static get type() {
1899    return "Node";
1900  }
1901  /**
1902   * Constructs a new node.
1903   *
1904   * @param {?string} nodeType - The node type.
1905   */
1906  constructor(nodeType = null) {
1907    super();
1908    this.nodeType = nodeType;
1909    this.updateType = NodeUpdateType.NONE;
1910    this.updateBeforeType = NodeUpdateType.NONE;
1911    this.updateAfterType = NodeUpdateType.NONE;
1912    this.version = 0;
1913    this.name = "";
1914    this.global = false;
1915    this.parents = false;
1916    this.isNode = true;
1917    this._beforeNodes = null;
1918    this._cacheKey = null;
1919    this._uuid = null;
1920    this._cacheKeyVersion = 0;
1921    this.id = _nodeId++;
1922    this.stackTrace = null;
1923    if (_Node.captureStackTrace === true) {
1924      this.stackTrace = new StackTrace();
1925    }
1926  }
1927  /**
1928   * Set this property to `true` when the node should be regenerated.
1929   *
1930   * @type {boolean}
1931   * @default false
1932   * @param {boolean} value
1933   */
1934  set needsUpdate(value) {
1935    if (value === true) {
1936      this.version++;
1937    }
1938  }
1939  /**
1940   * The UUID of the node.
1941   *
1942   * @type {string}
1943   * @readonly
1944   */
1945  get uuid() {
1946    if (this._uuid === null) {
1947      this._uuid = MathUtils.generateUUID();
1948    }
1949    return this._uuid;
1950  }
1951  /**
1952   * The type of the class. The value is usually the constructor name.
1953   *
1954   * @type {string}
1955  	 * @readonly
1956   */
1957  get type() {
1958    return this.constructor.type;
1959  }
1960  /**
1961   * Convenient method for defining {@link Node#update}.
1962   *
1963   * @param {Function} callback - The update method.
1964   * @param {string} updateType - The update type.
1965   * @return {Node} A reference to this node.
1966   */
1967  onUpdate(callback, updateType) {
1968    this.updateType = updateType;
1969    this.update = callback.bind(this);
1970    return this;
1971  }
1972  /**
1973   * Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but
1974   * this method automatically sets the update type to `FRAME`.
1975   *
1976   * @param {Function} callback - The update method.
1977   * @return {Node} A reference to this node.
1978   */
1979  onFrameUpdate(callback) {
1980    return this.onUpdate(callback, NodeUpdateType.FRAME);
1981  }
1982  /**
1983   * Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but
1984   * this method automatically sets the update type to `RENDER`.
1985   *
1986   * @param {Function} callback - The update method.
1987   * @return {Node} A reference to this node.
1988   */
1989  onRenderUpdate(callback) {
1990    return this.onUpdate(callback, NodeUpdateType.RENDER);
1991  }
1992  /**
1993   * Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but
1994   * this method automatically sets the update type to `OBJECT`.
1995   *
1996   * @param {Function} callback - The update method.
1997   * @return {Node} A reference to this node.
1998   */
1999  onObjectUpdate(callback) {
2000    return this.onUpdate(callback, NodeUpdateType.OBJECT);
2001  }
2002  /**
2003   * Convenient method for defining {@link Node#updateReference}.
2004   *
2005   * @param {Function} callback - The update method.
2006   * @return {Node} A reference to this node.
2007   */
2008  onReference(callback) {
2009    this.updateReference = callback.bind(this);
2010    return this;
2011  }
2012  /**
2013   * Nodes might refer to other objects like materials. This method allows to dynamically update the reference
2014   * to such objects based on a given state (e.g. the current node frame or builder).
2015   *
2016   * @param {any} state - This method can be invocated in different contexts so `state` can refer to any object type.
2017   * @return {any} The updated reference.
2018   */
2019  updateReference() {
2020    return this;
2021  }
2022  /**
2023   * By default this method returns the value of the {@link Node#global} flag. This method
2024   * can be overwritten in derived classes if an analytical way is required to determine the
2025   * global cache referring to the current shader-stage.
2026   *
2027   * @param {NodeBuilder} builder - The current node builder.
2028   * @return {boolean} Whether this node is global or not.
2029   */
2030  isGlobal() {
2031    return this.global;
2032  }
2033  /**
2034   * Generator function that can be used to iterate over the child nodes.
2035   *
2036   * @generator
2037   * @yields {Node} A child node.
2038   */
2039  *getChildren() {
2040    for (const { childNode } of this._getChildren()) {
2041      yield childNode;
2042    }
2043  }
2044  /**
2045   * Calling this method dispatches the `dispose` event. This event can be used
2046   * to register event listeners for clean up tasks.
2047   */
2048  dispose() {
2049    this.dispatchEvent({ type: "dispose" });
2050  }
2051  /**
2052   * Callback for {@link Node#traverse}.
2053   *
2054   * @callback traverseCallback
2055   * @param {Node} node - The current node.
2056   */
2057  /**
2058   * Can be used to traverse through the node's hierarchy.
2059   *
2060   * @param {traverseCallback} callback - A callback that is executed per node.
2061   */
2062  traverse(callback) {
2063    callback(this);
2064    for (const childNode of this.getChildren()) {
2065      childNode.traverse(callback);
2066    }
2067  }
2068  /**
2069   * Returns the child nodes of this node.
2070   *
2071   * @private
2072   * @param {Set<Node>} [ignores=new Set()] - A set of nodes to ignore during the search to avoid circular references.
2073   * @returns {Array<Object>} An array of objects describing the child nodes.
2074   */
2075  _getChildren(ignores = /* @__PURE__ */ new Set()) {
2076    const children2 = [];
2077    ignores.add(this);
2078    for (const property3 of Object.getOwnPropertyNames(this)) {
2079      const object = this[property3];
2080      if (property3.startsWith("_") === true || ignores.has(object)) continue;
2081      if (Array.isArray(object) === true) {
2082        for (let i = 0; i < object.length; i++) {
2083          const child = object[i];
2084          if (child && child.isNode === true) {
2085            children2.push({ property: property3, index: i, childNode: child });
2086          }
2087        }
2088      } else if (object && object.isNode === true) {
2089        children2.push({ property: property3, childNode: object });
2090      } else if (object && Object.getPrototypeOf(object) === Object.prototype) {
2091        for (const subProperty in object) {
2092          if (subProperty.startsWith("_") === true) continue;
2093          const child = object[subProperty];
2094          if (child && child.isNode === true) {
2095            children2.push({ property: property3, index: subProperty, childNode: child });
2096          }
2097        }
2098      }
2099    }
2100    return children2;
2101  }
2102  /**
2103   * Returns the cache key for this node.
2104   *
2105   * @param {boolean} [force=false] - When set to `true`, a recomputation of the cache key is forced.
2106   * @param {Set<Node>} [ignores=null] - A set of nodes to ignore during the computation of the cache key.
2107   * @return {number} The cache key of the node.
2108   */
2109  getCacheKey(force = false, ignores = null) {
2110    force = force || this.version !== this._cacheKeyVersion;
2111    if (force === true || this._cacheKey === null) {
2112      if (ignores === null) ignores = /* @__PURE__ */ new Set();
2113      const values = [];
2114      for (const { property: property3, childNode } of this._getChildren(ignores)) {
2115        values.push(hashString(property3.slice(0, -4)), childNode.getCacheKey(force, ignores));
2116      }
2117      this._cacheKey = hash$1(hashArray(values), this.customCacheKey());
2118      this._cacheKeyVersion = this.version;
2119    }
2120    return this._cacheKey;
2121  }
2122  /**
2123   * Generate a custom cache key for this node.
2124   *
2125   * @return {number} The cache key of the node.
2126   */
2127  customCacheKey() {
2128    return this.id;
2129  }
2130  /**
2131   * Returns the references to this node which is by default `this`.
2132   *
2133   * @return {Node} A reference to this node.
2134   */
2135  getScope() {
2136    return this;
2137  }
2138  /**
2139   * Returns the hash of the node which is used to identify the node. By default it's
2140   * the {@link Node#uuid} however derived node classes might have to overwrite this method
2141   * depending on their implementation.
2142   *
2143   * @param {NodeBuilder} builder - The current node builder.
2144   * @return {string} The hash.
2145   */
2146  getHash() {
2147    return String(this.id);
2148  }
2149  /**
2150   * Returns the update type of {@link Node#update}.
2151   *
2152   * @return {NodeUpdateType} The update type.
2153   */
2154  getUpdateType() {
2155    return this.updateType;
2156  }
2157  /**
2158   * Returns the update type of {@link Node#updateBefore}.
2159   *
2160   * @return {NodeUpdateType} The update type.
2161   */
2162  getUpdateBeforeType() {
2163    return this.updateBeforeType;
2164  }
2165  /**
2166   * Returns the update type of {@link Node#updateAfter}.
2167   *
2168   * @return {NodeUpdateType} The update type.
2169   */
2170  getUpdateAfterType() {
2171    return this.updateAfterType;
2172  }
2173  /**
2174   * Certain types are composed of multiple elements. For example a `vec3`
2175   * is composed of three `float` values. This method returns the type of
2176   * these elements.
2177   *
2178   * @param {NodeBuilder} builder - The current node builder.
2179   * @return {string} The type of the node.
2180   */
2181  getElementType(builder) {
2182    const type = this.getNodeType(builder);
2183    const elementType = builder.getElementType(type);
2184    return elementType;
2185  }
2186  /**
2187   * Returns the node member type for the given name.
2188   *
2189   * @param {NodeBuilder} builder - The current node builder.
2190   * @param {string} name - The name of the member.
2191   * @return {string} The type of the node.
2192   */
2193  getMemberType() {
2194    return "void";
2195  }
2196  /**
2197   * Returns the node's type.
2198   *
2199   * @param {NodeBuilder} builder - The current node builder.
2200   * @param {string} [output=null] - The output of the node.
2201   * @return {string} The type of the node.
2202   */
2203  getNodeType(builder, output3 = null) {
2204    const nodeData = builder.getDataFromNode(this);
2205    let type;
2206    if (output3 !== null) {
2207      nodeData.typeFromOutput = nodeData.typeFromOutput || {};
2208      type = nodeData.typeFromOutput[output3];
2209      if (type === void 0) {
2210        type = this.generateNodeType(builder, output3);
2211        nodeData.typeFromOutput[output3] = type;
2212      }
2213    } else {
2214      type = nodeData.type;
2215      if (type === void 0) {
2216        type = this.generateNodeType(builder);
2217        nodeData.type = type;
2218      }
2219    }
2220    return type;
2221  }
2222  /**
2223   * Returns the node's type.
2224   *
2225   * @param {NodeBuilder} builder - The current node builder.
2226   * @param {string} [output=null] - The output of the node.
2227   * @return {string} The type of the node.
2228   */
2229  generateNodeType(builder, output3 = null) {
2230    const nodeProperties = builder.getNodeProperties(this);
2231    if (nodeProperties.outputNode) {
2232      return nodeProperties.outputNode.getNodeType(builder, output3);
2233    }
2234    return this.nodeType;
2235  }
2236  /**
2237   * This method is used during the build process of a node and ensures
2238   * equal nodes are not built multiple times but just once. For example if
2239   * `attribute( 'uv' )` is used multiple times by the user, the build
2240   * process makes sure to process just the first node.
2241   *
2242   * @param {NodeBuilder} builder - The current node builder.
2243   * @return {Node} The shared node if possible. Otherwise `this` is returned.
2244   */
2245  getShared(builder) {
2246    const hash3 = this.getHash(builder);
2247    const nodeFromHash = builder.getNodeFromHash(hash3);
2248    return nodeFromHash || this;
2249  }
2250  /**
2251   * Returns the number of elements in the node array.
2252   *
2253   * @param {NodeBuilder} builder - The current node builder.
2254   * @return {?number} The number of elements in the node array.
2255   */
2256  getArrayCount() {
2257    return null;
2258  }
2259  /**
2260   * Represents the setup stage which is the first step of the build process, see {@link Node#build} method.
2261   * This method is often overwritten in derived modules to prepare the node which is used as a node's output/result.
2262   * If an output node is prepared, then it must be returned in the `return` statement of the derived module's setup function.
2263   *
2264   * @param {NodeBuilder} builder - The current node builder.
2265   * @return {?Node} The output node.
2266   */
2267  setup(builder) {
2268    const nodeProperties = builder.getNodeProperties(this);
2269    let index = 0;
2270    for (const childNode of this.getChildren()) {
2271      nodeProperties["node" + index++] = childNode;
2272    }
2273    return nodeProperties.outputNode || null;
2274  }
2275  /**
2276   * Represents the analyze stage which is the second step of the build process, see {@link Node#build} method.
2277   * This stage analyzes the node hierarchy and ensures descendent nodes are built.
2278   *
2279   * @param {NodeBuilder} builder - The current node builder.
2280   * @param {?Node} output - The target output node.
2281   */
2282  analyze(builder, output3 = null) {
2283    const usageCount = builder.increaseUsage(this);
2284    if (this.parents === true) {
2285      const nodeData = builder.getDataFromNode(this, "any");
2286      nodeData.stages = nodeData.stages || {};
2287      nodeData.stages[builder.shaderStage] = nodeData.stages[builder.shaderStage] || [];
2288      nodeData.stages[builder.shaderStage].push(output3);
2289    }
2290    if (usageCount === 1) {
2291      const nodeProperties = builder.getNodeProperties(this);
2292      for (const childNode of Object.values(nodeProperties)) {
2293        if (childNode && childNode.isNode === true) {
2294          childNode.build(builder, this);
2295        }
2296      }
2297    }
2298  }
2299  /**
2300   * Represents the generate stage which is the third step of the build process, see {@link Node#build} method.
2301   * This state builds the output node and returns the resulting shader string.
2302   *
2303   * @param {NodeBuilder} builder - The current node builder.
2304   * @param {?string} [output] - Can be used to define the output type.
2305   * @return {?string} The generated shader string.
2306   */
2307  generate(builder, output3) {
2308    const { outputNode } = builder.getNodeProperties(this);
2309    if (outputNode && outputNode.isNode === true) {
2310      return outputNode.build(builder, output3);
2311    }
2312  }
2313  /**
2314   * The method can be implemented to update the node's internal state before it is used to render an object.
2315   * The {@link Node#updateBeforeType} property defines how often the update is executed.
2316   *
2317   * @abstract
2318   * @param {NodeFrame} frame - A reference to the current node frame.
2319   * @return {?boolean} An optional bool that indicates whether the implementation actually performed an update or not (e.g. due to caching).
2320   */
2321  updateBefore() {
2322    warn("Abstract function.");
2323  }
2324  /**
2325   * The method can be implemented to update the node's internal state after it was used to render an object.
2326   * The {@link Node#updateAfterType} property defines how often the update is executed.
2327   *
2328   * @abstract
2329   * @param {NodeFrame} frame - A reference to the current node frame.
2330   * @return {?boolean} An optional bool that indicates whether the implementation actually performed an update or not (e.g. due to caching).
2331   */
2332  updateAfter() {
2333    warn("Abstract function.");
2334  }
2335  /**
2336   * The method can be implemented to update the node's internal state when it is used to render an object.
2337   * The {@link Node#updateType} property defines how often the update is executed.
2338   *
2339   * @abstract
2340   * @param {NodeFrame} frame - A reference to the current node frame.
2341   * @return {?boolean} An optional bool that indicates whether the implementation actually performed an update or not (e.g. due to caching).
2342   */
2343  update() {
2344    warn("Abstract function.");
2345  }
2346  before(node) {
2347    if (this._beforeNodes === null) this._beforeNodes = [];
2348    this._beforeNodes.push(node);
2349    return this;
2350  }
2351  /**
2352   * This method performs the build of a node. The behavior and return value depend on the current build stage:
2353   * - **setup**: Prepares the node and its children for the build process. This process can also create new nodes. Returns the node itself or a variant.
2354   * - **analyze**: Analyzes the node hierarchy for optimizations in the code generation stage. Returns `null`.
2355   * - **generate**: Generates the shader code for the node. Returns the generated shader string.
2356   *
2357   * @param {NodeBuilder} builder - The current node builder.
2358   * @param {?(string|Node)} [output=null] - Can be used to define the output type.
2359   * @return {?(Node|string)} The result of the build process, depending on the build stage.
2360   */
2361  build(builder, output3 = null) {
2362    const refNode = this.getShared(builder);
2363    if (this !== refNode) {
2364      return refNode.build(builder, output3);
2365    }
2366    if (this._beforeNodes !== null) {
2367      const currentBeforeNodes = this._beforeNodes;
2368      this._beforeNodes = null;
2369      for (const beforeNode of currentBeforeNodes) {
2370        beforeNode.build(builder, output3);
2371      }
2372      this._beforeNodes = currentBeforeNodes;
2373    }
2374    const nodeData = builder.getDataFromNode(this);
2375    nodeData.buildStages = nodeData.buildStages || {};
2376    nodeData.buildStages[builder.buildStage] = true;
2377    const parentBuildStage = _parentBuildStage[builder.buildStage];
2378    if (parentBuildStage && nodeData.buildStages[parentBuildStage] !== true) {
2379      const previousBuildStage = builder.getBuildStage();
2380      builder.setBuildStage(parentBuildStage);
2381      this.build(builder);
2382      builder.setBuildStage(previousBuildStage);
2383    }
2384    builder.addChain(this);
2385    let result = null;
2386    const buildStage = builder.getBuildStage();
2387    if (buildStage === "setup") {
2388      builder.addNode(this);
2389      this.updateReference(builder);
2390      const properties = builder.getNodeProperties(this);
2391      if (properties.initialized !== true) {
2392        properties.initialized = true;
2393        properties.outputNode = this.setup(builder) || properties.outputNode || null;
2394        for (const childNode of Object.values(properties)) {
2395          if (childNode && childNode.isNode === true) {
2396            if (childNode.parents === true) {
2397              const childProperties = builder.getNodeProperties(childNode);
2398              childProperties.parents = childProperties.parents || [];
2399              childProperties.parents.push(this);
2400            }
2401            childNode.build(builder);
2402          }
2403        }
2404        builder.addSequentialNode(this);
2405      }
2406      result = properties.outputNode;
2407    } else if (buildStage === "analyze") {
2408      this.analyze(builder, output3);
2409    } else if (buildStage === "generate") {
2410      const isGenerateOnce = this.generate.length < 2;
2411      if (isGenerateOnce) {
2412        const type = this.getNodeType(builder);
2413        const nodeData2 = builder.getDataFromNode(this);
2414        result = nodeData2.snippet;
2415        if (result === void 0) {
2416          if (nodeData2.generated === void 0) {
2417            nodeData2.generated = true;
2418            result = this.generate(builder) || "";
2419            nodeData2.snippet = result;
2420          } else {
2421            warn("Node: Recursion detected.", this);
2422            result = "/* Recursion detected. */";
2423          }
2424        } else if (nodeData2.flowCodes !== void 0 && builder.context.nodeBlock !== void 0) {
2425          builder.addFlowCodeHierarchy(this, builder.context.nodeBlock);
2426        }
2427        result = builder.format(result, type, output3);
2428      } else {
2429        result = this.generate(builder, output3) || "";
2430      }
2431      if (result === "" && output3 !== null && output3 !== "void" && output3 !== "OutputType") {
2432        error(`TSL: Invalid generated code, expected a "${output3}".`);
2433        result = builder.generateConst(output3);
2434      }
2435    }
2436    builder.removeChain(this);
2437    return result;
2438  }
2439  /**
2440   * Returns the child nodes as a JSON object.
2441   *
2442   * @return {Generator<Object>} An iterable list of serialized child objects as JSON.
2443   */
2444  getSerializeChildren() {
2445    return this._getChildren();
2446  }
2447  /**
2448   * Serializes the node to JSON.
2449   *
2450   * @param {Object} json - The output JSON object.
2451   */
2452  serialize(json) {
2453    const nodeChildren = this.getSerializeChildren();
2454    const inputNodes = {};
2455    for (const { property: property3, index, childNode } of nodeChildren) {
2456      if (index !== void 0) {
2457        if (inputNodes[property3] === void 0) {
2458          inputNodes[property3] = Number.isInteger(index) ? [] : {};
2459        }
2460        inputNodes[property3][index] = childNode.toJSON(json.meta).uuid;
2461      } else {
2462        inputNodes[property3] = childNode.toJSON(json.meta).uuid;
2463      }
2464    }
2465    if (Object.keys(inputNodes).length > 0) {
2466      json.inputNodes = inputNodes;
2467    }
2468  }
2469  /**
2470   * Deserializes the node from the given JSON.
2471   *
2472   * @param {Object} json - The JSON object.
2473   */
2474  deserialize(json) {
2475    if (json.inputNodes !== void 0) {
2476      const nodes = json.meta.nodes;
2477      for (const property3 in json.inputNodes) {
2478        if (Array.isArray(json.inputNodes[property3])) {
2479          const inputArray = [];
2480          for (const uuid of json.inputNodes[property3]) {
2481            inputArray.push(nodes[uuid]);
2482          }
2483          this[property3] = inputArray;
2484        } else if (typeof json.inputNodes[property3] === "object") {
2485          const inputObject = {};
2486          for (const subProperty in json.inputNodes[property3]) {
2487            const uuid = json.inputNodes[property3][subProperty];
2488            inputObject[subProperty] = nodes[uuid];
2489          }
2490          this[property3] = inputObject;
2491        } else {
2492          const uuid = json.inputNodes[property3];
2493          this[property3] = nodes[uuid];
2494        }
2495      }
2496    }
2497  }
2498  /**
2499   * Serializes the node into the three.js JSON Object/Scene format.
2500   *
2501   * @param {?Object} meta - An optional JSON object that already holds serialized data from other scene objects.
2502   * @return {Object} The serialized node.
2503   */
2504  toJSON(meta) {
2505    const { uuid, type } = this;
2506    const isRoot = meta === void 0 || typeof meta === "string";
2507    if (isRoot) {
2508      meta = {
2509        textures: {},
2510        images: {},
2511        nodes: {}
2512      };
2513    }
2514    let data = meta.nodes[uuid];
2515    if (data === void 0) {
2516      data = {
2517        uuid,
2518        type,
2519        meta,
2520        metadata: {
2521          version: 4.7,
2522          type: "Node",
2523          generator: "Node.toJSON"
2524        }
2525      };
2526      if (isRoot !== true) meta.nodes[data.uuid] = data;
2527      this.serialize(data);
2528      delete data.meta;
2529    }
2530    function extractFromCache(cache4) {
2531      const values = [];
2532      for (const key in cache4) {
2533        const data2 = cache4[key];
2534        delete data2.metadata;
2535        values.push(data2);
2536      }
2537      return values;
2538    }
2539    if (isRoot) {
2540      const textures = extractFromCache(meta.textures);
2541      const images = extractFromCache(meta.images);
2542      const nodes = extractFromCache(meta.nodes);
2543      if (textures.length > 0) data.textures = textures;
2544      if (images.length > 0) data.images = images;
2545      if (nodes.length > 0) data.nodes = nodes;
2546    }
2547    return data;
2548  }
2549};
2550Node2.captureStackTrace = false;
2551var ArrayElementNode = class extends Node2 {
2552  // @TODO: If extending from TempNode it breaks webgpu_compute
2553  static get type() {
2554    return "ArrayElementNode";
2555  }
2556  /**
2557   * Constructs an array element node.
2558   *
2559   * @param {Node} node - The array-like node.
2560   * @param {Node} indexNode - The index node that defines the element access.
2561   */
2562  constructor(node, indexNode) {
2563    super();
2564    this.node = node;
2565    this.indexNode = indexNode;
2566    this.isArrayElementNode = true;
2567  }
2568  /**
2569   * This method is overwritten since the node type is inferred from the array-like node.
2570   *
2571   * @param {NodeBuilder} builder - The current node builder.
2572   * @return {string} The node type.
2573   */
2574  generateNodeType(builder) {
2575    return this.node.getElementType(builder);
2576  }
2577  /**
2578   * This method is overwritten since the member type is inferred from the array-like node.
2579   *
2580   * @param {NodeBuilder} builder - The current node builder.
2581   * @param {string} name - The member name.
2582   * @return {string} The member type.
2583   */
2584  getMemberType(builder, name) {
2585    return this.node.getMemberType(builder, name);
2586  }
2587  generate(builder) {
2588    const indexType = this.indexNode.getNodeType(builder);
2589    const nodeSnippet = this.node.build(builder);
2590    const indexSnippet = this.indexNode.build(builder, !builder.isVector(indexType) && builder.isInteger(indexType) ? indexType : "uint");
2591    return `${nodeSnippet}[ ${indexSnippet} ]`;
2592  }
2593};
2594var ConvertNode = class extends Node2 {
2595  static get type() {
2596    return "ConvertNode";
2597  }
2598  /**
2599   * Constructs a new convert node.
2600   *
2601   * @param {Node} node - The node which type should be converted.
2602   * @param {string} convertTo - The target node type. Multiple types can be defined by separating them with a `|` sign.
2603   */
2604  constructor(node, convertTo) {
2605    super();
2606    this.node = node;
2607    this.convertTo = convertTo;
2608  }
2609  /**
2610   * This method is overwritten since the implementation tries to infer the best
2611   * matching type from the {@link ConvertNode#convertTo} property.
2612   *
2613   * @param {NodeBuilder} builder - The current node builder.
2614   * @return {string} The node type.
2615   */
2616  generateNodeType(builder) {
2617    const requestType = this.node.getNodeType(builder);
2618    let convertTo = null;
2619    for (const overloadingType of this.convertTo.split("|")) {
2620      if (convertTo === null || builder.getTypeLength(requestType) === builder.getTypeLength(overloadingType)) {
2621        convertTo = overloadingType;
2622      }
2623    }
2624    return convertTo;
2625  }
2626  serialize(data) {
2627    super.serialize(data);
2628    data.convertTo = this.convertTo;
2629  }
2630  deserialize(data) {
2631    super.deserialize(data);
2632    this.convertTo = data.convertTo;
2633  }
2634  generate(builder, output3) {
2635    const node = this.node;
2636    const type = this.getNodeType(builder);
2637    const snippet = node.build(builder, type);
2638    return builder.format(snippet, type, output3);
2639  }
2640};
2641var TempNode = class extends Node2 {
2642  static get type() {
2643    return "TempNode";
2644  }
2645  /**
2646   * Constructs a temp node.
2647   *
2648   * @param {?string} nodeType - The node type.
2649   */
2650  constructor(nodeType = null) {
2651    super(nodeType);
2652    this.isTempNode = true;
2653  }
2654  /**
2655   * Whether this node is used more than once in context of other nodes.
2656   *
2657   * @param {NodeBuilder} builder - The node builder.
2658   * @return {boolean} A flag that indicates if there is more than one dependency to other nodes.
2659   */
2660  hasDependencies(builder) {
2661    return builder.getDataFromNode(this).usageCount > 1;
2662  }
2663  build(builder, output3) {
2664    const buildStage = builder.getBuildStage();
2665    if (buildStage === "generate") {
2666      const type = builder.getVectorType(this.getNodeType(builder, output3));
2667      const nodeData = builder.getDataFromNode(this);
2668      if (nodeData.propertyName !== void 0) {
2669        return builder.format(nodeData.propertyName, type, output3);
2670      } else if (type !== "void" && output3 !== "void" && this.hasDependencies(builder)) {
2671        const snippet = super.build(builder, type);
2672        const nodeVar = builder.getVarFromNode(this, null, type);
2673        const propertyName = builder.getPropertyName(nodeVar);
2674        builder.addLineFlowCode(`${propertyName} = ${snippet}`, this);
2675        nodeData.snippet = snippet;
2676        nodeData.propertyName = propertyName;
2677        return builder.format(nodeData.propertyName, type, output3);
2678      }
2679    }
2680    return super.build(builder, output3);
2681  }
2682};
2683var JoinNode = class extends TempNode {
2684  static get type() {
2685    return "JoinNode";
2686  }
2687  /**
2688   * Constructs a new join node.
2689   *
2690   * @param {Array<Node>} nodes - An array of nodes that should be joined.
2691   * @param {?string} [nodeType=null] - The node type.
2692   */
2693  constructor(nodes = [], nodeType = null) {
2694    super(nodeType);
2695    this.nodes = nodes;
2696  }
2697  /**
2698   * This method is overwritten since the node type must be inferred from the
2699   * joined data length if not explicitly defined.
2700   *
2701   * @param {NodeBuilder} builder - The current node builder.
2702   * @return {string} The node type.
2703   */
2704  generateNodeType(builder) {
2705    if (this.nodeType !== null) {
2706      return builder.getVectorType(this.nodeType);
2707    }
2708    return builder.getTypeFromLength(this.nodes.reduce((count, cur) => count + builder.getTypeLength(cur.getNodeType(builder)), 0));
2709  }
2710  generate(builder, output3) {
2711    const type = this.getNodeType(builder);
2712    const maxLength = builder.getTypeLength(type);
2713    const nodes = this.nodes;
2714    const primitiveType = builder.getComponentType(type);
2715    const snippetValues = [];
2716    let length3 = 0;
2717    for (const input of nodes) {
2718      if (length3 >= maxLength) {
2719        error(`TSL: Length of parameters exceeds maximum length of function '${type}()' type.`, this.stackTrace);
2720        break;
2721      }
2722      let inputType = input.getNodeType(builder);
2723      let inputTypeLength = builder.getTypeLength(inputType);
2724      let inputSnippet;
2725      if (length3 + inputTypeLength > maxLength) {
2726        error(`TSL: Length of '${type}()' data exceeds maximum length of output type.`, this.stackTrace);
2727        inputTypeLength = maxLength - length3;
2728        inputType = builder.getTypeFromLength(inputTypeLength);
2729      }
2730      length3 += inputTypeLength;
2731      inputSnippet = input.build(builder, inputType);
2732      const inputPrimitiveType = builder.getComponentType(inputType);
2733      if (inputPrimitiveType !== primitiveType) {
2734        const targetType = builder.getTypeFromLength(inputTypeLength, primitiveType);
2735        inputSnippet = builder.format(inputSnippet, inputType, targetType);
2736      }
2737      snippetValues.push(inputSnippet);
2738    }
2739    const snippet = `${builder.getType(type)}( ${snippetValues.join(", ")} )`;
2740    return builder.format(snippet, type, output3);
2741  }
2742};
2743var _stringVectorComponents = vectorComponents.join("");
2744var SplitNode = class extends Node2 {
2745  static get type() {
2746    return "SplitNode";
2747  }
2748  /**
2749   * Constructs a new split node.
2750   *
2751   * @param {Node} node - The node that should be accessed.
2752   * @param {string} [components='x'] - The components that should be accessed.
2753   */
2754  constructor(node, components = "x") {
2755    super();
2756    this.node = node;
2757    this.components = components;
2758    this.isSplitNode = true;
2759  }
2760  /**
2761   * Returns the vector length which is computed based on the requested components.
2762   *
2763   * @return {number} The vector length.
2764   */
2765  getVectorLength() {
2766    let vectorLength = this.components.length;
2767    for (const c of this.components) {
2768      vectorLength = Math.max(vectorComponents.indexOf(c) + 1, vectorLength);
2769    }
2770    return vectorLength;
2771  }
2772  /**
2773   * Returns the component type of the node's type.
2774   *
2775   * @param {NodeBuilder} builder - The current node builder.
2776   * @return {string} The component type.
2777   */
2778  getComponentType(builder) {
2779    return builder.getComponentType(this.node.getNodeType(builder));
2780  }
2781  /**
2782   * This method is overwritten since the node type is inferred from requested components.
2783   *
2784   * @param {NodeBuilder} builder - The current node builder.
2785   * @return {string} The node type.
2786   */
2787  generateNodeType(builder) {
2788    return builder.getTypeFromLength(this.components.length, this.getComponentType(builder));
2789  }
2790  /**
2791   * Returns the scope of the node.
2792   *
2793   * @return {Node} The scope of the node.
2794   */
2795  getScope() {
2796    return this.node.getScope();
2797  }
2798  generate(builder, output3) {
2799    const node = this.node;
2800    const nodeTypeLength = builder.getTypeLength(node.getNodeType(builder));
2801    let snippet = null;
2802    if (nodeTypeLength > 1) {
2803      let type = null;
2804      const componentsLength = this.getVectorLength();
2805      if (componentsLength >= nodeTypeLength) {
2806        type = builder.getTypeFromLength(this.getVectorLength(), this.getComponentType(builder));
2807      }
2808      const nodeSnippet = node.build(builder, type);
2809      if (this.components.length === nodeTypeLength && this.components === _stringVectorComponents.slice(0, this.components.length)) {
2810        snippet = builder.format(nodeSnippet, type, output3);
2811      } else {
2812        snippet = builder.format(`${nodeSnippet}.${this.components}`, this.getNodeType(builder), output3);
2813      }
2814    } else {
2815      snippet = node.build(builder, output3);
2816    }
2817    return snippet;
2818  }
2819  serialize(data) {
2820    super.serialize(data);
2821    data.components = this.components;
2822  }
2823  deserialize(data) {
2824    super.deserialize(data);
2825    this.components = data.components;
2826  }
2827};
2828var SetNode = class extends TempNode {
2829  static get type() {
2830    return "SetNode";
2831  }
2832  /**
2833   * Constructs a new set node.
2834   *
2835   * @param {Node} sourceNode - The node that should be updated.
2836   * @param {string} components - The components that should be updated.
2837   * @param {Node} targetNode - The value node.
2838   */
2839  constructor(sourceNode, components, targetNode) {
2840    super();
2841    this.sourceNode = sourceNode;
2842    this.components = components;
2843    this.targetNode = targetNode;
2844  }
2845  /**
2846   * This method is overwritten since the node type is inferred from {@link SetNode#sourceNode}.
2847   *
2848   * @param {NodeBuilder} builder - The current node builder.
2849   * @return {string} The node type.
2850   */
2851  generateNodeType(builder) {
2852    return this.sourceNode.getNodeType(builder);
2853  }
2854  generate(builder) {
2855    const { sourceNode, components, targetNode } = this;
2856    const sourceType = this.getNodeType(builder);
2857    const componentType = builder.getComponentType(targetNode.getNodeType(builder));
2858    const targetType = builder.getTypeFromLength(components.length, componentType);
2859    const targetSnippet = targetNode.build(builder, targetType);
2860    const sourceSnippet = sourceNode.build(builder, sourceType);
2861    const length3 = builder.getTypeLength(sourceType);
2862    const snippetValues = [];
2863    for (let i = 0; i < length3; i++) {
2864      const component = vectorComponents[i];
2865      if (component === components[0]) {
2866        snippetValues.push(targetSnippet);
2867        i += components.length - 1;
2868      } else {
2869        snippetValues.push(sourceSnippet + "." + component);
2870      }
2871    }
2872    return `${builder.getType(sourceType)}( ${snippetValues.join(", ")} )`;
2873  }
2874};
2875var FlipNode = class extends TempNode {
2876  static get type() {
2877    return "FlipNode";
2878  }
2879  /**
2880   * Constructs a new flip node.
2881   *
2882   * @param {Node} sourceNode - The node which component(s) should be flipped.
2883   * @param {string} components - The components that should be flipped e.g. `'x'` or `'xy'`.
2884   */
2885  constructor(sourceNode, components) {
2886    super();
2887    this.sourceNode = sourceNode;
2888    this.components = components;
2889  }
2890  /**
2891   * This method is overwritten since the node type is inferred from the source node.
2892   *
2893   * @param {NodeBuilder} builder - The current node builder.
2894   * @return {string} The node type.
2895   */
2896  generateNodeType(builder) {
2897    return this.sourceNode.getNodeType(builder);
2898  }
2899  generate(builder) {
2900    const { components, sourceNode } = this;
2901    const sourceType = this.getNodeType(builder);
2902    const sourceSnippet = sourceNode.build(builder);
2903    const sourceCache = builder.getVarFromNode(this);
2904    const sourceProperty = builder.getPropertyName(sourceCache);
2905    builder.addLineFlowCode(sourceProperty + " = " + sourceSnippet, this);
2906    const length3 = builder.getTypeLength(sourceType);
2907    const snippetValues = [];
2908    let componentIndex = 0;
2909    for (let i = 0; i < length3; i++) {
2910      const component = vectorComponents[i];
2911      if (component === components[componentIndex]) {
2912        snippetValues.push("1.0 - " + (sourceProperty + "." + component));
2913        componentIndex++;
2914      } else {
2915        snippetValues.push(sourceProperty + "." + component);
2916      }
2917    }
2918    return `${builder.getType(sourceType)}( ${snippetValues.join(", ")} )`;
2919  }
2920};
2921var InputNode = class extends Node2 {
2922  static get type() {
2923    return "InputNode";
2924  }
2925  /**
2926   * Constructs a new input node.
2927   *
2928   * @param {any} value - The value of this node. This can be any JS primitive, functions, array buffers or even three.js objects (vector, matrices, colors).
2929   * @param {?string} nodeType - The node type. If no explicit type is defined, the node tries to derive the type from its value.
2930   */
2931  constructor(value, nodeType = null) {
2932    super(nodeType);
2933    this.isInputNode = true;
2934    this.value = value;
2935    this.precision = null;
2936  }
2937  generateNodeType() {
2938    if (this.nodeType === null) {
2939      return getValueType(this.value);
2940    }
2941    return this.nodeType;
2942  }
2943  /**
2944   * Returns the input type of the node which is by default the node type. Derived modules
2945   * might overwrite this method and use a fixed type or compute one analytically.
2946   *
2947   * A typical example for different input and node types are textures. The input type of a
2948   * normal RGBA texture is `texture` whereas its node type is `vec4`.
2949   *
2950   * @param {NodeBuilder} builder - The current node builder.
2951   * @return {string} The input type.
2952   */
2953  getInputType(builder) {
2954    return this.getNodeType(builder);
2955  }
2956  /**
2957   * Sets the precision to the given value. The method can be
2958   * overwritten in derived classes if the final precision must be computed
2959   * analytically.
2960   *
2961   * @param {('low'|'medium'|'high')} precision - The precision of the input value in the shader.
2962   * @return {InputNode} A reference to this node.
2963   */
2964  setPrecision(precision) {
2965    this.precision = precision;
2966    return this;
2967  }
2968  serialize(data) {
2969    super.serialize(data);
2970    data.value = this.value;
2971    if (this.value && this.value.toArray) data.value = this.value.toArray();
2972    data.valueType = getValueType(this.value);
2973    data.nodeType = this.nodeType;
2974    if (data.valueType === "ArrayBuffer") data.value = arrayBufferToBase64(data.value);
2975    data.precision = this.precision;
2976  }
2977  deserialize(data) {
2978    super.deserialize(data);
2979    this.nodeType = data.nodeType;
2980    this.value = Array.isArray(data.value) ? getValueFromType(data.valueType, ...data.value) : data.value;
2981    this.precision = data.precision || null;
2982    if (this.value && this.value.fromArray) this.value = this.value.fromArray(data.value);
2983  }
2984  generate() {
2985    warn("Abstract function.");
2986  }
2987};
2988var _regNum = /float|u?int/;
2989var ConstNode = class extends InputNode {
2990  static get type() {
2991    return "ConstNode";
2992  }
2993  /**
2994   * Constructs a new input node.
2995   *
2996   * @param {any} value - The value of this node. Usually a JS primitive or three.js object (vector, matrix, color).
2997   * @param {?string} nodeType - The node type. If no explicit type is defined, the node tries to derive the type from its value.
2998   */
2999  constructor(value, nodeType = null) {
3000    super(value, nodeType);
3001    this.isConstNode = true;
3002  }
3003  /**
3004   * Generates the shader string of the value with the current node builder.
3005   *
3006   * @param {NodeBuilder} builder - The current node builder.
3007   * @return {string} The generated value as a shader string.
3008   */
3009  generateConst(builder) {
3010    return builder.generateConst(this.getNodeType(builder), this.value);
3011  }
3012  generate(builder, output3) {
3013    const type = this.getNodeType(builder);
3014    if (_regNum.test(type) && _regNum.test(output3)) {
3015      return builder.generateConst(output3, this.value);
3016    }
3017    return builder.format(this.generateConst(builder), type, output3);
3018  }
3019};
3020var MemberNode = class extends Node2 {
3021  static get type() {
3022    return "MemberNode";
3023  }
3024  /**
3025   * Constructs a member node.
3026   *
3027   * @param {Node} structNode - The struct node.
3028   * @param {string} property - The property name.
3029   */
3030  constructor(structNode, property3) {
3031    super();
3032    this.structNode = structNode;
3033    this.property = property3;
3034    this.isMemberNode = true;
3035  }
3036  hasMember(builder) {
3037    if (this.structNode.isMemberNode) {
3038      if (this.structNode.hasMember(builder) === false) {
3039        return false;
3040      }
3041    }
3042    return this.structNode.getMemberType(builder, this.property) !== "void";
3043  }
3044  generateNodeType(builder) {
3045    if (this.hasMember(builder) === false) {
3046      return "float";
3047    }
3048    return this.structNode.getMemberType(builder, this.property);
3049  }
3050  getMemberType(builder, name) {
3051    if (this.hasMember(builder) === false) {
3052      return "float";
3053    }
3054    const type = this.getNodeType(builder);
3055    const struct3 = builder.getStructTypeNode(type);
3056    return struct3.getMemberType(builder, name);
3057  }
3058  generate(builder) {
3059    if (this.hasMember(builder) === false) {
3060      warn(`TSL: Member "${this.property}" does not exist in struct.`, this.stackTrace);
3061      const type = this.getNodeType(builder);
3062      return builder.generateConst(type);
3063    }
3064    const propertyName = this.structNode.build(builder);
3065    return propertyName + "." + this.property;
3066  }
3067};
3068var currentStack = null;
3069var NodeElements = /* @__PURE__ */ new Map();
3070function addMethodChaining(name, nodeElement) {
3071  if (NodeElements.has(name)) {
3072    warn(`TSL: Redefinition of method chaining '${name}'.`);
3073    return;
3074  }
3075  if (typeof nodeElement !== "function") throw new Error(`THREE.TSL: Node element ${name} is not a function`);
3076  NodeElements.set(name, nodeElement);
3077  if (name !== "assign") {
3078    Node2.prototype[name] = function(...params) {
3079      return this.isStackNode ? this.addToStack(nodeElement(...params)) : nodeElement(this, ...params);
3080    };
3081    Node2.prototype[name + "Assign"] = function(...params) {
3082      return this.isStackNode ? this.assign(params[0], nodeElement(...params)) : this.assign(nodeElement(this, ...params));
3083    };
3084  }
3085}
3086var parseSwizzle = (props) => props.replace(/r|s/g, "x").replace(/g|t/g, "y").replace(/b|p/g, "z").replace(/a|q/g, "w");
3087var parseSwizzleAndSort = (props) => parseSwizzle(props).split("").sort().join("");
3088Node2.prototype.assign = function(...params) {
3089  if (this.isStackNode !== true) {
3090    if (currentStack !== null) {
3091      currentStack.assign(this, ...params);
3092    } else {
3093      error("TSL: No stack defined for assign operation. Make sure the assign is inside a Fn().", new StackTrace());
3094    }
3095    return this;
3096  } else {
3097    const nodeElement = NodeElements.get("assign");
3098    return this.addToStack(nodeElement(...params));
3099  }
3100};
3101Node2.prototype.toVarIntent = function() {
3102  return this;
3103};
3104Node2.prototype.get = function(value) {
3105  return new MemberNode(this, value);
3106};
3107var proto = {};
3108function setProtoSwizzle(property3, altA, altB) {
3109  proto[property3] = proto[altA] = proto[altB] = {
3110    get() {
3111      this._cache = this._cache || {};
3112      let split3 = this._cache[property3];
3113      if (split3 === void 0) {
3114        split3 = new SplitNode(this, property3);
3115        this._cache[property3] = split3;
3116      }
3117      return split3;
3118    },
3119    set(value) {
3120      this[property3].assign(nodeObject(value));
3121    }
3122  };
3123  const propUpper = property3.toUpperCase();
3124  const altAUpper = altA.toUpperCase();
3125  const altBUpper = altB.toUpperCase();
3126  Node2.prototype["set" + propUpper] = Node2.prototype["set" + altAUpper] = Node2.prototype["set" + altBUpper] = function(value) {
3127    const swizzle = parseSwizzleAndSort(property3);
3128    return new SetNode(this, swizzle, nodeObject(value));
3129  };
3130  Node2.prototype["flip" + propUpper] = Node2.prototype["flip" + altAUpper] = Node2.prototype["flip" + altBUpper] = function() {
3131    const swizzle = parseSwizzleAndSort(property3);
3132    return new FlipNode(this, swizzle);
3133  };
3134}
3135var swizzleA = ["x", "y", "z", "w"];
3136var swizzleB = ["r", "g", "b", "a"];
3137var swizzleC = ["s", "t", "p", "q"];
3138for (let a = 0; a < 4; a++) {
3139  let prop = swizzleA[a];
3140  let altA = swizzleB[a];
3141  let altB = swizzleC[a];
3142  setProtoSwizzle(prop, altA, altB);
3143  for (let b = 0; b < 4; b++) {
3144    prop = swizzleA[a] + swizzleA[b];
3145    altA = swizzleB[a] + swizzleB[b];
3146    altB = swizzleC[a] + swizzleC[b];
3147    setProtoSwizzle(prop, altA, altB);
3148    for (let c = 0; c < 4; c++) {
3149      prop = swizzleA[a] + swizzleA[b] + swizzleA[c];
3150      altA = swizzleB[a] + swizzleB[b] + swizzleB[c];
3151      altB = swizzleC[a] + swizzleC[b] + swizzleC[c];
3152      setProtoSwizzle(prop, altA, altB);
3153      for (let d = 0; d < 4; d++) {
3154        prop = swizzleA[a] + swizzleA[b] + swizzleA[c] + swizzleA[d];
3155        altA = swizzleB[a] + swizzleB[b] + swizzleB[c] + swizzleB[d];
3156        altB = swizzleC[a] + swizzleC[b] + swizzleC[c] + swizzleC[d];
3157        setProtoSwizzle(prop, altA, altB);
3158      }
3159    }
3160  }
3161}
3162for (let i = 0; i < 32; i++) {
3163  proto[i] = {
3164    get() {
3165      this._cache = this._cache || {};
3166      let element3 = this._cache[i];
3167      if (element3 === void 0) {
3168        element3 = new ArrayElementNode(this, new ConstNode(i, "uint"));
3169        this._cache[i] = element3;
3170      }
3171      return element3;
3172    },
3173    set(value) {
3174      this[i].assign(nodeObject(value));
3175    }
3176  };
3177}
3178Object.defineProperties(Node2.prototype, proto);
3179var nodeBuilderFunctionsCacheMap = /* @__PURE__ */ new WeakMap();
3180var ShaderNodeObject = function(obj, altType = null) {
3181  const type = getValueType(obj);
3182  if (type === "node") {
3183    return obj;
3184  } else if (altType === null && (type === "float" || type === "boolean") || type && type !== "shader" && type !== "string") {
3185    return nodeObject(getConstNode(obj, altType));
3186  } else if (type === "shader") {
3187    return obj.isFn ? obj : Fn(obj);
3188  }
3189  return obj;
3190};
3191var ShaderNodeObjects = function(objects, altType = null) {
3192  for (const name in objects) {
3193    objects[name] = nodeObject(objects[name], altType);
3194  }
3195  return objects;
3196};
3197var ShaderNodeArray = function(array3, altType = null) {
3198  const len = array3.length;
3199  for (let i = 0; i < len; i++) {
3200    array3[i] = nodeObject(array3[i], altType);
3201  }
3202  return array3;
3203};
3204var ShaderNodeProxy = function(NodeClass, scope = null, factor = null, settings = null) {
3205  function assignNode(node) {
3206    if (settings !== null) {
3207      node = nodeObject(Object.assign(node, settings));
3208      if (settings.intent === true) {
3209        node = node.toVarIntent();
3210      }
3211    } else {
3212      node = nodeObject(node);
3213    }
3214    return node;
3215  }
3216  let fn, name = scope, minParams, maxParams;
3217  function verifyParamsLimit(params) {
3218    let tslName;
3219    if (name) tslName = /[a-z]/i.test(name) ? name + "()" : name;
3220    else tslName = NodeClass.type;
3221    if (minParams !== void 0 && params.length < minParams) {
3222      error(`TSL: "${tslName}" parameter length is less than minimum required.`, new StackTrace());
3223      return params.concat(new Array(minParams - params.length).fill(0));
3224    } else if (maxParams !== void 0 && params.length > maxParams) {
3225      error(`TSL: "${tslName}" parameter length exceeds limit.`, new StackTrace());
3226      return params.slice(0, maxParams);
3227    }
3228    return params;
3229  }
3230  if (scope === null) {
3231    fn = (...params) => {
3232      return assignNode(new NodeClass(...nodeArray(verifyParamsLimit(params))));
3233    };
3234  } else if (factor !== null) {
3235    factor = nodeObject(factor);
3236    fn = (...params) => {
3237      return assignNode(new NodeClass(scope, ...nodeArray(verifyParamsLimit(params)), factor));
3238    };
3239  } else {
3240    fn = (...params) => {
3241      return assignNode(new NodeClass(scope, ...nodeArray(verifyParamsLimit(params))));
3242    };
3243  }
3244  fn.setParameterLength = (...params) => {
3245    if (params.length === 1) minParams = maxParams = params[0];
3246    else if (params.length === 2) [minParams, maxParams] = params;
3247    return fn;
3248  };
3249  fn.setName = (value) => {
3250    name = value;
3251    return fn;
3252  };
3253  return fn;
3254};
3255var ShaderNodeImmutable = function(NodeClass, ...params) {
3256  return new NodeClass(...nodeArray(params));
3257};
3258var ShaderCallNodeInternal = class extends Node2 {
3259  constructor(shaderNode, rawInputs) {
3260    super();
3261    this.shaderNode = shaderNode;
3262    this.rawInputs = rawInputs;
3263    this.isShaderCallNodeInternal = true;
3264  }
3265  generateNodeType(builder) {
3266    return this.shaderNode.nodeType || this.getOutputNode(builder).getNodeType(builder);
3267  }
3268  getElementType(builder) {
3269    return this.getOutputNode(builder).getElementType(builder);
3270  }
3271  getMemberType(builder, name) {
3272    return this.getOutputNode(builder).getMemberType(builder, name);
3273  }
3274  call(builder) {
3275    const { shaderNode, rawInputs } = this;
3276    const properties = builder.getNodeProperties(shaderNode);
3277    const subBuild3 = builder.getClosestSubBuild(shaderNode.subBuilds) || "";
3278    const subBuildProperty = subBuild3 || "default";
3279    if (properties[subBuildProperty]) {
3280      return properties[subBuildProperty];
3281    }
3282    const previousSubBuildFn = builder.subBuildFn;
3283    const previousFnCall = builder.fnCall;
3284    builder.subBuildFn = subBuild3;
3285    builder.fnCall = this;
3286    let result = null;
3287    if (shaderNode.layout) {
3288      let functionNodesCacheMap = nodeBuilderFunctionsCacheMap.get(builder.constructor);
3289      if (functionNodesCacheMap === void 0) {
3290        functionNodesCacheMap = /* @__PURE__ */ new WeakMap();
3291        nodeBuilderFunctionsCacheMap.set(builder.constructor, functionNodesCacheMap);
3292      }
3293      let functionNode = functionNodesCacheMap.get(shaderNode);
3294      if (functionNode === void 0) {
3295        functionNode = nodeObject(builder.buildFunctionNode(shaderNode));
3296        functionNodesCacheMap.set(shaderNode, functionNode);
3297      }
3298      builder.addInclude(functionNode);
3299      const inputs = rawInputs ? getLayoutParameters(rawInputs) : null;
3300      result = nodeObject(functionNode.call(inputs));
3301    } else {
3302      const secureNodeBuilder = new Proxy(builder, {
3303        get: (target, property3, receiver) => {
3304          let value;
3305          if (Symbol.iterator === property3) {
3306            value = function* () {
3307              yield void 0;
3308            };
3309          } else {
3310            value = Reflect.get(target, property3, receiver);
3311          }
3312          return value;
3313        }
3314      });
3315      const inputs = rawInputs ? getProxyParameters(rawInputs) : null;
3316      const hasParameters = Array.isArray(rawInputs) ? rawInputs.length > 0 : rawInputs !== null;
3317      const jsFunc = shaderNode.jsFunc;
3318      const outputNode = hasParameters || jsFunc.length > 1 ? jsFunc(inputs, secureNodeBuilder) : jsFunc(secureNodeBuilder);
3319      result = nodeObject(outputNode);
3320    }
3321    builder.subBuildFn = previousSubBuildFn;
3322    builder.fnCall = previousFnCall;
3323    if (shaderNode.once) {
3324      properties[subBuildProperty] = result;
3325    }
3326    return result;
3327  }
3328  setupOutput(builder) {
3329    builder.addStack();
3330    builder.stack.outputNode = this.call(builder);
3331    return builder.removeStack();
3332  }
3333  getOutputNode(builder) {
3334    const properties = builder.getNodeProperties(this);
3335    const subBuildOutput = builder.getSubBuildOutput(this);
3336    properties[subBuildOutput] = properties[subBuildOutput] || this.setupOutput(builder);
3337    properties[subBuildOutput].subBuild = builder.getClosestSubBuild(this);
3338    return properties[subBuildOutput];
3339  }
3340  build(builder, output3 = null) {
3341    let result = null;
3342    const buildStage = builder.getBuildStage();
3343    const properties = builder.getNodeProperties(this);
3344    const subBuildOutput = builder.getSubBuildOutput(this);
3345    const outputNode = this.getOutputNode(builder);
3346    const previousFnCall = builder.fnCall;
3347    builder.fnCall = this;
3348    if (buildStage === "setup") {
3349      const subBuildInitialized = builder.getSubBuildProperty("initialized", this);
3350      if (properties[subBuildInitialized] !== true) {
3351        properties[subBuildInitialized] = true;
3352        properties[subBuildOutput] = this.getOutputNode(builder);
3353        properties[subBuildOutput].build(builder);
3354        if (this.shaderNode.subBuilds) {
3355          for (const node of builder.chaining) {
3356            const nodeData = builder.getDataFromNode(node, "any");
3357            nodeData.subBuilds = nodeData.subBuilds || /* @__PURE__ */ new Set();
3358            for (const subBuild3 of this.shaderNode.subBuilds) {
3359              nodeData.subBuilds.add(subBuild3);
3360            }
3361          }
3362        }
3363      }
3364      result = properties[subBuildOutput];
3365    } else if (buildStage === "analyze") {
3366      outputNode.build(builder, output3);
3367    } else if (buildStage === "generate") {
3368      result = outputNode.build(builder, output3) || "";
3369    }
3370    builder.fnCall = previousFnCall;
3371    return result;
3372  }
3373};
3374function getLayoutParameters(params) {
3375  let output3;
3376  nodeObjects(params);
3377  const isArrayAsParameter = params[0] && (params[0].isNode || Object.getPrototypeOf(params[0]) !== Object.prototype);
3378  if (isArrayAsParameter) {
3379    output3 = [...params];
3380  } else {
3381    output3 = params[0];
3382  }
3383  return output3;
3384}
3385function getProxyParameters(params) {
3386  let index = 0;
3387  nodeObjects(params);
3388  return new Proxy(params, {
3389    get: (target, property3, receiver) => {
3390      let value;
3391      if (property3 === "length") {
3392        value = params.length;
3393        return value;
3394      }
3395      if (Symbol.iterator === property3) {
3396        value = function* () {
3397          for (const inputNode of params) {
3398            yield nodeObject(inputNode);
3399          }
3400        };
3401      } else {
3402        if (params.length > 0) {
3403          if (Object.getPrototypeOf(params[0]) === Object.prototype) {
3404            const objectTarget = params[0];
3405            if (objectTarget[property3] === void 0) {
3406              value = objectTarget[index++];
3407            } else {
3408              value = Reflect.get(objectTarget, property3, receiver);
3409            }
3410          } else if (params[0] instanceof Node2) {
3411            if (params[property3] === void 0) {
3412              value = params[index++];
3413            } else {
3414              value = Reflect.get(params, property3, receiver);
3415            }
3416          }
3417        } else {
3418          value = Reflect.get(target, property3, receiver);
3419        }
3420        value = nodeObject(value);
3421      }
3422      return value;
3423    }
3424  });
3425}
3426var ShaderNodeInternal = class extends Node2 {
3427  constructor(jsFunc, nodeType) {
3428    super(nodeType);
3429    this.jsFunc = jsFunc;
3430    this.layout = null;
3431    this.global = true;
3432    this.once = false;
3433  }
3434  setLayout(layout) {
3435    this.layout = layout;
3436    return this;
3437  }
3438  getLayout() {
3439    return this.layout;
3440  }
3441  call(rawInputs = null) {
3442    return new ShaderCallNodeInternal(this, rawInputs);
3443  }
3444  setup() {
3445    return this.call();
3446  }
3447};
3448var bools = [false, true];
3449var uints = [0, 1, 2, 3];
3450var ints = [-1, -2];
3451var floats = [0.5, 1.5, 1 / 3, 1e-6, 1e6, Math.PI, Math.PI * 2, 1 / Math.PI, 2 / Math.PI, 1 / (Math.PI * 2), Math.PI / 2];
3452var boolsCacheMap = /* @__PURE__ */ new Map();
3453for (const bool3 of bools) boolsCacheMap.set(bool3, new ConstNode(bool3));
3454var uintsCacheMap = /* @__PURE__ */ new Map();
3455for (const uint3 of uints) uintsCacheMap.set(uint3, new ConstNode(uint3, "uint"));
3456var intsCacheMap = new Map([...uintsCacheMap].map((el) => new ConstNode(el.value, "int")));
3457for (const int3 of ints) intsCacheMap.set(int3, new ConstNode(int3, "int"));
3458var floatsCacheMap = new Map([...intsCacheMap].map((el) => new ConstNode(el.value)));
3459for (const float3 of floats) floatsCacheMap.set(float3, new ConstNode(float3));
3460for (const float3 of floats) floatsCacheMap.set(-float3, new ConstNode(-float3));
3461var cacheMaps = { bool: boolsCacheMap, uint: uintsCacheMap, ints: intsCacheMap, float: floatsCacheMap };
3462var constNodesCacheMap = new Map([...boolsCacheMap, ...floatsCacheMap]);
3463var getConstNode = (value, type) => {
3464  if (constNodesCacheMap.has(value)) {
3465    return constNodesCacheMap.get(value);
3466  } else if (value.isNode === true) {
3467    return value;
3468  } else {
3469    return new ConstNode(value, type);
3470  }
3471};
3472var ConvertType = function(type, cacheMap = null) {
3473  return (...params) => {
3474    for (const param of params) {
3475      if (param === void 0) {
3476        error(`TSL: Invalid parameter for the type "${type}".`, new StackTrace());
3477        return new ConstNode(0, type);
3478      }
3479    }
3480    if (params.length === 0 || !["bool", "float", "int", "uint"].includes(type) && params.every((param) => {
3481      const paramType = typeof param;
3482      return paramType !== "object" && paramType !== "function";
3483    })) {
3484      params = [getValueFromType(type, ...params)];
3485    }
3486    if (params.length === 1 && cacheMap !== null && cacheMap.has(params[0])) {
3487      return nodeObjectIntent(cacheMap.get(params[0]));
3488    }
3489    if (params.length === 1) {
3490      const node = getConstNode(params[0], type);
3491      if (node.nodeType === type) return nodeObjectIntent(node);
3492      return nodeObjectIntent(new ConvertNode(node, type));
3493    }
3494    const nodes = params.map((param) => getConstNode(param));
3495    return nodeObjectIntent(new JoinNode(nodes, type));
3496  };
3497};
3498function defined(value) {
3499  if (value && value.isNode) {
3500    value.traverse((node) => {
3501      if (node.isConstNode) {
3502        value = node.value;
3503      }
3504    });
3505  }
3506  return Boolean(value);
3507}
3508var getConstNodeType = (value) => value !== void 0 && value !== null ? value.nodeType || value.convertTo || (typeof value === "string" ? value : null) : null;
3509function ShaderNode(jsFunc, nodeType) {
3510  return new ShaderNodeInternal(jsFunc, nodeType);
3511}
3512var nodeObject = (val, altType = null) => (
3513  /* new */
3514  ShaderNodeObject(val, altType)
3515);
3516var nodeObjectIntent = (val, altType = null) => (
3517  /* new */
3518  nodeObject(val, altType).toVarIntent()
3519);
3520var nodeObjects = (val, altType = null) => new ShaderNodeObjects(val, altType);
3521var nodeArray = (val, altType = null) => new ShaderNodeArray(val, altType);
3522var nodeProxy = (NodeClass, scope = null, factor = null, settings = null) => new ShaderNodeProxy(NodeClass, scope, factor, settings);
3523var nodeImmutable = (NodeClass, ...params) => new ShaderNodeImmutable(NodeClass, ...params);
3524var nodeProxyIntent = (NodeClass, scope = null, factor = null, settings = {}) => new ShaderNodeProxy(NodeClass, scope, factor, { ...settings, intent: true });
3525var fnId = 0;
3526var FnNode = class extends Node2 {
3527  constructor(jsFunc, layout = null) {
3528    super();
3529    let nodeType = null;
3530    if (layout !== null) {
3531      if (typeof layout === "object") {
3532        nodeType = layout.return;
3533      } else {
3534        if (typeof layout === "string") {
3535          nodeType = layout;
3536        } else {
3537          error("TSL: Invalid layout type.", new StackTrace());
3538        }
3539        layout = null;
3540      }
3541    }
3542    this.shaderNode = new ShaderNode(jsFunc, nodeType);
3543    if (layout !== null) {
3544      this.setLayout(layout);
3545    }
3546    this.isFn = true;
3547  }
3548  setLayout(layout) {
3549    const nodeType = this.shaderNode.nodeType;
3550    if (typeof layout.inputs !== "object") {
3551      const fullLayout = {
3552        name: "fn" + fnId++,
3553        type: nodeType,
3554        inputs: []
3555      };
3556      for (const name in layout) {
3557        if (name === "return") continue;
3558        fullLayout.inputs.push({
3559          name,
3560          type: layout[name]
3561        });
3562      }
3563      layout = fullLayout;
3564    }
3565    this.shaderNode.setLayout(layout);
3566    return this;
3567  }
3568  generateNodeType(builder) {
3569    return this.shaderNode.getNodeType(builder) || "float";
3570  }
3571  call(...params) {
3572    const fnCall = this.shaderNode.call(params);
3573    if (this.shaderNode.nodeType === "void") fnCall.toStack();
3574    return fnCall.toVarIntent();
3575  }
3576  once(subBuilds = null) {
3577    this.shaderNode.once = true;
3578    this.shaderNode.subBuilds = subBuilds;
3579    return this;
3580  }
3581  generate(builder) {
3582    const type = this.getNodeType(builder);
3583    error('TSL: "Fn()" was declared but not invoked. Try calling it like "Fn()( ...params )".', this.stackTrace);
3584    return builder.generateConst(type);
3585  }
3586};
3587function Fn(jsFunc, layout = null) {
3588  const instance3 = new FnNode(jsFunc, layout);
3589  return new Proxy(() => {
3590  }, {
3591    apply(target, thisArg, params) {
3592      return instance3.call(...params);
3593    },
3594    get(target, prop, receiver) {
3595      return Reflect.get(instance3, prop, receiver);
3596    },
3597    set(target, prop, value, receiver) {
3598      return Reflect.set(instance3, prop, value, receiver);
3599    }
3600  });
3601}
3602var setCurrentStack = (stack3) => {
3603  currentStack = stack3;
3604};
3605var getCurrentStack = () => currentStack;
3606var If = (...params) => currentStack.If(...params);
3607var Switch = (...params) => currentStack.Switch(...params);
3608function Stack(node) {
3609  if (currentStack) currentStack.addToStack(node);
3610  return node;
3611}
3612addMethodChaining("toStack", Stack);
3613var color = new ConvertType("color");
3614var float = new ConvertType("float", cacheMaps.float);
3615var int = new ConvertType("int", cacheMaps.ints);
3616var uint = new ConvertType("uint", cacheMaps.uint);
3617var bool = new ConvertType("bool", cacheMaps.bool);
3618var vec2 = new ConvertType("vec2");
3619var ivec2 = new ConvertType("ivec2");
3620var uvec2 = new ConvertType("uvec2");
3621var bvec2 = new ConvertType("bvec2");
3622var vec3 = new ConvertType("vec3");
3623var ivec3 = new ConvertType("ivec3");
3624var uvec3 = new ConvertType("uvec3");
3625var bvec3 = new ConvertType("bvec3");
3626var vec4 = new ConvertType("vec4");
3627var ivec4 = new ConvertType("ivec4");
3628var uvec4 = new ConvertType("uvec4");
3629var bvec4 = new ConvertType("bvec4");
3630var mat2 = new ConvertType("mat2");
3631var mat3 = new ConvertType("mat3");
3632var mat4 = new ConvertType("mat4");
3633var string = (value = "") => new ConstNode(value, "string");
3634var arrayBuffer = (value) => new ConstNode(value, "ArrayBuffer");
3635addMethodChaining("toColor", color);
3636addMethodChaining("toFloat", float);
3637addMethodChaining("toInt", int);
3638addMethodChaining("toUint", uint);
3639addMethodChaining("toBool", bool);
3640addMethodChaining("toVec2", vec2);
3641addMethodChaining("toIVec2", ivec2);
3642addMethodChaining("toUVec2", uvec2);
3643addMethodChaining("toBVec2", bvec2);
3644addMethodChaining("toVec3", vec3);
3645addMethodChaining("toIVec3", ivec3);
3646addMethodChaining("toUVec3", uvec3);
3647addMethodChaining("toBVec3", bvec3);
3648addMethodChaining("toVec4", vec4);
3649addMethodChaining("toIVec4", ivec4);
3650addMethodChaining("toUVec4", uvec4);
3651addMethodChaining("toBVec4", bvec4);
3652addMethodChaining("toMat2", mat2);
3653addMethodChaining("toMat3", mat3);
3654addMethodChaining("toMat4", mat4);
3655var element = /* @__PURE__ */ nodeProxy(ArrayElementNode).setParameterLength(2);
3656var convert = (node, types) => new ConvertNode(nodeObject(node), types);
3657var split = (node, channels) => new SplitNode(nodeObject(node), channels);
3658addMethodChaining("element", element);
3659addMethodChaining("convert", convert);
3660var append = (node) => {
3661  warn("TSL: append() has been renamed to Stack().", new StackTrace());
3662  return Stack(node);
3663};
3664addMethodChaining("append", (node) => {
3665  warn("TSL: .append() has been renamed to .toStack().", new StackTrace());
3666  return Stack(node);
3667});
3668var PropertyNode = class extends Node2 {
3669  static get type() {
3670    return "PropertyNode";
3671  }
3672  /**
3673   * Constructs a new property node.
3674   *
3675   * @param {string} nodeType - The type of the node.
3676   * @param {?string} [name=null] - The name of the property in the shader.
3677   * @param {boolean} [varying=false] - Whether this property is a varying or not.
3678   */
3679  constructor(nodeType, name = null, varying3 = false) {
3680    super(nodeType);
3681    this.name = name;
3682    this.varying = varying3;
3683    this.isPropertyNode = true;
3684    this.global = true;
3685  }
3686  customCacheKey() {
3687    return hashString(this.type + ":" + (this.name || "") + ":" + (this.varying ? "1" : "0"));
3688  }
3689  getHash(builder) {
3690    return this.name || super.getHash(builder);
3691  }
3692  generate(builder) {
3693    let nodeVar;
3694    if (this.varying === true) {
3695      nodeVar = builder.getVaryingFromNode(this, this.name);
3696      nodeVar.needsInterpolation = true;
3697    } else {
3698      nodeVar = builder.getVarFromNode(this, this.name);
3699    }
3700    return builder.getPropertyName(nodeVar);
3701  }
3702};
3703var property = (type, name) => new PropertyNode(type, name);
3704var varyingProperty = (type, name) => new PropertyNode(type, name, true);
3705var diffuseColor = /* @__PURE__ */ nodeImmutable(PropertyNode, "vec4", "DiffuseColor");
3706var diffuseContribution = /* @__PURE__ */ nodeImmutable(PropertyNode, "vec3", "DiffuseContribution");
3707var emissive = /* @__PURE__ */ nodeImmutable(PropertyNode, "vec3", "EmissiveColor");
3708var roughness = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Roughness");
3709var metalness = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Metalness");
3710var clearcoat = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Clearcoat");
3711var clearcoatRoughness = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "ClearcoatRoughness");
3712var sheen = /* @__PURE__ */ nodeImmutable(PropertyNode, "vec3", "Sheen");
3713var sheenRoughness = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "SheenRoughness");
3714var iridescence = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Iridescence");
3715var iridescenceIOR = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "IridescenceIOR");
3716var iridescenceThickness = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "IridescenceThickness");
3717var alphaT = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "AlphaT");
3718var anisotropy = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Anisotropy");
3719var anisotropyT = /* @__PURE__ */ nodeImmutable(PropertyNode, "vec3", "AnisotropyT");
3720var anisotropyB = /* @__PURE__ */ nodeImmutable(PropertyNode, "vec3", "AnisotropyB");
3721var specularColor = /* @__PURE__ */ nodeImmutable(PropertyNode, "color", "SpecularColor");
3722var specularColorBlended = /* @__PURE__ */ nodeImmutable(PropertyNode, "color", "SpecularColorBlended");
3723var specularF90 = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "SpecularF90");
3724var shininess = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Shininess");
3725var output = /* @__PURE__ */ nodeImmutable(PropertyNode, "vec4", "Output");
3726var dashSize = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "dashSize");
3727var gapSize = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "gapSize");
3728var pointWidth = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "pointWidth");
3729var ior = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "IOR");
3730var transmission = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Transmission");
3731var thickness = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Thickness");
3732var attenuationDistance = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "AttenuationDistance");
3733var attenuationColor = /* @__PURE__ */ nodeImmutable(PropertyNode, "color", "AttenuationColor");
3734var dispersion = /* @__PURE__ */ nodeImmutable(PropertyNode, "float", "Dispersion");
3735var UniformGroupNode = class extends Node2 {
3736  static get type() {
3737    return "UniformGroupNode";
3738  }
3739  /**
3740   * Constructs a new uniform group node.
3741   *
3742   * @param {string} name - The name of the uniform group node.
3743   * @param {boolean} [shared=false] - Whether this uniform group node is shared or not.
3744   * @param {number} [order=1] - Influences the internal sorting.
3745   * @param {string|null} [updateType=null] - The update type of the uniform group node.
3746   */
3747  constructor(name, shared = false, order = 1, updateType = null) {
3748    super("string");
3749    this.name = name;
3750    this.shared = shared;
3751    this.order = order;
3752    this.updateType = updateType;
3753    this.isUniformGroup = true;
3754  }
3755  /**
3756   * Marks the uniform group node as needing an update.
3757   * This will trigger the necessary updates in the rendering process.
3758   */
3759  update() {
3760    this.needsUpdate = true;
3761  }
3762  /**
3763   * Serializes the uniform group node to a JSON object.
3764   *
3765   * @param {Object} data - The object to store the serialized data.
3766   */
3767  serialize(data) {
3768    super.serialize(data);
3769    data.name = this.name;
3770    data.version = this.version;
3771    data.shared = this.shared;
3772  }
3773  /**
3774   * Deserializes the uniform group node from a JSON object.
3775   *
3776   * @param {Object} data - The object containing the serialized data.
3777   */
3778  deserialize(data) {
3779    super.deserialize(data);
3780    this.name = data.name;
3781    this.version = data.version;
3782    this.shared = data.shared;
3783  }
3784};
3785var uniformGroup = (name, order = 1, updateType = null) => new UniformGroupNode(name, false, order, updateType);
3786var sharedUniformGroup = (name, order = 0, updateType = null) => new UniformGroupNode(name, true, order, updateType);
3787var frameGroup = /* @__PURE__ */ sharedUniformGroup("frame", 0, NodeUpdateType.FRAME);
3788var renderGroup = /* @__PURE__ */ sharedUniformGroup("render", 0, NodeUpdateType.RENDER);
3789var objectGroup = /* @__PURE__ */ uniformGroup("object", 1, NodeUpdateType.OBJECT);
3790var UniformNode = class extends InputNode {
3791  static get type() {
3792    return "UniformNode";
3793  }
3794  /**
3795   * Constructs a new uniform node.
3796   *
3797   * @param {any} value - The value of this node. Usually a JS primitive or three.js object (vector, matrix, color, texture).
3798   * @param {?string} nodeType - The node type. If no explicit type is defined, the node tries to derive the type from its value.
3799   */
3800  constructor(value, nodeType = null) {
3801    super(value, nodeType);
3802    this.isUniformNode = true;
3803    this.name = "";
3804    this.groupNode = objectGroup;
3805  }
3806  /**
3807   * Sets the {@link UniformNode#name} property.
3808   *
3809   * @param {string} name - The name of the uniform.
3810   * @return {UniformNode} A reference to this node.
3811   */
3812  setName(name) {
3813    this.name = name;
3814    return this;
3815  }
3816  /**
3817   * Sets the {@link UniformNode#name} property.
3818   *
3819   * @deprecated
3820   * @param {string} name - The name of the uniform.
3821   * @return {UniformNode} A reference to this node.
3822   */
3823  label(name) {
3824    warn('TSL: "label()" has been deprecated. Use "setName()" instead.', new StackTrace());
3825    return this.setName(name);
3826  }
3827  /**
3828   * Sets the {@link UniformNode#groupNode} property.
3829   *
3830   * @param {UniformGroupNode} group - The uniform group.
3831   * @return {UniformNode} A reference to this node.
3832   */
3833  setGroup(group) {
3834    this.groupNode = group;
3835    return this;
3836  }
3837  /**
3838   * Returns the {@link UniformNode#groupNode}.
3839   *
3840   * @return {UniformGroupNode} The uniform group.
3841   */
3842  getGroup() {
3843    return this.groupNode;
3844  }
3845  /**
3846   * By default, this method returns the result of {@link Node#getHash} but derived
3847   * classes might overwrite this method with a different implementation.
3848   *
3849   * @param {NodeBuilder} builder - The current node builder.
3850   * @return {string} The uniform hash.
3851   */
3852  getUniformHash(builder) {
3853    return this.getHash(builder);
3854  }
3855  onUpdate(callback, updateType) {
3856    callback = callback.bind(this);
3857    return super.onUpdate((frame) => {
3858      const value = callback(frame, this);
3859      if (value !== void 0) {
3860        this.value = value;
3861      }
3862    }, updateType);
3863  }
3864  getInputType(builder) {
3865    let type = super.getInputType(builder);
3866    if (type === "bool") {
3867      type = "uint";
3868    }
3869    return type;
3870  }
3871  generate(builder, output3) {
3872    const type = this.getNodeType(builder);
3873    const hash3 = this.getUniformHash(builder);
3874    let sharedNode = builder.getNodeFromHash(hash3);
3875    if (sharedNode === void 0) {
3876      builder.setHashNode(this, hash3);
3877      sharedNode = this;
3878    }
3879    const sharedNodeType = sharedNode.getInputType(builder);
3880    const nodeUniform = builder.getUniformFromNode(sharedNode, sharedNodeType, builder.shaderStage, this.name || builder.context.nodeName);
3881    const uniformName = builder.getPropertyName(nodeUniform);
3882    if (builder.context.nodeName !== void 0) delete builder.context.nodeName;
3883    let snippet = uniformName;
3884    if (type === "bool") {
3885      const nodeData = builder.getDataFromNode(this);
3886      let propertyName = nodeData.propertyName;
3887      if (propertyName === void 0) {
3888        const nodeVar = builder.getVarFromNode(this, null, "bool");
3889        propertyName = builder.getPropertyName(nodeVar);
3890        nodeData.propertyName = propertyName;
3891        snippet = builder.format(uniformName, sharedNodeType, type);
3892        builder.addLineFlowCode(`${propertyName} = ${snippet}`, this);
3893      }
3894      snippet = propertyName;
3895    }
3896    return builder.format(snippet, type, output3);
3897  }
3898};
3899var uniform = (value, type) => {
3900  const nodeType = getConstNodeType(type || value);
3901  if (nodeType === value) {
3902    value = getValueFromType(nodeType);
3903  }
3904  if (value && value.isNode === true) {
3905    let v = value.value;
3906    value.traverse((n) => {
3907      if (n.isConstNode === true) {
3908        v = n.value;
3909      }
3910    });
3911    value = v;
3912  }
3913  return new UniformNode(value, nodeType);
3914};
3915var ArrayNode = class extends TempNode {
3916  static get type() {
3917    return "ArrayNode";
3918  }
3919  /**
3920   * Constructs a new array node.
3921   *
3922   * @param {?string} nodeType - The data type of the elements.
3923   * @param {number} count - Size of the array.
3924   * @param {?Array<Node>} [values=null] - Array default values.
3925   */
3926  constructor(nodeType, count, values = null) {
3927    super(nodeType);
3928    this.count = count;
3929    this.values = values;
3930    this.isArrayNode = true;
3931  }
3932  /**
3933   * Returns the number of elements in the node array.
3934   *
3935   * @param {NodeBuilder} builder - The current node builder.
3936   * @return {number} The number of elements in the node array.
3937   */
3938  getArrayCount() {
3939    return this.count;
3940  }
3941  /**
3942   * Returns the node's type.
3943   *
3944   * @param {NodeBuilder} builder - The current node builder.
3945   * @return {string} The type of the node.
3946   */
3947  generateNodeType(builder) {
3948    if (this.nodeType === null) {
3949      return this.values[0].getNodeType(builder);
3950    }
3951    return this.nodeType;
3952  }
3953  /**
3954   * Returns the node's type.
3955   *
3956   * @param {NodeBuilder} builder - The current node builder.
3957   * @return {string} The type of the node.
3958   */
3959  getElementType(builder) {
3960    return this.getNodeType(builder);
3961  }
3962  /**
3963   * Returns the type of a member variable.
3964   *
3965   * @param {NodeBuilder} builder - The current node builder.
3966   * @param {string} name - The name of the member variable.
3967   * @return {string} The type of the member variable.
3968   */
3969  getMemberType(builder, name) {
3970    if (this.nodeType === null) {
3971      return this.values[0].getMemberType(builder, name);
3972    }
3973    return super.getMemberType(builder, name);
3974  }
3975  /**
3976   * This method builds the output node and returns the resulting array as a shader string.
3977   *
3978   * @param {NodeBuilder} builder - The current node builder.
3979   * @return {string} The generated shader string.
3980   */
3981  generate(builder) {
3982    const type = this.getNodeType(builder);
3983    return builder.generateArray(type, this.count, this.values);
3984  }
3985};
3986var array = (...params) => {
3987  let node;
3988  if (params.length === 1) {
3989    const values = params[0];
3990    node = new ArrayNode(null, values.length, values);
3991  } else {
3992    const nodeType = params[0];
3993    const count = params[1];
3994    node = new ArrayNode(nodeType, count);
3995  }
3996  return nodeObject(node);
3997};
3998addMethodChaining("toArray", (node, count) => array(Array(count).fill(node)));
3999var AssignNode = class extends TempNode {
4000  static get type() {
4001    return "AssignNode";
4002  }
4003  /**
4004   * Constructs a new assign node.
4005   *
4006   * @param {Node} targetNode - The target node.
4007   * @param {Node} sourceNode - The source type.
4008   */
4009  constructor(targetNode, sourceNode) {
4010    super();
4011    this.targetNode = targetNode;
4012    this.sourceNode = sourceNode;
4013    this.isAssignNode = true;
4014  }
4015  /**
4016   * Whether this node is used more than once in context of other nodes. This method
4017   * is overwritten since it always returns `false` (assigns are unique).
4018   *
4019   * @return {boolean} A flag that indicates if there is more than one dependency to other nodes. Always `false`.
4020   */
4021  hasDependencies() {
4022    return false;
4023  }
4024  generateNodeType(builder, output3) {
4025    return output3 !== "void" ? this.targetNode.getNodeType(builder) : "void";
4026  }
4027  /**
4028   * Whether a split is required when assigning source to target. This can happen when the component length of
4029   * target and source data type does not match.
4030   *
4031   * @param {NodeBuilder} builder - The current node builder.
4032   * @return {boolean} Whether a split is required when assigning source to target.
4033   */
4034  needsSplitAssign(builder) {
4035    const { targetNode } = this;
4036    if (builder.isAvailable("swizzleAssign") === false && targetNode.isSplitNode && targetNode.components.length > 1) {
4037      const targetLength = builder.getTypeLength(targetNode.node.getNodeType(builder));
4038      const assignDifferentVector = vectorComponents.join("").slice(0, targetLength) !== targetNode.components;
4039      return assignDifferentVector;
4040    }
4041    return false;
4042  }
4043  setup(builder) {
4044    const { targetNode, sourceNode } = this;
4045    const scope = targetNode.getScope();
4046    const scopeData = builder.getDataFromNode(scope);
4047    scopeData.assign = true;
4048    const properties = builder.getNodeProperties(this);
4049    properties.sourceNode = sourceNode;
4050    properties.targetNode = targetNode.context({ assign: true });
4051  }
4052  generate(builder, output3) {
4053    const { targetNode, sourceNode } = builder.getNodeProperties(this);
4054    const needsSplitAssign = this.needsSplitAssign(builder);
4055    const target = targetNode.build(builder);
4056    const targetType = targetNode.getNodeType(builder);
4057    const source = sourceNode.build(builder, targetType);
4058    const sourceType = sourceNode.getNodeType(builder);
4059    const nodeData = builder.getDataFromNode(this);
4060    let snippet;
4061    if (nodeData.initialized === true) {
4062      if (output3 !== "void") {
4063        snippet = target;
4064      }
4065    } else if (needsSplitAssign) {
4066      const sourceVar = builder.getVarFromNode(this, null, targetType);
4067      const sourceProperty = builder.getPropertyName(sourceVar);
4068      builder.addLineFlowCode(`${sourceProperty} = ${source}`, this);
4069      const splitNode = targetNode.node;
4070      const splitTargetNode = splitNode.node.context({ assign: true });
4071      const targetRoot = splitTargetNode.build(builder);
4072      for (let i = 0; i < splitNode.components.length; i++) {
4073        const component = splitNode.components[i];
4074        builder.addLineFlowCode(`${targetRoot}.${component} = ${sourceProperty}[ ${i} ]`, this);
4075      }
4076      if (output3 !== "void") {
4077        snippet = target;
4078      }
4079    } else {
4080      snippet = `${target} = ${source}`;
4081      if (output3 === "void" || sourceType === "void") {
4082        builder.addLineFlowCode(snippet, this);
4083        if (output3 !== "void") {
4084          snippet = target;
4085        }
4086      }
4087    }
4088    nodeData.initialized = true;
4089    return builder.format(snippet, targetType, output3);
4090  }
4091};
4092var assign = /* @__PURE__ */ nodeProxy(AssignNode).setParameterLength(2);
4093addMethodChaining("assign", assign);
4094var FunctionCallNode = class extends TempNode {
4095  static get type() {
4096    return "FunctionCallNode";
4097  }
4098  /**
4099   * Constructs a new function call node.
4100   *
4101   * @param {?FunctionNode} functionNode - The function node.
4102   * @param {Object<string, Node>} [parameters={}] - The parameters for the function call.
4103   */
4104  constructor(functionNode = null, parameters = {}) {
4105    super();
4106    this.functionNode = functionNode;
4107    this.parameters = parameters;
4108  }
4109  /**
4110   * Sets the parameters of the function call node.
4111   *
4112   * @param {Object<string, Node>} parameters - The parameters to set.
4113   * @return {FunctionCallNode} A reference to this node.
4114   */
4115  setParameters(parameters) {
4116    this.parameters = parameters;
4117    return this;
4118  }
4119  /**
4120   * Returns the parameters of the function call node.
4121   *
4122   * @return {Object<string, Node>} The parameters of this node.
4123   */
4124  getParameters() {
4125    return this.parameters;
4126  }
4127  /**
4128   * Returns the type of this function call node.
4129   *
4130   * @param {NodeBuilder} builder - The current node builder.
4131   * @returns {string} The type of this node.
4132   */
4133  generateNodeType(builder) {
4134    return this.functionNode.getNodeType(builder);
4135  }
4136  /**
4137   * Returns the function node of this function call node.
4138   *
4139   * @param {NodeBuilder} builder - The current node builder.
4140   * @param {string} [name] - The name of the member.
4141   * @returns {string} The type of the member.
4142   */
4143  getMemberType(builder, name) {
4144    return this.functionNode.getMemberType(builder, name);
4145  }
4146  generate(builder) {
4147    const params = [];
4148    const functionNode = this.functionNode;
4149    const inputs = functionNode.getInputs(builder);
4150    const parameters = this.parameters;
4151    const generateInput = (node, inputNode) => {
4152      const type = inputNode.type;
4153      const pointer = type === "pointer";
4154      let output3;
4155      if (pointer) output3 = "&" + node.build(builder);
4156      else output3 = node.build(builder, type);
4157      return output3;
4158    };
4159    if (Array.isArray(parameters)) {
4160      if (parameters.length > inputs.length) {
4161        error("TSL: The number of provided parameters exceeds the expected number of inputs in 'Fn()'.");
4162        parameters.length = inputs.length;
4163      } else if (parameters.length < inputs.length) {
4164        error("TSL: The number of provided parameters is less than the expected number of inputs in 'Fn()'.");
4165        while (parameters.length < inputs.length) {
4166          parameters.push(float(0));
4167        }
4168      }
4169      for (let i = 0; i < parameters.length; i++) {
4170        params.push(generateInput(parameters[i], inputs[i]));
4171      }
4172    } else {
4173      for (const inputNode of inputs) {
4174        const node = parameters[inputNode.name];
4175        if (node !== void 0) {
4176          params.push(generateInput(node, inputNode));
4177        } else {
4178          error(`TSL: Input '${inputNode.name}' not found in 'Fn()'.`);
4179          params.push(generateInput(float(0), inputNode));
4180        }
4181      }
4182    }
4183    const functionName = functionNode.build(builder, "property");
4184    return `${functionName}( ${params.join(", ")} )`;
4185  }
4186};
4187var call = (func, ...params) => {
4188  params = params.length > 1 || params[0] && params[0].isNode === true ? nodeArray(params) : nodeObjects(params[0]);
4189  return new FunctionCallNode(nodeObject(func), params);
4190};
4191addMethodChaining("call", call);
4192var _vectorOperators = {
4193  "==": "equal",
4194  "!=": "notEqual",
4195  "<": "lessThan",
4196  ">": "greaterThan",
4197  "<=": "lessThanEqual",
4198  ">=": "greaterThanEqual",
4199  "%": "mod"
4200};
4201var OperatorNode = class _OperatorNode extends TempNode {
4202  static get type() {
4203    return "OperatorNode";
4204  }
4205  /**
4206   * Constructs a new operator node.
4207   *
4208   * @param {string} op - The operator.
4209   * @param {Node} aNode - The first input.
4210   * @param {Node} bNode - The second input.
4211   * @param {...Node} params - Additional input parameters.
4212   */
4213  constructor(op, aNode, bNode, ...params) {
4214    super();
4215    if (params.length > 0) {
4216      let finalOp = new _OperatorNode(op, aNode, bNode);
4217      for (let i = 0; i < params.length - 1; i++) {
4218        finalOp = new _OperatorNode(op, finalOp, params[i]);
4219      }
4220      aNode = finalOp;
4221      bNode = params[params.length - 1];
4222    }
4223    this.op = op;
4224    this.aNode = aNode;
4225    this.bNode = bNode;
4226    this.isOperatorNode = true;
4227  }
4228  /**
4229   * Returns the operator method name.
4230   *
4231   * @param {NodeBuilder} builder - The current node builder.
4232   * @param {string} output - The output type.
4233   * @returns {string} The operator method name.
4234   */
4235  getOperatorMethod(builder, output3) {
4236    return builder.getMethod(_vectorOperators[this.op], output3);
4237  }
4238  /**
4239   * This method is overwritten since the node type is inferred from the operator
4240   * and the input node types.
4241   *
4242   * @param {NodeBuilder} builder - The current node builder.
4243   * @param {?string} [output=null] - The output type.
4244   * @return {string} The node type.
4245   */
4246  generateNodeType(builder, output3 = null) {
4247    const op = this.op;
4248    const aNode = this.aNode;
4249    const bNode = this.bNode;
4250    const typeA = aNode.getNodeType(builder);
4251    const typeB = bNode ? bNode.getNodeType(builder) : null;
4252    if (typeA === "void" || typeB === "void") {
4253      return output3 || "void";
4254    } else if (op === "%") {
4255      return typeA;
4256    } else if (op === "~" || op === "&" || op === "|" || op === "^" || op === ">>" || op === "<<") {
4257      return builder.getIntegerType(typeA);
4258    } else if (op === "!" || op === "&&" || op === "||" || op === "^^") {
4259      return "bool";
4260    } else if (op === "==" || op === "!=" || op === "<" || op === ">" || op === "<=" || op === ">=") {
4261      const typeLength = Math.max(builder.getTypeLength(typeA), builder.getTypeLength(typeB));
4262      return typeLength > 1 ? `bvec${typeLength}` : "bool";
4263    } else {
4264      if (builder.isMatrix(typeA)) {
4265        if (typeB === "float") {
4266          return typeA;
4267        } else if (builder.isVector(typeB)) {
4268          return builder.getVectorFromMatrix(typeA);
4269        } else if (builder.isMatrix(typeB)) {
4270          return typeA;
4271        }
4272      } else if (builder.isMatrix(typeB)) {
4273        if (typeA === "float") {
4274          return typeB;
4275        } else if (builder.isVector(typeA)) {
4276          return builder.getVectorFromMatrix(typeB);
4277        }
4278      }
4279      if (builder.getTypeLength(typeB) > builder.getTypeLength(typeA)) {
4280        return typeB;
4281      }
4282      return typeA;
4283    }
4284  }
4285  generate(builder, output3) {
4286    const op = this.op;
4287    const { aNode, bNode } = this;
4288    const type = this.getNodeType(builder, output3);
4289    let typeA = null;
4290    let typeB = null;
4291    if (type !== "void") {
4292      typeA = aNode.getNodeType(builder);
4293      typeB = bNode ? bNode.getNodeType(builder) : null;
4294      if (op === "<" || op === ">" || op === "<=" || op === ">=" || op === "==" || op === "!=") {
4295        if (builder.isVector(typeA)) {
4296          typeB = typeA;
4297        } else if (builder.isVector(typeB)) {
4298          typeA = typeB;
4299        } else if (typeA !== typeB) {
4300          typeA = typeB = "float";
4301        }
4302      } else if (op === ">>" || op === "<<") {
4303        typeA = type;
4304        typeB = builder.changeComponentType(typeB, "uint");
4305      } else if (op === "%") {
4306        typeA = type;
4307        typeB = builder.isInteger(typeA) && builder.isInteger(typeB) ? typeB : typeA;
4308      } else if (builder.isMatrix(typeA)) {
4309        if (typeB === "float") {
4310          typeB = "float";
4311        } else if (builder.isVector(typeB)) {
4312          typeB = builder.getVectorFromMatrix(typeA);
4313        } else if (builder.isMatrix(typeB)) ;
4314        else {
4315          typeA = typeB = type;
4316        }
4317      } else if (builder.isMatrix(typeB)) {
4318        if (typeA === "float") {
4319          typeA = "float";
4320        } else if (builder.isVector(typeA)) {
4321          typeA = builder.getVectorFromMatrix(typeB);
4322        } else {
4323          typeA = typeB = type;
4324        }
4325      } else {
4326        typeA = typeB = type;
4327      }
4328    } else {
4329      typeA = typeB = type;
4330    }
4331    const a = aNode.build(builder, typeA);
4332    const b = bNode ? bNode.build(builder, typeB) : null;
4333    const fnOpSnippet = builder.getFunctionOperator(op);
4334    if (output3 !== "void") {
4335      const isGLSL = builder.renderer.coordinateSystem === WebGLCoordinateSystem;
4336      if (op === "==" || op === "!=" || op === "<" || op === ">" || op === "<=" || op === ">=") {
4337        if (isGLSL) {
4338          if (builder.isVector(typeA)) {
4339            return builder.format(`${this.getOperatorMethod(builder, output3)}( ${a}, ${b} )`, type, output3);
4340          } else {
4341            return builder.format(`( ${a} ${op} ${b} )`, type, output3);
4342          }
4343        } else {
4344          return builder.format(`( ${a} ${op} ${b} )`, type, output3);
4345        }
4346      } else if (op === "%") {
4347        if (builder.isInteger(typeB)) {
4348          return builder.format(`( ${a} % ${b} )`, type, output3);
4349        } else {
4350          return builder.format(`${this.getOperatorMethod(builder, type)}( ${a}, ${b} )`, type, output3);
4351        }
4352      } else if (op === "!" || op === "~") {
4353        return builder.format(`(${op}${a})`, typeA, output3);
4354      } else if (fnOpSnippet) {
4355        return builder.format(`${fnOpSnippet}( ${a}, ${b} )`, type, output3);
4356      } else {
4357        if (builder.isMatrix(typeA) && typeB === "float") {
4358          return builder.format(`( ${b} ${op} ${a} )`, type, output3);
4359        } else if (typeA === "float" && builder.isMatrix(typeB)) {
4360          return builder.format(`${a} ${op} ${b}`, type, output3);
4361        } else {
4362          let snippet = `( ${a} ${op} ${b} )`;
4363          if (!isGLSL && type === "bool" && builder.isVector(typeA) && builder.isVector(typeB)) {
4364            snippet = `all${snippet}`;
4365          }
4366          return builder.format(snippet, type, output3);
4367        }
4368      }
4369    } else if (typeA !== "void") {
4370      if (fnOpSnippet) {
4371        return builder.format(`${fnOpSnippet}( ${a}, ${b} )`, type, output3);
4372      } else {
4373        if (builder.isMatrix(typeA) && typeB === "float") {
4374          return builder.format(`${b} ${op} ${a}`, type, output3);
4375        } else {
4376          return builder.format(`${a} ${op} ${b}`, type, output3);
4377        }
4378      }
4379    }
4380  }
4381  serialize(data) {
4382    super.serialize(data);
4383    data.op = this.op;
4384  }
4385  deserialize(data) {
4386    super.deserialize(data);
4387    this.op = data.op;
4388  }
4389};
4390var add = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "+").setParameterLength(2, Infinity).setName("add");
4391var sub = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "-").setParameterLength(2, Infinity).setName("sub");
4392var mul = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "*").setParameterLength(2, Infinity).setName("mul");
4393var div = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "/").setParameterLength(2, Infinity).setName("div");
4394var mod = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "%").setParameterLength(2).setName("mod");
4395var equal = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "==").setParameterLength(2).setName("equal");
4396var notEqual = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "!=").setParameterLength(2).setName("notEqual");
4397var lessThan = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "<").setParameterLength(2).setName("lessThan");
4398var greaterThan = /* @__PURE__ */ nodeProxyIntent(OperatorNode, ">").setParameterLength(2).setName("greaterThan");
4399var lessThanEqual = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "<=").setParameterLength(2).setName("lessThanEqual");
4400var greaterThanEqual = /* @__PURE__ */ nodeProxyIntent(OperatorNode, ">=").setParameterLength(2).setName("greaterThanEqual");
4401var and = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "&&").setParameterLength(2, Infinity).setName("and");
4402var or = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "||").setParameterLength(2, Infinity).setName("or");
4403var not = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "!").setParameterLength(1).setName("not");
4404var xor = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "^^").setParameterLength(2).setName("xor");
4405var bitAnd = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "&").setParameterLength(2).setName("bitAnd");
4406var bitNot = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "~").setParameterLength(1).setName("bitNot");
4407var bitOr = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "|").setParameterLength(2).setName("bitOr");
4408var bitXor = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "^").setParameterLength(2).setName("bitXor");
4409var shiftLeft = /* @__PURE__ */ nodeProxyIntent(OperatorNode, "<<").setParameterLength(2).setName("shiftLeft");
4410var shiftRight = /* @__PURE__ */ nodeProxyIntent(OperatorNode, ">>").setParameterLength(2).setName("shiftRight");
4411var incrementBefore = Fn(([a]) => {
4412  a.addAssign(1);
4413  return a;
4414});
4415var decrementBefore = Fn(([a]) => {
4416  a.subAssign(1);
4417  return a;
4418});
4419var increment = /* @__PURE__ */ Fn(([a]) => {
4420  const temp = int(a).toConst();
4421  a.addAssign(1);
4422  return temp;
4423});
4424var decrement = /* @__PURE__ */ Fn(([a]) => {
4425  const temp = int(a).toConst();
4426  a.subAssign(1);
4427  return temp;
4428});
4429addMethodChaining("add", add);
4430addMethodChaining("sub", sub);
4431addMethodChaining("mul", mul);
4432addMethodChaining("div", div);
4433addMethodChaining("mod", mod);
4434addMethodChaining("equal", equal);
4435addMethodChaining("notEqual", notEqual);
4436addMethodChaining("lessThan", lessThan);
4437addMethodChaining("greaterThan", greaterThan);
4438addMethodChaining("lessThanEqual", lessThanEqual);
4439addMethodChaining("greaterThanEqual", greaterThanEqual);
4440addMethodChaining("and", and);
4441addMethodChaining("or", or);
4442addMethodChaining("not", not);
4443addMethodChaining("xor", xor);
4444addMethodChaining("bitAnd", bitAnd);
4445addMethodChaining("bitNot", bitNot);
4446addMethodChaining("bitOr", bitOr);
4447addMethodChaining("bitXor", bitXor);
4448addMethodChaining("shiftLeft", shiftLeft);
4449addMethodChaining("shiftRight", shiftRight);
4450addMethodChaining("incrementBefore", incrementBefore);
4451addMethodChaining("decrementBefore", decrementBefore);
4452addMethodChaining("increment", increment);
4453addMethodChaining("decrement", decrement);
4454var modInt = (a, b) => {
4455  warn('TSL: "modInt()" is deprecated. Use "mod( int( ... ) )" instead.', new StackTrace());
4456  return mod(int(a), int(b));
4457};
4458addMethodChaining("modInt", modInt);
4459var MathNode = class _MathNode extends TempNode {
4460  static get type() {
4461    return "MathNode";
4462  }
4463  /**
4464   * Constructs a new math node.
4465   *
4466   * @param {string} method - The method name.
4467   * @param {Node} aNode - The first input.
4468   * @param {?Node} [bNode=null] - The second input.
4469   * @param {?Node} [cNode=null] - The third input.
4470   */
4471  constructor(method, aNode, bNode = null, cNode = null) {
4472    super();
4473    if ((method === _MathNode.MAX || method === _MathNode.MIN) && arguments.length > 3) {
4474      let finalOp = new _MathNode(method, aNode, bNode);
4475      for (let i = 2; i < arguments.length - 1; i++) {
4476        finalOp = new _MathNode(method, finalOp, arguments[i]);
4477      }
4478      aNode = finalOp;
4479      bNode = arguments[arguments.length - 1];
4480      cNode = null;
4481    }
4482    this.method = method;
4483    this.aNode = aNode;
4484    this.bNode = bNode;
4485    this.cNode = cNode;
4486    this.isMathNode = true;
4487  }
4488  /**
4489   * The input type is inferred from the node types of the input nodes.
4490   *
4491   * @param {NodeBuilder} builder - The current node builder.
4492   * @return {string} The input type.
4493   */
4494  getInputType(builder) {
4495    const aType = this.aNode.getNodeType(builder);
4496    const bType = this.bNode ? this.bNode.getNodeType(builder) : null;
4497    const cType = this.cNode ? this.cNode.getNodeType(builder) : null;
4498    const aLen = builder.isMatrix(aType) ? 0 : builder.getTypeLength(aType);
4499    const bLen = builder.isMatrix(bType) ? 0 : builder.getTypeLength(bType);
4500    const cLen = builder.isMatrix(cType) ? 0 : builder.getTypeLength(cType);
4501    if (aLen > bLen && aLen > cLen) {
4502      return aType;
4503    } else if (bLen > cLen) {
4504      return bType;
4505    } else if (cLen > aLen) {
4506      return cType;
4507    }
4508    return aType;
4509  }
4510  /**
4511   * The selected method as well as the input type determine the node type of this node.
4512   *
4513   * @param {NodeBuilder} builder - The current node builder.
4514   * @return {string} The node type.
4515   */
4516  generateNodeType(builder) {
4517    const method = this.method;
4518    if (method === _MathNode.LENGTH || method === _MathNode.DISTANCE || method === _MathNode.DOT) {
4519      return "float";
4520    } else if (method === _MathNode.CROSS) {
4521      return "vec3";
4522    } else if (method === _MathNode.ALL || method === _MathNode.ANY) {
4523      return "bool";
4524    } else if (method === _MathNode.EQUALS) {
4525      return builder.changeComponentType(this.aNode.getNodeType(builder), "bool");
4526    } else {
4527      return this.getInputType(builder);
4528    }
4529  }
4530  setup(builder) {
4531    const { aNode, bNode, method } = this;
4532    let outputNode = null;
4533    if (method === _MathNode.ONE_MINUS) {
4534      outputNode = sub(1, aNode);
4535    } else if (method === _MathNode.RECIPROCAL) {
4536      outputNode = div(1, aNode);
4537    } else if (method === _MathNode.DIFFERENCE) {
4538      outputNode = abs(sub(aNode, bNode));
4539    } else if (method === _MathNode.TRANSFORM_DIRECTION) {
4540      let tA = aNode;
4541      let tB = bNode;
4542      if (builder.isMatrix(tA.getNodeType(builder))) {
4543        tB = vec4(vec3(tB), 0);
4544      } else {
4545        tA = vec4(vec3(tA), 0);
4546      }
4547      const mulNode = mul(tA, tB).xyz;
4548      outputNode = normalize(mulNode);
4549    }
4550    if (outputNode !== null) {
4551      return outputNode;
4552    } else {
4553      return super.setup(builder);
4554    }
4555  }
4556  generate(builder, output3) {
4557    const properties = builder.getNodeProperties(this);
4558    if (properties.outputNode) {
4559      return super.generate(builder, output3);
4560    }
4561    let method = this.method;
4562    const type = this.getNodeType(builder);
4563    const inputType = this.getInputType(builder);
4564    const a = this.aNode;
4565    const b = this.bNode;
4566    const c = this.cNode;
4567    const coordinateSystem = builder.renderer.coordinateSystem;
4568    if (method === _MathNode.NEGATE) {
4569      return builder.format("( - " + a.build(builder, inputType) + " )", type, output3);
4570    } else {
4571      const params = [];
4572      if (method === _MathNode.CROSS) {
4573        params.push(
4574          a.build(builder, type),
4575          b.build(builder, type)
4576        );
4577      } else if (coordinateSystem === WebGLCoordinateSystem && method === _MathNode.STEP) {
4578        params.push(
4579          a.build(builder, builder.getTypeLength(a.getNodeType(builder)) === 1 ? "float" : inputType),
4580          b.build(builder, inputType)
4581        );
4582      } else if (coordinateSystem === WebGLCoordinateSystem && (method === _MathNode.MIN || method === _MathNode.MAX)) {
4583        params.push(
4584          a.build(builder, inputType),
4585          b.build(builder, builder.getTypeLength(b.getNodeType(builder)) === 1 ? "float" : inputType)
4586        );
4587      } else if (method === _MathNode.REFRACT) {
4588        params.push(
4589          a.build(builder, inputType),
4590          b.build(builder, inputType),
4591          c.build(builder, "float")
4592        );
4593      } else if (method === _MathNode.MIX) {
4594        params.push(
4595          a.build(builder, inputType),
4596          b.build(builder, inputType),
4597          c.build(builder, builder.getTypeLength(c.getNodeType(builder)) === 1 ? "float" : inputType)
4598        );
4599      } else {
4600        if (coordinateSystem === WebGPUCoordinateSystem && method === _MathNode.ATAN && b !== null) {
4601          method = "atan2";
4602        }
4603        if (builder.shaderStage !== "fragment" && (method === _MathNode.DFDX || method === _MathNode.DFDY)) {
4604          warn(`TSL: '${method}' is not supported in the ${builder.shaderStage} stage.`, this.stackTrace);
4605          method = "/*" + method + "*/";
4606        }
4607        params.push(a.build(builder, inputType));
4608        if (b !== null) params.push(b.build(builder, inputType));
4609        if (c !== null) params.push(c.build(builder, inputType));
4610      }
4611      return builder.format(`${builder.getMethod(method, type)}( ${params.join(", ")} )`, type, output3);
4612    }
4613  }
4614  serialize(data) {
4615    super.serialize(data);
4616    data.method = this.method;
4617  }
4618  deserialize(data) {
4619    super.deserialize(data);
4620    this.method = data.method;
4621  }
4622};
4623MathNode.ALL = "all";
4624MathNode.ANY = "any";
4625MathNode.RADIANS = "radians";
4626MathNode.DEGREES = "degrees";
4627MathNode.EXP = "exp";
4628MathNode.EXP2 = "exp2";
4629MathNode.LOG = "log";
4630MathNode.LOG2 = "log2";
4631MathNode.SQRT = "sqrt";
4632MathNode.INVERSE_SQRT = "inversesqrt";
4633MathNode.FLOOR = "floor";
4634MathNode.CEIL = "ceil";
4635MathNode.NORMALIZE = "normalize";
4636MathNode.FRACT = "fract";
4637MathNode.SIN = "sin";
4638MathNode.SINH = "sinh";
4639MathNode.COS = "cos";
4640MathNode.COSH = "cosh";
4641MathNode.TAN = "tan";
4642MathNode.TANH = "tanh";
4643MathNode.ASIN = "asin";
4644MathNode.ASINH = "asinh";
4645MathNode.ACOS = "acos";
4646MathNode.ACOSH = "acosh";
4647MathNode.ATAN = "atan";
4648MathNode.ATANH = "atanh";
4649MathNode.ABS = "abs";
4650MathNode.SIGN = "sign";
4651MathNode.LENGTH = "length";
4652MathNode.NEGATE = "negate";
4653MathNode.ONE_MINUS = "oneMinus";
4654MathNode.DFDX = "dFdx";
4655MathNode.DFDY = "dFdy";
4656MathNode.ROUND = "round";
4657MathNode.RECIPROCAL = "reciprocal";
4658MathNode.TRUNC = "trunc";
4659MathNode.FWIDTH = "fwidth";
4660MathNode.TRANSPOSE = "transpose";
4661MathNode.DETERMINANT = "determinant";
4662MathNode.INVERSE = "inverse";
4663MathNode.EQUALS = "equals";
4664MathNode.MIN = "min";
4665MathNode.MAX = "max";
4666MathNode.STEP = "step";
4667MathNode.REFLECT = "reflect";
4668MathNode.DISTANCE = "distance";
4669MathNode.DIFFERENCE = "difference";
4670MathNode.DOT = "dot";
4671MathNode.CROSS = "cross";
4672MathNode.POW = "pow";
4673MathNode.TRANSFORM_DIRECTION = "transformDirection";
4674MathNode.MIX = "mix";
4675MathNode.CLAMP = "clamp";
4676MathNode.REFRACT = "refract";
4677MathNode.SMOOTHSTEP = "smoothstep";
4678MathNode.FACEFORWARD = "faceforward";
4679var EPSILON = /* @__PURE__ */ float(1e-6);
4680var INFINITY = /* @__PURE__ */ float(1e6);
4681var PI = /* @__PURE__ */ float(Math.PI);
4682var PI2 = /* @__PURE__ */ float(Math.PI * 2);
4683var TWO_PI = /* @__PURE__ */ float(Math.PI * 2);
4684var HALF_PI = /* @__PURE__ */ float(Math.PI * 0.5);
4685var all = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ALL).setParameterLength(1);
4686var any = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ANY).setParameterLength(1);
4687var radians = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.RADIANS).setParameterLength(1);
4688var degrees = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.DEGREES).setParameterLength(1);
4689var exp = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.EXP).setParameterLength(1);
4690var exp2 = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.EXP2).setParameterLength(1);
4691var log2 = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.LOG).setParameterLength(1);
4692var log22 = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.LOG2).setParameterLength(1);
4693var sqrt = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.SQRT).setParameterLength(1);
4694var inverseSqrt = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.INVERSE_SQRT).setParameterLength(1);
4695var floor = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.FLOOR).setParameterLength(1);
4696var ceil = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.CEIL).setParameterLength(1);
4697var normalize = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.NORMALIZE).setParameterLength(1);
4698var fract = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.FRACT).setParameterLength(1);
4699var sin = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.SIN).setParameterLength(1);
4700var sinh = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.SINH).setParameterLength(1);
4701var cos = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.COS).setParameterLength(1);
4702var cosh = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.COSH).setParameterLength(1);
4703var tan = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.TAN).setParameterLength(1);
4704var tanh = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.TANH).setParameterLength(1);
4705var asin = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ASIN).setParameterLength(1);
4706var asinh = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ASINH).setParameterLength(1);
4707var acos = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ACOS).setParameterLength(1);
4708var acosh = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ACOSH).setParameterLength(1);
4709var atan = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ATAN).setParameterLength(1, 2);
4710var atanh = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ATANH).setParameterLength(1);
4711var abs = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ABS).setParameterLength(1);
4712var sign = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.SIGN).setParameterLength(1);
4713var length = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.LENGTH).setParameterLength(1);
4714var negate = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.NEGATE).setParameterLength(1);
4715var oneMinus = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ONE_MINUS).setParameterLength(1);
4716var dFdx = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.DFDX).setParameterLength(1);
4717var dFdy = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.DFDY).setParameterLength(1);
4718var round = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.ROUND).setParameterLength(1);
4719var reciprocal = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.RECIPROCAL).setParameterLength(1);
4720var trunc = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.TRUNC).setParameterLength(1);
4721var fwidth = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.FWIDTH).setParameterLength(1);
4722var transpose = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.TRANSPOSE).setParameterLength(1);
4723var determinant = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.DETERMINANT).setParameterLength(1);
4724var inverse = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.INVERSE).setParameterLength(1);
4725var min$1 = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.MIN).setParameterLength(2, Infinity);
4726var max$1 = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.MAX).setParameterLength(2, Infinity);
4727var step = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.STEP).setParameterLength(2);
4728var reflect = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.REFLECT).setParameterLength(2);
4729var distance = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.DISTANCE).setParameterLength(2);
4730var difference = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.DIFFERENCE).setParameterLength(2);
4731var dot = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.DOT).setParameterLength(2);
4732var cross = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.CROSS).setParameterLength(2);
4733var pow = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.POW).setParameterLength(2);
4734var pow2 = (x) => mul(x, x);
4735var pow3 = (x) => mul(x, x, x);
4736var pow4 = (x) => mul(x, x, x, x);
4737var transformDirection = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.TRANSFORM_DIRECTION).setParameterLength(2);
4738var cbrt = (a) => mul(sign(a), pow(abs(a), 1 / 3));
4739var lengthSq = (a) => dot(a, a);
4740var mix = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.MIX).setParameterLength(3);
4741var clamp = (value, low = 0, high = 1) => new MathNode(MathNode.CLAMP, nodeObject(value), nodeObject(low), nodeObject(high));
4742var saturate = (value) => clamp(value);
4743var refract = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.REFRACT).setParameterLength(3);
4744var smoothstep = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.SMOOTHSTEP).setParameterLength(3);
4745var faceForward = /* @__PURE__ */ nodeProxyIntent(MathNode, MathNode.FACEFORWARD).setParameterLength(3);
4746var rand = /* @__PURE__ */ Fn(([uv3]) => {
4747  const a = 12.9898, b = 78.233, c = 43758.5453;
4748  const dt = dot(uv3.xy, vec2(a, b)), sn = mod(dt, PI);
4749  return fract(sin(sn).mul(c));
4750});
4751var mixElement = (t, e1, e2) => mix(e1, e2, t);
4752var smoothstepElement = (x, low, high) => smoothstep(low, high, x);
4753var stepElement = (x, edge) => step(edge, x);
4754var faceforward = faceForward;
4755var inversesqrt = inverseSqrt;
4756addMethodChaining("all", all);
4757addMethodChaining("any", any);
4758addMethodChaining("radians", radians);
4759addMethodChaining("degrees", degrees);
4760addMethodChaining("exp", exp);
4761addMethodChaining("exp2", exp2);
4762addMethodChaining("log", log2);
4763addMethodChaining("log2", log22);
4764addMethodChaining("sqrt", sqrt);
4765addMethodChaining("inverseSqrt", inverseSqrt);
4766addMethodChaining("floor", floor);
4767addMethodChaining("ceil", ceil);
4768addMethodChaining("normalize", normalize);
4769addMethodChaining("fract", fract);
4770addMethodChaining("sin", sin);
4771addMethodChaining("sinh", sinh);
4772addMethodChaining("cos", cos);
4773addMethodChaining("cosh", cosh);
4774addMethodChaining("tan", tan);
4775addMethodChaining("tanh", tanh);
4776addMethodChaining("asin", asin);
4777addMethodChaining("asinh", asinh);
4778addMethodChaining("acos", acos);
4779addMethodChaining("acosh", acosh);
4780addMethodChaining("atan", atan);
4781addMethodChaining("atanh", atanh);
4782addMethodChaining("abs", abs);
4783addMethodChaining("sign", sign);
4784addMethodChaining("length", length);
4785addMethodChaining("lengthSq", lengthSq);
4786addMethodChaining("negate", negate);
4787addMethodChaining("oneMinus", oneMinus);
4788addMethodChaining("dFdx", dFdx);
4789addMethodChaining("dFdy", dFdy);
4790addMethodChaining("round", round);
4791addMethodChaining("reciprocal", reciprocal);
4792addMethodChaining("trunc", trunc);
4793addMethodChaining("fwidth", fwidth);
4794addMethodChaining("min", min$1);
4795addMethodChaining("max", max$1);
4796addMethodChaining("step", stepElement);
4797addMethodChaining("reflect", reflect);
4798addMethodChaining("distance", distance);
4799addMethodChaining("dot", dot);
4800addMethodChaining("cross", cross);
4801addMethodChaining("pow", pow);
4802addMethodChaining("pow2", pow2);
4803addMethodChaining("pow3", pow3);
4804addMethodChaining("pow4", pow4);
4805addMethodChaining("transformDirection", transformDirection);
4806addMethodChaining("mix", mixElement);
4807addMethodChaining("clamp", clamp);
4808addMethodChaining("refract", refract);
4809addMethodChaining("smoothstep", smoothstepElement);
4810addMethodChaining("faceForward", faceForward);
4811addMethodChaining("difference", difference);
4812addMethodChaining("saturate", saturate);
4813addMethodChaining("cbrt", cbrt);
4814addMethodChaining("transpose", transpose);
4815addMethodChaining("determinant", determinant);
4816addMethodChaining("inverse", inverse);
4817addMethodChaining("rand", rand);
4818var ConditionalNode = class extends Node2 {
4819  static get type() {
4820    return "ConditionalNode";
4821  }
4822  /**
4823   * Constructs a new conditional node.
4824   *
4825   * @param {Node} condNode - The node that defines the condition.
4826   * @param {Node} ifNode - The node that is evaluate when the condition ends up `true`.
4827   * @param {?Node} [elseNode=null] - The node that is evaluate when the condition ends up `false`.
4828   */
4829  constructor(condNode, ifNode, elseNode = null) {
4830    super();
4831    this.condNode = condNode;
4832    this.ifNode = ifNode;
4833    this.elseNode = elseNode;
4834  }
4835  /**
4836   * This method is overwritten since the node type is inferred from the if/else
4837   * nodes.
4838   *
4839   * @param {NodeBuilder} builder - The current node builder.
4840   * @return {string} The node type.
4841   */
4842  generateNodeType(builder) {
4843    const { ifNode, elseNode } = builder.getNodeProperties(this);
4844    if (ifNode === void 0) {
4845      builder.flowBuildStage(this, "setup");
4846      return this.getNodeType(builder);
4847    }
4848    const ifType = ifNode.getNodeType(builder);
4849    if (elseNode !== null) {
4850      const elseType = elseNode.getNodeType(builder);
4851      if (builder.getTypeLength(elseType) > builder.getTypeLength(ifType)) {
4852        return elseType;
4853      }
4854    }
4855    return ifType;
4856  }
4857  setup(builder) {
4858    const condNode = this.condNode;
4859    const ifNode = this.ifNode.isolate();
4860    const elseNode = this.elseNode ? this.elseNode.isolate() : null;
4861    const currentNodeBlock = builder.context.nodeBlock;
4862    builder.getDataFromNode(ifNode).parentNodeBlock = currentNodeBlock;
4863    if (elseNode !== null) builder.getDataFromNode(elseNode).parentNodeBlock = currentNodeBlock;
4864    const isUniformFlow = builder.context.uniformFlow;
4865    const properties = builder.getNodeProperties(this);
4866    properties.condNode = condNode;
4867    properties.ifNode = isUniformFlow ? ifNode : ifNode.context({ nodeBlock: ifNode });
4868    properties.elseNode = elseNode ? isUniformFlow ? elseNode : elseNode.context({ nodeBlock: elseNode }) : null;
4869  }
4870  generate(builder, output3) {
4871    const type = this.getNodeType(builder);
4872    const nodeData = builder.getDataFromNode(this);
4873    if (nodeData.nodeProperty !== void 0) {
4874      return nodeData.nodeProperty;
4875    }
4876    const { condNode, ifNode, elseNode } = builder.getNodeProperties(this);
4877    const functionNode = builder.currentFunctionNode;
4878    const needsOutput = output3 !== "void";
4879    const nodeProperty = needsOutput ? property(type).build(builder) : "";
4880    nodeData.nodeProperty = nodeProperty;
4881    const nodeSnippet = condNode.build(builder, "bool");
4882    const isUniformFlow = builder.context.uniformFlow;
4883    if (isUniformFlow && elseNode !== null) {
4884      const ifSnippet2 = ifNode.build(builder, type);
4885      const elseSnippet = elseNode.build(builder, type);
4886      const mathSnippet = builder.getTernary(nodeSnippet, ifSnippet2, elseSnippet);
4887      return builder.format(mathSnippet, type, output3);
4888    }
4889    builder.addFlowCode(`
4890${builder.tab}if ( ${nodeSnippet} ) {
4891
4892`).addFlowTab();
4893    let ifSnippet = ifNode.build(builder, type);
4894    if (ifSnippet) {
4895      if (needsOutput) {
4896        ifSnippet = nodeProperty + " = " + ifSnippet + ";";
4897      } else {
4898        ifSnippet = "return " + ifSnippet + ";";
4899        if (functionNode === null) {
4900          warn("TSL: Return statement used in an inline 'Fn()'. Define a layout struct to allow return values.", this.stackTrace);
4901          ifSnippet = "// " + ifSnippet;
4902        }
4903      }
4904    }
4905    builder.removeFlowTab().addFlowCode(builder.tab + "	" + ifSnippet + "\n\n" + builder.tab + "}");
4906    if (elseNode !== null) {
4907      builder.addFlowCode(" else {\n\n").addFlowTab();
4908      let elseSnippet = elseNode.build(builder, type);
4909      if (elseSnippet) {
4910        if (needsOutput) {
4911          elseSnippet = nodeProperty + " = " + elseSnippet + ";";
4912        } else {
4913          elseSnippet = "return " + elseSnippet + ";";
4914          if (functionNode === null) {
4915            warn("TSL: Return statement used in an inline 'Fn()'. Define a layout struct to allow return values.", this.stackTrace);
4916            elseSnippet = "// " + elseSnippet;
4917          }
4918        }
4919      }
4920      builder.removeFlowTab().addFlowCode(builder.tab + "	" + elseSnippet + "\n\n" + builder.tab + "}\n\n");
4921    } else {
4922      builder.addFlowCode("\n\n");
4923    }
4924    return builder.format(nodeProperty, type, output3);
4925  }
4926};
4927var select = /* @__PURE__ */ nodeProxy(ConditionalNode).setParameterLength(2, 3);
4928addMethodChaining("select", select);
4929var ContextNode = class extends Node2 {
4930  static get type() {
4931    return "ContextNode";
4932  }
4933  /**
4934   * Constructs a new context node.
4935   *
4936   * @param {Node} node - The node whose context should be modified.
4937   * @param {Object} [value={}] - The modified context data.
4938   */
4939  constructor(node = null, value = {}) {
4940    super();
4941    this.isContextNode = true;
4942    this.node = node;
4943    this.value = value;
4944  }
4945  /**
4946   * This method is overwritten to ensure it returns the reference to {@link ContextNode#node}.
4947   *
4948   * @return {Node} A reference to {@link ContextNode#node}.
4949   */
4950  getScope() {
4951    return this.node.getScope();
4952  }
4953  /**
4954   * This method is overwritten to ensure it returns the type of {@link ContextNode#node}.
4955   *
4956   * @param {NodeBuilder} builder - The current node builder.
4957   * @return {string} The node type.
4958   */
4959  generateNodeType(builder) {
4960    return this.node.getNodeType(builder);
4961  }
4962  /**
4963   * Gathers the context data from all parent context nodes.
4964   *
4965   * @return {Object} The gathered context data.
4966   */
4967  getFlowContextData() {
4968    const children2 = [];
4969    this.traverse((node) => {
4970      if (node.isContextNode === true) {
4971        children2.push(node.value);
4972      }
4973    });
4974    return Object.assign({}, ...children2);
4975  }
4976  /**
4977   * This method is overwritten to ensure it returns the member type of {@link ContextNode#node}.
4978   *
4979   * @param {NodeBuilder} builder - The current node builder.
4980   * @param {string} name - The member name.
4981   * @returns {string} The member type.
4982   */
4983  getMemberType(builder, name) {
4984    return this.node.getMemberType(builder, name);
4985  }
4986  analyze(builder) {
4987    const previousContext = builder.addContext(this.value);
4988    this.node.build(builder);
4989    builder.setContext(previousContext);
4990  }
4991  setup(builder) {
4992    const previousContext = builder.addContext(this.value);
4993    this.node.build(builder);
4994    builder.setContext(previousContext);
4995  }
4996  generate(builder, output3) {
4997    const previousContext = builder.addContext(this.value);
4998    const snippet = this.node.build(builder, output3);
4999    builder.setContext(previousContext);
5000    return snippet;
5001  }
5002};
5003var context = (nodeOrValue = null, value = {}) => {
5004  let node = nodeOrValue;
5005  if (node === null || node.isNode !== true) {
5006    value = node || value;
5007    node = null;
5008  }
5009  return new ContextNode(node, value);
5010};
5011var uniformFlow = (node) => context(node, { uniformFlow: true });
5012var setName = (node, name) => context(node, { nodeName: name });
5013function builtinShadowContext(shadowNode, light, node = null) {
5014  return context(node, {
5015    getShadow: ({ light: shadowLight, shadowColorNode }) => {
5016      if (light === shadowLight) {
5017        return shadowColorNode.mul(shadowNode);
5018      }
5019      return shadowColorNode;
5020    }
5021  });
5022}
5023function builtinAOContext(aoNode, node = null) {
5024  return context(node, {
5025    getAO: (inputNode, { material }) => {
5026      if (material.transparent === true) return inputNode;
5027      return inputNode !== null ? inputNode.mul(aoNode) : aoNode;
5028    }
5029  });
5030}
5031function label(node, name) {
5032  warn('TSL: "label()" has been deprecated. Use "setName()" instead.');
5033  return setName(node, name);
5034}
5035addMethodChaining("context", context);
5036addMethodChaining("label", label);
5037addMethodChaining("uniformFlow", uniformFlow);
5038addMethodChaining("setName", setName);
5039addMethodChaining("builtinShadowContext", (node, shadowNode, light) => builtinShadowContext(shadowNode, light, node));
5040addMethodChaining("builtinAOContext", (node, aoValue) => builtinAOContext(aoValue, node));
5041var VarNode = class extends Node2 {
5042  static get type() {
5043    return "VarNode";
5044  }
5045  /**
5046   * Constructs a new variable node.
5047   *
5048   * @param {Node} node - The node for which a variable should be created.
5049   * @param {?string} [name=null] - The name of the variable in the shader.
5050   * @param {boolean} [readOnly=false] - The read-only flag.
5051   */
5052  constructor(node, name = null, readOnly = false) {
5053    super();
5054    this.node = node;
5055    this.name = name;
5056    this.global = true;
5057    this.isVarNode = true;
5058    this.readOnly = readOnly;
5059    this.parents = true;
5060    this.intent = false;
5061  }
5062  /**
5063   * Sets the intent flag for this node.
5064   *
5065   * This flag is used to indicate that this node is used for intent
5066   * and should not be built directly. Instead, it is used to indicate that
5067   * the node should be treated as a variable intent.
5068   *
5069   * It's useful for assigning variables without needing creating a new variable node.
5070   *
5071   * @param {boolean} value - The value to set for the intent flag.
5072   * @returns {VarNode} This node.
5073   */
5074  setIntent(value) {
5075    this.intent = value;
5076    return this;
5077  }
5078  /**
5079   * Checks if this node is used for intent.
5080   *
5081   * @param {NodeBuilder} builder - The node builder.
5082   * @returns {boolean} Whether this node is used for intent.
5083   */
5084  isIntent(builder) {
5085    const data = builder.getDataFromNode(this);
5086    if (data.forceDeclaration === true) return false;
5087    return this.intent;
5088  }
5089  /**
5090   * Returns the intent flag of this node.
5091   *
5092   * @return {boolean} The intent flag.
5093   */
5094  getIntent() {
5095    return this.intent;
5096  }
5097  getMemberType(builder, name) {
5098    return this.node.getMemberType(builder, name);
5099  }
5100  getElementType(builder) {
5101    return this.node.getElementType(builder);
5102  }
5103  generateNodeType(builder) {
5104    return this.node.getNodeType(builder);
5105  }
5106  getArrayCount(builder) {
5107    return this.node.getArrayCount(builder);
5108  }
5109  isAssign(builder) {
5110    const data = builder.getDataFromNode(this);
5111    return data.assign;
5112  }
5113  build(...params) {
5114    const builder = params[0];
5115    if (this._hasStack(builder) === false && builder.buildStage === "setup") {
5116      if (builder.context.nodeLoop || builder.context.nodeBlock) {
5117        let addBefore = false;
5118        if (this.node.isShaderCallNodeInternal && this.node.shaderNode.getLayout() === null) {
5119          if (builder.fnCall && builder.fnCall.shaderNode) {
5120            const shaderNodeData = builder.getDataFromNode(this.node.shaderNode);
5121            if (shaderNodeData.hasLoop) {
5122              const data = builder.getDataFromNode(this);
5123              data.forceDeclaration = true;
5124              addBefore = true;
5125            }
5126          }
5127        }
5128        const baseStack = builder.getBaseStack();
5129        if (addBefore) {
5130          baseStack.addToStackBefore(this);
5131        } else {
5132          baseStack.addToStack(this);
5133        }
5134      }
5135    }
5136    if (this.isIntent(builder)) {
5137      if (this.isAssign(builder) !== true) {
5138        return this.node.build(...params);
5139      }
5140    }
5141    return super.build(...params);
5142  }
5143  generate(builder) {
5144    const { node, name, readOnly } = this;
5145    const { renderer } = builder;
5146    const isWebGPUBackend = renderer.backend.isWebGPUBackend === true;
5147    let isDeterministic = false;
5148    let shouldTreatAsReadOnly = false;
5149    if (readOnly) {
5150      isDeterministic = builder.isDeterministic(node);
5151      shouldTreatAsReadOnly = isWebGPUBackend ? readOnly : isDeterministic;
5152    }
5153    const nodeType = this.getNodeType(builder);
5154    if (nodeType == "void") {
5155      if (this.isIntent(builder) !== true) {
5156        error('TSL: ".toVar()" can not be used with void type.', this.stackTrace);
5157      }
5158      const snippet2 = node.build(builder);
5159      return snippet2;
5160    }
5161    const vectorType = builder.getVectorType(nodeType);
5162    const snippet = node.build(builder, vectorType);
5163    const nodeVar = builder.getVarFromNode(this, name, vectorType, void 0, shouldTreatAsReadOnly);
5164    const propertyName = builder.getPropertyName(nodeVar);
5165    let declarationPrefix = propertyName;
5166    if (shouldTreatAsReadOnly) {
5167      if (isWebGPUBackend) {
5168        declarationPrefix = isDeterministic ? `const ${propertyName}` : `let ${propertyName}`;
5169      } else {
5170        const count = node.getArrayCount(builder);
5171        declarationPrefix = `const ${builder.getVar(nodeVar.type, propertyName, count)}`;
5172      }
5173    }
5174    builder.addLineFlowCode(`${declarationPrefix} = ${snippet}`, this);
5175    return propertyName;
5176  }
5177  _hasStack(builder) {
5178    const nodeData = builder.getDataFromNode(this);
5179    return nodeData.stack !== void 0;
5180  }
5181};
5182var createVar = /* @__PURE__ */ nodeProxy(VarNode);
5183var Var = (node, name = null) => createVar(node, name).toStack();
5184var Const = (node, name = null) => createVar(node, name, true).toStack();
5185var VarIntent = (node) => {
5186  return createVar(node).setIntent(true).toStack();
5187};
5188addMethodChaining("toVar", Var);
5189addMethodChaining("toConst", Const);
5190addMethodChaining("toVarIntent", VarIntent);
5191var SubBuildNode = class extends Node2 {
5192  static get type() {
5193    return "SubBuild";
5194  }
5195  constructor(node, name, nodeType = null) {
5196    super(nodeType);
5197    this.node = node;
5198    this.name = name;
5199    this.isSubBuildNode = true;
5200  }
5201  generateNodeType(builder) {
5202    if (this.nodeType !== null) return this.nodeType;
5203    builder.addSubBuild(this.name);
5204    const nodeType = this.node.getNodeType(builder);
5205    builder.removeSubBuild();
5206    return nodeType;
5207  }
5208  build(builder, ...params) {
5209    builder.addSubBuild(this.name);
5210    const data = this.node.build(builder, ...params);
5211    builder.removeSubBuild();
5212    return data;
5213  }
5214};
5215var subBuild = (node, name, type = null) => new SubBuildNode(nodeObject(node), name, type);
5216var VaryingNode = class extends Node2 {
5217  static get type() {
5218    return "VaryingNode";
5219  }
5220  /**
5221   * Constructs a new varying node.
5222   *
5223   * @param {Node} node - The node for which a varying should be created.
5224   * @param {?string} name - The name of the varying in the shader.
5225   */
5226  constructor(node, name = null) {
5227    super();
5228    this.node = subBuild(node, "VERTEX");
5229    this.name = name;
5230    this.isVaryingNode = true;
5231    this.interpolationType = null;
5232    this.interpolationSampling = null;
5233    this.global = true;
5234  }
5235  /**
5236   * Defines the interpolation type of the varying.
5237   *
5238   * @param {string} type - The interpolation type.
5239   * @param {?string} sampling - The interpolation sampling type
5240   * @return {VaryingNode} A reference to this node.
5241   */
5242  setInterpolation(type, sampling = null) {
5243    this.interpolationType = type;
5244    this.interpolationSampling = sampling;
5245    return this;
5246  }
5247  getHash(builder) {
5248    return this.name || super.getHash(builder);
5249  }
5250  generateNodeType(builder) {
5251    return this.node.getNodeType(builder);
5252  }
5253  /**
5254   * This method performs the setup of a varying node with the current node builder.
5255   *
5256   * @param {NodeBuilder} builder - The current node builder.
5257   * @return {NodeVarying} The node varying from the node builder.
5258   */
5259  setupVarying(builder) {
5260    const properties = builder.getNodeProperties(this);
5261    let varying3 = properties.varying;
5262    if (varying3 === void 0) {
5263      const name = this.name;
5264      const type = this.getNodeType(builder);
5265      const interpolationType = this.interpolationType;
5266      const interpolationSampling = this.interpolationSampling;
5267      properties.varying = varying3 = builder.getVaryingFromNode(this, name, type, interpolationType, interpolationSampling);
5268      properties.node = subBuild(this.node, "VERTEX");
5269    }
5270    varying3.needsInterpolation || (varying3.needsInterpolation = builder.shaderStage === "fragment");
5271    return varying3;
5272  }
5273  setup(builder) {
5274    this.setupVarying(builder);
5275    builder.flowNodeFromShaderStage(NodeShaderStage.VERTEX, this.node);
5276  }
5277  analyze(builder) {
5278    this.setupVarying(builder);
5279    builder.flowNodeFromShaderStage(NodeShaderStage.VERTEX, this.node);
5280  }
5281  generate(builder) {
5282    const propertyKey = builder.getSubBuildProperty("property", builder.currentStack);
5283    const properties = builder.getNodeProperties(this);
5284    const varying3 = this.setupVarying(builder);
5285    if (properties[propertyKey] === void 0) {
5286      const type = this.getNodeType(builder);
5287      const propertyName = builder.getPropertyName(varying3, NodeShaderStage.VERTEX);
5288      builder.flowNodeFromShaderStage(NodeShaderStage.VERTEX, properties.node, type, propertyName);
5289      properties[propertyKey] = propertyName;
5290    }
5291    return builder.getPropertyName(varying3);
5292  }
5293};
5294var varying = /* @__PURE__ */ nodeProxy(VaryingNode).setParameterLength(1, 2);
5295var vertexStage = (node) => varying(node);
5296addMethodChaining("toVarying", varying);
5297addMethodChaining("toVertexStage", vertexStage);
5298var sRGBTransferEOTF = /* @__PURE__ */ Fn(([color3]) => {
5299  const a = color3.mul(0.9478672986).add(0.0521327014).pow(2.4);
5300  const b = color3.mul(0.0773993808);
5301  const factor = color3.lessThanEqual(0.04045);
5302  const rgbResult = mix(a, b, factor);
5303  return rgbResult;
5304}).setLayout({
5305  name: "sRGBTransferEOTF",
5306  type: "vec3",
5307  inputs: [
5308    { name: "color", type: "vec3" }
5309  ]
5310});
5311var sRGBTransferOETF = /* @__PURE__ */ Fn(([color3]) => {
5312  const a = color3.pow(0.41666).mul(1.055).sub(0.055);
5313  const b = color3.mul(12.92);
5314  const factor = color3.lessThanEqual(31308e-7);
5315  const rgbResult = mix(a, b, factor);
5316  return rgbResult;
5317}).setLayout({
5318  name: "sRGBTransferOETF",
5319  type: "vec3",
5320  inputs: [
5321    { name: "color", type: "vec3" }
5322  ]
5323});
5324var WORKING_COLOR_SPACE = "WorkingColorSpace";
5325var OUTPUT_COLOR_SPACE = "OutputColorSpace";
5326var ColorSpaceNode = class extends TempNode {
5327  static get type() {
5328    return "ColorSpaceNode";
5329  }
5330  /**
5331   * Constructs a new color space node.
5332   *
5333   * @param {Node} colorNode - Represents the color to convert.
5334   * @param {string} source - The source color space.
5335   * @param {string} target - The target color space.
5336   */
5337  constructor(colorNode, source, target) {
5338    super("vec4");
5339    this.colorNode = colorNode;
5340    this.source = source;
5341    this.target = target;
5342  }
5343  /**
5344   * This method resolves the constants `WORKING_COLOR_SPACE` and
5345   * `OUTPUT_COLOR_SPACE` based on the current configuration of the
5346   * color management and renderer.
5347   *
5348   * @param {NodeBuilder} builder - The current node builder.
5349   * @param {string} colorSpace - The color space to resolve.
5350   * @return {string} The resolved color space.
5351   */
5352  resolveColorSpace(builder, colorSpace) {
5353    if (colorSpace === WORKING_COLOR_SPACE) {
5354      return ColorManagement.workingColorSpace;
5355    } else if (colorSpace === OUTPUT_COLOR_SPACE) {
5356      return builder.context.outputColorSpace || builder.renderer.outputColorSpace;
5357    }
5358    return colorSpace;
5359  }
5360  setup(builder) {
5361    const { colorNode } = this;
5362    const source = this.resolveColorSpace(builder, this.source);
5363    const target = this.resolveColorSpace(builder, this.target);
5364    let outputNode = colorNode;
5365    if (ColorManagement.enabled === false || source === target || !source || !target) {
5366      return outputNode;
5367    }
5368    if (ColorManagement.getTransfer(source) === SRGBTransfer) {
5369      outputNode = vec4(sRGBTransferEOTF(outputNode.rgb), outputNode.a);
5370    }
5371    if (ColorManagement.getPrimaries(source) !== ColorManagement.getPrimaries(target)) {
5372      outputNode = vec4(
5373        mat3(ColorManagement._getMatrix(new Matrix3(), source, target)).mul(outputNode.rgb),
5374        outputNode.a
5375      );
5376    }
5377    if (ColorManagement.getTransfer(target) === SRGBTransfer) {
5378      outputNode = vec4(sRGBTransferOETF(outputNode.rgb), outputNode.a);
5379    }
5380    return outputNode;
5381  }
5382};
5383var workingToColorSpace = (node, targetColorSpace) => new ColorSpaceNode(nodeObject(node), WORKING_COLOR_SPACE, targetColorSpace);
5384var colorSpaceToWorking = (node, sourceColorSpace) => new ColorSpaceNode(nodeObject(node), sourceColorSpace, WORKING_COLOR_SPACE);
5385var convertColorSpace = (node, sourceColorSpace, targetColorSpace) => new ColorSpaceNode(nodeObject(node), sourceColorSpace, targetColorSpace);
5386addMethodChaining("workingToColorSpace", workingToColorSpace);
5387addMethodChaining("colorSpaceToWorking", colorSpaceToWorking);
5388var ReferenceElementNode$1 = class ReferenceElementNode extends ArrayElementNode {
5389  static get type() {
5390    return "ReferenceElementNode";
5391  }
5392  /**
5393   * Constructs a new reference element node.
5394   *
5395   * @param {ReferenceBaseNode} referenceNode - The reference node.
5396   * @param {Node} indexNode - The index node that defines the element access.
5397   */
5398  constructor(referenceNode, indexNode) {
5399    super(referenceNode, indexNode);
5400    this.referenceNode = referenceNode;
5401    this.isReferenceElementNode = true;
5402  }
5403  /**
5404   * This method is overwritten since the node type is inferred from
5405   * the uniform type of the reference node.
5406   *
5407   * @return {string} The node type.
5408   */
5409  generateNodeType() {
5410    return this.referenceNode.uniformType;
5411  }
5412  generate(builder) {
5413    const snippet = super.generate(builder);
5414    const arrayType = this.referenceNode.getNodeType();
5415    const elementType = this.getNodeType();
5416    return builder.format(snippet, arrayType, elementType);
5417  }
5418};
5419var ReferenceBaseNode = class extends Node2 {
5420  static get type() {
5421    return "ReferenceBaseNode";
5422  }
5423  /**
5424   * Constructs a new reference base node.
5425   *
5426   * @param {string} property - The name of the property the node refers to.
5427   * @param {string} uniformType - The uniform type that should be used to represent the property value.
5428   * @param {?Object} [object=null] - The object the property belongs to.
5429   * @param {?number} [count=null] - When the linked property is an array-like, this parameter defines its length.
5430   */
5431  constructor(property3, uniformType, object = null, count = null) {
5432    super();
5433    this.property = property3;
5434    this.uniformType = uniformType;
5435    this.object = object;
5436    this.count = count;
5437    this.properties = property3.split(".");
5438    this.reference = object;
5439    this.node = null;
5440    this.group = null;
5441    this.updateType = NodeUpdateType.OBJECT;
5442  }
5443  /**
5444   * Sets the uniform group for this reference node.
5445   *
5446   * @param {UniformGroupNode} group - The uniform group to set.
5447   * @return {ReferenceBaseNode} A reference to this node.
5448   */
5449  setGroup(group) {
5450    this.group = group;
5451    return this;
5452  }
5453  /**
5454   * When the referred property is array-like, this method can be used
5455   * to access elements via an index node.
5456   *
5457   * @param {IndexNode} indexNode - indexNode.
5458   * @return {ReferenceElementNode} A reference to an element.
5459   */
5460  element(indexNode) {
5461    return new ReferenceElementNode$1(this, nodeObject(indexNode));
5462  }
5463  /**
5464   * Sets the node type which automatically defines the internal
5465   * uniform type.
5466   *
5467   * @param {string} uniformType - The type to set.
5468   */
5469  setNodeType(uniformType) {
5470    const node = uniform(null, uniformType);
5471    if (this.group !== null) {
5472      node.setGroup(this.group);
5473    }
5474    this.node = node;
5475  }
5476  /**
5477   * This method is overwritten since the node type is inferred from
5478   * the type of the reference node.
5479   *
5480   * @param {NodeBuilder} builder - The current node builder.
5481   * @return {string} The node type.
5482   */
5483  generateNodeType(builder) {
5484    if (this.node === null) {
5485      this.updateReference(builder);
5486      this.updateValue();
5487    }
5488    return this.node.getNodeType(builder);
5489  }
5490  /**
5491   * Returns the property value from the given referred object.
5492   *
5493   * @param {Object} [object=this.reference] - The object to retrieve the property value from.
5494   * @return {any} The value.
5495   */
5496  getValueFromReference(object = this.reference) {
5497    const { properties } = this;
5498    let value = object[properties[0]];
5499    for (let i = 1; i < properties.length; i++) {
5500      value = value[properties[i]];
5501    }
5502    return value;
5503  }
5504  /**
5505   * Allows to update the reference based on the given state. The state is only
5506   * evaluated {@link ReferenceBaseNode#object} is not set.
5507   *
5508   * @param {(NodeFrame|NodeBuilder)} state - The current state.
5509   * @return {Object} The updated reference.
5510   */
5511  updateReference(state) {
5512    this.reference = this.object !== null ? this.object : state.object;
5513    return this.reference;
5514  }
5515  /**
5516   * The output of the reference node is the internal uniform node.
5517   *
5518   * @return {UniformNode} The output node.
5519   */
5520  setup() {
5521    this.updateValue();
5522    return this.node;
5523  }
5524  /**
5525   * Overwritten to update the internal uniform value.
5526   *
5527   * @param {NodeFrame} frame - A reference to the current node frame.
5528   */
5529  update() {
5530    this.updateValue();
5531  }
5532  /**
5533   * Retrieves the value from the referred object property and uses it
5534   * to updated the internal uniform.
5535   */
5536  updateValue() {
5537    if (this.node === null) this.setNodeType(this.uniformType);
5538    const value = this.getValueFromReference();
5539    if (Array.isArray(value)) {
5540      this.node.array = value;
5541    } else {
5542      this.node.value = value;
5543    }
5544  }
5545};
5546var reference$1 = (name, type, object) => new ReferenceBaseNode(name, type, object);
5547var RendererReferenceNode = class extends ReferenceBaseNode {
5548  static get type() {
5549    return "RendererReferenceNode";
5550  }
5551  /**
5552   * Constructs a new renderer reference node.
5553   *
5554   * @param {string} property - The name of the property the node refers to.
5555   * @param {string} inputType - The uniform type that should be used to represent the property value.
5556   * @param {?Renderer} [renderer=null] - The renderer the property belongs to. When no renderer is set,
5557   * the node refers to the renderer of the current state.
5558   */
5559  constructor(property3, inputType, renderer = null) {
5560    super(property3, inputType, renderer);
5561    this.renderer = renderer;
5562    this.setGroup(renderGroup);
5563  }
5564  /**
5565   * Updates the reference based on the given state. The state is only evaluated
5566   * {@link RendererReferenceNode#renderer} is not set.
5567   *
5568   * @param {(NodeFrame|NodeBuilder)} state - The current state.
5569   * @return {Object} The updated reference.
5570   */
5571  updateReference(state) {
5572    this.reference = this.renderer !== null ? this.renderer : state.renderer;
5573    return this.reference;
5574  }
5575};
5576var rendererReference = (name, type, renderer = null) => new RendererReferenceNode(name, type, renderer);
5577var ToneMappingNode = class extends TempNode {
5578  static get type() {
5579    return "ToneMappingNode";
5580  }
5581  /**
5582   * Constructs a new tone mapping node.
5583   *
5584   * @param {number} toneMapping - The tone mapping type.
5585   * @param {Node} exposureNode - The tone mapping exposure.
5586   * @param {Node} [colorNode=null] - The color node to process.
5587   */
5588  constructor(toneMapping3, exposureNode = toneMappingExposure, colorNode = null) {
5589    super("vec3");
5590    this._toneMapping = toneMapping3;
5591    this.exposureNode = exposureNode;
5592    this.colorNode = colorNode;
5593  }
5594  /**
5595   * Overwrites the default `customCacheKey()` implementation by including the tone
5596   * mapping type into the cache key.
5597   *
5598   * @return {number} The hash.
5599   */
5600  customCacheKey() {
5601    return hash$1(this._toneMapping);
5602  }
5603  /**
5604   * Sets the tone mapping type.
5605   *
5606   * @param {number} value - The tone mapping type.
5607   * @return {ToneMappingNode} A reference to this node.
5608   */
5609  setToneMapping(value) {
5610    this._toneMapping = value;
5611    return this;
5612  }
5613  /**
5614   * Gets the tone mapping type.
5615   *
5616   * @returns {number} The tone mapping type.
5617   */
5618  getToneMapping() {
5619    return this._toneMapping;
5620  }
5621  setup(builder) {
5622    const colorNode = this.colorNode || builder.context.color;
5623    const toneMapping3 = this._toneMapping;
5624    if (toneMapping3 === NoToneMapping) return colorNode;
5625    let outputNode = null;
5626    const toneMappingFn = builder.renderer.library.getToneMappingFunction(toneMapping3);
5627    if (toneMappingFn !== null) {
5628      outputNode = vec4(toneMappingFn(colorNode.rgb, this.exposureNode), colorNode.a);
5629    } else {
5630      error("ToneMappingNode: Unsupported Tone Mapping configuration.", toneMapping3);
5631      outputNode = colorNode;
5632    }
5633    return outputNode;
5634  }
5635};
5636var toneMapping = (mapping, exposure, color3) => new ToneMappingNode(mapping, nodeObject(exposure), nodeObject(color3));
5637var toneMappingExposure = /* @__PURE__ */ rendererReference("toneMappingExposure", "float");
5638addMethodChaining("toneMapping", (color3, mapping, exposure) => toneMapping(mapping, exposure, color3));
5639var _bufferLib = /* @__PURE__ */ new WeakMap();
5640function _getBufferAttribute(value, itemSize) {
5641  let buffer3 = _bufferLib.get(value);
5642  if (buffer3 === void 0) {
5643    buffer3 = new InterleavedBuffer(value, itemSize);
5644    _bufferLib.set(value, buffer3);
5645  }
5646  return buffer3;
5647}
5648var BufferAttributeNode = class extends InputNode {
5649  static get type() {
5650    return "BufferAttributeNode";
5651  }
5652  /**
5653   * Constructs a new buffer attribute node.
5654   *
5655   * @param {BufferAttribute|InterleavedBuffer|TypedArray} value - The attribute data.
5656   * @param {?string} [bufferType=null] - The buffer type (e.g. `'vec3'`).
5657   * @param {number} [bufferStride=0] - The buffer stride.
5658   * @param {number} [bufferOffset=0] - The buffer offset.
5659   */
5660  constructor(value, bufferType = null, bufferStride = 0, bufferOffset = 0) {
5661    super(value, bufferType);
5662    this.isBufferNode = true;
5663    this.bufferType = bufferType;
5664    this.bufferStride = bufferStride;
5665    this.bufferOffset = bufferOffset;
5666    this.usage = StaticDrawUsage;
5667    this.instanced = false;
5668    this.attribute = null;
5669    this.global = true;
5670    if (value && value.isBufferAttribute === true && value.itemSize <= 4) {
5671      this.attribute = value;
5672      this.usage = value.usage;
5673      this.instanced = value.isInstancedBufferAttribute;
5674    }
5675  }
5676  /**
5677   * This method is overwritten since the attribute data might be shared
5678   * and thus the hash should be shared as well.
5679   *
5680   * @param {NodeBuilder} builder - The current node builder.
5681   * @return {string} The hash.
5682   */
5683  getHash(builder) {
5684    let id;
5685    if (this.bufferStride === 0 && this.bufferOffset === 0) {
5686      let bufferData = builder.globalCache.getData(this.value);
5687      if (bufferData === void 0) {
5688        bufferData = {
5689          node: this
5690        };
5691        builder.globalCache.setData(this.value, bufferData);
5692      }
5693      id = bufferData.node.id;
5694    } else {
5695      id = this.id;
5696    }
5697    return String(id);
5698  }
5699  /**
5700   * This method is overwritten since the node type is inferred from
5701   * the buffer attribute.
5702   *
5703   * @param {NodeBuilder} builder - The current node builder.
5704   * @return {string} The node type.
5705   */
5706  generateNodeType(builder) {
5707    if (this.bufferType === null) {
5708      this.bufferType = builder.getTypeFromAttribute(this.attribute);
5709    }
5710    return this.bufferType;
5711  }
5712  /**
5713   * Depending on which value was passed to the node, `setup()` behaves
5714   * differently. If no instance of `BufferAttribute` was passed, the method
5715   * creates an internal attribute and configures it respectively.
5716   *
5717   * @param {NodeBuilder} builder - The current node builder.
5718   */
5719  setup(builder) {
5720    if (this.attribute !== null) return;
5721    const type = this.getNodeType(builder);
5722    const itemSize = builder.getTypeLength(type);
5723    const value = this.value;
5724    const stride = this.bufferStride || itemSize;
5725    const offset3 = this.bufferOffset;
5726    let buffer3;
5727    if (value.isInterleavedBuffer === true) {
5728      buffer3 = value;
5729    } else if (value.isBufferAttribute === true) {
5730      buffer3 = _getBufferAttribute(value.array, stride);
5731    } else {
5732      buffer3 = _getBufferAttribute(value, stride);
5733    }
5734    const bufferAttribute3 = new InterleavedBufferAttribute(buffer3, itemSize, offset3);
5735    buffer3.setUsage(this.usage);
5736    this.attribute = bufferAttribute3;
5737    this.attribute.isInstancedBufferAttribute = this.instanced;
5738  }
5739  /**
5740   * Generates the code snippet of the buffer attribute node.
5741   *
5742   * @param {NodeBuilder} builder - The current node builder.
5743   * @return {string} The generated code snippet.
5744   */
5745  generate(builder) {
5746    const nodeType = this.getNodeType(builder);
5747    const nodeAttribute = builder.getBufferAttributeFromNode(this, nodeType);
5748    const propertyName = builder.getPropertyName(nodeAttribute);
5749    let output3 = null;
5750    if (builder.shaderStage === "vertex" || builder.shaderStage === "compute") {
5751      this.name = propertyName;
5752      output3 = propertyName;
5753    } else {
5754      const nodeVarying = varying(this);
5755      output3 = nodeVarying.build(builder, nodeType);
5756    }
5757    return output3;
5758  }
5759  /**
5760   * Overwrites the default implementation to return a fixed value `'bufferAttribute'`.
5761   *
5762   * @param {NodeBuilder} builder - The current node builder.
5763   * @return {string} The input type.
5764   */
5765  getInputType() {
5766    return "bufferAttribute";
5767  }
5768  /**
5769   * Sets the `usage` property to the given value.
5770   *
5771   * @param {number} value - The usage to set.
5772   * @return {BufferAttributeNode} A reference to this node.
5773   */
5774  setUsage(value) {
5775    this.usage = value;
5776    if (this.attribute && this.attribute.isBufferAttribute === true) {
5777      this.attribute.usage = value;
5778    }
5779    return this;
5780  }
5781  /**
5782   * Sets the `instanced` property to the given value.
5783   *
5784   * @param {boolean} value - The value to set.
5785   * @return {BufferAttributeNode} A reference to this node.
5786   */
5787  setInstanced(value) {
5788    this.instanced = value;
5789    return this;
5790  }
5791};
5792function createBufferAttribute(array3, type = null, stride = 0, offset3 = 0, usage = StaticDrawUsage, instanced = false) {
5793  if (type === "mat3" || type === null && array3.itemSize === 9) {
5794    return mat3(
5795      new BufferAttributeNode(array3, "vec3", 9, 0).setUsage(usage).setInstanced(instanced),
5796      new BufferAttributeNode(array3, "vec3", 9, 3).setUsage(usage).setInstanced(instanced),
5797      new BufferAttributeNode(array3, "vec3", 9, 6).setUsage(usage).setInstanced(instanced)
5798    );
5799  } else if (type === "mat4" || type === null && array3.itemSize === 16) {
5800    return mat4(
5801      new BufferAttributeNode(array3, "vec4", 16, 0).setUsage(usage).setInstanced(instanced),
5802      new BufferAttributeNode(array3, "vec4", 16, 4).setUsage(usage).setInstanced(instanced),
5803      new BufferAttributeNode(array3, "vec4", 16, 8).setUsage(usage).setInstanced(instanced),
5804      new BufferAttributeNode(array3, "vec4", 16, 12).setUsage(usage).setInstanced(instanced)
5805    );
5806  }
5807  return new BufferAttributeNode(array3, type, stride, offset3).setUsage(usage);
5808}
5809var bufferAttribute = (array3, type = null, stride = 0, offset3 = 0) => createBufferAttribute(array3, type, stride, offset3);
5810var dynamicBufferAttribute = (array3, type = null, stride = 0, offset3 = 0) => createBufferAttribute(array3, type, stride, offset3, DynamicDrawUsage);
5811var instancedBufferAttribute = (array3, type = null, stride = 0, offset3 = 0) => createBufferAttribute(array3, type, stride, offset3, StaticDrawUsage, true);
5812var instancedDynamicBufferAttribute = (array3, type = null, stride = 0, offset3 = 0) => createBufferAttribute(array3, type, stride, offset3, DynamicDrawUsage, true);
5813addMethodChaining("toAttribute", (bufferNode) => bufferAttribute(bufferNode.value));
5814var IndexNode = class _IndexNode extends Node2 {
5815  static get type() {
5816    return "IndexNode";
5817  }
5818  /**
5819   * Constructs a new index node.
5820   *
5821   * @param {('vertex'|'instance'|'subgroup'|'invocationLocal'|'invocationGlobal'|'invocationSubgroup'|'draw')} scope - The scope of the index node.
5822   */
5823  constructor(scope) {
5824    super("uint");
5825    this.scope = scope;
5826    this.isIndexNode = true;
5827  }
5828  generate(builder) {
5829    const nodeType = this.getNodeType(builder);
5830    const scope = this.scope;
5831    let propertyName;
5832    if (scope === _IndexNode.VERTEX) {
5833      propertyName = builder.getVertexIndex();
5834    } else if (scope === _IndexNode.INSTANCE) {
5835      propertyName = builder.getInstanceIndex();
5836    } else if (scope === _IndexNode.DRAW) {
5837      propertyName = builder.getDrawIndex();
5838    } else if (scope === _IndexNode.INVOCATION_LOCAL) {
5839      propertyName = builder.getInvocationLocalIndex();
5840    } else if (scope === _IndexNode.INVOCATION_SUBGROUP) {
5841      propertyName = builder.getInvocationSubgroupIndex();
5842    } else if (scope === _IndexNode.SUBGROUP) {
5843      propertyName = builder.getSubgroupIndex();
5844    } else {
5845      throw new Error("THREE.IndexNode: Unknown scope: " + scope);
5846    }
5847    let output3;
5848    if (builder.shaderStage === "vertex" || builder.shaderStage === "compute") {
5849      output3 = propertyName;
5850    } else {
5851      const nodeVarying = varying(this);
5852      output3 = nodeVarying.build(builder, nodeType);
5853    }
5854    return output3;
5855  }
5856};
5857IndexNode.VERTEX = "vertex";
5858IndexNode.INSTANCE = "instance";
5859IndexNode.SUBGROUP = "subgroup";
5860IndexNode.INVOCATION_LOCAL = "invocationLocal";
5861IndexNode.INVOCATION_SUBGROUP = "invocationSubgroup";
5862IndexNode.DRAW = "draw";
5863var vertexIndex = /* @__PURE__ */ nodeImmutable(IndexNode, IndexNode.VERTEX);
5864var instanceIndex = /* @__PURE__ */ nodeImmutable(IndexNode, IndexNode.INSTANCE);
5865var subgroupIndex = /* @__PURE__ */ nodeImmutable(IndexNode, IndexNode.SUBGROUP);
5866var invocationSubgroupIndex = /* @__PURE__ */ nodeImmutable(IndexNode, IndexNode.INVOCATION_SUBGROUP);
5867var invocationLocalIndex = /* @__PURE__ */ nodeImmutable(IndexNode, IndexNode.INVOCATION_LOCAL);
5868var drawIndex = /* @__PURE__ */ nodeImmutable(IndexNode, IndexNode.DRAW);
5869var ComputeNode = class extends Node2 {
5870  static get type() {
5871    return "ComputeNode";
5872  }
5873  /**
5874   * Constructs a new compute node.
5875   *
5876   * @param {Node} computeNode - The node that defines the compute shader logic.
5877   * @param {Array<number>} workgroupSize - An array defining the X, Y, and Z dimensions of the workgroup for compute shader execution.
5878   */
5879  constructor(computeNode, workgroupSize) {
5880    super("void");
5881    this.isComputeNode = true;
5882    this.computeNode = computeNode;
5883    this.workgroupSize = workgroupSize;
5884    this.count = null;
5885    this.dispatchSize = null;
5886    this.version = 1;
5887    this.name = "";
5888    this.updateBeforeType = NodeUpdateType.OBJECT;
5889    this.onInitFunction = null;
5890    this.countNode = null;
5891  }
5892  /**
5893   * Executes the `dispose` event for this node.
5894   */
5895  dispose() {
5896    this.dispatchEvent({ type: "dispose" });
5897  }
5898  /**
5899   * Sets the {@link ComputeNode#name} property.
5900   *
5901   * @param {string} name - The name of the uniform.
5902   * @return {ComputeNode} A reference to this node.
5903   */
5904  setName(name) {
5905    this.name = name;
5906    return this;
5907  }
5908  /**
5909   * Sets the {@link ComputeNode#name} property.
5910   *
5911   * @deprecated
5912   * @param {string} name - The name of the uniform.
5913   * @return {ComputeNode} A reference to this node.
5914   */
5915  label(name) {
5916    warn('TSL: "label()" has been deprecated. Use "setName()" instead.', new StackTrace());
5917    return this.setName(name);
5918  }
5919  /**
5920   * Sets the callback to run during initialization.
5921   *
5922   * @param {Function} callback - The callback function.
5923   * @return {ComputeNode} A reference to this node.
5924   */
5925  onInit(callback) {
5926    this.onInitFunction = callback;
5927    return this;
5928  }
5929  /**
5930   * The method execute the compute for this node.
5931   *
5932   * @param {NodeFrame} frame - A reference to the current node frame.
5933   */
5934  updateBefore({ renderer }) {
5935    renderer.compute(this);
5936  }
5937  setup(builder) {
5938    if (this.count !== null && this.countNode === null) {
5939      this.countNode = uniform(this.count, "uint").onObjectUpdate(() => this.count);
5940    }
5941    const result = this.computeNode.build(builder);
5942    if (result) {
5943      const properties = builder.getNodeProperties(this);
5944      properties.outputComputeNode = result.outputNode;
5945      result.outputNode = null;
5946    }
5947    return result;
5948  }
5949  generate(builder, output3) {
5950    const { shaderStage } = builder;
5951    if (shaderStage === "compute") {
5952      const snippet = this.computeNode.build(builder, "void");
5953      if (snippet !== "") {
5954        builder.addLineFlowCode(snippet, this);
5955      }
5956      if (this.count !== null && builder.allowEarlyReturns === true) {
5957        const countSnippet = this.countNode.build(builder, "uint");
5958        const indexSnippet = instanceIndex.build(builder, "uint");
5959        builder.flow.code = `${builder.tab}if ( ${indexSnippet} >= ${countSnippet} ) { return; }
5960
5961${builder.flow.code}`;
5962      }
5963    } else {
5964      const properties = builder.getNodeProperties(this);
5965      const outputComputeNode = properties.outputComputeNode;
5966      if (outputComputeNode) {
5967        return outputComputeNode.build(builder, output3);
5968      }
5969    }
5970  }
5971};
5972var computeKernel = (node, workgroupSize = [64]) => {
5973  if (workgroupSize.length === 0 || workgroupSize.length > 3) {
5974    error("TSL: compute() workgroupSize must have 1, 2, or 3 elements", new StackTrace());
5975  }
5976  for (let i = 0; i < workgroupSize.length; i++) {
5977    const val = workgroupSize[i];
5978    if (typeof val !== "number" || val <= 0 || !Number.isInteger(val)) {
5979      error(`TSL: compute() workgroupSize element at index [ ${i} ] must be a positive integer`, new StackTrace());
5980    }
5981  }
5982  while (workgroupSize.length < 3) workgroupSize.push(1);
5983  return new ComputeNode(nodeObject(node), workgroupSize);
5984};
5985var compute = (node, count, workgroupSize) => {
5986  const computeNode = computeKernel(node, workgroupSize);
5987  if (typeof count === "number") {
5988    computeNode.count = count;
5989  } else {
5990    computeNode.dispatchSize = count;
5991  }
5992  return computeNode;
5993};
5994addMethodChaining("compute", compute);
5995addMethodChaining("computeKernel", computeKernel);
5996var IsolateNode = class extends Node2 {
5997  static get type() {
5998    return "IsolateNode";
5999  }
6000  /**
6001   * Constructs a new cache node.
6002   *
6003   * @param {Node} node - The node that should be cached.
6004   * @param {boolean} [parent=true] - Whether this node refers to a shared parent cache or not.
6005   */
6006  constructor(node, parent = true) {
6007    super();
6008    this.node = node;
6009    this.parent = parent;
6010    this.isIsolateNode = true;
6011  }
6012  generateNodeType(builder) {
6013    const previousCache = builder.getCache();
6014    const cache4 = builder.getCacheFromNode(this, this.parent);
6015    builder.setCache(cache4);
6016    const nodeType = this.node.getNodeType(builder);
6017    builder.setCache(previousCache);
6018    return nodeType;
6019  }
6020  build(builder, ...params) {
6021    const previousCache = builder.getCache();
6022    const cache4 = builder.getCacheFromNode(this, this.parent);
6023    builder.setCache(cache4);
6024    const data = this.node.build(builder, ...params);
6025    builder.setCache(previousCache);
6026    return data;
6027  }
6028  setParent(parent) {
6029    this.parent = parent;
6030    return this;
6031  }
6032  getParent() {
6033    return this.parent;
6034  }
6035};
6036var isolate = (node) => new IsolateNode(nodeObject(node));
6037function cache(node, parent = true) {
6038  warn('TSL: "cache()" has been deprecated. Use "isolate()" instead.');
6039  return isolate(node).setParent(parent);
6040}
6041addMethodChaining("cache", cache);
6042addMethodChaining("isolate", isolate);
6043var BypassNode = class extends Node2 {
6044  static get type() {
6045    return "BypassNode";
6046  }
6047  /**
6048   * Constructs a new bypass node.
6049   *
6050   * @param {Node} outputNode - The output node.
6051   * @param {Node} callNode - The call node.
6052   */
6053  constructor(outputNode, callNode) {
6054    super();
6055    this.isBypassNode = true;
6056    this.outputNode = outputNode;
6057    this.callNode = callNode;
6058  }
6059  generateNodeType(builder) {
6060    return this.outputNode.getNodeType(builder);
6061  }
6062  generate(builder) {
6063    const snippet = this.callNode.build(builder, "void");
6064    if (snippet !== "") {
6065      builder.addLineFlowCode(snippet, this);
6066    }
6067    return this.outputNode.build(builder);
6068  }
6069};
6070var bypass = /* @__PURE__ */ nodeProxy(BypassNode).setParameterLength(2);
6071addMethodChaining("bypass", bypass);
6072var remap = /* @__PURE__ */ Fn(([node, inLowNode, inHighNode, outLowNode = float(0), outHighNode = float(1), doClamp = bool(false)]) => {
6073  let t = node.sub(inLowNode).div(inHighNode.sub(inLowNode));
6074  if (defined(doClamp)) t = t.clamp();
6075  return t.mul(outHighNode.sub(outLowNode)).add(outLowNode);
6076});
6077function remapClamp(node, inLowNode, inHighNode, outLowNode = float(0), outHighNode = float(1)) {
6078  return remap(node, inLowNode, inHighNode, outLowNode, outHighNode, true);
6079}
6080addMethodChaining("remap", remap);
6081addMethodChaining("remapClamp", remapClamp);
6082var ExpressionNode = class extends Node2 {
6083  static get type() {
6084    return "ExpressionNode";
6085  }
6086  /**
6087   * Constructs a new expression node.
6088   *
6089   * @param {string} [snippet=''] - The native code snippet.
6090   * @param {string} [nodeType='void'] - The node type.
6091   */
6092  constructor(snippet = "", nodeType = "void") {
6093    super(nodeType);
6094    this.snippet = snippet;
6095  }
6096  generate(builder, output3) {
6097    const type = this.getNodeType(builder);
6098    const snippet = this.snippet;
6099    if (type === "void") {
6100      builder.addLineFlowCode(snippet, this);
6101    } else {
6102      return builder.format(snippet, type, output3);
6103    }
6104  }
6105};
6106var expression = /* @__PURE__ */ nodeProxy(ExpressionNode).setParameterLength(1, 2);
6107var Discard = (conditional) => (conditional ? select(conditional, expression("discard")) : expression("discard")).toStack();
6108var Return = () => expression("return").toStack();
6109addMethodChaining("discard", Discard);
6110var RenderOutputNode = class extends TempNode {
6111  static get type() {
6112    return "RenderOutputNode";
6113  }
6114  /**
6115   * Constructs a new render output node.
6116   *
6117   * @param {Node} colorNode - The color node to process.
6118   * @param {?number} toneMapping - The tone mapping type.
6119   * @param {?string} outputColorSpace - The output color space.
6120   */
6121  constructor(colorNode, toneMapping3, outputColorSpace) {
6122    super("vec4");
6123    this.colorNode = colorNode;
6124    this._toneMapping = toneMapping3;
6125    this.outputColorSpace = outputColorSpace;
6126    this.isRenderOutputNode = true;
6127  }
6128  /**
6129   * Sets the tone mapping type.
6130   *
6131   * @param {number} value - The tone mapping type.
6132   * @return {ToneMappingNode} A reference to this node.
6133   */
6134  setToneMapping(value) {
6135    this._toneMapping = value;
6136    return this;
6137  }
6138  /**
6139   * Gets the tone mapping type.
6140   *
6141   * @returns {number} The tone mapping type.
6142   */
6143  getToneMapping() {
6144    return this._toneMapping;
6145  }
6146  setup({ context: context3 }) {
6147    let outputNode = this.colorNode || context3.color;
6148    const toneMapping3 = (this._toneMapping !== null ? this._toneMapping : context3.toneMapping) || NoToneMapping;
6149    const outputColorSpace = (this.outputColorSpace !== null ? this.outputColorSpace : context3.outputColorSpace) || NoColorSpace;
6150    if (toneMapping3 !== NoToneMapping) {
6151      outputNode = outputNode.toneMapping(toneMapping3);
6152    }
6153    if (outputColorSpace !== NoColorSpace && outputColorSpace !== ColorManagement.workingColorSpace) {
6154      outputNode = outputNode.workingToColorSpace(outputColorSpace);
6155    }
6156    return outputNode;
6157  }
6158};
6159var renderOutput = (color3, toneMapping3 = null, outputColorSpace = null) => new RenderOutputNode(nodeObject(color3), toneMapping3, outputColorSpace);
6160addMethodChaining("renderOutput", renderOutput);
6161var DebugNode = class extends TempNode {
6162  static get type() {
6163    return "DebugNode";
6164  }
6165  constructor(node, callback = null) {
6166    super();
6167    this.node = node;
6168    this.callback = callback;
6169  }
6170  generateNodeType(builder) {
6171    return this.node.getNodeType(builder);
6172  }
6173  setup(builder) {
6174    return this.node.build(builder);
6175  }
6176  analyze(builder) {
6177    return this.node.build(builder);
6178  }
6179  generate(builder) {
6180    const callback = this.callback;
6181    const snippet = this.node.build(builder);
6182    if (callback !== null) {
6183      callback(builder, snippet);
6184    } else {
6185      const title = "--- TSL debug - " + builder.shaderStage + " shader ---";
6186      const border = "-".repeat(title.length);
6187      let code3 = "";
6188      code3 += "// #" + title + "#\n";
6189      code3 += builder.flow.code.replace(/^\t/mg, "") + "\n";
6190      code3 += "/* ... */ " + snippet + " /* ... */\n";
6191      code3 += "// #" + border + "#\n";
6192      log(code3);
6193    }
6194    return snippet;
6195  }
6196};
6197var debug = (node, callback = null) => new DebugNode(nodeObject(node), callback).toStack();
6198addMethodChaining("debug", debug);
6199var InspectorBase = class extends EventDispatcher {
6200  /**
6201   * Creates a new InspectorBase.
6202   */
6203  constructor() {
6204    super();
6205    this._renderer = null;
6206    this.currentFrame = null;
6207  }
6208  /**
6209   * Returns the node frame for the current renderer.
6210   *
6211   * @return {Object} The node frame.
6212   */
6213  get nodeFrame() {
6214    return this._renderer._nodes.nodeFrame;
6215  }
6216  /**
6217   * Sets the renderer for this inspector.
6218   *
6219   * @param {WebGLRenderer} renderer - The renderer to associate with this inspector.
6220   * @return {InspectorBase} This inspector instance.
6221   */
6222  setRenderer(renderer) {
6223    this._renderer = renderer;
6224    return this;
6225  }
6226  /**
6227   * Returns the renderer associated with this inspector.
6228   *
6229   * @return {WebGLRenderer} The associated renderer.
6230   */
6231  getRenderer() {
6232    return this._renderer;
6233  }
6234  /**
6235   * Initializes the inspector.
6236   */
6237  init() {
6238  }
6239  /**
6240   * Called when a frame begins.
6241   */
6242  begin() {
6243  }
6244  /**
6245   * Called when a frame ends.
6246   */
6247  finish() {
6248  }
6249  /**
6250   * Inspects a node.
6251   *
6252   * @param {Node} node - The node to inspect.
6253   */
6254  inspect() {
6255  }
6256  /**
6257   * When a compute operation is performed.
6258   *
6259   * @param {ComputeNode} computeNode - The compute node being executed.
6260   * @param {number|Array<number>} dispatchSizeOrCount - The dispatch size or count.
6261   */
6262  computeAsync() {
6263  }
6264  /**
6265   * Called when a compute operation begins.
6266   *
6267   * @param {string} uid - A unique identifier for the render context.
6268   * @param {ComputeNode} computeNode - The compute node being executed.
6269   */
6270  beginCompute() {
6271  }
6272  /**
6273   * Called when a compute operation ends.
6274   *
6275   * @param {string} uid - A unique identifier for the render context.
6276   * @param {ComputeNode} computeNode - The compute node being executed.
6277   */
6278  finishCompute() {
6279  }
6280  /**
6281   * Called when a render operation begins.
6282   *
6283   * @param {string} uid - A unique identifier for the render context.
6284   * @param {Scene} scene - The scene being rendered.
6285   * @param {Camera} camera - The camera being used for rendering.
6286   * @param {?WebGLRenderTarget} renderTarget - The render target, if any.
6287   */
6288  beginRender() {
6289  }
6290  /**
6291   * Called when an animation loop ends.
6292   *
6293   * @param {string} uid - A unique identifier for the render context.
6294   */
6295  finishRender() {
6296  }
6297  /**
6298   * Called when a texture copy operation is performed.
6299   *
6300   * @param {Texture} srcTexture - The source texture.
6301   * @param {Texture} dstTexture - The destination texture.
6302   */
6303  copyTextureToTexture() {
6304  }
6305  /**
6306   * Called when a framebuffer copy operation is performed.
6307   *
6308   * @param {Texture} framebufferTexture - The texture associated with the framebuffer.
6309   */
6310  copyFramebufferToTexture() {
6311  }
6312};
6313var InspectorNode = class extends Node2 {
6314  /**
6315   * Returns the type of the node.
6316   *
6317   * @returns {string}
6318   */
6319  static get type() {
6320    return "InspectorNode";
6321  }
6322  /**
6323   * Creates an InspectorNode.
6324   *
6325   * @param {Node} node - The node to inspect.
6326   * @param {string} [name=''] - Optional name for the inspector node.
6327   * @param {Function|null} [callback=null] - Optional callback to modify the node during setup.
6328   */
6329  constructor(node, name = "", callback = null) {
6330    super();
6331    this.node = node;
6332    this.name = name;
6333    this.callback = callback;
6334    this.updateType = NodeUpdateType.FRAME;
6335    this.isInspectorNode = true;
6336  }
6337  /**
6338   * Returns the name of the inspector node.
6339   *
6340   * @returns {string}
6341   */
6342  getName() {
6343    return this.name || this.node.name;
6344  }
6345  /**
6346   * Updates the inspector node, allowing inspection of the wrapped node.
6347   *
6348   * @param {NodeFrame} frame - A reference to the current node frame.
6349   */
6350  update(frame) {
6351    frame.renderer.inspector.inspect(this);
6352  }
6353  /**
6354   * Returns the type of the wrapped node.
6355   *
6356   * @param {NodeBuilder} builder - The node builder.
6357   * @returns {string}
6358   */
6359  generateNodeType(builder) {
6360    return this.node.getNodeType(builder);
6361  }
6362  /**
6363   * Sets up the inspector node.
6364   *
6365   * @param {NodeBuilder} builder - The node builder.
6366   * @returns {Node} The setup node.
6367   */
6368  setup(builder) {
6369    let node = this.node;
6370    if (builder.context.inspector === true && this.callback !== null) {
6371      node = this.callback(node);
6372    }
6373    if (builder.renderer.backend.isWebGPUBackend !== true && builder.renderer.inspector.constructor !== InspectorBase) {
6374      warnOnce('TSL: ".toInspector()" is only available with WebGPU.');
6375    }
6376    return node;
6377  }
6378};
6379function inspector(node, name = "", callback = null) {
6380  node = nodeObject(node);
6381  return node.before(new InspectorNode(node, name, callback));
6382}
6383addMethodChaining("toInspector", inspector);
6384function addNodeElement(name) {
6385  warn("TSL: AddNodeElement has been removed in favor of tree-shaking. Trying add", name);
6386}
6387var AttributeNode = class extends Node2 {
6388  static get type() {
6389    return "AttributeNode";
6390  }
6391  /**
6392   * Constructs a new attribute node.
6393   *
6394   * @param {string} attributeName - The name of the attribute.
6395   * @param {?string} nodeType - The node type.
6396   */
6397  constructor(attributeName, nodeType = null) {
6398    super(nodeType);
6399    this.global = true;
6400    this._attributeName = attributeName;
6401  }
6402  getHash(builder) {
6403    return this.getAttributeName(builder);
6404  }
6405  generateNodeType(builder) {
6406    let nodeType = this.nodeType;
6407    if (nodeType === null) {
6408      const attributeName = this.getAttributeName(builder);
6409      if (builder.hasGeometryAttribute(attributeName)) {
6410        const attribute3 = builder.geometry.getAttribute(attributeName);
6411        nodeType = builder.getTypeFromAttribute(attribute3);
6412      } else {
6413        nodeType = "float";
6414      }
6415    }
6416    return nodeType;
6417  }
6418  /**
6419   * Sets the attribute name to the given value. The method can be
6420   * overwritten in derived classes if the final name must be computed
6421   * analytically.
6422   *
6423   * @param {string} attributeName - The name of the attribute.
6424   * @return {AttributeNode} A reference to this node.
6425   */
6426  setAttributeName(attributeName) {
6427    this._attributeName = attributeName;
6428    return this;
6429  }
6430  /**
6431   * Returns the attribute name of this node. The method can be
6432   * overwritten in derived classes if the final name must be computed
6433   * analytically.
6434   *
6435   * @param {NodeBuilder} builder - The current node builder.
6436   * @return {string} The attribute name.
6437   */
6438  getAttributeName() {
6439    return this._attributeName;
6440  }
6441  generate(builder) {
6442    const attributeName = this.getAttributeName(builder);
6443    const nodeType = this.getNodeType(builder);
6444    const geometryAttribute = builder.hasGeometryAttribute(attributeName);
6445    if (geometryAttribute === true) {
6446      const attribute3 = builder.geometry.getAttribute(attributeName);
6447      const attributeType = builder.getTypeFromAttribute(attribute3);
6448      const nodeAttribute = builder.getAttribute(attributeName, attributeType);
6449      if (builder.shaderStage === "vertex") {
6450        return builder.format(nodeAttribute.name, attributeType, nodeType);
6451      } else {
6452        const nodeVarying = varying(this);
6453        return nodeVarying.build(builder, nodeType);
6454      }
6455    } else {
6456      warn(`AttributeNode: Vertex attribute "${attributeName}" not found on geometry.`);
6457      return builder.generateConst(nodeType);
6458    }
6459  }
6460  serialize(data) {
6461    super.serialize(data);
6462    data.global = this.global;
6463    data._attributeName = this._attributeName;
6464  }
6465  deserialize(data) {
6466    super.deserialize(data);
6467    this.global = data.global;
6468    this._attributeName = data._attributeName;
6469  }
6470};
6471var attribute = (name, nodeType = null) => new AttributeNode(name, nodeType);
6472var uv$1 = (index = 0) => attribute("uv" + (index > 0 ? index : ""), "vec2");
6473var TextureSizeNode = class extends Node2 {
6474  static get type() {
6475    return "TextureSizeNode";
6476  }
6477  /**
6478   * Constructs a new texture size node.
6479   *
6480   * @param {TextureNode} textureNode - A texture node which size should be retrieved.
6481   * @param {?Node<int>} [levelNode=null] - A level node which defines the requested mip.
6482   */
6483  constructor(textureNode, levelNode = null) {
6484    super("uvec2");
6485    this.isTextureSizeNode = true;
6486    this.textureNode = textureNode;
6487    this.levelNode = levelNode;
6488  }
6489  generate(builder, output3) {
6490    const textureProperty = this.textureNode.build(builder, "property");
6491    const level = this.levelNode === null ? "0" : this.levelNode.build(builder, "int");
6492    return builder.format(`${builder.getMethod("textureDimensions")}( ${textureProperty}, ${level} )`, this.getNodeType(builder), output3);
6493  }
6494};
6495var textureSize = /* @__PURE__ */ nodeProxy(TextureSizeNode).setParameterLength(1, 2);
6496var MaxMipLevelNode = class extends UniformNode {
6497  static get type() {
6498    return "MaxMipLevelNode";
6499  }
6500  /**
6501   * Constructs a new max mip level node.
6502   *
6503   * @param {TextureNode} textureNode - The texture node to compute the max mip level for.
6504   */
6505  constructor(textureNode) {
6506    super(0);
6507    this._textureNode = textureNode;
6508    this.updateType = NodeUpdateType.FRAME;
6509  }
6510  /**
6511   * The texture node to compute the max mip level for.
6512   *
6513   * @readonly
6514   * @type {TextureNode}
6515   */
6516  get textureNode() {
6517    return this._textureNode;
6518  }
6519  /**
6520   * The texture.
6521   *
6522   * @readonly
6523   * @type {Texture}
6524   */
6525  get texture() {
6526    return this._textureNode.value;
6527  }
6528  update() {
6529    const texture3 = this.texture;
6530    const images = texture3.images;
6531    const image = images && images.length > 0 ? images[0] && images[0].image || images[0] : texture3.image;
6532    if (image && image.width !== void 0) {
6533      const { width, height } = image;
6534      this.value = Math.log2(Math.max(width, height));
6535    }
6536  }
6537};
6538var maxMipLevel = /* @__PURE__ */ nodeProxy(MaxMipLevelNode).setParameterLength(1);
6539var NodeError = class extends Error {
6540  constructor(message, stackTrace = null) {
6541    super(message);
6542    this.name = "NodeError";
6543    this.stackTrace = stackTrace;
6544  }
6545};
6546var EmptyTexture$1 = /* @__PURE__ */ new Texture();
6547var TextureNode = class extends UniformNode {
6548  static get type() {
6549    return "TextureNode";
6550  }
6551  /**
6552   * Constructs a new texture node.
6553   *
6554   * @param {Texture} [value=EmptyTexture] - The texture.
6555   * @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
6556   * @param {?Node<int>} [levelNode=null] - The level node.
6557   * @param {?Node<float>} [biasNode=null] - The bias node.
6558   */
6559  constructor(value = EmptyTexture$1, uvNode = null, levelNode = null, biasNode = null) {
6560    super(value);
6561    this.isTextureNode = true;
6562    this.uvNode = uvNode;
6563    this.levelNode = levelNode;
6564    this.biasNode = biasNode;
6565    this.compareNode = null;
6566    this.depthNode = null;
6567    this.gradNode = null;
6568    this.offsetNode = null;
6569    this.sampler = true;
6570    this.updateMatrix = false;
6571    this.updateType = NodeUpdateType.NONE;
6572    this.referenceNode = null;
6573    this._value = value;
6574    this._matrixUniform = null;
6575    this._flipYUniform = null;
6576    this.setUpdateMatrix(uvNode === null);
6577  }
6578  set value(value) {
6579    if (this.referenceNode) {
6580      this.referenceNode.value = value;
6581    } else {
6582      this._value = value;
6583    }
6584  }
6585  /**
6586   * The texture value.
6587   *
6588   * @type {Texture}
6589   */
6590  get value() {
6591    return this.referenceNode ? this.referenceNode.value : this._value;
6592  }
6593  /**
6594   * Overwritten since the uniform hash is defined by the texture's UUID.
6595   *
6596   * @param {NodeBuilder} builder - The current node builder.
6597   * @return {string} The uniform hash.
6598   */
6599  getUniformHash() {
6600    return this.value.uuid;
6601  }
6602  /**
6603   * Overwritten since the node type is inferred from the texture type.
6604   *
6605   * @param {NodeBuilder} builder - The current node builder.
6606   * @return {string} The node type.
6607   */
6608  generateNodeType() {
6609    if (this.value.isDepthTexture === true) return "float";
6610    if (this.value.type === UnsignedIntType) {
6611      return "uvec4";
6612    } else if (this.value.type === IntType) {
6613      return "ivec4";
6614    }
6615    return "vec4";
6616  }
6617  /**
6618   * Overwrites the default implementation to return a fixed value `'texture'`.
6619   *
6620   * @param {NodeBuilder} builder - The current node builder.
6621   * @return {string} The input type.
6622   */
6623  getInputType() {
6624    return "texture";
6625  }
6626  /**
6627   * Returns a default uvs based on the current texture's channel.
6628   *
6629   * @return {AttributeNode<vec2>} The default uvs.
6630   */
6631  getDefaultUV() {
6632    return uv$1(this.value.channel);
6633  }
6634  /**
6635   * Overwritten to always return the texture reference of the node.
6636   *
6637   * @param {any} state - This method can be invocated in different contexts so `state` can refer to any object type.
6638   * @return {Texture} The texture reference.
6639   */
6640  updateReference() {
6641    return this.value;
6642  }
6643  /**
6644   * Transforms the given uv node with the texture transformation matrix.
6645   *
6646   * @param {Node} uvNode - The uv node to transform.
6647   * @return {Node} The transformed uv node.
6648   */
6649  getTransformedUV(uvNode) {
6650    if (this._matrixUniform === null) this._matrixUniform = uniform(this.value.matrix);
6651    return this._matrixUniform.mul(vec3(uvNode, 1)).xy;
6652  }
6653  /**
6654   * Defines whether the uv transformation matrix should automatically be updated or not.
6655   *
6656   * @param {boolean} value - The update toggle.
6657   * @return {TextureNode} A reference to this node.
6658   */
6659  setUpdateMatrix(value) {
6660    this.updateMatrix = value;
6661    return this;
6662  }
6663  /**
6664   * Setups the uv node. Depending on the backend as well as texture's image and type, it might be necessary
6665   * to modify the uv node for correct sampling.
6666   *
6667   * @param {NodeBuilder} builder - The current node builder.
6668   * @param {Node} uvNode - The uv node to setup.
6669   * @return {Node} The updated uv node.
6670   */
6671  setupUV(builder, uvNode) {
6672    if (builder.isFlipY()) {
6673      if (this._flipYUniform === null) this._flipYUniform = uniform(false);
6674      uvNode = uvNode.toVar();
6675      if (this.sampler) {
6676        uvNode = this._flipYUniform.select(uvNode.flipY(), uvNode);
6677      } else {
6678        uvNode = this._flipYUniform.select(uvNode.setY(int(textureSize(this, this.levelNode).y).sub(uvNode.y).sub(1)), uvNode);
6679      }
6680    }
6681    return uvNode;
6682  }
6683  /**
6684   * Setups texture node by preparing the internal nodes for code generation.
6685   *
6686   * @param {NodeBuilder} builder - The current node builder.
6687   */
6688  setup(builder) {
6689    const properties = builder.getNodeProperties(this);
6690    properties.referenceNode = this.referenceNode;
6691    const texture3 = this.value;
6692    if (!texture3 || texture3.isTexture !== true) {
6693      throw new NodeError("THREE.TSL: `texture( value )` function expects a valid instance of THREE.Texture().", this.stackTrace);
6694    }
6695    const uvNode = Fn(() => {
6696      let uvNode2 = this.uvNode;
6697      if ((uvNode2 === null || builder.context.forceUVContext === true) && builder.context.getUV) {
6698        uvNode2 = builder.context.getUV(this, builder);
6699      }
6700      if (!uvNode2) uvNode2 = this.getDefaultUV();
6701      if (this.updateMatrix === true) {
6702        uvNode2 = this.getTransformedUV(uvNode2);
6703      }
6704      uvNode2 = this.setupUV(builder, uvNode2);
6705      this.updateType = this._matrixUniform !== null || this._flipYUniform !== null ? NodeUpdateType.OBJECT : NodeUpdateType.NONE;
6706      return uvNode2;
6707    })();
6708    let levelNode = this.levelNode;
6709    if (levelNode === null && builder.context.getTextureLevel) {
6710      levelNode = builder.context.getTextureLevel(this);
6711    }
6712    let compareNode = null;
6713    let compareStepNode = null;
6714    if (this.compareNode !== null) {
6715      if (builder.renderer.hasCompatibility(Compatibility.TEXTURE_COMPARE)) {
6716        compareNode = this.compareNode;
6717      } else {
6718        const compareFunction = texture3.compareFunction;
6719        if (compareFunction === null || compareFunction === LessCompare || compareFunction === LessEqualCompare || compareFunction === GreaterCompare || compareFunction === GreaterEqualCompare) {
6720          compareStepNode = this.compareNode;
6721        } else {
6722          compareNode = this.compareNode;
6723          warnOnce('TSL: Only "LessCompare", "LessEqualCompare", "GreaterCompare" and "GreaterEqualCompare" are supported for depth texture comparison fallback.');
6724        }
6725      }
6726    }
6727    properties.uvNode = uvNode;
6728    properties.levelNode = levelNode;
6729    properties.biasNode = this.biasNode;
6730    properties.compareNode = compareNode;
6731    properties.compareStepNode = compareStepNode;
6732    properties.gradNode = this.gradNode;
6733    properties.depthNode = this.depthNode;
6734    properties.offsetNode = this.offsetNode;
6735  }
6736  /**
6737   * Generates the uv code snippet.
6738   *
6739   * @param {NodeBuilder} builder - The current node builder.
6740   * @param {Node} uvNode - The uv node to generate code for.
6741   * @return {string} The generated code snippet.
6742   */
6743  generateUV(builder, uvNode) {
6744    return uvNode.build(builder, this.sampler === true ? "vec2" : "ivec2");
6745  }
6746  /**
6747   * Generates the offset code snippet.
6748   *
6749   * @param {NodeBuilder} builder - The current node builder.
6750   * @param {Node} offsetNode - The offset node to generate code for.
6751   * @return {string} The generated code snippet.
6752   */
6753  generateOffset(builder, offsetNode) {
6754    return offsetNode.build(builder, "ivec2");
6755  }
6756  /**
6757   * Generates the snippet for the texture sampling.
6758   *
6759   * @param {NodeBuilder} builder - The current node builder.
6760   * @param {string} textureProperty - The texture property.
6761   * @param {string} uvSnippet - The uv snippet.
6762   * @param {?string} levelSnippet - The level snippet.
6763   * @param {?string} biasSnippet - The bias snippet.
6764   * @param {?string} depthSnippet - The depth snippet.
6765   * @param {?string} compareSnippet - The compare snippet.
6766   * @param {?Array<string>} gradSnippet - The grad snippet.
6767   * @param {?string} offsetSnippet - The offset snippet.
6768   * @return {string} The generated code snippet.
6769   */
6770  generateSnippet(builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet, offsetSnippet) {
6771    const texture3 = this.value;
6772    let snippet;
6773    if (biasSnippet) {
6774      snippet = builder.generateTextureBias(texture3, textureProperty, uvSnippet, biasSnippet, depthSnippet, offsetSnippet);
6775    } else if (gradSnippet) {
6776      snippet = builder.generateTextureGrad(texture3, textureProperty, uvSnippet, gradSnippet, depthSnippet, offsetSnippet);
6777    } else if (compareSnippet) {
6778      snippet = builder.generateTextureCompare(texture3, textureProperty, uvSnippet, compareSnippet, depthSnippet, offsetSnippet);
6779    } else if (this.sampler === false) {
6780      snippet = builder.generateTextureLoad(texture3, textureProperty, uvSnippet, levelSnippet, depthSnippet, offsetSnippet);
6781    } else if (levelSnippet) {
6782      snippet = builder.generateTextureLevel(texture3, textureProperty, uvSnippet, levelSnippet, depthSnippet, offsetSnippet);
6783    } else {
6784      snippet = builder.generateTexture(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet);
6785    }
6786    return snippet;
6787  }
6788  /**
6789   * Generates the code snippet of the texture node.
6790   *
6791   * @param {NodeBuilder} builder - The current node builder.
6792   * @param {string} output - The current output.
6793   * @return {string} The generated code snippet.
6794   */
6795  generate(builder, output3) {
6796    const texture3 = this.value;
6797    const properties = builder.getNodeProperties(this);
6798    const textureProperty = super.generate(builder, "property");
6799    if (/^sampler/.test(output3)) {
6800      return textureProperty + "_sampler";
6801    } else if (builder.isReference(output3)) {
6802      return textureProperty;
6803    } else {
6804      const nodeData = builder.getDataFromNode(this);
6805      const nodeType = this.getNodeType(builder);
6806      let propertyName = nodeData.propertyName;
6807      if (propertyName === void 0) {
6808        const { uvNode, levelNode, biasNode, compareNode, compareStepNode, depthNode, gradNode, offsetNode } = properties;
6809        const uvSnippet = this.generateUV(builder, uvNode);
6810        const levelSnippet = levelNode ? levelNode.build(builder, "float") : null;
6811        const biasSnippet = biasNode ? biasNode.build(builder, "float") : null;
6812        const depthSnippet = depthNode ? depthNode.build(builder, "int") : null;
6813        const compareSnippet = compareNode ? compareNode.build(builder, "float") : null;
6814        const compareStepSnippet = compareStepNode ? compareStepNode.build(builder, "float") : null;
6815        const gradSnippet = gradNode ? [gradNode[0].build(builder, "vec2"), gradNode[1].build(builder, "vec2")] : null;
6816        const offsetSnippet = offsetNode ? this.generateOffset(builder, offsetNode) : null;
6817        let finalDepthSnippet = depthSnippet;
6818        if (finalDepthSnippet === null && texture3.isArrayTexture && this.isTexture3DNode !== true) {
6819          finalDepthSnippet = "0";
6820        }
6821        const nodeVar = builder.getVarFromNode(this);
6822        propertyName = builder.getPropertyName(nodeVar);
6823        let snippet2 = this.generateSnippet(builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, finalDepthSnippet, compareSnippet, gradSnippet, offsetSnippet);
6824        if (compareStepSnippet !== null) {
6825          const compareFunction = texture3.compareFunction;
6826          if (compareFunction === GreaterCompare || compareFunction === GreaterEqualCompare) {
6827            snippet2 = step(expression(snippet2, nodeType), expression(compareStepSnippet, "float")).build(builder, nodeType);
6828          } else {
6829            snippet2 = step(expression(compareStepSnippet, "float"), expression(snippet2, nodeType)).build(builder, nodeType);
6830          }
6831        }
6832        builder.addLineFlowCode(`${propertyName} = ${snippet2}`, this);
6833        nodeData.snippet = snippet2;
6834        nodeData.propertyName = propertyName;
6835      }
6836      let snippet = propertyName;
6837      if (builder.needsToWorkingColorSpace(texture3)) {
6838        snippet = colorSpaceToWorking(expression(snippet, nodeType), texture3.colorSpace).setup(builder).build(builder, nodeType);
6839      }
6840      return builder.format(snippet, nodeType, output3);
6841    }
6842  }
6843  /**
6844   * Sets the sampler value.
6845   *
6846   * @param {boolean} value - The sampler value to set.
6847   * @return {TextureNode} A reference to this texture node.
6848   */
6849  setSampler(value) {
6850    this.sampler = value;
6851    return this;
6852  }
6853  /**
6854   * Returns the sampler value.
6855   *
6856   * @return {boolean} The sampler value.
6857   */
6858  getSampler() {
6859    return this.sampler;
6860  }
6861  // @TODO: Move to TSL
6862  /**
6863   * Samples the texture with the given uv node.
6864   *
6865   * @param {Node} uvNode - The uv node.
6866   * @return {TextureNode} A texture node representing the texture sample.
6867   */
6868  sample(uvNode) {
6869    const textureNode = this.clone();
6870    textureNode.uvNode = nodeObject(uvNode);
6871    textureNode.referenceNode = this.getBase();
6872    return nodeObject(textureNode);
6873  }
6874  /**
6875   * TSL function for creating a texture node that fetches/loads texels without interpolation.
6876   *
6877   * @param {Node<uvec2>} uvNode - The uv node.
6878   * @returns {TextureNode} A texture node representing the texture load.
6879   */
6880  load(uvNode) {
6881    return this.sample(uvNode).setSampler(false);
6882  }
6883  /**
6884   * Samples a blurred version of the texture by defining an internal bias.
6885   *
6886   * @param {Node<float>} amountNode - How blurred the texture should be.
6887   * @return {TextureNode} A texture node representing the texture sample.
6888   */
6889  blur(amountNode) {
6890    const textureNode = this.clone();
6891    textureNode.biasNode = nodeObject(amountNode).mul(maxMipLevel(textureNode));
6892    textureNode.referenceNode = this.getBase();
6893    const map = textureNode.value;
6894    if (textureNode.generateMipmaps === false && (map && map.generateMipmaps === false || map.minFilter === NearestFilter || map.magFilter === NearestFilter)) {
6895      warn("TSL: texture().blur() requires mipmaps and sampling. Use .generateMipmaps=true and .minFilter/.magFilter=THREE.LinearFilter in the Texture.");
6896      textureNode.biasNode = null;
6897    }
6898    return nodeObject(textureNode);
6899  }
6900  /**
6901   * Samples a specific mip of the texture.
6902   *
6903   * @param {Node<int>} levelNode - The mip level to sample.
6904   * @return {TextureNode} A texture node representing the texture sample.
6905   */
6906  level(levelNode) {
6907    const textureNode = this.clone();
6908    textureNode.levelNode = nodeObject(levelNode);
6909    textureNode.referenceNode = this.getBase();
6910    return nodeObject(textureNode);
6911  }
6912  /**
6913   * Returns the texture size of the requested level.
6914   *
6915   * @param {Node<int>} levelNode - The level to compute the size for.
6916   * @return {TextureSizeNode} The texture size.
6917   */
6918  size(levelNode) {
6919    return textureSize(this, levelNode);
6920  }
6921  /**
6922   * Samples the texture with the given bias.
6923   *
6924   * @param {Node<float>} biasNode - The bias node.
6925   * @return {TextureNode} A texture node representing the texture sample.
6926   */
6927  bias(biasNode) {
6928    const textureNode = this.clone();
6929    textureNode.biasNode = nodeObject(biasNode);
6930    textureNode.referenceNode = this.getBase();
6931    return nodeObject(textureNode);
6932  }
6933  /**
6934   * Returns the base texture of this node.
6935   * @return {TextureNode} The base texture node.
6936   */
6937  getBase() {
6938    return this.referenceNode ? this.referenceNode.getBase() : this;
6939  }
6940  /**
6941   * Samples the texture by executing a compare operation.
6942   *
6943   * @param {Node<float>} compareNode - The node that defines the compare value.
6944   * @return {TextureNode} A texture node representing the texture sample.
6945   */
6946  compare(compareNode) {
6947    const textureNode = this.clone();
6948    textureNode.compareNode = nodeObject(compareNode);
6949    textureNode.referenceNode = this.getBase();
6950    return nodeObject(textureNode);
6951  }
6952  /**
6953   * Samples the texture using an explicit gradient.
6954   *
6955   * @param {Node<vec2>} gradNodeX - The gradX node.
6956   * @param {Node<vec2>} gradNodeY - The gradY node.
6957   * @return {TextureNode} A texture node representing the texture sample.
6958   */
6959  grad(gradNodeX, gradNodeY) {
6960    const textureNode = this.clone();
6961    textureNode.gradNode = [nodeObject(gradNodeX), nodeObject(gradNodeY)];
6962    textureNode.referenceNode = this.getBase();
6963    return nodeObject(textureNode);
6964  }
6965  /**
6966   * Samples the texture by defining a depth node.
6967   *
6968   * @param {Node<int>} depthNode - The depth node.
6969   * @return {TextureNode} A texture node representing the texture sample.
6970   */
6971  depth(depthNode) {
6972    const textureNode = this.clone();
6973    textureNode.depthNode = nodeObject(depthNode);
6974    textureNode.referenceNode = this.getBase();
6975    return nodeObject(textureNode);
6976  }
6977  /**
6978   * Samples the texture by defining an offset node.
6979   *
6980   * @param {Node<ivec2>} offsetNode - The offset node.
6981   * @return {TextureNode} A texture node representing the texture sample.
6982   */
6983  offset(offsetNode) {
6984    const textureNode = this.clone();
6985    textureNode.offsetNode = nodeObject(offsetNode);
6986    textureNode.referenceNode = this.getBase();
6987    return nodeObject(textureNode);
6988  }
6989  // --
6990  serialize(data) {
6991    super.serialize(data);
6992    data.value = this.value.toJSON(data.meta).uuid;
6993    data.sampler = this.sampler;
6994    data.updateMatrix = this.updateMatrix;
6995    data.updateType = this.updateType;
6996  }
6997  deserialize(data) {
6998    super.deserialize(data);
6999    this.value = data.meta.textures[data.value];
7000    this.sampler = data.sampler;
7001    this.updateMatrix = data.updateMatrix;
7002    this.updateType = data.updateType;
7003  }
7004  /**
7005   * The update is used to implement the update of the uv transformation matrix.
7006   */
7007  update() {
7008    const texture3 = this.value;
7009    const matrixUniform = this._matrixUniform;
7010    if (matrixUniform !== null) matrixUniform.value = texture3.matrix;
7011    if (texture3.matrixAutoUpdate === true) {
7012      texture3.updateMatrix();
7013    }
7014    const flipYUniform = this._flipYUniform;
7015    if (flipYUniform !== null) {
7016      flipYUniform.value = texture3.image instanceof ImageBitmap && texture3.flipY === true || texture3.isRenderTargetTexture === true || texture3.isFramebufferTexture === true || texture3.isDepthTexture === true;
7017    }
7018  }
7019  /**
7020   * Clones the texture node.
7021   *
7022   * @return {TextureNode} The cloned texture node.
7023   */
7024  clone() {
7025    const newNode = new this.constructor(this.value, this.uvNode, this.levelNode, this.biasNode);
7026    newNode.sampler = this.sampler;
7027    newNode.depthNode = this.depthNode;
7028    newNode.compareNode = this.compareNode;
7029    newNode.gradNode = this.gradNode;
7030    newNode.offsetNode = this.offsetNode;
7031    return newNode;
7032  }
7033};
7034var textureBase = /* @__PURE__ */ nodeProxy(TextureNode).setParameterLength(1, 4).setName("texture");
7035var texture = (value = EmptyTexture$1, uvNode = null, levelNode = null, biasNode = null) => {
7036  let textureNode;
7037  if (value && value.isTextureNode === true) {
7038    textureNode = nodeObject(value.clone());
7039    textureNode.referenceNode = value.getBase();
7040    if (uvNode !== null) textureNode.uvNode = nodeObject(uvNode);
7041    if (levelNode !== null) textureNode.levelNode = nodeObject(levelNode);
7042    if (biasNode !== null) textureNode.biasNode = nodeObject(biasNode);
7043  } else {
7044    textureNode = textureBase(value, uvNode, levelNode, biasNode);
7045  }
7046  return textureNode;
7047};
7048var uniformTexture = (value = EmptyTexture$1) => texture(value);
7049var textureLoad = (...params) => texture(...params).setSampler(false);
7050var textureLevel = (value, uv3, level) => texture(value, uv3).level(level);
7051var sampler = (value) => (value.isNode === true ? value : texture(value)).convert("sampler");
7052var samplerComparison = (value) => (value.isNode === true ? value : texture(value)).convert("samplerComparison");
7053var BufferNode = class extends UniformNode {
7054  static get type() {
7055    return "BufferNode";
7056  }
7057  /**
7058   * Constructs a new buffer node.
7059   *
7060   * @param {Array<number>} value - Array-like buffer data.
7061   * @param {string} bufferType - The data type of the buffer.
7062   * @param {number} [bufferCount=0] - The count of buffer elements.
7063   */
7064  constructor(value, bufferType, bufferCount = 0) {
7065    super(value, bufferType);
7066    this.isBufferNode = true;
7067    this.bufferType = bufferType;
7068    this.bufferCount = bufferCount;
7069    this.updateRanges = [];
7070  }
7071  /**
7072   * Adds a range of data in the data array to be updated on the GPU.
7073   *
7074   * @param {number} start - Position at which to start update.
7075   * @param {number} count - The number of components to update.
7076   */
7077  addUpdateRange(start, count) {
7078    this.updateRanges.push({ start, count });
7079  }
7080  /**
7081   * Clears the update ranges.
7082   */
7083  clearUpdateRanges() {
7084    this.updateRanges.length = 0;
7085  }
7086  /**
7087   * The data type of the buffer elements.
7088   *
7089   * @param {NodeBuilder} builder - The current node builder.
7090   * @return {string} The element type.
7091   */
7092  getElementType(builder) {
7093    return this.getNodeType(builder);
7094  }
7095  /**
7096   * Overwrites the default implementation to return a fixed value `'buffer'`.
7097   *
7098   * @param {NodeBuilder} builder - The current node builder.
7099   * @return {string} The input type.
7100   */
7101  getInputType() {
7102    return "buffer";
7103  }
7104};
7105var buffer = (value, type, count) => new BufferNode(value, type, count);
7106var UniformArrayElementNode = class extends ArrayElementNode {
7107  static get type() {
7108    return "UniformArrayElementNode";
7109  }
7110  /**
7111   * Constructs a new buffer node.
7112   *
7113   * @param {UniformArrayNode} uniformArrayNode - The uniform array node to access.
7114   * @param {IndexNode} indexNode - The index data that define the position of the accessed element in the array.
7115   */
7116  constructor(uniformArrayNode, indexNode) {
7117    super(uniformArrayNode, indexNode);
7118    this.isArrayBufferElementNode = true;
7119  }
7120  generate(builder) {
7121    const snippet = super.generate(builder);
7122    const type = this.getNodeType(builder);
7123    const paddedType = this.node.getPaddedType();
7124    return builder.format(snippet, paddedType, type);
7125  }
7126};
7127var UniformArrayNode = class extends BufferNode {
7128  static get type() {
7129    return "UniformArrayNode";
7130  }
7131  /**
7132   * Constructs a new uniform array node.
7133   *
7134   * @param {Array<any>} value - Array holding the buffer data.
7135   * @param {?string} [elementType=null] - The data type of a buffer element.
7136   */
7137  constructor(value, elementType = null) {
7138    super(null);
7139    this.array = value;
7140    this.elementType = elementType === null ? getValueType(value[0]) : elementType;
7141    this.paddedType = this.getPaddedType();
7142    this.updateType = NodeUpdateType.RENDER;
7143    this.isArrayBufferNode = true;
7144  }
7145  /**
7146   * This method is overwritten since the node type is inferred from the
7147   * {@link UniformArrayNode#paddedType}.
7148   *
7149   * @param {NodeBuilder} builder - The current node builder.
7150   * @return {string} The node type.
7151   */
7152  generateNodeType() {
7153    return this.paddedType;
7154  }
7155  /**
7156   * The data type of the array elements.
7157   *
7158   * @param {NodeBuilder} builder - The current node builder.
7159   * @return {string} The element type.
7160   */
7161  getElementType() {
7162    return this.elementType;
7163  }
7164  /**
7165   * Returns the padded type based on the element type.
7166   *
7167   * @return {string} The padded type.
7168   */
7169  getPaddedType() {
7170    const elementType = this.elementType;
7171    let paddedType = "vec4";
7172    if (elementType === "mat2") {
7173      paddedType = "mat2";
7174    } else if (/mat/.test(elementType) === true) {
7175      paddedType = "mat4";
7176    } else if (elementType.charAt(0) === "i") {
7177      paddedType = "ivec4";
7178    } else if (elementType.charAt(0) === "u") {
7179      paddedType = "uvec4";
7180    }
7181    return paddedType;
7182  }
7183  /**
7184   * The update makes sure to correctly transfer the data from the (complex) objects
7185   * in the array to the internal, correctly padded value buffer.
7186   *
7187   * @param {NodeFrame} frame - A reference to the current node frame.
7188   */
7189  update() {
7190    const { array: array3, value } = this;
7191    const elementType = this.elementType;
7192    if (elementType === "float" || elementType === "int" || elementType === "uint") {
7193      for (let i = 0; i < array3.length; i++) {
7194        const index = i * 4;
7195        value[index] = array3[i];
7196      }
7197    } else if (elementType === "color") {
7198      for (let i = 0; i < array3.length; i++) {
7199        const index = i * 4;
7200        const vector = array3[i];
7201        value[index] = vector.r;
7202        value[index + 1] = vector.g;
7203        value[index + 2] = vector.b || 0;
7204      }
7205    } else if (elementType === "mat2") {
7206      for (let i = 0; i < array3.length; i++) {
7207        const index = i * 4;
7208        const matrix = array3[i];
7209        value[index] = matrix.elements[0];
7210        value[index + 1] = matrix.elements[1];
7211        value[index + 2] = matrix.elements[2];
7212        value[index + 3] = matrix.elements[3];
7213      }
7214    } else if (elementType === "mat3") {
7215      for (let i = 0; i < array3.length; i++) {
7216        const index = i * 16;
7217        const matrix = array3[i];
7218        value[index] = matrix.elements[0];
7219        value[index + 1] = matrix.elements[1];
7220        value[index + 2] = matrix.elements[2];
7221        value[index + 4] = matrix.elements[3];
7222        value[index + 5] = matrix.elements[4];
7223        value[index + 6] = matrix.elements[5];
7224        value[index + 8] = matrix.elements[6];
7225        value[index + 9] = matrix.elements[7];
7226        value[index + 10] = matrix.elements[8];
7227        value[index + 15] = 1;
7228      }
7229    } else if (elementType === "mat4") {
7230      for (let i = 0; i < array3.length; i++) {
7231        const index = i * 16;
7232        const matrix = array3[i];
7233        for (let i2 = 0; i2 < matrix.elements.length; i2++) {
7234          value[index + i2] = matrix.elements[i2];
7235        }
7236      }
7237    } else {
7238      for (let i = 0; i < array3.length; i++) {
7239        const index = i * 4;
7240        const vector = array3[i];
7241        value[index] = vector.x;
7242        value[index + 1] = vector.y;
7243        value[index + 2] = vector.z || 0;
7244        value[index + 3] = vector.w || 0;
7245      }
7246    }
7247  }
7248  /**
7249   * Implement the value buffer creation based on the array data.
7250   *
7251   * @param {NodeBuilder} builder - A reference to the current node builder.
7252   * @return {null}
7253   */
7254  setup(builder) {
7255    const length3 = this.array.length;
7256    const elementType = this.elementType;
7257    let arrayType = Float32Array;
7258    const paddedType = this.paddedType;
7259    const paddedElementLength = builder.getTypeLength(paddedType);
7260    if (elementType.charAt(0) === "i") arrayType = Int32Array;
7261    if (elementType.charAt(0) === "u") arrayType = Uint32Array;
7262    this.value = new arrayType(length3 * paddedElementLength);
7263    this.bufferCount = length3;
7264    this.bufferType = paddedType;
7265    this.update();
7266    return super.setup(builder);
7267  }
7268  /**
7269   * Overwrites the default `element()` method to provide element access
7270   * based on {@link UniformArrayNode}.
7271   *
7272   * @param {IndexNode} indexNode - The index node.
7273   * @return {UniformArrayElementNode}
7274   */
7275  element(indexNode) {
7276    return new UniformArrayElementNode(this, nodeObject(indexNode));
7277  }
7278};
7279var uniformArray = (values, nodeType) => new UniformArrayNode(values, nodeType);
7280var BuiltinNode = class extends Node2 {
7281  /**
7282   * Constructs a new builtin node.
7283   *
7284   * @param {string} name - The name of the built-in shader variable.
7285   */
7286  constructor(name) {
7287    super("float");
7288    this.name = name;
7289    this.isBuiltinNode = true;
7290  }
7291  /**
7292   * Generates the code snippet of the builtin node.
7293   *
7294   * @param {NodeBuilder} builder - The current node builder.
7295   * @return {string} The generated code snippet.
7296   */
7297  generate() {
7298    return this.name;
7299  }
7300};
7301var builtin = nodeProxy(BuiltinNode).setParameterLength(1);
7302var _screenSizeVec;
7303var _viewportVec;
7304var ScreenNode = class _ScreenNode extends Node2 {
7305  static get type() {
7306    return "ScreenNode";
7307  }
7308  /**
7309   * Constructs a new screen node.
7310   *
7311   * @param {('coordinate'|'viewport'|'size'|'uv'|'dpr')} scope - The node's scope.
7312   */
7313  constructor(scope) {
7314    super();
7315    this.scope = scope;
7316    this._output = null;
7317    this.isViewportNode = true;
7318  }
7319  /**
7320   * This method is overwritten since the node type depends on the selected scope.
7321   *
7322   * @return {('float'|'vec2'|'vec4')} The node type.
7323   */
7324  generateNodeType() {
7325    if (this.scope === _ScreenNode.DPR) return "float";
7326    if (this.scope === _ScreenNode.VIEWPORT) return "vec4";
7327    else return "vec2";
7328  }
7329  /**
7330   * This method is overwritten since the node's update type depends on the selected scope.
7331   *
7332   * @return {NodeUpdateType} The update type.
7333   */
7334  getUpdateType() {
7335    let updateType = NodeUpdateType.NONE;
7336    if (this.scope === _ScreenNode.SIZE || this.scope === _ScreenNode.VIEWPORT || this.scope === _ScreenNode.DPR) {
7337      updateType = NodeUpdateType.RENDER;
7338    }
7339    this.updateType = updateType;
7340    return updateType;
7341  }
7342  /**
7343   * `ScreenNode` implements {@link Node#update} to retrieve viewport and size information
7344   * from the current renderer.
7345   *
7346   * @param {NodeFrame} frame - A reference to the current node frame.
7347   */
7348  update({ renderer }) {
7349    const renderTarget = renderer.getRenderTarget();
7350    if (this.scope === _ScreenNode.VIEWPORT) {
7351      if (renderTarget !== null) {
7352        _viewportVec.copy(renderTarget.viewport);
7353      } else {
7354        renderer.getViewport(_viewportVec);
7355        _viewportVec.multiplyScalar(renderer.getPixelRatio());
7356      }
7357    } else if (this.scope === _ScreenNode.DPR) {
7358      this._output.value = renderer.getPixelRatio();
7359    } else {
7360      if (renderTarget !== null) {
7361        _screenSizeVec.width = renderTarget.width;
7362        _screenSizeVec.height = renderTarget.height;
7363      } else {
7364        renderer.getDrawingBufferSize(_screenSizeVec);
7365      }
7366    }
7367  }
7368  setup() {
7369    const scope = this.scope;
7370    let output3 = null;
7371    if (scope === _ScreenNode.SIZE) {
7372      output3 = uniform(_screenSizeVec || (_screenSizeVec = new Vector2()));
7373    } else if (scope === _ScreenNode.VIEWPORT) {
7374      output3 = uniform(_viewportVec || (_viewportVec = new Vector4()));
7375    } else if (scope === _ScreenNode.DPR) {
7376      output3 = uniform(1);
7377    } else {
7378      output3 = vec2(screenCoordinate.div(screenSize));
7379    }
7380    this._output = output3;
7381    return output3;
7382  }
7383  generate(builder) {
7384    if (this.scope === _ScreenNode.COORDINATE) {
7385      let coord = builder.getFragCoord();
7386      if (builder.isFlipY()) {
7387        const size3 = builder.getNodeProperties(screenSize).outputNode.build(builder);
7388        coord = `${builder.getType("vec2")}( ${coord}.x, ${size3}.y - ${coord}.y )`;
7389      }
7390      return coord;
7391    }
7392    return super.generate(builder);
7393  }
7394};
7395ScreenNode.COORDINATE = "coordinate";
7396ScreenNode.VIEWPORT = "viewport";
7397ScreenNode.SIZE = "size";
7398ScreenNode.UV = "uv";
7399ScreenNode.DPR = "dpr";
7400var screenDPR = /* @__PURE__ */ nodeImmutable(ScreenNode, ScreenNode.DPR);
7401var screenUV = /* @__PURE__ */ nodeImmutable(ScreenNode, ScreenNode.UV);
7402var screenSize = /* @__PURE__ */ nodeImmutable(ScreenNode, ScreenNode.SIZE);
7403var screenCoordinate = /* @__PURE__ */ nodeImmutable(ScreenNode, ScreenNode.COORDINATE);
7404var viewport = /* @__PURE__ */ nodeImmutable(ScreenNode, ScreenNode.VIEWPORT);
7405var viewportSize = viewport.zw;
7406var viewportCoordinate = /* @__PURE__ */ screenCoordinate.sub(viewport.xy);
7407var viewportUV = /* @__PURE__ */ viewportCoordinate.div(viewportSize);
7408var viewportResolution = /* @__PURE__ */ Fn(() => {
7409  warn('TSL: "viewportResolution" is deprecated. Use "screenSize" instead.', new StackTrace());
7410  return screenSize;
7411}, "vec2").once()();
7412var _cameraProjectionMatrixBase = null;
7413var _cameraProjectionMatrixArray = null;
7414var _cameraProjectionMatrixInverseBase = null;
7415var _cameraProjectionMatrixInverseArray = null;
7416var _cameraViewMatrixBase = null;
7417var _cameraViewMatrixArray = null;
7418var _cameraWorldMatrixBase = null;
7419var _cameraWorldMatrixArray = null;
7420var _cameraNormalMatrixBase = null;
7421var _cameraNormalMatrixArray = null;
7422var _cameraPositionBase = null;
7423var _cameraPositionArray = null;
7424var _cameraViewportBase = null;
7425var _cameraViewportArray = null;
7426var cameraIndex = /* @__PURE__ */ uniform(0, "uint").setName("u_cameraIndex").setGroup(sharedUniformGroup("cameraIndex")).toVarying("v_cameraIndex");
7427var cameraNear = /* @__PURE__ */ uniform("float").setName("cameraNear").setGroup(renderGroup).onRenderUpdate(({ camera }) => camera.near);
7428var cameraFar = /* @__PURE__ */ uniform("float").setName("cameraFar").setGroup(renderGroup).onRenderUpdate(({ camera }) => camera.far);
7429var cameraProjectionMatrix = /* @__PURE__ */ Fn(({ camera }) => {
7430  let cameraProjectionMatrix3;
7431  if (camera.isArrayCamera && camera.cameras.length > 0) {
7432    const matrices = [];
7433    for (const subCamera of camera.cameras) {
7434      matrices.push(subCamera.projectionMatrix);
7435    }
7436    if (_cameraProjectionMatrixArray === null) {
7437      _cameraProjectionMatrixArray = uniformArray(matrices).setGroup(renderGroup).setName("cameraProjectionMatrices");
7438    } else {
7439      _cameraProjectionMatrixArray.array = matrices;
7440    }
7441    cameraProjectionMatrix3 = _cameraProjectionMatrixArray.element(camera.isMultiViewCamera ? builtin("gl_ViewID_OVR") : cameraIndex).toConst("cameraProjectionMatrix");
7442  } else {
7443    if (_cameraProjectionMatrixBase === null) {
7444      _cameraProjectionMatrixBase = uniform(camera.projectionMatrix).setName("cameraProjectionMatrix").setGroup(renderGroup).onRenderUpdate(({ camera: camera2 }) => camera2.projectionMatrix);
7445    }
7446    cameraProjectionMatrix3 = _cameraProjectionMatrixBase;
7447  }
7448  return cameraProjectionMatrix3;
7449}).once()();
7450var cameraProjectionMatrixInverse = /* @__PURE__ */ Fn(({ camera }) => {
7451  let cameraProjectionMatrixInverse3;
7452  if (camera.isArrayCamera && camera.cameras.length > 0) {
7453    const matrices = [];
7454    for (const subCamera of camera.cameras) {
7455      matrices.push(subCamera.projectionMatrixInverse);
7456    }
7457    if (_cameraProjectionMatrixInverseArray === null) {
7458      _cameraProjectionMatrixInverseArray = uniformArray(matrices).setGroup(renderGroup).setName("cameraProjectionMatricesInverse");
7459    } else {
7460      _cameraProjectionMatrixInverseArray.array = matrices;
7461    }
7462    cameraProjectionMatrixInverse3 = _cameraProjectionMatrixInverseArray.element(camera.isMultiViewCamera ? builtin("gl_ViewID_OVR") : cameraIndex).toConst("cameraProjectionMatrixInverse");
7463  } else {
7464    if (_cameraProjectionMatrixInverseBase === null) {
7465      _cameraProjectionMatrixInverseBase = uniform(camera.projectionMatrixInverse).setName("cameraProjectionMatrixInverse").setGroup(renderGroup).onRenderUpdate(({ camera: camera2 }) => camera2.projectionMatrixInverse);
7466    }
7467    cameraProjectionMatrixInverse3 = _cameraProjectionMatrixInverseBase;
7468  }
7469  return cameraProjectionMatrixInverse3;
7470}).once()();
7471var cameraViewMatrix = /* @__PURE__ */ Fn(({ camera }) => {
7472  let cameraViewMatrix3;
7473  if (camera.isArrayCamera && camera.cameras.length > 0) {
7474    const matrices = [];
7475    for (const subCamera of camera.cameras) {
7476      matrices.push(subCamera.matrixWorldInverse);
7477    }
7478    if (_cameraViewMatrixArray === null) {
7479      _cameraViewMatrixArray = uniformArray(matrices).setGroup(renderGroup).setName("cameraViewMatrices");
7480    } else {
7481      _cameraViewMatrixArray.array = matrices;
7482    }
7483    cameraViewMatrix3 = _cameraViewMatrixArray.element(camera.isMultiViewCamera ? builtin("gl_ViewID_OVR") : cameraIndex).toConst("cameraViewMatrix");
7484  } else {
7485    if (_cameraViewMatrixBase === null) {
7486      _cameraViewMatrixBase = uniform(camera.matrixWorldInverse).setName("cameraViewMatrix").setGroup(renderGroup).onRenderUpdate(({ camera: camera2 }) => camera2.matrixWorldInverse);
7487    }
7488    cameraViewMatrix3 = _cameraViewMatrixBase;
7489  }
7490  return cameraViewMatrix3;
7491}).once()();
7492var cameraWorldMatrix = /* @__PURE__ */ Fn(({ camera }) => {
7493  let cameraWorldMatrix3;
7494  if (camera.isArrayCamera && camera.cameras.length > 0) {
7495    const matrices = [];
7496    for (const subCamera of camera.cameras) {
7497      matrices.push(subCamera.matrixWorld);
7498    }
7499    if (_cameraWorldMatrixArray === null) {
7500      _cameraWorldMatrixArray = uniformArray(matrices).setGroup(renderGroup).setName("cameraWorldMatrices");
7501    } else {
7502      _cameraWorldMatrixArray.array = matrices;
7503    }
7504    cameraWorldMatrix3 = _cameraWorldMatrixArray.element(camera.isMultiViewCamera ? builtin("gl_ViewID_OVR") : cameraIndex).toConst("cameraWorldMatrix");
7505  } else {
7506    if (_cameraWorldMatrixBase === null) {
7507      _cameraWorldMatrixBase = uniform(camera.matrixWorld).setName("cameraWorldMatrix").setGroup(renderGroup).onRenderUpdate(({ camera: camera2 }) => camera2.matrixWorld);
7508    }
7509    cameraWorldMatrix3 = _cameraWorldMatrixBase;
7510  }
7511  return cameraWorldMatrix3;
7512}).once()();
7513var cameraNormalMatrix = /* @__PURE__ */ Fn(({ camera }) => {
7514  let cameraNormalMatrix3;
7515  if (camera.isArrayCamera && camera.cameras.length > 0) {
7516    const matrices = [];
7517    for (const subCamera of camera.cameras) {
7518      matrices.push(subCamera.normalMatrix);
7519    }
7520    if (_cameraNormalMatrixArray === null) {
7521      _cameraNormalMatrixArray = uniformArray(matrices).setGroup(renderGroup).setName("cameraNormalMatrices");
7522    } else {
7523      _cameraNormalMatrixArray.array = matrices;
7524    }
7525    cameraNormalMatrix3 = _cameraNormalMatrixArray.element(camera.isMultiViewCamera ? builtin("gl_ViewID_OVR") : cameraIndex).toConst("cameraNormalMatrix");
7526  } else {
7527    if (_cameraNormalMatrixBase === null) {
7528      _cameraNormalMatrixBase = uniform(camera.normalMatrix).setName("cameraNormalMatrix").setGroup(renderGroup).onRenderUpdate(({ camera: camera2 }) => camera2.normalMatrix);
7529    }
7530    cameraNormalMatrix3 = _cameraNormalMatrixBase;
7531  }
7532  return cameraNormalMatrix3;
7533}).once()();
7534var cameraPosition = /* @__PURE__ */ Fn(({ camera }) => {
7535  let cameraPosition3;
7536  if (camera.isArrayCamera && camera.cameras.length > 0) {
7537    const positions = [];
7538    for (let i = 0, l = camera.cameras.length; i < l; i++) {
7539      positions.push(new Vector3());
7540    }
7541    if (_cameraPositionArray === null) {
7542      _cameraPositionArray = uniformArray(positions).setGroup(renderGroup).setName("cameraPositions").onRenderUpdate(({ camera: camera2 }, self2) => {
7543        const subCameras = camera2.cameras;
7544        const array3 = self2.array;
7545        for (let i = 0, l = subCameras.length; i < l; i++) {
7546          array3[i].setFromMatrixPosition(subCameras[i].matrixWorld);
7547        }
7548      });
7549    } else {
7550      _cameraPositionArray.array = positions;
7551    }
7552    cameraPosition3 = _cameraPositionArray.element(camera.isMultiViewCamera ? builtin("gl_ViewID_OVR") : cameraIndex).toConst("cameraPosition");
7553  } else {
7554    if (_cameraPositionBase === null) {
7555      _cameraPositionBase = uniform(new Vector3()).setName("cameraPosition").setGroup(renderGroup).onRenderUpdate(({ camera: camera2 }, self2) => self2.value.setFromMatrixPosition(camera2.matrixWorld));
7556    }
7557    cameraPosition3 = _cameraPositionBase;
7558  }
7559  return cameraPosition3;
7560}).once()();
7561var cameraViewport = /* @__PURE__ */ Fn(({ camera }) => {
7562  let cameraViewport3;
7563  if (camera.isArrayCamera && camera.cameras.length > 0) {
7564    const viewports = [];
7565    for (const subCamera of camera.cameras) {
7566      viewports.push(subCamera.viewport);
7567    }
7568    if (_cameraViewportArray === null) {
7569      _cameraViewportArray = uniformArray(viewports, "vec4").setGroup(renderGroup).setName("cameraViewports");
7570    } else {
7571      _cameraViewportArray.array = viewports;
7572    }
7573    cameraViewport3 = _cameraViewportArray.element(cameraIndex).toConst("cameraViewport");
7574  } else {
7575    if (_cameraViewportBase === null) {
7576      _cameraViewportBase = vec4(0, 0, screenSize.x, screenSize.y).toConst("cameraViewport");
7577    }
7578    cameraViewport3 = _cameraViewportBase;
7579  }
7580  return cameraViewport3;
7581}).once()();
7582var _sphere = /* @__PURE__ */ new Sphere();
7583var Object3DNode = class _Object3DNode extends Node2 {
7584  static get type() {
7585    return "Object3DNode";
7586  }
7587  /**
7588   * Constructs a new object 3D node.
7589   *
7590   * @param {('position'|'viewPosition'|'direction'|'scale'|'worldMatrix')} scope - The node represents a different type of transformation depending on the scope.
7591   * @param {?Object3D} [object3d=null] - The 3D object.
7592   */
7593  constructor(scope, object3d = null) {
7594    super();
7595    this.scope = scope;
7596    this.object3d = object3d;
7597    this.updateType = NodeUpdateType.OBJECT;
7598    this.uniformNode = new UniformNode(null);
7599  }
7600  /**
7601   * Overwritten since the node type is inferred from the scope.
7602   *
7603   * @return {('mat4'|'vec3'|'float')} The node type.
7604   */
7605  generateNodeType() {
7606    const scope = this.scope;
7607    if (scope === _Object3DNode.WORLD_MATRIX) {
7608      return "mat4";
7609    } else if (scope === _Object3DNode.POSITION || scope === _Object3DNode.VIEW_POSITION || scope === _Object3DNode.DIRECTION || scope === _Object3DNode.SCALE) {
7610      return "vec3";
7611    } else if (scope === _Object3DNode.RADIUS) {
7612      return "float";
7613    }
7614  }
7615  /**
7616   * Updates the uniform value depending on the scope.
7617   *
7618   * @param {NodeFrame} frame - The current node frame.
7619   */
7620  update(frame) {
7621    const object = this.object3d;
7622    const uniformNode = this.uniformNode;
7623    const scope = this.scope;
7624    if (scope === _Object3DNode.WORLD_MATRIX) {
7625      uniformNode.value = object.matrixWorld;
7626    } else if (scope === _Object3DNode.POSITION) {
7627      uniformNode.value = uniformNode.value || new Vector3();
7628      uniformNode.value.setFromMatrixPosition(object.matrixWorld);
7629    } else if (scope === _Object3DNode.SCALE) {
7630      uniformNode.value = uniformNode.value || new Vector3();
7631      uniformNode.value.setFromMatrixScale(object.matrixWorld);
7632    } else if (scope === _Object3DNode.DIRECTION) {
7633      uniformNode.value = uniformNode.value || new Vector3();
7634      object.getWorldDirection(uniformNode.value);
7635    } else if (scope === _Object3DNode.VIEW_POSITION) {
7636      const camera = frame.camera;
7637      uniformNode.value = uniformNode.value || new Vector3();
7638      uniformNode.value.setFromMatrixPosition(object.matrixWorld);
7639      uniformNode.value.applyMatrix4(camera.matrixWorldInverse);
7640    } else if (scope === _Object3DNode.RADIUS) {
7641      const geometry = frame.object.geometry;
7642      if (geometry.boundingSphere === null) geometry.computeBoundingSphere();
7643      _sphere.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld);
7644      uniformNode.value = _sphere.radius;
7645    }
7646  }
7647  /**
7648   * Generates the code snippet of the uniform node. The node type of the uniform
7649   * node also depends on the selected scope.
7650   *
7651   * @param {NodeBuilder} builder - The current node builder.
7652   * @return {string} The generated code snippet.
7653   */
7654  generate(builder) {
7655    const scope = this.scope;
7656    if (scope === _Object3DNode.WORLD_MATRIX) {
7657      this.uniformNode.nodeType = "mat4";
7658    } else if (scope === _Object3DNode.POSITION || scope === _Object3DNode.VIEW_POSITION || scope === _Object3DNode.DIRECTION || scope === _Object3DNode.SCALE) {
7659      this.uniformNode.nodeType = "vec3";
7660    } else if (scope === _Object3DNode.RADIUS) {
7661      this.uniformNode.nodeType = "float";
7662    }
7663    return this.uniformNode.build(builder);
7664  }
7665  serialize(data) {
7666    super.serialize(data);
7667    data.scope = this.scope;
7668  }
7669  deserialize(data) {
7670    super.deserialize(data);
7671    this.scope = data.scope;
7672  }
7673};
7674Object3DNode.WORLD_MATRIX = "worldMatrix";
7675Object3DNode.POSITION = "position";
7676Object3DNode.SCALE = "scale";
7677Object3DNode.VIEW_POSITION = "viewPosition";
7678Object3DNode.DIRECTION = "direction";
7679Object3DNode.RADIUS = "radius";
7680var objectDirection = /* @__PURE__ */ nodeProxy(Object3DNode, Object3DNode.DIRECTION).setParameterLength(1);
7681var objectWorldMatrix = /* @__PURE__ */ nodeProxy(Object3DNode, Object3DNode.WORLD_MATRIX).setParameterLength(1);
7682var objectPosition = /* @__PURE__ */ nodeProxy(Object3DNode, Object3DNode.POSITION).setParameterLength(1);
7683var objectScale = /* @__PURE__ */ nodeProxy(Object3DNode, Object3DNode.SCALE).setParameterLength(1);
7684var objectViewPosition = /* @__PURE__ */ nodeProxy(Object3DNode, Object3DNode.VIEW_POSITION).setParameterLength(1);
7685var objectRadius = /* @__PURE__ */ nodeProxy(Object3DNode, Object3DNode.RADIUS).setParameterLength(1);
7686var ModelNode = class extends Object3DNode {
7687  static get type() {
7688    return "ModelNode";
7689  }
7690  /**
7691   * Constructs a new object model node.
7692   *
7693   * @param {('position'|'viewPosition'|'direction'|'scale'|'worldMatrix')} scope - The node represents a different type of transformation depending on the scope.
7694   */
7695  constructor(scope) {
7696    super(scope);
7697  }
7698  /**
7699   * Extracts the model reference from the frame state and then
7700   * updates the uniform value depending on the scope.
7701   *
7702   * @param {NodeFrame} frame - The current node frame.
7703   */
7704  update(frame) {
7705    this.object3d = frame.object;
7706    super.update(frame);
7707  }
7708};
7709var modelDirection = /* @__PURE__ */ nodeImmutable(ModelNode, ModelNode.DIRECTION);
7710var modelWorldMatrix = /* @__PURE__ */ nodeImmutable(ModelNode, ModelNode.WORLD_MATRIX);
7711var modelPosition = /* @__PURE__ */ nodeImmutable(ModelNode, ModelNode.POSITION);
7712var modelScale = /* @__PURE__ */ nodeImmutable(ModelNode, ModelNode.SCALE);
7713var modelViewPosition = /* @__PURE__ */ nodeImmutable(ModelNode, ModelNode.VIEW_POSITION);
7714var modelRadius = /* @__PURE__ */ nodeImmutable(ModelNode, ModelNode.RADIUS);
7715var modelNormalMatrix = /* @__PURE__ */ uniform(new Matrix3()).onObjectUpdate(({ object }, self2) => self2.value.getNormalMatrix(object.matrixWorld));
7716var modelWorldMatrixInverse = /* @__PURE__ */ uniform(new Matrix4()).onObjectUpdate(({ object }, self2) => self2.value.copy(object.matrixWorld).invert());
7717var modelViewMatrix = /* @__PURE__ */ Fn((builder) => {
7718  return builder.context.modelViewMatrix || mediumpModelViewMatrix;
7719}).once()().toVar("modelViewMatrix");
7720var mediumpModelViewMatrix = /* @__PURE__ */ cameraViewMatrix.mul(modelWorldMatrix);
7721var highpModelViewMatrix = /* @__PURE__ */ Fn((builder) => {
7722  builder.context.isHighPrecisionModelViewMatrix = true;
7723  return uniform("mat4").onObjectUpdate(({ object, camera }) => {
7724    return object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld);
7725  });
7726}).once()().toVar("highpModelViewMatrix");
7727var highpModelNormalViewMatrix = /* @__PURE__ */ Fn((builder) => {
7728  const isHighPrecisionModelViewMatrix = builder.context.isHighPrecisionModelViewMatrix;
7729  return uniform("mat3").onObjectUpdate(({ object, camera }) => {
7730    if (isHighPrecisionModelViewMatrix !== true) {
7731      object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld);
7732    }
7733    return object.normalMatrix.getNormalMatrix(object.modelViewMatrix);
7734  });
7735}).once()().toVar("highpModelNormalViewMatrix");
7736var clipSpace = /* @__PURE__ */ Fn((builder) => {
7737  if (builder.shaderStage !== "fragment") {
7738    warnOnce("TSL: `clipSpace` is only available in fragment stage.");
7739    return vec4();
7740  }
7741  return builder.context.clipSpace.toVarying("v_clipSpace");
7742}).once()();
7743var positionGeometry = /* @__PURE__ */ attribute("position", "vec3");
7744var positionLocal = /* @__PURE__ */ positionGeometry.toVarying("positionLocal");
7745var positionPrevious = /* @__PURE__ */ positionGeometry.toVarying("positionPrevious");
7746var positionWorld = /* @__PURE__ */ Fn((builder) => {
7747  return modelWorldMatrix.mul(positionLocal).xyz.toVarying(builder.getSubBuildProperty("v_positionWorld"));
7748}, "vec3").once(["POSITION"])();
7749var positionWorldDirection = /* @__PURE__ */ Fn(() => {
7750  const vertexPWD = positionLocal.transformDirection(modelWorldMatrix).toVarying("v_positionWorldDirection");
7751  return vertexPWD.normalize().toVar("positionWorldDirection");
7752}, "vec3").once(["POSITION"])();
7753var positionView = /* @__PURE__ */ Fn((builder) => {
7754  if (builder.shaderStage === "fragment" && builder.material.vertexNode) {
7755    const viewPos = cameraProjectionMatrixInverse.mul(clipSpace);
7756    return viewPos.xyz.div(viewPos.w).toVar("positionView");
7757  }
7758  return builder.context.setupPositionView().toVarying("v_positionView");
7759}, "vec3").once(["POSITION", "VERTEX"])();
7760var positionViewDirection = /* @__PURE__ */ Fn((builder) => {
7761  let output3;
7762  if (builder.camera.isOrthographicCamera) {
7763    output3 = vec3(0, 0, 1);
7764  } else {
7765    output3 = positionView.negate().toVarying("v_positionViewDirection").normalize();
7766  }
7767  return output3.toVar("positionViewDirection");
7768}, "vec3").once(["POSITION"])();
7769var FrontFacingNode = class extends Node2 {
7770  static get type() {
7771    return "FrontFacingNode";
7772  }
7773  /**
7774   * Constructs a new front facing node.
7775   */
7776  constructor() {
7777    super("bool");
7778    this.isFrontFacingNode = true;
7779  }
7780  generate(builder) {
7781    if (builder.shaderStage !== "fragment") return "true";
7782    const { material } = builder;
7783    if (material.side === BackSide) {
7784      return "false";
7785    }
7786    return builder.getFrontFacing();
7787  }
7788};
7789var frontFacing = /* @__PURE__ */ nodeImmutable(FrontFacingNode);
7790var faceDirection = /* @__PURE__ */ float(frontFacing).mul(2).sub(1);
7791var directionToFaceDirection = /* @__PURE__ */ Fn(([direction], { material }) => {
7792  const side = material.side;
7793  if (side === BackSide) {
7794    direction = direction.mul(-1);
7795  } else if (side === DoubleSide) {
7796    direction = direction.mul(faceDirection);
7797  }
7798  return direction;
7799});
7800var normalGeometry = /* @__PURE__ */ attribute("normal", "vec3");
7801var normalLocal = /* @__PURE__ */ Fn((builder) => {
7802  if (builder.geometry.hasAttribute("normal") === false) {
7803    warn('TSL: Vertex attribute "normal" not found on geometry.');
7804    return vec3(0, 1, 0);
7805  }
7806  return normalGeometry;
7807}, "vec3").once()().toVar("normalLocal");
7808var normalFlat = /* @__PURE__ */ positionView.dFdx().cross(positionView.dFdy()).normalize().toVar("normalFlat");
7809var normalViewGeometry = /* @__PURE__ */ Fn((builder) => {
7810  let node;
7811  if (builder.isFlatShading()) {
7812    node = normalFlat;
7813  } else {
7814    node = transformNormalToView(normalLocal).toVarying("v_normalViewGeometry").normalize();
7815  }
7816  return node;
7817}, "vec3").once()().toVar("normalViewGeometry");
7818var normalWorldGeometry = /* @__PURE__ */ Fn((builder) => {
7819  let normal2 = normalViewGeometry.transformDirection(cameraViewMatrix);
7820  if (builder.isFlatShading() !== true) {
7821    normal2 = normal2.toVarying("v_normalWorldGeometry");
7822  }
7823  return normal2.normalize().toVar("normalWorldGeometry");
7824}, "vec3").once()();
7825var normalView = /* @__PURE__ */ Fn((builder) => {
7826  let node;
7827  if (builder.subBuildFn === "NORMAL" || builder.subBuildFn === "VERTEX") {
7828    node = normalViewGeometry;
7829    if (builder.isFlatShading() !== true) {
7830      node = directionToFaceDirection(node);
7831    }
7832  } else {
7833    node = builder.context.setupNormal().context({ getUV: null, getTextureLevel: null });
7834  }
7835  return node;
7836}, "vec3").once(["NORMAL", "VERTEX"])().toVar("normalView");
7837var normalWorld = /* @__PURE__ */ normalView.transformDirection(cameraViewMatrix).toVar("normalWorld");
7838var clearcoatNormalView = /* @__PURE__ */ Fn(({ subBuildFn, context: context3 }) => {
7839  let node;
7840  if (subBuildFn === "NORMAL" || subBuildFn === "VERTEX") {
7841    node = normalView;
7842  } else {
7843    node = context3.setupClearcoatNormal().context({ getUV: null, getTextureLevel: null });
7844  }
7845  return node;
7846}, "vec3").once(["NORMAL", "VERTEX"])().toVar("clearcoatNormalView");
7847var transformNormal = /* @__PURE__ */ Fn(([normal2, matrix = modelWorldMatrix]) => {
7848  const m = mat3(matrix);
7849  const transformedNormal = normal2.div(vec3(m[0].dot(m[0]), m[1].dot(m[1]), m[2].dot(m[2])));
7850  return m.mul(transformedNormal).xyz;
7851});
7852var transformNormalToView = /* @__PURE__ */ Fn(([normal2], builder) => {
7853  const modelNormalViewMatrix = builder.context.modelNormalViewMatrix;
7854  if (modelNormalViewMatrix) {
7855    return modelNormalViewMatrix.transformDirection(normal2);
7856  }
7857  const transformedNormal = modelNormalMatrix.mul(normal2);
7858  return cameraViewMatrix.transformDirection(transformedNormal);
7859});
7860var transformedNormalView = Fn(() => {
7861  warn('TSL: "transformedNormalView" is deprecated. Use "normalView" instead.');
7862  return normalView;
7863}).once(["NORMAL", "VERTEX"])();
7864var transformedNormalWorld = Fn(() => {
7865  warn('TSL: "transformedNormalWorld" is deprecated. Use "normalWorld" instead.');
7866  return normalWorld;
7867}).once(["NORMAL", "VERTEX"])();
7868var transformedClearcoatNormalView = Fn(() => {
7869  warn('TSL: "transformedClearcoatNormalView" is deprecated. Use "clearcoatNormalView" instead.');
7870  return clearcoatNormalView;
7871}).once(["NORMAL", "VERTEX"])();
7872var _m1$1 = /* @__PURE__ */ new Matrix4();
7873var materialRefractionRatio = /* @__PURE__ */ uniform(0).onReference(({ material }) => material).onObjectUpdate(({ material }) => material.refractionRatio);
7874var materialEnvIntensity = /* @__PURE__ */ uniform(1).onReference(({ material }) => material).onObjectUpdate(function({ material, scene }) {
7875  return material.envMap ? material.envMapIntensity : scene.environmentIntensity;
7876});
7877var materialEnvRotation = /* @__PURE__ */ uniform(new Matrix4()).onReference(function(frame) {
7878  return frame.material;
7879}).onObjectUpdate(function({ material, scene }) {
7880  const rotation = scene.environment !== null && material.envMap === null ? scene.environmentRotation : material.envMapRotation;
7881  if (rotation) {
7882    _m1$1.makeRotationFromEuler(rotation).transpose();
7883  } else {
7884    _m1$1.identity();
7885  }
7886  return _m1$1;
7887});
7888var reflectView = /* @__PURE__ */ positionViewDirection.negate().reflect(normalView);
7889var refractView = /* @__PURE__ */ positionViewDirection.negate().refract(normalView, materialRefractionRatio);
7890var reflectVector = /* @__PURE__ */ reflectView.transformDirection(cameraViewMatrix).toVar("reflectVector");
7891var refractVector = /* @__PURE__ */ refractView.transformDirection(cameraViewMatrix).toVar("reflectVector");
7892var EmptyTexture = /* @__PURE__ */ new CubeTexture();
7893var CubeTextureNode = class extends TextureNode {
7894  static get type() {
7895    return "CubeTextureNode";
7896  }
7897  /**
7898   * Constructs a new cube texture node.
7899   *
7900   * @param {CubeTexture} value - The cube texture.
7901   * @param {?Node<vec3>} [uvNode=null] - The uv node.
7902   * @param {?Node<int>} [levelNode=null] - The level node.
7903   * @param {?Node<float>} [biasNode=null] - The bias node.
7904   */
7905  constructor(value, uvNode = null, levelNode = null, biasNode = null) {
7906    super(value, uvNode, levelNode, biasNode);
7907    this.isCubeTextureNode = true;
7908  }
7909  /**
7910   * Overwrites the default implementation to return the appropriate cube texture type.
7911   *
7912   * @param {NodeBuilder} builder - The current node builder.
7913   * @return {string} The input type.
7914   */
7915  getInputType() {
7916    if (this.value.isDepthTexture === true) {
7917      return "cubeDepthTexture";
7918    }
7919    return "cubeTexture";
7920  }
7921  /**
7922   * Returns a default uvs based on the mapping type of the cube texture.
7923   *
7924   * @return {Node<vec3>} The default uv attribute.
7925   */
7926  getDefaultUV() {
7927    const texture3 = this.value;
7928    if (texture3.mapping === CubeReflectionMapping) {
7929      return reflectVector;
7930    } else if (texture3.mapping === CubeRefractionMapping) {
7931      return refractVector;
7932    } else {
7933      error('CubeTextureNode: Mapping "%s" not supported.', texture3.mapping);
7934      return vec3(0, 0, 0);
7935    }
7936  }
7937  /**
7938   * Overwritten with an empty implementation since the `updateMatrix` flag is ignored
7939   * for cube textures. The uv transformation matrix is not applied to cube textures.
7940   *
7941   * @param {boolean} value - The update toggle.
7942   */
7943  setUpdateMatrix() {
7944  }
7945  // Ignore .updateMatrix for CubeTextureNode
7946  /**
7947   * Setups the uv node. Depending on the backend as well as the texture type, it might be necessary
7948   * to modify the uv node for correct sampling.
7949   *
7950   * @param {NodeBuilder} builder - The current node builder.
7951   * @param {Node} uvNode - The uv node to setup.
7952   * @return {Node} The updated uv node.
7953   */
7954  setupUV(builder, uvNode) {
7955    const texture3 = this.value;
7956    if (texture3.isDepthTexture === true) {
7957      if (builder.renderer.coordinateSystem === WebGPUCoordinateSystem) {
7958        return vec3(uvNode.x, uvNode.y.negate(), uvNode.z);
7959      }
7960      return uvNode;
7961    }
7962    uvNode = materialEnvRotation.mul(uvNode);
7963    if (builder.renderer.coordinateSystem === WebGPUCoordinateSystem || !texture3.isRenderTargetTexture) {
7964      uvNode = vec3(uvNode.x.negate(), uvNode.yz);
7965    }
7966    return uvNode;
7967  }
7968  /**
7969   * Generates the uv code snippet.
7970   *
7971   * @param {NodeBuilder} builder - The current node builder.
7972   * @param {Node} cubeUV - The uv node to generate code for.
7973   * @return {string} The generated code snippet.
7974   */
7975  generateUV(builder, cubeUV) {
7976    return cubeUV.build(builder, this.sampler === true ? "vec3" : "ivec3");
7977  }
7978};
7979var cubeTextureBase = /* @__PURE__ */ nodeProxy(CubeTextureNode).setParameterLength(1, 4).setName("cubeTexture");
7980var cubeTexture = (value = EmptyTexture, uvNode = null, levelNode = null, biasNode = null) => {
7981  let textureNode;
7982  if (value && value.isCubeTextureNode === true) {
7983    textureNode = nodeObject(value.clone());
7984    textureNode.referenceNode = value;
7985    if (uvNode !== null) textureNode.uvNode = nodeObject(uvNode);
7986    if (levelNode !== null) textureNode.levelNode = nodeObject(levelNode);
7987    if (biasNode !== null) textureNode.biasNode = nodeObject(biasNode);
7988  } else {
7989    textureNode = cubeTextureBase(value, uvNode, levelNode, biasNode);
7990  }
7991  return textureNode;
7992};
7993var uniformCubeTexture = (value = EmptyTexture) => cubeTextureBase(value);
7994var ReferenceElementNode2 = class extends ArrayElementNode {
7995  static get type() {
7996    return "ReferenceElementNode";
7997  }
7998  /**
7999   * Constructs a new reference element node.
8000   *
8001   * @param {?ReferenceNode} referenceNode - The reference node.
8002   * @param {Node} indexNode - The index node that defines the element access.
8003   */
8004  constructor(referenceNode, indexNode) {
8005    super(referenceNode, indexNode);
8006    this.referenceNode = referenceNode;
8007    this.isReferenceElementNode = true;
8008  }
8009  /**
8010   * This method is overwritten since the node type is inferred from
8011   * the uniform type of the reference node.
8012   *
8013   * @return {string} The node type.
8014   */
8015  generateNodeType() {
8016    return this.referenceNode.uniformType;
8017  }
8018  generate(builder) {
8019    const snippet = super.generate(builder);
8020    const arrayType = this.referenceNode.getNodeType(builder);
8021    const elementType = this.getNodeType(builder);
8022    return builder.format(snippet, arrayType, elementType);
8023  }
8024};
8025var ReferenceNode = class extends Node2 {
8026  static get type() {
8027    return "ReferenceNode";
8028  }
8029  /**
8030   * Constructs a new reference node.
8031   *
8032   * @param {string} property - The name of the property the node refers to.
8033   * @param {string} uniformType - The uniform type that should be used to represent the property value.
8034   * @param {?Object} [object=null] - The object the property belongs to.
8035   * @param {?number} [count=null] - When the linked property is an array-like, this parameter defines its length.
8036   */
8037  constructor(property3, uniformType, object = null, count = null) {
8038    super();
8039    this.property = property3;
8040    this.uniformType = uniformType;
8041    this.object = object;
8042    this.count = count;
8043    this.properties = property3.split(".");
8044    this.reference = object;
8045    this.node = null;
8046    this.group = null;
8047    this.name = null;
8048    this.updateType = NodeUpdateType.OBJECT;
8049  }
8050  /**
8051   * When the referred property is array-like, this method can be used
8052   * to access elements via an index node.
8053   *
8054   * @param {IndexNode} indexNode - indexNode.
8055   * @return {ReferenceElementNode} A reference to an element.
8056   */
8057  element(indexNode) {
8058    return new ReferenceElementNode2(this, nodeObject(indexNode));
8059  }
8060  /**
8061   * Sets the uniform group for this reference node.
8062   *
8063   * @param {UniformGroupNode} group - The uniform group to set.
8064   * @return {ReferenceNode} A reference to this node.
8065   */
8066  setGroup(group) {
8067    this.group = group;
8068    return this;
8069  }
8070  /**
8071   * Sets the name for the internal uniform.
8072   *
8073   * @param {string} name - The label to set.
8074   * @return {ReferenceNode} A reference to this node.
8075   */
8076  setName(name) {
8077    this.name = name;
8078    return this;
8079  }
8080  /**
8081   * Sets the label for the internal uniform.
8082   *
8083   * @deprecated
8084   * @param {string} name - The label to set.
8085   * @return {ReferenceNode} A reference to this node.
8086   */
8087  label(name) {
8088    warn('TSL: "label()" has been deprecated. Use "setName()" instead.');
8089    return this.setName(name);
8090  }
8091  /**
8092   * Sets the node type which automatically defines the internal
8093   * uniform type.
8094   *
8095   * @param {string} uniformType - The type to set.
8096   */
8097  setNodeType(uniformType) {
8098    let node = null;
8099    if (this.count !== null) {
8100      node = buffer(null, uniformType, this.count);
8101    } else if (Array.isArray(this.getValueFromReference())) {
8102      node = uniformArray(null, uniformType);
8103    } else if (uniformType === "texture") {
8104      node = texture(null);
8105    } else if (uniformType === "cubeTexture") {
8106      node = cubeTexture(null);
8107    } else {
8108      node = uniform(null, uniformType);
8109    }
8110    if (this.group !== null) {
8111      node.setGroup(this.group);
8112    }
8113    if (this.name !== null) node.setName(this.name);
8114    this.node = node;
8115  }
8116  /**
8117   * This method is overwritten since the node type is inferred from
8118   * the type of the reference node.
8119   *
8120   * @param {NodeBuilder} builder - The current node builder.
8121   * @return {string} The node type.
8122   */
8123  generateNodeType(builder) {
8124    if (this.node === null) {
8125      this.updateReference(builder);
8126      this.updateValue();
8127    }
8128    return this.node.getNodeType(builder);
8129  }
8130  /**
8131   * Returns the property value from the given referred object.
8132   *
8133   * @param {Object} [object=this.reference] - The object to retrieve the property value from.
8134   * @return {any} The value.
8135   */
8136  getValueFromReference(object = this.reference) {
8137    const { properties } = this;
8138    let value = object[properties[0]];
8139    for (let i = 1; i < properties.length; i++) {
8140      value = value[properties[i]];
8141    }
8142    return value;
8143  }
8144  /**
8145   * Allows to update the reference based on the given state. The state is only
8146   * evaluated {@link ReferenceNode#object} is not set.
8147   *
8148   * @param {(NodeFrame|NodeBuilder)} state - The current state.
8149   * @return {Object} The updated reference.
8150   */
8151  updateReference(state) {
8152    this.reference = this.object !== null ? this.object : state.object;
8153    return this.reference;
8154  }
8155  /**
8156   * The output of the reference node is the internal uniform node.
8157   *
8158   * @param {NodeBuilder} builder - The current node builder.
8159   * @return {UniformNode} The output node.
8160   */
8161  setup() {
8162    this.updateValue();
8163    return this.node;
8164  }
8165  /**
8166   * Overwritten to update the internal uniform value.
8167   *
8168   * @param {NodeFrame} frame - A reference to the current node frame.
8169   */
8170  update() {
8171    this.updateValue();
8172  }
8173  /**
8174   * Retrieves the value from the referred object property and uses it
8175   * to updated the internal uniform.
8176   */
8177  updateValue() {
8178    if (this.node === null) this.setNodeType(this.uniformType);
8179    const value = this.getValueFromReference();
8180    if (Array.isArray(value)) {
8181      this.node.array = value;
8182    } else {
8183      this.node.value = value;
8184    }
8185  }
8186};
8187var reference = (name, type, object) => new ReferenceNode(name, type, object);
8188var referenceBuffer = (name, type, count, object) => new ReferenceNode(name, type, object, count);
8189var MaterialReferenceNode = class extends ReferenceNode {
8190  static get type() {
8191    return "MaterialReferenceNode";
8192  }
8193  /**
8194   * Constructs a new material reference node.
8195   *
8196   * @param {string} property - The name of the property the node refers to.
8197   * @param {string} inputType - The uniform type that should be used to represent the property value.
8198   * @param {?Material} [material=null] - The material the property belongs to. When no material is set,
8199   * the node refers to the material of the current rendered object.
8200   */
8201  constructor(property3, inputType, material = null) {
8202    super(property3, inputType, material);
8203    this.material = material;
8204    this.isMaterialReferenceNode = true;
8205  }
8206  /**
8207   * Updates the reference based on the given state. The state is only evaluated
8208   * {@link MaterialReferenceNode#material} is not set.
8209   *
8210   * @param {(NodeFrame|NodeBuilder)} state - The current state.
8211   * @return {Object} The updated reference.
8212   */
8213  updateReference(state) {
8214    this.reference = this.material !== null ? this.material : state.material;
8215    return this.reference;
8216  }
8217};
8218var materialReference = (name, type, material = null) => new MaterialReferenceNode(name, type, material);
8219var uv = uv$1();
8220var q0 = positionView.dFdx();
8221var q1 = positionView.dFdy();
8222var st0 = uv.dFdx();
8223var st1 = uv.dFdy();
8224var N = normalView;
8225var q1perp = q1.cross(N);
8226var q0perp = N.cross(q0);
8227var T = q1perp.mul(st0.x).add(q0perp.mul(st1.x));
8228var B = q1perp.mul(st0.y).add(q0perp.mul(st1.y));
8229var det = T.dot(T).max(B.dot(B));
8230var scale$1 = det.equal(0).select(0, det.inverseSqrt());
8231var tangentViewFrame = /* @__PURE__ */ T.mul(scale$1).toVar("tangentViewFrame");
8232var bitangentViewFrame = /* @__PURE__ */ B.mul(scale$1).toVar("bitangentViewFrame");
8233var tangentGeometry = /* @__PURE__ */ attribute("tangent", "vec4");
8234var tangentLocal = /* @__PURE__ */ tangentGeometry.xyz.toVar("tangentLocal");
8235var tangentView = /* @__PURE__ */ Fn((builder) => {
8236  let node;
8237  if (builder.subBuildFn === "VERTEX" || builder.geometry.hasAttribute("tangent")) {
8238    node = modelViewMatrix.mul(vec4(tangentLocal, 0)).xyz.toVarying("v_tangentView").normalize();
8239  } else {
8240    node = tangentViewFrame;
8241  }
8242  if (builder.isFlatShading() !== true) {
8243    node = directionToFaceDirection(node);
8244  }
8245  return node;
8246}, "vec3").once(["NORMAL", "VERTEX"])().toVar("tangentView");
8247var tangentWorld = /* @__PURE__ */ tangentView.transformDirection(cameraViewMatrix).toVarying("v_tangentWorld").normalize().toVar("tangentWorld");
8248var getBitangent = /* @__PURE__ */ Fn(([crossNormalTangent, varyingName], builder) => {
8249  let bitangent = crossNormalTangent.mul(tangentGeometry.w).xyz;
8250  if (builder.subBuildFn === "NORMAL" && builder.isFlatShading() !== true) {
8251    bitangent = bitangent.toVarying(varyingName);
8252  }
8253  return bitangent;
8254}).once(["NORMAL"]);
8255var bitangentGeometry = /* @__PURE__ */ getBitangent(normalGeometry.cross(tangentGeometry), "v_bitangentGeometry").normalize().toVar("bitangentGeometry");
8256var bitangentLocal = /* @__PURE__ */ getBitangent(normalLocal.cross(tangentLocal), "v_bitangentLocal").normalize().toVar("bitangentLocal");
8257var bitangentView = /* @__PURE__ */ Fn((builder) => {
8258  let node;
8259  if (builder.subBuildFn === "VERTEX" || builder.geometry.hasAttribute("tangent")) {
8260    node = getBitangent(normalView.cross(tangentView), "v_bitangentView").normalize();
8261  } else {
8262    node = bitangentViewFrame;
8263  }
8264  if (builder.isFlatShading() !== true) {
8265    node = directionToFaceDirection(node);
8266  }
8267  return node;
8268}, "vec3").once(["NORMAL", "VERTEX"])().toVar("bitangentView");
8269var bitangentWorld = /* @__PURE__ */ getBitangent(normalWorld.cross(tangentWorld), "v_bitangentWorld").normalize().toVar("bitangentWorld");
8270var TBNViewMatrix = /* @__PURE__ */ mat3(tangentView, bitangentView, normalView).toVar("TBNViewMatrix");
8271var parallaxDirection = /* @__PURE__ */ positionViewDirection.mul(TBNViewMatrix);
8272var parallaxUV = (uv3, scale2) => uv3.sub(parallaxDirection.mul(scale2));
8273var bentNormalView = /* @__PURE__ */ Fn(() => {
8274  let bentNormal = anisotropyB.cross(positionViewDirection);
8275  bentNormal = bentNormal.cross(anisotropyB).normalize();
8276  bentNormal = mix(bentNormal, normalView, anisotropy.mul(roughness.oneMinus()).oneMinus().pow2().pow2()).normalize();
8277  return bentNormal;
8278}).once()();
8279var directionToColor = (node) => nodeObject(node).mul(0.5).add(0.5);
8280var colorToDirection = (node) => nodeObject(node).mul(2).sub(1);
8281var unpackNormal = (xy) => vec3(xy, sqrt(saturate(float(1).sub(dot(xy, xy)))));
8282var NormalMapNode = class extends TempNode {
8283  static get type() {
8284    return "NormalMapNode";
8285  }
8286  /**
8287   * Constructs a new normal map node.
8288   *
8289   * @param {Node<vec3>} node - Represents the normal map data.
8290   * @param {?Node<vec2>} [scaleNode=null] - Controls the intensity of the effect.
8291   */
8292  constructor(node, scaleNode = null) {
8293    super("vec3");
8294    this.node = node;
8295    this.scaleNode = scaleNode;
8296    this.normalMapType = TangentSpaceNormalMap;
8297    this.unpackNormalMode = NoNormalPacking;
8298  }
8299  setup(builder) {
8300    const { normalMapType, scaleNode, unpackNormalMode } = this;
8301    let normalMap3 = this.node.mul(2).sub(1);
8302    if (normalMapType === TangentSpaceNormalMap) {
8303      if (unpackNormalMode === NormalRGPacking) {
8304        normalMap3 = unpackNormal(normalMap3.xy);
8305      } else if (unpackNormalMode === NormalGAPacking) {
8306        normalMap3 = unpackNormal(normalMap3.yw);
8307      } else if (unpackNormalMode !== NoNormalPacking) {
8308        error(`THREE.NodeMaterial: Unexpected unpack normal mode: ${unpackNormalMode}`);
8309      }
8310    } else {
8311      if (unpackNormalMode !== NoNormalPacking) {
8312        error(`THREE.NodeMaterial: Normal map type '${normalMapType}' is not compatible with unpack normal mode '${unpackNormalMode}'`);
8313      }
8314    }
8315    if (scaleNode !== null) {
8316      let scale2 = scaleNode;
8317      if (builder.isFlatShading() === true) {
8318        scale2 = directionToFaceDirection(scale2);
8319      }
8320      normalMap3 = vec3(normalMap3.xy.mul(scale2), normalMap3.z);
8321    }
8322    let output3 = null;
8323    if (normalMapType === ObjectSpaceNormalMap) {
8324      output3 = transformNormalToView(normalMap3);
8325    } else if (normalMapType === TangentSpaceNormalMap) {
8326      output3 = TBNViewMatrix.mul(normalMap3).normalize();
8327    } else {
8328      error(`NodeMaterial: Unsupported normal map type: ${normalMapType}`);
8329      output3 = normalView;
8330    }
8331    return output3;
8332  }
8333};
8334var normalMap = /* @__PURE__ */ nodeProxy(NormalMapNode).setParameterLength(1, 2);
8335var dHdxy_fwd = Fn(({ textureNode, bumpScale }) => {
8336  const sampleTexture = (callback) => textureNode.isolate().context({ getUV: (texNode) => callback(texNode.uvNode || uv$1()), forceUVContext: true });
8337  const Hll = float(sampleTexture((uvNode) => uvNode));
8338  return vec2(
8339    float(sampleTexture((uvNode) => uvNode.add(uvNode.dFdx()))).sub(Hll),
8340    float(sampleTexture((uvNode) => uvNode.add(uvNode.dFdy()))).sub(Hll)
8341  ).mul(bumpScale);
8342});
8343var perturbNormalArb = Fn((inputs) => {
8344  const { surf_pos, surf_norm, dHdxy } = inputs;
8345  const vSigmaX = surf_pos.dFdx().normalize();
8346  const vSigmaY = surf_pos.dFdy().normalize();
8347  const vN = surf_norm;
8348  const R1 = vSigmaY.cross(vN);
8349  const R2 = vN.cross(vSigmaX);
8350  const fDet = vSigmaX.dot(R1).mul(faceDirection);
8351  const vGrad = fDet.sign().mul(dHdxy.x.mul(R1).add(dHdxy.y.mul(R2)));
8352  return fDet.abs().mul(surf_norm).sub(vGrad).normalize();
8353});
8354var BumpMapNode = class extends TempNode {
8355  static get type() {
8356    return "BumpMapNode";
8357  }
8358  /**
8359   * Constructs a new bump map node.
8360   *
8361   * @param {Node<float>} textureNode - Represents the bump map data.
8362   * @param {?Node<float>} [scaleNode=null] - Controls the intensity of the bump effect.
8363   */
8364  constructor(textureNode, scaleNode = null) {
8365    super("vec3");
8366    this.textureNode = textureNode;
8367    this.scaleNode = scaleNode;
8368  }
8369  setup() {
8370    const bumpScale = this.scaleNode !== null ? this.scaleNode : 1;
8371    const dHdxy = dHdxy_fwd({ textureNode: this.textureNode, bumpScale });
8372    return perturbNormalArb({
8373      surf_pos: positionView,
8374      surf_norm: normalView,
8375      dHdxy
8376    });
8377  }
8378};
8379var bumpMap = /* @__PURE__ */ nodeProxy(BumpMapNode).setParameterLength(1, 2);
8380var _propertyCache = /* @__PURE__ */ new Map();
8381var MaterialNode = class _MaterialNode extends Node2 {
8382  static get type() {
8383    return "MaterialNode";
8384  }
8385  /**
8386   * Constructs a new material node.
8387   *
8388   * @param {string} scope - The scope defines what kind of material property is referred by the node.
8389   */
8390  constructor(scope) {
8391    super();
8392    this.scope = scope;
8393  }
8394  /**
8395   * Returns a cached reference node for the given property and type.
8396   *
8397   * @param {string} property - The name of the material property.
8398   * @param {string} type - The uniform type of the property.
8399   * @return {MaterialReferenceNode} A material reference node representing the property access.
8400   */
8401  getCache(property3, type) {
8402    let node = _propertyCache.get(property3);
8403    if (node === void 0) {
8404      node = materialReference(property3, type);
8405      _propertyCache.set(property3, node);
8406    }
8407    return node;
8408  }
8409  /**
8410   * Returns a float-typed material reference node for the given property name.
8411   *
8412   * @param {string} property - The name of the material property.
8413   * @return {MaterialReferenceNode<float>} A material reference node representing the property access.
8414   */
8415  getFloat(property3) {
8416    return this.getCache(property3, "float");
8417  }
8418  /**
8419   * Returns a color-typed material reference node for the given property name.
8420   *
8421   * @param {string} property - The name of the material property.
8422   * @return {MaterialReferenceNode<color>} A material reference node representing the property access.
8423   */
8424  getColor(property3) {
8425    return this.getCache(property3, "color");
8426  }
8427  /**
8428   * Returns a texture-typed material reference node for the given property name.
8429   *
8430   * @param {string} property - The name of the material property.
8431   * @return {MaterialReferenceNode} A material reference node representing the property access.
8432   */
8433  getTexture(property3) {
8434    return this.getCache(property3 === "map" ? "map" : property3 + "Map", "texture");
8435  }
8436  /**
8437   * The node setup is done depending on the selected scope. Multiple material properties
8438   * might be grouped into a single node composition if they logically belong together.
8439   *
8440   * @param {NodeBuilder} builder - The current node builder.
8441   * @return {Node} The node representing the selected scope.
8442   */
8443  setup(builder) {
8444    const material = builder.context.material;
8445    const scope = this.scope;
8446    let node = null;
8447    if (scope === _MaterialNode.COLOR) {
8448      const colorNode = material.color !== void 0 ? this.getColor(scope) : vec3();
8449      if (material.map && material.map.isTexture === true) {
8450        node = colorNode.mul(this.getTexture("map"));
8451      } else {
8452        node = colorNode;
8453      }
8454    } else if (scope === _MaterialNode.OPACITY) {
8455      const opacityNode = this.getFloat(scope);
8456      if (material.alphaMap && material.alphaMap.isTexture === true) {
8457        node = opacityNode.mul(this.getTexture("alpha"));
8458      } else {
8459        node = opacityNode;
8460      }
8461    } else if (scope === _MaterialNode.SPECULAR_STRENGTH) {
8462      if (material.specularMap && material.specularMap.isTexture === true) {
8463        node = this.getTexture("specular").r;
8464      } else {
8465        node = float(1);
8466      }
8467    } else if (scope === _MaterialNode.SPECULAR_INTENSITY) {
8468      const specularIntensityNode = this.getFloat(scope);
8469      if (material.specularIntensityMap && material.specularIntensityMap.isTexture === true) {
8470        node = specularIntensityNode.mul(this.getTexture(scope).a);
8471      } else {
8472        node = specularIntensityNode;
8473      }
8474    } else if (scope === _MaterialNode.SPECULAR_COLOR) {
8475      const specularColorNode = this.getColor(scope);
8476      if (material.specularColorMap && material.specularColorMap.isTexture === true) {
8477        node = specularColorNode.mul(this.getTexture(scope).rgb);
8478      } else {
8479        node = specularColorNode;
8480      }
8481    } else if (scope === _MaterialNode.ROUGHNESS) {
8482      const roughnessNode = this.getFloat(scope);
8483      if (material.roughnessMap && material.roughnessMap.isTexture === true) {
8484        node = roughnessNode.mul(this.getTexture(scope).g);
8485      } else {
8486        node = roughnessNode;
8487      }
8488    } else if (scope === _MaterialNode.METALNESS) {
8489      const metalnessNode = this.getFloat(scope);
8490      if (material.metalnessMap && material.metalnessMap.isTexture === true) {
8491        node = metalnessNode.mul(this.getTexture(scope).b);
8492      } else {
8493        node = metalnessNode;
8494      }
8495    } else if (scope === _MaterialNode.EMISSIVE) {
8496      const emissiveIntensityNode = this.getFloat("emissiveIntensity");
8497      const emissiveNode = this.getColor(scope).mul(emissiveIntensityNode);
8498      if (material.emissiveMap && material.emissiveMap.isTexture === true) {
8499        node = emissiveNode.mul(this.getTexture(scope));
8500      } else {
8501        node = emissiveNode;
8502      }
8503    } else if (scope === _MaterialNode.NORMAL) {
8504      if (material.normalMap) {
8505        node = normalMap(this.getTexture("normal"), this.getCache("normalScale", "vec2"));
8506        node.normalMapType = material.normalMapType;
8507        if (material.normalMap.format == RGFormat || material.normalMap.format == RED_GREEN_RGTC2_Format || material.normalMap.format == RG11_EAC_Format) {
8508          node.unpackNormalMode = NormalRGPacking;
8509        }
8510      } else if (material.bumpMap) {
8511        node = bumpMap(this.getTexture("bump").r, this.getFloat("bumpScale"));
8512      } else {
8513        node = normalView;
8514      }
8515    } else if (scope === _MaterialNode.CLEARCOAT) {
8516      const clearcoatNode = this.getFloat(scope);
8517      if (material.clearcoatMap && material.clearcoatMap.isTexture === true) {
8518        node = clearcoatNode.mul(this.getTexture(scope).r);
8519      } else {
8520        node = clearcoatNode;
8521      }
8522    } else if (scope === _MaterialNode.CLEARCOAT_ROUGHNESS) {
8523      const clearcoatRoughnessNode = this.getFloat(scope);
8524      if (material.clearcoatRoughnessMap && material.clearcoatRoughnessMap.isTexture === true) {
8525        node = clearcoatRoughnessNode.mul(this.getTexture(scope).r);
8526      } else {
8527        node = clearcoatRoughnessNode;
8528      }
8529    } else if (scope === _MaterialNode.CLEARCOAT_NORMAL) {
8530      if (material.clearcoatNormalMap) {
8531        node = normalMap(this.getTexture(scope), this.getCache(scope + "Scale", "vec2"));
8532      } else {
8533        node = normalView;
8534      }
8535    } else if (scope === _MaterialNode.SHEEN) {
8536      const sheenNode = this.getColor("sheenColor").mul(this.getFloat("sheen"));
8537      if (material.sheenColorMap && material.sheenColorMap.isTexture === true) {
8538        node = sheenNode.mul(this.getTexture("sheenColor").rgb);
8539      } else {
8540        node = sheenNode;
8541      }
8542    } else if (scope === _MaterialNode.SHEEN_ROUGHNESS) {
8543      const sheenRoughnessNode = this.getFloat(scope);
8544      if (material.sheenRoughnessMap && material.sheenRoughnessMap.isTexture === true) {
8545        node = sheenRoughnessNode.mul(this.getTexture(scope).a);
8546      } else {
8547        node = sheenRoughnessNode;
8548      }
8549      node = node.clamp(1e-4, 1);
8550    } else if (scope === _MaterialNode.ANISOTROPY) {
8551      if (material.anisotropyMap && material.anisotropyMap.isTexture === true) {
8552        const anisotropyPolar = this.getTexture(scope);
8553        const anisotropyMat = mat2(materialAnisotropyVector.x, materialAnisotropyVector.y, materialAnisotropyVector.y.negate(), materialAnisotropyVector.x);
8554        node = anisotropyMat.mul(anisotropyPolar.rg.mul(2).sub(vec2(1)).normalize().mul(anisotropyPolar.b));
8555      } else {
8556        node = materialAnisotropyVector;
8557      }
8558    } else if (scope === _MaterialNode.IRIDESCENCE_THICKNESS) {
8559      const iridescenceThicknessMaximum = reference("1", "float", material.iridescenceThicknessRange);
8560      if (material.iridescenceThicknessMap) {
8561        const iridescenceThicknessMinimum = reference("0", "float", material.iridescenceThicknessRange);
8562        node = iridescenceThicknessMaximum.sub(iridescenceThicknessMinimum).mul(this.getTexture(scope).g).add(iridescenceThicknessMinimum);
8563      } else {
8564        node = iridescenceThicknessMaximum;
8565      }
8566    } else if (scope === _MaterialNode.TRANSMISSION) {
8567      const transmissionNode = this.getFloat(scope);
8568      if (material.transmissionMap) {
8569        node = transmissionNode.mul(this.getTexture(scope).r);
8570      } else {
8571        node = transmissionNode;
8572      }
8573    } else if (scope === _MaterialNode.THICKNESS) {
8574      const thicknessNode = this.getFloat(scope);
8575      if (material.thicknessMap) {
8576        node = thicknessNode.mul(this.getTexture(scope).g);
8577      } else {
8578        node = thicknessNode;
8579      }
8580    } else if (scope === _MaterialNode.IOR) {
8581      node = this.getFloat(scope);
8582    } else if (scope === _MaterialNode.LIGHT_MAP) {
8583      node = this.getTexture(scope).rgb.mul(this.getFloat("lightMapIntensity"));
8584    } else if (scope === _MaterialNode.AO) {
8585      node = this.getTexture(scope).r.sub(1).mul(this.getFloat("aoMapIntensity")).add(1);
8586    } else if (scope === _MaterialNode.LINE_DASH_OFFSET) {
8587      node = material.dashOffset ? this.getFloat(scope) : float(0);
8588    } else {
8589      const outputType = this.getNodeType(builder);
8590      node = this.getCache(scope, outputType);
8591    }
8592    return node;
8593  }
8594};
8595MaterialNode.ALPHA_TEST = "alphaTest";
8596MaterialNode.COLOR = "color";
8597MaterialNode.OPACITY = "opacity";
8598MaterialNode.SHININESS = "shininess";
8599MaterialNode.SPECULAR = "specular";
8600MaterialNode.SPECULAR_STRENGTH = "specularStrength";
8601MaterialNode.SPECULAR_INTENSITY = "specularIntensity";
8602MaterialNode.SPECULAR_COLOR = "specularColor";
8603MaterialNode.REFLECTIVITY = "reflectivity";
8604MaterialNode.ROUGHNESS = "roughness";
8605MaterialNode.METALNESS = "metalness";
8606MaterialNode.NORMAL = "normal";
8607MaterialNode.CLEARCOAT = "clearcoat";
8608MaterialNode.CLEARCOAT_ROUGHNESS = "clearcoatRoughness";
8609MaterialNode.CLEARCOAT_NORMAL = "clearcoatNormal";
8610MaterialNode.EMISSIVE = "emissive";
8611MaterialNode.ROTATION = "rotation";
8612MaterialNode.SHEEN = "sheen";
8613MaterialNode.SHEEN_ROUGHNESS = "sheenRoughness";
8614MaterialNode.ANISOTROPY = "anisotropy";
8615MaterialNode.IRIDESCENCE = "iridescence";
8616MaterialNode.IRIDESCENCE_IOR = "iridescenceIOR";
8617MaterialNode.IRIDESCENCE_THICKNESS = "iridescenceThickness";
8618MaterialNode.IOR = "ior";
8619MaterialNode.TRANSMISSION = "transmission";
8620MaterialNode.THICKNESS = "thickness";
8621MaterialNode.ATTENUATION_DISTANCE = "attenuationDistance";
8622MaterialNode.ATTENUATION_COLOR = "attenuationColor";
8623MaterialNode.LINE_SCALE = "scale";
8624MaterialNode.LINE_DASH_SIZE = "dashSize";
8625MaterialNode.LINE_GAP_SIZE = "gapSize";
8626MaterialNode.LINE_WIDTH = "linewidth";
8627MaterialNode.LINE_DASH_OFFSET = "dashOffset";
8628MaterialNode.POINT_SIZE = "size";
8629MaterialNode.DISPERSION = "dispersion";
8630MaterialNode.LIGHT_MAP = "light";
8631MaterialNode.AO = "ao";
8632var materialAlphaTest = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.ALPHA_TEST);
8633var materialColor = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.COLOR);
8634var materialShininess = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.SHININESS);
8635var materialEmissive = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.EMISSIVE);
8636var materialOpacity = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.OPACITY);
8637var materialSpecular = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.SPECULAR);
8638var materialSpecularIntensity = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.SPECULAR_INTENSITY);
8639var materialSpecularColor = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.SPECULAR_COLOR);
8640var materialSpecularStrength = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.SPECULAR_STRENGTH);
8641var materialReflectivity = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.REFLECTIVITY);
8642var materialRoughness = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.ROUGHNESS);
8643var materialMetalness = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.METALNESS);
8644var materialNormal = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.NORMAL);
8645var materialClearcoat = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.CLEARCOAT);
8646var materialClearcoatRoughness = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.CLEARCOAT_ROUGHNESS);
8647var materialClearcoatNormal = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.CLEARCOAT_NORMAL);
8648var materialRotation = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.ROTATION);
8649var materialSheen = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.SHEEN);
8650var materialSheenRoughness = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.SHEEN_ROUGHNESS);
8651var materialAnisotropy = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.ANISOTROPY);
8652var materialIridescence = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.IRIDESCENCE);
8653var materialIridescenceIOR = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.IRIDESCENCE_IOR);
8654var materialIridescenceThickness = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS);
8655var materialTransmission = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.TRANSMISSION);
8656var materialThickness = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.THICKNESS);
8657var materialIOR = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.IOR);
8658var materialAttenuationDistance = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.ATTENUATION_DISTANCE);
8659var materialAttenuationColor = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.ATTENUATION_COLOR);
8660var materialLineScale = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.LINE_SCALE);
8661var materialLineDashSize = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.LINE_DASH_SIZE);
8662var materialLineGapSize = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.LINE_GAP_SIZE);
8663var materialLineWidth = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.LINE_WIDTH);
8664var materialLineDashOffset = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.LINE_DASH_OFFSET);
8665var materialPointSize = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.POINT_SIZE);
8666var materialDispersion = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.DISPERSION);
8667var materialLightMap = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.LIGHT_MAP);
8668var materialAO = /* @__PURE__ */ nodeImmutable(MaterialNode, MaterialNode.AO);
8669var materialAnisotropyVector = /* @__PURE__ */ uniform(new Vector2()).onReference(function(frame) {
8670  return frame.material;
8671}).onRenderUpdate(function({ material }) {
8672  this.value.set(material.anisotropy * Math.cos(material.anisotropyRotation), material.anisotropy * Math.sin(material.anisotropyRotation));
8673});
8674var modelViewProjection = /* @__PURE__ */ Fn((builder) => {
8675  return builder.context.setupModelViewProjection();
8676}, "vec4").once()().toVarying("v_modelViewProjection");
8677var StorageArrayElementNode = class extends ArrayElementNode {
8678  static get type() {
8679    return "StorageArrayElementNode";
8680  }
8681  /**
8682   * Constructs storage buffer element node.
8683   *
8684   * @param {StorageBufferNode} storageBufferNode - The storage buffer node.
8685   * @param {Node} indexNode - The index node that defines the element access.
8686   */
8687  constructor(storageBufferNode, indexNode) {
8688    super(storageBufferNode, indexNode);
8689    this.isStorageArrayElementNode = true;
8690  }
8691  /**
8692   * The storage buffer node.
8693   *
8694   * @param {Node} value
8695   * @type {StorageBufferNode}
8696   */
8697  set storageBufferNode(value) {
8698    this.node = value;
8699  }
8700  get storageBufferNode() {
8701    return this.node;
8702  }
8703  getMemberType(builder, name) {
8704    const structTypeNode = this.storageBufferNode.structTypeNode;
8705    if (structTypeNode) {
8706      return structTypeNode.getMemberType(builder, name);
8707    }
8708    return "void";
8709  }
8710  setup(builder) {
8711    if (builder.isAvailable("storageBuffer") === false) {
8712      if (this.node.isPBO === true) {
8713        builder.setupPBO(this.node);
8714      }
8715    }
8716    return super.setup(builder);
8717  }
8718  generate(builder, output3) {
8719    let snippet;
8720    const isAssignContext = builder.context.assign;
8721    if (builder.isAvailable("storageBuffer") === false) {
8722      if (this.node.isPBO === true && isAssignContext !== true && (this.node.value.isInstancedBufferAttribute || builder.shaderStage !== "compute")) {
8723        snippet = builder.generatePBO(this);
8724      } else {
8725        snippet = this.node.build(builder);
8726      }
8727    } else {
8728      snippet = super.generate(builder);
8729    }
8730    if (isAssignContext !== true) {
8731      const type = this.getNodeType(builder);
8732      snippet = builder.format(snippet, type, output3);
8733    }
8734    return snippet;
8735  }
8736};
8737var storageElement = /* @__PURE__ */ nodeProxy(StorageArrayElementNode).setParameterLength(2);
8738var StorageBufferNode = class extends BufferNode {
8739  static get type() {
8740    return "StorageBufferNode";
8741  }
8742  /**
8743   * Constructs a new storage buffer node.
8744   *
8745   * @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data.
8746   * @param {?(string|Struct)} [bufferType=null] - The buffer type (e.g. `'vec3'`).
8747   * @param {number} [bufferCount=0] - The buffer count.
8748   */
8749  constructor(value, bufferType = null, bufferCount = 0) {
8750    let nodeType, structTypeNode = null;
8751    if (bufferType && bufferType.isStruct) {
8752      nodeType = "struct";
8753      structTypeNode = bufferType.layout;
8754      if (value.isStorageBufferAttribute || value.isStorageInstancedBufferAttribute) {
8755        bufferCount = value.count;
8756      }
8757    } else if (bufferType === null && (value.isStorageBufferAttribute || value.isStorageInstancedBufferAttribute)) {
8758      nodeType = getTypeFromLength(value.itemSize);
8759      bufferCount = value.count;
8760    } else {
8761      nodeType = bufferType;
8762    }
8763    super(value, nodeType, bufferCount);
8764    this.isStorageBufferNode = true;
8765    this.structTypeNode = structTypeNode;
8766    this.access = NodeAccess.READ_WRITE;
8767    this.isAtomic = false;
8768    this.isPBO = false;
8769    this._attribute = null;
8770    this._varying = null;
8771    this.global = true;
8772    if (value.isStorageBufferAttribute !== true && value.isStorageInstancedBufferAttribute !== true) {
8773      if (value.isInstancedBufferAttribute) value.isStorageInstancedBufferAttribute = true;
8774      else value.isStorageBufferAttribute = true;
8775    }
8776  }
8777  /**
8778   * This method is overwritten since the buffer data might be shared
8779   * and thus the hash should be shared as well.
8780   *
8781   * @param {NodeBuilder} builder - The current node builder.
8782   * @return {string} The hash.
8783   */
8784  getHash(builder) {
8785    let id;
8786    if (this.bufferCount === 0) {
8787      let bufferData = builder.globalCache.getData(this.value);
8788      if (bufferData === void 0) {
8789        bufferData = {
8790          node: this
8791        };
8792        builder.globalCache.setData(this.value, bufferData);
8793      }
8794      id = bufferData.node.id;
8795    } else {
8796      id = this.id;
8797    }
8798    return String(id);
8799  }
8800  /**
8801   * Overwrites the default implementation to return a fixed value `'indirectStorageBuffer'` or `'storageBuffer'`.
8802   *
8803   * @param {NodeBuilder} builder - The current node builder.
8804   * @return {string} The input type.
8805   */
8806  getInputType() {
8807    return this.value.isIndirectStorageBufferAttribute ? "indirectStorageBuffer" : "storageBuffer";
8808  }
8809  /**
8810   * Enables element access with the given index node.
8811   *
8812   * @param {IndexNode} indexNode - The index node.
8813   * @return {StorageArrayElementNode} A node representing the element access.
8814   */
8815  element(indexNode) {
8816    return storageElement(this, indexNode);
8817  }
8818  /**
8819   * Defines whether this node is a PBO or not. Only relevant for WebGL.
8820   *
8821   * @param {boolean} value - The value so set.
8822   * @return {StorageBufferNode} A reference to this node.
8823   */
8824  setPBO(value) {
8825    this.isPBO = value;
8826    return this;
8827  }
8828  /**
8829   * Returns the `isPBO` value.
8830   *
8831   * @return {boolean} Whether the node represents a PBO or not.
8832   */
8833  getPBO() {
8834    return this.isPBO;
8835  }
8836  /**
8837   * Defines the node access.
8838   *
8839   * @param {string} value - The node access.
8840   * @return {StorageBufferNode} A reference to this node.
8841   */
8842  setAccess(value) {
8843    this.access = value;
8844    return this;
8845  }
8846  /**
8847   * Convenience method for configuring a read-only node access.
8848   *
8849   * @return {StorageBufferNode} A reference to this node.
8850   */
8851  toReadOnly() {
8852    return this.setAccess(NodeAccess.READ_ONLY);
8853  }
8854  /**
8855   * Defines whether the node is atomic or not.
8856   *
8857   * @param {boolean} value - The atomic flag.
8858   * @return {StorageBufferNode} A reference to this node.
8859   */
8860  setAtomic(value) {
8861    this.isAtomic = value;
8862    return this;
8863  }
8864  /**
8865   * Convenience method for making this node atomic.
8866   *
8867   * @return {StorageBufferNode} A reference to this node.
8868   */
8869  toAtomic() {
8870    return this.setAtomic(true);
8871  }
8872  /**
8873   * Returns attribute data for this storage buffer node.
8874   *
8875   * @return {{attribute: BufferAttributeNode, varying: VaryingNode}} The attribute data.
8876   */
8877  getAttributeData() {
8878    if (this._attribute === null) {
8879      this._attribute = bufferAttribute(this.value);
8880      this._varying = varying(this._attribute);
8881    }
8882    return {
8883      attribute: this._attribute,
8884      varying: this._varying
8885    };
8886  }
8887  /**
8888   * This method is overwritten since the node type from the availability of storage buffers
8889   * and the attribute data.
8890   *
8891   * @param {NodeBuilder} builder - The current node builder.
8892   * @return {string} The node type.
8893   */
8894  generateNodeType(builder) {
8895    if (this.structTypeNode !== null) {
8896      return this.structTypeNode.getNodeType(builder);
8897    }
8898    if (builder.isAvailable("storageBuffer") || builder.isAvailable("indirectStorageBuffer")) {
8899      return super.generateNodeType(builder);
8900    }
8901    const { attribute: attribute3 } = this.getAttributeData();
8902    return attribute3.getNodeType(builder);
8903  }
8904  /**
8905   * Returns the type of a member of the struct.
8906   *
8907   * @param {NodeBuilder} builder - The current node builder.
8908   * @param {string} name - The name of the member.
8909   * @return {string} The type of the member.
8910   */
8911  getMemberType(builder, name) {
8912    if (this.structTypeNode !== null) {
8913      return this.structTypeNode.getMemberType(builder, name);
8914    }
8915    return "void";
8916  }
8917  /**
8918   * Generates the code snippet of the storage buffer node.
8919   *
8920   * @param {NodeBuilder} builder - The current node builder.
8921   * @return {string} The generated code snippet.
8922   */
8923  generate(builder) {
8924    if (this.structTypeNode !== null) this.structTypeNode.build(builder);
8925    if (builder.isAvailable("storageBuffer") || builder.isAvailable("indirectStorageBuffer")) {
8926      return super.generate(builder);
8927    }
8928    const { attribute: attribute3, varying: varying3 } = this.getAttributeData();
8929    const output3 = varying3.build(builder);
8930    builder.registerTransform(output3, attribute3);
8931    return output3;
8932  }
8933};
8934var storage = (value, type = null, count = 0) => new StorageBufferNode(value, type, count);
8935var InstanceNode = class extends Node2 {
8936  static get type() {
8937    return "InstanceNode";
8938  }
8939  /**
8940   * Constructs a new instance node.
8941   *
8942   * @param {number} count - The number of instances.
8943   * @param {InstancedBufferAttribute|StorageInstancedBufferAttribute} instanceMatrix - Instanced buffer attribute representing the instance transformations.
8944   * @param {?InstancedBufferAttribute|StorageInstancedBufferAttribute} instanceColor - Instanced buffer attribute representing the instance colors.
8945   */
8946  constructor(count, instanceMatrix, instanceColor = null) {
8947    super("void");
8948    this.count = count;
8949    this.instanceMatrix = instanceMatrix;
8950    this.instanceColor = instanceColor;
8951    this.instanceMatrixNode = null;
8952    this.instanceColorNode = null;
8953    this.updateType = NodeUpdateType.FRAME;
8954    this.buffer = null;
8955    this.bufferColor = null;
8956    this.previousInstanceMatrixNode = null;
8957  }
8958  /**
8959   * Tracks whether the matrix data is provided via a storage buffer.
8960   *
8961   * @type {boolean}
8962   */
8963  get isStorageMatrix() {
8964    const { instanceMatrix } = this;
8965    return instanceMatrix && instanceMatrix.isStorageInstancedBufferAttribute === true;
8966  }
8967  /**
8968   * Tracks whether the color data is provided via a storage buffer.
8969   *
8970   * @type {boolean}
8971   */
8972  get isStorageColor() {
8973    const { instanceColor } = this;
8974    return instanceColor && instanceColor.isStorageInstancedBufferAttribute === true;
8975  }
8976  /**
8977   * Setups the internal buffers and nodes and assigns the transformed vertex data
8978   * to predefined node variables for accumulation. That follows the same patterns
8979   * like with morph and skinning nodes.
8980   *
8981   * @param {NodeBuilder} builder - The current node builder.
8982   */
8983  setup(builder) {
8984    let { instanceMatrixNode, instanceColorNode } = this;
8985    if (instanceMatrixNode === null) {
8986      instanceMatrixNode = this._createInstanceMatrixNode(true, builder);
8987      this.instanceMatrixNode = instanceMatrixNode;
8988    }
8989    const { instanceColor, isStorageColor } = this;
8990    if (instanceColor && instanceColorNode === null) {
8991      if (isStorageColor) {
8992        instanceColorNode = storage(instanceColor, "vec3", Math.max(instanceColor.count, 1)).element(instanceIndex);
8993      } else {
8994        const bufferAttribute3 = new InstancedBufferAttribute(instanceColor.array, 3);
8995        const bufferFn = instanceColor.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
8996        this.bufferColor = bufferAttribute3;
8997        instanceColorNode = vec3(bufferFn(bufferAttribute3, "vec3", 3, 0));
8998      }
8999      this.instanceColorNode = instanceColorNode;
9000    }
9001    const instancePosition = instanceMatrixNode.mul(positionLocal).xyz;
9002    positionLocal.assign(instancePosition);
9003    if (builder.needsPreviousData()) {
9004      positionPrevious.assign(this.getPreviousInstancedPosition(builder));
9005    }
9006    if (builder.hasGeometryAttribute("normal")) {
9007      const instanceNormal = transformNormal(normalLocal, instanceMatrixNode);
9008      normalLocal.assign(instanceNormal);
9009    }
9010    if (this.instanceColorNode !== null) {
9011      varyingProperty("vec3", "vInstanceColor").assign(this.instanceColorNode);
9012    }
9013  }
9014  /**
9015   * Checks if the internal buffers require an update.
9016   *
9017   * @param {NodeFrame} frame - The current node frame.
9018   */
9019  update(frame) {
9020    if (this.buffer !== null && this.isStorageMatrix !== true) {
9021      this.buffer.clearUpdateRanges();
9022      this.buffer.updateRanges.push(...this.instanceMatrix.updateRanges);
9023      if (this.instanceMatrix.version !== this.buffer.version) {
9024        this.buffer.version = this.instanceMatrix.version;
9025      }
9026    }
9027    if (this.instanceColor && this.bufferColor !== null && this.isStorageColor !== true) {
9028      this.bufferColor.clearUpdateRanges();
9029      this.bufferColor.updateRanges.push(...this.instanceColor.updateRanges);
9030      if (this.instanceColor.version !== this.bufferColor.version) {
9031        this.bufferColor.version = this.instanceColor.version;
9032      }
9033    }
9034    if (this.previousInstanceMatrixNode !== null) {
9035      frame.object.previousInstanceMatrix.array.set(this.instanceMatrix.array);
9036    }
9037  }
9038  /**
9039   * Computes the transformed/instanced vertex position of the previous frame.
9040   *
9041   * @param {NodeBuilder} builder - The current node builder.
9042   * @return {Node<vec3>} The instanced position from the previous frame.
9043   */
9044  getPreviousInstancedPosition(builder) {
9045    const instancedMesh3 = builder.object;
9046    if (this.previousInstanceMatrixNode === null) {
9047      instancedMesh3.previousInstanceMatrix = this.instanceMatrix.clone();
9048      this.previousInstanceMatrixNode = this._createInstanceMatrixNode(false, builder);
9049    }
9050    return this.previousInstanceMatrixNode.mul(positionPrevious).xyz;
9051  }
9052  /**
9053   * Creates a node representing the instance matrix data.
9054   *
9055   * @private
9056   * @param {boolean} assignBuffer - Whether the created interleaved buffer should be assigned to the `buffer` member or not.
9057   * @param {NodeBuilder} builder - A reference to the current node builder.
9058   * @return {Node} The instance matrix node.
9059   */
9060  _createInstanceMatrixNode(assignBuffer, builder) {
9061    let instanceMatrixNode;
9062    const { instanceMatrix } = this;
9063    const { count } = instanceMatrix;
9064    if (this.isStorageMatrix) {
9065      instanceMatrixNode = storage(instanceMatrix, "mat4", Math.max(count, 1)).element(instanceIndex);
9066    } else {
9067      const uniformBufferSize = count * 16 * 4;
9068      if (uniformBufferSize <= builder.getUniformBufferLimit()) {
9069        instanceMatrixNode = buffer(instanceMatrix.array, "mat4", Math.max(count, 1)).element(instanceIndex);
9070      } else {
9071        const interleaved = new InstancedInterleavedBuffer(instanceMatrix.array, 16, 1);
9072        if (assignBuffer === true) this.buffer = interleaved;
9073        const bufferFn = instanceMatrix.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
9074        const instanceBuffers = [
9075          bufferFn(interleaved, "vec4", 16, 0),
9076          bufferFn(interleaved, "vec4", 16, 4),
9077          bufferFn(interleaved, "vec4", 16, 8),
9078          bufferFn(interleaved, "vec4", 16, 12)
9079        ];
9080        instanceMatrixNode = mat4(...instanceBuffers);
9081      }
9082    }
9083    return instanceMatrixNode;
9084  }
9085};
9086var instance = /* @__PURE__ */ nodeProxy(InstanceNode).setParameterLength(2, 3);
9087var InstancedMeshNode = class extends InstanceNode {
9088  static get type() {
9089    return "InstancedMeshNode";
9090  }
9091  /**
9092   * Constructs a new instanced mesh node.
9093   *
9094   * @param {InstancedMesh} instancedMesh - The instanced mesh.
9095   */
9096  constructor(instancedMesh3) {
9097    const { count, instanceMatrix, instanceColor } = instancedMesh3;
9098    super(count, instanceMatrix, instanceColor);
9099    this.instancedMesh = instancedMesh3;
9100  }
9101};
9102var instancedMesh = /* @__PURE__ */ nodeProxy(InstancedMeshNode).setParameterLength(1);
9103var BatchNode = class extends Node2 {
9104  static get type() {
9105    return "BatchNode";
9106  }
9107  /**
9108   * Constructs a new batch node.
9109   *
9110   * @param {BatchedMesh} batchMesh - A reference to batched mesh.
9111   */
9112  constructor(batchMesh) {
9113    super("void");
9114    this.batchMesh = batchMesh;
9115    this.batchingIdNode = null;
9116  }
9117  /**
9118   * Setups the internal buffers and nodes and assigns the transformed vertex data
9119   * to predefined node variables for accumulation. That follows the same patterns
9120   * like with morph and skinning nodes.
9121   *
9122   * @param {NodeBuilder} builder - The current node builder.
9123   */
9124  setup(builder) {
9125    if (this.batchingIdNode === null) {
9126      if (builder.getDrawIndex() === null) {
9127        this.batchingIdNode = instanceIndex;
9128      } else {
9129        this.batchingIdNode = drawIndex;
9130      }
9131    }
9132    const getIndirectIndex = Fn(([id]) => {
9133      const size4 = int(textureSize(textureLoad(this.batchMesh._indirectTexture), 0).x).toConst();
9134      const x2 = int(id).mod(size4).toConst();
9135      const y2 = int(id).div(size4).toConst();
9136      return textureLoad(this.batchMesh._indirectTexture, ivec2(x2, y2)).x;
9137    }).setLayout({
9138      name: "getIndirectIndex",
9139      type: "uint",
9140      inputs: [
9141        { name: "id", type: "int" }
9142      ]
9143    });
9144    const indirectId = getIndirectIndex(int(this.batchingIdNode));
9145    const matricesTexture = this.batchMesh._matricesTexture;
9146    const size3 = int(textureSize(textureLoad(matricesTexture), 0).x).toConst();
9147    const j = float(indirectId).mul(4).toInt().toConst();
9148    const x = j.mod(size3).toConst();
9149    const y = j.div(size3).toConst();
9150    const batchingMatrix = mat4(
9151      textureLoad(matricesTexture, ivec2(x, y)),
9152      textureLoad(matricesTexture, ivec2(x.add(1), y)),
9153      textureLoad(matricesTexture, ivec2(x.add(2), y)),
9154      textureLoad(matricesTexture, ivec2(x.add(3), y))
9155    );
9156    const colorsTexture = this.batchMesh._colorsTexture;
9157    if (colorsTexture !== null) {
9158      const getBatchingColor = Fn(([id]) => {
9159        const size4 = int(textureSize(textureLoad(colorsTexture), 0).x).toConst();
9160        const j2 = id;
9161        const x2 = j2.mod(size4).toConst();
9162        const y2 = j2.div(size4).toConst();
9163        return textureLoad(colorsTexture, ivec2(x2, y2)).rgb;
9164      }).setLayout({
9165        name: "getBatchingColor",
9166        type: "vec3",
9167        inputs: [
9168          { name: "id", type: "int" }
9169        ]
9170      });
9171      const color3 = getBatchingColor(indirectId);
9172      varyingProperty("vec3", "vBatchColor").assign(color3);
9173    }
9174    const bm = mat3(batchingMatrix);
9175    positionLocal.assign(batchingMatrix.mul(positionLocal));
9176    const transformedNormal = normalLocal.div(vec3(bm[0].dot(bm[0]), bm[1].dot(bm[1]), bm[2].dot(bm[2])));
9177    const batchingNormal = bm.mul(transformedNormal).xyz;
9178    normalLocal.assign(batchingNormal);
9179    if (builder.hasGeometryAttribute("tangent")) {
9180      tangentLocal.mulAssign(bm);
9181    }
9182  }
9183};
9184var batch2 = /* @__PURE__ */ nodeProxy(BatchNode).setParameterLength(1);
9185var _frameId = /* @__PURE__ */ new WeakMap();
9186var SkinningNode = class extends Node2 {
9187  static get type() {
9188    return "SkinningNode";
9189  }
9190  /**
9191   * Constructs a new skinning node.
9192   *
9193   * @param {SkinnedMesh} skinnedMesh - The skinned mesh.
9194   */
9195  constructor(skinnedMesh) {
9196    super("void");
9197    this.skinnedMesh = skinnedMesh;
9198    this.updateType = NodeUpdateType.OBJECT;
9199    this.skinIndexNode = attribute("skinIndex", "uvec4");
9200    this.skinWeightNode = attribute("skinWeight", "vec4");
9201    this.bindMatrixNode = reference("bindMatrix", "mat4");
9202    this.bindMatrixInverseNode = reference("bindMatrixInverse", "mat4");
9203    this.boneMatricesNode = referenceBuffer("skeleton.boneMatrices", "mat4", skinnedMesh.skeleton.bones.length);
9204    this.positionNode = positionLocal;
9205    this.toPositionNode = positionLocal;
9206    this.previousBoneMatricesNode = null;
9207  }
9208  /**
9209   * Transforms the given vertex position via skinning.
9210   *
9211   * @param {Node} [boneMatrices=this.boneMatricesNode] - The bone matrices
9212   * @param {Node<vec3>} [position=this.positionNode] - The vertex position in local space.
9213   * @return {Node<vec3>} The transformed vertex position.
9214   */
9215  getSkinnedPosition(boneMatrices = this.boneMatricesNode, position = this.positionNode) {
9216    const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this;
9217    const boneMatX = boneMatrices.element(skinIndexNode.x);
9218    const boneMatY = boneMatrices.element(skinIndexNode.y);
9219    const boneMatZ = boneMatrices.element(skinIndexNode.z);
9220    const boneMatW = boneMatrices.element(skinIndexNode.w);
9221    const skinVertex = bindMatrixNode.mul(position);
9222    const skinned = add(
9223      boneMatX.mul(skinWeightNode.x).mul(skinVertex),
9224      boneMatY.mul(skinWeightNode.y).mul(skinVertex),
9225      boneMatZ.mul(skinWeightNode.z).mul(skinVertex),
9226      boneMatW.mul(skinWeightNode.w).mul(skinVertex)
9227    );
9228    return bindMatrixInverseNode.mul(skinned).xyz;
9229  }
9230  /**
9231   * Transforms the given vertex normal and tangent via skinning.
9232   *
9233   * @param {Node} [boneMatrices=this.boneMatricesNode] - The bone matrices
9234   * @param {Node<vec3>} [normal=normalLocal] - The vertex normal in local space.
9235   * @param {Node<vec3>} [tangent=tangentLocal] - The vertex tangent in local space.
9236   * @return {{skinNormal: Node<vec3>, skinTangent:Node<vec3>}} The transformed vertex normal and tangent.
9237   */
9238  getSkinnedNormalAndTangent(boneMatrices = this.boneMatricesNode, normal2 = normalLocal, tangent = tangentLocal) {
9239    const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this;
9240    const boneMatX = boneMatrices.element(skinIndexNode.x);
9241    const boneMatY = boneMatrices.element(skinIndexNode.y);
9242    const boneMatZ = boneMatrices.element(skinIndexNode.z);
9243    const boneMatW = boneMatrices.element(skinIndexNode.w);
9244    let skinMatrix = add(
9245      skinWeightNode.x.mul(boneMatX),
9246      skinWeightNode.y.mul(boneMatY),
9247      skinWeightNode.z.mul(boneMatZ),
9248      skinWeightNode.w.mul(boneMatW)
9249    );
9250    skinMatrix = bindMatrixInverseNode.mul(skinMatrix).mul(bindMatrixNode);
9251    const skinNormal = skinMatrix.transformDirection(normal2).xyz;
9252    const skinTangent = skinMatrix.transformDirection(tangent).xyz;
9253    return { skinNormal, skinTangent };
9254  }
9255  /**
9256   * Computes the transformed/skinned vertex position of the previous frame.
9257   *
9258   * @param {NodeBuilder} builder - The current node builder.
9259   * @return {Node<vec3>} The skinned position from the previous frame.
9260   */
9261  getPreviousSkinnedPosition(builder) {
9262    const skinnedMesh = builder.object;
9263    if (this.previousBoneMatricesNode === null) {
9264      skinnedMesh.skeleton.previousBoneMatrices = new Float32Array(skinnedMesh.skeleton.boneMatrices);
9265      this.previousBoneMatricesNode = referenceBuffer("skeleton.previousBoneMatrices", "mat4", skinnedMesh.skeleton.bones.length);
9266    }
9267    return this.getSkinnedPosition(this.previousBoneMatricesNode, positionPrevious);
9268  }
9269  /**
9270   * Setups the skinning node by assigning the transformed vertex data to predefined node variables.
9271   *
9272   * @param {NodeBuilder} builder - The current node builder.
9273   * @return {Node<vec3>} The transformed vertex position.
9274   */
9275  setup(builder) {
9276    if (builder.needsPreviousData()) {
9277      positionPrevious.assign(this.getPreviousSkinnedPosition(builder));
9278    }
9279    const skinPosition = this.getSkinnedPosition();
9280    if (this.toPositionNode) this.toPositionNode.assign(skinPosition);
9281    if (builder.hasGeometryAttribute("normal")) {
9282      const { skinNormal, skinTangent } = this.getSkinnedNormalAndTangent();
9283      normalLocal.assign(skinNormal);
9284      if (builder.hasGeometryAttribute("tangent")) {
9285        tangentLocal.assign(skinTangent);
9286      }
9287    }
9288    return skinPosition;
9289  }
9290  /**
9291   * Generates the code snippet of the skinning node.
9292   *
9293   * @param {NodeBuilder} builder - The current node builder.
9294   * @param {string} output - The current output.
9295   * @return {string} The generated code snippet.
9296   */
9297  generate(builder, output3) {
9298    if (output3 !== "void") {
9299      return super.generate(builder, output3);
9300    }
9301  }
9302  /**
9303   * Updates the state of the skinned mesh by updating the skeleton once per frame.
9304   *
9305   * @param {NodeFrame} frame - The current node frame.
9306   */
9307  update(frame) {
9308    const skeleton = frame.object && frame.object.skeleton ? frame.object.skeleton : this.skinnedMesh.skeleton;
9309    if (_frameId.get(skeleton) === frame.frameId) return;
9310    _frameId.set(skeleton, frame.frameId);
9311    if (this.previousBoneMatricesNode !== null) {
9312      if (skeleton.previousBoneMatrices === null) {
9313        skeleton.previousBoneMatrices = new Float32Array(skeleton.boneMatrices);
9314      }
9315      skeleton.previousBoneMatrices.set(skeleton.boneMatrices);
9316    }
9317    skeleton.update();
9318  }
9319};
9320var skinning = (skinnedMesh) => new SkinningNode(skinnedMesh);
9321var computeSkinning = (skinnedMesh, toPosition = null) => {
9322  const node = new SkinningNode(skinnedMesh);
9323  node.positionNode = storage(new InstancedBufferAttribute(skinnedMesh.geometry.getAttribute("position").array, 3), "vec3").setPBO(true).toReadOnly().element(instanceIndex).toVar();
9324  node.skinIndexNode = storage(new InstancedBufferAttribute(new Uint32Array(skinnedMesh.geometry.getAttribute("skinIndex").array), 4), "uvec4").setPBO(true).toReadOnly().element(instanceIndex).toVar();
9325  node.skinWeightNode = storage(new InstancedBufferAttribute(skinnedMesh.geometry.getAttribute("skinWeight").array, 4), "vec4").setPBO(true).toReadOnly().element(instanceIndex).toVar();
9326  node.bindMatrixNode = uniform(skinnedMesh.bindMatrix, "mat4");
9327  node.bindMatrixInverseNode = uniform(skinnedMesh.bindMatrixInverse, "mat4");
9328  node.boneMatricesNode = buffer(skinnedMesh.skeleton.boneMatrices, "mat4", skinnedMesh.skeleton.bones.length);
9329  node.toPositionNode = toPosition;
9330  return nodeObject(node);
9331};
9332var LoopNode = class extends Node2 {
9333  static get type() {
9334    return "LoopNode";
9335  }
9336  /**
9337   * Constructs a new loop node.
9338   *
9339   * @param {Array<any>} params - Depending on the loop type, array holds different parameterization values for the loop.
9340   */
9341  constructor(params = []) {
9342    super("void");
9343    this.params = params;
9344  }
9345  /**
9346   * Returns a loop variable name based on an index. The pattern is
9347   * `0` = `i`, `1`= `j`, `2`= `k` and so on.
9348   *
9349   * @param {number} index - The index.
9350   * @return {string} The loop variable name.
9351   */
9352  getVarName(index) {
9353    return String.fromCharCode("i".charCodeAt(0) + index);
9354  }
9355  /**
9356   * Returns properties about this node.
9357   *
9358   * @param {NodeBuilder} builder - The current node builder.
9359   * @return {Object} The node properties.
9360   */
9361  getProperties(builder) {
9362    const properties = builder.getNodeProperties(this);
9363    if (properties.stackNode !== void 0) return properties;
9364    const inputs = {};
9365    for (let i = 0, l = this.params.length - 1; i < l; i++) {
9366      const param = this.params[i];
9367      const name = param.isNode !== true && param.name || this.getVarName(i);
9368      const type = param.isNode !== true && param.type || "int";
9369      inputs[name] = expression(name, type);
9370    }
9371    const stack3 = builder.addStack();
9372    const fnCall = this.params[this.params.length - 1](inputs);
9373    properties.returnsNode = fnCall.context({ nodeLoop: fnCall });
9374    properties.stackNode = stack3;
9375    const baseParam = this.params[0];
9376    if (baseParam.isNode !== true && typeof baseParam.update === "function") {
9377      const fnUpdateCall = Fn(this.params[0].update)(inputs);
9378      properties.updateNode = fnUpdateCall.context({ nodeLoop: fnUpdateCall });
9379    }
9380    builder.removeStack();
9381    return properties;
9382  }
9383  setup(builder) {
9384    this.getProperties(builder);
9385    if (builder.fnCall) {
9386      const shaderNodeData = builder.getDataFromNode(builder.fnCall.shaderNode);
9387      shaderNodeData.hasLoop = true;
9388    }
9389  }
9390  generate(builder) {
9391    const properties = this.getProperties(builder);
9392    const params = this.params;
9393    const stackNode = properties.stackNode;
9394    for (let i = 0, l = params.length - 1; i < l; i++) {
9395      const param = params[i];
9396      let isWhile = false, start = null, end = null, name = null, type = null, condition = null, update = null;
9397      if (param.isNode) {
9398        if (param.getNodeType(builder) === "bool") {
9399          isWhile = true;
9400          type = "bool";
9401          end = param.build(builder, type);
9402        } else {
9403          type = "int";
9404          name = this.getVarName(i);
9405          start = "0";
9406          end = param.build(builder, type);
9407          condition = "<";
9408        }
9409      } else {
9410        type = param.type || "int";
9411        name = param.name || this.getVarName(i);
9412        start = param.start;
9413        end = param.end;
9414        condition = param.condition;
9415        update = param.update;
9416        if (typeof start === "number") start = builder.generateConst(type, start);
9417        else if (start && start.isNode) start = start.build(builder, type);
9418        if (typeof end === "number") end = builder.generateConst(type, end);
9419        else if (end && end.isNode) end = end.build(builder, type);
9420        if (start !== void 0 && end === void 0) {
9421          start = start + " - 1";
9422          end = "0";
9423          condition = ">=";
9424        } else if (end !== void 0 && start === void 0) {
9425          start = "0";
9426          condition = "<";
9427        }
9428        if (condition === void 0) {
9429          if (Number(start) > Number(end)) {
9430            condition = ">=";
9431          } else {
9432            condition = "<";
9433          }
9434        }
9435      }
9436      let loopSnippet;
9437      if (isWhile) {
9438        loopSnippet = `while ( ${end} )`;
9439      } else {
9440        const internalParam = { start, end };
9441        const startSnippet = internalParam.start;
9442        const endSnippet = internalParam.end;
9443        let updateSnippet;
9444        const deltaOperator = () => condition.includes("<") ? "+=" : "-=";
9445        if (update !== void 0 && update !== null) {
9446          switch (typeof update) {
9447            case "function":
9448              const flow = builder.flowStagesNode(properties.updateNode, "void");
9449              const snippet = flow.code.replace(/\t|;/g, "");
9450              updateSnippet = snippet;
9451              break;
9452            case "number":
9453              updateSnippet = name + " " + deltaOperator() + " " + builder.generateConst(type, update);
9454              break;
9455            case "string":
9456              updateSnippet = name + " " + update;
9457              break;
9458            default:
9459              if (update.isNode) {
9460                updateSnippet = name + " " + deltaOperator() + " " + update.build(builder);
9461              } else {
9462                error("TSL: 'Loop( { update: ... } )' is not a function, string or number.", this.stackTrace);
9463                updateSnippet = "break /* invalid update */";
9464              }
9465          }
9466        } else {
9467          if (type === "int" || type === "uint") {
9468            update = condition.includes("<") ? "++" : "--";
9469          } else {
9470            update = deltaOperator() + " 1.";
9471          }
9472          updateSnippet = name + " " + update;
9473        }
9474        const declarationSnippet = builder.getVar(type, name) + " = " + startSnippet;
9475        const conditionalSnippet = name + " " + condition + " " + endSnippet;
9476        loopSnippet = `for ( ${declarationSnippet}; ${conditionalSnippet}; ${updateSnippet} )`;
9477      }
9478      builder.addFlowCode((i === 0 ? "\n" : "") + builder.tab + loopSnippet + " {\n\n").addFlowTab();
9479    }
9480    const stackSnippet = stackNode.build(builder, "void");
9481    properties.returnsNode.build(builder, "void");
9482    builder.removeFlowTab().addFlowCode("\n" + builder.tab + stackSnippet);
9483    for (let i = 0, l = this.params.length - 1; i < l; i++) {
9484      builder.addFlowCode((i === 0 ? "" : builder.tab) + "}\n\n").removeFlowTab();
9485    }
9486    builder.addFlowTab();
9487  }
9488};
9489var Loop = (...params) => new LoopNode(nodeArray(params, "int")).toStack();
9490var Continue = () => expression("continue").toStack();
9491var Break = () => expression("break").toStack();
9492var _morphTextures = /* @__PURE__ */ new WeakMap();
9493var _morphVec4 = /* @__PURE__ */ new Vector4();
9494var getMorph = /* @__PURE__ */ Fn(({ bufferMap, influence, stride, width, depth: depth3, offset: offset3 }) => {
9495  const texelIndex = int(vertexIndex).mul(stride).add(offset3);
9496  const y = texelIndex.div(width);
9497  const x = texelIndex.sub(y.mul(width));
9498  const bufferAttrib = textureLoad(bufferMap, ivec2(x, y)).depth(depth3).xyz;
9499  return bufferAttrib.mul(influence);
9500});
9501function getEntry(geometry) {
9502  const hasMorphPosition = geometry.morphAttributes.position !== void 0;
9503  const hasMorphNormals = geometry.morphAttributes.normal !== void 0;
9504  const hasMorphColors = geometry.morphAttributes.color !== void 0;
9505  const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
9506  const morphTargetsCount = morphAttribute !== void 0 ? morphAttribute.length : 0;
9507  let entry = _morphTextures.get(geometry);
9508  if (entry === void 0 || entry.count !== morphTargetsCount) {
9509    let disposeTexture = function() {
9510      bufferTexture.dispose();
9511      _morphTextures.delete(geometry);
9512      geometry.removeEventListener("dispose", disposeTexture);
9513    };
9514    if (entry !== void 0) entry.texture.dispose();
9515    const morphTargets = geometry.morphAttributes.position || [];
9516    const morphNormals = geometry.morphAttributes.normal || [];
9517    const morphColors = geometry.morphAttributes.color || [];
9518    let vertexDataCount = 0;
9519    if (hasMorphPosition === true) vertexDataCount = 1;
9520    if (hasMorphNormals === true) vertexDataCount = 2;
9521    if (hasMorphColors === true) vertexDataCount = 3;
9522    let width = geometry.attributes.position.count * vertexDataCount;
9523    let height = 1;
9524    const maxTextureSize = 4096;
9525    if (width > maxTextureSize) {
9526      height = Math.ceil(width / maxTextureSize);
9527      width = maxTextureSize;
9528    }
9529    const buffer3 = new Float32Array(width * height * 4 * morphTargetsCount);
9530    const bufferTexture = new DataArrayTexture(buffer3, width, height, morphTargetsCount);
9531    bufferTexture.type = FloatType;
9532    bufferTexture.needsUpdate = true;
9533    const vertexDataStride = vertexDataCount * 4;
9534    for (let i = 0; i < morphTargetsCount; i++) {
9535      const morphTarget = morphTargets[i];
9536      const morphNormal = morphNormals[i];
9537      const morphColor = morphColors[i];
9538      const offset3 = width * height * 4 * i;
9539      for (let j = 0; j < morphTarget.count; j++) {
9540        const stride = j * vertexDataStride;
9541        if (hasMorphPosition === true) {
9542          _morphVec4.fromBufferAttribute(morphTarget, j);
9543          buffer3[offset3 + stride + 0] = _morphVec4.x;
9544          buffer3[offset3 + stride + 1] = _morphVec4.y;
9545          buffer3[offset3 + stride + 2] = _morphVec4.z;
9546          buffer3[offset3 + stride + 3] = 0;
9547        }
9548        if (hasMorphNormals === true) {
9549          _morphVec4.fromBufferAttribute(morphNormal, j);
9550          buffer3[offset3 + stride + 4] = _morphVec4.x;
9551          buffer3[offset3 + stride + 5] = _morphVec4.y;
9552          buffer3[offset3 + stride + 6] = _morphVec4.z;
9553          buffer3[offset3 + stride + 7] = 0;
9554        }
9555        if (hasMorphColors === true) {
9556          _morphVec4.fromBufferAttribute(morphColor, j);
9557          buffer3[offset3 + stride + 8] = _morphVec4.x;
9558          buffer3[offset3 + stride + 9] = _morphVec4.y;
9559          buffer3[offset3 + stride + 10] = _morphVec4.z;
9560          buffer3[offset3 + stride + 11] = morphColor.itemSize === 4 ? _morphVec4.w : 1;
9561        }
9562      }
9563    }
9564    entry = {
9565      count: morphTargetsCount,
9566      texture: bufferTexture,
9567      stride: vertexDataCount,
9568      size: new Vector2(width, height)
9569    };
9570    _morphTextures.set(geometry, entry);
9571    geometry.addEventListener("dispose", disposeTexture);
9572  }
9573  return entry;
9574}
9575var MorphNode = class extends Node2 {
9576  static get type() {
9577    return "MorphNode";
9578  }
9579  /**
9580   * Constructs a new morph node.
9581   *
9582   * @param {Mesh} mesh - The mesh holding the morph targets.
9583   */
9584  constructor(mesh) {
9585    super("void");
9586    this.mesh = mesh;
9587    this.morphBaseInfluence = uniform(1);
9588    this.updateType = NodeUpdateType.OBJECT;
9589  }
9590  /**
9591   * Setups the morph node by assigning the transformed vertex data to predefined node variables.
9592   *
9593   * @param {NodeBuilder} builder - The current node builder.
9594   */
9595  setup(builder) {
9596    const { geometry } = builder;
9597    const hasMorphPosition = geometry.morphAttributes.position !== void 0;
9598    const hasMorphNormals = geometry.hasAttribute("normal") && geometry.morphAttributes.normal !== void 0;
9599    const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
9600    const morphTargetsCount = morphAttribute !== void 0 ? morphAttribute.length : 0;
9601    const { texture: bufferMap, stride, size: size3 } = getEntry(geometry);
9602    if (hasMorphPosition === true) positionLocal.mulAssign(this.morphBaseInfluence);
9603    if (hasMorphNormals === true) normalLocal.mulAssign(this.morphBaseInfluence);
9604    const width = int(size3.width);
9605    Loop(morphTargetsCount, ({ i }) => {
9606      const influence = float(0).toVar();
9607      if (this.mesh.count > 1 && (this.mesh.morphTexture !== null && this.mesh.morphTexture !== void 0)) {
9608        influence.assign(textureLoad(this.mesh.morphTexture, ivec2(int(i).add(1), int(instanceIndex))).r);
9609      } else {
9610        influence.assign(reference("morphTargetInfluences", "float").element(i).toVar());
9611      }
9612      If(influence.notEqual(0), () => {
9613        if (hasMorphPosition === true) {
9614          positionLocal.addAssign(getMorph({
9615            bufferMap,
9616            influence,
9617            stride,
9618            width,
9619            depth: i,
9620            offset: int(0)
9621          }));
9622        }
9623        if (hasMorphNormals === true) {
9624          normalLocal.addAssign(getMorph({
9625            bufferMap,
9626            influence,
9627            stride,
9628            width,
9629            depth: i,
9630            offset: int(1)
9631          }));
9632        }
9633      });
9634    });
9635  }
9636  /**
9637   * Updates the state of the morphed mesh by updating the base influence.
9638   *
9639   * @param {NodeFrame} frame - The current node frame.
9640   */
9641  update() {
9642    const morphBaseInfluence = this.morphBaseInfluence;
9643    if (this.mesh.geometry.morphTargetsRelative) {
9644      morphBaseInfluence.value = 1;
9645    } else {
9646      morphBaseInfluence.value = 1 - this.mesh.morphTargetInfluences.reduce((a, b) => a + b, 0);
9647    }
9648  }
9649};
9650var morphReference = /* @__PURE__ */ nodeProxy(MorphNode).setParameterLength(1);
9651var LightingNode = class extends Node2 {
9652  static get type() {
9653    return "LightingNode";
9654  }
9655  /**
9656   * Constructs a new lighting node.
9657   */
9658  constructor() {
9659    super("vec3");
9660    this.isLightingNode = true;
9661  }
9662};
9663var AONode = class extends LightingNode {
9664  static get type() {
9665    return "AONode";
9666  }
9667  /**
9668   * Constructs a new AO node.
9669   *
9670   * @param {?Node<float>} [aoNode=null] - The ambient occlusion node.
9671   */
9672  constructor(aoNode = null) {
9673    super();
9674    this.aoNode = aoNode;
9675  }
9676  setup(builder) {
9677    builder.context.ambientOcclusion.mulAssign(this.aoNode);
9678  }
9679};
9680var LightingContextNode = class extends ContextNode {
9681  static get type() {
9682    return "LightingContextNode";
9683  }
9684  /**
9685   * Constructs a new lighting context node.
9686   *
9687   * @param {LightsNode} lightsNode - The lights node.
9688   * @param {?LightingModel} [lightingModel=null] - The current lighting model.
9689   * @param {?Node<vec3>} [backdropNode=null] - A backdrop node.
9690   * @param {?Node<float>} [backdropAlphaNode=null] - A backdrop alpha node.
9691   */
9692  constructor(lightsNode, lightingModel = null, backdropNode = null, backdropAlphaNode = null) {
9693    super(lightsNode);
9694    this.lightingModel = lightingModel;
9695    this.backdropNode = backdropNode;
9696    this.backdropAlphaNode = backdropAlphaNode;
9697    this._value = null;
9698  }
9699  /**
9700   * Returns a lighting context object.
9701   *
9702   * @return {{
9703   * radiance: Node<vec3>,
9704   * irradiance: Node<vec3>,
9705   * iblIrradiance: Node<vec3>,
9706   * ambientOcclusion: Node<float>,
9707   * reflectedLight: {directDiffuse: Node<vec3>, directSpecular: Node<vec3>, indirectDiffuse: Node<vec3>, indirectSpecular: Node<vec3>},
9708   * backdrop: Node<vec3>,
9709   * backdropAlpha: Node<float>
9710   * }} The lighting context object.
9711   */
9712  getContext() {
9713    const { backdropNode, backdropAlphaNode } = this;
9714    const directDiffuse = vec3().toVar("directDiffuse"), directSpecular = vec3().toVar("directSpecular"), indirectDiffuse = vec3().toVar("indirectDiffuse"), indirectSpecular = vec3().toVar("indirectSpecular");
9715    const reflectedLight = {
9716      directDiffuse,
9717      directSpecular,
9718      indirectDiffuse,
9719      indirectSpecular
9720    };
9721    const context3 = {
9722      radiance: vec3().toVar("radiance"),
9723      irradiance: vec3().toVar("irradiance"),
9724      iblIrradiance: vec3().toVar("iblIrradiance"),
9725      ambientOcclusion: float(1).toVar("ambientOcclusion"),
9726      reflectedLight,
9727      backdrop: backdropNode,
9728      backdropAlpha: backdropAlphaNode
9729    };
9730    return context3;
9731  }
9732  setup(builder) {
9733    this.value = this._value || (this._value = this.getContext());
9734    this.value.lightingModel = this.lightingModel || builder.context.lightingModel;
9735    return super.setup(builder);
9736  }
9737};
9738var lightingContext = /* @__PURE__ */ nodeProxy(LightingContextNode);
9739var IrradianceNode = class extends LightingNode {
9740  static get type() {
9741    return "IrradianceNode";
9742  }
9743  /**
9744   * Constructs a new irradiance node.
9745   *
9746   * @param {Node<vec3>} node - A node contributing irradiance.
9747   */
9748  constructor(node) {
9749    super();
9750    this.node = node;
9751  }
9752  setup(builder) {
9753    builder.context.irradiance.addAssign(this.node);
9754  }
9755};
9756var _size$5 = /* @__PURE__ */ new Vector2();
9757var ViewportTextureNode = class extends TextureNode {
9758  static get type() {
9759    return "ViewportTextureNode";
9760  }
9761  /**
9762   * Constructs a new viewport texture node.
9763   *
9764   * @param {Node} [uvNode=screenUV] - The uv node.
9765   * @param {?Node} [levelNode=null] - The level node.
9766   * @param {?Texture} [framebufferTexture=null] - A framebuffer texture holding the viewport data. If not provided, a framebuffer texture is created automatically.
9767   */
9768  constructor(uvNode = screenUV, levelNode = null, framebufferTexture = null) {
9769    let defaultFramebuffer = null;
9770    if (framebufferTexture === null) {
9771      defaultFramebuffer = new FramebufferTexture();
9772      defaultFramebuffer.minFilter = LinearMipmapLinearFilter;
9773      framebufferTexture = defaultFramebuffer;
9774    } else {
9775      defaultFramebuffer = framebufferTexture;
9776    }
9777    super(framebufferTexture, uvNode, levelNode);
9778    this.generateMipmaps = false;
9779    this.defaultFramebuffer = defaultFramebuffer;
9780    this.isOutputTextureNode = true;
9781    this.updateBeforeType = NodeUpdateType.RENDER;
9782    this._cacheTextures = /* @__PURE__ */ new WeakMap();
9783  }
9784  /**
9785   * This methods returns a texture for the given render target or canvas target reference.
9786   *
9787   * To avoid rendering errors, `ViewportTextureNode` must use unique framebuffer textures
9788   * for different render contexts.
9789   *
9790   * @param {?(RenderTarget|CanvasTarget)} [reference=null] - The render target or canvas target reference.
9791   * @return {Texture} The framebuffer texture.
9792   */
9793  getTextureForReference(reference3 = null) {
9794    let defaultFramebuffer;
9795    let cacheTextures;
9796    if (this.referenceNode) {
9797      defaultFramebuffer = this.referenceNode.defaultFramebuffer;
9798      cacheTextures = this.referenceNode._cacheTextures;
9799    } else {
9800      defaultFramebuffer = this.defaultFramebuffer;
9801      cacheTextures = this._cacheTextures;
9802    }
9803    if (reference3 === null) {
9804      return defaultFramebuffer;
9805    }
9806    if (cacheTextures.has(reference3) === false) {
9807      const framebufferTexture = defaultFramebuffer.clone();
9808      cacheTextures.set(reference3, framebufferTexture);
9809    }
9810    return cacheTextures.get(reference3);
9811  }
9812  updateReference(frame) {
9813    const renderer = frame.renderer;
9814    const renderTarget = renderer.getRenderTarget();
9815    const canvasTarget = renderer.getCanvasTarget();
9816    const reference3 = renderTarget ? renderTarget : canvasTarget;
9817    this.value = this.getTextureForReference(reference3);
9818    return this.value;
9819  }
9820  updateBefore(frame) {
9821    const renderer = frame.renderer;
9822    const renderTarget = renderer.getRenderTarget();
9823    const canvasTarget = renderer.getCanvasTarget();
9824    const reference3 = renderTarget ? renderTarget : canvasTarget;
9825    if (reference3 === null) {
9826      renderer.getDrawingBufferSize(_size$5);
9827    } else if (reference3.getDrawingBufferSize) {
9828      reference3.getDrawingBufferSize(_size$5);
9829    } else {
9830      _size$5.set(reference3.width, reference3.height);
9831    }
9832    const framebufferTexture = this.getTextureForReference(reference3);
9833    if (framebufferTexture.image.width !== _size$5.width || framebufferTexture.image.height !== _size$5.height) {
9834      framebufferTexture.image.width = _size$5.width;
9835      framebufferTexture.image.height = _size$5.height;
9836      framebufferTexture.needsUpdate = true;
9837    }
9838    const currentGenerateMipmaps = framebufferTexture.generateMipmaps;
9839    framebufferTexture.generateMipmaps = this.generateMipmaps;
9840    renderer.copyFramebufferToTexture(framebufferTexture);
9841    framebufferTexture.generateMipmaps = currentGenerateMipmaps;
9842  }
9843  clone() {
9844    const viewportTextureNode = new this.constructor(this.uvNode, this.levelNode, this.value);
9845    viewportTextureNode.generateMipmaps = this.generateMipmaps;
9846    return viewportTextureNode;
9847  }
9848};
9849var viewportTexture = /* @__PURE__ */ nodeProxy(ViewportTextureNode).setParameterLength(0, 3);
9850var viewportMipTexture = /* @__PURE__ */ nodeProxy(ViewportTextureNode, null, null, { generateMipmaps: true }).setParameterLength(0, 3);
9851var _singletonOpaqueViewportTextureNode = /* @__PURE__ */ viewportMipTexture();
9852var viewportOpaqueMipTexture = (uv3 = screenUV, level = null) => _singletonOpaqueViewportTextureNode.sample(uv3, level);
9853var _sharedDepthbuffer = null;
9854var ViewportDepthTextureNode = class extends ViewportTextureNode {
9855  static get type() {
9856    return "ViewportDepthTextureNode";
9857  }
9858  /**
9859   * Constructs a new viewport depth texture node.
9860   *
9861   * @param {Node} [uvNode=screenUV] - The uv node.
9862   * @param {?Node} [levelNode=null] - The level node.
9863   * @param {?DepthTexture} [depthTexture=null] - A depth texture. If not provided, uses a shared depth texture.
9864   */
9865  constructor(uvNode = screenUV, levelNode = null, depthTexture = null) {
9866    if (depthTexture === null) {
9867      if (_sharedDepthbuffer === null) {
9868        _sharedDepthbuffer = new DepthTexture();
9869      }
9870      depthTexture = _sharedDepthbuffer;
9871    }
9872    super(uvNode, levelNode, depthTexture);
9873  }
9874};
9875var viewportDepthTexture = /* @__PURE__ */ nodeProxy(ViewportDepthTextureNode).setParameterLength(0, 3);
9876var ViewportDepthNode = class _ViewportDepthNode extends Node2 {
9877  static get type() {
9878    return "ViewportDepthNode";
9879  }
9880  /**
9881   * Constructs a new viewport depth node.
9882   *
9883   * @param {('depth'|'depthBase'|'linearDepth')} scope - The node's scope.
9884   * @param {?Node} [valueNode=null] - The value node.
9885   */
9886  constructor(scope, valueNode = null) {
9887    super("float");
9888    this.scope = scope;
9889    this.valueNode = valueNode;
9890    this.isViewportDepthNode = true;
9891  }
9892  generate(builder) {
9893    const { scope } = this;
9894    if (scope === _ViewportDepthNode.DEPTH_BASE) {
9895      return builder.getFragDepth();
9896    }
9897    return super.generate(builder);
9898  }
9899  setup({ camera }) {
9900    const { scope } = this;
9901    const value = this.valueNode;
9902    let node = null;
9903    if (scope === _ViewportDepthNode.DEPTH_BASE) {
9904      if (value !== null) {
9905        node = depthBase().assign(value);
9906      }
9907    } else if (scope === _ViewportDepthNode.DEPTH) {
9908      if (camera.isPerspectiveCamera) {
9909        node = viewZToPerspectiveDepth(positionView.z, cameraNear, cameraFar);
9910      } else {
9911        node = viewZToOrthographicDepth(positionView.z, cameraNear, cameraFar);
9912      }
9913    } else if (scope === _ViewportDepthNode.LINEAR_DEPTH) {
9914      if (value !== null) {
9915        if (camera.isPerspectiveCamera) {
9916          const viewZ = perspectiveDepthToViewZ(value, cameraNear, cameraFar);
9917          node = viewZToOrthographicDepth(viewZ, cameraNear, cameraFar);
9918        } else {
9919          node = value;
9920        }
9921      } else {
9922        node = viewZToOrthographicDepth(positionView.z, cameraNear, cameraFar);
9923      }
9924    }
9925    return node;
9926  }
9927};
9928ViewportDepthNode.DEPTH_BASE = "depthBase";
9929ViewportDepthNode.DEPTH = "depth";
9930ViewportDepthNode.LINEAR_DEPTH = "linearDepth";
9931var viewZToOrthographicDepth = (viewZ, near, far) => viewZ.add(near).div(near.sub(far));
9932var viewZToReversedOrthographicDepth = (viewZ, near, far) => viewZ.add(far).div(far.sub(near));
9933var orthographicDepthToViewZ = /* @__PURE__ */ Fn(([depth3, near, far], builder) => {
9934  if (builder.renderer.reversedDepthBuffer === true) {
9935    return far.sub(near).mul(depth3).sub(far);
9936  } else {
9937    return near.sub(far).mul(depth3).sub(near);
9938  }
9939});
9940var viewZToPerspectiveDepth = (viewZ, near, far) => near.add(viewZ).mul(far).div(far.sub(near).mul(viewZ));
9941var viewZToReversedPerspectiveDepth = (viewZ, near, far) => near.mul(viewZ.add(far)).div(viewZ.mul(near.sub(far)));
9942var perspectiveDepthToViewZ = /* @__PURE__ */ Fn(([depth3, near, far], builder) => {
9943  if (builder.renderer.reversedDepthBuffer === true) {
9944    return near.mul(far).div(near.sub(far).mul(depth3).sub(near));
9945  } else {
9946    return near.mul(far).div(far.sub(near).mul(depth3).sub(far));
9947  }
9948});
9949var viewZToLogarithmicDepth = (viewZ, near, far) => {
9950  near = near.max(1e-6).toVar();
9951  const numerator = log22(viewZ.negate().div(near));
9952  const denominator = log22(far.div(near));
9953  return numerator.div(denominator);
9954};
9955var logarithmicDepthToViewZ = (depth3, near, far) => {
9956  const exponent = depth3.mul(log2(far.div(near)));
9957  return float(Math.E).pow(exponent).mul(near).negate();
9958};
9959var depthBase = /* @__PURE__ */ nodeProxy(ViewportDepthNode, ViewportDepthNode.DEPTH_BASE);
9960var depth = /* @__PURE__ */ nodeImmutable(ViewportDepthNode, ViewportDepthNode.DEPTH);
9961var linearDepth = /* @__PURE__ */ nodeProxy(ViewportDepthNode, ViewportDepthNode.LINEAR_DEPTH).setParameterLength(0, 1);
9962var viewportLinearDepth = /* @__PURE__ */ linearDepth(viewportDepthTexture());
9963depth.assign = (value) => depthBase(value);
9964var ClippingNode = class _ClippingNode extends Node2 {
9965  static get type() {
9966    return "ClippingNode";
9967  }
9968  /**
9969   * Constructs a new clipping node.
9970   *
9971   * @param {('default'|'hardware'|'alphaToCoverage')} [scope='default'] - The node's scope. Similar to other nodes,
9972   * the selected scope influences the behavior of the node and what type of code is generated.
9973   */
9974  constructor(scope = _ClippingNode.DEFAULT) {
9975    super();
9976    this.scope = scope;
9977  }
9978  /**
9979   * Setups the node depending on the selected scope.
9980   *
9981   * @param {NodeBuilder} builder - The current node builder.
9982   * @return {Node} The result node.
9983   */
9984  setup(builder) {
9985    super.setup(builder);
9986    const clippingContext = builder.clippingContext;
9987    const { intersectionPlanes, unionPlanes } = clippingContext;
9988    this.hardwareClipping = builder.material.hardwareClipping;
9989    if (this.scope === _ClippingNode.ALPHA_TO_COVERAGE) {
9990      return this.setupAlphaToCoverage(intersectionPlanes, unionPlanes);
9991    } else if (this.scope === _ClippingNode.HARDWARE) {
9992      return this.setupHardwareClipping(unionPlanes, builder);
9993    } else {
9994      return this.setupDefault(intersectionPlanes, unionPlanes);
9995    }
9996  }
9997  /**
9998   * Setups alpha to coverage.
9999   *
10000   * @param {Array<Vector4>} intersectionPlanes - The intersection planes.
10001   * @param {Array<Vector4>} unionPlanes - The union planes.
10002   * @return {Node} The result node.
10003   */
10004  setupAlphaToCoverage(intersectionPlanes, unionPlanes) {
10005    return Fn(() => {
10006      const distanceToPlane = float().toVar("distanceToPlane");
10007      const distanceGradient = float().toVar("distanceToGradient");
10008      const clipOpacity = float(1).toVar("clipOpacity");
10009      const numUnionPlanes = unionPlanes.length;
10010      if (this.hardwareClipping === false && numUnionPlanes > 0) {
10011        const clippingPlanes = uniformArray(unionPlanes).setGroup(renderGroup);
10012        Loop(numUnionPlanes, ({ i }) => {
10013          const plane = clippingPlanes.element(i);
10014          distanceToPlane.assign(positionView.dot(plane.xyz).negate().add(plane.w));
10015          distanceGradient.assign(distanceToPlane.fwidth().div(2));
10016          clipOpacity.mulAssign(smoothstep(distanceGradient.negate(), distanceGradient, distanceToPlane));
10017        });
10018      }
10019      const numIntersectionPlanes = intersectionPlanes.length;
10020      if (numIntersectionPlanes > 0) {
10021        const clippingPlanes = uniformArray(intersectionPlanes).setGroup(renderGroup);
10022        const intersectionClipOpacity = float(1).toVar("intersectionClipOpacity");
10023        Loop(numIntersectionPlanes, ({ i }) => {
10024          const plane = clippingPlanes.element(i);
10025          distanceToPlane.assign(positionView.dot(plane.xyz).negate().add(plane.w));
10026          distanceGradient.assign(distanceToPlane.fwidth().div(2));
10027          intersectionClipOpacity.mulAssign(smoothstep(distanceGradient.negate(), distanceGradient, distanceToPlane).oneMinus());
10028        });
10029        clipOpacity.mulAssign(intersectionClipOpacity.oneMinus());
10030      }
10031      diffuseColor.a.mulAssign(clipOpacity);
10032      diffuseColor.a.equal(0).discard();
10033    })();
10034  }
10035  /**
10036   * Setups the default clipping.
10037   *
10038   * @param {Array<Vector4>} intersectionPlanes - The intersection planes.
10039   * @param {Array<Vector4>} unionPlanes - The union planes.
10040   * @return {Node} The result node.
10041   */
10042  setupDefault(intersectionPlanes, unionPlanes) {
10043    return Fn(() => {
10044      const numUnionPlanes = unionPlanes.length;
10045      if (this.hardwareClipping === false && numUnionPlanes > 0) {
10046        const clippingPlanes = uniformArray(unionPlanes).setGroup(renderGroup);
10047        Loop(numUnionPlanes, ({ i }) => {
10048          const plane = clippingPlanes.element(i);
10049          positionView.dot(plane.xyz).greaterThan(plane.w).discard();
10050        });
10051      }
10052      const numIntersectionPlanes = intersectionPlanes.length;
10053      if (numIntersectionPlanes > 0) {
10054        const clippingPlanes = uniformArray(intersectionPlanes).setGroup(renderGroup);
10055        const clipped = bool(true).toVar("clipped");
10056        Loop(numIntersectionPlanes, ({ i }) => {
10057          const plane = clippingPlanes.element(i);
10058          clipped.assign(positionView.dot(plane.xyz).greaterThan(plane.w).and(clipped));
10059        });
10060        clipped.discard();
10061      }
10062    })();
10063  }
10064  /**
10065   * Setups hardware clipping.
10066   *
10067   * @param {Array<Vector4>} unionPlanes - The union planes.
10068   * @param {NodeBuilder} builder - The current node builder.
10069   * @return {Node} The result node.
10070   */
10071  setupHardwareClipping(unionPlanes, builder) {
10072    const numUnionPlanes = unionPlanes.length;
10073    builder.enableHardwareClipping(numUnionPlanes);
10074    return Fn(() => {
10075      const clippingPlanes = uniformArray(unionPlanes).setGroup(renderGroup);
10076      const hw_clip_distances = builtin(builder.getClipDistance());
10077      Loop(numUnionPlanes, ({ i }) => {
10078        const plane = clippingPlanes.element(i);
10079        const distance3 = positionView.dot(plane.xyz).sub(plane.w).negate();
10080        hw_clip_distances.element(i).assign(distance3);
10081      });
10082    })();
10083  }
10084};
10085ClippingNode.ALPHA_TO_COVERAGE = "alphaToCoverage";
10086ClippingNode.DEFAULT = "default";
10087ClippingNode.HARDWARE = "hardware";
10088var clipping = () => new ClippingNode();
10089var clippingAlpha = () => new ClippingNode(ClippingNode.ALPHA_TO_COVERAGE);
10090var hardwareClipping = () => new ClippingNode(ClippingNode.HARDWARE);
10091var ALPHA_HASH_SCALE = 0.05;
10092var hash2D = /* @__PURE__ */ Fn(([value]) => {
10093  return fract(mul(1e4, sin(mul(17, value.x).add(mul(0.1, value.y)))).mul(add(0.1, abs(sin(mul(13, value.y).add(value.x))))));
10094});
10095var hash3D = /* @__PURE__ */ Fn(([value]) => {
10096  return hash2D(vec2(hash2D(value.xy), value.z));
10097});
10098var getAlphaHashThreshold = /* @__PURE__ */ Fn(([position]) => {
10099  const maxDeriv = max$1(
10100    length(dFdx(position.xyz)),
10101    length(dFdy(position.xyz))
10102  );
10103  const pixScale = float(1).div(float(ALPHA_HASH_SCALE).mul(maxDeriv)).toVar("pixScale");
10104  const pixScales = vec2(
10105    exp2(floor(log22(pixScale))),
10106    exp2(ceil(log22(pixScale)))
10107  );
10108  const alpha = vec2(
10109    hash3D(floor(pixScales.x.mul(position.xyz))),
10110    hash3D(floor(pixScales.y.mul(position.xyz)))
10111  );
10112  const lerpFactor = fract(log22(pixScale));
10113  const x = add(mul(lerpFactor.oneMinus(), alpha.x), mul(lerpFactor, alpha.y));
10114  const a = min$1(lerpFactor, lerpFactor.oneMinus());
10115  const cases = vec3(
10116    x.mul(x).div(mul(2, a).mul(sub(1, a))),
10117    x.sub(mul(0.5, a)).div(sub(1, a)),
10118    sub(1, sub(1, x).mul(sub(1, x)).div(mul(2, a).mul(sub(1, a))))
10119  );
10120  const threshold = x.lessThan(a.oneMinus()).select(x.lessThan(a).select(cases.x, cases.y), cases.z);
10121  return clamp(threshold, 1e-6, 1);
10122}).setLayout({
10123  name: "getAlphaHashThreshold",
10124  type: "float",
10125  inputs: [
10126    { name: "position", type: "vec3" }
10127  ]
10128});
10129var VertexColorNode = class extends AttributeNode {
10130  static get type() {
10131    return "VertexColorNode";
10132  }
10133  /**
10134   * Constructs a new vertex color node.
10135   *
10136   * @param {number} index - The attribute index.
10137   */
10138  constructor(index) {
10139    super(null, "vec4");
10140    this.isVertexColorNode = true;
10141    this.index = index;
10142  }
10143  /**
10144   * Overwrites the default implementation by honoring the attribute index.
10145   *
10146   * @param {NodeBuilder} builder - The current node builder.
10147   * @return {string} The attribute name.
10148   */
10149  getAttributeName() {
10150    const index = this.index;
10151    return "color" + (index > 0 ? index : "");
10152  }
10153  generate(builder) {
10154    const attributeName = this.getAttributeName(builder);
10155    const geometryAttribute = builder.hasGeometryAttribute(attributeName);
10156    let result;
10157    if (geometryAttribute === true) {
10158      result = super.generate(builder);
10159    } else {
10160      result = builder.generateConst(this.nodeType, new Vector4(1, 1, 1, 1));
10161    }
10162    return result;
10163  }
10164  serialize(data) {
10165    super.serialize(data);
10166    data.index = this.index;
10167  }
10168  deserialize(data) {
10169    super.deserialize(data);
10170    this.index = data.index;
10171  }
10172};
10173var vertexColor = (index = 0) => new VertexColorNode(index);
10174var blendBurn = /* @__PURE__ */ Fn(([base, blend]) => {
10175  return min$1(1, base.oneMinus().div(blend)).oneMinus();
10176}).setLayout({
10177  name: "blendBurn",
10178  type: "vec3",
10179  inputs: [
10180    { name: "base", type: "vec3" },
10181    { name: "blend", type: "vec3" }
10182  ]
10183});
10184var blendDodge = /* @__PURE__ */ Fn(([base, blend]) => {
10185  return min$1(base.div(blend.oneMinus()), 1);
10186}).setLayout({
10187  name: "blendDodge",
10188  type: "vec3",
10189  inputs: [
10190    { name: "base", type: "vec3" },
10191    { name: "blend", type: "vec3" }
10192  ]
10193});
10194var blendScreen = /* @__PURE__ */ Fn(([base, blend]) => {
10195  return base.oneMinus().mul(blend.oneMinus()).oneMinus();
10196}).setLayout({
10197  name: "blendScreen",
10198  type: "vec3",
10199  inputs: [
10200    { name: "base", type: "vec3" },
10201    { name: "blend", type: "vec3" }
10202  ]
10203});
10204var blendOverlay = /* @__PURE__ */ Fn(([base, blend]) => {
10205  return mix(base.mul(2).mul(blend), base.oneMinus().mul(2).mul(blend.oneMinus()).oneMinus(), step(0.5, base));
10206}).setLayout({
10207  name: "blendOverlay",
10208  type: "vec3",
10209  inputs: [
10210    { name: "base", type: "vec3" },
10211    { name: "blend", type: "vec3" }
10212  ]
10213});
10214var blendColor = /* @__PURE__ */ Fn(([base, blend]) => {
10215  const outAlpha = blend.a.add(base.a.mul(blend.a.oneMinus()));
10216  return vec4(blend.rgb.mul(blend.a).add(base.rgb.mul(base.a).mul(blend.a.oneMinus())).div(outAlpha), outAlpha);
10217}).setLayout({
10218  name: "blendColor",
10219  type: "vec4",
10220  inputs: [
10221    { name: "base", type: "vec4" },
10222    { name: "blend", type: "vec4" }
10223  ]
10224});
10225var premultiplyAlpha = /* @__PURE__ */ Fn(([color3]) => {
10226  return vec4(color3.rgb.mul(color3.a), color3.a);
10227}, { color: "vec4", return: "vec4" });
10228var unpremultiplyAlpha = /* @__PURE__ */ Fn(([color3]) => {
10229  If(color3.a.equal(0), () => vec4(0));
10230  return vec4(color3.rgb.div(color3.a), color3.a);
10231}, { color: "vec4", return: "vec4" });
10232var NodeMaterial = class extends Material {
10233  static get type() {
10234    return "NodeMaterial";
10235  }
10236  /**
10237   * Represents the type of the node material.
10238   *
10239   * @type {string}
10240   */
10241  get type() {
10242    return this.constructor.type;
10243  }
10244  set type(_value) {
10245  }
10246  /**
10247   * Constructs a new node material.
10248   */
10249  constructor() {
10250    super();
10251    this.isNodeMaterial = true;
10252    this.fog = true;
10253    this.lights = false;
10254    this.hardwareClipping = false;
10255    this.lightsNode = null;
10256    this.envNode = null;
10257    this.aoNode = null;
10258    this.colorNode = null;
10259    this.normalNode = null;
10260    this.opacityNode = null;
10261    this.backdropNode = null;
10262    this.backdropAlphaNode = null;
10263    this.alphaTestNode = null;
10264    this.maskNode = null;
10265    this.maskShadowNode = null;
10266    this.positionNode = null;
10267    this.geometryNode = null;
10268    this.depthNode = null;
10269    this.receivedShadowPositionNode = null;
10270    this.castShadowPositionNode = null;
10271    this.receivedShadowNode = null;
10272    this.castShadowNode = null;
10273    this.outputNode = null;
10274    this.mrtNode = null;
10275    this.fragmentNode = null;
10276    this.vertexNode = null;
10277    this.contextNode = null;
10278  }
10279  /**
10280   * Returns an array of child nodes for this material.
10281   *
10282   * @private
10283   * @returns {Array<{property: string, childNode: Node}>}
10284   */
10285  _getNodeChildren() {
10286    const children2 = [];
10287    for (const property3 of Object.getOwnPropertyNames(this)) {
10288      if (property3.startsWith("_") === true) continue;
10289      const object = this[property3];
10290      if (object && object.isNode === true) {
10291        children2.push({ property: property3, childNode: object });
10292      }
10293    }
10294    return children2;
10295  }
10296  /**
10297   * Allows to define a custom cache key that influence the material key computation
10298   * for render objects.
10299   *
10300   * @return {string} The custom cache key.
10301   */
10302  customProgramCacheKey() {
10303    const values = [];
10304    for (const { property: property3, childNode } of this._getNodeChildren()) {
10305      values.push(hashString(property3.slice(0, -4)), childNode.getCacheKey());
10306    }
10307    return this.type + hashArray(values);
10308  }
10309  /**
10310   * Builds this material with the given node builder.
10311   *
10312   * @param {NodeBuilder} builder - The current node builder.
10313   */
10314  build(builder) {
10315    this.setup(builder);
10316  }
10317  /**
10318   * Setups a node material observer with the given builder.
10319   *
10320   * @param {NodeBuilder} builder - The current node builder.
10321   * @return {NodeMaterialObserver} The node material observer.
10322   */
10323  setupObserver(builder) {
10324    return new NodeMaterialObserver(builder);
10325  }
10326  /**
10327   * Setups the vertex and fragment stage of this node material.
10328   *
10329   * @param {NodeBuilder} builder - The current node builder.
10330   */
10331  setup(builder) {
10332    builder.context.setupNormal = () => subBuild(this.setupNormal(builder), "NORMAL", "vec3");
10333    builder.context.setupPositionView = () => this.setupPositionView(builder);
10334    builder.context.setupModelViewProjection = () => this.setupModelViewProjection(builder);
10335    const renderer = builder.renderer;
10336    const renderTarget = renderer.getRenderTarget();
10337    builder.addStack();
10338    const mvp = this.setupVertex(builder);
10339    const vertexNode = subBuild(this.vertexNode || mvp, "VERTEX");
10340    builder.context.clipSpace = vertexNode;
10341    builder.stack.outputNode = vertexNode;
10342    this.setupHardwareClipping(builder);
10343    if (this.geometryNode !== null) {
10344      builder.stack.outputNode = builder.stack.outputNode.bypass(this.geometryNode);
10345    }
10346    builder.addFlow("vertex", builder.removeStack());
10347    builder.addStack();
10348    let resultNode;
10349    const clippingNode = this.setupClipping(builder);
10350    if (this.depthWrite === true || this.depthTest === true) {
10351      if (renderTarget !== null) {
10352        if (renderTarget.depthBuffer === true) this.setupDepth(builder);
10353      } else {
10354        if (renderer.depth === true) this.setupDepth(builder);
10355      }
10356    }
10357    if (this.fragmentNode === null) {
10358      this.setupDiffuseColor(builder);
10359      this.setupVariants(builder);
10360      const outgoingLightNode = this.setupLighting(builder);
10361      if (clippingNode !== null) builder.stack.addToStack(clippingNode);
10362      const basicOutput = vec4(outgoingLightNode, diffuseColor.a).max(0);
10363      resultNode = this.setupOutput(builder, basicOutput);
10364      output.assign(resultNode);
10365      const isCustomOutput = this.outputNode !== null;
10366      if (isCustomOutput) resultNode = this.outputNode;
10367      if (builder.context.getOutput) {
10368        resultNode = builder.context.getOutput(resultNode, builder);
10369      }
10370      if (renderTarget !== null) {
10371        const mrt3 = renderer.getMRT();
10372        const materialMRT = this.mrtNode;
10373        if (mrt3 !== null) {
10374          if (isCustomOutput) output.assign(resultNode);
10375          resultNode = mrt3;
10376          if (materialMRT !== null) {
10377            resultNode = mrt3.merge(materialMRT);
10378          }
10379        } else if (materialMRT !== null) {
10380          resultNode = materialMRT;
10381        }
10382      }
10383    } else {
10384      let fragmentNode = this.fragmentNode;
10385      if (fragmentNode.isOutputStructNode !== true) {
10386        fragmentNode = vec4(fragmentNode);
10387      }
10388      resultNode = this.setupOutput(builder, fragmentNode);
10389    }
10390    builder.stack.outputNode = resultNode;
10391    builder.addFlow("fragment", builder.removeStack());
10392    builder.observer = this.setupObserver(builder);
10393  }
10394  /**
10395   * Setups the clipping node.
10396   *
10397   * @param {NodeBuilder} builder - The current node builder.
10398   * @return {ClippingNode} The clipping node.
10399   */
10400  setupClipping(builder) {
10401    if (builder.clippingContext === null) return null;
10402    const { unionPlanes, intersectionPlanes } = builder.clippingContext;
10403    let result = null;
10404    if (unionPlanes.length > 0 || intersectionPlanes.length > 0) {
10405      const samples = builder.renderer.currentSamples;
10406      if (this.alphaToCoverage && samples > 1) {
10407        result = clippingAlpha();
10408      } else {
10409        builder.stack.addToStack(clipping());
10410      }
10411    }
10412    return result;
10413  }
10414  /**
10415   * Setups the hardware clipping if available on the current device.
10416   *
10417   * @param {NodeBuilder} builder - The current node builder.
10418   */
10419  setupHardwareClipping(builder) {
10420    this.hardwareClipping = false;
10421    if (builder.clippingContext === null) return;
10422    const candidateCount = builder.clippingContext.unionPlanes.length;
10423    if (candidateCount > 0 && candidateCount <= 8 && builder.isAvailable("clipDistance")) {
10424      builder.stack.addToStack(hardwareClipping());
10425      this.hardwareClipping = true;
10426    }
10427    return;
10428  }
10429  /**
10430   * Setups the depth of this material.
10431   *
10432   * @param {NodeBuilder} builder - The current node builder.
10433   */
10434  setupDepth(builder) {
10435    const { renderer, camera } = builder;
10436    let depthNode = this.depthNode;
10437    if (depthNode === null) {
10438      const mrt3 = renderer.getMRT();
10439      if (mrt3 && mrt3.has("depth")) {
10440        depthNode = mrt3.get("depth");
10441      } else if (renderer.logarithmicDepthBuffer === true) {
10442        if (camera.isPerspectiveCamera) {
10443          depthNode = viewZToLogarithmicDepth(positionView.z, cameraNear, cameraFar);
10444        } else {
10445          depthNode = viewZToOrthographicDepth(positionView.z, cameraNear, cameraFar);
10446        }
10447      }
10448    }
10449    if (depthNode !== null) {
10450      depth.assign(depthNode).toStack();
10451    }
10452  }
10453  /**
10454   * Setups the position node in view space. This method exists
10455   * so derived node materials can modify the implementation e.g. sprite materials.
10456   *
10457   * @param {NodeBuilder} builder - The current node builder.
10458   * @return {Node<vec3>} The position in view space.
10459   */
10460  setupPositionView() {
10461    return modelViewMatrix.mul(positionLocal).xyz;
10462  }
10463  /**
10464   * Setups the position in clip space.
10465   *
10466   * @param {NodeBuilder} builder - The current node builder.
10467   * @return {Node<vec4>} The position in view space.
10468   */
10469  setupModelViewProjection() {
10470    return cameraProjectionMatrix.mul(positionView);
10471  }
10472  /**
10473   * Setups the logic for the vertex stage.
10474   *
10475   * @param {NodeBuilder} builder - The current node builder.
10476   * @return {Node<vec4>} The position in clip space.
10477   */
10478  setupVertex(builder) {
10479    builder.addStack();
10480    this.setupPosition(builder);
10481    builder.context.position = builder.removeStack();
10482    return modelViewProjection;
10483  }
10484  /**
10485   * Setups the computation of the position in local space.
10486   *
10487   * @param {NodeBuilder} builder - The current node builder.
10488   * @return {Node<vec3>} The position in local space.
10489   */
10490  setupPosition(builder) {
10491    const { object, geometry } = builder;
10492    if (geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color) {
10493      morphReference(object).toStack();
10494    }
10495    if (object.isSkinnedMesh === true) {
10496      skinning(object).toStack();
10497    }
10498    if (this.displacementMap) {
10499      const displacementMap = materialReference("displacementMap", "texture");
10500      const displacementScale = materialReference("displacementScale", "float");
10501      const displacementBias = materialReference("displacementBias", "float");
10502      positionLocal.addAssign(normalLocal.normalize().mul(displacementMap.x.mul(displacementScale).add(displacementBias)));
10503    }
10504    if (object.isBatchedMesh) {
10505      batch2(object).toStack();
10506    }
10507    if (object.isInstancedMesh && object.instanceMatrix && object.instanceMatrix.isInstancedBufferAttribute === true) {
10508      instancedMesh(object).toStack();
10509    }
10510    if (this.positionNode !== null) {
10511      positionLocal.assign(subBuild(this.positionNode, "POSITION", "vec3"));
10512    }
10513    return positionLocal;
10514  }
10515  /**
10516   * Setups the computation of the material's diffuse color.
10517   *
10518   * @param {NodeBuilder} builder - The current node builder.
10519   * @param {BufferGeometry} geometry - The geometry.
10520   */
10521  setupDiffuseColor(builder) {
10522    const { object, geometry } = builder;
10523    if (this.maskNode !== null) {
10524      bool(this.maskNode).not().discard();
10525    }
10526    let colorNode = this.colorNode ? vec4(this.colorNode) : materialColor;
10527    if (this.vertexColors === true && geometry.hasAttribute("color")) {
10528      colorNode = colorNode.mul(vertexColor());
10529    }
10530    if (object.instanceColor) {
10531      const instanceColor = varyingProperty("vec3", "vInstanceColor");
10532      colorNode = instanceColor.mul(colorNode);
10533    }
10534    if (object.isBatchedMesh && object._colorsTexture) {
10535      const batchColor = varyingProperty("vec3", "vBatchColor");
10536      colorNode = batchColor.mul(colorNode);
10537    }
10538    diffuseColor.assign(colorNode);
10539    const opacityNode = this.opacityNode ? float(this.opacityNode) : materialOpacity;
10540    diffuseColor.a.assign(diffuseColor.a.mul(opacityNode));
10541    let alphaTestNode = null;
10542    if (this.alphaTestNode !== null || this.alphaTest > 0) {
10543      alphaTestNode = this.alphaTestNode !== null ? float(this.alphaTestNode) : materialAlphaTest;
10544      if (this.alphaToCoverage === true) {
10545        diffuseColor.a = smoothstep(alphaTestNode, alphaTestNode.add(fwidth(diffuseColor.a)), diffuseColor.a);
10546        diffuseColor.a.lessThanEqual(0).discard();
10547      } else {
10548        diffuseColor.a.lessThanEqual(alphaTestNode).discard();
10549      }
10550    }
10551    if (this.alphaHash === true) {
10552      diffuseColor.a.lessThan(getAlphaHashThreshold(positionLocal)).discard();
10553    }
10554    if (builder.isOpaque()) {
10555      diffuseColor.a.assign(1);
10556    }
10557  }
10558  /**
10559   * Abstract interface method that can be implemented by derived materials
10560   * to setup material-specific node variables.
10561   *
10562   * @abstract
10563   * @param {NodeBuilder} builder - The current node builder.
10564   */
10565  setupVariants() {
10566  }
10567  /**
10568   * Setups the outgoing light node variable
10569   *
10570   * @return {Node<vec3>} The outgoing light node.
10571   */
10572  setupOutgoingLight() {
10573    return this.lights === true ? vec3(0) : diffuseColor.rgb;
10574  }
10575  /**
10576   * Setups the normal node from the material.
10577   *
10578   * @return {Node<vec3>} The normal node.
10579   */
10580  setupNormal() {
10581    return this.normalNode ? vec3(this.normalNode) : materialNormal;
10582  }
10583  /**
10584   * Setups the environment node from the material.
10585   *
10586   * @param {NodeBuilder} builder - The current node builder.
10587   * @return {Node<vec4>} The environment node.
10588   */
10589  setupEnvironment() {
10590    let node = null;
10591    if (this.envNode) {
10592      node = this.envNode;
10593    } else if (this.envMap) {
10594      node = this.envMap.isCubeTexture ? materialReference("envMap", "cubeTexture") : materialReference("envMap", "texture");
10595    }
10596    return node;
10597  }
10598  /**
10599   * Setups the light map node from the material.
10600   *
10601   * @param {NodeBuilder} builder - The current node builder.
10602   * @return {Node<vec3>} The light map node.
10603   */
10604  setupLightMap(builder) {
10605    let node = null;
10606    if (builder.material.lightMap) {
10607      node = new IrradianceNode(materialLightMap);
10608    }
10609    return node;
10610  }
10611  /**
10612   * Setups the lights node based on the scene, environment and material.
10613   *
10614   * @param {NodeBuilder} builder - The current node builder.
10615   * @return {LightsNode} The lights node.
10616   */
10617  setupLights(builder) {
10618    const materialLightsNode = [];
10619    const envNode = this.setupEnvironment(builder);
10620    if (envNode && envNode.isLightingNode) {
10621      materialLightsNode.push(envNode);
10622    }
10623    const lightMapNode = this.setupLightMap(builder);
10624    if (lightMapNode && lightMapNode.isLightingNode) {
10625      materialLightsNode.push(lightMapNode);
10626    }
10627    let aoNode = this.aoNode;
10628    if (aoNode === null && builder.material.aoMap) {
10629      aoNode = materialAO;
10630    }
10631    if (builder.context.getAO) {
10632      aoNode = builder.context.getAO(aoNode, builder);
10633    }
10634    if (aoNode) {
10635      materialLightsNode.push(new AONode(aoNode));
10636    }
10637    let lightsN = this.lightsNode || builder.lightsNode;
10638    if (materialLightsNode.length > 0) {
10639      lightsN = builder.renderer.lighting.createNode([...lightsN.getLights(), ...materialLightsNode]);
10640    }
10641    return lightsN;
10642  }
10643  /**
10644   * This method should be implemented by most derived materials
10645   * since it defines the material's lighting model.
10646   *
10647   * @abstract
10648   * @param {NodeBuilder} builder - The current node builder.
10649   * @return {LightingModel} The lighting model.
10650   */
10651  setupLightingModel() {
10652  }
10653  /**
10654   * Setups the outgoing light node.
10655   *
10656   * @param {NodeBuilder} builder - The current node builder.
10657   * @return {Node<vec3>} The outgoing light node.
10658   */
10659  setupLighting(builder) {
10660    const { material } = builder;
10661    const { backdropNode, backdropAlphaNode, emissiveNode } = this;
10662    const lights3 = this.lights === true || this.lightsNode !== null;
10663    const lightsNode = lights3 ? this.setupLights(builder) : null;
10664    let outgoingLightNode = this.setupOutgoingLight(builder);
10665    if (lightsNode && lightsNode.getScope().hasLights) {
10666      const lightingModel = this.setupLightingModel(builder) || null;
10667      outgoingLightNode = lightingContext(lightsNode, lightingModel, backdropNode, backdropAlphaNode);
10668    } else if (backdropNode !== null) {
10669      outgoingLightNode = vec3(backdropAlphaNode !== null ? mix(outgoingLightNode, backdropNode, backdropAlphaNode) : backdropNode);
10670    }
10671    if (emissiveNode && emissiveNode.isNode === true || material.emissive && material.emissive.isColor === true) {
10672      emissive.assign(vec3(emissiveNode ? emissiveNode : materialEmissive));
10673      outgoingLightNode = outgoingLightNode.add(emissive);
10674    }
10675    return outgoingLightNode;
10676  }
10677  /**
10678   * Setup the fog.
10679   *
10680   * @param {NodeBuilder} builder - The current node builder.
10681   * @param {Node<vec4>} outputNode - The existing output node.
10682   * @return {Node<vec4>} The output node.
10683   */
10684  setupFog(builder, outputNode) {
10685    const fogNode = builder.fogNode;
10686    if (fogNode) {
10687      output.assign(outputNode);
10688      outputNode = vec4(fogNode.toVar());
10689    }
10690    return outputNode;
10691  }
10692  /**
10693   * Setups premultiplied alpha.
10694   *
10695   * @param {NodeBuilder} builder - The current node builder.
10696   * @param {Node<vec4>} outputNode - The existing output node.
10697   * @return {Node<vec4>} The output node.
10698   */
10699  setupPremultipliedAlpha(builder, outputNode) {
10700    return premultiplyAlpha(outputNode);
10701  }
10702  /**
10703   * Setups the output node.
10704   *
10705   * @param {NodeBuilder} builder - The current node builder.
10706   * @param {Node<vec4>} outputNode - The existing output node.
10707   * @return {Node<vec4>} The output node.
10708   */
10709  setupOutput(builder, outputNode) {
10710    if (this.fog === true) {
10711      outputNode = this.setupFog(builder, outputNode);
10712    }
10713    if (this.premultipliedAlpha === true) {
10714      outputNode = this.setupPremultipliedAlpha(builder, outputNode);
10715    }
10716    return outputNode;
10717  }
10718  /**
10719   * Most classic material types have a node pendant e.g. for `MeshBasicMaterial`
10720   * there is `MeshBasicNodeMaterial`. This utility method is intended for
10721   * defining all material properties of the classic type in the node type.
10722   *
10723   * @param {Material} material - The material to copy properties with their values to this node material.
10724   */
10725  setDefaultValues(material) {
10726    for (const property3 in material) {
10727      const value = material[property3];
10728      if (this[property3] === void 0) {
10729        this[property3] = value;
10730        if (value && value.clone) this[property3] = value.clone();
10731      }
10732    }
10733    const descriptors = Object.getOwnPropertyDescriptors(material.constructor.prototype);
10734    for (const key in descriptors) {
10735      if (Object.getOwnPropertyDescriptor(this.constructor.prototype, key) === void 0 && descriptors[key].get !== void 0) {
10736        Object.defineProperty(this.constructor.prototype, key, descriptors[key]);
10737      }
10738    }
10739  }
10740  /**
10741   * Serializes this material to JSON.
10742   *
10743   * @param {?(Object|string)} meta - The meta information for serialization.
10744   * @return {Object} The serialized node.
10745   */
10746  toJSON(meta) {
10747    const isRoot = meta === void 0 || typeof meta === "string";
10748    if (isRoot) {
10749      meta = {
10750        textures: {},
10751        images: {},
10752        nodes: {}
10753      };
10754    }
10755    const data = Material.prototype.toJSON.call(this, meta);
10756    data.inputNodes = {};
10757    for (const { property: property3, childNode } of this._getNodeChildren()) {
10758      data.inputNodes[property3] = childNode.toJSON(meta).uuid;
10759    }
10760    function extractFromCache(cache4) {
10761      const values = [];
10762      for (const key in cache4) {
10763        const data2 = cache4[key];
10764        delete data2.metadata;
10765        values.push(data2);
10766      }
10767      return values;
10768    }
10769    if (isRoot) {
10770      const textures = extractFromCache(meta.textures);
10771      const images = extractFromCache(meta.images);
10772      const nodes = extractFromCache(meta.nodes);
10773      if (textures.length > 0) data.textures = textures;
10774      if (images.length > 0) data.images = images;
10775      if (nodes.length > 0) data.nodes = nodes;
10776    }
10777    return data;
10778  }
10779  /**
10780   * Copies the properties of the given node material to this instance.
10781   *
10782   * @param {NodeMaterial} source - The material to copy.
10783   * @return {NodeMaterial} A reference to this node material.
10784   */
10785  copy(source) {
10786    this.lightsNode = source.lightsNode;
10787    this.envNode = source.envNode;
10788    this.aoNode = source.aoNode;
10789    this.colorNode = source.colorNode;
10790    this.normalNode = source.normalNode;
10791    this.opacityNode = source.opacityNode;
10792    this.backdropNode = source.backdropNode;
10793    this.backdropAlphaNode = source.backdropAlphaNode;
10794    this.alphaTestNode = source.alphaTestNode;
10795    this.maskNode = source.maskNode;
10796    this.maskShadowNode = source.maskShadowNode;
10797    this.positionNode = source.positionNode;
10798    this.geometryNode = source.geometryNode;
10799    this.depthNode = source.depthNode;
10800    this.receivedShadowPositionNode = source.receivedShadowPositionNode;
10801    this.castShadowPositionNode = source.castShadowPositionNode;
10802    this.receivedShadowNode = source.receivedShadowNode;
10803    this.castShadowNode = source.castShadowNode;
10804    this.outputNode = source.outputNode;
10805    this.mrtNode = source.mrtNode;
10806    this.fragmentNode = source.fragmentNode;
10807    this.vertexNode = source.vertexNode;
10808    this.contextNode = source.contextNode;
10809    return super.copy(source);
10810  }
10811};
10812var _defaultValues$d = /* @__PURE__ */ new LineBasicMaterial();
10813var LineBasicNodeMaterial = class extends NodeMaterial {
10814  static get type() {
10815    return "LineBasicNodeMaterial";
10816  }
10817  /**
10818   * Constructs a new line basic node material.
10819   *
10820   * @param {Object} [parameters] - The configuration parameter.
10821   */
10822  constructor(parameters) {
10823    super();
10824    this.isLineBasicNodeMaterial = true;
10825    this.setDefaultValues(_defaultValues$d);
10826    this.setValues(parameters);
10827  }
10828};
10829var _defaultValues$c = /* @__PURE__ */ new LineDashedMaterial();
10830var LineDashedNodeMaterial = class extends NodeMaterial {
10831  static get type() {
10832    return "LineDashedNodeMaterial";
10833  }
10834  /**
10835   * Constructs a new line dashed node material.
10836   *
10837   * @param {Object} [parameters] - The configuration parameter.
10838   */
10839  constructor(parameters) {
10840    super();
10841    this.isLineDashedNodeMaterial = true;
10842    this.setDefaultValues(_defaultValues$c);
10843    this.dashOffset = 0;
10844    this.offsetNode = null;
10845    this.dashScaleNode = null;
10846    this.dashSizeNode = null;
10847    this.gapSizeNode = null;
10848    this.setValues(parameters);
10849  }
10850  /**
10851   * Setups the dash specific node variables.
10852   *
10853   * @param {NodeBuilder} builder - The current node builder.
10854   */
10855  setupVariants() {
10856    const offsetNode = this.offsetNode ? float(this.offsetNode) : materialLineDashOffset;
10857    const dashScaleNode = this.dashScaleNode ? float(this.dashScaleNode) : materialLineScale;
10858    const dashSizeNode = this.dashSizeNode ? float(this.dashSizeNode) : materialLineDashSize;
10859    const gapSizeNode = this.gapSizeNode ? float(this.gapSizeNode) : materialLineGapSize;
10860    dashSize.assign(dashSizeNode);
10861    gapSize.assign(gapSizeNode);
10862    const vLineDistance = varying(attribute("lineDistance").mul(dashScaleNode));
10863    const vLineDistanceOffset = offsetNode ? vLineDistance.add(offsetNode) : vLineDistance;
10864    vLineDistanceOffset.mod(dashSize.add(gapSize)).greaterThan(dashSize).discard();
10865  }
10866};
10867var _defaultValues$a = /* @__PURE__ */ new MeshNormalMaterial();
10868var MeshNormalNodeMaterial = class extends NodeMaterial {
10869  static get type() {
10870    return "MeshNormalNodeMaterial";
10871  }
10872  /**
10873   * Constructs a new mesh normal node material.
10874   *
10875   * @param {Object} [parameters] - The configuration parameter.
10876   */
10877  constructor(parameters) {
10878    super();
10879    this.isMeshNormalNodeMaterial = true;
10880    this.setDefaultValues(_defaultValues$a);
10881    this.setValues(parameters);
10882  }
10883  /**
10884   * Overwrites the default implementation by computing the diffuse color
10885   * based on the normal data.
10886   */
10887  setupDiffuseColor() {
10888    const opacityNode = this.opacityNode ? float(this.opacityNode) : materialOpacity;
10889    diffuseColor.assign(colorSpaceToWorking(vec4(directionToColor(normalView), opacityNode), SRGBColorSpace));
10890  }
10891};
10892var equirectUV = /* @__PURE__ */ Fn(([dir = positionWorldDirection]) => {
10893  const u = dir.z.atan(dir.x).mul(1 / (Math.PI * 2)).add(0.5);
10894  const v = dir.y.clamp(-1, 1).asin().mul(1 / Math.PI).add(0.5);
10895  return vec2(u, v);
10896});
10897var CubeRenderTarget = class extends RenderTarget {
10898  /**
10899   * Constructs a new cube render target.
10900   *
10901   * @param {number} [size=1] - The size of the render target.
10902   * @param {RenderTarget~Options} [options] - The configuration object.
10903   */
10904  constructor(size3 = 1, options = {}) {
10905    super(size3, size3, options);
10906    this.isCubeRenderTarget = true;
10907    const image = { width: size3, height: size3, depth: 1 };
10908    const images = [image, image, image, image, image, image];
10909    this.texture = new CubeTexture(images);
10910    this._setTextureOptions(options);
10911    this.texture.isRenderTargetTexture = true;
10912  }
10913  /**
10914   * Converts the given equirectangular texture to a cube map.
10915   *
10916   * @param {Renderer} renderer - The renderer.
10917   * @param {Texture} texture - The equirectangular texture.
10918   * @return {CubeRenderTarget} A reference to this cube render target.
10919   */
10920  fromEquirectangularTexture(renderer, texture$1) {
10921    const currentMinFilter = texture$1.minFilter;
10922    const currentGenerateMipmaps = texture$1.generateMipmaps;
10923    texture$1.generateMipmaps = true;
10924    this.texture.type = texture$1.type;
10925    this.texture.colorSpace = texture$1.colorSpace;
10926    this.texture.generateMipmaps = texture$1.generateMipmaps;
10927    this.texture.minFilter = texture$1.minFilter;
10928    this.texture.magFilter = texture$1.magFilter;
10929    const geometry = new BoxGeometry(5, 5, 5);
10930    const uvNode = equirectUV(positionWorldDirection);
10931    const material = new NodeMaterial();
10932    material.colorNode = texture(texture$1, uvNode, 0);
10933    material.side = BackSide;
10934    material.blending = NoBlending;
10935    const mesh = new Mesh(geometry, material);
10936    const scene = new Scene();
10937    scene.add(mesh);
10938    if (texture$1.minFilter === LinearMipmapLinearFilter) texture$1.minFilter = LinearFilter;
10939    const camera = new CubeCamera(1, 10, this);
10940    const currentMRT = renderer.getMRT();
10941    renderer.setMRT(null);
10942    camera.update(renderer, scene);
10943    renderer.setMRT(currentMRT);
10944    texture$1.minFilter = currentMinFilter;
10945    texture$1.generateMipmaps = currentGenerateMipmaps;
10946    mesh.geometry.dispose();
10947    mesh.material.dispose();
10948    return this;
10949  }
10950  /**
10951   * Clears this cube render target.
10952   *
10953   * @param {Renderer} renderer - The renderer.
10954   * @param {boolean} [color=true] - Whether the color buffer should be cleared or not.
10955   * @param {boolean} [depth=true] - Whether the depth buffer should be cleared or not.
10956   * @param {boolean} [stencil=true] - Whether the stencil buffer should be cleared or not.
10957   */
10958  clear(renderer, color3 = true, depth3 = true, stencil = true) {
10959    const currentRenderTarget = renderer.getRenderTarget();
10960    for (let i = 0; i < 6; i++) {
10961      renderer.setRenderTarget(this, i);
10962      renderer.clear(color3, depth3, stencil);
10963    }
10964    renderer.setRenderTarget(currentRenderTarget);
10965  }
10966};
10967var _cache$1 = /* @__PURE__ */ new WeakMap();
10968var CubeMapNode = class extends TempNode {
10969  static get type() {
10970    return "CubeMapNode";
10971  }
10972  /**
10973   * Constructs a new cube map node.
10974   *
10975   * @param {Node} envNode - The node representing the environment map.
10976   */
10977  constructor(envNode) {
10978    super("vec3");
10979    this.envNode = envNode;
10980    this._cubeTexture = null;
10981    this._cubeTextureNode = cubeTexture(null);
10982    const defaultTexture = new CubeTexture();
10983    defaultTexture.isRenderTargetTexture = true;
10984    this._defaultTexture = defaultTexture;
10985    this.updateBeforeType = NodeUpdateType.RENDER;
10986  }
10987  updateBefore(frame) {
10988    const { renderer, material } = frame;
10989    const envNode = this.envNode;
10990    if (envNode.isTextureNode || envNode.isMaterialReferenceNode) {
10991      const texture3 = envNode.isTextureNode ? envNode.value : material[envNode.property];
10992      if (texture3 && texture3.isTexture) {
10993        const mapping = texture3.mapping;
10994        if (mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping) {
10995          if (_cache$1.has(texture3)) {
10996            const cubeMap = _cache$1.get(texture3);
10997            mapTextureMapping(cubeMap, texture3.mapping);
10998            this._cubeTexture = cubeMap;
10999          } else {
11000            const image = texture3.image;
11001            if (isEquirectangularMapReady$1(image)) {
11002              const renderTarget = new CubeRenderTarget(image.height);
11003              renderTarget.fromEquirectangularTexture(renderer, texture3);
11004              mapTextureMapping(renderTarget.texture, texture3.mapping);
11005              this._cubeTexture = renderTarget.texture;
11006              _cache$1.set(texture3, renderTarget.texture);
11007              texture3.addEventListener("dispose", onTextureDispose);
11008            } else {
11009              this._cubeTexture = this._defaultTexture;
11010            }
11011          }
11012          this._cubeTextureNode.value = this._cubeTexture;
11013        } else {
11014          this._cubeTextureNode = this.envNode;
11015        }
11016      }
11017    }
11018  }
11019  setup(builder) {
11020    this.updateBefore(builder);
11021    return this._cubeTextureNode;
11022  }
11023};
11024function isEquirectangularMapReady$1(image) {
11025  if (image === null || image === void 0) return false;
11026  return image.height > 0;
11027}
11028function onTextureDispose(event) {
11029  const texture3 = event.target;
11030  texture3.removeEventListener("dispose", onTextureDispose);
11031  const renderTarget = _cache$1.get(texture3);
11032  if (renderTarget !== void 0) {
11033    _cache$1.delete(texture3);
11034    renderTarget.dispose();
11035  }
11036}
11037function mapTextureMapping(texture3, mapping) {
11038  if (mapping === EquirectangularReflectionMapping) {
11039    texture3.mapping = CubeReflectionMapping;
11040  } else if (mapping === EquirectangularRefractionMapping) {
11041    texture3.mapping = CubeRefractionMapping;
11042  }
11043}
11044var cubeMapNode = /* @__PURE__ */ nodeProxy(CubeMapNode).setParameterLength(1);
11045var BasicEnvironmentNode = class extends LightingNode {
11046  static get type() {
11047    return "BasicEnvironmentNode";
11048  }
11049  /**
11050   * Constructs a new basic environment node.
11051   *
11052   * @param {Node} [envNode=null] - A node representing the environment.
11053   */
11054  constructor(envNode = null) {
11055    super();
11056    this.envNode = envNode;
11057  }
11058  setup(builder) {
11059    builder.context.environment = cubeMapNode(this.envNode);
11060  }
11061};
11062var BasicLightMapNode = class extends LightingNode {
11063  static get type() {
11064    return "BasicLightMapNode";
11065  }
11066  /**
11067   * Constructs a new basic light map node.
11068   *
11069   * @param {?Node<vec3>} [lightMapNode=null] - The light map node.
11070   */
11071  constructor(lightMapNode = null) {
11072    super();
11073    this.lightMapNode = lightMapNode;
11074  }
11075  setup(builder) {
11076    const RECIPROCAL_PI2 = float(1 / Math.PI);
11077    builder.context.irradianceLightMap = this.lightMapNode.mul(RECIPROCAL_PI2);
11078  }
11079};
11080var LightingModel = class {
11081  /**
11082   * This method is intended for setting up lighting model and context data
11083   * which are later used in the evaluation process.
11084   *
11085   * @abstract
11086   * @param {NodeBuilder} builder - The current node builder.
11087   */
11088  start(builder) {
11089    builder.lightsNode.setupLights(builder, builder.lightsNode.getLightNodes(builder));
11090    this.indirect(builder);
11091  }
11092  /**
11093   * This method is intended for executing final tasks like final updates
11094   * to the outgoing light.
11095   *
11096   * @abstract
11097   * @param {NodeBuilder} builder - The current node builder.
11098   */
11099  finish() {
11100  }
11101  /**
11102   * This method is intended for implementing the direct light term and
11103   * executed during the build process of directional, point and spot light nodes.
11104   *
11105   * @abstract
11106   * @param {Object} lightData - The light data.
11107   * @param {NodeBuilder} builder - The current node builder.
11108   */
11109  direct() {
11110  }
11111  /**
11112   * This method is intended for implementing the direct light term for
11113   * rect area light nodes.
11114   *
11115   * @abstract
11116   * @param {Object} lightData - The light data.
11117   * @param {NodeBuilder} builder - The current node builder.
11118   */
11119  directRectArea() {
11120  }
11121  /**
11122   * This method is intended for implementing the indirect light term.
11123   *
11124   * @abstract
11125   * @param {NodeBuilder} builder - The current node builder.
11126   */
11127  indirect() {
11128  }
11129  /**
11130   * This method is intended for implementing the ambient occlusion term.
11131   * Unlike other methods, this method must be called manually by the lighting
11132   * model in its indirect term.
11133   *
11134   * @abstract
11135   * @param {NodeBuilder} builder - The current node builder.
11136   */
11137  ambientOcclusion() {
11138  }
11139};
11140var BasicLightingModel = class extends LightingModel {
11141  /**
11142   * Constructs a new basic lighting model.
11143   */
11144  constructor() {
11145    super();
11146  }
11147  /**
11148   * Implements the baked indirect lighting with its modulation.
11149   *
11150   * @param {NodeBuilder} builder - The current node builder.
11151   */
11152  indirect({ context: context3 }) {
11153    const ambientOcclusion = context3.ambientOcclusion;
11154    const reflectedLight = context3.reflectedLight;
11155    const irradianceLightMap = context3.irradianceLightMap;
11156    reflectedLight.indirectDiffuse.assign(vec4(0));
11157    if (irradianceLightMap) {
11158      reflectedLight.indirectDiffuse.addAssign(irradianceLightMap);
11159    } else {
11160      reflectedLight.indirectDiffuse.addAssign(vec4(1, 1, 1, 0));
11161    }
11162    reflectedLight.indirectDiffuse.mulAssign(ambientOcclusion);
11163    reflectedLight.indirectDiffuse.mulAssign(diffuseColor.rgb);
11164  }
11165  /**
11166   * Implements the environment mapping.
11167   *
11168   * @param {NodeBuilder} builder - The current node builder.
11169   */
11170  finish(builder) {
11171    const { material, context: context3 } = builder;
11172    const outgoingLight = context3.outgoingLight;
11173    const envNode = builder.context.environment;
11174    if (envNode) {
11175      switch (material.combine) {
11176        case MultiplyOperation:
11177          outgoingLight.rgb.assign(mix(outgoingLight.rgb, outgoingLight.rgb.mul(envNode.rgb), materialSpecularStrength.mul(materialReflectivity)));
11178          break;
11179        case MixOperation:
11180          outgoingLight.rgb.assign(mix(outgoingLight.rgb, envNode.rgb, materialSpecularStrength.mul(materialReflectivity)));
11181          break;
11182        case AddOperation:
11183          outgoingLight.rgb.addAssign(envNode.rgb.mul(materialSpecularStrength.mul(materialReflectivity)));
11184          break;
11185        default:
11186          warn("BasicLightingModel: Unsupported .combine value:", material.combine);
11187          break;
11188      }
11189    }
11190  }
11191};
11192var _defaultValues$9 = /* @__PURE__ */ new MeshBasicMaterial();
11193var MeshBasicNodeMaterial = class extends NodeMaterial {
11194  static get type() {
11195    return "MeshBasicNodeMaterial";
11196  }
11197  /**
11198   * Constructs a new mesh basic node material.
11199   *
11200   * @param {Object} [parameters] - The configuration parameter.
11201   */
11202  constructor(parameters) {
11203    super();
11204    this.isMeshBasicNodeMaterial = true;
11205    this.lights = true;
11206    this.setDefaultValues(_defaultValues$9);
11207    this.setValues(parameters);
11208  }
11209  /**
11210   * Basic materials are not affected by normal and bump maps so we
11211   * return by default {@link normalViewGeometry}.
11212   *
11213   * @return {Node<vec3>} The normal node.
11214   */
11215  setupNormal() {
11216    return directionToFaceDirection(normalViewGeometry);
11217  }
11218  /**
11219   * Overwritten since this type of material uses {@link BasicEnvironmentNode}
11220   * to implement the default environment mapping.
11221   *
11222   * @param {NodeBuilder} builder - The current node builder.
11223   * @return {?BasicEnvironmentNode<vec3>} The environment node.
11224   */
11225  setupEnvironment(builder) {
11226    const envNode = super.setupEnvironment(builder);
11227    return envNode ? new BasicEnvironmentNode(envNode) : null;
11228  }
11229  /**
11230   * This method must be overwritten since light maps are evaluated
11231   * with a special scaling factor for basic materials.
11232   *
11233   * @param {NodeBuilder} builder - The current node builder.
11234   * @return {?BasicLightMapNode<vec3>} The light map node.
11235   */
11236  setupLightMap(builder) {
11237    let node = null;
11238    if (builder.material.lightMap) {
11239      node = new BasicLightMapNode(materialLightMap);
11240    }
11241    return node;
11242  }
11243  /**
11244   * The material overwrites this method because `lights` is set to `true` but
11245   * we still want to return the diffuse color as the outgoing light.
11246   *
11247   * @return {Node<vec3>} The outgoing light node.
11248   */
11249  setupOutgoingLight() {
11250    return diffuseColor.rgb;
11251  }
11252  /**
11253   * Setups the lighting model.
11254   *
11255   * @return {BasicLightingModel} The lighting model.
11256   */
11257  setupLightingModel() {
11258    return new BasicLightingModel();
11259  }
11260};
11261var F_Schlick = /* @__PURE__ */ Fn(({ f0, f90, dotVH }) => {
11262  const fresnel = dotVH.mul(-5.55473).sub(6.98316).mul(dotVH).exp2();
11263  return f0.mul(fresnel.oneMinus()).add(f90.mul(fresnel));
11264});
11265var BRDF_Lambert = /* @__PURE__ */ Fn((inputs) => {
11266  return inputs.diffuseColor.mul(1 / Math.PI);
11267});
11268var G_BlinnPhong_Implicit = () => float(0.25);
11269var D_BlinnPhong = /* @__PURE__ */ Fn(({ dotNH }) => {
11270  return shininess.mul(float(0.5)).add(1).mul(float(1 / Math.PI)).mul(dotNH.pow(shininess));
11271});
11272var BRDF_BlinnPhong = /* @__PURE__ */ Fn(({ lightDirection }) => {
11273  const halfDir = lightDirection.add(positionViewDirection).normalize();
11274  const dotNH = normalView.dot(halfDir).clamp();
11275  const dotVH = positionViewDirection.dot(halfDir).clamp();
11276  const F = F_Schlick({ f0: specularColor, f90: 1, dotVH });
11277  const G = G_BlinnPhong_Implicit();
11278  const D = D_BlinnPhong({ dotNH });
11279  return F.mul(G).mul(D);
11280});
11281var PhongLightingModel = class extends BasicLightingModel {
11282  /**
11283   * Constructs a new phong lighting model.
11284   *
11285   * @param {boolean} [specular=true] - Whether specular is supported or not.
11286   */
11287  constructor(specular = true) {
11288    super();
11289    this.specular = specular;
11290  }
11291  /**
11292   * Implements the direct lighting. The specular portion is optional an can be controlled
11293   * with the {@link PhongLightingModel#specular} flag.
11294   *
11295   * @param {Object} lightData - The light data.
11296   */
11297  direct({ lightDirection, lightColor, reflectedLight }) {
11298    const dotNL = normalView.dot(lightDirection).clamp();
11299    const irradiance = dotNL.mul(lightColor);
11300    reflectedLight.directDiffuse.addAssign(irradiance.mul(BRDF_Lambert({ diffuseColor: diffuseColor.rgb })));
11301    if (this.specular === true) {
11302      reflectedLight.directSpecular.addAssign(irradiance.mul(BRDF_BlinnPhong({ lightDirection })).mul(materialSpecularStrength));
11303    }
11304  }
11305  /**
11306   * Implements the indirect lighting.
11307   *
11308   * @param {NodeBuilder} builder - The current node builder.
11309   */
11310  indirect(builder) {
11311    const { ambientOcclusion, irradiance, reflectedLight } = builder.context;
11312    reflectedLight.indirectDiffuse.addAssign(irradiance.mul(BRDF_Lambert({ diffuseColor })));
11313    reflectedLight.indirectDiffuse.mulAssign(ambientOcclusion);
11314  }
11315};
11316var _defaultValues$8 = /* @__PURE__ */ new MeshLambertMaterial();
11317var MeshLambertNodeMaterial = class extends NodeMaterial {
11318  static get type() {
11319    return "MeshLambertNodeMaterial";
11320  }
11321  /**
11322   * Constructs a new mesh lambert node material.
11323   *
11324   * @param {Object} [parameters] - The configuration parameter.
11325   */
11326  constructor(parameters) {
11327    super();
11328    this.isMeshLambertNodeMaterial = true;
11329    this.lights = true;
11330    this.setDefaultValues(_defaultValues$8);
11331    this.setValues(parameters);
11332  }
11333  /**
11334   * Overwritten since this type of material uses {@link BasicEnvironmentNode}
11335   * to implement the default environment mapping.
11336   *
11337   * @param {NodeBuilder} builder - The current node builder.
11338   * @return {?BasicEnvironmentNode<vec3>} The environment node.
11339   */
11340  setupEnvironment(builder) {
11341    const envNode = super.setupEnvironment(builder);
11342    return envNode ? new BasicEnvironmentNode(envNode) : null;
11343  }
11344  /**
11345   * Setups the lighting model.
11346   *
11347   * @return {PhongLightingModel} The lighting model.
11348   */
11349  setupLightingModel() {
11350    return new PhongLightingModel(false);
11351  }
11352};
11353var _defaultValues$7 = /* @__PURE__ */ new MeshPhongMaterial();
11354var MeshPhongNodeMaterial = class extends NodeMaterial {
11355  static get type() {
11356    return "MeshPhongNodeMaterial";
11357  }
11358  /**
11359   * Constructs a new mesh lambert node material.
11360   *
11361   * @param {Object} [parameters] - The configuration parameter.
11362   */
11363  constructor(parameters) {
11364    super();
11365    this.isMeshPhongNodeMaterial = true;
11366    this.lights = true;
11367    this.shininessNode = null;
11368    this.specularNode = null;
11369    this.setDefaultValues(_defaultValues$7);
11370    this.setValues(parameters);
11371  }
11372  /**
11373   * Overwritten since this type of material uses {@link BasicEnvironmentNode}
11374   * to implement the default environment mapping.
11375   *
11376   * @param {NodeBuilder} builder - The current node builder.
11377   * @return {?BasicEnvironmentNode<vec3>} The environment node.
11378   */
11379  setupEnvironment(builder) {
11380    const envNode = super.setupEnvironment(builder);
11381    return envNode ? new BasicEnvironmentNode(envNode) : null;
11382  }
11383  /**
11384   * Setups the lighting model.
11385   *
11386   * @return {PhongLightingModel} The lighting model.
11387   */
11388  setupLightingModel() {
11389    return new PhongLightingModel();
11390  }
11391  /**
11392   * Setups the phong specific node variables.
11393   *
11394   * @param {NodeBuilder} builder - The current node builder.
11395   */
11396  setupVariants() {
11397    const shininessNode = (this.shininessNode ? float(this.shininessNode) : materialShininess).max(1e-4);
11398    shininess.assign(shininessNode);
11399    const specularNode = this.specularNode || materialSpecular;
11400    specularColor.assign(specularNode);
11401  }
11402  copy(source) {
11403    this.shininessNode = source.shininessNode;
11404    this.specularNode = source.specularNode;
11405    return super.copy(source);
11406  }
11407};
11408var getGeometryRoughness = /* @__PURE__ */ Fn((builder) => {
11409  if (builder.geometry.hasAttribute("normal") === false) {
11410    return float(0);
11411  }
11412  const dxy = normalViewGeometry.dFdx().abs().max(normalViewGeometry.dFdy().abs());
11413  const geometryRoughness = dxy.x.max(dxy.y).max(dxy.z);
11414  return geometryRoughness;
11415});
11416var getRoughness = /* @__PURE__ */ Fn((inputs) => {
11417  const { roughness: roughness3 } = inputs;
11418  const geometryRoughness = getGeometryRoughness();
11419  let roughnessFactor = roughness3.max(0.0525);
11420  roughnessFactor = roughnessFactor.add(geometryRoughness);
11421  roughnessFactor = roughnessFactor.min(1);
11422  return roughnessFactor;
11423});
11424var V_GGX_SmithCorrelated = /* @__PURE__ */ Fn(({ alpha, dotNL, dotNV }) => {
11425  const a2 = alpha.pow2();
11426  const gv = dotNL.mul(a2.add(a2.oneMinus().mul(dotNV.pow2())).sqrt());
11427  const gl = dotNV.mul(a2.add(a2.oneMinus().mul(dotNL.pow2())).sqrt());
11428  return div(0.5, gv.add(gl).max(EPSILON));
11429}).setLayout({
11430  name: "V_GGX_SmithCorrelated",
11431  type: "float",
11432  inputs: [
11433    { name: "alpha", type: "float" },
11434    { name: "dotNL", type: "float" },
11435    { name: "dotNV", type: "float" }
11436  ]
11437});
11438var V_GGX_SmithCorrelated_Anisotropic = /* @__PURE__ */ Fn(({ alphaT: alphaT3, alphaB, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL }) => {
11439  const gv = dotNL.mul(vec3(alphaT3.mul(dotTV), alphaB.mul(dotBV), dotNV).length());
11440  const gl = dotNV.mul(vec3(alphaT3.mul(dotTL), alphaB.mul(dotBL), dotNL).length());
11441  return div(0.5, gv.add(gl).max(EPSILON));
11442}).setLayout({
11443  name: "V_GGX_SmithCorrelated_Anisotropic",
11444  type: "float",
11445  inputs: [
11446    { name: "alphaT", type: "float", qualifier: "in" },
11447    { name: "alphaB", type: "float", qualifier: "in" },
11448    { name: "dotTV", type: "float", qualifier: "in" },
11449    { name: "dotBV", type: "float", qualifier: "in" },
11450    { name: "dotTL", type: "float", qualifier: "in" },
11451    { name: "dotBL", type: "float", qualifier: "in" },
11452    { name: "dotNV", type: "float", qualifier: "in" },
11453    { name: "dotNL", type: "float", qualifier: "in" }
11454  ]
11455});
11456var D_GGX = /* @__PURE__ */ Fn(({ alpha, dotNH }) => {
11457  const a2 = alpha.pow2();
11458  const denom = dotNH.pow2().mul(a2.oneMinus()).oneMinus();
11459  return a2.div(denom.pow2()).mul(1 / Math.PI);
11460}).setLayout({
11461  name: "D_GGX",
11462  type: "float",
11463  inputs: [
11464    { name: "alpha", type: "float" },
11465    { name: "dotNH", type: "float" }
11466  ]
11467});
11468var RECIPROCAL_PI = /* @__PURE__ */ float(1 / Math.PI);
11469var D_GGX_Anisotropic = /* @__PURE__ */ Fn(({ alphaT: alphaT3, alphaB, dotNH, dotTH, dotBH }) => {
11470  const a2 = alphaT3.mul(alphaB);
11471  const v = vec3(alphaB.mul(dotTH), alphaT3.mul(dotBH), a2.mul(dotNH));
11472  const v2 = v.dot(v);
11473  const w22 = a2.div(v2);
11474  return RECIPROCAL_PI.mul(a2.mul(w22.pow2()));
11475}).setLayout({
11476  name: "D_GGX_Anisotropic",
11477  type: "float",
11478  inputs: [
11479    { name: "alphaT", type: "float", qualifier: "in" },
11480    { name: "alphaB", type: "float", qualifier: "in" },
11481    { name: "dotNH", type: "float", qualifier: "in" },
11482    { name: "dotTH", type: "float", qualifier: "in" },
11483    { name: "dotBH", type: "float", qualifier: "in" }
11484  ]
11485});
11486var BRDF_GGX = /* @__PURE__ */ Fn(({ lightDirection, f0, f90, roughness: roughness3, f, normalView: normalView$1 = normalView, USE_IRIDESCENCE, USE_ANISOTROPY }) => {
11487  const alpha = roughness3.pow2();
11488  const halfDir = lightDirection.add(positionViewDirection).normalize();
11489  const dotNL = normalView$1.dot(lightDirection).clamp();
11490  const dotNV = normalView$1.dot(positionViewDirection).clamp();
11491  const dotNH = normalView$1.dot(halfDir).clamp();
11492  const dotVH = positionViewDirection.dot(halfDir).clamp();
11493  let F = F_Schlick({ f0, f90, dotVH });
11494  let V, D;
11495  if (defined(USE_IRIDESCENCE)) {
11496    F = iridescence.mix(F, f);
11497  }
11498  if (defined(USE_ANISOTROPY)) {
11499    const dotTL = anisotropyT.dot(lightDirection);
11500    const dotTV = anisotropyT.dot(positionViewDirection);
11501    const dotTH = anisotropyT.dot(halfDir);
11502    const dotBL = anisotropyB.dot(lightDirection);
11503    const dotBV = anisotropyB.dot(positionViewDirection);
11504    const dotBH = anisotropyB.dot(halfDir);
11505    V = V_GGX_SmithCorrelated_Anisotropic({ alphaT, alphaB: alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL });
11506    D = D_GGX_Anisotropic({ alphaT, alphaB: alpha, dotNH, dotTH, dotBH });
11507  } else {
11508    V = V_GGX_SmithCorrelated({ alpha, dotNL, dotNV });
11509    D = D_GGX({ alpha, dotNH });
11510  }
11511  return F.mul(V).mul(D);
11512});
11513var DATA = new Uint16Array([
11514  12469,
11515  15057,
11516  12620,
11517  14925,
11518  13266,
11519  14620,
11520  13807,
11521  14376,
11522  14323,
11523  13990,
11524  14545,
11525  13625,
11526  14713,
11527  13328,
11528  14840,
11529  12882,
11530  14931,
11531  12528,
11532  14996,
11533  12233,
11534  15039,
11535  11829,
11536  15066,
11537  11525,
11538  15080,
11539  11295,
11540  15085,
11541  10976,
11542  15082,
11543  10705,
11544  15073,
11545  10495,
11546  13880,
11547  14564,
11548  13898,
11549  14542,
11550  13977,
11551  14430,
11552  14158,
11553  14124,
11554  14393,
11555  13732,
11556  14556,
11557  13410,
11558  14702,
11559  12996,
11560  14814,
11561  12596,
11562  14891,
11563  12291,
11564  14937,
11565  11834,
11566  14957,
11567  11489,
11568  14958,
11569  11194,
11570  14943,
11571  10803,
11572  14921,
11573  10506,
11574  14893,
11575  10278,
11576  14858,
11577  9960,
11578  14484,
11579  14039,
11580  14487,
11581  14025,
11582  14499,
11583  13941,
11584  14524,
11585  13740,
11586  14574,
11587  13468,
11588  14654,
11589  13106,
11590  14743,
11591  12678,
11592  14818,
11593  12344,
11594  14867,
11595  11893,
11596  14889,
11597  11509,
11598  14893,
11599  11180,
11600  14881,
11601  10751,
11602  14852,
11603  10428,
11604  14812,
11605  10128,
11606  14765,
11607  9754,
11608  14712,
11609  9466,
11610  14764,
11611  13480,
11612  14764,
11613  13475,
11614  14766,
11615  13440,
11616  14766,
11617  13347,
11618  14769,
11619  13070,
11620  14786,
11621  12713,
11622  14816,
11623  12387,
11624  14844,
11625  11957,
11626  14860,
11627  11549,
11628  14868,
11629  11215,
11630  14855,
11631  10751,
11632  14825,
11633  10403,
11634  14782,
11635  10044,
11636  14729,
11637  9651,
11638  14666,
11639  9352,
11640  14599,
11641  9029,
11642  14967,
11643  12835,
11644  14966,
11645  12831,
11646  14963,
11647  12804,
11648  14954,
11649  12723,
11650  14936,
11651  12564,
11652  14917,
11653  12347,
11654  14900,
11655  11958,
11656  14886,
11657  11569,
11658  14878,
11659  11247,
11660  14859,
11661  10765,
11662  14828,
11663  10401,
11664  14784,
11665  10011,
11666  14727,
11667  9600,
11668  14660,
11669  9289,
11670  14586,
11671  8893,
11672  14508,
11673  8533,
11674  15111,
11675  12234,
11676  15110,
11677  12234,
11678  15104,
11679  12216,
11680  15092,
11681  12156,
11682  15067,
11683  12010,
11684  15028,
11685  11776,
11686  14981,
11687  11500,
11688  14942,
11689  11205,
11690  14902,
11691  10752,
11692  14861,
11693  10393,
11694  14812,
11695  9991,
11696  14752,
11697  9570,
11698  14682,
11699  9252,
11700  14603,
11701  8808,
11702  14519,
11703  8445,
11704  14431,
11705  8145,
11706  15209,
11707  11449,
11708  15208,
11709  11451,
11710  15202,
11711  11451,
11712  15190,
11713  11438,
11714  15163,
11715  11384,
11716  15117,
11717  11274,
11718  15055,
11719  10979,
11720  14994,
11721  10648,
11722  14932,
11723  10343,
11724  14871,
11725  9936,
11726  14803,
11727  9532,
11728  14729,
11729  9218,
11730  14645,
11731  8742,
11732  14556,
11733  8381,
11734  14461,
11735  8020,
11736  14365,
11737  7603,
11738  15273,
11739  10603,
11740  15272,
11741  10607,
11742  15267,
11743  10619,
11744  15256,
11745  10631,
11746  15231,
11747  10614,
11748  15182,
11749  10535,
11750  15118,
11751  10389,
11752  15042,
11753  10167,
11754  14963,
11755  9787,
11756  14883,
11757  9447,
11758  14800,
11759  9115,
11760  14710,
11761  8665,
11762  14615,
11763  8318,
11764  14514,
11765  7911,
11766  14411,
11767  7507,
11768  14279,
11769  7198,
11770  15314,
11771  9675,
11772  15313,
11773  9683,
11774  15309,
11775  9712,
11776  15298,
11777  9759,
11778  15277,
11779  9797,
11780  15229,
11781  9773,
11782  15166,
11783  9668,
11784  15084,
11785  9487,
11786  14995,
11787  9274,
11788  14898,
11789  8910,
11790  14800,
11791  8539,
11792  14697,
11793  8234,
11794  14590,
11795  7790,
11796  14479,
11797  7409,
11798  14367,
11799  7067,
11800  14178,
11801  6621,
11802  15337,
11803  8619,
11804  15337,
11805  8631,
11806  15333,
11807  8677,
11808  15325,
11809  8769,
11810  15305,
11811  8871,
11812  15264,
11813  8940,
11814  15202,
11815  8909,
11816  15119,
11817  8775,
11818  15022,
11819  8565,
11820  14916,
11821  8328,
11822  14804,
11823  8009,
11824  14688,
11825  7614,
11826  14569,
11827  7287,
11828  14448,
11829  6888,
11830  14321,
11831  6483,
11832  14088,
11833  6171,
11834  15350,
11835  7402,
11836  15350,
11837  7419,
11838  15347,
11839  7480,
11840  15340,
11841  7613,
11842  15322,
11843  7804,
11844  15287,
11845  7973,
11846  15229,
11847  8057,
11848  15148,
11849  8012,
11850  15046,
11851  7846,
11852  14933,
11853  7611,
11854  14810,
11855  7357,
11856  14682,
11857  7069,
11858  14552,
11859  6656,
11860  14421,
11861  6316,
11862  14251,
11863  5948,
11864  14007,
11865  5528,
11866  15356,
11867  5942,
11868  15356,
11869  5977,
11870  15353,
11871  6119,
11872  15348,
11873  6294,
11874  15332,
11875  6551,
11876  15302,
11877  6824,
11878  15249,
11879  7044,
11880  15171,
11881  7122,
11882  15070,
11883  7050,
11884  14949,
11885  6861,
11886  14818,
11887  6611,
11888  14679,
11889  6349,
11890  14538,
11891  6067,
11892  14398,
11893  5651,
11894  14189,
11895  5311,
11896  13935,
11897  4958,
11898  15359,
11899  4123,
11900  15359,
11901  4153,
11902  15356,
11903  4296,
11904  15353,
11905  4646,
11906  15338,
11907  5160,
11908  15311,
11909  5508,
11910  15263,
11911  5829,
11912  15188,
11913  6042,
11914  15088,
11915  6094,
11916  14966,
11917  6001,
11918  14826,
11919  5796,
11920  14678,
11921  5543,
11922  14527,
11923  5287,
11924  14377,
11925  4985,
11926  14133,
11927  4586,
11928  13869,
11929  4257,
11930  15360,
11931  1563,
11932  15360,
11933  1642,
11934  15358,
11935  2076,
11936  15354,
11937  2636,
11938  15341,
11939  3350,
11940  15317,
11941  4019,
11942  15273,
11943  4429,
11944  15203,
11945  4732,
11946  15105,
11947  4911,
11948  14981,
11949  4932,
11950  14836,
11951  4818,
11952  14679,
11953  4621,
11954  14517,
11955  4386,
11956  14359,
11957  4156,
11958  14083,
11959  3795,
11960  13808,
11961  3437,
11962  15360,
11963  122,
11964  15360,
11965  137,
11966  15358,
11967  285,
11968  15355,
11969  636,
11970  15344,
11971  1274,
11972  15322,
11973  2177,
11974  15281,
11975  2765,
11976  15215,
11977  3223,
11978  15120,
11979  3451,
11980  14995,
11981  3569,
11982  14846,
11983  3567,
11984  14681,
11985  3466,
11986  14511,
11987  3305,
11988  14344,
11989  3121,
11990  14037,
11991  2800,
11992  13753,
11993  2467,
11994  15360,
11995  0,
11996  15360,
11997  1,
11998  15359,
11999  21,
12000  15355,
12001  89,
12002  15346,
12003  253,
12004  15325,
12005  479,
12006  15287,
12007  796,
12008  15225,
12009  1148,
12010  15133,
12011  1492,
12012  15008,
12013  1749,
12014  14856,
12015  1882,
12016  14685,
12017  1886,
12018  14506,
12019  1783,
12020  14324,
12021  1608,
12022  13996,
12023  1398,
12024  13702,
12025  1183
12026]);
12027var lut = null;
12028var DFGLUT = /* @__PURE__ */ Fn(({ roughness: roughness3, dotNV }) => {
12029  if (lut === null) {
12030    lut = new DataTexture(DATA, 16, 16, RGFormat, HalfFloatType);
12031    lut.name = "DFG_LUT";
12032    lut.minFilter = LinearFilter;
12033    lut.magFilter = LinearFilter;
12034    lut.wrapS = ClampToEdgeWrapping;
12035    lut.wrapT = ClampToEdgeWrapping;
12036    lut.generateMipmaps = false;
12037    lut.needsUpdate = true;
12038  }
12039  const uv3 = vec2(roughness3, dotNV);
12040  return texture(lut, uv3).rg;
12041});
12042var BRDF_GGX_Multiscatter = /* @__PURE__ */ Fn(({ lightDirection, f0, f90, roughness: _roughness, f, USE_IRIDESCENCE, USE_ANISOTROPY }) => {
12043  const singleScatter = BRDF_GGX({ lightDirection, f0, f90, roughness: _roughness, f, USE_IRIDESCENCE, USE_ANISOTROPY });
12044  const dotNL = normalView.dot(lightDirection).clamp();
12045  const dotNV = normalView.dot(positionViewDirection).clamp();
12046  const dfgV = DFGLUT({ roughness: _roughness, dotNV });
12047  const dfgL = DFGLUT({ roughness: _roughness, dotNV: dotNL });
12048  const FssEss_V = f0.mul(dfgV.x).add(f90.mul(dfgV.y));
12049  const FssEss_L = f0.mul(dfgL.x).add(f90.mul(dfgL.y));
12050  const Ess_V = dfgV.x.add(dfgV.y);
12051  const Ess_L = dfgL.x.add(dfgL.y);
12052  const Ems_V = float(1).sub(Ess_V);
12053  const Ems_L = float(1).sub(Ess_L);
12054  const Favg = f0.add(f0.oneMinus().mul(0.047619));
12055  const Fms = FssEss_V.mul(FssEss_L).mul(Favg).div(float(1).sub(Ems_V.mul(Ems_L).mul(Favg).mul(Favg)).add(EPSILON));
12056  const compensationFactor = Ems_V.mul(Ems_L);
12057  const multiScatter = Fms.mul(compensationFactor);
12058  return singleScatter.add(multiScatter);
12059});
12060var EnvironmentBRDF = /* @__PURE__ */ Fn((inputs) => {
12061  const { dotNV, specularColor: specularColor3, specularF90: specularF903, roughness: roughness3 } = inputs;
12062  const fab = DFGLUT({ dotNV, roughness: roughness3 });
12063  return specularColor3.mul(fab.x).add(specularF903.mul(fab.y));
12064});
12065var Schlick_to_F0 = /* @__PURE__ */ Fn(({ f, f90, dotVH }) => {
12066  const x = dotVH.oneMinus().saturate();
12067  const x2 = x.mul(x);
12068  const x5 = x.mul(x2, x2).clamp(0, 0.9999);
12069  return f.sub(vec3(f90).mul(x5)).div(x5.oneMinus());
12070}).setLayout({
12071  name: "Schlick_to_F0",
12072  type: "vec3",
12073  inputs: [
12074    { name: "f", type: "vec3" },
12075    { name: "f90", type: "float" },
12076    { name: "dotVH", type: "float" }
12077  ]
12078});
12079var D_Charlie = /* @__PURE__ */ Fn(({ roughness: roughness3, dotNH }) => {
12080  const alpha = roughness3.pow2();
12081  const invAlpha = float(1).div(alpha);
12082  const cos2h = dotNH.pow2();
12083  const sin2h = cos2h.oneMinus().max(78125e-7);
12084  return float(2).add(invAlpha).mul(sin2h.pow(invAlpha.mul(0.5))).div(2 * Math.PI);
12085}).setLayout({
12086  name: "D_Charlie",
12087  type: "float",
12088  inputs: [
12089    { name: "roughness", type: "float" },
12090    { name: "dotNH", type: "float" }
12091  ]
12092});
12093var V_Neubelt = /* @__PURE__ */ Fn(({ dotNV, dotNL }) => {
12094  return float(1).div(float(4).mul(dotNL.add(dotNV).sub(dotNL.mul(dotNV))));
12095}).setLayout({
12096  name: "V_Neubelt",
12097  type: "float",
12098  inputs: [
12099    { name: "dotNV", type: "float" },
12100    { name: "dotNL", type: "float" }
12101  ]
12102});
12103var BRDF_Sheen = /* @__PURE__ */ Fn(({ lightDirection }) => {
12104  const halfDir = lightDirection.add(positionViewDirection).normalize();
12105  const dotNL = normalView.dot(lightDirection).clamp();
12106  const dotNV = normalView.dot(positionViewDirection).clamp();
12107  const dotNH = normalView.dot(halfDir).clamp();
12108  const D = D_Charlie({ roughness: sheenRoughness, dotNH });
12109  const V = V_Neubelt({ dotNV, dotNL });
12110  return sheen.mul(D).mul(V);
12111});
12112var LTC_Uv = /* @__PURE__ */ Fn(({ N: N2, V, roughness: roughness3 }) => {
12113  const LUT_SIZE = 64;
12114  const LUT_SCALE = (LUT_SIZE - 1) / LUT_SIZE;
12115  const LUT_BIAS = 0.5 / LUT_SIZE;
12116  const dotNV = N2.dot(V).saturate();
12117  const uv3 = vec2(roughness3, dotNV.oneMinus().sqrt());
12118  uv3.assign(uv3.mul(LUT_SCALE).add(LUT_BIAS));
12119  return uv3;
12120}).setLayout({
12121  name: "LTC_Uv",
12122  type: "vec2",
12123  inputs: [
12124    { name: "N", type: "vec3" },
12125    { name: "V", type: "vec3" },
12126    { name: "roughness", type: "float" }
12127  ]
12128});
12129var LTC_ClippedSphereFormFactor = /* @__PURE__ */ Fn(({ f }) => {
12130  const l = f.length();
12131  return max$1(l.mul(l).add(f.z).div(l.add(1)), 0);
12132}).setLayout({
12133  name: "LTC_ClippedSphereFormFactor",
12134  type: "float",
12135  inputs: [
12136    { name: "f", type: "vec3" }
12137  ]
12138});
12139var LTC_EdgeVectorFormFactor = /* @__PURE__ */ Fn(({ v1, v2 }) => {
12140  const x = v1.dot(v2);
12141  const y = x.abs().toVar();
12142  const a = y.mul(0.0145206).add(0.4965155).mul(y).add(0.8543985).toVar();
12143  const b = y.add(4.1616724).mul(y).add(3.417594).toVar();
12144  const v = a.div(b);
12145  const theta_sintheta = x.greaterThan(0).select(v, max$1(x.mul(x).oneMinus(), 1e-7).inverseSqrt().mul(0.5).sub(v));
12146  return v1.cross(v2).mul(theta_sintheta);
12147}).setLayout({
12148  name: "LTC_EdgeVectorFormFactor",
12149  type: "vec3",
12150  inputs: [
12151    { name: "v1", type: "vec3" },
12152    { name: "v2", type: "vec3" }
12153  ]
12154});
12155var LTC_Evaluate = /* @__PURE__ */ Fn(({ N: N2, V, P, mInv, p0, p1, p2, p3 }) => {
12156  const v1 = p1.sub(p0).toVar();
12157  const v2 = p3.sub(p0).toVar();
12158  const lightNormal = v1.cross(v2);
12159  const result = vec3().toVar();
12160  If(lightNormal.dot(P.sub(p0)).greaterThanEqual(0), () => {
12161    const T1 = V.sub(N2.mul(V.dot(N2))).normalize();
12162    const T22 = N2.cross(T1).negate();
12163    const mat = mInv.mul(mat3(T1, T22, N2).transpose()).toVar();
12164    const coords0 = mat.mul(p0.sub(P)).normalize().toVar();
12165    const coords1 = mat.mul(p1.sub(P)).normalize().toVar();
12166    const coords2 = mat.mul(p2.sub(P)).normalize().toVar();
12167    const coords3 = mat.mul(p3.sub(P)).normalize().toVar();
12168    const vectorFormFactor = vec3(0).toVar();
12169    vectorFormFactor.addAssign(LTC_EdgeVectorFormFactor({ v1: coords0, v2: coords1 }));
12170    vectorFormFactor.addAssign(LTC_EdgeVectorFormFactor({ v1: coords1, v2: coords2 }));
12171    vectorFormFactor.addAssign(LTC_EdgeVectorFormFactor({ v1: coords2, v2: coords3 }));
12172    vectorFormFactor.addAssign(LTC_EdgeVectorFormFactor({ v1: coords3, v2: coords0 }));
12173    result.assign(vec3(LTC_ClippedSphereFormFactor({ f: vectorFormFactor })));
12174  });
12175  return result;
12176}).setLayout({
12177  name: "LTC_Evaluate",
12178  type: "vec3",
12179  inputs: [
12180    { name: "N", type: "vec3" },
12181    { name: "V", type: "vec3" },
12182    { name: "P", type: "vec3" },
12183    { name: "mInv", type: "mat3" },
12184    { name: "p0", type: "vec3" },
12185    { name: "p1", type: "vec3" },
12186    { name: "p2", type: "vec3" },
12187    { name: "p3", type: "vec3" }
12188  ]
12189});
12190var bC = 1 / 6;
12191var w0 = (a) => mul(bC, mul(a, mul(a, a.negate().add(3)).sub(3)).add(1));
12192var w1 = (a) => mul(bC, mul(a, mul(a, mul(3, a).sub(6))).add(4));
12193var w2 = (a) => mul(bC, mul(a, mul(a, mul(-3, a).add(3)).add(3)).add(1));
12194var w3 = (a) => mul(bC, pow(a, 3));
12195var g0 = (a) => w0(a).add(w1(a));
12196var g1 = (a) => w2(a).add(w3(a));
12197var h0 = (a) => add(-1, w1(a).div(w0(a).add(w1(a))));
12198var h1 = (a) => add(1, w3(a).div(w2(a).add(w3(a))));
12199var bicubic = (textureNode, texelSize, lod) => {
12200  const uv3 = textureNode.uvNode;
12201  const uvScaled = mul(uv3, texelSize.zw).add(0.5);
12202  const iuv = floor(uvScaled);
12203  const fuv = fract(uvScaled);
12204  const g0x = g0(fuv.x);
12205  const g1x = g1(fuv.x);
12206  const h0x = h0(fuv.x);
12207  const h1x = h1(fuv.x);
12208  const h0y = h0(fuv.y);
12209  const h1y = h1(fuv.y);
12210  const p0 = vec2(iuv.x.add(h0x), iuv.y.add(h0y)).sub(0.5).mul(texelSize.xy);
12211  const p1 = vec2(iuv.x.add(h1x), iuv.y.add(h0y)).sub(0.5).mul(texelSize.xy);
12212  const p2 = vec2(iuv.x.add(h0x), iuv.y.add(h1y)).sub(0.5).mul(texelSize.xy);
12213  const p3 = vec2(iuv.x.add(h1x), iuv.y.add(h1y)).sub(0.5).mul(texelSize.xy);
12214  const a = g0(fuv.y).mul(add(g0x.mul(textureNode.sample(p0).level(lod)), g1x.mul(textureNode.sample(p1).level(lod))));
12215  const b = g1(fuv.y).mul(add(g0x.mul(textureNode.sample(p2).level(lod)), g1x.mul(textureNode.sample(p3).level(lod))));
12216  return a.add(b);
12217};
12218var textureBicubicLevel = /* @__PURE__ */ Fn(([textureNode, lodNode]) => {
12219  const fLodSize = vec2(textureNode.size(int(lodNode)));
12220  const cLodSize = vec2(textureNode.size(int(lodNode.add(1))));
12221  const fLodSizeInv = div(1, fLodSize);
12222  const cLodSizeInv = div(1, cLodSize);
12223  const fSample = bicubic(textureNode, vec4(fLodSizeInv, fLodSize), floor(lodNode));
12224  const cSample = bicubic(textureNode, vec4(cLodSizeInv, cLodSize), ceil(lodNode));
12225  return fract(lodNode).mix(fSample, cSample);
12226});
12227var textureBicubic = /* @__PURE__ */ Fn(([textureNode, strength]) => {
12228  const lod = strength.mul(maxMipLevel(textureNode));
12229  return textureBicubicLevel(textureNode, lod);
12230});
12231var getVolumeTransmissionRay = /* @__PURE__ */ Fn(([n, v, thickness3, ior3, modelMatrix]) => {
12232  const refractionVector = vec3(refract(v.negate(), normalize(n), div(1, ior3)));
12233  const modelScale3 = vec3(
12234    length(modelMatrix[0].xyz),
12235    length(modelMatrix[1].xyz),
12236    length(modelMatrix[2].xyz)
12237  );
12238  return normalize(refractionVector).mul(thickness3.mul(modelScale3));
12239}).setLayout({
12240  name: "getVolumeTransmissionRay",
12241  type: "vec3",
12242  inputs: [
12243    { name: "n", type: "vec3" },
12244    { name: "v", type: "vec3" },
12245    { name: "thickness", type: "float" },
12246    { name: "ior", type: "float" },
12247    { name: "modelMatrix", type: "mat4" }
12248  ]
12249});
12250var applyIorToRoughness = /* @__PURE__ */ Fn(([roughness3, ior3]) => {
12251  return roughness3.mul(clamp(ior3.mul(2).sub(2), 0, 1));
12252}).setLayout({
12253  name: "applyIorToRoughness",
12254  type: "float",
12255  inputs: [
12256    { name: "roughness", type: "float" },
12257    { name: "ior", type: "float" }
12258  ]
12259});
12260var viewportBackSideTexture = /* @__PURE__ */ viewportMipTexture();
12261var viewportFrontSideTexture = /* @__PURE__ */ viewportOpaqueMipTexture();
12262var getTransmissionSample = /* @__PURE__ */ Fn(([fragCoord, roughness3, ior3], { material }) => {
12263  const vTexture = material.side === BackSide ? viewportBackSideTexture : viewportFrontSideTexture;
12264  const transmissionSample = vTexture.sample(fragCoord);
12265  const lod = log22(screenSize.x).mul(applyIorToRoughness(roughness3, ior3));
12266  return textureBicubicLevel(transmissionSample, lod);
12267});
12268var volumeAttenuation = /* @__PURE__ */ Fn(([transmissionDistance, attenuationColor3, attenuationDistance3]) => {
12269  If(attenuationDistance3.notEqual(0), () => {
12270    const attenuationCoefficient = log2(attenuationColor3).negate().div(attenuationDistance3);
12271    const transmittance = exp(attenuationCoefficient.negate().mul(transmissionDistance));
12272    return transmittance;
12273  });
12274  return vec3(1);
12275}).setLayout({
12276  name: "volumeAttenuation",
12277  type: "vec3",
12278  inputs: [
12279    { name: "transmissionDistance", type: "float" },
12280    { name: "attenuationColor", type: "vec3" },
12281    { name: "attenuationDistance", type: "float" }
12282  ]
12283});
12284var getIBLVolumeRefraction = /* @__PURE__ */ Fn(([n, v, roughness3, diffuseColor3, specularColor3, specularF903, position, modelMatrix, viewMatrix, projMatrix, ior3, thickness3, attenuationColor3, attenuationDistance3, dispersion3]) => {
12285  let transmittedLight, transmittance;
12286  if (dispersion3) {
12287    transmittedLight = vec4().toVar();
12288    transmittance = vec3().toVar();
12289    const halfSpread = ior3.sub(1).mul(dispersion3.mul(0.025));
12290    const iors = vec3(ior3.sub(halfSpread), ior3, ior3.add(halfSpread));
12291    Loop({ start: 0, end: 3 }, ({ i }) => {
12292      const ior4 = iors.element(i);
12293      const transmissionRay = getVolumeTransmissionRay(n, v, thickness3, ior4, modelMatrix);
12294      const refractedRayExit = position.add(transmissionRay);
12295      const ndcPos = projMatrix.mul(viewMatrix.mul(vec4(refractedRayExit, 1)));
12296      const refractionCoords = vec2(ndcPos.xy.div(ndcPos.w)).toVar();
12297      refractionCoords.addAssign(1);
12298      refractionCoords.divAssign(2);
12299      refractionCoords.assign(vec2(refractionCoords.x, refractionCoords.y.oneMinus()));
12300      const transmissionSample = getTransmissionSample(refractionCoords, roughness3, ior4);
12301      transmittedLight.element(i).assign(transmissionSample.element(i));
12302      transmittedLight.a.addAssign(transmissionSample.a);
12303      transmittance.element(i).assign(diffuseColor3.element(i).mul(volumeAttenuation(length(transmissionRay), attenuationColor3, attenuationDistance3).element(i)));
12304    });
12305    transmittedLight.a.divAssign(3);
12306  } else {
12307    const transmissionRay = getVolumeTransmissionRay(n, v, thickness3, ior3, modelMatrix);
12308    const refractedRayExit = position.add(transmissionRay);
12309    const ndcPos = projMatrix.mul(viewMatrix.mul(vec4(refractedRayExit, 1)));
12310    const refractionCoords = vec2(ndcPos.xy.div(ndcPos.w)).toVar();
12311    refractionCoords.addAssign(1);
12312    refractionCoords.divAssign(2);
12313    refractionCoords.assign(vec2(refractionCoords.x, refractionCoords.y.oneMinus()));
12314    transmittedLight = getTransmissionSample(refractionCoords, roughness3, ior3);
12315    transmittance = diffuseColor3.mul(volumeAttenuation(length(transmissionRay), attenuationColor3, attenuationDistance3));
12316  }
12317  const attenuatedColor = transmittance.rgb.mul(transmittedLight.rgb);
12318  const dotNV = n.dot(v).clamp();
12319  const F = vec3(EnvironmentBRDF({
12320    // n, v, specularColor, specularF90, roughness
12321    dotNV,
12322    specularColor: specularColor3,
12323    specularF90: specularF903,
12324    roughness: roughness3
12325  }));
12326  const transmittanceFactor = transmittance.r.add(transmittance.g, transmittance.b).div(3);
12327  return vec4(F.oneMinus().mul(attenuatedColor), transmittedLight.a.oneMinus().mul(transmittanceFactor).oneMinus());
12328});
12329var XYZ_TO_REC709 = /* @__PURE__ */ mat3(
12330  3.2404542,
12331  -0.969266,
12332  0.0556434,
12333  -1.5371385,
12334  1.8760108,
12335  -0.2040259,
12336  -0.4985314,
12337  0.041556,
12338  1.0572252
12339);
12340var Fresnel0ToIor = (fresnel0) => {
12341  const sqrtF0 = fresnel0.sqrt();
12342  return vec3(1).add(sqrtF0).div(vec3(1).sub(sqrtF0));
12343};
12344var IorToFresnel0 = (transmittedIor, incidentIor) => {
12345  return transmittedIor.sub(incidentIor).div(transmittedIor.add(incidentIor)).pow2();
12346};
12347var evalSensitivity = (OPD, shift3) => {
12348  const phase = OPD.mul(2 * Math.PI * 1e-9);
12349  const val = vec3(54856e-17, 44201e-17, 52481e-17);
12350  const pos = vec3(1681e3, 1795300, 2208400);
12351  const VAR = vec3(43278e5, 93046e5, 66121e5);
12352  const x = float(9747e-17 * Math.sqrt(2 * Math.PI * 45282e5)).mul(phase.mul(2239900).add(shift3.x).cos()).mul(phase.pow2().mul(-45282e5).exp());
12353  let xyz = val.mul(VAR.mul(2 * Math.PI).sqrt()).mul(pos.mul(phase).add(shift3).cos()).mul(phase.pow2().negate().mul(VAR).exp());
12354  xyz = vec3(xyz.x.add(x), xyz.y, xyz.z).div(10685e-11);
12355  const rgb = XYZ_TO_REC709.mul(xyz);
12356  return rgb;
12357};
12358var evalIridescence = /* @__PURE__ */ Fn(({ outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0 }) => {
12359  const iridescenceIOR3 = mix(outsideIOR, eta2, smoothstep(0, 0.03, thinFilmThickness));
12360  const sinTheta2Sq = outsideIOR.div(iridescenceIOR3).pow2().mul(cosTheta1.pow2().oneMinus());
12361  const cosTheta2Sq = sinTheta2Sq.oneMinus();
12362  If(cosTheta2Sq.lessThan(0), () => {
12363    return vec3(1);
12364  });
12365  const cosTheta2 = cosTheta2Sq.sqrt();
12366  const R0 = IorToFresnel0(iridescenceIOR3, outsideIOR);
12367  const R12 = F_Schlick({ f0: R0, f90: 1, dotVH: cosTheta1 });
12368  const T121 = R12.oneMinus();
12369  const phi12 = iridescenceIOR3.lessThan(outsideIOR).select(Math.PI, 0);
12370  const phi21 = float(Math.PI).sub(phi12);
12371  const baseIOR = Fresnel0ToIor(baseF0.clamp(0, 0.9999));
12372  const R1 = IorToFresnel0(baseIOR, iridescenceIOR3.toVec3());
12373  const R23 = F_Schlick({ f0: R1, f90: 1, dotVH: cosTheta2 });
12374  const phi23 = vec3(
12375    baseIOR.x.lessThan(iridescenceIOR3).select(Math.PI, 0),
12376    baseIOR.y.lessThan(iridescenceIOR3).select(Math.PI, 0),
12377    baseIOR.z.lessThan(iridescenceIOR3).select(Math.PI, 0)
12378  );
12379  const OPD = iridescenceIOR3.mul(thinFilmThickness, cosTheta2, 2);
12380  const phi = vec3(phi21).add(phi23);
12381  const R123 = R12.mul(R23).clamp(1e-5, 0.9999);
12382  const r123 = R123.sqrt();
12383  const Rs = T121.pow2().mul(R23).div(vec3(1).sub(R123));
12384  const C0 = R12.add(Rs);
12385  const I = C0.toVar();
12386  const Cm = Rs.sub(T121).toVar();
12387  Loop({ start: 1, end: 2, condition: "<=", name: "m" }, ({ m }) => {
12388    Cm.mulAssign(r123);
12389    const Sm = evalSensitivity(float(m).mul(OPD), float(m).mul(phi)).mul(2);
12390    I.addAssign(Cm.mul(Sm));
12391  });
12392  return I.max(vec3(0));
12393}).setLayout({
12394  name: "evalIridescence",
12395  type: "vec3",
12396  inputs: [
12397    { name: "outsideIOR", type: "float" },
12398    { name: "eta2", type: "float" },
12399    { name: "cosTheta1", type: "float" },
12400    { name: "thinFilmThickness", type: "float" },
12401    { name: "baseF0", type: "vec3" }
12402  ]
12403});
12404var IBLSheenBRDF = /* @__PURE__ */ Fn(({ normal: normal2, viewDir, roughness: roughness3 }) => {
12405  const dotNV = normal2.dot(viewDir).saturate();
12406  const r2 = roughness3.mul(roughness3);
12407  const rInv = roughness3.add(0.1).reciprocal();
12408  const a = float(-1.9362).add(roughness3.mul(1.0678)).add(r2.mul(0.4573)).sub(rInv.mul(0.8469));
12409  const b = float(-0.6014).add(roughness3.mul(0.5538)).sub(r2.mul(0.467)).sub(rInv.mul(0.1255));
12410  const DG = a.mul(dotNV).add(b).exp();
12411  return DG.saturate();
12412});
12413var clearcoatF0 = vec3(0.04);
12414var clearcoatF90 = float(1);
12415var PhysicalLightingModel = class extends LightingModel {
12416  /**
12417   * Constructs a new physical lighting model.
12418   *
12419   * @param {boolean} [clearcoat=false] - Whether clearcoat is supported or not.
12420   * @param {boolean} [sheen=false] - Whether sheen is supported or not.
12421   * @param {boolean} [iridescence=false] - Whether iridescence is supported or not.
12422   * @param {boolean} [anisotropy=false] - Whether anisotropy is supported or not.
12423   * @param {boolean} [transmission=false] - Whether transmission is supported or not.
12424   * @param {boolean} [dispersion=false] - Whether dispersion is supported or not.
12425   */
12426  constructor(clearcoat3 = false, sheen3 = false, iridescence3 = false, anisotropy3 = false, transmission3 = false, dispersion3 = false) {
12427    super();
12428    this.clearcoat = clearcoat3;
12429    this.sheen = sheen3;
12430    this.iridescence = iridescence3;
12431    this.anisotropy = anisotropy3;
12432    this.transmission = transmission3;
12433    this.dispersion = dispersion3;
12434    this.clearcoatRadiance = null;
12435    this.clearcoatSpecularDirect = null;
12436    this.clearcoatSpecularIndirect = null;
12437    this.sheenSpecularDirect = null;
12438    this.sheenSpecularIndirect = null;
12439    this.iridescenceFresnel = null;
12440    this.iridescenceF0 = null;
12441    this.iridescenceF0Dielectric = null;
12442    this.iridescenceF0Metallic = null;
12443  }
12444  /**
12445   * Depending on what features are requested, the method prepares certain node variables
12446   * which are later used for lighting computations.
12447   *
12448   * @param {NodeBuilder} builder - The current node builder.
12449   */
12450  start(builder) {
12451    if (this.clearcoat === true) {
12452      this.clearcoatRadiance = vec3().toVar("clearcoatRadiance");
12453      this.clearcoatSpecularDirect = vec3().toVar("clearcoatSpecularDirect");
12454      this.clearcoatSpecularIndirect = vec3().toVar("clearcoatSpecularIndirect");
12455    }
12456    if (this.sheen === true) {
12457      this.sheenSpecularDirect = vec3().toVar("sheenSpecularDirect");
12458      this.sheenSpecularIndirect = vec3().toVar("sheenSpecularIndirect");
12459    }
12460    if (this.iridescence === true) {
12461      const dotNVi = normalView.dot(positionViewDirection).clamp();
12462      const iridescenceFresnelDielectric = evalIridescence({
12463        outsideIOR: float(1),
12464        eta2: iridescenceIOR,
12465        cosTheta1: dotNVi,
12466        thinFilmThickness: iridescenceThickness,
12467        baseF0: specularColor
12468      });
12469      const iridescenceFresnelMetallic = evalIridescence({
12470        outsideIOR: float(1),
12471        eta2: iridescenceIOR,
12472        cosTheta1: dotNVi,
12473        thinFilmThickness: iridescenceThickness,
12474        baseF0: diffuseColor.rgb
12475      });
12476      this.iridescenceFresnel = mix(iridescenceFresnelDielectric, iridescenceFresnelMetallic, metalness);
12477      this.iridescenceF0Dielectric = Schlick_to_F0({ f: iridescenceFresnelDielectric, f90: 1, dotVH: dotNVi });
12478      this.iridescenceF0Metallic = Schlick_to_F0({ f: iridescenceFresnelMetallic, f90: 1, dotVH: dotNVi });
12479      this.iridescenceF0 = mix(this.iridescenceF0Dielectric, this.iridescenceF0Metallic, metalness);
12480    }
12481    if (this.transmission === true) {
12482      const position = positionWorld;
12483      const v = cameraPosition.sub(positionWorld).normalize();
12484      const n = normalWorld;
12485      const context3 = builder.context;
12486      context3.backdrop = getIBLVolumeRefraction(
12487        n,
12488        v,
12489        roughness,
12490        diffuseContribution,
12491        specularColorBlended,
12492        specularF90,
12493        // specularF90
12494        position,
12495        // positionWorld
12496        modelWorldMatrix,
12497        // modelMatrix
12498        cameraViewMatrix,
12499        // viewMatrix
12500        cameraProjectionMatrix,
12501        // projMatrix
12502        ior,
12503        thickness,
12504        attenuationColor,
12505        attenuationDistance,
12506        this.dispersion ? dispersion : null
12507      );
12508      context3.backdropAlpha = transmission;
12509      diffuseColor.a.mulAssign(mix(1, context3.backdrop.a, transmission));
12510    }
12511    super.start(builder);
12512  }
12513  // Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting"
12514  // Approximates multi-scattering in order to preserve energy.
12515  // http://www.jcgt.org/published/0008/01/03/
12516  computeMultiscattering(singleScatter, multiScatter, specularF903, f0, iridescenceF0 = null) {
12517    const dotNV = normalView.dot(positionViewDirection).clamp();
12518    const fab = DFGLUT({ roughness, dotNV });
12519    const Fr = iridescenceF0 ? iridescence.mix(f0, iridescenceF0) : f0;
12520    const FssEss = Fr.mul(fab.x).add(specularF903.mul(fab.y));
12521    const Ess = fab.x.add(fab.y);
12522    const Ems = Ess.oneMinus();
12523    const Favg = Fr.add(Fr.oneMinus().mul(0.047619));
12524    const Fms = FssEss.mul(Favg).div(Ems.mul(Favg).oneMinus());
12525    singleScatter.addAssign(FssEss);
12526    multiScatter.addAssign(Fms.mul(Ems));
12527  }
12528  /**
12529   * Implements the direct light.
12530   *
12531   * @param {Object} lightData - The light data.
12532   * @param {NodeBuilder} builder - The current node builder.
12533   */
12534  direct({ lightDirection, lightColor, reflectedLight }) {
12535    const dotNL = normalView.dot(lightDirection).clamp();
12536    const irradiance = dotNL.mul(lightColor).toVar();
12537    if (this.sheen === true) {
12538      this.sheenSpecularDirect.addAssign(irradiance.mul(BRDF_Sheen({ lightDirection })));
12539      const sheenAlbedoV = IBLSheenBRDF({ normal: normalView, viewDir: positionViewDirection, roughness: sheenRoughness });
12540      const sheenAlbedoL = IBLSheenBRDF({ normal: normalView, viewDir: lightDirection, roughness: sheenRoughness });
12541      const sheenEnergyComp = sheen.r.max(sheen.g).max(sheen.b).mul(sheenAlbedoV.max(sheenAlbedoL)).oneMinus();
12542      irradiance.mulAssign(sheenEnergyComp);
12543    }
12544    if (this.clearcoat === true) {
12545      const dotNLcc = clearcoatNormalView.dot(lightDirection).clamp();
12546      const ccIrradiance = dotNLcc.mul(lightColor);
12547      this.clearcoatSpecularDirect.addAssign(ccIrradiance.mul(BRDF_GGX({ lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: clearcoatNormalView })));
12548    }
12549    reflectedLight.directDiffuse.addAssign(irradiance.mul(BRDF_Lambert({ diffuseColor: diffuseContribution })));
12550    reflectedLight.directSpecular.addAssign(irradiance.mul(BRDF_GGX_Multiscatter({ lightDirection, f0: specularColorBlended, f90: 1, roughness, f: this.iridescenceFresnel, USE_IRIDESCENCE: this.iridescence, USE_ANISOTROPY: this.anisotropy })));
12551  }
12552  /**
12553   * This method is intended for implementing the direct light term for
12554   * rect area light nodes.
12555   *
12556   * @param {Object} input - The input data.
12557   * @param {NodeBuilder} builder - The current node builder.
12558   */
12559  directRectArea({ lightColor, lightPosition: lightPosition3, halfWidth, halfHeight, reflectedLight, ltc_1, ltc_2 }) {
12560    const p0 = lightPosition3.add(halfWidth).sub(halfHeight);
12561    const p1 = lightPosition3.sub(halfWidth).sub(halfHeight);
12562    const p2 = lightPosition3.sub(halfWidth).add(halfHeight);
12563    const p3 = lightPosition3.add(halfWidth).add(halfHeight);
12564    const N2 = normalView;
12565    const V = positionViewDirection;
12566    const P = positionView.toVar();
12567    const uv3 = LTC_Uv({ N: N2, V, roughness });
12568    const t1 = ltc_1.sample(uv3).toVar();
12569    const t2 = ltc_2.sample(uv3).toVar();
12570    const mInv = mat3(
12571      vec3(t1.x, 0, t1.y),
12572      vec3(0, 1, 0),
12573      vec3(t1.z, 0, t1.w)
12574    ).toVar();
12575    const fresnel = specularColorBlended.mul(t2.x).add(specularF90.sub(specularColorBlended).mul(t2.y)).toVar();
12576    reflectedLight.directSpecular.addAssign(lightColor.mul(fresnel).mul(LTC_Evaluate({ N: N2, V, P, mInv, p0, p1, p2, p3 })));
12577    reflectedLight.directDiffuse.addAssign(lightColor.mul(diffuseContribution).mul(LTC_Evaluate({ N: N2, V, P, mInv: mat3(1, 0, 0, 0, 1, 0, 0, 0, 1), p0, p1, p2, p3 })));
12578    if (this.clearcoat === true) {
12579      const Ncc = clearcoatNormalView;
12580      const uvClearcoat = LTC_Uv({ N: Ncc, V, roughness: clearcoatRoughness });
12581      const t1Clearcoat = ltc_1.sample(uvClearcoat);
12582      const t2Clearcoat = ltc_2.sample(uvClearcoat);
12583      const mInvClearcoat = mat3(
12584        vec3(t1Clearcoat.x, 0, t1Clearcoat.y),
12585        vec3(0, 1, 0),
12586        vec3(t1Clearcoat.z, 0, t1Clearcoat.w)
12587      );
12588      const fresnelClearcoat = clearcoatF0.mul(t2Clearcoat.x).add(clearcoatF90.sub(clearcoatF0).mul(t2Clearcoat.y));
12589      this.clearcoatSpecularDirect.addAssign(lightColor.mul(fresnelClearcoat).mul(LTC_Evaluate({ N: Ncc, V, P, mInv: mInvClearcoat, p0, p1, p2, p3 })));
12590    }
12591  }
12592  /**
12593   * Implements the indirect lighting.
12594   *
12595   * @param {NodeBuilder} builder - The current node builder.
12596   */
12597  indirect(builder) {
12598    this.indirectDiffuse(builder);
12599    this.indirectSpecular(builder);
12600    this.ambientOcclusion(builder);
12601  }
12602  /**
12603   * Implements the indirect diffuse term.
12604   *
12605   * @param {NodeBuilder} builder - The current node builder.
12606   */
12607  indirectDiffuse(builder) {
12608    const { irradiance, reflectedLight } = builder.context;
12609    const diffuse = irradiance.mul(BRDF_Lambert({ diffuseColor: diffuseContribution })).toVar();
12610    if (this.sheen === true) {
12611      const sheenAlbedo = IBLSheenBRDF({ normal: normalView, viewDir: positionViewDirection, roughness: sheenRoughness });
12612      const sheenEnergyComp = sheen.r.max(sheen.g).max(sheen.b).mul(sheenAlbedo).oneMinus();
12613      diffuse.mulAssign(sheenEnergyComp);
12614    }
12615    reflectedLight.indirectDiffuse.addAssign(diffuse);
12616  }
12617  /**
12618   * Implements the indirect specular term.
12619   *
12620   * @param {NodeBuilder} builder - The current node builder.
12621   */
12622  indirectSpecular(builder) {
12623    const { radiance, iblIrradiance, reflectedLight } = builder.context;
12624    if (this.sheen === true) {
12625      this.sheenSpecularIndirect.addAssign(iblIrradiance.mul(
12626        sheen,
12627        IBLSheenBRDF({
12628          normal: normalView,
12629          viewDir: positionViewDirection,
12630          roughness: sheenRoughness
12631        })
12632      ));
12633    }
12634    if (this.clearcoat === true) {
12635      const dotNVcc = clearcoatNormalView.dot(positionViewDirection).clamp();
12636      const clearcoatEnv = EnvironmentBRDF({
12637        dotNV: dotNVcc,
12638        specularColor: clearcoatF0,
12639        specularF90: clearcoatF90,
12640        roughness: clearcoatRoughness
12641      });
12642      this.clearcoatSpecularIndirect.addAssign(this.clearcoatRadiance.mul(clearcoatEnv));
12643    }
12644    const singleScatteringDielectric = vec3().toVar("singleScatteringDielectric");
12645    const multiScatteringDielectric = vec3().toVar("multiScatteringDielectric");
12646    const singleScatteringMetallic = vec3().toVar("singleScatteringMetallic");
12647    const multiScatteringMetallic = vec3().toVar("multiScatteringMetallic");
12648    this.computeMultiscattering(singleScatteringDielectric, multiScatteringDielectric, specularF90, specularColor, this.iridescenceF0Dielectric);
12649    this.computeMultiscattering(singleScatteringMetallic, multiScatteringMetallic, specularF90, diffuseColor.rgb, this.iridescenceF0Metallic);
12650    const singleScattering = mix(singleScatteringDielectric, singleScatteringMetallic, metalness);
12651    const multiScattering = mix(multiScatteringDielectric, multiScatteringMetallic, metalness);
12652    const totalScatteringDielectric = singleScatteringDielectric.add(multiScatteringDielectric);
12653    const diffuse = diffuseContribution.mul(totalScatteringDielectric.oneMinus());
12654    const cosineWeightedIrradiance = iblIrradiance.mul(1 / Math.PI);
12655    const indirectSpecular = radiance.mul(singleScattering).add(multiScattering.mul(cosineWeightedIrradiance)).toVar();
12656    const indirectDiffuse = diffuse.mul(cosineWeightedIrradiance).toVar();
12657    if (this.sheen === true) {
12658      const sheenAlbedo = IBLSheenBRDF({ normal: normalView, viewDir: positionViewDirection, roughness: sheenRoughness });
12659      const sheenEnergyComp = sheen.r.max(sheen.g).max(sheen.b).mul(sheenAlbedo).oneMinus();
12660      indirectSpecular.mulAssign(sheenEnergyComp);
12661      indirectDiffuse.mulAssign(sheenEnergyComp);
12662    }
12663    reflectedLight.indirectSpecular.addAssign(indirectSpecular);
12664    reflectedLight.indirectDiffuse.addAssign(indirectDiffuse);
12665  }
12666  /**
12667   * Implements the ambient occlusion term.
12668   *
12669   * @param {NodeBuilder} builder - The current node builder.
12670   */
12671  ambientOcclusion(builder) {
12672    const { ambientOcclusion, reflectedLight } = builder.context;
12673    const dotNV = normalView.dot(positionViewDirection).clamp();
12674    const aoNV = dotNV.add(ambientOcclusion);
12675    const aoExp = roughness.mul(-16).oneMinus().negate().exp2();
12676    const aoNode = ambientOcclusion.sub(aoNV.pow(aoExp).oneMinus()).clamp();
12677    if (this.clearcoat === true) {
12678      this.clearcoatSpecularIndirect.mulAssign(ambientOcclusion);
12679    }
12680    if (this.sheen === true) {
12681      this.sheenSpecularIndirect.mulAssign(ambientOcclusion);
12682    }
12683    reflectedLight.indirectDiffuse.mulAssign(ambientOcclusion);
12684    reflectedLight.indirectSpecular.mulAssign(aoNode);
12685  }
12686  /**
12687   * Used for final lighting accumulations depending on the requested features.
12688   *
12689   * @param {NodeBuilder} builder - The current node builder.
12690   */
12691  finish({ context: context3 }) {
12692    const { outgoingLight } = context3;
12693    if (this.clearcoat === true) {
12694      const dotNVcc = clearcoatNormalView.dot(positionViewDirection).clamp();
12695      const Fcc = F_Schlick({
12696        dotVH: dotNVcc,
12697        f0: clearcoatF0,
12698        f90: clearcoatF90
12699      });
12700      const clearcoatLight = outgoingLight.mul(clearcoat.mul(Fcc).oneMinus()).add(this.clearcoatSpecularDirect.add(this.clearcoatSpecularIndirect).mul(clearcoat));
12701      outgoingLight.assign(clearcoatLight);
12702    }
12703    if (this.sheen === true) {
12704      const sheenLight = outgoingLight.add(this.sheenSpecularDirect, this.sheenSpecularIndirect.mul(1 / Math.PI));
12705      outgoingLight.assign(sheenLight);
12706    }
12707  }
12708};
12709var cubeUV_r0 = /* @__PURE__ */ float(1);
12710var cubeUV_m0 = /* @__PURE__ */ float(-2);
12711var cubeUV_r1 = /* @__PURE__ */ float(0.8);
12712var cubeUV_m1 = /* @__PURE__ */ float(-1);
12713var cubeUV_r4 = /* @__PURE__ */ float(0.4);
12714var cubeUV_m4 = /* @__PURE__ */ float(2);
12715var cubeUV_r5 = /* @__PURE__ */ float(0.305);
12716var cubeUV_m5 = /* @__PURE__ */ float(3);
12717var cubeUV_r6 = /* @__PURE__ */ float(0.21);
12718var cubeUV_m6 = /* @__PURE__ */ float(4);
12719var cubeUV_minMipLevel = /* @__PURE__ */ float(4);
12720var cubeUV_minTileSize = /* @__PURE__ */ float(16);
12721var getFace = /* @__PURE__ */ Fn(([direction]) => {
12722  const absDirection = vec3(abs(direction)).toVar();
12723  const face = float(-1).toVar();
12724  If(absDirection.x.greaterThan(absDirection.z), () => {
12725    If(absDirection.x.greaterThan(absDirection.y), () => {
12726      face.assign(select(direction.x.greaterThan(0), 0, 3));
12727    }).Else(() => {
12728      face.assign(select(direction.y.greaterThan(0), 1, 4));
12729    });
12730  }).Else(() => {
12731    If(absDirection.z.greaterThan(absDirection.y), () => {
12732      face.assign(select(direction.z.greaterThan(0), 2, 5));
12733    }).Else(() => {
12734      face.assign(select(direction.y.greaterThan(0), 1, 4));
12735    });
12736  });
12737  return face;
12738}).setLayout({
12739  name: "getFace",
12740  type: "float",
12741  inputs: [
12742    { name: "direction", type: "vec3" }
12743  ]
12744});
12745var getUV = /* @__PURE__ */ Fn(([direction, face]) => {
12746  const uv3 = vec2().toVar();
12747  If(face.equal(0), () => {
12748    uv3.assign(vec2(direction.z, direction.y).div(abs(direction.x)));
12749  }).ElseIf(face.equal(1), () => {
12750    uv3.assign(vec2(direction.x.negate(), direction.z.negate()).div(abs(direction.y)));
12751  }).ElseIf(face.equal(2), () => {
12752    uv3.assign(vec2(direction.x.negate(), direction.y).div(abs(direction.z)));
12753  }).ElseIf(face.equal(3), () => {
12754    uv3.assign(vec2(direction.z.negate(), direction.y).div(abs(direction.x)));
12755  }).ElseIf(face.equal(4), () => {
12756    uv3.assign(vec2(direction.x.negate(), direction.z).div(abs(direction.y)));
12757  }).Else(() => {
12758    uv3.assign(vec2(direction.x, direction.y).div(abs(direction.z)));
12759  });
12760  return mul(0.5, uv3.add(1));
12761}).setLayout({
12762  name: "getUV",
12763  type: "vec2",
12764  inputs: [
12765    { name: "direction", type: "vec3" },
12766    { name: "face", type: "float" }
12767  ]
12768});
12769var roughnessToMip = /* @__PURE__ */ Fn(([roughness3]) => {
12770  const mip = float(0).toVar();
12771  If(roughness3.greaterThanEqual(cubeUV_r1), () => {
12772    mip.assign(cubeUV_r0.sub(roughness3).mul(cubeUV_m1.sub(cubeUV_m0)).div(cubeUV_r0.sub(cubeUV_r1)).add(cubeUV_m0));
12773  }).ElseIf(roughness3.greaterThanEqual(cubeUV_r4), () => {
12774    mip.assign(cubeUV_r1.sub(roughness3).mul(cubeUV_m4.sub(cubeUV_m1)).div(cubeUV_r1.sub(cubeUV_r4)).add(cubeUV_m1));
12775  }).ElseIf(roughness3.greaterThanEqual(cubeUV_r5), () => {
12776    mip.assign(cubeUV_r4.sub(roughness3).mul(cubeUV_m5.sub(cubeUV_m4)).div(cubeUV_r4.sub(cubeUV_r5)).add(cubeUV_m4));
12777  }).ElseIf(roughness3.greaterThanEqual(cubeUV_r6), () => {
12778    mip.assign(cubeUV_r5.sub(roughness3).mul(cubeUV_m6.sub(cubeUV_m5)).div(cubeUV_r5.sub(cubeUV_r6)).add(cubeUV_m5));
12779  }).Else(() => {
12780    mip.assign(float(-2).mul(log22(mul(1.16, roughness3))));
12781  });
12782  return mip;
12783}).setLayout({
12784  name: "roughnessToMip",
12785  type: "float",
12786  inputs: [
12787    { name: "roughness", type: "float" }
12788  ]
12789});
12790var getDirection = /* @__PURE__ */ Fn(([uv_immutable, face]) => {
12791  const uv3 = uv_immutable.toVar();
12792  uv3.assign(mul(2, uv3).sub(1));
12793  const direction = vec3(uv3, 1).toVar();
12794  If(face.equal(0), () => {
12795    direction.assign(direction.zyx);
12796  }).ElseIf(face.equal(1), () => {
12797    direction.assign(direction.xzy);
12798    direction.xz.mulAssign(-1);
12799  }).ElseIf(face.equal(2), () => {
12800    direction.x.mulAssign(-1);
12801  }).ElseIf(face.equal(3), () => {
12802    direction.assign(direction.zyx);
12803    direction.xz.mulAssign(-1);
12804  }).ElseIf(face.equal(4), () => {
12805    direction.assign(direction.xzy);
12806    direction.xy.mulAssign(-1);
12807  }).ElseIf(face.equal(5), () => {
12808    direction.z.mulAssign(-1);
12809  });
12810  return direction;
12811}).setLayout({
12812  name: "getDirection",
12813  type: "vec3",
12814  inputs: [
12815    { name: "uv", type: "vec2" },
12816    { name: "face", type: "float" }
12817  ]
12818});
12819var textureCubeUV = /* @__PURE__ */ Fn(([envMap, sampleDir_immutable, roughness_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP]) => {
12820  const roughness3 = float(roughness_immutable);
12821  const sampleDir = vec3(sampleDir_immutable);
12822  const mip = clamp(roughnessToMip(roughness3), cubeUV_m0, CUBEUV_MAX_MIP);
12823  const mipF = fract(mip);
12824  const mipInt = floor(mip);
12825  const color0 = vec3(bilinearCubeUV(envMap, sampleDir, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP)).toVar();
12826  If(mipF.notEqual(0), () => {
12827    const color1 = vec3(bilinearCubeUV(envMap, sampleDir, mipInt.add(1), CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP)).toVar();
12828    color0.assign(mix(color0, color1, mipF));
12829  });
12830  return color0;
12831});
12832var bilinearCubeUV = /* @__PURE__ */ Fn(([envMap, direction_immutable, mipInt_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP]) => {
12833  const mipInt = float(mipInt_immutable).toVar();
12834  const direction = vec3(direction_immutable);
12835  const face = float(getFace(direction)).toVar();
12836  const filterInt = float(max$1(cubeUV_minMipLevel.sub(mipInt), 0)).toVar();
12837  mipInt.assign(max$1(mipInt, cubeUV_minMipLevel));
12838  const faceSize = float(exp2(mipInt)).toVar();
12839  const uv3 = vec2(getUV(direction, face).mul(faceSize.sub(2)).add(1)).toVar();
12840  If(face.greaterThan(2), () => {
12841    uv3.y.addAssign(faceSize);
12842    face.subAssign(3);
12843  });
12844  uv3.x.addAssign(face.mul(faceSize));
12845  uv3.x.addAssign(filterInt.mul(mul(3, cubeUV_minTileSize)));
12846  uv3.y.addAssign(mul(4, exp2(CUBEUV_MAX_MIP).sub(faceSize)));
12847  uv3.x.mulAssign(CUBEUV_TEXEL_WIDTH);
12848  uv3.y.mulAssign(CUBEUV_TEXEL_HEIGHT);
12849  return envMap.sample(uv3).grad(vec2(), vec2());
12850});
12851var getSample = /* @__PURE__ */ Fn(({ envMap, mipInt, outputDirection, theta, axis, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP }) => {
12852  const cosTheta = cos(theta);
12853  const sampleDirection = outputDirection.mul(cosTheta).add(axis.cross(outputDirection).mul(sin(theta))).add(axis.mul(axis.dot(outputDirection).mul(cosTheta.oneMinus())));
12854  return bilinearCubeUV(envMap, sampleDirection, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP);
12855});
12856var blur = /* @__PURE__ */ Fn(({ n, latitudinal, poleAxis, outputDirection, weights, samples, dTheta, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP }) => {
12857  const axis = vec3(select(latitudinal, poleAxis, cross(poleAxis, outputDirection))).toVar();
12858  If(axis.equal(vec3(0)), () => {
12859    axis.assign(vec3(outputDirection.z, 0, outputDirection.x.negate()));
12860  });
12861  axis.assign(normalize(axis));
12862  const gl_FragColor = vec3().toVar();
12863  gl_FragColor.addAssign(weights.element(0).mul(getSample({ theta: 0, axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP })));
12864  Loop({ start: int(1), end: n }, ({ i }) => {
12865    If(i.greaterThanEqual(samples), () => {
12866      Break();
12867    });
12868    const theta = float(dTheta.mul(float(i))).toVar();
12869    gl_FragColor.addAssign(weights.element(i).mul(getSample({ theta: theta.mul(-1), axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP })));
12870    gl_FragColor.addAssign(weights.element(i).mul(getSample({ theta, axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP })));
12871  });
12872  return vec4(gl_FragColor, 1);
12873});
12874var radicalInverse_VdC = /* @__PURE__ */ Fn(([bits_immutable]) => {
12875  const bits = uint(bits_immutable).toVar();
12876  bits.assign(bits.shiftLeft(uint(16)).bitOr(bits.shiftRight(uint(16))));
12877  bits.assign(bits.bitAnd(uint(1431655765)).shiftLeft(uint(1)).bitOr(bits.bitAnd(uint(2863311530)).shiftRight(uint(1))));
12878  bits.assign(bits.bitAnd(uint(858993459)).shiftLeft(uint(2)).bitOr(bits.bitAnd(uint(3435973836)).shiftRight(uint(2))));
12879  bits.assign(bits.bitAnd(uint(252645135)).shiftLeft(uint(4)).bitOr(bits.bitAnd(uint(4042322160)).shiftRight(uint(4))));
12880  bits.assign(bits.bitAnd(uint(16711935)).shiftLeft(uint(8)).bitOr(bits.bitAnd(uint(4278255360)).shiftRight(uint(8))));
12881  return float(bits).mul(23283064365386963e-26);
12882});
12883var hammersley = /* @__PURE__ */ Fn(([i, N2]) => {
12884  return vec2(float(i).div(float(N2)), radicalInverse_VdC(i));
12885});
12886var importanceSampleGGX_VNDF = /* @__PURE__ */ Fn(([Xi, V, roughness3]) => {
12887  const alpha = roughness3.mul(roughness3).toConst();
12888  const T1 = vec3(1, 0, 0).toConst();
12889  const T22 = cross(V, T1).toConst();
12890  const r = sqrt(Xi.x).toConst();
12891  const phi = mul(2, 3.14159265359).mul(Xi.y).toConst();
12892  const t1 = r.mul(cos(phi)).toConst();
12893  const t2 = r.mul(sin(phi)).toVar();
12894  const s = mul(0.5, V.z.add(1)).toConst();
12895  t2.assign(s.oneMinus().mul(sqrt(t1.mul(t1).oneMinus())).add(s.mul(t2)));
12896  const Nh = T1.mul(t1).add(T22.mul(t2)).add(V.mul(sqrt(max$1(0, t1.mul(t1).add(t2.mul(t2)).oneMinus()))));
12897  return normalize(vec3(alpha.mul(Nh.x), alpha.mul(Nh.y), max$1(0, Nh.z)));
12898});
12899var ggxConvolution = /* @__PURE__ */ Fn(({ roughness: roughness3, mipInt, envMap, N_immutable, GGX_SAMPLES: GGX_SAMPLES2, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP }) => {
12900  const N2 = vec3(N_immutable).toVar();
12901  const prefilteredColor = vec3(0).toVar();
12902  const totalWeight = float(0).toVar();
12903  If(roughness3.lessThan(1e-3), () => {
12904    prefilteredColor.assign(bilinearCubeUV(envMap, N2, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP));
12905  }).Else(() => {
12906    const up = select(abs(N2.z).lessThan(0.999), vec3(0, 0, 1), vec3(1, 0, 0));
12907    const tangent = normalize(cross(up, N2)).toVar();
12908    const bitangent = cross(N2, tangent).toVar();
12909    Loop({ start: uint(0), end: GGX_SAMPLES2 }, ({ i }) => {
12910      const Xi = hammersley(i, GGX_SAMPLES2);
12911      const H_tangent = importanceSampleGGX_VNDF(Xi, vec3(0, 0, 1), roughness3);
12912      const H = normalize(tangent.mul(H_tangent.x).add(bitangent.mul(H_tangent.y)).add(N2.mul(H_tangent.z)));
12913      const L = normalize(H.mul(dot(N2, H).mul(2)).sub(N2));
12914      const NdotL = max$1(dot(N2, L), 0);
12915      If(NdotL.greaterThan(0), () => {
12916        const sampleColor = bilinearCubeUV(envMap, L, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP);
12917        prefilteredColor.addAssign(sampleColor.mul(NdotL));
12918        totalWeight.addAssign(NdotL);
12919      });
12920    });
12921    If(totalWeight.greaterThan(0), () => {
12922      prefilteredColor.assign(prefilteredColor.div(totalWeight));
12923    });
12924  });
12925  return vec4(prefilteredColor, 1);
12926});
12927var LOD_MIN = 4;
12928var EXTRA_LOD_SIGMA = [0.125, 0.215, 0.35, 0.446, 0.526, 0.582];
12929var MAX_SAMPLES = 20;
12930var GGX_SAMPLES = 512;
12931var _flatCamera = /* @__PURE__ */ new OrthographicCamera(-1, 1, 1, -1, 0, 1);
12932var _cubeCamera = /* @__PURE__ */ new PerspectiveCamera(90, 1);
12933var _clearColor$2 = /* @__PURE__ */ new Color();
12934var _oldTarget = null;
12935var _oldActiveCubeFace = 0;
12936var _oldActiveMipmapLevel = 0;
12937var _origin = /* @__PURE__ */ new Vector3();
12938var _uniformsMap = /* @__PURE__ */ new WeakMap();
12939var _faceLib = [
12940  3,
12941  1,
12942  5,
12943  0,
12944  4,
12945  2
12946];
12947var _direction = /* @__PURE__ */ getDirection(uv$1(), attribute("faceIndex")).normalize();
12948var _outputDirection = /* @__PURE__ */ vec3(_direction.x, _direction.y, _direction.z);
12949var PMREMGenerator = class {
12950  /**
12951   * Constructs a new PMREM generator.
12952   *
12953   * @param {Renderer} renderer - The renderer.
12954   */
12955  constructor(renderer) {
12956    this._renderer = renderer;
12957    this._pingPongRenderTarget = null;
12958    this._lodMax = 0;
12959    this._cubeSize = 0;
12960    this._sizeLods = [];
12961    this._sigmas = [];
12962    this._lodMeshes = [];
12963    this._blurMaterial = null;
12964    this._ggxMaterial = null;
12965    this._cubemapMaterial = null;
12966    this._equirectMaterial = null;
12967    this._backgroundBox = null;
12968  }
12969  get _hasInitialized() {
12970    return this._renderer.hasInitialized();
12971  }
12972  /**
12973   * Generates a PMREM from a supplied Scene, which can be faster than using an
12974   * image if networking bandwidth is low. Optional sigma specifies a blur radius
12975   * in radians to be applied to the scene before PMREM generation. Optional near
12976   * and far planes ensure the scene is rendered in its entirety.
12977   *
12978   * @param {Scene} scene - The scene to be captured.
12979   * @param {number} [sigma=0] - The blur radius in radians.
12980   * @param {number} [near=0.1] - The near plane distance.
12981   * @param {number} [far=100] - The far plane distance.
12982   * @param {Object} [options={}] - The configuration options.
12983   * @param {number} [options.size=256] - The texture size of the PMREM.
12984   * @param {Vector3} [options.renderTarget=origin] - The position of the internal cube camera that renders the scene.
12985   * @param {?RenderTarget} [options.renderTarget=null] - The render target to use.
12986   * @return {RenderTarget} The resulting PMREM.
12987   * @see {@link PMREMGenerator#fromScene}
12988   */
12989  fromScene(scene, sigma = 0, near = 0.1, far = 100, options = {}) {
12990    const {
12991      size: size3 = 256,
12992      position = _origin,
12993      renderTarget = null
12994    } = options;
12995    this._setSize(size3);
12996    if (this._hasInitialized === false) {
12997      warn('PMREMGenerator: ".fromScene()" called before the backend is initialized. Try using "await renderer.init()" instead.');
12998      const cubeUVRenderTarget2 = renderTarget || this._allocateTarget();
12999      options.renderTarget = cubeUVRenderTarget2;
13000      this.fromSceneAsync(scene, sigma, near, far, options);
13001      return cubeUVRenderTarget2;
13002    }
13003    _oldTarget = this._renderer.getRenderTarget();
13004    _oldActiveCubeFace = this._renderer.getActiveCubeFace();
13005    _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
13006    const cubeUVRenderTarget = renderTarget || this._allocateTarget();
13007    cubeUVRenderTarget.depthBuffer = true;
13008    this._init(cubeUVRenderTarget);
13009    this._sceneToCubeUV(scene, near, far, cubeUVRenderTarget, position);
13010    if (sigma > 0) {
13011      this._blur(cubeUVRenderTarget, 0, 0, sigma);
13012    }
13013    this._applyPMREM(cubeUVRenderTarget);
13014    this._cleanup(cubeUVRenderTarget);
13015    return cubeUVRenderTarget;
13016  }
13017  /**
13018   * Generates a PMREM from a supplied Scene, which can be faster than using an
13019   * image if networking bandwidth is low. Optional sigma specifies a blur radius
13020   * in radians to be applied to the scene before PMREM generation. Optional near
13021   * and far planes ensure the scene is rendered in its entirety (the cubeCamera
13022   * is placed at the origin).
13023   *
13024   * @deprecated
13025   * @param {Scene} scene - The scene to be captured.
13026   * @param {number} [sigma=0] - The blur radius in radians.
13027   * @param {number} [near=0.1] - The near plane distance.
13028   * @param {number} [far=100] - The far plane distance.
13029   * @param {Object} [options={}] - The configuration options.
13030   * @param {number} [options.size=256] - The texture size of the PMREM.
13031   * @param {Vector3} [options.position=origin] - The position of the internal cube camera that renders the scene.
13032   * @param {?RenderTarget} [options.renderTarget=null] - The render target to use.
13033   * @return {Promise<RenderTarget>} A Promise that resolve with the PMREM when the generation has been finished.
13034   * @see {@link PMREMGenerator#fromScene}
13035   */
13036  async fromSceneAsync(scene, sigma = 0, near = 0.1, far = 100, options = {}) {
13037    warnOnce('PMREMGenerator: ".fromSceneAsync()" is deprecated. Use "await renderer.init()" instead.');
13038    await this._renderer.init();
13039    return this.fromScene(scene, sigma, near, far, options);
13040  }
13041  /**
13042   * Generates a PMREM from an equirectangular texture, which can be either LDR
13043   * or HDR. The ideal input image size is 1k (1024 x 512),
13044   * as this matches best with the 256 x 256 cubemap output.
13045   *
13046   * @param {Texture} equirectangular - The equirectangular texture to be converted.
13047   * @param {?RenderTarget} [renderTarget=null] - The render target to use.
13048   * @return {RenderTarget} The resulting PMREM.
13049   * @see {@link PMREMGenerator#fromEquirectangularAsync}
13050   */
13051  fromEquirectangular(equirectangular, renderTarget = null) {
13052    if (this._hasInitialized === false) {
13053      warn('PMREMGenerator: .fromEquirectangular() called before the backend is initialized. Try using "await renderer.init()" instead.');
13054      this._setSizeFromTexture(equirectangular);
13055      const cubeUVRenderTarget = renderTarget || this._allocateTarget();
13056      this.fromEquirectangularAsync(equirectangular, cubeUVRenderTarget);
13057      return cubeUVRenderTarget;
13058    }
13059    return this._fromTexture(equirectangular, renderTarget);
13060  }
13061  /**
13062   * Generates a PMREM from an equirectangular texture, which can be either LDR
13063   * or HDR. The ideal input image size is 1k (1024 x 512),
13064   * as this matches best with the 256 x 256 cubemap output.
13065   *
13066   * @deprecated
13067   * @param {Texture} equirectangular - The equirectangular texture to be converted.
13068   * @param {?RenderTarget} [renderTarget=null] - The render target to use.
13069   * @return {Promise<RenderTarget>} The resulting PMREM.
13070   * @see {@link PMREMGenerator#fromEquirectangular}
13071   */
13072  async fromEquirectangularAsync(equirectangular, renderTarget = null) {
13073    warnOnce('PMREMGenerator: ".fromEquirectangularAsync()" is deprecated. Use "await renderer.init()" instead.');
13074    await this._renderer.init();
13075    return this._fromTexture(equirectangular, renderTarget);
13076  }
13077  /**
13078   * Generates a PMREM from an cubemap texture, which can be either LDR
13079   * or HDR. The ideal input cube size is 256 x 256,
13080   * as this matches best with the 256 x 256 cubemap output.
13081   *
13082   * @param {Texture} cubemap - The cubemap texture to be converted.
13083   * @param {?RenderTarget} [renderTarget=null] - The render target to use.
13084   * @return {RenderTarget} The resulting PMREM.
13085   * @see {@link PMREMGenerator#fromCubemapAsync}
13086   */
13087  fromCubemap(cubemap, renderTarget = null) {
13088    if (this._hasInitialized === false) {
13089      warn("PMREMGenerator: .fromCubemap() called before the backend is initialized. Try using .fromCubemapAsync() instead.");
13090      this._setSizeFromTexture(cubemap);
13091      const cubeUVRenderTarget = renderTarget || this._allocateTarget();
13092      this.fromCubemapAsync(cubemap, renderTarget);
13093      return cubeUVRenderTarget;
13094    }
13095    return this._fromTexture(cubemap, renderTarget);
13096  }
13097  /**
13098   * Generates a PMREM from an cubemap texture, which can be either LDR
13099   * or HDR. The ideal input cube size is 256 x 256,
13100   * with the 256 x 256 cubemap output.
13101   *
13102   * @deprecated
13103   * @param {Texture} cubemap - The cubemap texture to be converted.
13104   * @param {?RenderTarget} [renderTarget=null] - The render target to use.
13105   * @return {Promise<RenderTarget>} The resulting PMREM.
13106   * @see {@link PMREMGenerator#fromCubemap}
13107   */
13108  async fromCubemapAsync(cubemap, renderTarget = null) {
13109    warnOnce('PMREMGenerator: ".fromCubemapAsync()" is deprecated. Use "await renderer.init()" instead.');
13110    await this._renderer.init();
13111    return this._fromTexture(cubemap, renderTarget);
13112  }
13113  /**
13114   * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
13115   * your texture's network fetch for increased concurrency.
13116   *
13117   * @returns {Promise}
13118   */
13119  async compileCubemapShader() {
13120    if (this._cubemapMaterial === null) {
13121      this._cubemapMaterial = _getCubemapMaterial();
13122      await this._compileMaterial(this._cubemapMaterial);
13123    }
13124  }
13125  /**
13126   * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
13127   * your texture's network fetch for increased concurrency.
13128   *
13129   * @returns {Promise}
13130   */
13131  async compileEquirectangularShader() {
13132    if (this._equirectMaterial === null) {
13133      this._equirectMaterial = _getEquirectMaterial();
13134      await this._compileMaterial(this._equirectMaterial);
13135    }
13136  }
13137  /**
13138   * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
13139   * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
13140   * one of them will cause any others to also become unusable.
13141   */
13142  dispose() {
13143    this._dispose();
13144    if (this._cubemapMaterial !== null) this._cubemapMaterial.dispose();
13145    if (this._equirectMaterial !== null) this._equirectMaterial.dispose();
13146    if (this._backgroundBox !== null) {
13147      this._backgroundBox.geometry.dispose();
13148      this._backgroundBox.material.dispose();
13149    }
13150  }
13151  // private interface
13152  _setSizeFromTexture(texture3) {
13153    if (texture3.mapping === CubeReflectionMapping || texture3.mapping === CubeRefractionMapping) {
13154      this._setSize(texture3.image.length === 0 ? 16 : texture3.image[0].width || texture3.image[0].image.width);
13155    } else {
13156      this._setSize(texture3.image.width / 4);
13157    }
13158  }
13159  _setSize(cubeSize) {
13160    this._lodMax = Math.floor(Math.log2(cubeSize));
13161    this._cubeSize = Math.pow(2, this._lodMax);
13162  }
13163  _dispose() {
13164    if (this._blurMaterial !== null) this._blurMaterial.dispose();
13165    if (this._ggxMaterial !== null) this._ggxMaterial.dispose();
13166    if (this._pingPongRenderTarget !== null) this._pingPongRenderTarget.dispose();
13167    for (let i = 0; i < this._lodMeshes.length; i++) {
13168      this._lodMeshes[i].geometry.dispose();
13169    }
13170  }
13171  _cleanup(outputTarget) {
13172    this._renderer.setRenderTarget(_oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel);
13173    outputTarget.scissorTest = false;
13174    this._setViewport(outputTarget, 0, 0, outputTarget.width, outputTarget.height);
13175  }
13176  _fromTexture(texture3, renderTarget) {
13177    this._setSizeFromTexture(texture3);
13178    _oldTarget = this._renderer.getRenderTarget();
13179    _oldActiveCubeFace = this._renderer.getActiveCubeFace();
13180    _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
13181    const cubeUVRenderTarget = renderTarget || this._allocateTarget();
13182    this._init(cubeUVRenderTarget);
13183    this._textureToCubeUV(texture3, cubeUVRenderTarget);
13184    this._applyPMREM(cubeUVRenderTarget);
13185    this._cleanup(cubeUVRenderTarget);
13186    return cubeUVRenderTarget;
13187  }
13188  _allocateTarget() {
13189    const width = 3 * Math.max(this._cubeSize, 16 * 7);
13190    const height = 4 * this._cubeSize;
13191    const cubeUVRenderTarget = _createRenderTarget(width, height);
13192    return cubeUVRenderTarget;
13193  }
13194  _init(renderTarget) {
13195    if (this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== renderTarget.width || this._pingPongRenderTarget.height !== renderTarget.height) {
13196      if (this._pingPongRenderTarget !== null) {
13197        this._dispose();
13198      }
13199      this._pingPongRenderTarget = _createRenderTarget(renderTarget.width, renderTarget.height);
13200      const { _lodMax } = this;
13201      ({ lodMeshes: this._lodMeshes, sizeLods: this._sizeLods, sigmas: this._sigmas } = _createPlanes(_lodMax));
13202      this._blurMaterial = _getBlurShader(_lodMax, renderTarget.width, renderTarget.height);
13203      this._ggxMaterial = _getGGXShader(_lodMax, renderTarget.width, renderTarget.height);
13204    }
13205  }
13206  async _compileMaterial(material) {
13207    const mesh = new Mesh(new BufferGeometry(), material);
13208    await this._renderer.compile(mesh, _flatCamera);
13209  }
13210  _sceneToCubeUV(scene, near, far, cubeUVRenderTarget, position) {
13211    const cubeCamera = _cubeCamera;
13212    cubeCamera.near = near;
13213    cubeCamera.far = far;
13214    const upSign = [1, 1, 1, 1, -1, 1];
13215    const forwardSign = [1, -1, 1, -1, 1, -1];
13216    const renderer = this._renderer;
13217    const originalAutoClear = renderer.autoClear;
13218    renderer.getClearColor(_clearColor$2);
13219    renderer.autoClear = false;
13220    if (this._backgroundBox === null) {
13221      this._backgroundBox = new Mesh(
13222        new BoxGeometry(),
13223        new MeshBasicMaterial({
13224          name: "PMREM.Background",
13225          side: BackSide,
13226          depthWrite: false,
13227          depthTest: false
13228        })
13229      );
13230    }
13231    const backgroundBox = this._backgroundBox;
13232    const backgroundMaterial = backgroundBox.material;
13233    let useSolidColor = false;
13234    const background = scene.background;
13235    if (background) {
13236      if (background.isColor) {
13237        backgroundMaterial.color.copy(background);
13238        scene.background = null;
13239        useSolidColor = true;
13240      }
13241    } else {
13242      backgroundMaterial.color.copy(_clearColor$2);
13243      useSolidColor = true;
13244    }
13245    renderer.setRenderTarget(cubeUVRenderTarget);
13246    renderer.clear();
13247    if (useSolidColor) {
13248      renderer.render(backgroundBox, cubeCamera);
13249    }
13250    for (let i = 0; i < 6; i++) {
13251      const col = i % 3;
13252      if (col === 0) {
13253        cubeCamera.up.set(0, upSign[i], 0);
13254        cubeCamera.position.set(position.x, position.y, position.z);
13255        cubeCamera.lookAt(position.x + forwardSign[i], position.y, position.z);
13256      } else if (col === 1) {
13257        cubeCamera.up.set(0, 0, upSign[i]);
13258        cubeCamera.position.set(position.x, position.y, position.z);
13259        cubeCamera.lookAt(position.x, position.y + forwardSign[i], position.z);
13260      } else {
13261        cubeCamera.up.set(0, upSign[i], 0);
13262        cubeCamera.position.set(position.x, position.y, position.z);
13263        cubeCamera.lookAt(position.x, position.y, position.z + forwardSign[i]);
13264      }
13265      const size3 = this._cubeSize;
13266      this._setViewport(cubeUVRenderTarget, col * size3, i > 2 ? size3 : 0, size3, size3);
13267      renderer.render(scene, cubeCamera);
13268    }
13269    renderer.autoClear = originalAutoClear;
13270    scene.background = background;
13271  }
13272  _textureToCubeUV(texture3, cubeUVRenderTarget) {
13273    const renderer = this._renderer;
13274    const isCubeTexture = texture3.mapping === CubeReflectionMapping || texture3.mapping === CubeRefractionMapping;
13275    if (isCubeTexture) {
13276      if (this._cubemapMaterial === null) {
13277        this._cubemapMaterial = _getCubemapMaterial(texture3);
13278      }
13279    } else {
13280      if (this._equirectMaterial === null) {
13281        this._equirectMaterial = _getEquirectMaterial(texture3);
13282      }
13283    }
13284    const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial;
13285    material.fragmentNode.value = texture3;
13286    const mesh = this._lodMeshes[0];
13287    mesh.material = material;
13288    const size3 = this._cubeSize;
13289    this._setViewport(cubeUVRenderTarget, 0, 0, 3 * size3, 2 * size3);
13290    renderer.setRenderTarget(cubeUVRenderTarget);
13291    renderer.render(mesh, _flatCamera);
13292  }
13293  _applyPMREM(cubeUVRenderTarget) {
13294    const renderer = this._renderer;
13295    const autoClear = renderer.autoClear;
13296    renderer.autoClear = false;
13297    const n = this._lodMeshes.length;
13298    for (let i = 1; i < n; i++) {
13299      this._applyGGXFilter(cubeUVRenderTarget, i - 1, i);
13300    }
13301    renderer.autoClear = autoClear;
13302  }
13303  /**
13304   * Applies GGX VNDF importance sampling filter to generate a prefiltered environment map.
13305   * Uses Monte Carlo integration with VNDF importance sampling to accurately represent the
13306   * GGX BRDF for physically-based rendering. Reads from the previous LOD level and
13307   * applies incremental roughness filtering to avoid over-blurring.
13308   *
13309   * @private
13310   * @param {RenderTarget} cubeUVRenderTarget
13311   * @param {number} lodIn - Source LOD level to read from
13312   * @param {number} lodOut - Target LOD level to write to
13313   */
13314  _applyGGXFilter(cubeUVRenderTarget, lodIn, lodOut) {
13315    const renderer = this._renderer;
13316    const pingPongRenderTarget = this._pingPongRenderTarget;
13317    const ggxMaterial = this._ggxMaterial;
13318    const ggxMesh = this._lodMeshes[lodOut];
13319    ggxMesh.material = ggxMaterial;
13320    const ggxUniforms = _uniformsMap.get(ggxMaterial);
13321    const targetRoughness = lodOut / (this._lodMeshes.length - 1);
13322    const sourceRoughness = lodIn / (this._lodMeshes.length - 1);
13323    const incrementalRoughness = Math.sqrt(targetRoughness * targetRoughness - sourceRoughness * sourceRoughness);
13324    const blurStrength = 0 + targetRoughness * 1.25;
13325    const adjustedRoughness = incrementalRoughness * blurStrength;
13326    const { _lodMax } = this;
13327    const outputSize = this._sizeLods[lodOut];
13328    const x = 3 * outputSize * (lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0);
13329    const y = 4 * (this._cubeSize - outputSize);
13330    cubeUVRenderTarget.texture.frame = (cubeUVRenderTarget.texture.frame || 0) + 1;
13331    ggxUniforms.envMap.value = cubeUVRenderTarget.texture;
13332    ggxUniforms.roughness.value = adjustedRoughness;
13333    ggxUniforms.mipInt.value = _lodMax - lodIn;
13334    this._setViewport(pingPongRenderTarget, x, y, 3 * outputSize, 2 * outputSize);
13335    renderer.setRenderTarget(pingPongRenderTarget);
13336    renderer.render(ggxMesh, _flatCamera);
13337    pingPongRenderTarget.texture.frame = (pingPongRenderTarget.texture.frame || 0) + 1;
13338    ggxUniforms.envMap.value = pingPongRenderTarget.texture;
13339    ggxUniforms.roughness.value = 0;
13340    ggxUniforms.mipInt.value = _lodMax - lodOut;
13341    this._setViewport(cubeUVRenderTarget, x, y, 3 * outputSize, 2 * outputSize);
13342    renderer.setRenderTarget(cubeUVRenderTarget);
13343    renderer.render(ggxMesh, _flatCamera);
13344  }
13345  /**
13346   * This is a two-pass Gaussian blur for a cubemap. Normally this is done
13347   * vertically and horizontally, but this breaks down on a cube. Here we apply
13348   * the blur latitudinally (around the poles), and then longitudinally (towards
13349   * the poles) to approximate the orthogonally-separable blur. It is least
13350   * accurate at the poles, but still does a decent job.
13351   *
13352   * Used for initial scene blur in fromScene() method when sigma > 0.
13353   *
13354   * @private
13355   * @param {RenderTarget} cubeUVRenderTarget - The cubemap render target.
13356   * @param {number} lodIn - The input level-of-detail.
13357   * @param {number} lodOut - The output level-of-detail.
13358   * @param {number} sigma - The blur radius in radians.
13359   * @param {Vector3} [poleAxis] - The pole axis.
13360   */
13361  _blur(cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis) {
13362    const pingPongRenderTarget = this._pingPongRenderTarget;
13363    this._halfBlur(
13364      cubeUVRenderTarget,
13365      pingPongRenderTarget,
13366      lodIn,
13367      lodOut,
13368      sigma,
13369      "latitudinal",
13370      poleAxis
13371    );
13372    this._halfBlur(
13373      pingPongRenderTarget,
13374      cubeUVRenderTarget,
13375      lodOut,
13376      lodOut,
13377      sigma,
13378      "longitudinal",
13379      poleAxis
13380    );
13381  }
13382  _halfBlur(targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis) {
13383    const renderer = this._renderer;
13384    const blurMaterial = this._blurMaterial;
13385    if (direction !== "latitudinal" && direction !== "longitudinal") {
13386      error("blur direction must be either latitudinal or longitudinal!");
13387    }
13388    const STANDARD_DEVIATIONS = 3;
13389    const blurMesh = this._lodMeshes[lodOut];
13390    blurMesh.material = blurMaterial;
13391    const blurUniforms = _uniformsMap.get(blurMaterial);
13392    const pixels = this._sizeLods[lodIn] - 1;
13393    const radiansPerPixel = isFinite(sigmaRadians) ? Math.PI / (2 * pixels) : 2 * Math.PI / (2 * MAX_SAMPLES - 1);
13394    const sigmaPixels = sigmaRadians / radiansPerPixel;
13395    const samples = isFinite(sigmaRadians) ? 1 + Math.floor(STANDARD_DEVIATIONS * sigmaPixels) : MAX_SAMPLES;
13396    if (samples > MAX_SAMPLES) {
13397      warn(`sigmaRadians, ${sigmaRadians}, is too large and will clip, as it requested ${samples} samples when the maximum is set to ${MAX_SAMPLES}`);
13398    }
13399    const weights = [];
13400    let sum = 0;
13401    for (let i = 0; i < MAX_SAMPLES; ++i) {
13402      const x2 = i / sigmaPixels;
13403      const weight = Math.exp(-x2 * x2 / 2);
13404      weights.push(weight);
13405      if (i === 0) {
13406        sum += weight;
13407      } else if (i < samples) {
13408        sum += 2 * weight;
13409      }
13410    }
13411    for (let i = 0; i < weights.length; i++) {
13412      weights[i] = weights[i] / sum;
13413    }
13414    targetIn.texture.frame = (targetIn.texture.frame || 0) + 1;
13415    blurUniforms.envMap.value = targetIn.texture;
13416    blurUniforms.samples.value = samples;
13417    blurUniforms.weights.array = weights;
13418    blurUniforms.latitudinal.value = direction === "latitudinal" ? 1 : 0;
13419    if (poleAxis) {
13420      blurUniforms.poleAxis.value = poleAxis;
13421    }
13422    const { _lodMax } = this;
13423    blurUniforms.dTheta.value = radiansPerPixel;
13424    blurUniforms.mipInt.value = _lodMax - lodIn;
13425    const outputSize = this._sizeLods[lodOut];
13426    const x = 3 * outputSize * (lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0);
13427    const y = 4 * (this._cubeSize - outputSize);
13428    this._setViewport(targetOut, x, y, 3 * outputSize, 2 * outputSize);
13429    renderer.setRenderTarget(targetOut);
13430    renderer.render(blurMesh, _flatCamera);
13431  }
13432  _setViewport(target, x, y, width, height) {
13433    if (this._renderer.isWebGLRenderer) {
13434      target.viewport.set(x, target.height - height - y, width, height);
13435      target.scissor.set(x, target.height - height - y, width, height);
13436    } else {
13437      target.viewport.set(x, y, width, height);
13438      target.scissor.set(x, y, width, height);
13439    }
13440  }
13441};
13442function _createPlanes(lodMax) {
13443  const sizeLods = [];
13444  const sigmas = [];
13445  const lodMeshes = [];
13446  let lod = lodMax;
13447  const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
13448  for (let i = 0; i < totalLods; i++) {
13449    const sizeLod = Math.pow(2, lod);
13450    sizeLods.push(sizeLod);
13451    let sigma = 1 / sizeLod;
13452    if (i > lodMax - LOD_MIN) {
13453      sigma = EXTRA_LOD_SIGMA[i - lodMax + LOD_MIN - 1];
13454    } else if (i === 0) {
13455      sigma = 0;
13456    }
13457    sigmas.push(sigma);
13458    const texelSize = 1 / (sizeLod - 2);
13459    const min5 = -texelSize;
13460    const max5 = 1 + texelSize;
13461    const uv1 = [min5, min5, max5, min5, max5, max5, min5, min5, max5, max5, min5, max5];
13462    const cubeFaces = 6;
13463    const vertices = 6;
13464    const positionSize = 3;
13465    const uvSize = 2;
13466    const faceIndexSize = 1;
13467    const position = new Float32Array(positionSize * vertices * cubeFaces);
13468    const uv3 = new Float32Array(uvSize * vertices * cubeFaces);
13469    const faceIndex = new Float32Array(faceIndexSize * vertices * cubeFaces);
13470    for (let face = 0; face < cubeFaces; face++) {
13471      const x = face % 3 * 2 / 3 - 1;
13472      const y = face > 2 ? 0 : -1;
13473      const coordinates = [
13474        x,
13475        y,
13476        0,
13477        x + 2 / 3,
13478        y,
13479        0,
13480        x + 2 / 3,
13481        y + 1,
13482        0,
13483        x,
13484        y,
13485        0,
13486        x + 2 / 3,
13487        y + 1,
13488        0,
13489        x,
13490        y + 1,
13491        0
13492      ];
13493      const faceIdx = _faceLib[face];
13494      position.set(coordinates, positionSize * vertices * faceIdx);
13495      uv3.set(uv1, uvSize * vertices * faceIdx);
13496      const fill = [faceIdx, faceIdx, faceIdx, faceIdx, faceIdx, faceIdx];
13497      faceIndex.set(fill, faceIndexSize * vertices * faceIdx);
13498    }
13499    const planes = new BufferGeometry();
13500    planes.setAttribute("position", new BufferAttribute(position, positionSize));
13501    planes.setAttribute("uv", new BufferAttribute(uv3, uvSize));
13502    planes.setAttribute("faceIndex", new BufferAttribute(faceIndex, faceIndexSize));
13503    lodMeshes.push(new Mesh(planes, null));
13504    if (lod > LOD_MIN) {
13505      lod--;
13506    }
13507  }
13508  return { lodMeshes, sizeLods, sigmas };
13509}
13510function _createRenderTarget(width, height) {
13511  const params = {
13512    magFilter: LinearFilter,
13513    minFilter: LinearFilter,
13514    generateMipmaps: false,
13515    type: HalfFloatType,
13516    format: RGBAFormat,
13517    colorSpace: LinearSRGBColorSpace
13518    //depthBuffer: false
13519  };
13520  const cubeUVRenderTarget = new RenderTarget(width, height, params);
13521  cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
13522  cubeUVRenderTarget.texture.name = "PMREM.cubeUv";
13523  cubeUVRenderTarget.texture.isPMREMTexture = true;
13524  cubeUVRenderTarget.scissorTest = true;
13525  return cubeUVRenderTarget;
13526}
13527function _getMaterial(type) {
13528  const material = new NodeMaterial();
13529  material.depthTest = false;
13530  material.depthWrite = false;
13531  material.blending = NoBlending;
13532  material.name = `PMREM_${type}`;
13533  return material;
13534}
13535function _getBlurShader(lodMax, width, height) {
13536  const weights = uniformArray(new Array(MAX_SAMPLES).fill(0));
13537  const poleAxis = uniform(new Vector3(0, 1, 0));
13538  const dTheta = uniform(0);
13539  const n = float(MAX_SAMPLES);
13540  const latitudinal = uniform(0);
13541  const samples = uniform(1);
13542  const envMap = texture();
13543  const mipInt = uniform(0);
13544  const CUBEUV_TEXEL_WIDTH = float(1 / width);
13545  const CUBEUV_TEXEL_HEIGHT = float(1 / height);
13546  const CUBEUV_MAX_MIP = float(lodMax);
13547  const materialUniforms = {
13548    n,
13549    latitudinal,
13550    weights,
13551    poleAxis,
13552    outputDirection: _outputDirection,
13553    dTheta,
13554    samples,
13555    envMap,
13556    mipInt,
13557    CUBEUV_TEXEL_WIDTH,
13558    CUBEUV_TEXEL_HEIGHT,
13559    CUBEUV_MAX_MIP
13560  };
13561  const material = _getMaterial("blur");
13562  material.fragmentNode = blur({ ...materialUniforms, latitudinal: latitudinal.equal(1) });
13563  _uniformsMap.set(material, materialUniforms);
13564  return material;
13565}
13566function _getGGXShader(lodMax, width, height) {
13567  const envMap = texture();
13568  const roughness3 = uniform(0);
13569  const mipInt = uniform(0);
13570  const CUBEUV_TEXEL_WIDTH = float(1 / width);
13571  const CUBEUV_TEXEL_HEIGHT = float(1 / height);
13572  const CUBEUV_MAX_MIP = float(lodMax);
13573  const materialUniforms = {
13574    envMap,
13575    roughness: roughness3,
13576    mipInt,
13577    CUBEUV_TEXEL_WIDTH,
13578    CUBEUV_TEXEL_HEIGHT,
13579    CUBEUV_MAX_MIP
13580  };
13581  const material = _getMaterial("ggx");
13582  material.fragmentNode = ggxConvolution({
13583    ...materialUniforms,
13584    N_immutable: _outputDirection,
13585    GGX_SAMPLES: uint(GGX_SAMPLES)
13586  });
13587  _uniformsMap.set(material, materialUniforms);
13588  return material;
13589}
13590function _getCubemapMaterial(envTexture) {
13591  const material = _getMaterial("cubemap");
13592  material.fragmentNode = cubeTexture(envTexture, _outputDirection);
13593  return material;
13594}
13595function _getEquirectMaterial(envTexture) {
13596  const material = _getMaterial("equirect");
13597  material.fragmentNode = texture(envTexture, equirectUV(_outputDirection), 0);
13598  return material;
13599}
13600var _cache = /* @__PURE__ */ new WeakMap();
13601function _generateCubeUVSize(imageHeight) {
13602  const maxMip = Math.log2(imageHeight) - 2;
13603  const texelHeight = 1 / imageHeight;
13604  const texelWidth = 1 / (3 * Math.max(Math.pow(2, maxMip), 7 * 16));
13605  return { texelWidth, texelHeight, maxMip };
13606}
13607function _getPMREMFromTexture(texture3, renderer, generator) {
13608  const cache4 = _getCache(renderer);
13609  let cacheTexture = cache4.get(texture3);
13610  const pmremVersion = cacheTexture !== void 0 ? cacheTexture.pmremVersion : -1;
13611  if (pmremVersion !== texture3.pmremVersion) {
13612    const image = texture3.image;
13613    if (texture3.isCubeTexture) {
13614      if (isCubeMapReady(image)) {
13615        cacheTexture = generator.fromCubemap(texture3, cacheTexture);
13616      } else {
13617        return null;
13618      }
13619    } else {
13620      if (isEquirectangularMapReady(image)) {
13621        cacheTexture = generator.fromEquirectangular(texture3, cacheTexture);
13622      } else {
13623        return null;
13624      }
13625    }
13626    cacheTexture.pmremVersion = texture3.pmremVersion;
13627    cache4.set(texture3, cacheTexture);
13628  }
13629  return cacheTexture.texture;
13630}
13631function _getCache(renderer) {
13632  let rendererCache = _cache.get(renderer);
13633  if (rendererCache === void 0) {
13634    rendererCache = /* @__PURE__ */ new WeakMap();
13635    _cache.set(renderer, rendererCache);
13636  }
13637  return rendererCache;
13638}
13639var PMREMNode = class extends TempNode {
13640  static get type() {
13641    return "PMREMNode";
13642  }
13643  /**
13644   * Constructs a new function overloading node.
13645   *
13646   * @param {Texture} value - The input texture.
13647   * @param {Node<vec2>} [uvNode=null] - The uv node.
13648   * @param {Node<float>} [levelNode=null] - The level node.
13649   */
13650  constructor(value, uvNode = null, levelNode = null) {
13651    super("vec3");
13652    this._value = value;
13653    this._pmrem = null;
13654    this.uvNode = uvNode;
13655    this.levelNode = levelNode;
13656    this._generator = null;
13657    const defaultTexture = new Texture();
13658    defaultTexture.isRenderTargetTexture = true;
13659    this._texture = texture(defaultTexture);
13660    this._width = uniform(0);
13661    this._height = uniform(0);
13662    this._maxMip = uniform(0);
13663    this.updateBeforeType = NodeUpdateType.RENDER;
13664  }
13665  set value(value) {
13666    this._value = value;
13667    this._pmrem = null;
13668  }
13669  /**
13670   * The node's texture value.
13671   *
13672   * @type {Texture}
13673   */
13674  get value() {
13675    return this._value;
13676  }
13677  /**
13678   * Uses the given PMREM texture to update internal values.
13679   *
13680   * @param {Texture} texture - The PMREM texture.
13681   */
13682  updateFromTexture(texture3) {
13683    const cubeUVSize = _generateCubeUVSize(texture3.image.height);
13684    this._texture.value = texture3;
13685    this._width.value = cubeUVSize.texelWidth;
13686    this._height.value = cubeUVSize.texelHeight;
13687    this._maxMip.value = cubeUVSize.maxMip;
13688  }
13689  updateBefore(frame) {
13690    let pmrem = this._pmrem;
13691    const pmremVersion = pmrem ? pmrem.pmremVersion : -1;
13692    const texture3 = this._value;
13693    if (pmremVersion !== texture3.pmremVersion) {
13694      if (texture3.isPMREMTexture === true) {
13695        pmrem = texture3;
13696      } else {
13697        pmrem = _getPMREMFromTexture(texture3, frame.renderer, this._generator);
13698      }
13699      if (pmrem !== null) {
13700        this._pmrem = pmrem;
13701        this.updateFromTexture(pmrem);
13702      }
13703    }
13704  }
13705  setup(builder) {
13706    if (this._generator === null) {
13707      this._generator = new PMREMGenerator(builder.renderer);
13708    }
13709    this.updateBefore(builder);
13710    let uvNode = this.uvNode;
13711    if (uvNode === null && builder.context.getUV) {
13712      uvNode = builder.context.getUV(this, builder);
13713    }
13714    uvNode = materialEnvRotation.mul(vec3(uvNode.x, uvNode.y.negate(), uvNode.z));
13715    let levelNode = this.levelNode;
13716    if (levelNode === null && builder.context.getTextureLevel) {
13717      levelNode = builder.context.getTextureLevel(this);
13718    }
13719    return textureCubeUV(this._texture, uvNode, levelNode, this._width, this._height, this._maxMip);
13720  }
13721  dispose() {
13722    super.dispose();
13723    if (this._generator !== null) this._generator.dispose();
13724  }
13725};
13726function isCubeMapReady(image) {
13727  if (image === null || image === void 0) return false;
13728  let count = 0;
13729  const length3 = 6;
13730  for (let i = 0; i < length3; i++) {
13731    if (image[i] !== void 0) count++;
13732  }
13733  return count === length3;
13734}
13735function isEquirectangularMapReady(image) {
13736  if (image === null || image === void 0) return false;
13737  return image.height > 0;
13738}
13739var pmremTexture = /* @__PURE__ */ nodeProxy(PMREMNode).setParameterLength(1, 3);
13740var _rendererCache = /* @__PURE__ */ new WeakMap();
13741var EnvironmentNode = class extends LightingNode {
13742  static get type() {
13743    return "EnvironmentNode";
13744  }
13745  /**
13746   * Constructs a new environment node.
13747   *
13748   * @param {Node} [envNode=null] - A node representing the environment.
13749   */
13750  constructor(envNode = null) {
13751    super();
13752    this.envNode = envNode;
13753  }
13754  setup(builder) {
13755    const { material } = builder;
13756    let envNode = this.envNode;
13757    if (envNode.isTextureNode || envNode.isMaterialReferenceNode) {
13758      const value = envNode.isTextureNode ? envNode.value : material[envNode.property];
13759      const cache4 = this._getPMREMNodeCache(builder.renderer);
13760      let cacheEnvNode = cache4.get(value);
13761      if (cacheEnvNode === void 0) {
13762        cacheEnvNode = pmremTexture(value);
13763        cache4.set(value, cacheEnvNode);
13764      }
13765      envNode = cacheEnvNode;
13766    }
13767    const useAnisotropy = material.useAnisotropy === true || material.anisotropy > 0;
13768    const radianceNormalView = useAnisotropy ? bentNormalView : normalView;
13769    const radiance = envNode.context(createRadianceContext(roughness, radianceNormalView)).mul(materialEnvIntensity);
13770    const irradiance = envNode.context(createIrradianceContext(normalWorld)).mul(Math.PI).mul(materialEnvIntensity);
13771    const isolateRadiance = isolate(radiance);
13772    const isolateIrradiance = isolate(irradiance);
13773    builder.context.radiance.addAssign(isolateRadiance);
13774    builder.context.iblIrradiance.addAssign(isolateIrradiance);
13775    const clearcoatRadiance = builder.context.lightingModel.clearcoatRadiance;
13776    if (clearcoatRadiance) {
13777      const clearcoatRadianceContext = envNode.context(createRadianceContext(clearcoatRoughness, clearcoatNormalView)).mul(materialEnvIntensity);
13778      const isolateClearcoatRadiance = isolate(clearcoatRadianceContext);
13779      clearcoatRadiance.addAssign(isolateClearcoatRadiance);
13780    }
13781  }
13782  /**
13783   * Returns the PMREM node cache of the current renderer.
13784   *
13785   * @private
13786   * @param {Renderer} renderer - The current renderer.
13787   * @return {WeakMap} The node cache.
13788   */
13789  _getPMREMNodeCache(renderer) {
13790    let pmremCache = _rendererCache.get(renderer);
13791    if (pmremCache === void 0) {
13792      pmremCache = /* @__PURE__ */ new WeakMap();
13793      _rendererCache.set(renderer, pmremCache);
13794    }
13795    return pmremCache;
13796  }
13797};
13798var createRadianceContext = (roughnessNode, normalViewNode) => {
13799  let reflectVec = null;
13800  return {
13801    getUV: () => {
13802      if (reflectVec === null) {
13803        reflectVec = positionViewDirection.negate().reflect(normalViewNode);
13804        reflectVec = pow4(roughnessNode).mix(reflectVec, normalViewNode).normalize();
13805        reflectVec = reflectVec.transformDirection(cameraViewMatrix);
13806      }
13807      return reflectVec;
13808    },
13809    getTextureLevel: () => {
13810      return roughnessNode;
13811    }
13812  };
13813};
13814var createIrradianceContext = (normalWorldNode) => {
13815  return {
13816    getUV: () => {
13817      return normalWorldNode;
13818    },
13819    getTextureLevel: () => {
13820      return float(1);
13821    }
13822  };
13823};
13824var _defaultValues$6 = /* @__PURE__ */ new MeshStandardMaterial();
13825var MeshStandardNodeMaterial = class extends NodeMaterial {
13826  static get type() {
13827    return "MeshStandardNodeMaterial";
13828  }
13829  /**
13830   * Constructs a new mesh standard node material.
13831   *
13832   * @param {Object} [parameters] - The configuration parameter.
13833   */
13834  constructor(parameters) {
13835    super();
13836    this.isMeshStandardNodeMaterial = true;
13837    this.lights = true;
13838    this.emissiveNode = null;
13839    this.metalnessNode = null;
13840    this.roughnessNode = null;
13841    this.setDefaultValues(_defaultValues$6);
13842    this.setValues(parameters);
13843  }
13844  /**
13845   * Overwritten since this type of material uses {@link EnvironmentNode}
13846   * to implement the PBR (PMREM based) environment mapping. Besides, the
13847   * method honors `Scene.environment`.
13848   *
13849   * @param {NodeBuilder} builder - The current node builder.
13850   * @return {?EnvironmentNode<vec3>} The environment node.
13851   */
13852  setupEnvironment(builder) {
13853    let envNode = super.setupEnvironment(builder);
13854    if (envNode === null && builder.environmentNode) {
13855      envNode = builder.environmentNode;
13856    }
13857    return envNode ? new EnvironmentNode(envNode) : null;
13858  }
13859  /**
13860   * Setups the lighting model.
13861   *
13862   * @return {PhysicalLightingModel} The lighting model.
13863   */
13864  setupLightingModel() {
13865    return new PhysicalLightingModel();
13866  }
13867  /**
13868   * Setups the specular related node variables.
13869   */
13870  setupSpecular() {
13871    const specularColorNode = mix(vec3(0.04), diffuseColor.rgb, metalness);
13872    specularColor.assign(vec3(0.04));
13873    specularColorBlended.assign(specularColorNode);
13874    specularF90.assign(1);
13875  }
13876  /**
13877   * Setups the standard specific node variables.
13878   *
13879   * @param {NodeBuilder} builder - The current node builder.
13880   */
13881  setupVariants() {
13882    const metalnessNode = this.metalnessNode ? float(this.metalnessNode) : materialMetalness;
13883    metalness.assign(metalnessNode);
13884    let roughnessNode = this.roughnessNode ? float(this.roughnessNode) : materialRoughness;
13885    roughnessNode = getRoughness({ roughness: roughnessNode });
13886    roughness.assign(roughnessNode);
13887    this.setupSpecular();
13888    diffuseContribution.assign(diffuseColor.rgb.mul(metalnessNode.oneMinus()));
13889  }
13890  copy(source) {
13891    this.emissiveNode = source.emissiveNode;
13892    this.metalnessNode = source.metalnessNode;
13893    this.roughnessNode = source.roughnessNode;
13894    return super.copy(source);
13895  }
13896};
13897var _defaultValues$5 = /* @__PURE__ */ new MeshPhysicalMaterial();
13898var MeshPhysicalNodeMaterial = class extends MeshStandardNodeMaterial {
13899  static get type() {
13900    return "MeshPhysicalNodeMaterial";
13901  }
13902  /**
13903   * Constructs a new mesh physical node material.
13904   *
13905   * @param {Object} [parameters] - The configuration parameter.
13906   */
13907  constructor(parameters) {
13908    super();
13909    this.isMeshPhysicalNodeMaterial = true;
13910    this.clearcoatNode = null;
13911    this.clearcoatRoughnessNode = null;
13912    this.clearcoatNormalNode = null;
13913    this.sheenNode = null;
13914    this.sheenRoughnessNode = null;
13915    this.iridescenceNode = null;
13916    this.iridescenceIORNode = null;
13917    this.iridescenceThicknessNode = null;
13918    this.specularIntensityNode = null;
13919    this.specularColorNode = null;
13920    this.iorNode = null;
13921    this.transmissionNode = null;
13922    this.thicknessNode = null;
13923    this.attenuationDistanceNode = null;
13924    this.attenuationColorNode = null;
13925    this.dispersionNode = null;
13926    this.anisotropyNode = null;
13927    this.setDefaultValues(_defaultValues$5);
13928    this.setValues(parameters);
13929  }
13930  /**
13931   * Whether the lighting model should use clearcoat or not.
13932   *
13933   * @type {boolean}
13934   * @default true
13935   */
13936  get useClearcoat() {
13937    return this.clearcoat > 0 || this.clearcoatNode !== null;
13938  }
13939  /**
13940   * Whether the lighting model should use iridescence or not.
13941   *
13942   * @type {boolean}
13943   * @default true
13944   */
13945  get useIridescence() {
13946    return this.iridescence > 0 || this.iridescenceNode !== null;
13947  }
13948  /**
13949   * Whether the lighting model should use sheen or not.
13950   *
13951   * @type {boolean}
13952   * @default true
13953   */
13954  get useSheen() {
13955    return this.sheen > 0 || this.sheenNode !== null;
13956  }
13957  /**
13958   * Whether the lighting model should use anisotropy or not.
13959   *
13960   * @type {boolean}
13961   * @default true
13962   */
13963  get useAnisotropy() {
13964    return this.anisotropy > 0 || this.anisotropyNode !== null;
13965  }
13966  /**
13967   * Whether the lighting model should use transmission or not.
13968   *
13969   * @type {boolean}
13970   * @default true
13971   */
13972  get useTransmission() {
13973    return this.transmission > 0 || this.transmissionNode !== null;
13974  }
13975  /**
13976   * Whether the lighting model should use dispersion or not.
13977   *
13978   * @type {boolean}
13979   * @default true
13980   */
13981  get useDispersion() {
13982    return this.dispersion > 0 || this.dispersionNode !== null;
13983  }
13984  /**
13985   * Setups the specular related node variables.
13986   */
13987  setupSpecular() {
13988    const iorNode = this.iorNode ? float(this.iorNode) : materialIOR;
13989    ior.assign(iorNode);
13990    specularColor.assign(min$1(pow2(ior.sub(1).div(ior.add(1))).mul(materialSpecularColor), vec3(1)).mul(materialSpecularIntensity));
13991    specularColorBlended.assign(mix(specularColor, diffuseColor.rgb, metalness));
13992    specularF90.assign(mix(materialSpecularIntensity, 1, metalness));
13993  }
13994  /**
13995   * Setups the lighting model.
13996   *
13997   * @return {PhysicalLightingModel} The lighting model.
13998   */
13999  setupLightingModel() {
14000    return new PhysicalLightingModel(this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion);
14001  }
14002  /**
14003   * Setups the physical specific node variables.
14004   *
14005   * @param {NodeBuilder} builder - The current node builder.
14006   */
14007  setupVariants(builder) {
14008    super.setupVariants(builder);
14009    if (this.useClearcoat) {
14010      const clearcoatNode = this.clearcoatNode ? float(this.clearcoatNode) : materialClearcoat;
14011      const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float(this.clearcoatRoughnessNode) : materialClearcoatRoughness;
14012      clearcoat.assign(clearcoatNode);
14013      clearcoatRoughness.assign(getRoughness({ roughness: clearcoatRoughnessNode }));
14014    }
14015    if (this.useSheen) {
14016      const sheenNode = this.sheenNode ? vec3(this.sheenNode) : materialSheen;
14017      const sheenRoughnessNode = this.sheenRoughnessNode ? float(this.sheenRoughnessNode) : materialSheenRoughness;
14018      sheen.assign(sheenNode);
14019      sheenRoughness.assign(sheenRoughnessNode);
14020    }
14021    if (this.useIridescence) {
14022      const iridescenceNode = this.iridescenceNode ? float(this.iridescenceNode) : materialIridescence;
14023      const iridescenceIORNode = this.iridescenceIORNode ? float(this.iridescenceIORNode) : materialIridescenceIOR;
14024      const iridescenceThicknessNode = this.iridescenceThicknessNode ? float(this.iridescenceThicknessNode) : materialIridescenceThickness;
14025      iridescence.assign(iridescenceNode);
14026      iridescenceIOR.assign(iridescenceIORNode);
14027      iridescenceThickness.assign(iridescenceThicknessNode);
14028    }
14029    if (this.useAnisotropy) {
14030      const anisotropyV = (this.anisotropyNode ? vec2(this.anisotropyNode) : materialAnisotropy).toVar();
14031      anisotropy.assign(anisotropyV.length());
14032      If(anisotropy.equal(0), () => {
14033        anisotropyV.assign(vec2(1, 0));
14034      }).Else(() => {
14035        anisotropyV.divAssign(vec2(anisotropy));
14036        anisotropy.assign(anisotropy.saturate());
14037      });
14038      alphaT.assign(anisotropy.pow2().mix(roughness.pow2(), 1));
14039      anisotropyT.assign(TBNViewMatrix[0].mul(anisotropyV.x).add(TBNViewMatrix[1].mul(anisotropyV.y)));
14040      anisotropyB.assign(TBNViewMatrix[1].mul(anisotropyV.x).sub(TBNViewMatrix[0].mul(anisotropyV.y)));
14041    }
14042    if (this.useTransmission) {
14043      const transmissionNode = this.transmissionNode ? float(this.transmissionNode) : materialTransmission;
14044      const thicknessNode = this.thicknessNode ? float(this.thicknessNode) : materialThickness;
14045      const attenuationDistanceNode = this.attenuationDistanceNode ? float(this.attenuationDistanceNode) : materialAttenuationDistance;
14046      const attenuationColorNode = this.attenuationColorNode ? vec3(this.attenuationColorNode) : materialAttenuationColor;
14047      transmission.assign(transmissionNode);
14048      thickness.assign(thicknessNode);
14049      attenuationDistance.assign(attenuationDistanceNode);
14050      attenuationColor.assign(attenuationColorNode);
14051      if (this.useDispersion) {
14052        const dispersionNode = this.dispersionNode ? float(this.dispersionNode) : materialDispersion;
14053        dispersion.assign(dispersionNode);
14054      }
14055    }
14056  }
14057  /**
14058   * Setups the clearcoat normal node.
14059   *
14060   * @return {Node<vec3>} The clearcoat normal.
14061   */
14062  setupClearcoatNormal() {
14063    return this.clearcoatNormalNode ? vec3(this.clearcoatNormalNode) : materialClearcoatNormal;
14064  }
14065  setup(builder) {
14066    builder.context.setupClearcoatNormal = () => subBuild(this.setupClearcoatNormal(builder), "NORMAL", "vec3");
14067    super.setup(builder);
14068  }
14069  copy(source) {
14070    this.clearcoatNode = source.clearcoatNode;
14071    this.clearcoatRoughnessNode = source.clearcoatRoughnessNode;
14072    this.clearcoatNormalNode = source.clearcoatNormalNode;
14073    this.sheenNode = source.sheenNode;
14074    this.sheenRoughnessNode = source.sheenRoughnessNode;
14075    this.iridescenceNode = source.iridescenceNode;
14076    this.iridescenceIORNode = source.iridescenceIORNode;
14077    this.iridescenceThicknessNode = source.iridescenceThicknessNode;
14078    this.specularIntensityNode = source.specularIntensityNode;
14079    this.specularColorNode = source.specularColorNode;
14080    this.iorNode = source.iorNode;
14081    this.transmissionNode = source.transmissionNode;
14082    this.thicknessNode = source.thicknessNode;
14083    this.attenuationDistanceNode = source.attenuationDistanceNode;
14084    this.attenuationColorNode = source.attenuationColorNode;
14085    this.dispersionNode = source.dispersionNode;
14086    this.anisotropyNode = source.anisotropyNode;
14087    return super.copy(source);
14088  }
14089};
14090var getGradientIrradiance = /* @__PURE__ */ Fn(({ normal: normal2, lightDirection, builder }) => {
14091  const dotNL = normal2.dot(lightDirection);
14092  const coord = vec2(dotNL.mul(0.5).add(0.5), 0);
14093  if (builder.material.gradientMap) {
14094    const gradientMap = materialReference("gradientMap", "texture").context({ getUV: () => coord });
14095    return vec3(gradientMap.r);
14096  } else {
14097    const fw = coord.fwidth().mul(0.5);
14098    return mix(vec3(0.7), vec3(1), smoothstep(float(0.7).sub(fw.x), float(0.7).add(fw.x), coord.x));
14099  }
14100});
14101var ToonLightingModel = class extends LightingModel {
14102  /**
14103   * Implements the direct lighting. Instead of using a conventional smooth irradiance, the irradiance is
14104   * reduced to a small number of discrete shades to create a comic-like, flat look.
14105   *
14106   * @param {Object} lightData - The light data.
14107   * @param {NodeBuilder} builder - The current node builder.
14108   */
14109  direct({ lightDirection, lightColor, reflectedLight }, builder) {
14110    const irradiance = getGradientIrradiance({ normal: normalGeometry, lightDirection, builder }).mul(lightColor);
14111    reflectedLight.directDiffuse.addAssign(irradiance.mul(BRDF_Lambert({ diffuseColor: diffuseColor.rgb })));
14112  }
14113  /**
14114   * Implements the indirect lighting.
14115   *
14116   * @param {NodeBuilder} builder - The current node builder.
14117   */
14118  indirect(builder) {
14119    const { ambientOcclusion, irradiance, reflectedLight } = builder.context;
14120    reflectedLight.indirectDiffuse.addAssign(irradiance.mul(BRDF_Lambert({ diffuseColor })));
14121    reflectedLight.indirectDiffuse.mulAssign(ambientOcclusion);
14122  }
14123};
14124var _defaultValues$4 = /* @__PURE__ */ new MeshToonMaterial();
14125var MeshToonNodeMaterial = class extends NodeMaterial {
14126  static get type() {
14127    return "MeshToonNodeMaterial";
14128  }
14129  /**
14130   * Constructs a new mesh toon node material.
14131   *
14132   * @param {Object} [parameters] - The configuration parameter.
14133   */
14134  constructor(parameters) {
14135    super();
14136    this.isMeshToonNodeMaterial = true;
14137    this.lights = true;
14138    this.setDefaultValues(_defaultValues$4);
14139    this.setValues(parameters);
14140  }
14141  /**
14142   * Setups the lighting model.
14143   *
14144   * @return {ToonLightingModel} The lighting model.
14145   */
14146  setupLightingModel() {
14147    return new ToonLightingModel();
14148  }
14149};
14150var matcapUV = /* @__PURE__ */ Fn(() => {
14151  const x = vec3(positionViewDirection.z, 0, positionViewDirection.x.negate()).normalize();
14152  const y = positionViewDirection.cross(x);
14153  return vec2(x.dot(normalView), y.dot(normalView)).mul(0.495).add(0.5);
14154}).once(["NORMAL", "VERTEX"])().toVar("matcapUV");
14155var _defaultValues$3 = /* @__PURE__ */ new MeshMatcapMaterial();
14156var MeshMatcapNodeMaterial = class extends NodeMaterial {
14157  static get type() {
14158    return "MeshMatcapNodeMaterial";
14159  }
14160  /**
14161   * Constructs a new mesh normal node material.
14162   *
14163   * @param {Object} [parameters] - The configuration parameter.
14164   */
14165  constructor(parameters) {
14166    super();
14167    this.isMeshMatcapNodeMaterial = true;
14168    this.setDefaultValues(_defaultValues$3);
14169    this.setValues(parameters);
14170  }
14171  /**
14172   * Setups the matcap specific node variables.
14173   *
14174   * @param {NodeBuilder} builder - The current node builder.
14175   */
14176  setupVariants(builder) {
14177    const uv3 = matcapUV;
14178    let matcapColor;
14179    if (builder.material.matcap) {
14180      matcapColor = materialReference("matcap", "texture").context({ getUV: () => uv3 });
14181    } else {
14182      matcapColor = vec3(mix(0.2, 0.8, uv3.y));
14183    }
14184    diffuseColor.rgb.mulAssign(matcapColor.rgb);
14185  }
14186};
14187var RotateNode = class extends TempNode {
14188  static get type() {
14189    return "RotateNode";
14190  }
14191  /**
14192   * Constructs a new rotate node.
14193   *
14194   * @param {Node} positionNode - The position node.
14195   * @param {Node} rotationNode - Represents the rotation that is applied to the position node. Depending
14196   * on whether the position data are 2D or 3D, the rotation is expressed a single float value or an Euler value.
14197   */
14198  constructor(positionNode, rotationNode) {
14199    super();
14200    this.positionNode = positionNode;
14201    this.rotationNode = rotationNode;
14202  }
14203  /**
14204   * The type of the {@link RotateNode#positionNode} defines the node's type.
14205   *
14206   * @param {NodeBuilder} builder - The current node builder.
14207   * @return {string} The node's type.
14208   */
14209  generateNodeType(builder) {
14210    return this.positionNode.getNodeType(builder);
14211  }
14212  setup(builder) {
14213    const { rotationNode, positionNode } = this;
14214    const nodeType = this.getNodeType(builder);
14215    if (nodeType === "vec2") {
14216      const cosAngle = rotationNode.cos();
14217      const sinAngle = rotationNode.sin();
14218      const rotationMatrix = mat2(
14219        cosAngle,
14220        sinAngle,
14221        sinAngle.negate(),
14222        cosAngle
14223      );
14224      return rotationMatrix.mul(positionNode);
14225    } else {
14226      const rotation = rotationNode;
14227      const rotationXMatrix = mat4(vec4(1, 0, 0, 0), vec4(0, cos(rotation.x), sin(rotation.x).negate(), 0), vec4(0, sin(rotation.x), cos(rotation.x), 0), vec4(0, 0, 0, 1));
14228      const rotationYMatrix = mat4(vec4(cos(rotation.y), 0, sin(rotation.y), 0), vec4(0, 1, 0, 0), vec4(sin(rotation.y).negate(), 0, cos(rotation.y), 0), vec4(0, 0, 0, 1));
14229      const rotationZMatrix = mat4(vec4(cos(rotation.z), sin(rotation.z).negate(), 0, 0), vec4(sin(rotation.z), cos(rotation.z), 0, 0), vec4(0, 0, 1, 0), vec4(0, 0, 0, 1));
14230      return rotationXMatrix.mul(rotationYMatrix).mul(rotationZMatrix).mul(vec4(positionNode, 1)).xyz;
14231    }
14232  }
14233};
14234var rotate = /* @__PURE__ */ nodeProxy(RotateNode).setParameterLength(2);
14235var _defaultValues$2 = /* @__PURE__ */ new SpriteMaterial();
14236var SpriteNodeMaterial = class extends NodeMaterial {
14237  static get type() {
14238    return "SpriteNodeMaterial";
14239  }
14240  /**
14241   * Constructs a new sprite node material.
14242   *
14243   * @param {Object} [parameters] - The configuration parameter.
14244   */
14245  constructor(parameters) {
14246    super();
14247    this.isSpriteNodeMaterial = true;
14248    this._useSizeAttenuation = true;
14249    this.positionNode = null;
14250    this.rotationNode = null;
14251    this.scaleNode = null;
14252    this.transparent = true;
14253    this.setDefaultValues(_defaultValues$2);
14254    this.setValues(parameters);
14255  }
14256  /**
14257   * Setups the position node in view space. This method implements
14258   * the sprite specific vertex shader.
14259   *
14260   * @param {NodeBuilder} builder - The current node builder.
14261   * @return {Node<vec3>} The position in view space.
14262   */
14263  setupPositionView(builder) {
14264    const { object, camera } = builder;
14265    const { positionNode, rotationNode, scaleNode, sizeAttenuation } = this;
14266    const mvPosition = modelViewMatrix.mul(vec3(positionNode || 0));
14267    let scale2 = vec2(modelWorldMatrix[0].xyz.length(), modelWorldMatrix[1].xyz.length());
14268    if (scaleNode !== null) {
14269      scale2 = scale2.mul(vec2(scaleNode));
14270    }
14271    if (camera.isPerspectiveCamera && sizeAttenuation === false) {
14272      scale2 = scale2.mul(mvPosition.z.negate());
14273    }
14274    let alignedPosition = positionGeometry.xy;
14275    if (object.center && object.center.isVector2 === true) {
14276      const center = reference$1("center", "vec2", object);
14277      alignedPosition = alignedPosition.sub(center.sub(0.5));
14278    }
14279    alignedPosition = alignedPosition.mul(scale2);
14280    const rotation = float(rotationNode || materialRotation);
14281    const rotatedPosition = rotate(alignedPosition, rotation);
14282    return vec4(mvPosition.xy.add(rotatedPosition), mvPosition.zw);
14283  }
14284  copy(source) {
14285    this.positionNode = source.positionNode;
14286    this.rotationNode = source.rotationNode;
14287    this.scaleNode = source.scaleNode;
14288    return super.copy(source);
14289  }
14290  /**
14291   * Whether to use size attenuation or not.
14292   *
14293   * @type {boolean}
14294   * @default true
14295   */
14296  get sizeAttenuation() {
14297    return this._useSizeAttenuation;
14298  }
14299  set sizeAttenuation(value) {
14300    if (this._useSizeAttenuation !== value) {
14301      this._useSizeAttenuation = value;
14302      this.needsUpdate = true;
14303    }
14304  }
14305};
14306var _defaultValues$1 = /* @__PURE__ */ new PointsMaterial();
14307var _size$4 = /* @__PURE__ */ new Vector2();
14308var PointsNodeMaterial = class extends SpriteNodeMaterial {
14309  static get type() {
14310    return "PointsNodeMaterial";
14311  }
14312  /**
14313   * Constructs a new points node material.
14314   *
14315   * @param {Object} [parameters] - The configuration parameter.
14316   */
14317  constructor(parameters) {
14318    super();
14319    this.sizeNode = null;
14320    this.isPointsNodeMaterial = true;
14321    this.setDefaultValues(_defaultValues$1);
14322    this.setValues(parameters);
14323  }
14324  setupPositionView() {
14325    const { positionNode } = this;
14326    return modelViewMatrix.mul(vec3(positionNode || positionLocal)).xyz;
14327  }
14328  setupVertexSprite(builder) {
14329    const { material, camera } = builder;
14330    const { rotationNode, scaleNode, sizeNode, sizeAttenuation } = this;
14331    let mvp = super.setupVertex(builder);
14332    if (material.isNodeMaterial !== true) {
14333      return mvp;
14334    }
14335    let pointSize = sizeNode !== null ? vec2(sizeNode) : materialPointSize;
14336    pointSize = pointSize.mul(screenDPR);
14337    if (camera.isPerspectiveCamera && sizeAttenuation === true) {
14338      pointSize = pointSize.mul(scale.div(positionView.z.negate()));
14339    }
14340    if (scaleNode && scaleNode.isNode) {
14341      pointSize = pointSize.mul(vec2(scaleNode));
14342    }
14343    let offset3 = positionGeometry.xy;
14344    if (rotationNode && rotationNode.isNode) {
14345      const rotation = float(rotationNode);
14346      offset3 = rotate(offset3, rotation);
14347    }
14348    offset3 = offset3.mul(pointSize);
14349    offset3 = offset3.div(viewportSize.div(2));
14350    offset3 = offset3.mul(mvp.w);
14351    mvp = mvp.add(vec4(offset3, 0, 0));
14352    return mvp;
14353  }
14354  setupVertex(builder) {
14355    if (builder.object.isPoints) {
14356      return super.setupVertex(builder);
14357    } else {
14358      return this.setupVertexSprite(builder);
14359    }
14360  }
14361  /**
14362   * Whether alpha to coverage should be used or not.
14363   *
14364   * @type {boolean}
14365   * @default true
14366   */
14367  get alphaToCoverage() {
14368    return this._useAlphaToCoverage;
14369  }
14370  set alphaToCoverage(value) {
14371    if (this._useAlphaToCoverage !== value) {
14372      this._useAlphaToCoverage = value;
14373      this.needsUpdate = true;
14374    }
14375  }
14376};
14377var scale = /* @__PURE__ */ uniform(1).onFrameUpdate(function({ renderer }) {
14378  const size3 = renderer.getSize(_size$4);
14379  this.value = 0.5 * size3.y;
14380});
14381var ShadowMaskModel = class extends LightingModel {
14382  /**
14383   * Constructs a new shadow mask model.
14384   */
14385  constructor() {
14386    super();
14387    this.shadowNode = float(1).toVar("shadowMask");
14388  }
14389  /**
14390   * Only used to save the shadow mask.
14391   *
14392   * @param {Object} input - The input data.
14393   */
14394  direct({ lightNode }) {
14395    if (lightNode.shadowNode !== null) {
14396      this.shadowNode.mulAssign(lightNode.shadowNode);
14397    }
14398  }
14399  /**
14400   * Uses the shadow mask to produce the final color.
14401   *
14402   * @param {NodeBuilder} builder - The current node builder.
14403   */
14404  finish({ context: context3 }) {
14405    diffuseColor.a.mulAssign(this.shadowNode.oneMinus());
14406    context3.outgoingLight.rgb.assign(diffuseColor.rgb);
14407  }
14408};
14409var _defaultValues = /* @__PURE__ */ new ShadowMaterial();
14410var ShadowNodeMaterial = class extends NodeMaterial {
14411  static get type() {
14412    return "ShadowNodeMaterial";
14413  }
14414  /**
14415   * Constructs a new shadow node material.
14416   *
14417   * @param {Object} [parameters] - The configuration parameter.
14418   */
14419  constructor(parameters) {
14420    super();
14421    this.isShadowNodeMaterial = true;
14422    this.lights = true;
14423    this.transparent = true;
14424    this.setDefaultValues(_defaultValues);
14425    this.setValues(parameters);
14426  }
14427  /**
14428   * Setups the lighting model.
14429   *
14430   * @return {ShadowMaskModel} The lighting model.
14431   */
14432  setupLightingModel() {
14433    return new ShadowMaskModel();
14434  }
14435};
14436var scatteringDensity = property("vec3");
14437var linearDepthRay = property("vec3");
14438var outgoingRayLight = property("vec3");
14439var Animation = class {
14440  /**
14441   * Constructs a new animation loop management component.
14442   *
14443   * @param {Renderer} renderer - A reference to the main renderer.
14444   * @param {NodeManager} nodes - Renderer component for managing nodes related logic.
14445   * @param {Info} info - Renderer component for managing metrics and monitoring data.
14446   */
14447  constructor(renderer, nodes, info) {
14448    this.renderer = renderer;
14449    this.nodes = nodes;
14450    this.info = info;
14451    this._context = typeof self !== "undefined" ? self : null;
14452    this._animationLoop = null;
14453    this._requestId = null;
14454  }
14455  /**
14456   * Starts the internal animation loop.
14457   */
14458  start() {
14459    const update = (time3, xrFrame) => {
14460      this._requestId = this._context.requestAnimationFrame(update);
14461      if (this.info.autoReset === true) this.info.reset();
14462      this.nodes.nodeFrame.update();
14463      this.info.frame = this.nodes.nodeFrame.frameId;
14464      this.renderer._inspector.begin();
14465      if (this._animationLoop !== null) this._animationLoop(time3, xrFrame);
14466      this.renderer._inspector.finish();
14467    };
14468    update();
14469  }
14470  /**
14471   * Stops the internal animation loop.
14472   */
14473  stop() {
14474    if (this._context !== null) this._context.cancelAnimationFrame(this._requestId);
14475    this._requestId = null;
14476  }
14477  /**
14478   * Returns the user-level animation loop.
14479   *
14480   * @return {?Function} The animation loop.
14481   */
14482  getAnimationLoop() {
14483    return this._animationLoop;
14484  }
14485  /**
14486   * Defines the user-level animation loop.
14487   *
14488   * @param {?Function} callback - The animation loop.
14489   */
14490  setAnimationLoop(callback) {
14491    this._animationLoop = callback;
14492  }
14493  /**
14494   * Returns the animation context.
14495   *
14496   * @return {Window|XRSession} The animation context.
14497   */
14498  getContext() {
14499    return this._context;
14500  }
14501  /**
14502   * Defines the context in which `requestAnimationFrame()` is executed.
14503   *
14504   * @param {Window|XRSession} context - The context to set.
14505   */
14506  setContext(context3) {
14507    this._context = context3;
14508  }
14509  /**
14510   * Frees all internal resources and stops the animation loop.
14511   */
14512  dispose() {
14513    this.stop();
14514  }
14515};
14516var ChainMap = class {
14517  /**
14518   * Constructs a new Chain Map.
14519   */
14520  constructor() {
14521    this.weakMaps = {};
14522  }
14523  /**
14524   * Returns the Weak Map for the given keys.
14525   *
14526   * @param {Array<Object>} keys - List of keys.
14527   * @return {WeakMap} The weak map.
14528   */
14529  _getWeakMap(keys5) {
14530    const length3 = keys5.length;
14531    let weakMap = this.weakMaps[length3];
14532    if (weakMap === void 0) {
14533      weakMap = /* @__PURE__ */ new WeakMap();
14534      this.weakMaps[length3] = weakMap;
14535    }
14536    return weakMap;
14537  }
14538  /**
14539   * Returns the value for the given array of keys.
14540   *
14541   * @param {Array<Object>} keys - List of keys.
14542   * @return {any} The value. Returns `undefined` if no value was found.
14543   */
14544  get(keys5) {
14545    let map = this._getWeakMap(keys5);
14546    for (let i = 0; i < keys5.length - 1; i++) {
14547      map = map.get(keys5[i]);
14548      if (map === void 0) return void 0;
14549    }
14550    return map.get(keys5[keys5.length - 1]);
14551  }
14552  /**
14553   * Sets the value for the given keys.
14554   *
14555   * @param {Array<Object>} keys - List of keys.
14556   * @param {any} value - The value to set.
14557   * @return {ChainMap} A reference to this Chain Map.
14558   */
14559  set(keys5, value) {
14560    let map = this._getWeakMap(keys5);
14561    for (let i = 0; i < keys5.length - 1; i++) {
14562      const key = keys5[i];
14563      if (map.has(key) === false) map.set(key, /* @__PURE__ */ new WeakMap());
14564      map = map.get(key);
14565    }
14566    map.set(keys5[keys5.length - 1], value);
14567    return this;
14568  }
14569  /**
14570   * Deletes a value for the given keys.
14571   *
14572   * @param {Array<Object>} keys - The keys.
14573   * @return {boolean} Returns `true` if the value has been removed successfully and `false` if the value has not be found.
14574   */
14575  delete(keys5) {
14576    let map = this._getWeakMap(keys5);
14577    for (let i = 0; i < keys5.length - 1; i++) {
14578      map = map.get(keys5[i]);
14579      if (map === void 0) return false;
14580    }
14581    return map.delete(keys5[keys5.length - 1]);
14582  }
14583};
14584var _id$a = 0;
14585function getKeys(obj) {
14586  const keys5 = Object.keys(obj);
14587  let proto2 = Object.getPrototypeOf(obj);
14588  while (proto2) {
14589    const descriptors = Object.getOwnPropertyDescriptors(proto2);
14590    for (const key in descriptors) {
14591      if (descriptors[key] !== void 0) {
14592        const descriptor = descriptors[key];
14593        if (descriptor && typeof descriptor.get === "function") {
14594          keys5.push(key);
14595        }
14596      }
14597    }
14598    proto2 = Object.getPrototypeOf(proto2);
14599  }
14600  return keys5;
14601}
14602var RenderObject = class {
14603  /**
14604   * Constructs a new render object.
14605   *
14606   * @param {NodeManager} nodes - Renderer component for managing nodes related logic.
14607   * @param {Geometries} geometries - Renderer component for managing geometries.
14608   * @param {Renderer} renderer - The renderer.
14609   * @param {Object3D} object - The 3D object.
14610   * @param {Material} material - The 3D object's material.
14611   * @param {Scene} scene - The scene the 3D object belongs to.
14612   * @param {Camera} camera - The camera the object should be rendered with.
14613   * @param {LightsNode} lightsNode - The lights node.
14614   * @param {RenderContext} renderContext - The render context.
14615   * @param {ClippingContext} clippingContext - The clipping context.
14616   */
14617  constructor(nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext) {
14618    this.id = _id$a++;
14619    this._nodes = nodes;
14620    this._geometries = geometries;
14621    this.renderer = renderer;
14622    this.object = object;
14623    this.material = material;
14624    this.scene = scene;
14625    this.camera = camera;
14626    this.lightsNode = lightsNode;
14627    this.context = renderContext;
14628    this.geometry = object.geometry;
14629    this.version = material.version;
14630    this.drawRange = null;
14631    this.attributes = null;
14632    this.attributesId = null;
14633    this.pipeline = null;
14634    this.group = null;
14635    this.vertexBuffers = null;
14636    this.drawParams = null;
14637    this.bundle = null;
14638    this.clippingContext = clippingContext;
14639    this.clippingContextCacheKey = clippingContext !== null ? clippingContext.cacheKey : "";
14640    this.initialNodesCacheKey = this.getDynamicCacheKey();
14641    this.initialCacheKey = this.getCacheKey();
14642    this._nodeBuilderState = null;
14643    this._bindings = null;
14644    this._monitor = null;
14645    this.onDispose = null;
14646    this.isRenderObject = true;
14647    this.onMaterialDispose = () => {
14648      this.dispose();
14649    };
14650    this.onGeometryDispose = () => {
14651      this.attributes = null;
14652      this.attributesId = null;
14653    };
14654    this.material.addEventListener("dispose", this.onMaterialDispose);
14655    this.geometry.addEventListener("dispose", this.onGeometryDispose);
14656  }
14657  /**
14658   * Updates the clipping context.
14659   *
14660   * @param {ClippingContext} context - The clipping context to set.
14661   */
14662  updateClipping(context3) {
14663    this.clippingContext = context3;
14664  }
14665  /**
14666   * Whether the clipping requires an update or not.
14667   *
14668   * @type {boolean}
14669   * @readonly
14670   */
14671  get clippingNeedsUpdate() {
14672    if (this.clippingContext === null || this.clippingContext.cacheKey === this.clippingContextCacheKey) return false;
14673    this.clippingContextCacheKey = this.clippingContext.cacheKey;
14674    return true;
14675  }
14676  /**
14677   * The number of clipping planes defined in context of hardware clipping.
14678   *
14679   * @type {number}
14680   * @readonly
14681   */
14682  get hardwareClippingPlanes() {
14683    return this.material.hardwareClipping === true ? this.clippingContext.unionClippingCount : 0;
14684  }
14685  /**
14686   * Returns the node builder state of this render object.
14687   *
14688   * @return {NodeBuilderState} The node builder state.
14689   */
14690  getNodeBuilderState() {
14691    return this._nodeBuilderState || (this._nodeBuilderState = this._nodes.getForRender(this));
14692  }
14693  /**
14694   * Returns the node material observer of this render object.
14695   *
14696   * @return {NodeMaterialObserver} The node material observer.
14697   */
14698  getMonitor() {
14699    return this._monitor || (this._monitor = this.getNodeBuilderState().observer);
14700  }
14701  /**
14702   * Returns an array of bind groups of this render object.
14703   *
14704   * @return {Array<BindGroup>} The bindings.
14705   */
14706  getBindings() {
14707    return this._bindings || (this._bindings = this.getNodeBuilderState().createBindings());
14708  }
14709  /**
14710   * Returns a binding group by group name of this render object.
14711   *
14712   * @param {string} name - The name of the binding group.
14713   * @return {?BindGroup} The bindings.
14714   */
14715  getBindingGroup(name) {
14716    for (const bindingGroup of this.getBindings()) {
14717      if (bindingGroup.name === name) {
14718        return bindingGroup;
14719      }
14720    }
14721  }
14722  /**
14723   * Returns the index of the render object's geometry.
14724   *
14725   * @return {?BufferAttribute} The index. Returns `null` for non-indexed geometries.
14726   */
14727  getIndex() {
14728    return this._geometries.getIndex(this);
14729  }
14730  /**
14731   * Returns the indirect buffer attribute.
14732   *
14733   * @return {?BufferAttribute} The indirect attribute. `null` if no indirect drawing is used.
14734   */
14735  getIndirect() {
14736    return this._geometries.getIndirect(this);
14737  }
14738  /**
14739   * Returns the byte offset into the indirect attribute buffer.
14740   *
14741   * @return {number|Array<number>} The byte offset into the indirect attribute buffer.
14742   */
14743  getIndirectOffset() {
14744    return this._geometries.getIndirectOffset(this);
14745  }
14746  /**
14747   * Returns an array that acts as a key for identifying the render object in a chain map.
14748   *
14749   * @return {Array<Object>} An array with object references.
14750   */
14751  getChainArray() {
14752    return [this.object, this.material, this.context, this.lightsNode];
14753  }
14754  /**
14755   * This method is used when the geometry of a 3D object has been exchanged and the
14756   * respective render object now requires an update.
14757   *
14758   * @param {BufferGeometry} geometry - The geometry to set.
14759   */
14760  setGeometry(geometry) {
14761    this.geometry = geometry;
14762    this.attributes = null;
14763    this.attributesId = null;
14764  }
14765  /**
14766   * Returns the buffer attributes of the render object. The returned array holds
14767   * attribute definitions on geometry and node level.
14768   *
14769   * @return {Array<BufferAttribute>} An array with buffer attributes.
14770   */
14771  getAttributes() {
14772    if (this.attributes !== null) return this.attributes;
14773    const nodeAttributes = this.getNodeBuilderState().nodeAttributes;
14774    const geometry = this.geometry;
14775    const attributes = [];
14776    const vertexBuffers = /* @__PURE__ */ new Set();
14777    const attributesId = {};
14778    for (const nodeAttribute of nodeAttributes) {
14779      let attribute3;
14780      if (nodeAttribute.node && nodeAttribute.node.attribute) {
14781        attribute3 = nodeAttribute.node.attribute;
14782      } else {
14783        attribute3 = geometry.getAttribute(nodeAttribute.name);
14784        attributesId[nodeAttribute.name] = attribute3.id;
14785      }
14786      if (attribute3 === void 0) continue;
14787      attributes.push(attribute3);
14788      const bufferAttribute3 = attribute3.isInterleavedBufferAttribute ? attribute3.data : attribute3;
14789      vertexBuffers.add(bufferAttribute3);
14790    }
14791    this.attributes = attributes;
14792    this.attributesId = attributesId;
14793    this.vertexBuffers = Array.from(vertexBuffers.values());
14794    return attributes;
14795  }
14796  /**
14797   * Returns the vertex buffers of the render object.
14798   *
14799   * @return {Array<BufferAttribute|InterleavedBuffer>} An array with buffer attribute or interleaved buffers.
14800   */
14801  getVertexBuffers() {
14802    if (this.vertexBuffers === null) this.getAttributes();
14803    return this.vertexBuffers;
14804  }
14805  /**
14806   * Returns the draw parameters for the render object.
14807   *
14808   * @return {?{vertexCount: number, firstVertex: number, instanceCount: number, firstInstance: number}} The draw parameters.
14809   */
14810  getDrawParameters() {
14811    const { object, material, geometry, group, drawRange } = this;
14812    const drawParams = this.drawParams || (this.drawParams = {
14813      vertexCount: 0,
14814      firstVertex: 0,
14815      instanceCount: 0,
14816      firstInstance: 0
14817    });
14818    const index = this.getIndex();
14819    const hasIndex = index !== null;
14820    let instanceCount = 1;
14821    if (geometry.isInstancedBufferGeometry === true) {
14822      instanceCount = geometry.instanceCount;
14823    } else if (object.count !== void 0) {
14824      instanceCount = Math.max(0, object.count);
14825    }
14826    if (instanceCount === 0) return null;
14827    drawParams.instanceCount = instanceCount;
14828    if (object.isBatchedMesh === true) return drawParams;
14829    let rangeFactor = 1;
14830    if (material.wireframe === true && !object.isPoints && !object.isLineSegments && !object.isLine && !object.isLineLoop) {
14831      rangeFactor = 2;
14832    }
14833    let firstVertex = drawRange.start * rangeFactor;
14834    let lastVertex = (drawRange.start + drawRange.count) * rangeFactor;
14835    if (group !== null) {
14836      firstVertex = Math.max(firstVertex, group.start * rangeFactor);
14837      lastVertex = Math.min(lastVertex, (group.start + group.count) * rangeFactor);
14838    }
14839    const position = geometry.attributes.position;
14840    let itemCount = Infinity;
14841    if (hasIndex) {
14842      itemCount = index.count;
14843    } else if (position !== void 0 && position !== null) {
14844      itemCount = position.count;
14845    }
14846    firstVertex = Math.max(firstVertex, 0);
14847    lastVertex = Math.min(lastVertex, itemCount);
14848    const count = lastVertex - firstVertex;
14849    if (count < 0 || count === Infinity) return null;
14850    drawParams.vertexCount = count;
14851    drawParams.firstVertex = firstVertex;
14852    return drawParams;
14853  }
14854  /**
14855   * Returns the render object's geometry cache key.
14856   *
14857   * The geometry cache key is part of the material cache key.
14858   *
14859   * @return {string} The geometry cache key.
14860   */
14861  getGeometryCacheKey() {
14862    const { geometry } = this;
14863    let cacheKey = "";
14864    for (const name of Object.keys(geometry.attributes).sort()) {
14865      const attribute3 = geometry.attributes[name];
14866      cacheKey += name + ",";
14867      if (attribute3.data) cacheKey += attribute3.data.stride + ",";
14868      if (attribute3.offset) cacheKey += attribute3.offset + ",";
14869      if (attribute3.itemSize) cacheKey += attribute3.itemSize + ",";
14870      if (attribute3.normalized) cacheKey += "n,";
14871    }
14872    for (const name of Object.keys(geometry.morphAttributes).sort()) {
14873      const targets = geometry.morphAttributes[name];
14874      cacheKey += "morph-" + name + ",";
14875      for (let i = 0, l = targets.length; i < l; i++) {
14876        const attribute3 = targets[i];
14877        cacheKey += attribute3.id + ",";
14878      }
14879    }
14880    if (geometry.index) {
14881      cacheKey += "index,";
14882    }
14883    return cacheKey;
14884  }
14885  /**
14886   * Returns the render object's material cache key.
14887   *
14888   * The material cache key is part of the render object cache key.
14889   *
14890   * @return {number} The material cache key.
14891   */
14892  getMaterialCacheKey() {
14893    const { object, material, renderer } = this;
14894    let cacheKey = material.customProgramCacheKey();
14895    for (const property3 of getKeys(material)) {
14896      if (/^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test(property3)) continue;
14897      const value = material[property3];
14898      let valueKey;
14899      if (value !== null) {
14900        const type = typeof value;
14901        if (type === "number") {
14902          valueKey = value !== 0 ? "1" : "0";
14903        } else if (type === "object") {
14904          valueKey = "{";
14905          if (value.isTexture) {
14906            valueKey += value.mapping;
14907            if (renderer.backend.isWebGPUBackend === true) {
14908              valueKey += value.magFilter;
14909              valueKey += value.minFilter;
14910              valueKey += value.wrapS;
14911              valueKey += value.wrapT;
14912              valueKey += value.wrapR;
14913            }
14914          }
14915          valueKey += "}";
14916        } else {
14917          valueKey = String(value);
14918        }
14919      } else {
14920        valueKey = String(value);
14921      }
14922      cacheKey += /*property + ':' +*/
14923      valueKey + ",";
14924    }
14925    cacheKey += this.clippingContextCacheKey + ",";
14926    if (object.geometry) {
14927      cacheKey += this.getGeometryCacheKey();
14928    }
14929    if (object.skeleton) {
14930      cacheKey += object.skeleton.bones.length + ",";
14931    }
14932    if (object.isBatchedMesh) {
14933      cacheKey += object._matricesTexture.uuid + ",";
14934      if (object._colorsTexture !== null) {
14935        cacheKey += object._colorsTexture.uuid + ",";
14936      }
14937    }
14938    if (object.isInstancedMesh || object.count > 1 || Array.isArray(object.morphTargetInfluences)) {
14939      cacheKey += object.uuid + ",";
14940    }
14941    cacheKey += this.context.id + ",";
14942    cacheKey += object.receiveShadow + ",";
14943    return hashString(cacheKey);
14944  }
14945  /**
14946   * Whether the geometry requires an update or not.
14947   *
14948   * @type {boolean}
14949   * @readonly
14950   */
14951  get needsGeometryUpdate() {
14952    if (this.geometry.id !== this.object.geometry.id) return true;
14953    if (this.attributes !== null) {
14954      const attributesId = this.attributesId;
14955      for (const name in attributesId) {
14956        const attribute3 = this.geometry.getAttribute(name);
14957        if (attribute3 === void 0 || attributesId[name] !== attribute3.id) {
14958          return true;
14959        }
14960      }
14961    }
14962    return false;
14963  }
14964  /**
14965   * Whether the render object requires an update or not.
14966   *
14967   * Note: There are two distinct places where render objects are checked for an update.
14968   *
14969   * 1. In `RenderObjects.get()` which is executed when the render object is request. This
14970   * method checks the `needsUpdate` flag and recreates the render object if necessary.
14971   * 2. In `Renderer._renderObjectDirect()` right after getting the render object via
14972   * `RenderObjects.get()`. The render object's NodeMaterialObserver is then used to detect
14973   * a need for a refresh due to material, geometry or object related value changes.
14974   *
14975   * TODO: Investigate if it's possible to merge both steps so there is only a single place
14976   * that performs the 'needsUpdate' check.
14977   *
14978   * @type {boolean}
14979   * @readonly
14980   */
14981  get needsUpdate() {
14982    return (
14983      /*this.object.static !== true &&*/
14984      this.initialNodesCacheKey !== this.getDynamicCacheKey() || this.clippingNeedsUpdate
14985    );
14986  }
14987  /**
14988   * Returns the dynamic cache key which represents a key that is computed per draw command.
14989   *
14990   * @return {number} The cache key.
14991   */
14992  getDynamicCacheKey() {
14993    let cacheKey = 0;
14994    if (this.material.isShadowPassMaterial !== true) {
14995      cacheKey = this._nodes.getCacheKey(this.scene, this.lightsNode);
14996    }
14997    if (this.camera.isArrayCamera) {
14998      cacheKey = hash$1(cacheKey, this.camera.cameras.length);
14999    }
15000    if (this.object.receiveShadow) {
15001      cacheKey = hash$1(cacheKey, 1);
15002    }
15003    cacheKey = hash$1(cacheKey, this.renderer.contextNode.id, this.renderer.contextNode.version);
15004    return cacheKey;
15005  }
15006  /**
15007   * Returns the render object's cache key.
15008   *
15009   * @return {number} The cache key.
15010   */
15011  getCacheKey() {
15012    return this.getMaterialCacheKey() + this.getDynamicCacheKey();
15013  }
15014  /**
15015   * Frees internal resources.
15016   */
15017  dispose() {
15018    this.material.removeEventListener("dispose", this.onMaterialDispose);
15019    this.geometry.removeEventListener("dispose", this.onGeometryDispose);
15020    this.onDispose();
15021  }
15022};
15023var _chainKeys$3 = [];
15024var RenderObjects = class {
15025  /**
15026   * Constructs a new render object management component.
15027   *
15028   * @param {Renderer} renderer - The renderer.
15029   * @param {NodeManager} nodes - Renderer component for managing nodes related logic.
15030   * @param {Geometries} geometries - Renderer component for managing geometries.
15031   * @param {Pipelines} pipelines - Renderer component for managing pipelines.
15032   * @param {Bindings} bindings - Renderer component for managing bindings.
15033   * @param {Info} info - Renderer component for managing metrics and monitoring data.
15034   */
15035  constructor(renderer, nodes, geometries, pipelines, bindings, info) {
15036    this.renderer = renderer;
15037    this.nodes = nodes;
15038    this.geometries = geometries;
15039    this.pipelines = pipelines;
15040    this.bindings = bindings;
15041    this.info = info;
15042    this.chainMaps = {};
15043  }
15044  /**
15045   * Returns a render object for the given object and state data.
15046   *
15047   * @param {Object3D} object - The 3D object.
15048   * @param {Material} material - The 3D object's material.
15049   * @param {Scene} scene - The scene the 3D object belongs to.
15050   * @param {Camera} camera - The camera the 3D object should be rendered with.
15051   * @param {LightsNode} lightsNode - The lights node.
15052   * @param {RenderContext} renderContext - The render context.
15053   * @param {ClippingContext} clippingContext - The clipping context.
15054   * @param {string} [passId] - An optional ID for identifying the pass.
15055   * @return {RenderObject} The render object.
15056   */
15057  get(object, material, scene, camera, lightsNode, renderContext, clippingContext, passId) {
15058    const chainMap = this.getChainMap(passId);
15059    _chainKeys$3[0] = object;
15060    _chainKeys$3[1] = material;
15061    _chainKeys$3[2] = renderContext;
15062    _chainKeys$3[3] = lightsNode;
15063    let renderObject = chainMap.get(_chainKeys$3);
15064    if (renderObject === void 0) {
15065      renderObject = this.createRenderObject(this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId);
15066      chainMap.set(_chainKeys$3, renderObject);
15067    } else {
15068      renderObject.camera = camera;
15069      renderObject.updateClipping(clippingContext);
15070      if (renderObject.needsGeometryUpdate) {
15071        renderObject.setGeometry(object.geometry);
15072      }
15073      if (renderObject.version !== material.version || renderObject.needsUpdate) {
15074        if (renderObject.initialCacheKey !== renderObject.getCacheKey()) {
15075          renderObject.dispose();
15076          renderObject = this.get(object, material, scene, camera, lightsNode, renderContext, clippingContext, passId);
15077        } else {
15078          renderObject.version = material.version;
15079        }
15080      }
15081    }
15082    _chainKeys$3[0] = null;
15083    _chainKeys$3[1] = null;
15084    _chainKeys$3[2] = null;
15085    _chainKeys$3[3] = null;
15086    return renderObject;
15087  }
15088  /**
15089   * Returns a chain map for the given pass ID.
15090   *
15091   * @param {string} [passId='default'] - The pass ID.
15092   * @return {ChainMap} The chain map.
15093   */
15094  getChainMap(passId = "default") {
15095    return this.chainMaps[passId] || (this.chainMaps[passId] = new ChainMap());
15096  }
15097  /**
15098   * Frees internal resources.
15099   */
15100  dispose() {
15101    this.chainMaps = {};
15102  }
15103  /**
15104   * Factory method for creating render objects with the given list of parameters.
15105   *
15106   * @param {NodeManager} nodes - Renderer component for managing nodes related logic.
15107   * @param {Geometries} geometries - Renderer component for managing geometries.
15108   * @param {Renderer} renderer - The renderer.
15109   * @param {Object3D} object - The 3D object.
15110   * @param {Material} material - The object's material.
15111   * @param {Scene} scene - The scene the 3D object belongs to.
15112   * @param {Camera} camera - The camera the object should be rendered with.
15113   * @param {LightsNode} lightsNode - The lights node.
15114   * @param {RenderContext} renderContext - The render context.
15115   * @param {ClippingContext} clippingContext - The clipping context.
15116   * @param {string} [passId] - An optional ID for identifying the pass.
15117   * @return {RenderObject} The render object.
15118   */
15119  createRenderObject(nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId) {
15120    const chainMap = this.getChainMap(passId);
15121    const renderObject = new RenderObject(nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext);
15122    renderObject.onDispose = () => {
15123      this.pipelines.delete(renderObject);
15124      this.bindings.deleteForRender(renderObject);
15125      this.nodes.delete(renderObject);
15126      chainMap.delete(renderObject.getChainArray());
15127    };
15128    return renderObject;
15129  }
15130};
15131var DataMap = class {
15132  /**
15133   * Constructs a new data map.
15134   */
15135  constructor() {
15136    this.data = /* @__PURE__ */ new WeakMap();
15137  }
15138  /**
15139   * Returns the dictionary for the given object.
15140   *
15141   * @param {Object} object - The object.
15142   * @return {Object} The dictionary.
15143   */
15144  get(object) {
15145    let map = this.data.get(object);
15146    if (map === void 0) {
15147      map = {};
15148      this.data.set(object, map);
15149    }
15150    return map;
15151  }
15152  /**
15153   * Deletes the dictionary for the given object.
15154   *
15155   * @param {Object} object - The object.
15156   * @return {?Object} The deleted dictionary.
15157   */
15158  delete(object) {
15159    let map = null;
15160    if (this.data.has(object)) {
15161      map = this.data.get(object);
15162      this.data.delete(object);
15163    }
15164    return map;
15165  }
15166  /**
15167   * Returns `true` if the given object has a dictionary defined.
15168   *
15169   * @param {Object} object - The object to test.
15170   * @return {boolean} Whether a dictionary is defined or not.
15171   */
15172  has(object) {
15173    return this.data.has(object);
15174  }
15175  /**
15176   * Frees internal resources.
15177   */
15178  dispose() {
15179    this.data = /* @__PURE__ */ new WeakMap();
15180  }
15181};
15182var AttributeType = {
15183  VERTEX: 1,
15184  INDEX: 2,
15185  STORAGE: 3,
15186  INDIRECT: 4
15187};
15188var GPU_CHUNK_BYTES = 16;
15189var BlendColorFactor = 211;
15190var OneMinusBlendColorFactor = 212;
15191var Attributes = class extends DataMap {
15192  /**
15193   * Constructs a new attribute management component.
15194   *
15195   * @param {Backend} backend - The renderer's backend.
15196   * @param {Info} info - Renderer component for managing metrics and monitoring data.
15197   */
15198  constructor(backend, info) {
15199    super();
15200    this.backend = backend;
15201    this.info = info;
15202  }
15203  /**
15204   * Deletes the data for the given attribute.
15205   *
15206   * @param {BufferAttribute} attribute - The attribute.
15207   * @return {?Object} The deleted attribute data.
15208   */
15209  delete(attribute3) {
15210    const attributeData = super.delete(attribute3);
15211    if (attributeData !== null) {
15212      this.backend.destroyAttribute(attribute3);
15213      this.info.destroyAttribute(attribute3);
15214    }
15215    return attributeData;
15216  }
15217  /**
15218   * Updates the given attribute. This method creates attribute buffers
15219   * for new attributes and updates data for existing ones.
15220   *
15221   * @param {BufferAttribute} attribute - The attribute to update.
15222   * @param {number} type - The attribute type.
15223   */
15224  update(attribute3, type) {
15225    const data = this.get(attribute3);
15226    if (data.version === void 0) {
15227      if (type === AttributeType.VERTEX) {
15228        this.backend.createAttribute(attribute3);
15229        this.info.createAttribute(attribute3);
15230      } else if (type === AttributeType.INDEX) {
15231        this.backend.createIndexAttribute(attribute3);
15232        this.info.createIndexAttribute(attribute3);
15233      } else if (type === AttributeType.STORAGE) {
15234        this.backend.createStorageAttribute(attribute3);
15235        this.info.createStorageAttribute(attribute3);
15236      } else if (type === AttributeType.INDIRECT) {
15237        this.backend.createIndirectStorageAttribute(attribute3);
15238        this.info.createIndirectStorageAttribute(attribute3);
15239      }
15240      data.version = this._getBufferAttribute(attribute3).version;
15241    } else {
15242      const bufferAttribute3 = this._getBufferAttribute(attribute3);
15243      if (data.version < bufferAttribute3.version || bufferAttribute3.usage === DynamicDrawUsage) {
15244        this.backend.updateAttribute(attribute3);
15245        data.version = bufferAttribute3.version;
15246      }
15247    }
15248  }
15249  /**
15250   * Utility method for handling interleaved buffer attributes correctly.
15251   * To process them, their `InterleavedBuffer` is returned.
15252   *
15253   * @param {BufferAttribute} attribute - The attribute.
15254   * @return {BufferAttribute|InterleavedBuffer}
15255   */
15256  _getBufferAttribute(attribute3) {
15257    if (attribute3.isInterleavedBufferAttribute) attribute3 = attribute3.data;
15258    return attribute3;
15259  }
15260};
15261function getWireframeVersion(geometry) {
15262  return geometry.index !== null ? geometry.index.version : geometry.attributes.position.version;
15263}
15264function getWireframeId(geometry) {
15265  return geometry.index !== null ? geometry.index.id : geometry.attributes.position.id;
15266}
15267function getWireframeIndex(geometry) {
15268  const indices = [];
15269  const geometryIndex = geometry.index;
15270  const geometryPosition = geometry.attributes.position;
15271  if (geometryIndex !== null) {
15272    const array3 = geometryIndex.array;
15273    for (let i = 0, l = array3.length; i < l; i += 3) {
15274      const a = array3[i + 0];
15275      const b = array3[i + 1];
15276      const c = array3[i + 2];
15277      indices.push(a, b, b, c, c, a);
15278    }
15279  } else {
15280    const array3 = geometryPosition.array;
15281    for (let i = 0, l = array3.length / 3 - 1; i < l; i += 3) {
15282      const a = i + 0;
15283      const b = i + 1;
15284      const c = i + 2;
15285      indices.push(a, b, b, c, c, a);
15286    }
15287  }
15288  const attribute3 = new (geometryPosition.count >= 65535 ? Uint32BufferAttribute : Uint16BufferAttribute)(indices, 1);
15289  attribute3.version = getWireframeVersion(geometry);
15290  attribute3.__id = getWireframeId(geometry);
15291  return attribute3;
15292}
15293var Geometries = class extends DataMap {
15294  /**
15295   * Constructs a new geometry management component.
15296   *
15297   * @param {Attributes} attributes - Renderer component for managing attributes.
15298   * @param {Info} info - Renderer component for managing metrics and monitoring data.
15299   */
15300  constructor(attributes, info) {
15301    super();
15302    this.attributes = attributes;
15303    this.info = info;
15304    this.wireframes = /* @__PURE__ */ new WeakMap();
15305    this.attributeCall = /* @__PURE__ */ new WeakMap();
15306    this._geometryDisposeListeners = /* @__PURE__ */ new Map();
15307  }
15308  /**
15309   * Returns `true` if the given render object has an initialized geometry.
15310   *
15311   * @param {RenderObject} renderObject - The render object.
15312   * @return {boolean} Whether if the given render object has an initialized geometry or not.
15313   */
15314  has(renderObject) {
15315    const geometry = renderObject.geometry;
15316    return super.has(geometry) && this.get(geometry).initialized === true;
15317  }
15318  /**
15319   * Prepares the geometry of the given render object for rendering.
15320   *
15321   * @param {RenderObject} renderObject - The render object.
15322   */
15323  updateForRender(renderObject) {
15324    if (this.has(renderObject) === false) this.initGeometry(renderObject);
15325    this.updateAttributes(renderObject);
15326  }
15327  /**
15328   * Initializes the geometry of the given render object.
15329   *
15330   * @param {RenderObject} renderObject - The render object.
15331   */
15332  initGeometry(renderObject) {
15333    const geometry = renderObject.geometry;
15334    const geometryData = this.get(geometry);
15335    geometryData.initialized = true;
15336    this.info.memory.geometries++;
15337    const onDispose = () => {
15338      this.info.memory.geometries--;
15339      const index = geometry.index;
15340      const geometryAttributes = renderObject.getAttributes();
15341      if (index !== null) {
15342        this.attributes.delete(index);
15343      }
15344      for (const geometryAttribute of geometryAttributes) {
15345        this.attributes.delete(geometryAttribute);
15346      }
15347      const wireframeAttribute = this.wireframes.get(geometry);
15348      if (wireframeAttribute !== void 0) {
15349        this.attributes.delete(wireframeAttribute);
15350      }
15351      geometry.removeEventListener("dispose", onDispose);
15352      this._geometryDisposeListeners.delete(geometry);
15353    };
15354    geometry.addEventListener("dispose", onDispose);
15355    this._geometryDisposeListeners.set(geometry, onDispose);
15356  }
15357  /**
15358   * Updates the geometry attributes of the given render object.
15359   *
15360   * @param {RenderObject} renderObject - The render object.
15361   */
15362  updateAttributes(renderObject) {
15363    const attributes = renderObject.getAttributes();
15364    for (const attribute3 of attributes) {
15365      if (attribute3.isStorageBufferAttribute || attribute3.isStorageInstancedBufferAttribute) {
15366        this.updateAttribute(attribute3, AttributeType.STORAGE);
15367      } else {
15368        this.updateAttribute(attribute3, AttributeType.VERTEX);
15369      }
15370    }
15371    const index = this.getIndex(renderObject);
15372    if (index !== null) {
15373      this.updateAttribute(index, AttributeType.INDEX);
15374    }
15375    const indirect = renderObject.geometry.indirect;
15376    if (indirect !== null) {
15377      this.updateAttribute(indirect, AttributeType.INDIRECT);
15378    }
15379  }
15380  /**
15381   * Updates the given attribute.
15382   *
15383   * @param {BufferAttribute} attribute - The attribute to update.
15384   * @param {number} type - The attribute type.
15385   */
15386  updateAttribute(attribute3, type) {
15387    const callId = this.info.render.calls;
15388    if (!attribute3.isInterleavedBufferAttribute) {
15389      if (this.attributeCall.get(attribute3) !== callId) {
15390        this.attributes.update(attribute3, type);
15391        this.attributeCall.set(attribute3, callId);
15392      }
15393    } else {
15394      if (this.attributeCall.get(attribute3) === void 0) {
15395        this.attributes.update(attribute3, type);
15396        this.attributeCall.set(attribute3, callId);
15397      } else if (this.attributeCall.get(attribute3.data) !== callId) {
15398        this.attributes.update(attribute3, type);
15399        this.attributeCall.set(attribute3.data, callId);
15400        this.attributeCall.set(attribute3, callId);
15401      }
15402    }
15403  }
15404  /**
15405   * Returns the indirect buffer attribute of the given render object.
15406   *
15407   * @param {RenderObject} renderObject - The render object.
15408   * @return {?BufferAttribute} The indirect attribute. `null` if no indirect drawing is used.
15409   */
15410  getIndirect(renderObject) {
15411    return renderObject.geometry.indirect;
15412  }
15413  /**
15414   * Returns the byte offset into the indirect attribute buffer of the given render object.
15415   *
15416   * @param {RenderObject} renderObject - The render object.
15417   * @return {number} The byte offset into the indirect attribute buffer.
15418   */
15419  getIndirectOffset(renderObject) {
15420    return renderObject.geometry.indirectOffset;
15421  }
15422  /**
15423   * Returns the index of the given render object's geometry. This is implemented
15424   * in a method to return a wireframe index if necessary.
15425   *
15426   * @param {RenderObject} renderObject - The render object.
15427   * @return {?BufferAttribute} The index. Returns `null` for non-indexed geometries.
15428   */
15429  getIndex(renderObject) {
15430    const { geometry, material } = renderObject;
15431    let index = geometry.index;
15432    if (material.wireframe === true) {
15433      const wireframes = this.wireframes;
15434      let wireframeAttribute = wireframes.get(geometry);
15435      if (wireframeAttribute === void 0) {
15436        wireframeAttribute = getWireframeIndex(geometry);
15437        wireframes.set(geometry, wireframeAttribute);
15438      } else if (wireframeAttribute.version !== getWireframeVersion(geometry) || wireframeAttribute.__id !== getWireframeId(geometry)) {
15439        this.attributes.delete(wireframeAttribute);
15440        wireframeAttribute = getWireframeIndex(geometry);
15441        wireframes.set(geometry, wireframeAttribute);
15442      }
15443      index = wireframeAttribute;
15444    }
15445    return index;
15446  }
15447  dispose() {
15448    for (const [geometry, onDispose] of this._geometryDisposeListeners.entries()) {
15449      geometry.removeEventListener("dispose", onDispose);
15450    }
15451    this._geometryDisposeListeners.clear();
15452  }
15453};
15454var Info = class {
15455  /**
15456   * Constructs a new info component.
15457   */
15458  constructor() {
15459    this.autoReset = true;
15460    this.frame = 0;
15461    this.calls = 0;
15462    this.render = {
15463      calls: 0,
15464      frameCalls: 0,
15465      drawCalls: 0,
15466      triangles: 0,
15467      points: 0,
15468      lines: 0,
15469      timestamp: 0
15470    };
15471    this.compute = {
15472      calls: 0,
15473      frameCalls: 0,
15474      timestamp: 0
15475    };
15476    this.memory = {
15477      geometries: 0,
15478      textures: 0,
15479      attributes: 0,
15480      indexAttributes: 0,
15481      storageAttributes: 0,
15482      indirectStorageAttributes: 0,
15483      readbackBuffers: 0,
15484      programs: 0,
15485      renderTargets: 0,
15486      total: 0,
15487      texturesSize: 0,
15488      attributesSize: 0,
15489      indexAttributesSize: 0,
15490      storageAttributesSize: 0,
15491      indirectStorageAttributesSize: 0,
15492      readbackBuffersSize: 0,
15493      programsSize: 0
15494    };
15495    this.memoryMap = /* @__PURE__ */ new Map();
15496  }
15497  /**
15498   * This method should be executed per draw call and updates the corresponding metrics.
15499   *
15500   * @param {Object3D} object - The 3D object that is going to be rendered.
15501   * @param {number} count - The vertex or index count.
15502   * @param {number} instanceCount - The instance count.
15503   */
15504  update(object, count, instanceCount) {
15505    this.render.drawCalls++;
15506    if (object.isMesh || object.isSprite) {
15507      this.render.triangles += instanceCount * (count / 3);
15508    } else if (object.isPoints) {
15509      this.render.points += instanceCount * count;
15510    } else if (object.isLineSegments) {
15511      this.render.lines += instanceCount * (count / 2);
15512    } else if (object.isLine) {
15513      this.render.lines += instanceCount * (count - 1);
15514    } else {
15515      error("WebGPUInfo: Unknown object type.");
15516    }
15517  }
15518  /**
15519   * Resets frame related metrics.
15520   */
15521  reset() {
15522    this.render.drawCalls = 0;
15523    this.render.frameCalls = 0;
15524    this.compute.frameCalls = 0;
15525    this.render.triangles = 0;
15526    this.render.points = 0;
15527    this.render.lines = 0;
15528  }
15529  /**
15530   * Performs a complete reset of the object.
15531   */
15532  dispose() {
15533    this.reset();
15534    this.calls = 0;
15535    this.render.calls = 0;
15536    this.compute.calls = 0;
15537    this.render.timestamp = 0;
15538    this.compute.timestamp = 0;
15539    for (const prop in this.memory) {
15540      this.memory[prop] = 0;
15541    }
15542    this.memoryMap.clear();
15543  }
15544  /**
15545   * Tracks texture memory explicitly, updating counts and byte tracking.
15546   *
15547   * @param {Texture} texture
15548   */
15549  createTexture(texture3) {
15550    const size3 = this._getTextureMemorySize(texture3);
15551    this.memoryMap.set(texture3, size3);
15552    this.memory.textures++;
15553    this.memory.total += size3;
15554    this.memory.texturesSize += size3;
15555  }
15556  /**
15557   * Tracks texture memory explicitly, updating counts and byte tracking.
15558   *
15559   * @param {Texture} texture
15560   */
15561  destroyTexture(texture3) {
15562    const size3 = this.memoryMap.get(texture3) || 0;
15563    this.memoryMap.delete(texture3);
15564    this.memory.textures--;
15565    this.memory.total -= size3;
15566    this.memory.texturesSize -= size3;
15567  }
15568  /**
15569   * Tracks attribute memory explicitly, updating counts and byte tracking.
15570   *
15571   * @param {BufferAttribute} attribute
15572   * @param {string} type - type of attribute
15573   * @private
15574   */
15575  _createAttribute(attribute3, type) {
15576    const size3 = this._getAttributeMemorySize(attribute3);
15577    this.memoryMap.set(attribute3, { size: size3, type });
15578    this.memory[type]++;
15579    this.memory.total += size3;
15580    this.memory[type + "Size"] += size3;
15581  }
15582  /**
15583   * Tracks a regular attribute memory explicitly.
15584   *
15585   * @param {BufferAttribute} attribute - The attribute to track.
15586   */
15587  createAttribute(attribute3) {
15588    this._createAttribute(attribute3, "attributes");
15589  }
15590  /**
15591   * Tracks an index attribute memory explicitly.
15592   *
15593   * @param {BufferAttribute} attribute - The index attribute to track.
15594   */
15595  createIndexAttribute(attribute3) {
15596    this._createAttribute(attribute3, "indexAttributes");
15597  }
15598  /**
15599   * Tracks a storage attribute memory explicitly.
15600   *
15601   * @param {BufferAttribute} attribute - The storage attribute to track.
15602   */
15603  createStorageAttribute(attribute3) {
15604    this._createAttribute(attribute3, "storageAttributes");
15605  }
15606  /**
15607   * Tracks an indirect storage attribute memory explicitly.
15608   *
15609   * @param {BufferAttribute} attribute - The indirect storage attribute to track.
15610   */
15611  createIndirectStorageAttribute(attribute3) {
15612    this._createAttribute(attribute3, "indirectStorageAttributes");
15613  }
15614  /**
15615   * Tracks attribute memory explicitly, updating counts and byte tracking.
15616   *
15617   * @param {BufferAttribute} attribute
15618   */
15619  destroyAttribute(attribute3) {
15620    const data = this.memoryMap.get(attribute3);
15621    if (data) {
15622      this.memoryMap.delete(attribute3);
15623      this.memory[data.type]--;
15624      this.memory.total -= data.size;
15625      this.memory[data.type + "Size"] -= data.size;
15626    }
15627  }
15628  /**
15629   * Tracks a readback buffer memory explicitly.
15630   *
15631   * @param {ReadbackBuffer} readbackBuffer - The readback buffer to track.
15632   */
15633  createReadbackBuffer(readbackBuffer) {
15634    const maxByteLength = readbackBuffer.maxByteLength;
15635    this.memoryMap.set(readbackBuffer, { size: maxByteLength, type: "readbackBuffers" });
15636    this.memory.readbackBuffers++;
15637    this.memory.total += maxByteLength;
15638    this.memory.readbackBuffersSize += maxByteLength;
15639  }
15640  /**
15641   * Tracks a readback buffer memory explicitly.
15642   *
15643   * @param {ReadbackBuffer} readbackBuffer - The readback buffer to track.
15644   */
15645  destroyReadbackBuffer(readbackBuffer) {
15646    const { size: size3 } = this.memoryMap.get(readbackBuffer);
15647    this.memoryMap.delete(readbackBuffer);
15648    this.memory.readbackBuffers--;
15649    this.memory.total -= size3;
15650    this.memory.readbackBuffersSize -= size3;
15651  }
15652  /**
15653   * Tracks program memory explicitly, updating counts and byte tracking.
15654   *
15655   * @param {ProgrammableStage} program - The program to track.
15656   */
15657  createProgram(program) {
15658    const size3 = program.code.length;
15659    this.memoryMap.set(program, size3);
15660    this.memory.programs++;
15661    this.memory.total += size3;
15662    this.memory.programsSize += size3;
15663  }
15664  /**
15665   * Tracks program memory explicitly, updating counts and byte tracking.
15666   *
15667   * @param {Object} program - The program to track.
15668   */
15669  destroyProgram(program) {
15670    const size3 = this.memoryMap.get(program) || 0;
15671    this.memoryMap.delete(program);
15672    this.memory.programs--;
15673    this.memory.total -= size3;
15674    this.memory.programsSize -= size3;
15675  }
15676  /**
15677   * Calculates the memory size of a texture in bytes.
15678   *
15679   * @param {Texture} texture - The texture to calculate the size for.
15680   * @return {number} The calculated size in bytes.
15681   * @private
15682   */
15683  _getTextureMemorySize(texture3) {
15684    if (texture3.isCompressedTexture) {
15685      return 1;
15686    }
15687    let bytesPerChannel = 1;
15688    if (texture3.type === ByteType || texture3.type === UnsignedByteType) bytesPerChannel = 1;
15689    else if (texture3.type === ShortType || texture3.type === UnsignedShortType || texture3.type === HalfFloatType) bytesPerChannel = 2;
15690    else if (texture3.type === IntType || texture3.type === UnsignedIntType || texture3.type === FloatType) bytesPerChannel = 4;
15691    let channels = 4;
15692    if (texture3.format === AlphaFormat || texture3.format === RedFormat || texture3.format === RedIntegerFormat || texture3.format === DepthFormat || texture3.format === DepthStencilFormat) channels = 1;
15693    else if (texture3.format === RGFormat || texture3.format === RGIntegerFormat) channels = 2;
15694    else if (texture3.format === RGBFormat || texture3.format === RGBIntegerFormat) channels = 3;
15695    let bytesPerPixel = bytesPerChannel * channels;
15696    if (texture3.type === UnsignedShort4444Type || texture3.type === UnsignedShort5551Type) bytesPerPixel = 2;
15697    else if (texture3.type === UnsignedInt248Type || texture3.type === UnsignedInt5999Type || texture3.type === UnsignedInt101111Type) bytesPerPixel = 4;
15698    const width = texture3.width || 1;
15699    const height = texture3.height || 1;
15700    const depth3 = texture3.isCubeTexture ? 6 : texture3.depth || 1;
15701    let size3 = width * height * depth3 * bytesPerPixel;
15702    const mipmaps = texture3.mipmaps;
15703    if (mipmaps && mipmaps.length > 0) {
15704      let mipmapSize = 0;
15705      for (let i = 0; i < mipmaps.length; i++) {
15706        const mipmap = mipmaps[i];
15707        if (mipmap.data) {
15708          mipmapSize += mipmap.data.byteLength;
15709        } else {
15710          const mipWidth = mipmap.width || Math.max(1, width >> i);
15711          const mipHeight = mipmap.height || Math.max(1, height >> i);
15712          mipmapSize += mipWidth * mipHeight * depth3 * bytesPerPixel;
15713        }
15714      }
15715      size3 += mipmapSize;
15716    } else if (texture3.generateMipmaps) {
15717      size3 = size3 * 1.333;
15718    }
15719    return Math.round(size3);
15720  }
15721  /**
15722   * Calculates the memory size of an attribute in bytes.
15723   *
15724   * @param {BufferAttribute} attribute - The attribute to calculate the size for.
15725   * @return {number} The calculated size in bytes.
15726   * @private
15727   */
15728  _getAttributeMemorySize(attribute3) {
15729    if (attribute3.isInterleavedBufferAttribute) attribute3 = attribute3.data;
15730    if (attribute3.array) {
15731      return attribute3.array.byteLength;
15732    } else if (attribute3.count && attribute3.itemSize) {
15733      return attribute3.count * attribute3.itemSize * 4;
15734    }
15735    return 0;
15736  }
15737};
15738var Pipeline = class {
15739  /**
15740   * Constructs a new pipeline.
15741   *
15742   * @param {string} cacheKey - The pipeline's cache key.
15743   */
15744  constructor(cacheKey) {
15745    this.cacheKey = cacheKey;
15746    this.usedTimes = 0;
15747  }
15748};
15749var RenderObjectPipeline = class extends Pipeline {
15750  /**
15751   * Constructs a new render object pipeline.
15752   *
15753   * @param {string} cacheKey - The pipeline's cache key.
15754   * @param {ProgrammableStage} vertexProgram - The pipeline's vertex shader.
15755   * @param {ProgrammableStage} fragmentProgram - The pipeline's fragment shader.
15756   */
15757  constructor(cacheKey, vertexProgram, fragmentProgram) {
15758    super(cacheKey);
15759    this.vertexProgram = vertexProgram;
15760    this.fragmentProgram = fragmentProgram;
15761  }
15762};
15763var ComputePipeline = class extends Pipeline {
15764  /**
15765   * Constructs a new compute pipeline.
15766   *
15767   * @param {string} cacheKey - The pipeline's cache key.
15768   * @param {ProgrammableStage} computeProgram - The pipeline's compute shader.
15769   */
15770  constructor(cacheKey, computeProgram) {
15771    super(cacheKey);
15772    this.computeProgram = computeProgram;
15773    this.isComputePipeline = true;
15774  }
15775};
15776var _id$9 = 0;
15777var ProgrammableStage = class {
15778  /**
15779   * Constructs a new programmable stage.
15780   *
15781   * @param {string} code - The shader code.
15782   * @param {('vertex'|'fragment'|'compute')} stage - The type of stage.
15783   * @param {string} name - The name of the shader.
15784   * @param {?Array<Object>} [transforms=null] - The transforms (only relevant for compute stages with WebGL 2 which uses Transform Feedback).
15785   * @param {?Array<Object>} [attributes=null] - The attributes (only relevant for compute stages with WebGL 2 which uses Transform Feedback).
15786   */
15787  constructor(code3, stage, name, transforms = null, attributes = null) {
15788    this.id = _id$9++;
15789    this.code = code3;
15790    this.stage = stage;
15791    this.name = name;
15792    this.transforms = transforms;
15793    this.attributes = attributes;
15794    this.usedTimes = 0;
15795  }
15796};
15797var Pipelines = class extends DataMap {
15798  /**
15799   * Constructs a new pipeline management component.
15800   *
15801   * @param {Backend} backend - The renderer's backend.
15802   * @param {NodeManager} nodes - Renderer component for managing nodes related logic.
15803   * @param {Info} info - Renderer component for managing metrics and monitoring data.
15804   */
15805  constructor(backend, nodes, info) {
15806    super();
15807    this.backend = backend;
15808    this.nodes = nodes;
15809    this.info = info;
15810    this.bindings = null;
15811    this.caches = /* @__PURE__ */ new Map();
15812    this.programs = {
15813      vertex: /* @__PURE__ */ new Map(),
15814      fragment: /* @__PURE__ */ new Map(),
15815      compute: /* @__PURE__ */ new Map()
15816    };
15817  }
15818  /**
15819   * Returns a compute pipeline for the given compute node.
15820   *
15821   * @param {Node} computeNode - The compute node.
15822   * @param {Array<BindGroup>} bindings - The bindings.
15823   * @return {ComputePipeline} The compute pipeline.
15824   */
15825  getForCompute(computeNode, bindings) {
15826    const { backend } = this;
15827    const data = this.get(computeNode);
15828    if (this._needsComputeUpdate(computeNode)) {
15829      const previousPipeline = data.pipeline;
15830      if (previousPipeline) {
15831        previousPipeline.usedTimes--;
15832        previousPipeline.computeProgram.usedTimes--;
15833      }
15834      const nodeBuilderState = this.nodes.getForCompute(computeNode);
15835      let stageCompute = this.programs.compute.get(nodeBuilderState.computeShader);
15836      if (stageCompute === void 0) {
15837        if (previousPipeline && previousPipeline.computeProgram.usedTimes === 0) this._releaseProgram(previousPipeline.computeProgram);
15838        stageCompute = new ProgrammableStage(nodeBuilderState.computeShader, "compute", computeNode.name, nodeBuilderState.transforms, nodeBuilderState.nodeAttributes);
15839        this.programs.compute.set(nodeBuilderState.computeShader, stageCompute);
15840        backend.createProgram(stageCompute);
15841        this.info.createProgram(stageCompute);
15842      }
15843      const cacheKey = this._getComputeCacheKey(computeNode, stageCompute);
15844      let pipeline = this.caches.get(cacheKey);
15845      if (pipeline === void 0) {
15846        if (previousPipeline && previousPipeline.usedTimes === 0) this._releasePipeline(previousPipeline);
15847        pipeline = this._getComputePipeline(computeNode, stageCompute, cacheKey, bindings);
15848      }
15849      pipeline.usedTimes++;
15850      stageCompute.usedTimes++;
15851      data.version = computeNode.version;
15852      data.pipeline = pipeline;
15853    }
15854    return data.pipeline;
15855  }
15856  /**
15857   * Returns a render pipeline for the given render object.
15858   *
15859   * @param {RenderObject} renderObject - The render object.
15860   * @param {?Array<Promise>} [promises=null] - An array of compilation promises which is only relevant in context of `Renderer.compileAsync()`.
15861   * @return {RenderObjectPipeline} The render pipeline.
15862   */
15863  getForRender(renderObject, promises = null) {
15864    const { backend } = this;
15865    const data = this.get(renderObject);
15866    if (this._needsRenderUpdate(renderObject)) {
15867      const previousPipeline = data.pipeline;
15868      if (previousPipeline) {
15869        previousPipeline.usedTimes--;
15870        previousPipeline.vertexProgram.usedTimes--;
15871        previousPipeline.fragmentProgram.usedTimes--;
15872      }
15873      const nodeBuilderState = renderObject.getNodeBuilderState();
15874      const name = renderObject.material ? renderObject.material.name : "";
15875      let stageVertex = this.programs.vertex.get(nodeBuilderState.vertexShader);
15876      if (stageVertex === void 0) {
15877        if (previousPipeline && previousPipeline.vertexProgram.usedTimes === 0) this._releaseProgram(previousPipeline.vertexProgram);
15878        stageVertex = new ProgrammableStage(nodeBuilderState.vertexShader, "vertex", name);
15879        this.programs.vertex.set(nodeBuilderState.vertexShader, stageVertex);
15880        backend.createProgram(stageVertex);
15881        this.info.createProgram(stageVertex);
15882      }
15883      let stageFragment = this.programs.fragment.get(nodeBuilderState.fragmentShader);
15884      if (stageFragment === void 0) {
15885        if (previousPipeline && previousPipeline.fragmentProgram.usedTimes === 0) this._releaseProgram(previousPipeline.fragmentProgram);
15886        stageFragment = new ProgrammableStage(nodeBuilderState.fragmentShader, "fragment", name);
15887        this.programs.fragment.set(nodeBuilderState.fragmentShader, stageFragment);
15888        backend.createProgram(stageFragment);
15889        this.info.createProgram(stageFragment);
15890      }
15891      const cacheKey = this._getRenderCacheKey(renderObject, stageVertex, stageFragment);
15892      let pipeline = this.caches.get(cacheKey);
15893      if (pipeline === void 0) {
15894        if (previousPipeline && previousPipeline.usedTimes === 0) this._releasePipeline(previousPipeline);
15895        pipeline = this._getRenderPipeline(renderObject, stageVertex, stageFragment, cacheKey, promises);
15896      } else {
15897        renderObject.pipeline = pipeline;
15898      }
15899      pipeline.usedTimes++;
15900      stageVertex.usedTimes++;
15901      stageFragment.usedTimes++;
15902      data.pipeline = pipeline;
15903    }
15904    return data.pipeline;
15905  }
15906  /**
15907   * Checks if the render pipeline for the given render object is ready for drawing.
15908   * Returns false if the GPU pipeline is still being compiled asynchronously.
15909   *
15910   * @param {RenderObject} renderObject - The render object.
15911   * @return {boolean} True if the pipeline is ready for drawing.
15912   */
15913  isReady(renderObject) {
15914    const data = this.get(renderObject);
15915    const pipeline = data.pipeline;
15916    if (pipeline === void 0) return false;
15917    const pipelineData = this.backend.get(pipeline);
15918    return pipelineData.pipeline !== void 0 && pipelineData.pipeline !== null;
15919  }
15920  /**
15921   * Deletes the pipeline for the given render object.
15922   *
15923   * @param {RenderObject} object - The render object.
15924   * @return {?Object} The deleted dictionary.
15925   */
15926  delete(object) {
15927    const pipeline = this.get(object).pipeline;
15928    if (pipeline) {
15929      pipeline.usedTimes--;
15930      if (pipeline.usedTimes === 0) this._releasePipeline(pipeline);
15931      if (pipeline.isComputePipeline) {
15932        pipeline.computeProgram.usedTimes--;
15933        if (pipeline.computeProgram.usedTimes === 0) this._releaseProgram(pipeline.computeProgram);
15934      } else {
15935        pipeline.fragmentProgram.usedTimes--;
15936        pipeline.vertexProgram.usedTimes--;
15937        if (pipeline.vertexProgram.usedTimes === 0) this._releaseProgram(pipeline.vertexProgram);
15938        if (pipeline.fragmentProgram.usedTimes === 0) this._releaseProgram(pipeline.fragmentProgram);
15939      }
15940    }
15941    return super.delete(object);
15942  }
15943  /**
15944   * Frees internal resources.
15945   */
15946  dispose() {
15947    super.dispose();
15948    this.caches = /* @__PURE__ */ new Map();
15949    this.programs = {
15950      vertex: /* @__PURE__ */ new Map(),
15951      fragment: /* @__PURE__ */ new Map(),
15952      compute: /* @__PURE__ */ new Map()
15953    };
15954  }
15955  /**
15956   * Updates the pipeline for the given render object.
15957   *
15958   * @param {RenderObject} renderObject - The render object.
15959   */
15960  updateForRender(renderObject) {
15961    this.getForRender(renderObject);
15962  }
15963  /**
15964   * Returns a compute pipeline for the given parameters.
15965   *
15966   * @private
15967   * @param {Node} computeNode - The compute node.
15968   * @param {ProgrammableStage} stageCompute - The programmable stage representing the compute shader.
15969   * @param {string} cacheKey - The cache key.
15970   * @param {Array<BindGroup>} bindings - The bindings.
15971   * @return {ComputePipeline} The compute pipeline.
15972   */
15973  _getComputePipeline(computeNode, stageCompute, cacheKey, bindings) {
15974    cacheKey = cacheKey || this._getComputeCacheKey(computeNode, stageCompute);
15975    let pipeline = this.caches.get(cacheKey);
15976    if (pipeline === void 0) {
15977      pipeline = new ComputePipeline(cacheKey, stageCompute);
15978      this.caches.set(cacheKey, pipeline);
15979      this.backend.createComputePipeline(pipeline, bindings);
15980    }
15981    return pipeline;
15982  }
15983  /**
15984   * Returns a render pipeline for the given parameters.
15985   *
15986   * @private
15987   * @param {RenderObject} renderObject - The render object.
15988   * @param {ProgrammableStage} stageVertex - The programmable stage representing the vertex shader.
15989   * @param {ProgrammableStage} stageFragment - The programmable stage representing the fragment shader.
15990   * @param {string} cacheKey - The cache key.
15991   * @param {?Array<Promise>} promises - An array of compilation promises which is only relevant in context of `Renderer.compileAsync()`.
15992   * @return {RenderObjectPipeline} The render pipeline.
15993   */
15994  _getRenderPipeline(renderObject, stageVertex, stageFragment, cacheKey, promises) {
15995    cacheKey = cacheKey || this._getRenderCacheKey(renderObject, stageVertex, stageFragment);
15996    let pipeline = this.caches.get(cacheKey);
15997    if (pipeline === void 0) {
15998      pipeline = new RenderObjectPipeline(cacheKey, stageVertex, stageFragment);
15999      this.caches.set(cacheKey, pipeline);
16000      renderObject.pipeline = pipeline;
16001      this.backend.createRenderPipeline(renderObject, promises);
16002    }
16003    return pipeline;
16004  }
16005  /**
16006   * Computes a cache key representing a compute pipeline.
16007   *
16008   * @private
16009   * @param {Node} computeNode - The compute node.
16010   * @param {ProgrammableStage} stageCompute - The programmable stage representing the compute shader.
16011   * @return {string} The cache key.
16012   */
16013  _getComputeCacheKey(computeNode, stageCompute) {
16014    return computeNode.id + "," + stageCompute.id;
16015  }
16016  /**
16017   * Computes a cache key representing a render pipeline.
16018   *
16019   * @private
16020   * @param {RenderObject} renderObject - The render object.
16021   * @param {ProgrammableStage} stageVertex - The programmable stage representing the vertex shader.
16022   * @param {ProgrammableStage} stageFragment - The programmable stage representing the fragment shader.
16023   * @return {string} The cache key.
16024   */
16025  _getRenderCacheKey(renderObject, stageVertex, stageFragment) {
16026    return stageVertex.id + "," + stageFragment.id + "," + this.backend.getRenderCacheKey(renderObject);
16027  }
16028  /**
16029   * Releases the given pipeline.
16030   *
16031   * @private
16032   * @param {Pipeline} pipeline - The pipeline to release.
16033   */
16034  _releasePipeline(pipeline) {
16035    this.caches.delete(pipeline.cacheKey);
16036  }
16037  /**
16038   * Releases the shader program.
16039   *
16040   * @private
16041   * @param {Object} program - The shader program to release.
16042   */
16043  _releaseProgram(program) {
16044    const code3 = program.code;
16045    const stage = program.stage;
16046    this.programs[stage].delete(code3);
16047    this.info.destroyProgram(program);
16048  }
16049  /**
16050   * Returns `true` if the compute pipeline for the given compute node requires an update.
16051   *
16052   * @private
16053   * @param {Node} computeNode - The compute node.
16054   * @return {boolean} Whether the compute pipeline for the given compute node requires an update or not.
16055   */
16056  _needsComputeUpdate(computeNode) {
16057    const data = this.get(computeNode);
16058    return data.pipeline === void 0 || data.version !== computeNode.version;
16059  }
16060  /**
16061   * Returns `true` if the render pipeline for the given render object requires an update.
16062   *
16063   * @private
16064   * @param {RenderObject} renderObject - The render object.
16065   * @return {boolean} Whether the render object for the given render object requires an update or not.
16066   */
16067  _needsRenderUpdate(renderObject) {
16068    const data = this.get(renderObject);
16069    return data.pipeline === void 0 || this.backend.needsRenderUpdate(renderObject);
16070  }
16071};
16072var Bindings = class extends DataMap {
16073  /**
16074   * Constructs a new bindings management component.
16075   *
16076   * @param {Backend} backend - The renderer's backend.
16077   * @param {NodeManager} nodes - Renderer component for managing nodes related logic.
16078   * @param {Textures} textures - Renderer component for managing textures.
16079   * @param {Attributes} attributes - Renderer component for managing attributes.
16080   * @param {Pipelines} pipelines - Renderer component for managing pipelines.
16081   * @param {Info} info - Renderer component for managing metrics and monitoring data.
16082   */
16083  constructor(backend, nodes, textures, attributes, pipelines, info) {
16084    super();
16085    this.backend = backend;
16086    this.textures = textures;
16087    this.pipelines = pipelines;
16088    this.attributes = attributes;
16089    this.nodes = nodes;
16090    this.info = info;
16091    this.pipelines.bindings = this;
16092  }
16093  /**
16094   * Returns the bind groups for the given render object.
16095   *
16096   * @param {RenderObject} renderObject - The render object.
16097   * @return {Array<BindGroup>} The bind groups.
16098   */
16099  getForRender(renderObject) {
16100    const bindings = renderObject.getBindings();
16101    for (const bindGroup of bindings) {
16102      const groupData = this.get(bindGroup);
16103      if (groupData.bindGroup === void 0) {
16104        this._init(bindGroup);
16105        this.backend.createBindings(bindGroup, bindings, 0);
16106        groupData.bindGroup = bindGroup;
16107      }
16108    }
16109    return bindings;
16110  }
16111  /**
16112   * Returns the bind groups for the given compute node.
16113   *
16114   * @param {Node} computeNode - The compute node.
16115   * @return {Array<BindGroup>} The bind groups.
16116   */
16117  getForCompute(computeNode) {
16118    const bindings = this.nodes.getForCompute(computeNode).bindings;
16119    for (const bindGroup of bindings) {
16120      const groupData = this.get(bindGroup);
16121      if (groupData.bindGroup === void 0) {
16122        this._init(bindGroup);
16123        this.backend.createBindings(bindGroup, bindings, 0);
16124        groupData.bindGroup = bindGroup;
16125      }
16126    }
16127    return bindings;
16128  }
16129  /**
16130   * Updates the bindings for the given compute node.
16131   *
16132   * @param {Node} computeNode - The compute node.
16133   */
16134  updateForCompute(computeNode) {
16135    this._updateBindings(this.getForCompute(computeNode));
16136  }
16137  /**
16138   * Updates the bindings for the given render object.
16139   *
16140   * @param {RenderObject} renderObject - The render object.
16141   */
16142  updateForRender(renderObject) {
16143    this._updateBindings(this.getForRender(renderObject));
16144  }
16145  /**
16146   * Deletes the bindings for the given compute node.
16147   *
16148   * @param {Node} computeNode - The compute node.
16149   */
16150  deleteForCompute(computeNode) {
16151    const bindings = this.nodes.getForCompute(computeNode).bindings;
16152    for (const bindGroup of bindings) {
16153      this.backend.deleteBindGroupData(bindGroup);
16154      this.delete(bindGroup);
16155    }
16156  }
16157  /**
16158   * Deletes the bindings for the given renderObject node.
16159   *
16160   * @param {RenderObject} renderObject - The renderObject.
16161   */
16162  deleteForRender(renderObject) {
16163    const bindings = renderObject.getBindings();
16164    for (const bindGroup of bindings) {
16165      this.backend.deleteBindGroupData(bindGroup);
16166      this.delete(bindGroup);
16167    }
16168  }
16169  /**
16170   * Updates the given array of bindings.
16171   *
16172   * @param {Array<BindGroup>} bindings - The bind groups.
16173   */
16174  _updateBindings(bindings) {
16175    for (const bindGroup of bindings) {
16176      this._update(bindGroup, bindings);
16177    }
16178  }
16179  /**
16180   * Initializes the given bind group.
16181   *
16182   * @param {BindGroup} bindGroup - The bind group to initialize.
16183   */
16184  _init(bindGroup) {
16185    for (const binding of bindGroup.bindings) {
16186      if (binding.isSampledTexture) {
16187        this.textures.updateTexture(binding.texture);
16188      } else if (binding.isSampler) {
16189        this.textures.updateSampler(binding.texture);
16190      } else if (binding.isStorageBuffer) {
16191        const attribute3 = binding.attribute;
16192        const attributeType = attribute3.isIndirectStorageBufferAttribute ? AttributeType.INDIRECT : AttributeType.STORAGE;
16193        this.attributes.update(attribute3, attributeType);
16194      }
16195    }
16196  }
16197  /**
16198   * Updates the given bind group.
16199   *
16200   * @param {BindGroup} bindGroup - The bind group to update.
16201   * @param {Array<BindGroup>} bindings - The bind groups.
16202   */
16203  _update(bindGroup, bindings) {
16204    const { backend } = this;
16205    let needsBindingsUpdate = false;
16206    let cacheBindings = true;
16207    let cacheIndex = 0;
16208    let version = 0;
16209    for (const binding of bindGroup.bindings) {
16210      const updatedGroup = this.nodes.updateGroup(binding);
16211      if (updatedGroup === false) continue;
16212      if (binding.isStorageBuffer) {
16213        const attribute3 = binding.attribute;
16214        const attributeType = attribute3.isIndirectStorageBufferAttribute ? AttributeType.INDIRECT : AttributeType.STORAGE;
16215        const bindingData = backend.get(binding);
16216        this.attributes.update(attribute3, attributeType);
16217        if (bindingData.attribute !== attribute3) {
16218          bindingData.attribute = attribute3;
16219          needsBindingsUpdate = true;
16220        }
16221      }
16222      if (binding.isUniformBuffer) {
16223        const updated = binding.update();
16224        if (updated) {
16225          backend.updateBinding(binding);
16226        }
16227      } else if (binding.isSampledTexture) {
16228        const updated = binding.update();
16229        const texture3 = binding.texture;
16230        const texturesTextureData = this.textures.get(texture3);
16231        if (updated) {
16232          this.textures.updateTexture(texture3);
16233          if (binding.generation !== texturesTextureData.generation) {
16234            binding.generation = texturesTextureData.generation;
16235            needsBindingsUpdate = true;
16236          }
16237          texturesTextureData.bindGroups.add(bindGroup);
16238        }
16239        const textureData = backend.get(texture3);
16240        if (textureData.externalTexture !== void 0 || texturesTextureData.isDefaultTexture) {
16241          cacheBindings = false;
16242        } else {
16243          cacheIndex = cacheIndex * 10 + texture3.id;
16244          version += texture3.version;
16245        }
16246        if (texture3.isStorageTexture === true && texture3.mipmapsAutoUpdate === true) {
16247          const textureData2 = this.get(texture3);
16248          if (binding.store === true) {
16249            textureData2.needsMipmap = true;
16250          } else if (this.textures.needsMipmaps(texture3) && textureData2.needsMipmap === true) {
16251            this.backend.generateMipmaps(texture3);
16252            textureData2.needsMipmap = false;
16253          }
16254        }
16255      } else if (binding.isSampler) {
16256        const updated = binding.update();
16257        if (updated) {
16258          const samplerKey = this.textures.updateSampler(binding.texture);
16259          if (binding.samplerKey !== samplerKey) {
16260            binding.samplerKey = samplerKey;
16261            needsBindingsUpdate = true;
16262          }
16263        }
16264      }
16265      if (binding.isBuffer && binding.updateRanges.length > 0) {
16266        binding.clearUpdateRanges();
16267      }
16268    }
16269    if (needsBindingsUpdate === true) {
16270      this.backend.updateBindings(bindGroup, bindings, cacheBindings ? cacheIndex : 0, version);
16271    }
16272  }
16273};
16274function painterSortStable(a, b) {
16275  if (a.groupOrder !== b.groupOrder) {
16276    return a.groupOrder - b.groupOrder;
16277  } else if (a.renderOrder !== b.renderOrder) {
16278    return a.renderOrder - b.renderOrder;
16279  } else if (a.z !== b.z) {
16280    return a.z - b.z;
16281  } else {
16282    return a.id - b.id;
16283  }
16284}
16285function reversePainterSortStable(a, b) {
16286  if (a.groupOrder !== b.groupOrder) {
16287    return a.groupOrder - b.groupOrder;
16288  } else if (a.renderOrder !== b.renderOrder) {
16289    return a.renderOrder - b.renderOrder;
16290  } else if (a.z !== b.z) {
16291    return b.z - a.z;
16292  } else {
16293    return a.id - b.id;
16294  }
16295}
16296function needsDoublePass(material) {
16297  const hasTransmission = material.transmission > 0 || material.transmissionNode && material.transmissionNode.isNode;
16298  return hasTransmission && material.side === DoubleSide && material.forceSinglePass === false;
16299}
16300var RenderList = class {
16301  /**
16302   * Constructs a render list.
16303   *
16304   * @param {Lighting} lighting - The lighting management component.
16305   * @param {Scene} scene - The scene.
16306   * @param {Camera} camera - The camera the scene is rendered with.
16307   */
16308  constructor(lighting, scene, camera) {
16309    this.renderItems = [];
16310    this.renderItemsIndex = 0;
16311    this.opaque = [];
16312    this.transparentDoublePass = [];
16313    this.transparent = [];
16314    this.bundles = [];
16315    this.lightsNode = lighting.getNode(scene, camera);
16316    this.lightsArray = [];
16317    this.scene = scene;
16318    this.camera = camera;
16319    this.occlusionQueryCount = 0;
16320  }
16321  /**
16322   * This method is called right at the beginning of a render call
16323   * before the scene is analyzed. It prepares the internal data
16324   * structures for the upcoming render lists generation.
16325   *
16326   * @return {RenderList} A reference to this render list.
16327   */
16328  begin() {
16329    this.renderItemsIndex = 0;
16330    this.opaque.length = 0;
16331    this.transparentDoublePass.length = 0;
16332    this.transparent.length = 0;
16333    this.bundles.length = 0;
16334    this.lightsArray.length = 0;
16335    this.occlusionQueryCount = 0;
16336    return this;
16337  }
16338  /**
16339   * Returns a render item for the giving render item state. The state is defined
16340   * by a series of object-related parameters.
16341   *
16342   * The method avoids object creation by holding render items and reusing them in
16343   * subsequent render calls (just with different property values).
16344   *
16345   * @param {Object3D} object - The 3D object.
16346   * @param {BufferGeometry} geometry - The 3D object's geometry.
16347   * @param {Material} material - The 3D object's material.
16348   * @param {number} groupOrder - The current group order.
16349   * @param {number} z - Th 3D object's depth value (z value in clip space).
16350   * @param {?number} group - {?Object} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
16351   * @param {ClippingContext} clippingContext - The current clipping context.
16352   * @return {Object} The render item.
16353   */
16354  getNextRenderItem(object, geometry, material, groupOrder, z, group, clippingContext) {
16355    let renderItem = this.renderItems[this.renderItemsIndex];
16356    if (renderItem === void 0) {
16357      renderItem = {
16358        id: object.id,
16359        object,
16360        geometry,
16361        material,
16362        groupOrder,
16363        renderOrder: object.renderOrder,
16364        z,
16365        group,
16366        clippingContext
16367      };
16368      this.renderItems[this.renderItemsIndex] = renderItem;
16369    } else {
16370      renderItem.id = object.id;
16371      renderItem.object = object;
16372      renderItem.geometry = geometry;
16373      renderItem.material = material;
16374      renderItem.groupOrder = groupOrder;
16375      renderItem.renderOrder = object.renderOrder;
16376      renderItem.z = z;
16377      renderItem.group = group;
16378      renderItem.clippingContext = clippingContext;
16379    }
16380    this.renderItemsIndex++;
16381    return renderItem;
16382  }
16383  /**
16384   * Pushes the given object as a render item to the internal render lists.
16385   * The selected lists depend on the object properties.
16386   *
16387   * @param {Object3D} object - The 3D object.
16388   * @param {BufferGeometry} geometry - The 3D object's geometry.
16389   * @param {Material} material - The 3D object's material.
16390   * @param {number} groupOrder - The current group order.
16391   * @param {number} z - Th 3D object's depth value (z value in clip space).
16392   * @param {?number} group - {?Object} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
16393   * @param {ClippingContext} clippingContext - The current clipping context.
16394   */
16395  push(object, geometry, material, groupOrder, z, group, clippingContext) {
16396    const renderItem = this.getNextRenderItem(object, geometry, material, groupOrder, z, group, clippingContext);
16397    if (object.occlusionTest === true) this.occlusionQueryCount++;
16398    if (material.transparent === true || material.transmission > 0 || material.transmissionNode && material.transmissionNode.isNode || material.backdropNode && material.backdropNode.isNode) {
16399      if (needsDoublePass(material)) this.transparentDoublePass.push(renderItem);
16400      this.transparent.push(renderItem);
16401    } else {
16402      this.opaque.push(renderItem);
16403    }
16404  }
16405  /**
16406   * Inserts the given object as a render item at the start of the internal render lists.
16407   * The selected lists depend on the object properties.
16408   *
16409   * @param {Object3D} object - The 3D object.
16410   * @param {BufferGeometry} geometry - The 3D object's geometry.
16411   * @param {Material} material - The 3D object's material.
16412   * @param {number} groupOrder - The current group order.
16413   * @param {number} z - Th 3D object's depth value (z value in clip space).
16414   * @param {?number} group - {?Object} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
16415   * @param {ClippingContext} clippingContext - The current clipping context.
16416   */
16417  unshift(object, geometry, material, groupOrder, z, group, clippingContext) {
16418    const renderItem = this.getNextRenderItem(object, geometry, material, groupOrder, z, group, clippingContext);
16419    if (material.transparent === true || material.transmission > 0 || material.transmissionNode && material.transmissionNode.isNode || material.backdropNode && material.backdropNode.isNode) {
16420      if (needsDoublePass(material)) this.transparentDoublePass.unshift(renderItem);
16421      this.transparent.unshift(renderItem);
16422    } else {
16423      this.opaque.unshift(renderItem);
16424    }
16425  }
16426  /**
16427   * Pushes render bundle group data into the render list.
16428   *
16429   * @param {Object} group - Bundle group data.
16430   */
16431  pushBundle(group) {
16432    this.bundles.push(group);
16433  }
16434  /**
16435   * Pushes a light into the render list.
16436   *
16437   * @param {Light} light - The light.
16438   */
16439  pushLight(light) {
16440    this.lightsArray.push(light);
16441  }
16442  /**
16443   * Sorts the internal render lists.
16444   *
16445   * @param {?function(any, any): number} customOpaqueSort - A custom sort function for opaque objects.
16446   * @param {?function(any, any): number} customTransparentSort -  A custom sort function for transparent objects.
16447   */
16448  sort(customOpaqueSort, customTransparentSort) {
16449    if (this.opaque.length > 1) this.opaque.sort(customOpaqueSort || painterSortStable);
16450    if (this.transparentDoublePass.length > 1) this.transparentDoublePass.sort(customTransparentSort || reversePainterSortStable);
16451    if (this.transparent.length > 1) this.transparent.sort(customTransparentSort || reversePainterSortStable);
16452  }
16453  /**
16454   * This method performs finalizing tasks right after the render lists
16455   * have been generated.
16456   */
16457  finish() {
16458    this.lightsNode.setLights(this.lightsArray);
16459    for (let i = this.renderItemsIndex, il = this.renderItems.length; i < il; i++) {
16460      const renderItem = this.renderItems[i];
16461      if (renderItem.id === null) break;
16462      renderItem.id = null;
16463      renderItem.object = null;
16464      renderItem.geometry = null;
16465      renderItem.material = null;
16466      renderItem.groupOrder = null;
16467      renderItem.renderOrder = null;
16468      renderItem.z = null;
16469      renderItem.group = null;
16470      renderItem.clippingContext = null;
16471    }
16472  }
16473};
16474var _chainKeys$2 = [];
16475var RenderLists = class {
16476  /**
16477   * Constructs a render lists management component.
16478   *
16479   * @param {Lighting} lighting - The lighting management component.
16480   */
16481  constructor(lighting) {
16482    this.lighting = lighting;
16483    this.lists = new ChainMap();
16484  }
16485  /**
16486   * Returns a render list for the given scene and camera.
16487   *
16488   * @param {Scene} scene - The scene.
16489   * @param {Camera} camera - The camera.
16490   * @return {RenderList} The render list.
16491   */
16492  get(scene, camera) {
16493    const lists = this.lists;
16494    _chainKeys$2[0] = scene;
16495    _chainKeys$2[1] = camera;
16496    let list = lists.get(_chainKeys$2);
16497    if (list === void 0) {
16498      list = new RenderList(this.lighting, scene, camera);
16499      lists.set(_chainKeys$2, list);
16500    }
16501    _chainKeys$2[0] = null;
16502    _chainKeys$2[1] = null;
16503    return list;
16504  }
16505  /**
16506   * Frees all internal resources.
16507   */
16508  dispose() {
16509    this.lists = new ChainMap();
16510  }
16511};
16512var _id$8 = 0;
16513var RenderContext = class {
16514  /**
16515   * Constructs a new render context.
16516   */
16517  constructor() {
16518    this.id = _id$8++;
16519    this.mrt = null;
16520    this.color = true;
16521    this.clearColor = true;
16522    this.clearColorValue = { r: 0, g: 0, b: 0, a: 1 };
16523    this.depth = true;
16524    this.clearDepth = true;
16525    this.clearDepthValue = 1;
16526    this.stencil = false;
16527    this.clearStencil = true;
16528    this.clearStencilValue = 1;
16529    this.viewport = false;
16530    this.viewportValue = new Vector4();
16531    this.scissor = false;
16532    this.scissorValue = new Vector4();
16533    this.renderTarget = null;
16534    this.textures = null;
16535    this.depthTexture = null;
16536    this.activeCubeFace = 0;
16537    this.activeMipmapLevel = 0;
16538    this.sampleCount = 1;
16539    this.width = 0;
16540    this.height = 0;
16541    this.occlusionQueryCount = 0;
16542    this.clippingContext = null;
16543    this.camera = null;
16544    this.isRenderContext = true;
16545  }
16546  /**
16547   * Returns the cache key of this render context.
16548   *
16549   * @return {number} The cache key.
16550   */
16551  getCacheKey() {
16552    return getCacheKey(this);
16553  }
16554};
16555function getCacheKey(renderContext) {
16556  const { textures, activeCubeFace, activeMipmapLevel } = renderContext;
16557  const values = [activeCubeFace, activeMipmapLevel];
16558  for (const texture3 of textures) {
16559    values.push(texture3.id);
16560  }
16561  return hashArray(values);
16562}
16563var RenderContexts = class {
16564  /**
16565   * Constructs a new render context management component.
16566   *
16567   * @param {Renderer} renderer - The renderer.
16568   */
16569  constructor(renderer) {
16570    this.renderer = renderer;
16571    this._renderContexts = {};
16572  }
16573  /**
16574   * Returns a render context for the given scene, camera and render target.
16575   *
16576   * @param {?RenderTarget} [renderTarget=null] - The active render target.
16577   * @param {?MRTNode} [mrt=null] - The MRT configuration
16578   * @param {?number} [callDepth=0] - The call depth of the renderer.
16579   * @return {RenderContext} The render context.
16580   */
16581  get(renderTarget = null, mrt3 = null, callDepth = 0) {
16582    let attachmentState;
16583    if (renderTarget === null) {
16584      attachmentState = "default";
16585    } else {
16586      const format = renderTarget.texture.format;
16587      const type = renderTarget.texture.type;
16588      const count = renderTarget.textures.length;
16589      attachmentState = `${count}:${format}:${type}:${renderTarget.samples}:${renderTarget.depthBuffer}:${renderTarget.stencilBuffer}`;
16590    }
16591    const mrtState = mrt3 !== null ? mrt3.id : "default";
16592    const renderStateKey = attachmentState + "-" + mrtState + "-" + callDepth;
16593    let renderState = this._renderContexts[renderStateKey];
16594    if (renderState === void 0) {
16595      renderState = new RenderContext();
16596      renderState.mrt = mrt3;
16597      this._renderContexts[renderStateKey] = renderState;
16598    }
16599    if (renderTarget !== null) renderState.sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples;
16600    renderState.clearDepthValue = this.renderer.getClearDepth();
16601    renderState.clearStencilValue = this.renderer.getClearStencil();
16602    return renderState;
16603  }
16604  /**
16605   * Frees internal resources.
16606   */
16607  dispose() {
16608    this._renderContexts = {};
16609  }
16610};
16611var _size$3 = /* @__PURE__ */ new Vector3();
16612var Textures = class extends DataMap {
16613  /**
16614   * Constructs a new texture management component.
16615   *
16616   * @param {Renderer} renderer - The renderer.
16617   * @param {Backend} backend - The renderer's backend.
16618   * @param {Info} info - Renderer component for managing metrics and monitoring data.
16619   */
16620  constructor(renderer, backend, info) {
16621    super();
16622    this.renderer = renderer;
16623    this.backend = backend;
16624    this.info = info;
16625    this._htmlTextures = /* @__PURE__ */ new Set();
16626  }
16627  /**
16628   * Updates the given render target. Based on the given render target configuration,
16629   * it updates the texture states representing the attachments of the framebuffer.
16630   *
16631   * @param {RenderTarget} renderTarget - The render target to update.
16632   * @param {number} [activeMipmapLevel=0] - The active mipmap level.
16633   */
16634  updateRenderTarget(renderTarget, activeMipmapLevel = 0) {
16635    const renderTargetData = this.get(renderTarget);
16636    const sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples;
16637    const depthTextureMips = renderTargetData.depthTextureMips || (renderTargetData.depthTextureMips = {});
16638    const textures = renderTarget.textures;
16639    const size3 = this.getSize(textures[0]);
16640    const mipWidth = size3.width >> activeMipmapLevel;
16641    const mipHeight = size3.height >> activeMipmapLevel;
16642    let depthTexture = renderTarget.depthTexture || depthTextureMips[activeMipmapLevel];
16643    const useDepthTexture = renderTarget.depthBuffer === true || renderTarget.stencilBuffer === true;
16644    let textureNeedsUpdate = false;
16645    if (depthTexture === void 0 && useDepthTexture) {
16646      depthTexture = new DepthTexture();
16647      depthTexture.format = renderTarget.stencilBuffer ? DepthStencilFormat : DepthFormat;
16648      depthTexture.type = renderTarget.stencilBuffer ? UnsignedInt248Type : UnsignedIntType;
16649      depthTexture.image.width = mipWidth;
16650      depthTexture.image.height = mipHeight;
16651      depthTexture.image.depth = size3.depth;
16652      depthTexture.renderTarget = renderTarget;
16653      depthTexture.isArrayTexture = renderTarget.multiview === true && size3.depth > 1;
16654      depthTextureMips[activeMipmapLevel] = depthTexture;
16655    }
16656    if (renderTargetData.width !== size3.width || size3.height !== renderTargetData.height) {
16657      textureNeedsUpdate = true;
16658      if (depthTexture) {
16659        depthTexture.needsUpdate = true;
16660        depthTexture.image.width = mipWidth;
16661        depthTexture.image.height = mipHeight;
16662        depthTexture.image.depth = depthTexture.isArrayTexture ? depthTexture.image.depth : 1;
16663      }
16664    }
16665    renderTargetData.width = size3.width;
16666    renderTargetData.height = size3.height;
16667    renderTargetData.textures = textures;
16668    renderTargetData.depthTexture = depthTexture || null;
16669    renderTargetData.depth = renderTarget.depthBuffer;
16670    renderTargetData.stencil = renderTarget.stencilBuffer;
16671    renderTargetData.renderTarget = renderTarget;
16672    if (renderTargetData.sampleCount !== sampleCount) {
16673      textureNeedsUpdate = true;
16674      if (depthTexture) {
16675        depthTexture.needsUpdate = true;
16676      }
16677      renderTargetData.sampleCount = sampleCount;
16678    }
16679    const options = { sampleCount };
16680    if (renderTarget.isXRRenderTarget !== true) {
16681      for (let i = 0; i < textures.length; i++) {
16682        const texture3 = textures[i];
16683        if (textureNeedsUpdate) texture3.needsUpdate = true;
16684        this.updateTexture(texture3, options);
16685      }
16686      if (depthTexture) {
16687        this.updateTexture(depthTexture, options);
16688      }
16689    }
16690    if (renderTargetData.initialized !== true) {
16691      renderTargetData.initialized = true;
16692      this.info.memory.renderTargets++;
16693      renderTargetData.onDispose = () => {
16694        this._destroyRenderTarget(renderTarget);
16695      };
16696      renderTarget.addEventListener("dispose", renderTargetData.onDispose);
16697    }
16698  }
16699  /**
16700   * Updates the given texture. Depending on the texture state, this method
16701   * triggers the upload of texture data to the GPU memory. If the texture data are
16702   * not yet ready for the upload, it uses default texture data for as a placeholder.
16703   *
16704   * @param {Texture} texture - The texture to update.
16705   * @param {Object} [options={}] - The options.
16706   */
16707  updateTexture(texture3, options = {}) {
16708    const textureData = this.get(texture3);
16709    if (textureData.initialized === true && textureData.version === texture3.version) return;
16710    const isRenderTarget = texture3.isRenderTargetTexture || texture3.isDepthTexture || texture3.isFramebufferTexture;
16711    const backend = this.backend;
16712    if (isRenderTarget && textureData.initialized === true) {
16713      backend.destroyTexture(texture3);
16714    }
16715    if (texture3.isFramebufferTexture) {
16716      const renderTarget = this.renderer.getRenderTarget();
16717      if (renderTarget) {
16718        texture3.type = renderTarget.texture.type;
16719      } else {
16720        texture3.type = UnsignedByteType;
16721      }
16722    }
16723    if (texture3.isHTMLTexture && texture3.image) {
16724      const canvas = this.renderer.domElement;
16725      if ("requestPaint" in canvas) {
16726        if (!canvas.hasAttribute("layoutsubtree")) {
16727          canvas.setAttribute("layoutsubtree", "true");
16728        }
16729        if (texture3.image.parentNode !== canvas) {
16730          canvas.appendChild(texture3.image);
16731        }
16732        if (this._htmlTextures.size === 0) {
16733          const htmlTextures = this._htmlTextures;
16734          canvas.onpaint = (event) => {
16735            const changed = event && event.changedElements;
16736            for (const t of htmlTextures) {
16737              if (!changed || changed.includes(t.image)) {
16738                t.needsUpdate = true;
16739              }
16740            }
16741          };
16742        }
16743        this._htmlTextures.add(texture3);
16744      }
16745    }
16746    const { width, height, depth: depth3 } = this.getSize(texture3);
16747    options.width = width;
16748    options.height = height;
16749    options.depth = depth3;
16750    options.needsMipmaps = this.needsMipmaps(texture3);
16751    options.levels = options.needsMipmaps ? this.getMipLevels(texture3, width, height) : 1;
16752    if (texture3.isCubeTexture && texture3.mipmaps.length > 0) options.levels++;
16753    if (isRenderTarget || texture3.isStorageTexture === true || texture3.isExternalTexture === true) {
16754      backend.createTexture(texture3, options);
16755      textureData.generation = texture3.version;
16756    } else {
16757      if (texture3.version > 0) {
16758        const image = texture3.image;
16759        if (image === void 0) {
16760          warn("Renderer: Texture marked for update but image is undefined.");
16761        } else if (image.complete === false) {
16762          warn("Renderer: Texture marked for update but image is incomplete.");
16763        } else {
16764          if (texture3.images) {
16765            const images = [];
16766            for (const image2 of texture3.images) {
16767              images.push(image2);
16768            }
16769            options.images = images;
16770          } else {
16771            options.image = image;
16772          }
16773          if (textureData.isDefaultTexture === void 0 || textureData.isDefaultTexture === true) {
16774            backend.createTexture(texture3, options);
16775            textureData.isDefaultTexture = false;
16776            textureData.generation = texture3.version;
16777          }
16778          if (texture3.source.dataReady === true) backend.updateTexture(texture3, options);
16779          const skipAutoGeneration = texture3.isStorageTexture === true && texture3.mipmapsAutoUpdate === false;
16780          if (options.needsMipmaps && texture3.mipmaps.length === 0 && !skipAutoGeneration) {
16781            backend.generateMipmaps(texture3);
16782          }
16783          if (texture3.onUpdate) texture3.onUpdate(texture3);
16784        }
16785      } else {
16786        backend.createDefaultTexture(texture3);
16787        textureData.isDefaultTexture = true;
16788        textureData.generation = texture3.version;
16789      }
16790    }
16791    if (textureData.initialized !== true) {
16792      textureData.initialized = true;
16793      textureData.generation = texture3.version;
16794      textureData.bindGroups = /* @__PURE__ */ new Set();
16795      this.info.createTexture(texture3);
16796      if (texture3.isVideoTexture && ColorManagement.enabled === true && ColorManagement.getTransfer(texture3.colorSpace) !== SRGBTransfer) {
16797        warn("WebGPURenderer: Video textures must use a color space with a sRGB transfer function, e.g. SRGBColorSpace.");
16798      }
16799      textureData.onDispose = () => {
16800        this._destroyTexture(texture3);
16801      };
16802      texture3.addEventListener("dispose", textureData.onDispose);
16803    }
16804    textureData.version = texture3.version;
16805  }
16806  /**
16807   * Updates the sampler for the given texture. This method has no effect
16808   * for the WebGL backend since it has no concept of samplers. Texture
16809   * parameters are configured with the `texParameter()` command for each
16810   * texture.
16811   *
16812   * In WebGPU, samplers are objects like textures and it's possible to share
16813   * them when the texture parameters match.
16814   *
16815   * @param {Texture} texture - The texture to update the sampler for.
16816   * @return {string} The current sampler key.
16817   */
16818  updateSampler(texture3) {
16819    return this.backend.updateSampler(texture3);
16820  }
16821  /**
16822   * Computes the size of the given texture and writes the result
16823   * into the target vector. This vector is also returned by the
16824   * method.
16825   *
16826   * If no texture data are available for the compute yet, the method
16827   * returns default size values.
16828   *
16829   * @param {Texture} texture - The texture to compute the size for.
16830   * @param {Vector3} target - The target vector.
16831   * @return {Vector3} The target vector.
16832   */
16833  getSize(texture3, target = _size$3) {
16834    let image = texture3.images ? texture3.images[0] : texture3.image;
16835    if (image) {
16836      if (image.image !== void 0) image = image.image;
16837      if (texture3.isHTMLTexture) {
16838        target.width = image.offsetWidth || 1;
16839        target.height = image.offsetHeight || 1;
16840        target.depth = 1;
16841      } else if (typeof HTMLVideoElement !== "undefined" && image instanceof HTMLVideoElement) {
16842        target.width = image.videoWidth || 1;
16843        target.height = image.videoHeight || 1;
16844        target.depth = 1;
16845      } else if (typeof VideoFrame !== "undefined" && image instanceof VideoFrame) {
16846        target.width = image.displayWidth || 1;
16847        target.height = image.displayHeight || 1;
16848        target.depth = 1;
16849      } else {
16850        target.width = image.width || 1;
16851        target.height = image.height || 1;
16852        target.depth = texture3.isCubeTexture ? 6 : image.depth || 1;
16853      }
16854    } else {
16855      target.width = target.height = target.depth = 1;
16856    }
16857    return target;
16858  }
16859  /**
16860   * Computes the number of mipmap levels for the given texture.
16861   *
16862   * @param {Texture} texture - The texture.
16863   * @param {number} width - The texture's width.
16864   * @param {number} height - The texture's height.
16865   * @return {number} The number of mipmap levels.
16866   */
16867  getMipLevels(texture3, width, height) {
16868    let mipLevelCount;
16869    if (texture3.mipmaps.length > 0) {
16870      mipLevelCount = texture3.mipmaps.length;
16871    } else {
16872      if (texture3.isCompressedTexture === true) {
16873        mipLevelCount = 1;
16874      } else {
16875        mipLevelCount = Math.floor(Math.log2(Math.max(width, height))) + 1;
16876      }
16877    }
16878    return mipLevelCount;
16879  }
16880  /**
16881   * Returns `true` if the given texture makes use of mipmapping.
16882   *
16883   * @param {Texture} texture - The texture.
16884   * @return {boolean} Whether mipmaps are required or not.
16885   */
16886  needsMipmaps(texture3) {
16887    return texture3.generateMipmaps === true || texture3.mipmaps.length > 0;
16888  }
16889  /**
16890   * Frees internal resources when the given render target isn't
16891   * required anymore.
16892   *
16893   * @param {RenderTarget} renderTarget - The render target to destroy.
16894   */
16895  _destroyRenderTarget(renderTarget) {
16896    if (this.has(renderTarget) === true) {
16897      const renderTargetData = this.get(renderTarget);
16898      const textures = renderTargetData.textures;
16899      const depthTexture = renderTargetData.depthTexture;
16900      renderTarget.removeEventListener("dispose", renderTargetData.onDispose);
16901      for (let i = 0; i < textures.length; i++) {
16902        this._destroyTexture(textures[i]);
16903      }
16904      if (depthTexture) {
16905        this._destroyTexture(depthTexture);
16906      }
16907      this.delete(renderTarget);
16908      this.backend.delete(renderTarget);
16909      this.info.memory.renderTargets--;
16910    }
16911  }
16912  /**
16913   * Frees internal resource when the given texture isn't
16914   * required anymore.
16915   *
16916   * @param {Texture} texture - The texture to destroy.
16917   */
16918  _destroyTexture(texture3) {
16919    if (this.has(texture3) === true) {
16920      const textureData = this.get(texture3);
16921      texture3.removeEventListener("dispose", textureData.onDispose);
16922      const isDefaultTexture = textureData.isDefaultTexture;
16923      this.backend.destroyTexture(texture3, isDefaultTexture);
16924      if (textureData.bindGroups) {
16925        for (const bindGroup of textureData.bindGroups) {
16926          const bindingsData = this.backend.get(bindGroup);
16927          bindingsData.groups = void 0;
16928          bindingsData.versions = void 0;
16929        }
16930      }
16931      this._htmlTextures.delete(texture3);
16932      this.delete(texture3);
16933      this.info.destroyTexture(texture3);
16934    }
16935  }
16936};
16937var Color4 = class extends Color {
16938  /**
16939   * Constructs a new four-component color.
16940   * You can also pass a single THREE.Color, hex or
16941   * string argument to this constructor.
16942   *
16943   * @param {number|string} [r=1] - The red value.
16944   * @param {number} [g=1] - The green value.
16945   * @param {number} [b=1] - The blue value.
16946   * @param {number} [a=1] - The alpha value.
16947   */
16948  constructor(r, g, b, a = 1) {
16949    super(r, g, b);
16950    this.a = a;
16951  }
16952  /**
16953   * Overwrites the default to honor alpha.
16954   * You can also pass a single THREE.Color, hex or
16955   * string argument to this method.
16956   *
16957   * @param {number|string|Color} r - The red value.
16958   * @param {number} [g] - The green value.
16959   * @param {number} [b] - The blue value.
16960   * @param {number} [a=1] - The alpha value.
16961   * @return {Color4} A reference to this object.
16962   */
16963  set(r, g, b, a = 1) {
16964    this.a = a;
16965    return super.set(r, g, b);
16966  }
16967  /**
16968   * Overwrites the default to honor alpha.
16969   *
16970   * @param {Color4} color - The color to copy.
16971   * @return {Color4} A reference to this object.
16972   */
16973  copy(color3) {
16974    if (color3.a !== void 0) this.a = color3.a;
16975    return super.copy(color3);
16976  }
16977  /**
16978   * Overwrites the default to honor alpha.
16979   *
16980   * @return {Color4} The cloned color.
16981   */
16982  clone() {
16983    return new this.constructor(this.r, this.g, this.b, this.a);
16984  }
16985};
16986var ParameterNode = class extends PropertyNode {
16987  static get type() {
16988    return "ParameterNode";
16989  }
16990  /**
16991   * Constructs a new parameter node.
16992   *
16993   * @param {string} nodeType - The type of the node.
16994   * @param {?string} [name=null] - The name of the parameter in the shader.
16995   */
16996  constructor(nodeType, name = null) {
16997    super(nodeType, name);
16998    this.isParameterNode = true;
16999  }
17000  /**
17001   * Gets the type of a member variable in the parameter node.
17002   *
17003   * @param {NodeBuilder} builder - The node builder.
17004   * @param {string} name - The name of the member variable.
17005   * @returns {string}
17006   */
17007  getMemberType(builder, name) {
17008    const type = this.getNodeType(builder);
17009    const struct3 = builder.getStructTypeNode(type);
17010    let memberType;
17011    if (struct3 !== null) {
17012      memberType = struct3.getMemberType(builder, name);
17013    } else {
17014      error(`TSL: Member "${name}" not found in struct "${type}".`, new StackTrace());
17015      memberType = "float";
17016    }
17017    return memberType;
17018  }
17019  getHash() {
17020    return String(this.id);
17021  }
17022  generate() {
17023    return this.name;
17024  }
17025};
17026var parameter = (type, name) => new ParameterNode(type, name);
17027var StackNode = class extends Node2 {
17028  static get type() {
17029    return "StackNode";
17030  }
17031  /**
17032   * Constructs a new stack node.
17033   *
17034   * @param {?StackNode} [parent=null] - The parent stack node.
17035   */
17036  constructor(parent = null) {
17037    super();
17038    this.nodes = [];
17039    this.outputNode = null;
17040    this.parent = parent;
17041    this._currentCond = null;
17042    this._expressionNode = null;
17043    this._currentNode = null;
17044    this.isStackNode = true;
17045  }
17046  getElementType(builder) {
17047    return this.hasOutput(builder) ? this.outputNode.getElementType(builder) : "void";
17048  }
17049  generateNodeType(builder) {
17050    return this.hasOutput(builder) ? this.outputNode.getNodeType(builder) : "void";
17051  }
17052  getMemberType(builder, name) {
17053    return this.hasOutput(builder) ? this.outputNode.getMemberType(builder, name) : "void";
17054  }
17055  /**
17056   * Adds a node to this stack.
17057   *
17058   * @param {Node} node - The node to add.
17059   * @param {number} [index=this.nodes.length] - The index where the node should be added.
17060   * @return {StackNode} A reference to this stack node.
17061   */
17062  addToStack(node, index = this.nodes.length) {
17063    if (node.isNode !== true) {
17064      error("TSL: Invalid node added to stack.", new StackTrace());
17065      return this;
17066    }
17067    this.nodes.splice(index, 0, node);
17068    return this;
17069  }
17070  /**
17071   * Adds a node to the stack before the current node.
17072   *
17073   * @param {Node} node - The node to add.
17074   * @return {StackNode} A reference to this stack node.
17075   */
17076  addToStackBefore(node) {
17077    const index = this._currentNode ? this.nodes.indexOf(this._currentNode) : 0;
17078    return this.addToStack(node, index);
17079  }
17080  /**
17081   * Represent an `if` statement in TSL.
17082   *
17083   * @param {Node} boolNode - Represents the condition.
17084   * @param {Function} method - TSL code which is executed if the condition evaluates to `true`.
17085   * @return {StackNode} A reference to this stack node.
17086   */
17087  If(boolNode, method) {
17088    const methodNode = new ShaderNode(method);
17089    this._currentCond = select(boolNode, methodNode);
17090    return this.addToStack(this._currentCond);
17091  }
17092  /**
17093   * Represent an `elseif` statement in TSL.
17094   *
17095   * @param {Node} boolNode - Represents the condition.
17096   * @param {Function} method - TSL code which is executed if the condition evaluates to `true`.
17097   * @return {StackNode} A reference to this stack node.
17098   */
17099  ElseIf(boolNode, method) {
17100    const methodNode = new ShaderNode(method);
17101    const ifNode = select(boolNode, methodNode);
17102    this._currentCond.elseNode = ifNode;
17103    this._currentCond = ifNode;
17104    return this;
17105  }
17106  /**
17107   * Represent an `else` statement in TSL.
17108   *
17109   * @param {Function} method - TSL code which is executed in the `else` case.
17110   * @return {StackNode} A reference to this stack node.
17111   */
17112  Else(method) {
17113    this._currentCond.elseNode = new ShaderNode(method);
17114    return this;
17115  }
17116  /**
17117   * Represents a `switch` statement in TSL.
17118   *
17119   * @param {any} expression - Represents the expression.
17120   * @param {Function} method - TSL code which is executed if the condition evaluates to `true`.
17121   * @return {StackNode} A reference to this stack node.
17122   */
17123  Switch(expression3) {
17124    this._expressionNode = nodeObject(expression3);
17125    return this;
17126  }
17127  /**
17128   * Represents a `case` statement in TSL. The TSL version accepts an arbitrary numbers of values.
17129   * The last parameter must be the callback method that should be executed in the `true` case.
17130   *
17131   * @param {...any} params - The values of the `Case()` statement as well as the callback method.
17132   * @return {StackNode} A reference to this stack node.
17133   */
17134  Case(...params) {
17135    const caseNodes = [];
17136    if (params.length >= 2) {
17137      for (let i = 0; i < params.length - 1; i++) {
17138        caseNodes.push(this._expressionNode.equal(nodeObject(params[i])));
17139      }
17140    } else {
17141      error("TSL: Invalid parameter length. Case() requires at least two parameters.", new StackTrace());
17142    }
17143    const method = params[params.length - 1];
17144    const methodNode = new ShaderNode(method);
17145    let caseNode = caseNodes[0];
17146    for (let i = 1; i < caseNodes.length; i++) {
17147      caseNode = caseNode.or(caseNodes[i]);
17148    }
17149    const condNode = select(caseNode, methodNode);
17150    if (this._currentCond === null) {
17151      this._currentCond = condNode;
17152      return this.addToStack(this._currentCond);
17153    } else {
17154      this._currentCond.elseNode = condNode;
17155      this._currentCond = condNode;
17156      return this;
17157    }
17158  }
17159  /**
17160   * Represents the default code block of a Switch/Case statement.
17161   *
17162   * @param {Function} method - TSL code which is executed in the `else` case.
17163   * @return {StackNode} A reference to this stack node.
17164   */
17165  Default(method) {
17166    this.Else(method);
17167    return this;
17168  }
17169  setup(builder) {
17170    const nodeProperties = builder.getNodeProperties(this);
17171    let index = 0;
17172    for (const childNode of this.getChildren()) {
17173      if (childNode.isVarNode && childNode.isIntent(builder)) {
17174        if (childNode.isAssign(builder) !== true) {
17175          continue;
17176        }
17177      }
17178      nodeProperties["node" + index++] = childNode;
17179    }
17180    return nodeProperties.outputNode || null;
17181  }
17182  hasOutput(builder) {
17183    return this.outputNode && this.outputNode.isNode && this.outputNode.getNodeType(builder) !== "void";
17184  }
17185  build(builder, ...params) {
17186    const previousStack = getCurrentStack();
17187    const buildStage = builder.buildStage;
17188    setCurrentStack(this);
17189    builder.setActiveStack(this);
17190    const buildNode = (node) => {
17191      this._currentNode = node;
17192      if (node.isVarNode && node.isIntent(builder)) {
17193        if (node.isAssign(builder) !== true) {
17194          return;
17195        }
17196      }
17197      if (buildStage === "setup") {
17198        node.build(builder);
17199      } else if (buildStage === "analyze") {
17200        node.build(builder, this);
17201      } else if (buildStage === "generate") {
17202        const stages = builder.getDataFromNode(node, "any").stages;
17203        const parents = stages && stages[builder.shaderStage];
17204        if (node.isVarNode && parents && parents.length === 1 && parents[0] && parents[0].isStackNode) {
17205          return;
17206        }
17207        node.build(builder, "void");
17208      }
17209    };
17210    const nodes = [...this.nodes];
17211    for (const node of nodes) {
17212      buildNode(node);
17213    }
17214    this._currentNode = null;
17215    const newNodes = this.nodes.filter((node) => nodes.indexOf(node) === -1);
17216    for (const node of newNodes) {
17217      buildNode(node);
17218    }
17219    let result;
17220    if (this.hasOutput(builder)) {
17221      result = this.outputNode.build(builder, ...params);
17222    } else {
17223      result = super.build(builder, ...params);
17224    }
17225    setCurrentStack(previousStack);
17226    builder.removeActiveStack(this);
17227    return result;
17228  }
17229};
17230var stack = /* @__PURE__ */ nodeProxy(StackNode).setParameterLength(0, 1);
17231function getMembersLayout(members) {
17232  return Object.entries(members).map(([name, value]) => {
17233    if (typeof value === "string") {
17234      return { name, type: value, atomic: false };
17235    }
17236    return { name, type: value.type, atomic: value.atomic || false };
17237  });
17238}
17239var StructTypeNode = class extends Node2 {
17240  static get type() {
17241    return "StructTypeNode";
17242  }
17243  /**
17244   * Creates an instance of StructTypeNode.
17245   *
17246   * @param {Object} membersLayout - The layout of the members for the struct.
17247   * @param {?string} [name=null] - The optional name of the struct.
17248   */
17249  constructor(membersLayout, name = null) {
17250    super("struct");
17251    this.membersLayout = getMembersLayout(membersLayout);
17252    this.name = name;
17253    this.isStructLayoutNode = true;
17254  }
17255  /**
17256   * Returns the length of the struct.
17257   * The length is calculated by summing the lengths of the struct's members.
17258   *
17259   * @returns {number} The length of the struct.
17260   */
17261  getLength() {
17262    const BYTES_PER_ELEMENT = Float32Array.BYTES_PER_ELEMENT;
17263    let maxAlignment = 1;
17264    let offset3 = 0;
17265    for (const member of this.membersLayout) {
17266      const type = member.type;
17267      const itemSize = getMemoryLengthFromType(type);
17268      const alignment = getAlignmentFromType(type) / BYTES_PER_ELEMENT;
17269      maxAlignment = Math.max(maxAlignment, alignment);
17270      const chunkOffset = offset3 % maxAlignment;
17271      const overhang = chunkOffset % alignment;
17272      if (overhang !== 0) {
17273        offset3 += alignment - overhang;
17274      }
17275      offset3 += itemSize;
17276    }
17277    return Math.ceil(offset3 / maxAlignment) * maxAlignment;
17278  }
17279  getMemberType(builder, name) {
17280    const member = this.membersLayout.find((m) => m.name === name);
17281    return member ? member.type : "void";
17282  }
17283  generateNodeType(builder) {
17284    const structType = builder.getStructTypeFromNode(this, this.membersLayout, this.name);
17285    return structType.name;
17286  }
17287  setup(builder) {
17288    builder.getStructTypeFromNode(this, this.membersLayout, this.name);
17289    builder.addInclude(this);
17290  }
17291  generate(builder) {
17292    return this.getNodeType(builder);
17293  }
17294};
17295var StructNode = class extends Node2 {
17296  static get type() {
17297    return "StructNode";
17298  }
17299  constructor(structTypeNode, values) {
17300    super("vec3");
17301    this.structTypeNode = structTypeNode;
17302    this.values = values;
17303    this.isStructNode = true;
17304  }
17305  generateNodeType(builder) {
17306    return this.structTypeNode.getNodeType(builder);
17307  }
17308  getMemberType(builder, name) {
17309    return this.structTypeNode.getMemberType(builder, name);
17310  }
17311  _getChildren() {
17312    const children2 = super._getChildren();
17313    const structTypeProperty = children2.find((child) => child.childNode === this.structTypeNode);
17314    children2.splice(children2.indexOf(structTypeProperty), 1);
17315    children2.push(structTypeProperty);
17316    return children2;
17317  }
17318  generate(builder) {
17319    const nodeVar = builder.getVarFromNode(this);
17320    const structType = nodeVar.type;
17321    const propertyName = builder.getPropertyName(nodeVar);
17322    builder.addLineFlowCode(`${propertyName} = ${builder.generateStruct(structType, this.structTypeNode.membersLayout, this.values)}`, this);
17323    return nodeVar.name;
17324  }
17325};
17326var struct = (membersLayout, name = null) => {
17327  const structLayout = new StructTypeNode(membersLayout, name);
17328  const struct3 = (...params) => {
17329    let values = null;
17330    if (params.length > 0) {
17331      if (params[0].isNode) {
17332        values = {};
17333        const names = Object.keys(membersLayout);
17334        for (let i = 0; i < params.length; i++) {
17335          values[names[i]] = params[i];
17336        }
17337      } else {
17338        values = params[0];
17339      }
17340    }
17341    return new StructNode(structLayout, values);
17342  };
17343  struct3.layout = structLayout;
17344  struct3.isStruct = true;
17345  return struct3;
17346};
17347var OutputStructNode = class extends Node2 {
17348  static get type() {
17349    return "OutputStructNode";
17350  }
17351  /**
17352   * Constructs a new output struct node. The constructor can be invoked with an
17353   * arbitrary number of nodes representing the members.
17354   *
17355   * @param {...Node} members - A parameter list of nodes.
17356   */
17357  constructor(...members) {
17358    super();
17359    this.members = members;
17360    this.isOutputStructNode = true;
17361  }
17362  generateNodeType() {
17363    return "OutputType";
17364  }
17365  generate(builder) {
17366    const nodeData = builder.getDataFromNode(this);
17367    if (nodeData.membersLayout === void 0) {
17368      const members2 = this.members;
17369      const membersLayout = [];
17370      for (let i = 0; i < members2.length; i++) {
17371        const name = "m" + i;
17372        const type = members2[i].getNodeType(builder);
17373        membersLayout.push({ name, type, index: i });
17374      }
17375      nodeData.membersLayout = membersLayout;
17376      nodeData.structType = builder.getOutputStructTypeFromNode(this, nodeData.membersLayout);
17377    }
17378    const propertyName = builder.getOutputStructName();
17379    const members = this.members;
17380    const structPrefix = propertyName !== "" ? propertyName + "." : "";
17381    for (let i = 0; i < members.length; i++) {
17382      const snippet = members[i].build(builder);
17383      builder.addLineFlowCode(`${structPrefix}m${i} = ${snippet}`, this);
17384    }
17385    return propertyName;
17386  }
17387};
17388var outputStruct = /* @__PURE__ */ nodeProxy(OutputStructNode);
17389var BlendMode = class {
17390  /**
17391   * Constructs a new blending configuration.
17392   *
17393   * @param {(NoBlending|NormalBlending|AdditiveBlending|SubtractiveBlending|MultiplyBlending|CustomBlending|MaterialBlending)} [blending=NormalBlending] - The blending mode.
17394   */
17395  constructor(blending = NormalBlending) {
17396    this.blending = blending;
17397    this.blendSrc = SrcAlphaFactor;
17398    this.blendDst = OneMinusSrcAlphaFactor;
17399    this.blendEquation = AddEquation;
17400    this.blendSrcAlpha = null;
17401    this.blendDstAlpha = null;
17402    this.blendEquationAlpha = null;
17403    this.premultiplyAlpha = false;
17404  }
17405  /**
17406   * Copies the blending properties from the given source to this instance.
17407   *
17408   * @param {BlendMode} source - The blending configuration to copy from.
17409   * @return {BlendMode} A reference to this instance.
17410   */
17411  copy(source) {
17412    this.blending = source.blending;
17413    this.blendSrc = source.blendSrc;
17414    this.blendDst = source.blendDst;
17415    this.blendEquation = source.blendEquation;
17416    this.blendSrcAlpha = source.blendSrcAlpha;
17417    this.blendDstAlpha = source.blendDstAlpha;
17418    this.blendEquationAlpha = source.blendEquationAlpha;
17419    this.premultiplyAlpha = source.premultiplyAlpha;
17420    return this;
17421  }
17422  /**
17423   * Returns a clone of this blending configuration.
17424   *
17425   * @return {BlendMode} A new Blending instance with the same properties.
17426   */
17427  clone() {
17428    return new this.constructor().copy(this);
17429  }
17430};
17431var _noBlending = /* @__PURE__ */ new BlendMode(NoBlending);
17432var _materialBlending = /* @__PURE__ */ new BlendMode(MaterialBlending);
17433function getTextureIndex(textures, name) {
17434  for (let i = 0; i < textures.length; i++) {
17435    if (textures[i].name === name) {
17436      return i;
17437    }
17438  }
17439  return -1;
17440}
17441var MRTNode = class extends OutputStructNode {
17442  static get type() {
17443    return "MRTNode";
17444  }
17445  /**
17446   * Constructs a new output struct node.
17447   *
17448   * @param {Object<string, Node>} outputNodes - The MRT outputs.
17449   */
17450  constructor(outputNodes) {
17451    super();
17452    this.outputNodes = outputNodes;
17453    this.blendModes = {
17454      output: _materialBlending
17455    };
17456    this.isMRTNode = true;
17457  }
17458  /**
17459   * Sets the blend mode for the given output name.
17460   *
17461   * @param {string} name - The name of the output.
17462   * @param {BlendMode} blend - The blending mode.
17463   * @return {MRTNode} The current MRT node.
17464   */
17465  setBlendMode(name, blend) {
17466    this.blendModes[name] = blend;
17467    return this;
17468  }
17469  /**
17470   * Returns the blend mode for the given output name.
17471   *
17472   * @param {string} name - The name of the output.
17473   * @return {BlendMode} The blend mode.
17474   */
17475  getBlendMode(name) {
17476    return this.blendModes[name] || _noBlending;
17477  }
17478  /**
17479   * Returns `true` if the MRT node has an output with the given name.
17480   *
17481   * @param {string} name - The name of the output.
17482   * @return {NodeBuilder} Whether the MRT node has an output for the given name or not.
17483   */
17484  has(name) {
17485    return this.outputNodes[name] !== void 0;
17486  }
17487  /**
17488   * Returns the output node for the given name.
17489   *
17490   * @param {string} name - The name of the output.
17491   * @return {Node} The output node.
17492   */
17493  get(name) {
17494    return this.outputNodes[name];
17495  }
17496  /**
17497   * Merges the outputs of the given MRT node with the outputs of this node.
17498   *
17499   * @param {MRTNode} mrtNode - The MRT to merge.
17500   * @return {MRTNode} A new MRT node with merged outputs..
17501   */
17502  merge(mrtNode) {
17503    const outputs = { ...this.outputNodes, ...mrtNode.outputNodes };
17504    const blendings = { ...this.blendModes, ...mrtNode.blendModes };
17505    const mrtTarget = mrt(outputs);
17506    mrtTarget.blendings = blendings;
17507    return mrtTarget;
17508  }
17509  setup(builder) {
17510    const outputNodes = this.outputNodes;
17511    const mrt3 = builder.renderer.getRenderTarget();
17512    const members = [];
17513    const textures = mrt3.textures;
17514    for (const name in outputNodes) {
17515      const index = getTextureIndex(textures, name);
17516      members[index] = vec4(outputNodes[name]);
17517    }
17518    this.members = members;
17519    return super.setup(builder);
17520  }
17521};
17522var mrt = /* @__PURE__ */ nodeProxy(MRTNode);
17523var BitcastNode = class extends TempNode {
17524  static get type() {
17525    return "BitcastNode";
17526  }
17527  /**
17528   * Constructs a new bitcast node.
17529   *
17530   * @param {Node} valueNode - The value to convert.
17531   * @param {string} conversionType - The type to convert to.
17532   * @param {?string} [inputType = null] - The expected input data type of the bitcast operation.
17533   */
17534  constructor(valueNode, conversionType, inputType = null) {
17535    super();
17536    this.valueNode = valueNode;
17537    this.conversionType = conversionType;
17538    this.inputType = inputType;
17539    this.isBitcastNode = true;
17540  }
17541  generateNodeType(builder) {
17542    if (this.inputType !== null) {
17543      const valueType = this.valueNode.getNodeType(builder);
17544      const valueLength = builder.getTypeLength(valueType);
17545      return builder.getTypeFromLength(valueLength, this.conversionType);
17546    }
17547    return this.conversionType;
17548  }
17549  generate(builder) {
17550    const type = this.getNodeType(builder);
17551    let inputType = "";
17552    if (this.inputType !== null) {
17553      const valueType = this.valueNode.getNodeType(builder);
17554      const valueTypeLength = builder.getTypeLength(valueType);
17555      inputType = valueTypeLength === 1 ? this.inputType : builder.changeComponentType(valueType, this.inputType);
17556    } else {
17557      inputType = this.valueNode.getNodeType(builder);
17558    }
17559    return `${builder.getBitcastMethod(type, inputType)}( ${this.valueNode.build(builder, inputType)} )`;
17560  }
17561};
17562var bitcast = /* @__PURE__ */ nodeProxyIntent(BitcastNode).setParameterLength(2);
17563var floatBitsToInt = (value) => new BitcastNode(value, "int", "float");
17564var floatBitsToUint = (value) => new BitcastNode(value, "uint", "float");
17565var intBitsToFloat = (value) => new BitcastNode(value, "float", "int");
17566var uintBitsToFloat = (value) => new BitcastNode(value, "float", "uint");
17567var registeredBitcountFunctions = {};
17568var BitcountNode = class _BitcountNode extends MathNode {
17569  static get type() {
17570    return "BitcountNode";
17571  }
17572  /**
17573   * Constructs a new math node.
17574   *
17575   * @param {'countTrailingZeros'|'countLeadingZeros'|'countOneBits'} method - The method name.
17576   * @param {Node} aNode - The first input.
17577   */
17578  constructor(method, aNode) {
17579    super(method, aNode);
17580    this.isBitcountNode = true;
17581  }
17582  /**
17583   * Casts the input value of the function to an integer if necessary.
17584   *
17585   * @private
17586   * @param {Node<uint>|Node<int>} inputNode - The input value.
17587   * @param {Node<uint>} outputNode - The output value.
17588   * @param {string} elementType - The type of the input value.
17589   */
17590  _resolveElementType(inputNode, outputNode, elementType) {
17591    if (elementType === "int") {
17592      outputNode.assign(bitcast(inputNode, "uint"));
17593    } else {
17594      outputNode.assign(inputNode);
17595    }
17596  }
17597  _returnDataNode(inputType) {
17598    switch (inputType) {
17599      case "uint": {
17600        return uint;
17601      }
17602      case "int": {
17603        return int;
17604      }
17605      case "uvec2": {
17606        return uvec2;
17607      }
17608      case "uvec3": {
17609        return uvec3;
17610      }
17611      case "uvec4": {
17612        return uvec4;
17613      }
17614      case "ivec2": {
17615        return ivec2;
17616      }
17617      case "ivec3": {
17618        return ivec3;
17619      }
17620      case "ivec4": {
17621        return ivec4;
17622      }
17623    }
17624  }
17625  /**
17626   * Creates and registers a reusable GLSL function that emulates the behavior of countTrailingZeros.
17627   *
17628   * @private
17629   * @param {string} method - The name of the function to create.
17630   * @param {string} elementType - The type of the input value.
17631   * @returns {Function} - The generated function
17632   */
17633  _createTrailingZerosBaseLayout(method, elementType) {
17634    const outputConvertNode = this._returnDataNode(elementType);
17635    const fnDef = Fn(([value]) => {
17636      const v = uint(0);
17637      this._resolveElementType(value, v, elementType);
17638      const f = float(v.bitAnd(negate(v)));
17639      const uintBits = floatBitsToUint(f);
17640      const numTrailingZeros = uintBits.shiftRight(23).sub(127);
17641      return outputConvertNode(numTrailingZeros);
17642    }).setLayout({
17643      name: method,
17644      type: elementType,
17645      inputs: [
17646        { name: "value", type: elementType }
17647      ]
17648    });
17649    return fnDef;
17650  }
17651  /**
17652   * Creates and registers a reusable GLSL function that emulates the behavior of countLeadingZeros.
17653   *
17654   * @private
17655   * @param {string} method - The name of the function to create.
17656   * @param {string} elementType - The type of the input value.
17657   * @returns {Function} - The generated function
17658   */
17659  _createLeadingZerosBaseLayout(method, elementType) {
17660    const outputConvertNode = this._returnDataNode(elementType);
17661    const fnDef = Fn(([value]) => {
17662      If(value.equal(uint(0)), () => {
17663        return uint(32);
17664      });
17665      const v = uint(0);
17666      const n = uint(0);
17667      this._resolveElementType(value, v, elementType);
17668      If(v.shiftRight(16).equal(0), () => {
17669        n.addAssign(16);
17670        v.shiftLeftAssign(16);
17671      });
17672      If(v.shiftRight(24).equal(0), () => {
17673        n.addAssign(8);
17674        v.shiftLeftAssign(8);
17675      });
17676      If(v.shiftRight(28).equal(0), () => {
17677        n.addAssign(4);
17678        v.shiftLeftAssign(4);
17679      });
17680      If(v.shiftRight(30).equal(0), () => {
17681        n.addAssign(2);
17682        v.shiftLeftAssign(2);
17683      });
17684      If(v.shiftRight(31).equal(0), () => {
17685        n.addAssign(1);
17686      });
17687      return outputConvertNode(n);
17688    }).setLayout({
17689      name: method,
17690      type: elementType,
17691      inputs: [
17692        { name: "value", type: elementType }
17693      ]
17694    });
17695    return fnDef;
17696  }
17697  /**
17698   * Creates and registers a reusable GLSL function that emulates the behavior of countOneBits.
17699   *
17700   * @private
17701   * @param {string} method - The name of the function to create.
17702   * @param {string} elementType - The type of the input value.
17703   * @returns {Function} - The generated function
17704   */
17705  _createOneBitsBaseLayout(method, elementType) {
17706    const outputConvertNode = this._returnDataNode(elementType);
17707    const fnDef = Fn(([value]) => {
17708      const v = uint(0);
17709      this._resolveElementType(value, v, elementType);
17710      v.assign(v.sub(v.shiftRight(uint(1)).bitAnd(uint(1431655765))));
17711      v.assign(v.bitAnd(uint(858993459)).add(v.shiftRight(uint(2)).bitAnd(uint(858993459))));
17712      const numBits = v.add(v.shiftRight(uint(4))).bitAnd(uint(252645135)).mul(uint(16843009)).shiftRight(uint(24));
17713      return outputConvertNode(numBits);
17714    }).setLayout({
17715      name: method,
17716      type: elementType,
17717      inputs: [
17718        { name: "value", type: elementType }
17719      ]
17720    });
17721    return fnDef;
17722  }
17723  /**
17724   * Creates and registers a reusable GLSL function that emulates the behavior of the specified bitcount function.
17725   * including considerations for component-wise bitcounts on vector type inputs.
17726   *
17727   * @private
17728   * @param {string} method - The name of the function to create.
17729   * @param {string} inputType - The type of the input value.
17730   * @param {number} typeLength - The vec length of the input value.
17731   * @param {Function} baseFn - The base function that operates on an individual component of the vector.
17732   * @returns {Function} - The alias function for the specified bitcount method.
17733   */
17734  _createMainLayout(method, inputType, typeLength, baseFn) {
17735    const outputConvertNode = this._returnDataNode(inputType);
17736    const fnDef = Fn(([value]) => {
17737      if (typeLength === 1) {
17738        return outputConvertNode(baseFn(value));
17739      } else {
17740        const vec = outputConvertNode(0);
17741        const components = ["x", "y", "z", "w"];
17742        for (let i = 0; i < typeLength; i++) {
17743          const component = components[i];
17744          vec[component].assign(baseFn(value[component]));
17745        }
17746        return vec;
17747      }
17748    }).setLayout({
17749      name: method,
17750      type: inputType,
17751      inputs: [
17752        { name: "value", type: inputType }
17753      ]
17754    });
17755    return fnDef;
17756  }
17757  setup(builder) {
17758    const { method, aNode } = this;
17759    const { renderer } = builder;
17760    if (renderer.backend.isWebGPUBackend) {
17761      return super.setup(builder);
17762    }
17763    const inputType = this.getInputType(builder);
17764    const elementType = builder.getElementType(inputType);
17765    const typeLength = builder.getTypeLength(inputType);
17766    const baseMethod = `${method}_base_${elementType}`;
17767    const newMethod = `${method}_${inputType}`;
17768    let baseFn = registeredBitcountFunctions[baseMethod];
17769    if (baseFn === void 0) {
17770      switch (method) {
17771        case _BitcountNode.COUNT_LEADING_ZEROS: {
17772          baseFn = this._createLeadingZerosBaseLayout(baseMethod, elementType);
17773          break;
17774        }
17775        case _BitcountNode.COUNT_TRAILING_ZEROS: {
17776          baseFn = this._createTrailingZerosBaseLayout(baseMethod, elementType);
17777          break;
17778        }
17779        case _BitcountNode.COUNT_ONE_BITS: {
17780          baseFn = this._createOneBitsBaseLayout(baseMethod, elementType);
17781          break;
17782        }
17783      }
17784      registeredBitcountFunctions[baseMethod] = baseFn;
17785    }
17786    let fn = registeredBitcountFunctions[newMethod];
17787    if (fn === void 0) {
17788      fn = this._createMainLayout(newMethod, inputType, typeLength, baseFn);
17789      registeredBitcountFunctions[newMethod] = fn;
17790    }
17791    const output3 = Fn(() => {
17792      return fn(
17793        aNode
17794      );
17795    });
17796    return output3();
17797  }
17798};
17799BitcountNode.COUNT_TRAILING_ZEROS = "countTrailingZeros";
17800BitcountNode.COUNT_LEADING_ZEROS = "countLeadingZeros";
17801BitcountNode.COUNT_ONE_BITS = "countOneBits";
17802var countTrailingZeros = /* @__PURE__ */ nodeProxyIntent(BitcountNode, BitcountNode.COUNT_TRAILING_ZEROS).setParameterLength(1);
17803var countLeadingZeros = /* @__PURE__ */ nodeProxyIntent(BitcountNode, BitcountNode.COUNT_LEADING_ZEROS).setParameterLength(1);
17804var countOneBits = /* @__PURE__ */ nodeProxyIntent(BitcountNode, BitcountNode.COUNT_ONE_BITS).setParameterLength(1);
17805var hash = /* @__PURE__ */ Fn(([seed]) => {
17806  const state = seed.toUint().mul(747796405).add(2891336453);
17807  const word = state.shiftRight(state.shiftRight(28).add(4)).bitXor(state).mul(277803737);
17808  const result = word.shiftRight(22).bitXor(word);
17809  return result.toFloat().mul(1 / 2 ** 32);
17810});
17811var parabola = (x, k) => pow(mul(4, x.mul(sub(1, x))), k);
17812var gain = (x, k) => x.lessThan(0.5) ? parabola(x.mul(2), k).div(2) : sub(1, parabola(mul(sub(1, x), 2), k).div(2));
17813var pcurve = (x, a, b) => pow(div(pow(x, a), add(pow(x, a), pow(sub(1, x), b))), 1 / a);
17814var sinc = (x, k) => sin(PI.mul(k.mul(x).sub(1))).div(PI.mul(k.mul(x).sub(1)));
17815var PackFloatNode = class extends TempNode {
17816  static get type() {
17817    return "PackFloatNode";
17818  }
17819  /**
17820   *
17821   * @param {'snorm' | 'unorm' | 'float16'} encoding - The numeric encoding that describes how the float values are mapped to the integer range.
17822   * @param {Node} vectorNode - The vector node to be packed
17823   */
17824  constructor(encoding, vectorNode) {
17825    super();
17826    this.vectorNode = vectorNode;
17827    this.encoding = encoding;
17828    this.isPackFloatNode = true;
17829  }
17830  generateNodeType() {
17831    return "uint";
17832  }
17833  generate(builder) {
17834    const inputType = this.vectorNode.getNodeType(builder);
17835    return `${builder.getFloatPackingMethod(this.encoding)}(${this.vectorNode.build(builder, inputType)})`;
17836  }
17837};
17838var packSnorm2x16 = /* @__PURE__ */ nodeProxyIntent(PackFloatNode, "snorm").setParameterLength(1);
17839var packUnorm2x16 = /* @__PURE__ */ nodeProxyIntent(PackFloatNode, "unorm").setParameterLength(1);
17840var packHalf2x16 = /* @__PURE__ */ nodeProxyIntent(PackFloatNode, "float16").setParameterLength(1);
17841var UnpackFloatNode = class extends TempNode {
17842  static get type() {
17843    return "UnpackFloatNode";
17844  }
17845  /**
17846   *
17847   * @param {'snorm' | 'unorm' | 'float16'} encoding - The numeric encoding that describes how the integer values are mapped to the float range
17848   * @param {Node} uintNode - The uint node to be unpacked
17849   */
17850  constructor(encoding, uintNode) {
17851    super();
17852    this.uintNode = uintNode;
17853    this.encoding = encoding;
17854    this.isUnpackFloatNode = true;
17855  }
17856  generateNodeType() {
17857    return "vec2";
17858  }
17859  generate(builder) {
17860    const inputType = this.uintNode.getNodeType(builder);
17861    return `${builder.getFloatUnpackingMethod(this.encoding)}(${this.uintNode.build(builder, inputType)})`;
17862  }
17863};
17864var unpackSnorm2x16 = /* @__PURE__ */ nodeProxyIntent(UnpackFloatNode, "snorm").setParameterLength(1);
17865var unpackUnorm2x16 = /* @__PURE__ */ nodeProxyIntent(UnpackFloatNode, "unorm").setParameterLength(1);
17866var unpackHalf2x16 = /* @__PURE__ */ nodeProxyIntent(UnpackFloatNode, "float16").setParameterLength(1);
17867var tri = /* @__PURE__ */ Fn(([x]) => {
17868  return x.fract().sub(0.5).abs();
17869}).setLayout({
17870  name: "tri",
17871  type: "float",
17872  inputs: [
17873    { name: "x", type: "float" }
17874  ]
17875});
17876var tri3 = /* @__PURE__ */ Fn(([p]) => {
17877  return vec3(tri(p.z.add(tri(p.y.mul(1)))), tri(p.z.add(tri(p.x.mul(1)))), tri(p.y.add(tri(p.x.mul(1)))));
17878}).setLayout({
17879  name: "tri3",
17880  type: "vec3",
17881  inputs: [
17882    { name: "p", type: "vec3" }
17883  ]
17884});
17885var triNoise3D = /* @__PURE__ */ Fn(([position, speed, time3]) => {
17886  const p = vec3(position).toVar();
17887  const z = float(1.4).toVar();
17888  const rz = float(0).toVar();
17889  const bp = vec3(p).toVar();
17890  Loop({ start: float(0), end: float(3), type: "float", condition: "<=" }, () => {
17891    const dg = vec3(tri3(bp.mul(2))).toVar();
17892    p.addAssign(dg.add(time3.mul(float(0.1).mul(speed))));
17893    bp.mulAssign(1.8);
17894    z.mulAssign(1.5);
17895    p.mulAssign(1.2);
17896    const t = float(tri(p.z.add(tri(p.x.add(tri(p.y)))))).toVar();
17897    rz.addAssign(t.div(z));
17898    bp.addAssign(0.14);
17899  });
17900  return rz;
17901}).setLayout({
17902  name: "triNoise3D",
17903  type: "float",
17904  inputs: [
17905    { name: "position", type: "vec3" },
17906    { name: "speed", type: "float" },
17907    { name: "time", type: "float" }
17908  ]
17909});
17910var FunctionOverloadingNode = class extends Node2 {
17911  static get type() {
17912    return "FunctionOverloadingNode";
17913  }
17914  /**
17915   * Constructs a new function overloading node.
17916   *
17917   * @param {Array<Function>} functionNodes - Array of `Fn` function definitions.
17918   * @param {...Node} parametersNodes - A list of parameter nodes.
17919   */
17920  constructor(functionNodes = [], ...parametersNodes) {
17921    super();
17922    this.functionNodes = functionNodes;
17923    this.parametersNodes = parametersNodes;
17924    this._candidateFn = null;
17925    this.global = true;
17926  }
17927  /**
17928   * This method is overwritten since the node type is inferred from
17929   * the function's return type.
17930   *
17931   * @param {NodeBuilder} builder - The current node builder.
17932   * @return {string} The node type.
17933   */
17934  generateNodeType(builder) {
17935    const candidateFn = this.getCandidateFn(builder);
17936    return candidateFn.shaderNode.layout.type;
17937  }
17938  /**
17939   * Returns the candidate function for the current parameters.
17940   *
17941   * @param {NodeBuilder} builder - The current node builder.
17942   * @return {FunctionNode} The candidate function.
17943   */
17944  getCandidateFn(builder) {
17945    const params = this.parametersNodes;
17946    let candidateFn = this._candidateFn;
17947    if (candidateFn === null) {
17948      let bestCandidateFn = null;
17949      let bestScore = -1;
17950      for (const functionNode of this.functionNodes) {
17951        const shaderNode = functionNode.shaderNode;
17952        const layout = shaderNode.layout;
17953        if (layout === null) {
17954          throw new Error("FunctionOverloadingNode: FunctionNode must be a layout.");
17955        }
17956        const inputs = layout.inputs;
17957        if (params.length === inputs.length) {
17958          let currentScore = 0;
17959          for (let i = 0; i < params.length; i++) {
17960            const param = params[i];
17961            const input = inputs[i];
17962            if (param.getNodeType(builder) === input.type) {
17963              currentScore++;
17964            }
17965          }
17966          if (currentScore > bestScore) {
17967            bestCandidateFn = functionNode;
17968            bestScore = currentScore;
17969          }
17970        }
17971      }
17972      this._candidateFn = candidateFn = bestCandidateFn;
17973    }
17974    return candidateFn;
17975  }
17976  /**
17977   * Sets up the node for the current parameters.
17978   *
17979   * @param {NodeBuilder} builder - The current node builder.
17980   * @return {Node} The setup node.
17981   */
17982  setup(builder) {
17983    const candidateFn = this.getCandidateFn(builder);
17984    return candidateFn(...this.parametersNodes);
17985  }
17986};
17987var overloadingBaseFn = /* @__PURE__ */ nodeProxy(FunctionOverloadingNode);
17988var overloadingFn = (functionNodes) => (...params) => overloadingBaseFn(functionNodes, ...params);
17989var time = /* @__PURE__ */ uniform(0).setGroup(renderGroup).onRenderUpdate((frame) => frame.time);
17990var deltaTime = /* @__PURE__ */ uniform(0).setGroup(renderGroup).onRenderUpdate((frame) => frame.deltaTime);
17991var frameId = /* @__PURE__ */ uniform(0, "uint").setGroup(renderGroup).onRenderUpdate((frame) => frame.frameId);
17992var oscSine = (t = time) => t.add(0.75).mul(Math.PI * 2).sin().mul(0.5).add(0.5);
17993var oscSquare = (t = time) => t.fract().round();
17994var oscTriangle = (t = time) => t.add(0.5).fract().mul(2).sub(1).abs();
17995var oscSawtooth = (t = time) => t.fract();
17996function replaceDefaultUV(callback, node = null) {
17997  const getUV2 = typeof callback === "function" ? callback : () => callback;
17998  return context(node, { getUV: getUV2 });
17999}
18000var rotateUV = /* @__PURE__ */ Fn(([uv3, rotation, center = vec2(0.5)]) => {
18001  return rotate(uv3.sub(center), rotation).add(center);
18002});
18003var spherizeUV = /* @__PURE__ */ Fn(([uv3, strength, center = vec2(0.5)]) => {
18004  const delta = uv3.sub(center);
18005  const delta2 = delta.dot(delta);
18006  const delta4 = delta2.mul(delta2);
18007  const deltaOffset = delta4.mul(strength);
18008  return uv3.add(delta.mul(deltaOffset));
18009});
18010var billboarding = /* @__PURE__ */ Fn(({ position = null, horizontal = true, vertical = false }) => {
18011  let worldMatrix;
18012  if (position !== null) {
18013    worldMatrix = modelWorldMatrix.toVar();
18014    worldMatrix[3][0] = position.x;
18015    worldMatrix[3][1] = position.y;
18016    worldMatrix[3][2] = position.z;
18017  } else {
18018    worldMatrix = modelWorldMatrix;
18019  }
18020  const modelViewMatrix3 = cameraViewMatrix.mul(worldMatrix);
18021  if (defined(horizontal)) {
18022    modelViewMatrix3[0][0] = modelWorldMatrix[0].length();
18023    modelViewMatrix3[0][1] = 0;
18024    modelViewMatrix3[0][2] = 0;
18025  }
18026  if (defined(vertical)) {
18027    modelViewMatrix3[1][0] = 0;
18028    modelViewMatrix3[1][1] = modelWorldMatrix[1].length();
18029    modelViewMatrix3[1][2] = 0;
18030  }
18031  modelViewMatrix3[2][0] = 0;
18032  modelViewMatrix3[2][1] = 0;
18033  modelViewMatrix3[2][2] = 1;
18034  return cameraProjectionMatrix.mul(modelViewMatrix3).mul(positionLocal);
18035});
18036var viewportSafeUV = /* @__PURE__ */ Fn(([uv3 = null]) => {
18037  const depth3 = linearDepth();
18038  const depthDiff = linearDepth(viewportDepthTexture(uv3)).sub(depth3);
18039  const finalUV = depthDiff.lessThan(0).select(screenUV, uv3);
18040  return finalUV;
18041});
18042var spritesheetUV = /* @__PURE__ */ Fn(([countNode, uvNode = uv$1(), frameNode = float(0)]) => {
18043  const width = countNode.x;
18044  const height = countNode.y;
18045  const frameNum = frameNode.mod(width.mul(height)).floor();
18046  const column = frameNum.mod(width);
18047  const row = height.sub(frameNum.add(1).div(width).ceil());
18048  const scale2 = countNode.reciprocal();
18049  const uvFrameOffset = vec2(column, row);
18050  return uvNode.add(uvFrameOffset).mul(scale2);
18051});
18052var triplanarTextures = /* @__PURE__ */ Fn(([textureXNode, textureYNode = null, textureZNode = null, scaleNode = float(1), positionNode = positionLocal, normalNode = normalLocal]) => {
18053  let bf = normalNode.abs().normalize();
18054  bf = bf.div(bf.dot(vec3(1)));
18055  const tx = positionNode.yz.mul(scaleNode);
18056  const ty = positionNode.zx.mul(scaleNode);
18057  const tz = positionNode.xy.mul(scaleNode);
18058  const textureX = textureXNode.value;
18059  const textureY = textureYNode !== null ? textureYNode.value : textureX;
18060  const textureZ = textureZNode !== null ? textureZNode.value : textureX;
18061  const cx = texture(textureX, tx).mul(bf.x);
18062  const cy = texture(textureY, ty).mul(bf.y);
18063  const cz = texture(textureZ, tz).mul(bf.z);
18064  return add(cx, cy, cz);
18065});
18066var triplanarTexture = (...params) => triplanarTextures(...params);
18067var _reflectorPlane = new Plane();
18068var _normal = new Vector3();
18069var _reflectorWorldPosition = new Vector3();
18070var _cameraWorldPosition = new Vector3();
18071var _rotationMatrix = new Matrix4();
18072var _lookAtPosition = new Vector3(0, 0, -1);
18073var clipPlane = new Vector4();
18074var _view = new Vector3();
18075var _target = new Vector3();
18076var _q = new Vector4();
18077var _size$2 = new Vector2();
18078var _defaultRT = new RenderTarget();
18079var _defaultUV = screenUV.flipX();
18080_defaultRT.depthTexture = new DepthTexture(1, 1);
18081var _inReflector = false;
18082var ReflectorNode = class _ReflectorNode extends TextureNode {
18083  static get type() {
18084    return "ReflectorNode";
18085  }
18086  /**
18087   * Constructs a new reflector node.
18088   *
18089   * @param {Object} [parameters={}] - An object holding configuration parameters.
18090   * @param {Object3D} [parameters.target=new Object3D()] - The 3D object the reflector is linked to.
18091   * @param {number} [parameters.resolutionScale=1] - The resolution scale.
18092   * @param {boolean} [parameters.generateMipmaps=false] - Whether mipmaps should be generated or not.
18093   * @param {boolean} [parameters.bounces=true] - Whether reflectors can render other reflector nodes or not.
18094   * @param {boolean} [parameters.depth=false] - Whether depth data should be generated or not.
18095   * @param {number} [parameters.samples] - Anti-Aliasing samples of the internal render-target.
18096   * @param {TextureNode} [parameters.defaultTexture] - The default texture node.
18097   * @param {ReflectorBaseNode} [parameters.reflector] - The reflector base node.
18098   */
18099  constructor(parameters = {}) {
18100    super(parameters.defaultTexture || _defaultRT.texture, _defaultUV);
18101    this._reflectorBaseNode = parameters.reflector || new ReflectorBaseNode(this, parameters);
18102    this._depthNode = null;
18103    this.setUpdateMatrix(false);
18104  }
18105  /**
18106   * A reference to the internal reflector node.
18107   *
18108   * @type {ReflectorBaseNode}
18109   */
18110  get reflector() {
18111    return this._reflectorBaseNode;
18112  }
18113  /**
18114   * A reference to 3D object the reflector is linked to.
18115   *
18116   * @type {Object3D}
18117   */
18118  get target() {
18119    return this._reflectorBaseNode.target;
18120  }
18121  /**
18122   * Returns a node representing the mirror's depth. That can be used
18123   * to implement more advanced reflection effects like distance attenuation.
18124   *
18125   * @return {Node} The depth node.
18126   */
18127  getDepthNode() {
18128    if (this._depthNode === null) {
18129      if (this._reflectorBaseNode.depth !== true) {
18130        throw new Error("THREE.ReflectorNode: Depth node can only be requested when the reflector is created with { depth: true }. ");
18131      }
18132      this._depthNode = new _ReflectorNode({
18133        defaultTexture: _defaultRT.depthTexture,
18134        reflector: this._reflectorBaseNode
18135      });
18136    }
18137    return this._depthNode;
18138  }
18139  setup(builder) {
18140    if (!builder.object.isQuadMesh) this._reflectorBaseNode.build(builder);
18141    return super.setup(builder);
18142  }
18143  clone() {
18144    const newNode = new this.constructor(this.reflectorNode);
18145    newNode.uvNode = this.uvNode;
18146    newNode.levelNode = this.levelNode;
18147    newNode.biasNode = this.biasNode;
18148    newNode.sampler = this.sampler;
18149    newNode.depthNode = this.depthNode;
18150    newNode.compareNode = this.compareNode;
18151    newNode.gradNode = this.gradNode;
18152    newNode.offsetNode = this.offsetNode;
18153    newNode._reflectorBaseNode = this._reflectorBaseNode;
18154    return newNode;
18155  }
18156  /**
18157   * Frees internal resources. Should be called when the node is no longer in use.
18158   */
18159  dispose() {
18160    super.dispose();
18161    this._reflectorBaseNode.dispose();
18162  }
18163};
18164var ReflectorBaseNode = class extends Node2 {
18165  static get type() {
18166    return "ReflectorBaseNode";
18167  }
18168  /**
18169   * Constructs a new reflector base node.
18170   *
18171   * @param {TextureNode} textureNode - Represents the rendered reflections as a texture node.
18172   * @param {Object} [parameters={}] - An object holding configuration parameters.
18173   * @param {Object3D} [parameters.target=new Object3D()] - The 3D object the reflector is linked to.
18174   * @param {number} [parameters.resolutionScale=1] - The resolution scale.
18175   * @param {boolean} [parameters.generateMipmaps=false] - Whether mipmaps should be generated or not.
18176   * @param {boolean} [parameters.bounces=true] - Whether reflectors can render other reflector nodes or not.
18177   * @param {boolean} [parameters.depth=false] - Whether depth data should be generated or not.
18178   * @param {number} [parameters.samples] - Anti-Aliasing samples of the internal render-target.
18179   */
18180  constructor(textureNode, parameters = {}) {
18181    super();
18182    const {
18183      target = new Object3D(),
18184      resolutionScale = 1,
18185      generateMipmaps = false,
18186      bounces = true,
18187      depth: depth3 = false,
18188      samples = 0
18189    } = parameters;
18190    this.textureNode = textureNode;
18191    this.target = target;
18192    this.resolutionScale = resolutionScale;
18193    if (parameters.resolution !== void 0) {
18194      warnOnce('ReflectorNode: The "resolution" parameter has been renamed to "resolutionScale".');
18195      this.resolutionScale = parameters.resolution;
18196    }
18197    this.generateMipmaps = generateMipmaps;
18198    this.bounces = bounces;
18199    this.depth = depth3;
18200    this.samples = samples;
18201    this.updateBeforeType = bounces ? NodeUpdateType.RENDER : NodeUpdateType.FRAME;
18202    this.virtualCameras = /* @__PURE__ */ new WeakMap();
18203    this.renderTargets = /* @__PURE__ */ new Map();
18204    this.forceUpdate = false;
18205    this.hasOutput = false;
18206  }
18207  /**
18208   * Updates the resolution of the internal render target.
18209   *
18210   * @private
18211   * @param {RenderTarget} renderTarget - The render target to resize.
18212   * @param {Renderer} renderer - The renderer that is used to determine the new size.
18213   */
18214  _updateResolution(renderTarget, renderer) {
18215    const resolution = this.resolutionScale;
18216    renderer.getDrawingBufferSize(_size$2);
18217    renderTarget.setSize(Math.round(_size$2.width * resolution), Math.round(_size$2.height * resolution));
18218  }
18219  setup(builder) {
18220    this._updateResolution(_defaultRT, builder.renderer);
18221    return super.setup(builder);
18222  }
18223  /**
18224   * Frees internal resources. Should be called when the node is no longer in use.
18225   */
18226  dispose() {
18227    super.dispose();
18228    for (const renderTarget of this.renderTargets.values()) {
18229      renderTarget.dispose();
18230    }
18231  }
18232  /**
18233   * Returns a virtual camera for the given camera. The virtual camera is used to
18234   * render the scene from the reflector's view so correct reflections can be produced.
18235   *
18236   * @param {Camera} camera - The scene's camera.
18237   * @return {Camera} The corresponding virtual camera.
18238   */
18239  getVirtualCamera(camera) {
18240    let virtualCamera = this.virtualCameras.get(camera);
18241    if (virtualCamera === void 0) {
18242      virtualCamera = camera.clone();
18243      this.virtualCameras.set(camera, virtualCamera);
18244    }
18245    return virtualCamera;
18246  }
18247  /**
18248   * Returns a render target for the given camera. The reflections are rendered
18249   * into this render target.
18250   *
18251   * @param {Camera} camera - The scene's camera.
18252   * @return {RenderTarget} The render target.
18253   */
18254  getRenderTarget(camera) {
18255    let renderTarget = this.renderTargets.get(camera);
18256    if (renderTarget === void 0) {
18257      renderTarget = new RenderTarget(0, 0, { type: HalfFloatType, samples: this.samples });
18258      if (this.generateMipmaps === true) {
18259        renderTarget.texture.minFilter = LinearMipMapLinearFilter;
18260        renderTarget.texture.generateMipmaps = true;
18261      }
18262      if (this.depth === true) {
18263        renderTarget.depthTexture = new DepthTexture();
18264      }
18265      this.renderTargets.set(camera, renderTarget);
18266    }
18267    return renderTarget;
18268  }
18269  updateBefore(frame) {
18270    if (this.bounces === false && _inReflector) return false;
18271    _inReflector = true;
18272    const { scene, camera, renderer, material } = frame;
18273    const { target } = this;
18274    const virtualCamera = this.getVirtualCamera(camera);
18275    const renderTarget = this.getRenderTarget(virtualCamera);
18276    renderer.getDrawingBufferSize(_size$2);
18277    this._updateResolution(renderTarget, renderer);
18278    _reflectorWorldPosition.setFromMatrixPosition(target.matrixWorld);
18279    _cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
18280    _rotationMatrix.extractRotation(target.matrixWorld);
18281    _normal.set(0, 0, 1);
18282    _normal.applyMatrix4(_rotationMatrix);
18283    _view.subVectors(_reflectorWorldPosition, _cameraWorldPosition);
18284    const isFacingAway = _view.dot(_normal) > 0;
18285    let needsClear = false;
18286    if (isFacingAway === true && this.forceUpdate === false) {
18287      if (this.hasOutput === false) {
18288        _inReflector = false;
18289        return;
18290      }
18291      needsClear = true;
18292    }
18293    _view.reflect(_normal).negate();
18294    _view.add(_reflectorWorldPosition);
18295    _rotationMatrix.extractRotation(camera.matrixWorld);
18296    _lookAtPosition.set(0, 0, -1);
18297    _lookAtPosition.applyMatrix4(_rotationMatrix);
18298    _lookAtPosition.add(_cameraWorldPosition);
18299    _target.subVectors(_reflectorWorldPosition, _lookAtPosition);
18300    _target.reflect(_normal).negate();
18301    _target.add(_reflectorWorldPosition);
18302    virtualCamera.coordinateSystem = camera.coordinateSystem;
18303    virtualCamera.position.copy(_view);
18304    virtualCamera.up.set(0, 1, 0);
18305    virtualCamera.up.applyMatrix4(_rotationMatrix);
18306    virtualCamera.up.reflect(_normal);
18307    virtualCamera.lookAt(_target);
18308    virtualCamera.near = camera.near;
18309    virtualCamera.far = camera.far;
18310    virtualCamera.updateMatrixWorld();
18311    virtualCamera.projectionMatrix.copy(camera.projectionMatrix);
18312    _reflectorPlane.setFromNormalAndCoplanarPoint(_normal, _reflectorWorldPosition);
18313    _reflectorPlane.applyMatrix4(virtualCamera.matrixWorldInverse);
18314    clipPlane.set(_reflectorPlane.normal.x, _reflectorPlane.normal.y, _reflectorPlane.normal.z, _reflectorPlane.constant);
18315    const projectionMatrix = virtualCamera.projectionMatrix;
18316    _q.x = (Math.sign(clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
18317    _q.y = (Math.sign(clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
18318    _q.z = -1;
18319    _q.w = (1 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
18320    clipPlane.multiplyScalar(1 / clipPlane.dot(_q));
18321    const clipBias = 0;
18322    projectionMatrix.elements[2] = clipPlane.x;
18323    projectionMatrix.elements[6] = clipPlane.y;
18324    projectionMatrix.elements[10] = renderer.coordinateSystem === WebGPUCoordinateSystem ? clipPlane.z - clipBias : clipPlane.z + 1 - clipBias;
18325    projectionMatrix.elements[14] = clipPlane.w;
18326    this.textureNode.value = renderTarget.texture;
18327    if (this.depth === true) {
18328      this.textureNode.getDepthNode().value = renderTarget.depthTexture;
18329    }
18330    material.visible = false;
18331    const currentRenderTarget = renderer.getRenderTarget();
18332    const currentMRT = renderer.getMRT();
18333    const currentAutoClear = renderer.autoClear;
18334    renderer.setMRT(null);
18335    renderer.setRenderTarget(renderTarget);
18336    renderer.autoClear = true;
18337    const previousName = scene.name;
18338    scene.name = (scene.name || "Scene") + " [ Reflector ]";
18339    if (needsClear) {
18340      renderer.clear();
18341      this.hasOutput = false;
18342    } else {
18343      renderer.render(scene, virtualCamera);
18344      this.hasOutput = true;
18345    }
18346    scene.name = previousName;
18347    renderer.setMRT(currentMRT);
18348    renderer.setRenderTarget(currentRenderTarget);
18349    renderer.autoClear = currentAutoClear;
18350    material.visible = true;
18351    _inReflector = false;
18352    this.forceUpdate = false;
18353  }
18354  /**
18355   * The resolution scale.
18356   *
18357   * @deprecated
18358   * @type {number}
18359   * @default {1}
18360   */
18361  get resolution() {
18362    warnOnce('ReflectorNode: The "resolution" property has been renamed to "resolutionScale".');
18363    return this.resolutionScale;
18364  }
18365  set resolution(value) {
18366    warnOnce('ReflectorNode: The "resolution" property has been renamed to "resolutionScale".');
18367    this.resolutionScale = value;
18368  }
18369};
18370var reflector = (parameters) => new ReflectorNode(parameters);
18371var _camera = /* @__PURE__ */ new OrthographicCamera(-1, 1, 1, -1, 0, 1);
18372var QuadGeometry = class extends BufferGeometry {
18373  /**
18374   * Constructs a new quad geometry.
18375   *
18376   * @param {boolean} [flipY=false] - Whether the uv coordinates should be flipped along the vertical axis or not.
18377   */
18378  constructor(flipY = false) {
18379    super();
18380    const uv3 = flipY === false ? [0, -1, 0, 1, 2, 1] : [0, 2, 0, 0, 2, 0];
18381    this.setAttribute("position", new Float32BufferAttribute([-1, 3, 0, -1, -1, 0, 3, -1, 0], 3));
18382    this.setAttribute("uv", new Float32BufferAttribute(uv3, 2));
18383  }
18384};
18385var _geometry = /* @__PURE__ */ new QuadGeometry();
18386var QuadMesh = class extends Mesh {
18387  /**
18388   * Constructs a new quad mesh.
18389   *
18390   * @param {?Material} [material=null] - The material to render the quad mesh with.
18391   */
18392  constructor(material = null) {
18393    super(_geometry, material);
18394    this.camera = _camera;
18395    this.isQuadMesh = true;
18396  }
18397  /**
18398   * Async version of `render()`.
18399   *
18400   * @async
18401   * @deprecated
18402   * @param {Renderer} renderer - The renderer.
18403   * @return {Promise} A Promise that resolves when the render has been finished.
18404   */
18405  async renderAsync(renderer) {
18406    warnOnce('QuadMesh: "renderAsync()" has been deprecated. Use "render()" and "await renderer.init();" when creating the renderer.');
18407    await renderer.init();
18408    renderer.render(this, _camera);
18409  }
18410  /**
18411   * Renders the quad mesh
18412   *
18413   * @param {Renderer} renderer - The renderer.
18414   */
18415  render(renderer) {
18416    renderer.render(this, _camera);
18417  }
18418};
18419var _size$1 = /* @__PURE__ */ new Vector2();
18420var RTTNode = class extends TextureNode {
18421  static get type() {
18422    return "RTTNode";
18423  }
18424  /**
18425   * Constructs a new RTT node.
18426   *
18427   * @param {Node} node - The node to render a texture with.
18428   * @param {?number} [width=null] - The width of the internal render target. If not width is applied, the render target is automatically resized.
18429   * @param {?number} [height=null] - The height of the internal render target.
18430   * @param {Object} [options={type:HalfFloatType}] - The options for the internal render target.
18431   */
18432  constructor(node, width = null, height = null, options = { type: HalfFloatType }) {
18433    const renderTarget = new RenderTarget(width, height, options);
18434    super(renderTarget.texture, uv$1());
18435    this.isRTTNode = true;
18436    this.node = node;
18437    this.width = width;
18438    this.height = height;
18439    this.pixelRatio = 1;
18440    this.renderTarget = renderTarget;
18441    this.textureNeedsUpdate = true;
18442    this.autoUpdate = true;
18443    this._rttNode = null;
18444    this._quadMesh = new QuadMesh(new NodeMaterial());
18445    this.updateBeforeType = NodeUpdateType.RENDER;
18446  }
18447  /**
18448   * Whether the internal render target should automatically be resized or not.
18449   *
18450   * @type {boolean}
18451   * @readonly
18452   * @default true
18453   */
18454  get autoResize() {
18455    return this.width === null;
18456  }
18457  setup(builder) {
18458    this._rttNode = this.node.context(builder.getSharedContext());
18459    this._quadMesh.material.name = "RTT";
18460    this._quadMesh.material.needsUpdate = true;
18461    return super.setup(builder);
18462  }
18463  /**
18464   * Sets the size of the internal render target
18465   *
18466   * @param {number} width - The width to set.
18467   * @param {number} height - The width to set.
18468   */
18469  setSize(width, height) {
18470    this.width = width;
18471    this.height = height;
18472    const effectiveWidth = width * this.pixelRatio;
18473    const effectiveHeight = height * this.pixelRatio;
18474    this.renderTarget.setSize(effectiveWidth, effectiveHeight);
18475    this.textureNeedsUpdate = true;
18476  }
18477  /**
18478   * Sets the pixel ratio. This will also resize the render target.
18479   *
18480   * @param {number} pixelRatio - The pixel ratio to set.
18481   */
18482  setPixelRatio(pixelRatio) {
18483    this.pixelRatio = pixelRatio;
18484    this.setSize(this.width, this.height);
18485  }
18486  updateBefore({ renderer }) {
18487    if (this.textureNeedsUpdate === false && this.autoUpdate === false) return;
18488    this.textureNeedsUpdate = false;
18489    if (this.autoResize === true) {
18490      const pixelRatio = renderer.getPixelRatio();
18491      const size3 = renderer.getSize(_size$1);
18492      const effectiveWidth = Math.floor(size3.width * pixelRatio);
18493      const effectiveHeight = Math.floor(size3.height * pixelRatio);
18494      if (effectiveWidth !== this.renderTarget.width || effectiveHeight !== this.renderTarget.height) {
18495        this.renderTarget.setSize(effectiveWidth, effectiveHeight);
18496        this.textureNeedsUpdate = true;
18497      }
18498    }
18499    let name = "RTT";
18500    if (this.node.name) {
18501      name = this.node.name + " [ " + name + " ]";
18502    }
18503    this._quadMesh.material.fragmentNode = this._rttNode;
18504    this._quadMesh.name = name;
18505    const currentRenderTarget = renderer.getRenderTarget();
18506    renderer.setRenderTarget(this.renderTarget);
18507    this._quadMesh.render(renderer);
18508    renderer.setRenderTarget(currentRenderTarget);
18509  }
18510  clone() {
18511    const newNode = new TextureNode(this.value, this.uvNode, this.levelNode);
18512    newNode.sampler = this.sampler;
18513    newNode.referenceNode = this;
18514    return newNode;
18515  }
18516};
18517var rtt = (node, ...params) => new RTTNode(nodeObject(node), ...params);
18518var convertToTexture = (node, ...params) => {
18519  if (node.isSampleNode || node.isTextureNode) return node;
18520  if (node.isPassNode) return node.getTextureNode();
18521  return rtt(node, ...params);
18522};
18523var getViewPosition = /* @__PURE__ */ Fn(([screenPosition, depth3, projectionMatrixInverse], builder) => {
18524  let clipSpacePosition;
18525  if (builder.renderer.coordinateSystem === WebGPUCoordinateSystem) {
18526    screenPosition = vec2(screenPosition.x, screenPosition.y.oneMinus()).mul(2).sub(1);
18527    clipSpacePosition = vec4(vec3(screenPosition, depth3), 1);
18528  } else {
18529    clipSpacePosition = vec4(vec3(screenPosition.x, screenPosition.y.oneMinus(), depth3).mul(2).sub(1), 1);
18530  }
18531  const viewSpacePosition = vec4(projectionMatrixInverse.mul(clipSpacePosition));
18532  return viewSpacePosition.xyz.div(viewSpacePosition.w);
18533});
18534var getScreenPosition = /* @__PURE__ */ Fn(([viewPosition, projectionMatrix]) => {
18535  const sampleClipPos = projectionMatrix.mul(vec4(viewPosition, 1));
18536  const sampleUv = sampleClipPos.xy.div(sampleClipPos.w).mul(0.5).add(0.5).toVar();
18537  return vec2(sampleUv.x, sampleUv.y.oneMinus());
18538});
18539var getNormalFromDepth = /* @__PURE__ */ Fn(([uv3, depthTexture, projectionMatrixInverse]) => {
18540  const size3 = textureSize(textureLoad(depthTexture));
18541  const p = ivec2(uv3.mul(size3)).toVar();
18542  const c0 = textureLoad(depthTexture, p).toVar();
18543  const l2 = textureLoad(depthTexture, p.sub(ivec2(2, 0))).toVar();
18544  const l1 = textureLoad(depthTexture, p.sub(ivec2(1, 0))).toVar();
18545  const r1 = textureLoad(depthTexture, p.add(ivec2(1, 0))).toVar();
18546  const r2 = textureLoad(depthTexture, p.add(ivec2(2, 0))).toVar();
18547  const b2 = textureLoad(depthTexture, p.add(ivec2(0, 2))).toVar();
18548  const b1 = textureLoad(depthTexture, p.add(ivec2(0, 1))).toVar();
18549  const t1 = textureLoad(depthTexture, p.sub(ivec2(0, 1))).toVar();
18550  const t2 = textureLoad(depthTexture, p.sub(ivec2(0, 2))).toVar();
18551  const dl = abs(sub(float(2).mul(l1).sub(l2), c0)).toVar();
18552  const dr = abs(sub(float(2).mul(r1).sub(r2), c0)).toVar();
18553  const db = abs(sub(float(2).mul(b1).sub(b2), c0)).toVar();
18554  const dt = abs(sub(float(2).mul(t1).sub(t2), c0)).toVar();
18555  const ce = getViewPosition(uv3, c0, projectionMatrixInverse).toVar();
18556  const dpdx = dl.lessThan(dr).select(ce.sub(getViewPosition(uv3.sub(vec2(float(1).div(size3.x), 0)), l1, projectionMatrixInverse)), ce.negate().add(getViewPosition(uv3.add(vec2(float(1).div(size3.x), 0)), r1, projectionMatrixInverse)));
18557  const dpdy = db.lessThan(dt).select(ce.sub(getViewPosition(uv3.add(vec2(0, float(1).div(size3.y))), b1, projectionMatrixInverse)), ce.negate().add(getViewPosition(uv3.sub(vec2(0, float(1).div(size3.y))), t1, projectionMatrixInverse)));
18558  return normalize(cross(dpdx, dpdy));
18559});
18560var interleavedGradientNoise = Fn(([position]) => {
18561  return fract(float(52.9829189).mul(fract(dot(position, vec2(0.06711056, 583715e-8)))));
18562}).setLayout({
18563  name: "interleavedGradientNoise",
18564  type: "float",
18565  inputs: [
18566    { name: "position", type: "vec2" }
18567  ]
18568});
18569var vogelDiskSample = Fn(([sampleIndex, samplesCount, phi]) => {
18570  const goldenAngle = float(2.399963229728653);
18571  const r = sqrt(float(sampleIndex).add(0.5).div(float(samplesCount)));
18572  const theta = float(sampleIndex).mul(goldenAngle).add(phi);
18573  return vec2(cos(theta), sin(theta)).mul(r);
18574}).setLayout({
18575  name: "vogelDiskSample",
18576  type: "vec2",
18577  inputs: [
18578    { name: "sampleIndex", type: "int" },
18579    { name: "samplesCount", type: "int" },
18580    { name: "phi", type: "float" }
18581  ]
18582});
18583var SampleNode = class extends Node2 {
18584  /**
18585   * Returns the type of the node.
18586   *
18587   * @type {string}
18588   * @readonly
18589   * @static
18590   */
18591  static get type() {
18592    return "SampleNode";
18593  }
18594  /**
18595   * Creates an instance of SampleNode.
18596   *
18597   * @param {Function} callback - The function to be called when sampling. Should accept a UV node and return a value.
18598   * @param {?Node<vec2>} [uvNode=null] - The UV node to be used in the texture sampling.
18599   */
18600  constructor(callback, uvNode = null) {
18601    super();
18602    this.callback = callback;
18603    this.uvNode = uvNode;
18604    this.isSampleNode = true;
18605  }
18606  /**
18607   * Sets up the node by sampling with the default UV accessor.
18608   *
18609   * @returns {Node} The result of the callback function when called with the UV node.
18610   */
18611  setup() {
18612    return this.sample(uv$1());
18613  }
18614  /**
18615   * Calls the callback function with the provided UV node.
18616   *
18617   * @param {Node<vec2>} uv - The UV node or value to be passed to the callback.
18618   * @returns {Node} The result of the callback function.
18619   */
18620  sample(uv3) {
18621    return this.callback(uv3);
18622  }
18623};
18624var sample = (callback, uv3 = null) => new SampleNode(callback, nodeObject(uv3));
18625var EventNode = class _EventNode extends Node2 {
18626  static get type() {
18627    return "EventNode";
18628  }
18629  /**
18630   * Creates an EventNode.
18631   *
18632   * @param {string} eventType - The type of event
18633   * @param {Function} callback - The callback to execute on update.
18634   */
18635  constructor(eventType, callback) {
18636    super("void");
18637    this.eventType = eventType;
18638    this.callback = callback;
18639    if (eventType === _EventNode.OBJECT) {
18640      this.updateType = NodeUpdateType.OBJECT;
18641    } else if (eventType === _EventNode.MATERIAL) {
18642      this.updateType = NodeUpdateType.RENDER;
18643    } else if (eventType === _EventNode.FRAME) {
18644      this.updateType = NodeUpdateType.FRAME;
18645    } else if (eventType === _EventNode.BEFORE_OBJECT) {
18646      this.updateBeforeType = NodeUpdateType.OBJECT;
18647    } else if (eventType === _EventNode.BEFORE_MATERIAL) {
18648      this.updateBeforeType = NodeUpdateType.RENDER;
18649    } else if (eventType === _EventNode.BEFORE_FRAME) {
18650      this.updateBeforeType = NodeUpdateType.FRAME;
18651    }
18652  }
18653  update(frame) {
18654    this.callback(frame);
18655  }
18656  updateBefore(frame) {
18657    this.callback(frame);
18658  }
18659};
18660EventNode.OBJECT = "object";
18661EventNode.MATERIAL = "material";
18662EventNode.FRAME = "frame";
18663EventNode.BEFORE_OBJECT = "beforeObject";
18664EventNode.BEFORE_MATERIAL = "beforeMaterial";
18665EventNode.BEFORE_FRAME = "beforeFrame";
18666var createEvent = (type, callback) => new EventNode(type, callback).toStack();
18667var OnObjectUpdate = (callback) => createEvent(EventNode.OBJECT, callback);
18668var OnMaterialUpdate = (callback) => createEvent(EventNode.MATERIAL, callback);
18669var OnFrameUpdate = (callback) => createEvent(EventNode.FRAME, callback);
18670var OnBeforeObjectUpdate = (callback) => createEvent(EventNode.BEFORE_OBJECT, callback);
18671var OnBeforeMaterialUpdate = (callback) => createEvent(EventNode.BEFORE_MATERIAL, callback);
18672var OnBeforeFrameUpdate = (callback) => createEvent(EventNode.BEFORE_FRAME, callback);
18673var StorageInstancedBufferAttribute = class extends InstancedBufferAttribute {
18674  /**
18675   * Constructs a new storage instanced buffer attribute.
18676   *
18677   * @param {number|TypedArray} count - The item count. It is also valid to pass a typed array as an argument.
18678   * The subsequent parameters are then obsolete.
18679   * @param {number} itemSize - The item size.
18680   * @param {TypedArray.constructor} [typeClass=Float32Array] - A typed array constructor.
18681   */
18682  constructor(count, itemSize, typeClass = Float32Array) {
18683    const array3 = ArrayBuffer.isView(count) ? count : new typeClass(count * itemSize);
18684    super(array3, itemSize);
18685    this.isStorageInstancedBufferAttribute = true;
18686  }
18687};
18688var StorageBufferAttribute = class extends BufferAttribute {
18689  /**
18690   * Constructs a new storage buffer attribute.
18691   *
18692   * @param {number|TypedArray} count - The item count. It is also valid to pass a typed array as an argument.
18693   * The subsequent parameters are then obsolete.
18694   * @param {number} itemSize - The item size.
18695   * @param {TypedArray.constructor} [typeClass=Float32Array] - A typed array constructor.
18696   */
18697  constructor(count, itemSize, typeClass = Float32Array) {
18698    const array3 = ArrayBuffer.isView(count) ? count : new typeClass(count * itemSize);
18699    super(array3, itemSize);
18700    this.isStorageBufferAttribute = true;
18701  }
18702};
18703var attributeArray = (count, type = "float") => {
18704  let itemSize, typedArray;
18705  if (type.isStruct === true) {
18706    itemSize = type.layout.getLength();
18707    typedArray = getTypedArrayFromType("float");
18708  } else {
18709    itemSize = getLengthFromType(type);
18710    typedArray = getTypedArrayFromType(type);
18711  }
18712  const buffer3 = new StorageBufferAttribute(count, itemSize, typedArray);
18713  const node = storage(buffer3, type, count);
18714  return node;
18715};
18716var instancedArray = (count, type = "float") => {
18717  let itemSize, typedArray;
18718  if (type.isStruct === true) {
18719    itemSize = type.layout.getLength();
18720    typedArray = getTypedArrayFromType("float");
18721  } else {
18722    itemSize = getLengthFromType(type);
18723    typedArray = getTypedArrayFromType(type);
18724  }
18725  const buffer3 = new StorageInstancedBufferAttribute(count, itemSize, typedArray);
18726  const node = storage(buffer3, type, buffer3.count);
18727  return node;
18728};
18729var PointUVNode = class extends Node2 {
18730  static get type() {
18731    return "PointUVNode";
18732  }
18733  /**
18734   * Constructs a new point uv node.
18735   */
18736  constructor() {
18737    super("vec2");
18738    this.isPointUVNode = true;
18739  }
18740  generate() {
18741    return "vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )";
18742  }
18743};
18744var pointUV = /* @__PURE__ */ nodeImmutable(PointUVNode);
18745var _m1 = /* @__PURE__ */ new Matrix4();
18746var backgroundBlurriness = /* @__PURE__ */ uniform(0).setGroup(renderGroup).onRenderUpdate(({ scene }) => scene.backgroundBlurriness);
18747var backgroundIntensity = /* @__PURE__ */ uniform(1).setGroup(renderGroup).onRenderUpdate(({ scene }) => scene.backgroundIntensity);
18748var backgroundRotation = /* @__PURE__ */ uniform(new Matrix4()).setGroup(renderGroup).onRenderUpdate(({ scene }) => {
18749  const background = scene.background;
18750  if (background !== null && background.isTexture && background.mapping !== UVMapping) {
18751    _m1.makeRotationFromEuler(scene.backgroundRotation).transpose();
18752  } else {
18753    _m1.identity();
18754  }
18755  return _m1;
18756});
18757var StorageTextureNode = class extends TextureNode {
18758  static get type() {
18759    return "StorageTextureNode";
18760  }
18761  /**
18762   * Constructs a new storage texture node.
18763   *
18764   * @param {StorageTexture} value - The storage texture.
18765   * @param {Node<vec2|vec3>} uvNode - The uv node.
18766   * @param {?Node} [storeNode=null] - The value node that should be stored in the texture.
18767   */
18768  constructor(value, uvNode, storeNode = null) {
18769    super(value, uvNode);
18770    this.storeNode = storeNode;
18771    this.mipLevel = 0;
18772    this.isStorageTextureNode = true;
18773    this.access = NodeAccess.WRITE_ONLY;
18774  }
18775  /**
18776   * Overwrites the default implementation to return a fixed value `'storageTexture'`.
18777   *
18778   * @param {NodeBuilder} builder - The current node builder.
18779   * @return {string} The input type.
18780   */
18781  getInputType() {
18782    return "storageTexture";
18783  }
18784  setup(builder) {
18785    super.setup(builder);
18786    const properties = builder.getNodeProperties(this);
18787    properties.storeNode = this.storeNode;
18788    return properties;
18789  }
18790  /**
18791   * Defines the node access.
18792   *
18793   * @param {string} value - The node access.
18794   * @return {StorageTextureNode} A reference to this node.
18795   */
18796  setAccess(value) {
18797    this.access = value;
18798    return this;
18799  }
18800  /**
18801   * Sets the mip level to write to.
18802   *
18803   * @param {number} level - The mip level.
18804   * @return {StorageTextureNode} A reference to this node.
18805   */
18806  setMipLevel(level) {
18807    this.mipLevel = level;
18808    return this;
18809  }
18810  /**
18811   * Generates the code snippet of the storage node. If no `storeNode`
18812   * is defined, the texture node is generated as normal texture.
18813   *
18814   * @param {NodeBuilder} builder - The current node builder.
18815   * @param {string} output - The current output.
18816   * @return {string} The generated code snippet.
18817   */
18818  generate(builder, output3) {
18819    if (this.storeNode !== null) {
18820      this.generateStore(builder);
18821      return "";
18822    }
18823    return super.generate(builder, output3);
18824  }
18825  /**
18826   * Generates the snippet for the storage texture.
18827   *
18828   * @param {NodeBuilder} builder - The current node builder.
18829   * @param {string} textureProperty - The texture property.
18830   * @param {string} uvSnippet - The uv snippet.
18831   * @param {?string} levelSnippet - The level snippet.
18832   * @param {?string} biasSnippet - The bias snippet.
18833   * @param {?string} depthSnippet - The depth snippet.
18834   * @param {?string} compareSnippet - The compare snippet.
18835   * @param {?Array<string>} gradSnippet - The grad snippet.
18836   * @param {?string} offsetSnippet - The offset snippet.
18837   * @return {string} The generated code snippet.
18838   */
18839  generateSnippet(builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet, offsetSnippet) {
18840    const texture3 = this.value;
18841    return builder.generateStorageTextureLoad(texture3, textureProperty, uvSnippet, levelSnippet, depthSnippet, offsetSnippet);
18842  }
18843  /**
18844   * Convenience method for configuring a read/write node access.
18845   *
18846   * @return {StorageTextureNode} A reference to this node.
18847   */
18848  toReadWrite() {
18849    return this.setAccess(NodeAccess.READ_WRITE);
18850  }
18851  /**
18852   * Convenience method for configuring a read-only node access.
18853   *
18854   * @return {StorageTextureNode} A reference to this node.
18855   */
18856  toReadOnly() {
18857    return this.setAccess(NodeAccess.READ_ONLY);
18858  }
18859  /**
18860   * Convenience method for configuring a write-only node access.
18861   *
18862   * @return {StorageTextureNode} A reference to this node.
18863   */
18864  toWriteOnly() {
18865    return this.setAccess(NodeAccess.WRITE_ONLY);
18866  }
18867  /**
18868   * Generates the code snippet of the storage texture node.
18869   *
18870   * @param {NodeBuilder} builder - The current node builder.
18871   */
18872  generateStore(builder) {
18873    const properties = builder.getNodeProperties(this);
18874    const { uvNode, storeNode, depthNode } = properties;
18875    const textureProperty = super.generate(builder, "property");
18876    const uvSnippet = uvNode.build(builder, this.value.is3DTexture === true ? "uvec3" : "uvec2");
18877    const storeSnippet = storeNode.build(builder, "vec4");
18878    const depthSnippet = depthNode ? depthNode.build(builder, "int") : null;
18879    const snippet = builder.generateTextureStore(this.value, textureProperty, uvSnippet, depthSnippet, storeSnippet);
18880    builder.addLineFlowCode(snippet, this);
18881  }
18882  clone() {
18883    const newNode = super.clone();
18884    newNode.storeNode = this.storeNode;
18885    newNode.mipLevel = this.mipLevel;
18886    newNode.access = this.access;
18887    return newNode;
18888  }
18889};
18890var storageTexture = /* @__PURE__ */ nodeProxy(StorageTextureNode).setParameterLength(1, 3);
18891var textureStore = (value, uvNode, storeNode) => {
18892  let node;
18893  if (value.isStorageTextureNode === true) {
18894    node = value.clone();
18895    node.uvNode = uvNode;
18896    node.storeNode = storeNode;
18897  } else {
18898    node = storageTexture(value, uvNode, storeNode);
18899  }
18900  if (storeNode !== null) node.toStack();
18901  return node;
18902};
18903var normal = Fn(({ texture: texture3, uv: uv3 }) => {
18904  const epsilon = 1e-4;
18905  const ret = vec3().toVar();
18906  If(uv3.x.lessThan(epsilon), () => {
18907    ret.assign(vec3(1, 0, 0));
18908  }).ElseIf(uv3.y.lessThan(epsilon), () => {
18909    ret.assign(vec3(0, 1, 0));
18910  }).ElseIf(uv3.z.lessThan(epsilon), () => {
18911    ret.assign(vec3(0, 0, 1));
18912  }).ElseIf(uv3.x.greaterThan(1 - epsilon), () => {
18913    ret.assign(vec3(-1, 0, 0));
18914  }).ElseIf(uv3.y.greaterThan(1 - epsilon), () => {
18915    ret.assign(vec3(0, -1, 0));
18916  }).ElseIf(uv3.z.greaterThan(1 - epsilon), () => {
18917    ret.assign(vec3(0, 0, -1));
18918  }).Else(() => {
18919    const step3 = 0.01;
18920    const x = texture3.sample(uv3.add(vec3(-step3, 0, 0))).r.sub(texture3.sample(uv3.add(vec3(step3, 0, 0))).r);
18921    const y = texture3.sample(uv3.add(vec3(0, -step3, 0))).r.sub(texture3.sample(uv3.add(vec3(0, step3, 0))).r);
18922    const z = texture3.sample(uv3.add(vec3(0, 0, -step3))).r.sub(texture3.sample(uv3.add(vec3(0, 0, step3))).r);
18923    ret.assign(vec3(x, y, z));
18924  });
18925  return ret.normalize();
18926});
18927var Texture3DNode = class extends TextureNode {
18928  static get type() {
18929    return "Texture3DNode";
18930  }
18931  /**
18932   * Constructs a new 3D texture node.
18933   *
18934   * @param {Data3DTexture} value - The 3D texture.
18935   * @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
18936   * @param {?Node<int>} [levelNode=null] - The level node.
18937   */
18938  constructor(value, uvNode = null, levelNode = null) {
18939    super(value, uvNode, levelNode);
18940    this.isTexture3DNode = true;
18941  }
18942  /**
18943   * Overwrites the default implementation to return a fixed value `'texture3D'`.
18944   *
18945   * @param {NodeBuilder} builder - The current node builder.
18946   * @return {string} The input type.
18947   */
18948  getInputType() {
18949    return "texture3D";
18950  }
18951  /**
18952   * Returns a default uv node which is in context of 3D textures a three-dimensional
18953   * uv node.
18954   *
18955   * @return {Node<vec3>} The default uv node.
18956   */
18957  getDefaultUV() {
18958    return vec3(0.5, 0.5, 0.5);
18959  }
18960  /**
18961   * Overwritten with an empty implementation since the `updateMatrix` flag is ignored
18962   * for 3D textures. The uv transformation matrix is not applied to 3D textures.
18963   *
18964   * @param {boolean} value - The update toggle.
18965   */
18966  setUpdateMatrix() {
18967  }
18968  // Ignore .updateMatrix for 3d TextureNode
18969  /**
18970   * Generates the uv code snippet.
18971   *
18972   * @param {NodeBuilder} builder - The current node builder.
18973   * @param {Node} uvNode - The uv node to generate code for.
18974   * @return {string} The generated code snippet.
18975   */
18976  generateUV(builder, uvNode) {
18977    return uvNode.build(builder, this.sampler === true ? "vec3" : "ivec3");
18978  }
18979  /**
18980   * Generates the offset code snippet.
18981   *
18982   * @param {NodeBuilder} builder - The current node builder.
18983   * @param {Node} offsetNode - The offset node to generate code for.
18984   * @return {string} The generated code snippet.
18985   */
18986  generateOffset(builder, offsetNode) {
18987    return offsetNode.build(builder, "ivec3");
18988  }
18989  /**
18990   * Computes the normal for the given uv. These texture coordiantes represent a
18991   * position inside the 3D texture. Unlike geometric normals, this normal
18992   * represents a slope or gradient of scalar data inside the 3D texture.
18993   *
18994   * @param {Node<vec3>} uvNode - The uv node that defines a position in the 3D texture.
18995   * @return {Node<vec3>} The normal representing the slope/gradient in the data.
18996   */
18997  normal(uvNode) {
18998    return normal({ texture: this, uv: uvNode });
18999  }
19000};
19001var texture3D = /* @__PURE__ */ nodeProxy(Texture3DNode).setParameterLength(1, 3);
19002var texture3DLoad = (...params) => texture3D(...params).setSampler(false);
19003var texture3DLevel = (value, uvNode, levelNode) => texture3D(value, uvNode).level(levelNode);
19004var UserDataNode = class extends ReferenceNode {
19005  static get type() {
19006    return "UserDataNode";
19007  }
19008  /**
19009   * Constructs a new user data node.
19010   *
19011   * @param {string} property - The property name that should be referenced by the node.
19012   * @param {string} inputType - The node data type of the reference.
19013   * @param {?Object} [userData=null] - A reference to the `userData` object. If not provided, the `userData` property of the 3D object that uses the node material is evaluated.
19014   */
19015  constructor(property3, inputType, userData3 = null) {
19016    super(property3, inputType, userData3);
19017    this.userData = userData3;
19018  }
19019  /**
19020   * Overwritten to make sure {@link ReferenceNode#reference} points to the correct
19021   * `userData` field.
19022   *
19023   * @param {(NodeFrame|NodeBuilder)} state - The current state to evaluate.
19024   * @return {Object} A reference to the `userData` field.
19025   */
19026  updateReference(state) {
19027    this.reference = this.userData !== null ? this.userData : state.object.userData;
19028    return this.reference;
19029  }
19030};
19031var userData = (name, inputType, userData3) => new UserDataNode(name, inputType, userData3);
19032var _objectData = /* @__PURE__ */ new WeakMap();
19033var VelocityNode = class extends TempNode {
19034  static get type() {
19035    return "VelocityNode";
19036  }
19037  /**
19038   * Constructs a new vertex color node.
19039   */
19040  constructor() {
19041    super("vec2");
19042    this.projectionMatrix = null;
19043    this.updateType = NodeUpdateType.OBJECT;
19044    this.updateAfterType = NodeUpdateType.OBJECT;
19045    this.previousModelWorldMatrix = uniform(new Matrix4());
19046    this.previousProjectionMatrix = uniform(new Matrix4()).setGroup(renderGroup);
19047    this.previousCameraViewMatrix = uniform(new Matrix4());
19048  }
19049  /**
19050   * Sets the given projection matrix.
19051   *
19052   * @param {Matrix4} projectionMatrix - The projection matrix to set.
19053   */
19054  setProjectionMatrix(projectionMatrix) {
19055    this.projectionMatrix = projectionMatrix;
19056  }
19057  /**
19058   * Updates velocity specific uniforms.
19059   *
19060   * @param {NodeFrame} frame - A reference to the current node frame.
19061   */
19062  update({ frameId: frameId3, camera, object }) {
19063    const previousModelMatrix = getPreviousMatrix(object);
19064    this.previousModelWorldMatrix.value.copy(previousModelMatrix);
19065    const cameraData = getData(camera);
19066    if (cameraData.frameId !== frameId3) {
19067      cameraData.frameId = frameId3;
19068      if (cameraData.previousProjectionMatrix === void 0) {
19069        cameraData.previousProjectionMatrix = new Matrix4();
19070        cameraData.previousCameraViewMatrix = new Matrix4();
19071        cameraData.currentProjectionMatrix = new Matrix4();
19072        cameraData.currentCameraViewMatrix = new Matrix4();
19073        cameraData.previousProjectionMatrix.copy(this.projectionMatrix || camera.projectionMatrix);
19074        cameraData.previousCameraViewMatrix.copy(camera.matrixWorldInverse);
19075      } else {
19076        cameraData.previousProjectionMatrix.copy(cameraData.currentProjectionMatrix);
19077        cameraData.previousCameraViewMatrix.copy(cameraData.currentCameraViewMatrix);
19078      }
19079      cameraData.currentProjectionMatrix.copy(this.projectionMatrix || camera.projectionMatrix);
19080      cameraData.currentCameraViewMatrix.copy(camera.matrixWorldInverse);
19081      this.previousProjectionMatrix.value.copy(cameraData.previousProjectionMatrix);
19082      this.previousCameraViewMatrix.value.copy(cameraData.previousCameraViewMatrix);
19083    }
19084  }
19085  /**
19086   * Overwritten to updated velocity specific uniforms.
19087   *
19088   * @param {NodeFrame} frame - A reference to the current node frame.
19089   */
19090  updateAfter({ object }) {
19091    getPreviousMatrix(object).copy(object.matrixWorld);
19092  }
19093  /**
19094   * Implements the velocity computation based on the previous and current vertex data.
19095   *
19096   * @param {NodeBuilder} builder - A reference to the current node builder.
19097   * @return {Node<vec2>} The motion vector.
19098   */
19099  setup() {
19100    const projectionMatrix = this.projectionMatrix === null ? cameraProjectionMatrix : uniform(this.projectionMatrix);
19101    const previousModelViewMatrix = this.previousCameraViewMatrix.mul(this.previousModelWorldMatrix);
19102    const clipPositionCurrent = projectionMatrix.mul(modelViewMatrix).mul(positionLocal);
19103    const clipPositionPrevious = this.previousProjectionMatrix.mul(previousModelViewMatrix).mul(positionPrevious);
19104    const ndcPositionCurrent = clipPositionCurrent.xy.div(clipPositionCurrent.w);
19105    const ndcPositionPrevious = clipPositionPrevious.xy.div(clipPositionPrevious.w);
19106    const velocity3 = sub(ndcPositionCurrent, ndcPositionPrevious);
19107    return velocity3;
19108  }
19109};
19110function getData(object) {
19111  let objectData = _objectData.get(object);
19112  if (objectData === void 0) {
19113    objectData = {};
19114    _objectData.set(object, objectData);
19115  }
19116  return objectData;
19117}
19118function getPreviousMatrix(object, index = 0) {
19119  const objectData = getData(object);
19120  let matrix = objectData[index];
19121  if (matrix === void 0) {
19122    objectData[index] = matrix = new Matrix4();
19123    objectData[index].copy(object.matrixWorld);
19124  }
19125  return matrix;
19126}
19127var velocity = /* @__PURE__ */ nodeImmutable(VelocityNode);
19128var grayscale = /* @__PURE__ */ Fn(([color3]) => {
19129  return luminance(color3.rgb);
19130});
19131var saturation = /* @__PURE__ */ Fn(([color3, adjustment = float(1)]) => {
19132  return adjustment.mix(luminance(color3.rgb), color3.rgb);
19133});
19134var vibrance = /* @__PURE__ */ Fn(([color3, adjustment = float(1)]) => {
19135  const average = add(color3.r, color3.g, color3.b).div(3);
19136  const mx = color3.r.max(color3.g.max(color3.b));
19137  const amt = mx.sub(average).mul(adjustment).mul(-3);
19138  return mix(color3.rgb, mx, amt);
19139});
19140var hue = /* @__PURE__ */ Fn(([color3, adjustment = float(1)]) => {
19141  const k = vec3(0.57735, 0.57735, 0.57735);
19142  const cosAngle = adjustment.cos();
19143  return vec3(color3.rgb.mul(cosAngle).add(k.cross(color3.rgb).mul(adjustment.sin()).add(k.mul(dot(k, color3.rgb).mul(cosAngle.oneMinus())))));
19144});
19145var luminance = (color3, luminanceCoefficients = vec3(ColorManagement.getLuminanceCoefficients(new Vector3()))) => dot(color3, luminanceCoefficients);
19146var cdl = /* @__PURE__ */ Fn(([
19147  color3,
19148  slope = vec3(1),
19149  offset3 = vec3(0),
19150  power = vec3(1),
19151  saturation3 = float(1),
19152  // ASC CDL v1.2 explicitly requires Rec. 709 luminance coefficients.
19153  luminanceCoefficients = vec3(ColorManagement.getLuminanceCoefficients(new Vector3(), LinearSRGBColorSpace))
19154]) => {
19155  const luma = color3.rgb.dot(vec3(luminanceCoefficients));
19156  const v = max$1(color3.rgb.mul(slope).add(offset3), 0).toVar();
19157  const pv = v.pow(power).toVar();
19158  If(v.r.greaterThan(0), () => {
19159    v.r.assign(pv.r);
19160  });
19161  If(v.g.greaterThan(0), () => {
19162    v.g.assign(pv.g);
19163  });
19164  If(v.b.greaterThan(0), () => {
19165    v.b.assign(pv.b);
19166  });
19167  v.assign(luma.add(v.sub(luma).mul(saturation3)));
19168  return vec4(v.rgb, color3.a);
19169});
19170var posterize = Fn(([source, steps]) => {
19171  return source.mul(steps).floor().div(steps);
19172});
19173var _sharedFramebuffer = null;
19174var ViewportSharedTextureNode = class extends ViewportTextureNode {
19175  static get type() {
19176    return "ViewportSharedTextureNode";
19177  }
19178  /**
19179   * Constructs a new viewport shared texture node.
19180   *
19181   * @param {Node} [uvNode=screenUV] - The uv node.
19182   * @param {?Node} [levelNode=null] - The level node.
19183   */
19184  constructor(uvNode = screenUV, levelNode = null) {
19185    if (_sharedFramebuffer === null) {
19186      _sharedFramebuffer = new FramebufferTexture();
19187    }
19188    super(uvNode, levelNode, _sharedFramebuffer);
19189  }
19190  /**
19191   * Overwritten so the method always returns the unique shared
19192   * framebuffer texture.
19193   *
19194   * @return {FramebufferTexture} The shared framebuffer texture.
19195   */
19196  getTextureForReference() {
19197    return _sharedFramebuffer;
19198  }
19199  updateReference() {
19200    return this;
19201  }
19202};
19203var viewportSharedTexture = /* @__PURE__ */ nodeProxy(ViewportSharedTextureNode).setParameterLength(0, 2);
19204var _size = /* @__PURE__ */ new Vector2();
19205var PassTextureNode = class extends TextureNode {
19206  static get type() {
19207    return "PassTextureNode";
19208  }
19209  /**
19210   * Constructs a new pass texture node.
19211   *
19212   * @param {PassNode} passNode - The pass node.
19213   * @param {Texture} texture - The output texture.
19214   */
19215  constructor(passNode, texture3) {
19216    super(texture3);
19217    this.passNode = passNode;
19218    this.isPassTextureNode = true;
19219    this.setUpdateMatrix(false);
19220  }
19221  setup(builder) {
19222    const properties = builder.getNodeProperties(this);
19223    properties.passNode = this.passNode;
19224    return super.setup(builder);
19225  }
19226  clone() {
19227    return new this.constructor(this.passNode, this.value);
19228  }
19229};
19230var PassMultipleTextureNode = class extends PassTextureNode {
19231  static get type() {
19232    return "PassMultipleTextureNode";
19233  }
19234  /**
19235   * Constructs a new pass texture node.
19236   *
19237   * @param {PassNode} passNode - The pass node.
19238   * @param {string} textureName - The output texture name.
19239   * @param {boolean} [previousTexture=false] - Whether previous frame data should be used or not.
19240   */
19241  constructor(passNode, textureName, previousTexture = false) {
19242    super(passNode, null);
19243    this.textureName = textureName;
19244    this.previousTexture = previousTexture;
19245    this.isPassMultipleTextureNode = true;
19246  }
19247  /**
19248   * Updates the texture reference of this node.
19249   */
19250  updateTexture() {
19251    this.value = this.previousTexture ? this.passNode.getPreviousTexture(this.textureName) : this.passNode.getTexture(this.textureName);
19252  }
19253  setup(builder) {
19254    this.updateTexture();
19255    return super.setup(builder);
19256  }
19257  clone() {
19258    const newNode = new this.constructor(this.passNode, this.textureName, this.previousTexture);
19259    newNode.uvNode = this.uvNode;
19260    newNode.levelNode = this.levelNode;
19261    newNode.biasNode = this.biasNode;
19262    newNode.sampler = this.sampler;
19263    newNode.depthNode = this.depthNode;
19264    newNode.compareNode = this.compareNode;
19265    newNode.gradNode = this.gradNode;
19266    newNode.offsetNode = this.offsetNode;
19267    return newNode;
19268  }
19269};
19270var PassNode = class _PassNode extends TempNode {
19271  static get type() {
19272    return "PassNode";
19273  }
19274  /**
19275   * Constructs a new pass node.
19276   *
19277   * @param {('color'|'depth')} scope - The scope of the pass. The scope determines whether the node outputs color or depth.
19278   * @param {Scene} scene - A reference to the scene.
19279   * @param {Camera} camera - A reference to the camera.
19280   * @param {Object} options - Options for the internal render target.
19281   */
19282  constructor(scope, scene, camera, options = {}) {
19283    super("vec4");
19284    this.scope = scope;
19285    this.scene = scene;
19286    this.camera = camera;
19287    this.options = options;
19288    this._pixelRatio = 1;
19289    this._width = 1;
19290    this._height = 1;
19291    const depthTexture = new DepthTexture();
19292    depthTexture.isRenderTargetTexture = true;
19293    depthTexture.name = "depth";
19294    const renderTarget = new RenderTarget(this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType, ...options });
19295    renderTarget.texture.name = "output";
19296    renderTarget.depthTexture = depthTexture;
19297    this.renderTarget = renderTarget;
19298    this.overrideMaterial = null;
19299    this.transparent = true;
19300    this.opaque = true;
19301    this.contextNode = null;
19302    this._contextNodeCache = null;
19303    this._textures = {
19304      output: renderTarget.texture,
19305      depth: depthTexture
19306    };
19307    this._textureNodes = {};
19308    this._linearDepthNodes = {};
19309    this._viewZNodes = {};
19310    this._previousTextures = {};
19311    this._previousTextureNodes = {};
19312    this._cameraNear = uniform(0);
19313    this._cameraFar = uniform(0);
19314    this._mrt = null;
19315    this._layers = null;
19316    this._resolutionScale = 1;
19317    this._viewport = null;
19318    this._scissor = null;
19319    this.isPassNode = true;
19320    this.updateBeforeType = NodeUpdateType.FRAME;
19321    this.global = true;
19322  }
19323  /**
19324   * Sets the resolution scale for the pass.
19325   * The resolution scale is a factor that is multiplied with the renderer's width and height.
19326   *
19327   * @param {number} resolutionScale - The resolution scale to set. A value of `1` means full resolution.
19328   * @return {PassNode} A reference to this pass.
19329   */
19330  setResolutionScale(resolutionScale) {
19331    this._resolutionScale = resolutionScale;
19332    return this;
19333  }
19334  /**
19335   * Gets the current resolution scale of the pass.
19336   *
19337   * @return {number} The current resolution scale. A value of `1` means full resolution.
19338   */
19339  getResolutionScale() {
19340    return this._resolutionScale;
19341  }
19342  /**
19343   * Sets the resolution for the pass.
19344   * The resolution is a factor that is multiplied with the renderer's width and height.
19345   *
19346   * @param {number} resolution - The resolution to set. A value of `1` means full resolution.
19347   * @return {PassNode} A reference to this pass.
19348   * @deprecated since r181. Use {@link PassNode#setResolutionScale `setResolutionScale()`} instead.
19349   */
19350  setResolution(resolution) {
19351    warn("PassNode: .setResolution() is deprecated. Use .setResolutionScale() instead.");
19352    return this.setResolutionScale(resolution);
19353  }
19354  /**
19355   * Gets the current resolution of the pass.
19356   *
19357   * @return {number} The current resolution. A value of `1` means full resolution.
19358   * @deprecated since r181. Use {@link PassNode#getResolutionScale `getResolutionScale()`} instead.
19359   */
19360  getResolution() {
19361    warn("PassNode: .getResolution() is deprecated. Use .getResolutionScale() instead.");
19362    return this.getResolutionScale();
19363  }
19364  /**
19365   * Sets the layer configuration that should be used when rendering the pass.
19366   *
19367   * @param {Layers} layers - The layers object to set.
19368   * @return {PassNode} A reference to this pass.
19369   */
19370  setLayers(layers2) {
19371    this._layers = layers2;
19372    return this;
19373  }
19374  /**
19375   * Gets the current layer configuration of the pass.
19376   *
19377   * @return {?Layers} .
19378   */
19379  getLayers() {
19380    return this._layers;
19381  }
19382  /**
19383   * Sets the given MRT node to setup MRT for this pass.
19384   *
19385   * @param {MRTNode} mrt - The MRT object.
19386   * @return {PassNode} A reference to this pass.
19387   */
19388  setMRT(mrt3) {
19389    this._mrt = mrt3;
19390    return this;
19391  }
19392  /**
19393   * Returns the current MRT node.
19394   *
19395   * @return {MRTNode} The current MRT node.
19396   */
19397  getMRT() {
19398    return this._mrt;
19399  }
19400  /**
19401   * Returns the texture for the given output name.
19402   *
19403   * @param {string} name - The output name to get the texture for.
19404   * @return {Texture} The texture.
19405   */
19406  getTexture(name) {
19407    let texture3 = this._textures[name];
19408    if (texture3 === void 0) {
19409      const refTexture = this.renderTarget.texture;
19410      texture3 = refTexture.clone();
19411      texture3.name = name;
19412      this._textures[name] = texture3;
19413      this.renderTarget.textures.push(texture3);
19414    }
19415    return texture3;
19416  }
19417  /**
19418   * Returns the texture holding the data of the previous frame for the given output name.
19419   *
19420   * @param {string} name - The output name to get the texture for.
19421   * @return {Texture} The texture holding the data of the previous frame.
19422   */
19423  getPreviousTexture(name) {
19424    let texture3 = this._previousTextures[name];
19425    if (texture3 === void 0) {
19426      texture3 = this.getTexture(name).clone();
19427      this._previousTextures[name] = texture3;
19428    }
19429    return texture3;
19430  }
19431  /**
19432   * Switches current and previous textures for the given output name.
19433   *
19434   * @param {string} name - The output name.
19435   */
19436  toggleTexture(name) {
19437    const prevTexture = this._previousTextures[name];
19438    if (prevTexture !== void 0) {
19439      const texture3 = this._textures[name];
19440      const index = this.renderTarget.textures.indexOf(texture3);
19441      this.renderTarget.textures[index] = prevTexture;
19442      this._textures[name] = prevTexture;
19443      this._previousTextures[name] = texture3;
19444      this._textureNodes[name].updateTexture();
19445      this._previousTextureNodes[name].updateTexture();
19446    }
19447  }
19448  /**
19449   * Returns the texture node for the given output name.
19450   *
19451   * @param {string} [name='output'] - The output name to get the texture node for.
19452   * @return {TextureNode} The texture node.
19453   */
19454  getTextureNode(name = "output") {
19455    let textureNode = this._textureNodes[name];
19456    if (textureNode === void 0) {
19457      textureNode = new PassMultipleTextureNode(this, name);
19458      textureNode.updateTexture();
19459      this._textureNodes[name] = textureNode;
19460    }
19461    return textureNode;
19462  }
19463  /**
19464   * Returns the previous texture node for the given output name.
19465   *
19466   * @param {string} [name='output'] - The output name to get the previous texture node for.
19467   * @return {TextureNode} The previous texture node.
19468   */
19469  getPreviousTextureNode(name = "output") {
19470    let textureNode = this._previousTextureNodes[name];
19471    if (textureNode === void 0) {
19472      if (this._textureNodes[name] === void 0) this.getTextureNode(name);
19473      textureNode = new PassMultipleTextureNode(this, name, true);
19474      textureNode.updateTexture();
19475      this._previousTextureNodes[name] = textureNode;
19476    }
19477    return textureNode;
19478  }
19479  /**
19480   * Returns a viewZ node of this pass.
19481   *
19482   * @param {string} [name='depth'] - The output name to get the viewZ node for. In most cases the default `'depth'` can be used however the parameter exists for custom depth outputs.
19483   * @return {Node} The viewZ node.
19484   */
19485  getViewZNode(name = "depth") {
19486    let viewZNode = this._viewZNodes[name];
19487    if (viewZNode === void 0) {
19488      const cameraNear3 = this._cameraNear;
19489      const cameraFar3 = this._cameraFar;
19490      this._viewZNodes[name] = viewZNode = perspectiveDepthToViewZ(this.getTextureNode(name), cameraNear3, cameraFar3);
19491    }
19492    return viewZNode;
19493  }
19494  /**
19495   * Returns a linear depth node of this pass.
19496   *
19497   * @param {string} [name='depth'] - The output name to get the linear depth node for. In most cases the default `'depth'` can be used however the parameter exists for custom depth outputs.
19498   * @return {Node} The linear depth node.
19499   */
19500  getLinearDepthNode(name = "depth") {
19501    let linearDepthNode = this._linearDepthNodes[name];
19502    if (linearDepthNode === void 0) {
19503      const cameraNear3 = this._cameraNear;
19504      const cameraFar3 = this._cameraFar;
19505      const viewZNode = this.getViewZNode(name);
19506      this._linearDepthNodes[name] = linearDepthNode = viewZToOrthographicDepth(viewZNode, cameraNear3, cameraFar3);
19507    }
19508    return linearDepthNode;
19509  }
19510  /**
19511   * Precompiles the pass.
19512   *
19513   * Note that this method must be called after the pass configuration is complete.
19514   * So calls like `setMRT()` and `getTextureNode()` must proceed the precompilation.
19515   *
19516   * @async
19517   * @param {Renderer} renderer - The renderer.
19518   * @return {Promise} A Promise that resolves when the compile has been finished.
19519   * @see {@link Renderer#compileAsync}
19520   */
19521  async compileAsync(renderer) {
19522    const currentRenderTarget = renderer.getRenderTarget();
19523    const currentMRT = renderer.getMRT();
19524    renderer.setRenderTarget(this.renderTarget);
19525    renderer.setMRT(this._mrt);
19526    await renderer.compileAsync(this.scene, this.camera);
19527    renderer.setRenderTarget(currentRenderTarget);
19528    renderer.setMRT(currentMRT);
19529  }
19530  setup({ renderer }) {
19531    this.renderTarget.samples = this.options.samples === void 0 ? renderer.samples : this.options.samples;
19532    this.renderTarget.texture.type = renderer.getOutputBufferType();
19533    if (renderer.reversedDepthBuffer === true) {
19534      this.renderTarget.depthTexture.type = FloatType;
19535    }
19536    return this.scope === _PassNode.COLOR ? this.getTextureNode() : this.getLinearDepthNode();
19537  }
19538  updateBefore(frame) {
19539    const { renderer } = frame;
19540    const { scene } = this;
19541    let camera;
19542    let pixelRatio;
19543    const outputRenderTarget = renderer.getOutputRenderTarget();
19544    if (outputRenderTarget && outputRenderTarget.isXRRenderTarget === true) {
19545      pixelRatio = 1;
19546      camera = renderer.xr.getCamera();
19547      renderer.xr.updateCamera(camera);
19548      _size.set(outputRenderTarget.width, outputRenderTarget.height);
19549    } else {
19550      camera = this.camera;
19551      pixelRatio = renderer.getPixelRatio();
19552      renderer.getSize(_size);
19553    }
19554    this._pixelRatio = pixelRatio;
19555    this.setSize(_size.width, _size.height);
19556    const currentRenderTarget = renderer.getRenderTarget();
19557    const currentMRT = renderer.getMRT();
19558    const currentAutoClear = renderer.autoClear;
19559    const currentTransparent = renderer.transparent;
19560    const currentOpaque = renderer.opaque;
19561    const currentMask = camera.layers.mask;
19562    const currentContextNode = renderer.contextNode;
19563    const currentOverrideMaterial = scene.overrideMaterial;
19564    this._cameraNear.value = camera.near;
19565    this._cameraFar.value = camera.far;
19566    if (this._layers !== null) {
19567      camera.layers.mask = this._layers.mask;
19568    }
19569    for (const name in this._previousTextures) {
19570      this.toggleTexture(name);
19571    }
19572    if (this.overrideMaterial !== null) {
19573      scene.overrideMaterial = this.overrideMaterial;
19574    }
19575    renderer.setRenderTarget(this.renderTarget);
19576    renderer.setMRT(this._mrt);
19577    renderer.autoClear = true;
19578    renderer.transparent = this.transparent;
19579    renderer.opaque = this.opaque;
19580    if (this.contextNode !== null) {
19581      if (this._contextNodeCache === null || this._contextNodeCache.version !== this.version) {
19582        this._contextNodeCache = {
19583          version: this.version,
19584          context: context({ ...renderer.contextNode.getFlowContextData(), ...this.contextNode.getFlowContextData() })
19585        };
19586      }
19587      renderer.contextNode = this._contextNodeCache.context;
19588    }
19589    const currentSceneName = scene.name;
19590    scene.name = this.name ? this.name : scene.name;
19591    renderer.render(scene, camera);
19592    scene.name = currentSceneName;
19593    scene.overrideMaterial = currentOverrideMaterial;
19594    renderer.setRenderTarget(currentRenderTarget);
19595    renderer.setMRT(currentMRT);
19596    renderer.autoClear = currentAutoClear;
19597    renderer.transparent = currentTransparent;
19598    renderer.opaque = currentOpaque;
19599    renderer.contextNode = currentContextNode;
19600    camera.layers.mask = currentMask;
19601  }
19602  /**
19603   * Sets the size of the pass's render target. Honors the pixel ratio.
19604   *
19605   * @param {number} width - The width to set.
19606   * @param {number} height - The height to set.
19607   */
19608  setSize(width, height) {
19609    this._width = width;
19610    this._height = height;
19611    const effectiveWidth = Math.floor(this._width * this._pixelRatio * this._resolutionScale);
19612    const effectiveHeight = Math.floor(this._height * this._pixelRatio * this._resolutionScale);
19613    this.renderTarget.setSize(effectiveWidth, effectiveHeight);
19614    if (this._scissor !== null) {
19615      this.renderTarget.scissor.copy(this._scissor).multiplyScalar(this._pixelRatio * this._resolutionScale).floor();
19616      this.renderTarget.scissorTest = true;
19617    } else {
19618      this.renderTarget.scissorTest = false;
19619    }
19620    if (this._viewport !== null) {
19621      this.renderTarget.viewport.copy(this._viewport).multiplyScalar(this._pixelRatio * this._resolutionScale).floor();
19622    }
19623  }
19624  /**
19625   * This method allows to define the pass's scissor rectangle. By default, the scissor rectangle is kept
19626   * in sync with the pass's dimensions. To reverse the process and use auto-sizing again, call the method
19627   * with `null` as the single argument.
19628   *
19629   * @param {?(number | Vector4)} x - The horizontal coordinate for the lower left corner of the box in logical pixel unit.
19630   * Instead of passing four arguments, the method also works with a single four-dimensional vector.
19631   * @param {number} y - The vertical coordinate for the lower left corner of the box in logical pixel unit.
19632   * @param {number} width - The width of the scissor box in logical pixel unit.
19633   * @param {number} height - The height of the scissor box in logical pixel unit.
19634   */
19635  setScissor(x, y, width, height) {
19636    if (x === null) {
19637      this._scissor = null;
19638    } else {
19639      if (this._scissor === null) this._scissor = new Vector4();
19640      if (x.isVector4) {
19641        this._scissor.copy(x);
19642      } else {
19643        this._scissor.set(x, y, width, height);
19644      }
19645    }
19646  }
19647  /**
19648   * This method allows to define the pass's viewport. By default, the viewport is kept in sync
19649   * with the pass's dimensions. To reverse the process and use auto-sizing again, call the method
19650   * with `null` as the single argument.
19651   *
19652   * @param {number | Vector4} x - The horizontal coordinate for the lower left corner of the viewport origin in logical pixel unit.
19653   * @param {number} y - The vertical coordinate for the lower left corner of the viewport origin  in logical pixel unit.
19654   * @param {number} width - The width of the viewport in logical pixel unit.
19655   * @param {number} height - The height of the viewport in logical pixel unit.
19656   */
19657  setViewport(x, y, width, height) {
19658    if (x === null) {
19659      this._viewport = null;
19660    } else {
19661      if (this._viewport === null) this._viewport = new Vector4();
19662      if (x.isVector4) {
19663        this._viewport.copy(x);
19664      } else {
19665        this._viewport.set(x, y, width, height);
19666      }
19667    }
19668  }
19669  /**
19670   * Sets the pixel ratio the pass's render target and updates the size.
19671   *
19672   * @param {number} pixelRatio - The pixel ratio to set.
19673   */
19674  setPixelRatio(pixelRatio) {
19675    this._pixelRatio = pixelRatio;
19676    this.setSize(this._width, this._height);
19677  }
19678  /**
19679   * Frees internal resources. Should be called when the node is no longer in use.
19680   */
19681  dispose() {
19682    this.renderTarget.dispose();
19683  }
19684};
19685PassNode.COLOR = "color";
19686PassNode.DEPTH = "depth";
19687var pass = (scene, camera, options) => new PassNode(PassNode.COLOR, scene, camera, options);
19688var passTexture = (pass3, texture3) => new PassTextureNode(pass3, texture3);
19689var depthPass = (scene, camera, options) => new PassNode(PassNode.DEPTH, scene, camera, options);
19690var ToonOutlinePassNode = class extends PassNode {
19691  static get type() {
19692    return "ToonOutlinePassNode";
19693  }
19694  /**
19695   * Constructs a new outline pass node.
19696   *
19697   * @param {Scene} scene - A reference to the scene.
19698   * @param {Camera} camera - A reference to the camera.
19699   * @param {Node} colorNode - Defines the outline's color.
19700   * @param {Node} thicknessNode - Defines the outline's thickness.
19701   * @param {Node} alphaNode - Defines the outline's alpha.
19702   */
19703  constructor(scene, camera, colorNode, thicknessNode, alphaNode) {
19704    super(PassNode.COLOR, scene, camera);
19705    this.colorNode = colorNode;
19706    this.thicknessNode = thicknessNode;
19707    this.alphaNode = alphaNode;
19708    this._materialCache = /* @__PURE__ */ new WeakMap();
19709    this.name = "Outline Pass";
19710  }
19711  updateBefore(frame) {
19712    const { renderer } = frame;
19713    const currentRenderObjectFunction = renderer.getRenderObjectFunction();
19714    renderer.setRenderObjectFunction((object, scene, camera, geometry, material, group, lightsNode, clippingContext) => {
19715      if (material.isMeshToonMaterial || material.isMeshToonNodeMaterial) {
19716        if (material.wireframe === false) {
19717          const outlineMaterial = this._getOutlineMaterial(material);
19718          renderer.renderObject(object, scene, camera, geometry, outlineMaterial, group, lightsNode, clippingContext);
19719        }
19720      }
19721      renderer.renderObject(object, scene, camera, geometry, material, group, lightsNode, clippingContext);
19722    });
19723    super.updateBefore(frame);
19724    renderer.setRenderObjectFunction(currentRenderObjectFunction);
19725  }
19726  /**
19727   * Creates the material used for outline rendering.
19728   *
19729   * @private
19730   * @return {NodeMaterial} The outline material.
19731   */
19732  _createMaterial() {
19733    const material = new NodeMaterial();
19734    material.isMeshToonOutlineMaterial = true;
19735    material.name = "Toon_Outline";
19736    material.side = BackSide;
19737    const outlineNormal = normalLocal.negate();
19738    const mvp = cameraProjectionMatrix.mul(modelViewMatrix);
19739    const ratio = float(1);
19740    const pos = mvp.mul(vec4(positionLocal, 1));
19741    const pos2 = mvp.mul(vec4(positionLocal.add(outlineNormal), 1));
19742    const norm = normalize(pos.sub(pos2));
19743    material.vertexNode = pos.add(norm.mul(this.thicknessNode).mul(pos.w).mul(ratio));
19744    material.colorNode = vec4(this.colorNode, this.alphaNode);
19745    return material;
19746  }
19747  /**
19748   * For the given toon material, this method returns a corresponding
19749   * outline material.
19750   *
19751   * @private
19752   * @param {(MeshToonMaterial|MeshToonNodeMaterial)} originalMaterial - The toon material.
19753   * @return {NodeMaterial} The outline material.
19754   */
19755  _getOutlineMaterial(originalMaterial) {
19756    let outlineMaterial = this._materialCache.get(originalMaterial);
19757    if (outlineMaterial === void 0) {
19758      outlineMaterial = this._createMaterial();
19759      this._materialCache.set(originalMaterial, outlineMaterial);
19760    }
19761    return outlineMaterial;
19762  }
19763};
19764var toonOutlinePass = (scene, camera, color3 = new Color(0, 0, 0), thickness3 = 3e-3, alpha = 1) => new ToonOutlinePassNode(scene, camera, nodeObject(color3), nodeObject(thickness3), nodeObject(alpha));
19765var linearToneMapping = /* @__PURE__ */ Fn(([color3, exposure]) => {
19766  return color3.mul(exposure).clamp();
19767}).setLayout({
19768  name: "linearToneMapping",
19769  type: "vec3",
19770  inputs: [
19771    { name: "color", type: "vec3" },
19772    { name: "exposure", type: "float" }
19773  ]
19774});
19775var reinhardToneMapping = /* @__PURE__ */ Fn(([color3, exposure]) => {
19776  color3 = color3.mul(exposure);
19777  return color3.div(color3.add(1)).clamp();
19778}).setLayout({
19779  name: "reinhardToneMapping",
19780  type: "vec3",
19781  inputs: [
19782    { name: "color", type: "vec3" },
19783    { name: "exposure", type: "float" }
19784  ]
19785});
19786var cineonToneMapping = /* @__PURE__ */ Fn(([color3, exposure]) => {
19787  color3 = color3.mul(exposure);
19788  color3 = color3.sub(4e-3).max(0);
19789  const a = color3.mul(color3.mul(6.2).add(0.5));
19790  const b = color3.mul(color3.mul(6.2).add(1.7)).add(0.06);
19791  return a.div(b).pow(2.2);
19792}).setLayout({
19793  name: "cineonToneMapping",
19794  type: "vec3",
19795  inputs: [
19796    { name: "color", type: "vec3" },
19797    { name: "exposure", type: "float" }
19798  ]
19799});
19800var RRTAndODTFit = /* @__PURE__ */ Fn(([color3]) => {
19801  const a = color3.mul(color3.add(0.0245786)).sub(90537e-9);
19802  const b = color3.mul(color3.add(0.432951).mul(0.983729)).add(0.238081);
19803  return a.div(b);
19804});
19805var acesFilmicToneMapping = /* @__PURE__ */ Fn(([color3, exposure]) => {
19806  const ACESInputMat = mat3(
19807    0.59719,
19808    0.35458,
19809    0.04823,
19810    0.076,
19811    0.90834,
19812    0.01566,
19813    0.0284,
19814    0.13383,
19815    0.83777
19816  );
19817  const ACESOutputMat = mat3(
19818    1.60475,
19819    -0.53108,
19820    -0.07367,
19821    -0.10208,
19822    1.10813,
19823    -605e-5,
19824    -327e-5,
19825    -0.07276,
19826    1.07602
19827  );
19828  color3 = color3.mul(exposure).div(0.6);
19829  color3 = ACESInputMat.mul(color3);
19830  color3 = RRTAndODTFit(color3);
19831  color3 = ACESOutputMat.mul(color3);
19832  return color3.clamp();
19833}).setLayout({
19834  name: "acesFilmicToneMapping",
19835  type: "vec3",
19836  inputs: [
19837    { name: "color", type: "vec3" },
19838    { name: "exposure", type: "float" }
19839  ]
19840});
19841var LINEAR_REC2020_TO_LINEAR_SRGB = /* @__PURE__ */ mat3(vec3(1.6605, -0.1246, -0.0182), vec3(-0.5876, 1.1329, -0.1006), vec3(-0.0728, -83e-4, 1.1187));
19842var LINEAR_SRGB_TO_LINEAR_REC2020 = /* @__PURE__ */ mat3(vec3(0.6274, 0.0691, 0.0164), vec3(0.3293, 0.9195, 0.088), vec3(0.0433, 0.0113, 0.8956));
19843var agxDefaultContrastApprox = /* @__PURE__ */ Fn(([x_immutable]) => {
19844  const x = vec3(x_immutable).toVar();
19845  const x2 = vec3(x.mul(x)).toVar();
19846  const x4 = vec3(x2.mul(x2)).toVar();
19847  return float(15.5).mul(x4.mul(x2)).sub(mul(40.14, x4.mul(x))).add(mul(31.96, x4).sub(mul(6.868, x2.mul(x))).add(mul(0.4298, x2).add(mul(0.1191, x).sub(232e-5))));
19848});
19849var agxToneMapping = /* @__PURE__ */ Fn(([color3, exposure]) => {
19850  const colortone = vec3(color3).toVar();
19851  const AgXInsetMatrix = mat3(vec3(0.856627153315983, 0.137318972929847, 0.11189821299995), vec3(0.0951212405381588, 0.761241990602591, 0.0767994186031903), vec3(0.0482516061458583, 0.101439036467562, 0.811302368396859));
19852  const AgXOutsetMatrix = mat3(vec3(1.1271005818144368, -0.1413297634984383, -0.14132976349843826), vec3(-0.11060664309660323, 1.157823702216272, -0.11060664309660294), vec3(-0.016493938717834573, -0.016493938717834257, 1.2519364065950405));
19853  const AgxMinEv = float(-12.47393);
19854  const AgxMaxEv = float(4.026069);
19855  colortone.mulAssign(exposure);
19856  colortone.assign(LINEAR_SRGB_TO_LINEAR_REC2020.mul(colortone));
19857  colortone.assign(AgXInsetMatrix.mul(colortone));
19858  colortone.assign(max$1(colortone, 1e-10));
19859  colortone.assign(log22(colortone));
19860  colortone.assign(colortone.sub(AgxMinEv).div(AgxMaxEv.sub(AgxMinEv)));
19861  colortone.assign(clamp(colortone, 0, 1));
19862  colortone.assign(agxDefaultContrastApprox(colortone));
19863  colortone.assign(AgXOutsetMatrix.mul(colortone));
19864  colortone.assign(pow(max$1(vec3(0), colortone), vec3(2.2)));
19865  colortone.assign(LINEAR_REC2020_TO_LINEAR_SRGB.mul(colortone));
19866  colortone.assign(clamp(colortone, 0, 1));
19867  return colortone;
19868}).setLayout({
19869  name: "agxToneMapping",
19870  type: "vec3",
19871  inputs: [
19872    { name: "color", type: "vec3" },
19873    { name: "exposure", type: "float" }
19874  ]
19875});
19876var neutralToneMapping = /* @__PURE__ */ Fn(([color3, exposure]) => {
19877  const StartCompression = float(0.8 - 0.04);
19878  const Desaturation = float(0.15);
19879  color3 = color3.mul(exposure);
19880  const x = min$1(color3.r, min$1(color3.g, color3.b));
19881  const offset3 = select(x.lessThan(0.08), x.sub(mul(6.25, x.mul(x))), 0.04);
19882  color3.subAssign(offset3);
19883  const peak = max$1(color3.r, max$1(color3.g, color3.b));
19884  If(peak.lessThan(StartCompression), () => {
19885    return color3;
19886  });
19887  const d = sub(1, StartCompression);
19888  const newPeak = sub(1, d.mul(d).div(peak.add(d.sub(StartCompression))));
19889  color3.mulAssign(newPeak.div(peak));
19890  const g = sub(1, div(1, Desaturation.mul(peak.sub(newPeak)).add(1)));
19891  return mix(color3, vec3(newPeak), g);
19892}).setLayout({
19893  name: "neutralToneMapping",
19894  type: "vec3",
19895  inputs: [
19896    { name: "color", type: "vec3" },
19897    { name: "exposure", type: "float" }
19898  ]
19899});
19900var CodeNode = class extends Node2 {
19901  static get type() {
19902    return "CodeNode";
19903  }
19904  /**
19905   * Constructs a new code node.
19906   *
19907   * @param {string} [code=''] - The native code.
19908   * @param {Array<Node>} [includes=[]] - An array of includes.
19909   * @param {('js'|'wgsl'|'glsl')} [language=''] - The used language.
19910   */
19911  constructor(code3 = "", includes = [], language = "") {
19912    super("code");
19913    this.isCodeNode = true;
19914    this.global = true;
19915    this.code = code3;
19916    this.includes = includes;
19917    this.language = language;
19918  }
19919  /**
19920   * Sets the includes of this code node.
19921   *
19922   * @param {Array<Node>} includes - The includes to set.
19923   * @return {CodeNode} A reference to this node.
19924   */
19925  setIncludes(includes) {
19926    this.includes = includes;
19927    return this;
19928  }
19929  /**
19930   * Returns the includes of this code node.
19931   *
19932   * @param {NodeBuilder} builder - The current node builder.
19933   * @return {Array<Node>} The includes.
19934   */
19935  getIncludes() {
19936    return this.includes;
19937  }
19938  generate(builder) {
19939    const includes = this.getIncludes(builder);
19940    for (const include of includes) {
19941      include.build(builder);
19942    }
19943    const nodeCode = builder.getCodeFromNode(this, this.getNodeType(builder));
19944    nodeCode.code = this.code;
19945    return nodeCode.code;
19946  }
19947  serialize(data) {
19948    super.serialize(data);
19949    data.code = this.code;
19950    data.language = this.language;
19951  }
19952  deserialize(data) {
19953    super.deserialize(data);
19954    this.code = data.code;
19955    this.language = data.language;
19956  }
19957};
19958var code = /* @__PURE__ */ nodeProxy(CodeNode).setParameterLength(1, 3);
19959var js = (src, includes) => code(src, includes, "js");
19960var wgsl = (src, includes) => code(src, includes, "wgsl");
19961var glsl = (src, includes) => code(src, includes, "glsl");
19962var FunctionNode = class extends CodeNode {
19963  static get type() {
19964    return "FunctionNode";
19965  }
19966  /**
19967   * Constructs a new function node.
19968   *
19969   * @param {string} [code=''] - The native code.
19970   * @param {Array<Node>} [includes=[]] - An array of includes.
19971   * @param {('js'|'wgsl'|'glsl')} [language=''] - The used language.
19972   */
19973  constructor(code3 = "", includes = [], language = "") {
19974    super(code3, includes, language);
19975  }
19976  /**
19977   * Returns the type of this function node.
19978   *
19979   * @param {NodeBuilder} builder - The current node builder.
19980   * @return {string} The type.
19981   */
19982  generateNodeType(builder) {
19983    return this.getNodeFunction(builder).type;
19984  }
19985  /**
19986   * Returns the type of a member of this function node.
19987   *
19988   * @param {NodeBuilder} builder - The current node builder.
19989   * @param {string} name - The name of the member.
19990   * @return {string} The type of the member.
19991   */
19992  getMemberType(builder, name) {
19993    const type = this.getNodeType(builder);
19994    const structType = builder.getStructTypeNode(type);
19995    return structType.getMemberType(builder, name);
19996  }
19997  /**
19998   * Returns the inputs of this function node.
19999   *
20000   * @param {NodeBuilder} builder - The current node builder.
20001   * @return {Array<NodeFunctionInput>} The inputs.
20002   */
20003  getInputs(builder) {
20004    return this.getNodeFunction(builder).inputs;
20005  }
20006  /**
20007   * Returns the node function for this function node.
20008   *
20009   * @param {NodeBuilder} builder - The current node builder.
20010   * @return {NodeFunction} The node function.
20011   */
20012  getNodeFunction(builder) {
20013    const nodeData = builder.getDataFromNode(this);
20014    let nodeFunction = nodeData.nodeFunction;
20015    if (nodeFunction === void 0) {
20016      nodeFunction = builder.parser.parseFunction(this.code);
20017      nodeData.nodeFunction = nodeFunction;
20018    }
20019    return nodeFunction;
20020  }
20021  generate(builder, output3) {
20022    super.generate(builder);
20023    const nodeFunction = this.getNodeFunction(builder);
20024    const name = nodeFunction.name;
20025    const type = nodeFunction.type;
20026    const nodeCode = builder.getCodeFromNode(this, type);
20027    if (name !== "") {
20028      nodeCode.name = name;
20029    }
20030    const propertyName = builder.getPropertyName(nodeCode);
20031    const code3 = this.getNodeFunction(builder).getCode(propertyName);
20032    nodeCode.code = code3 + "\n";
20033    if (output3 === "property") {
20034      return propertyName;
20035    } else {
20036      return builder.format(`${propertyName}()`, type, output3);
20037    }
20038  }
20039};
20040var nativeFn = (code3, includes = [], language = "") => {
20041  for (let i = 0; i < includes.length; i++) {
20042    const include = includes[i];
20043    if (typeof include === "function") {
20044      includes[i] = include.functionNode;
20045    }
20046  }
20047  const functionNode = new FunctionNode(code3, includes, language);
20048  const fn = (...params) => functionNode.call(...params);
20049  fn.functionNode = functionNode;
20050  return fn;
20051};
20052var glslFn = (code3, includes) => nativeFn(code3, includes, "glsl");
20053var wgslFn = (code3, includes) => nativeFn(code3, includes, "wgsl");
20054function getViewZNode(builder) {
20055  let viewZ;
20056  const getViewZ = builder.context.getViewZ;
20057  if (getViewZ !== void 0) {
20058    viewZ = getViewZ(this);
20059  }
20060  return (viewZ || positionView.z).negate();
20061}
20062var rangeFogFactor = Fn(([near, far], builder) => {
20063  const viewZ = getViewZNode(builder);
20064  return smoothstep(near, far, viewZ);
20065});
20066var densityFogFactor = Fn(([density], builder) => {
20067  const viewZ = getViewZNode(builder);
20068  return density.mul(density, viewZ, viewZ).negate().exp().oneMinus();
20069});
20070var exponentialHeightFogFactor = Fn(([density, height], builder) => {
20071  const viewZ = getViewZNode(builder);
20072  const distance3 = height.sub(positionWorld.y).max(0).toConst();
20073  const m = distance3.mul(viewZ).toConst();
20074  return density.mul(density, m, m).negate().exp().oneMinus();
20075});
20076var fog = Fn(([color3, factor]) => {
20077  return vec4(factor.toFloat().mix(output.rgb, color3.toVec3()), output.a);
20078});
20079var min = null;
20080var max = null;
20081var RangeNode = class extends Node2 {
20082  static get type() {
20083    return "RangeNode";
20084  }
20085  /**
20086   * Constructs a new range node.
20087   *
20088   * @param {Node<any>} [minNode=float()] - A node defining the lower bound of the range.
20089   * @param {Node<any>} [maxNode=float()] - A node defining the upper bound of the range.
20090   */
20091  constructor(minNode = float(), maxNode = float()) {
20092    super();
20093    this.minNode = minNode;
20094    this.maxNode = maxNode;
20095  }
20096  /**
20097   * Returns the vector length which is computed based on the range definition.
20098   *
20099   * @param {NodeBuilder} builder - The current node builder.
20100   * @return {number} The vector length.
20101   */
20102  getVectorLength(builder) {
20103    const minNode = this.getConstNode(this.minNode);
20104    const maxNode = this.getConstNode(this.maxNode);
20105    const minLength = builder.getTypeLength(getValueType(minNode.value));
20106    const maxLength = builder.getTypeLength(getValueType(maxNode.value));
20107    return minLength > maxLength ? minLength : maxLength;
20108  }
20109  /**
20110   * This method is overwritten since the node type is inferred from range definition.
20111   *
20112   * @param {NodeBuilder} builder - The current node builder.
20113   * @return {string} The node type.
20114   */
20115  generateNodeType(builder) {
20116    return builder.object.count > 1 ? builder.getTypeFromLength(this.getVectorLength(builder)) : "float";
20117  }
20118  /**
20119   * Returns a constant node from the given node by traversing it.
20120   *
20121   * @param {Node} node - The node to traverse.
20122   * @returns {Node} The constant node, if found.
20123   */
20124  getConstNode(node) {
20125    let output3 = null;
20126    node.traverse((n) => {
20127      if (n.isConstNode === true) {
20128        output3 = n;
20129      }
20130    });
20131    if (output3 === null) {
20132      throw new NodeError('THREE.TSL: No "ConstNode" found in node graph.', this.stackTrace);
20133    }
20134    return output3;
20135  }
20136  setup(builder) {
20137    const object = builder.object;
20138    let output3 = null;
20139    if (object.count > 1) {
20140      const minNode = this.getConstNode(this.minNode);
20141      const maxNode = this.getConstNode(this.maxNode);
20142      const minValue = minNode.value;
20143      const maxValue = maxNode.value;
20144      const minLength = builder.getTypeLength(getValueType(minValue));
20145      const maxLength = builder.getTypeLength(getValueType(maxValue));
20146      min = min || new Vector4();
20147      max = max || new Vector4();
20148      min.setScalar(0);
20149      max.setScalar(0);
20150      if (minLength === 1) min.setScalar(minValue);
20151      else if (minValue.isColor) min.set(minValue.r, minValue.g, minValue.b, 1);
20152      else min.set(minValue.x, minValue.y, minValue.z || 0, minValue.w || 0);
20153      if (maxLength === 1) max.setScalar(maxValue);
20154      else if (maxValue.isColor) max.set(maxValue.r, maxValue.g, maxValue.b, 1);
20155      else max.set(maxValue.x, maxValue.y, maxValue.z || 0, maxValue.w || 0);
20156      const stride = 4;
20157      const length3 = stride * object.count;
20158      const array3 = new Float32Array(length3);
20159      for (let i = 0; i < length3; i++) {
20160        const index = i % stride;
20161        const minElementValue = min.getComponent(index);
20162        const maxElementValue = max.getComponent(index);
20163        array3[i] = MathUtils.lerp(minElementValue, maxElementValue, Math.random());
20164      }
20165      const nodeType = this.getNodeType(builder);
20166      const uniformBufferSize = object.count * 4 * 4;
20167      if (uniformBufferSize <= builder.getUniformBufferLimit()) {
20168        output3 = buffer(array3, "vec4", object.count).element(instanceIndex).convert(nodeType);
20169      } else {
20170        const bufferAttribute3 = new InstancedBufferAttribute(array3, 4);
20171        builder.geometry.setAttribute("__range" + this.id, bufferAttribute3);
20172        output3 = instancedBufferAttribute(bufferAttribute3).convert(nodeType);
20173      }
20174    } else {
20175      output3 = float(0);
20176    }
20177    return output3;
20178  }
20179};
20180var range = /* @__PURE__ */ nodeProxy(RangeNode).setParameterLength(2);
20181var ComputeBuiltinNode = class extends Node2 {
20182  static get type() {
20183    return "ComputeBuiltinNode";
20184  }
20185  /**
20186   * Constructs a new compute builtin node.
20187   *
20188   * @param {string} builtinName - The built-in name.
20189   * @param {string} nodeType - The node type.
20190   */
20191  constructor(builtinName, nodeType) {
20192    super(nodeType);
20193    this._builtinName = builtinName;
20194  }
20195  /**
20196   * This method is overwritten since hash is derived from the built-in name.
20197   *
20198   * @param {NodeBuilder} builder - The current node builder.
20199   * @return {string} The hash.
20200   */
20201  getHash(builder) {
20202    return this.getBuiltinName(builder);
20203  }
20204  /**
20205   * This method is overwritten since the node type is simply derived from `nodeType`..
20206   *
20207   * @param {NodeBuilder} builder - The current node builder.
20208   * @return {string} The node type.
20209   */
20210  generateNodeType() {
20211    return this.nodeType;
20212  }
20213  /**
20214   * Sets the builtin name.
20215   *
20216   * @param {string} builtinName - The built-in name.
20217   * @return {ComputeBuiltinNode} A reference to this node.
20218   */
20219  setBuiltinName(builtinName) {
20220    this._builtinName = builtinName;
20221    return this;
20222  }
20223  /**
20224   * Returns the builtin name.
20225   *
20226   * @param {NodeBuilder} builder - The current node builder.
20227   * @return {string} The builtin name.
20228   */
20229  getBuiltinName() {
20230    return this._builtinName;
20231  }
20232  /**
20233   * Whether the current node builder has the builtin or not.
20234   *
20235   * @param {NodeBuilder} builder - The current node builder.
20236   * @return {boolean} Whether the builder has the builtin or not.
20237   */
20238  hasBuiltin(builder) {
20239    return builder.hasBuiltin(this._builtinName);
20240  }
20241  generate(builder, output3) {
20242    const builtinName = this.getBuiltinName(builder);
20243    const nodeType = this.getNodeType(builder);
20244    if (builder.shaderStage === "compute") {
20245      return builder.format(builtinName, nodeType, output3);
20246    } else {
20247      warn(`ComputeBuiltinNode: Compute built-in value ${builtinName} can not be accessed in the ${builder.shaderStage} stage`);
20248      return builder.generateConst(nodeType);
20249    }
20250  }
20251  serialize(data) {
20252    super.serialize(data);
20253    data.global = this.global;
20254    data._builtinName = this._builtinName;
20255  }
20256  deserialize(data) {
20257    super.deserialize(data);
20258    this.global = data.global;
20259    this._builtinName = data._builtinName;
20260  }
20261};
20262var computeBuiltin = (name, nodeType) => new ComputeBuiltinNode(name, nodeType);
20263var numWorkgroups = /* @__PURE__ */ computeBuiltin("numWorkgroups", "uvec3");
20264var workgroupId = /* @__PURE__ */ computeBuiltin("workgroupId", "uvec3");
20265var globalId = /* @__PURE__ */ computeBuiltin("globalId", "uvec3");
20266var localId = /* @__PURE__ */ computeBuiltin("localId", "uvec3");
20267var subgroupSize = /* @__PURE__ */ computeBuiltin("subgroupSize", "uint");
20268var BarrierNode = class extends Node2 {
20269  /**
20270   * Constructs a new barrier node.
20271   *
20272   * @param {string} scope - The scope defines the behavior of the node.
20273   */
20274  constructor(scope) {
20275    super();
20276    this.scope = scope;
20277    this.isBarrierNode = true;
20278  }
20279  setup(builder) {
20280    builder.allowEarlyReturns = false;
20281    builder.allowGlobalVariables = false;
20282  }
20283  generate(builder) {
20284    const { scope } = this;
20285    const { renderer } = builder;
20286    if (renderer.backend.isWebGLBackend === true) {
20287      builder.addFlowCode(`	// ${scope}Barrier 
20288`);
20289    } else {
20290      builder.addLineFlowCode(`${scope}Barrier()`, this);
20291    }
20292  }
20293};
20294var barrier = nodeProxy(BarrierNode);
20295var workgroupBarrier = () => barrier("workgroup").toStack();
20296var storageBarrier = () => barrier("storage").toStack();
20297var textureBarrier = () => barrier("texture").toStack();
20298var WorkgroupInfoElementNode = class extends ArrayElementNode {
20299  /**
20300   * Constructs a new workgroup info element node.
20301   *
20302   * @param {Node} workgroupInfoNode - The workgroup info node.
20303   * @param {Node} indexNode - The index node that defines the element access.
20304   */
20305  constructor(workgroupInfoNode, indexNode) {
20306    super(workgroupInfoNode, indexNode);
20307    this.isWorkgroupInfoElementNode = true;
20308  }
20309  generate(builder, output3) {
20310    let snippet;
20311    const isAssignContext = builder.context.assign;
20312    snippet = super.generate(builder);
20313    if (isAssignContext !== true) {
20314      const type = this.getNodeType(builder);
20315      snippet = builder.format(snippet, type, output3);
20316    }
20317    return snippet;
20318  }
20319};
20320var WorkgroupInfoNode = class extends Node2 {
20321  /**
20322   * Constructs a new buffer scoped to type scope.
20323   *
20324   * @param {string} scope - TODO.
20325   * @param {string} bufferType - The data type of a 'workgroup' scoped buffer element.
20326   * @param {number} [bufferCount=0] - The number of elements in the buffer.
20327   */
20328  constructor(scope, bufferType, bufferCount = 0) {
20329    super(bufferType);
20330    this.bufferType = bufferType;
20331    this.bufferCount = bufferCount;
20332    this.isWorkgroupInfoNode = true;
20333    this.elementType = bufferType;
20334    this.scope = scope;
20335    this.name = "";
20336  }
20337  /**
20338   * Sets the name of this node.
20339   *
20340   * @param {string} name - The name to set.
20341   * @return {WorkgroupInfoNode} A reference to this node.
20342   */
20343  setName(name) {
20344    this.name = name;
20345    return this;
20346  }
20347  /**
20348   * Sets the name/label of this node.
20349   *
20350   * @deprecated
20351   * @param {string} name - The name to set.
20352   * @return {WorkgroupInfoNode} A reference to this node.
20353   */
20354  label(name) {
20355    warn('TSL: "label()" has been deprecated. Use "setName()" instead.', new StackTrace());
20356    return this.setName(name);
20357  }
20358  /**
20359   * Sets the scope of this node.
20360   *
20361   * @param {string} scope - The scope to set.
20362   * @return {WorkgroupInfoNode} A reference to this node.
20363   */
20364  setScope(scope) {
20365    this.scope = scope;
20366    return this;
20367  }
20368  /**
20369   * The data type of the array buffer.
20370   *
20371   * @return {string} The element type.
20372   */
20373  getElementType() {
20374    return this.elementType;
20375  }
20376  /**
20377   * Overwrites the default implementation since the input type
20378   * is inferred from the scope.
20379   *
20380   * @param {NodeBuilder} builder - The current node builder.
20381   * @return {string} The input type.
20382   */
20383  getInputType() {
20384    return `${this.scope}Array`;
20385  }
20386  /**
20387   * This method can be used to access elements via an index node.
20388   *
20389   * @param {IndexNode} indexNode - indexNode.
20390   * @return {WorkgroupInfoElementNode} A reference to an element.
20391   */
20392  element(indexNode) {
20393    return new WorkgroupInfoElementNode(this, indexNode);
20394  }
20395  generate(builder) {
20396    const name = this.name !== "" ? this.name : `${this.scope}Array_${this.id}`;
20397    return builder.getScopedArray(name, this.scope.toLowerCase(), this.bufferType, this.bufferCount);
20398  }
20399};
20400var workgroupArray = (type, count) => new WorkgroupInfoNode("Workgroup", type, count);
20401var AtomicFunctionNode = class extends Node2 {
20402  static get type() {
20403    return "AtomicFunctionNode";
20404  }
20405  /**
20406   * Constructs a new atomic function node.
20407   *
20408   * @param {string} method - The signature of the atomic function to construct.
20409   * @param {Node} pointerNode - An atomic variable or element of an atomic buffer.
20410   * @param {Node} valueNode - The value that mutates the atomic variable.
20411   */
20412  constructor(method, pointerNode, valueNode) {
20413    super("uint");
20414    this.method = method;
20415    this.pointerNode = pointerNode;
20416    this.valueNode = valueNode;
20417    this.parents = true;
20418  }
20419  /**
20420   * Overwrites the default implementation to return the type of
20421   * the pointer node.
20422   *
20423   * @param {NodeBuilder} builder - The current node builder.
20424   * @return {string} The input type.
20425   */
20426  getInputType(builder) {
20427    return this.pointerNode.getNodeType(builder);
20428  }
20429  /**
20430   * Overwritten since the node type is inferred from the input type.
20431   *
20432   * @param {NodeBuilder} builder - The current node builder.
20433   * @return {string} The node type.
20434   */
20435  generateNodeType(builder) {
20436    return this.getInputType(builder);
20437  }
20438  generate(builder) {
20439    const properties = builder.getNodeProperties(this);
20440    const parents = properties.parents;
20441    const method = this.method;
20442    const type = this.getNodeType(builder);
20443    const inputType = this.getInputType(builder);
20444    const a = this.pointerNode;
20445    const b = this.valueNode;
20446    const params = [];
20447    params.push(`&${a.build(builder, inputType)}`);
20448    if (b !== null) {
20449      params.push(b.build(builder, inputType));
20450    }
20451    const methodSnippet = `${builder.getMethod(method, type)}( ${params.join(", ")} )`;
20452    const isVoid = parents ? parents.length === 1 && parents[0].isStackNode === true : false;
20453    if (isVoid) {
20454      builder.addLineFlowCode(methodSnippet, this);
20455    } else {
20456      if (properties.constNode === void 0) {
20457        properties.constNode = expression(methodSnippet, type).toConst();
20458      }
20459      return properties.constNode.build(builder);
20460    }
20461  }
20462};
20463AtomicFunctionNode.ATOMIC_LOAD = "atomicLoad";
20464AtomicFunctionNode.ATOMIC_STORE = "atomicStore";
20465AtomicFunctionNode.ATOMIC_ADD = "atomicAdd";
20466AtomicFunctionNode.ATOMIC_SUB = "atomicSub";
20467AtomicFunctionNode.ATOMIC_MAX = "atomicMax";
20468AtomicFunctionNode.ATOMIC_MIN = "atomicMin";
20469AtomicFunctionNode.ATOMIC_AND = "atomicAnd";
20470AtomicFunctionNode.ATOMIC_OR = "atomicOr";
20471AtomicFunctionNode.ATOMIC_XOR = "atomicXor";
20472var atomicNode = nodeProxy(AtomicFunctionNode);
20473var atomicFunc = (method, pointerNode, valueNode) => {
20474  return atomicNode(method, pointerNode, valueNode).toStack();
20475};
20476var atomicLoad = (pointerNode) => atomicFunc(AtomicFunctionNode.ATOMIC_LOAD, pointerNode, null);
20477var atomicStore = (pointerNode, valueNode) => atomicFunc(AtomicFunctionNode.ATOMIC_STORE, pointerNode, valueNode);
20478var atomicAdd = (pointerNode, valueNode) => atomicFunc(AtomicFunctionNode.ATOMIC_ADD, pointerNode, valueNode);
20479var atomicSub = (pointerNode, valueNode) => atomicFunc(AtomicFunctionNode.ATOMIC_SUB, pointerNode, valueNode);
20480var atomicMax = (pointerNode, valueNode) => atomicFunc(AtomicFunctionNode.ATOMIC_MAX, pointerNode, valueNode);
20481var atomicMin = (pointerNode, valueNode) => atomicFunc(AtomicFunctionNode.ATOMIC_MIN, pointerNode, valueNode);
20482var atomicAnd = (pointerNode, valueNode) => atomicFunc(AtomicFunctionNode.ATOMIC_AND, pointerNode, valueNode);
20483var atomicOr = (pointerNode, valueNode) => atomicFunc(AtomicFunctionNode.ATOMIC_OR, pointerNode, valueNode);
20484var atomicXor = (pointerNode, valueNode) => atomicFunc(AtomicFunctionNode.ATOMIC_XOR, pointerNode, valueNode);
20485var SubgroupFunctionNode = class _SubgroupFunctionNode extends TempNode {
20486  static get type() {
20487    return "SubgroupFunctionNode";
20488  }
20489  /**
20490   * Constructs a new function node.
20491   *
20492   * @param {string} method - The subgroup/wave intrinsic method to construct.
20493   * @param {Node} [aNode=null] - The method's first argument.
20494   * @param {Node} [bNode=null] - The method's second argument.
20495   */
20496  constructor(method, aNode = null, bNode = null) {
20497    super();
20498    this.method = method;
20499    this.aNode = aNode;
20500    this.bNode = bNode;
20501  }
20502  getInputType(builder) {
20503    const aType = this.aNode ? this.aNode.getNodeType(builder) : null;
20504    const bType = this.bNode ? this.bNode.getNodeType(builder) : null;
20505    const aLen = builder.isMatrix(aType) ? 0 : builder.getTypeLength(aType);
20506    const bLen = builder.isMatrix(bType) ? 0 : builder.getTypeLength(bType);
20507    if (aLen > bLen) {
20508      return aType;
20509    } else {
20510      return bType;
20511    }
20512  }
20513  generateNodeType(builder) {
20514    const method = this.method;
20515    if (method === _SubgroupFunctionNode.SUBGROUP_ELECT) {
20516      return "bool";
20517    } else if (method === _SubgroupFunctionNode.SUBGROUP_BALLOT) {
20518      return "uvec4";
20519    } else {
20520      return this.getInputType(builder);
20521    }
20522  }
20523  generate(builder, output3) {
20524    const method = this.method;
20525    const type = this.getNodeType(builder);
20526    const inputType = this.getInputType(builder);
20527    const a = this.aNode;
20528    const b = this.bNode;
20529    const params = [];
20530    if (method === _SubgroupFunctionNode.SUBGROUP_BROADCAST || method === _SubgroupFunctionNode.SUBGROUP_SHUFFLE || method === _SubgroupFunctionNode.QUAD_BROADCAST) {
20531      const bType = b.getNodeType(builder);
20532      params.push(
20533        a.build(builder, type),
20534        b.build(builder, bType === "float" ? "int" : type)
20535      );
20536    } else if (method === _SubgroupFunctionNode.SUBGROUP_SHUFFLE_XOR || method === _SubgroupFunctionNode.SUBGROUP_SHUFFLE_DOWN || method === _SubgroupFunctionNode.SUBGROUP_SHUFFLE_UP) {
20537      params.push(
20538        a.build(builder, type),
20539        b.build(builder, "uint")
20540      );
20541    } else {
20542      if (a !== null) params.push(a.build(builder, inputType));
20543      if (b !== null) params.push(b.build(builder, inputType));
20544    }
20545    const paramsString = params.length === 0 ? "()" : `( ${params.join(", ")} )`;
20546    return builder.format(`${builder.getMethod(method, type)}${paramsString}`, type, output3);
20547  }
20548  serialize(data) {
20549    super.serialize(data);
20550    data.method = this.method;
20551  }
20552  deserialize(data) {
20553    super.deserialize(data);
20554    this.method = data.method;
20555  }
20556};
20557SubgroupFunctionNode.SUBGROUP_ELECT = "subgroupElect";
20558SubgroupFunctionNode.SUBGROUP_BALLOT = "subgroupBallot";
20559SubgroupFunctionNode.SUBGROUP_ADD = "subgroupAdd";
20560SubgroupFunctionNode.SUBGROUP_INCLUSIVE_ADD = "subgroupInclusiveAdd";
20561SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_AND = "subgroupExclusiveAdd";
20562SubgroupFunctionNode.SUBGROUP_MUL = "subgroupMul";
20563SubgroupFunctionNode.SUBGROUP_INCLUSIVE_MUL = "subgroupInclusiveMul";
20564SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_MUL = "subgroupExclusiveMul";
20565SubgroupFunctionNode.SUBGROUP_AND = "subgroupAnd";
20566SubgroupFunctionNode.SUBGROUP_OR = "subgroupOr";
20567SubgroupFunctionNode.SUBGROUP_XOR = "subgroupXor";
20568SubgroupFunctionNode.SUBGROUP_MIN = "subgroupMin";
20569SubgroupFunctionNode.SUBGROUP_MAX = "subgroupMax";
20570SubgroupFunctionNode.SUBGROUP_ALL = "subgroupAll";
20571SubgroupFunctionNode.SUBGROUP_ANY = "subgroupAny";
20572SubgroupFunctionNode.SUBGROUP_BROADCAST_FIRST = "subgroupBroadcastFirst";
20573SubgroupFunctionNode.QUAD_SWAP_X = "quadSwapX";
20574SubgroupFunctionNode.QUAD_SWAP_Y = "quadSwapY";
20575SubgroupFunctionNode.QUAD_SWAP_DIAGONAL = "quadSwapDiagonal";
20576SubgroupFunctionNode.SUBGROUP_BROADCAST = "subgroupBroadcast";
20577SubgroupFunctionNode.SUBGROUP_SHUFFLE = "subgroupShuffle";
20578SubgroupFunctionNode.SUBGROUP_SHUFFLE_XOR = "subgroupShuffleXor";
20579SubgroupFunctionNode.SUBGROUP_SHUFFLE_UP = "subgroupShuffleUp";
20580SubgroupFunctionNode.SUBGROUP_SHUFFLE_DOWN = "subgroupShuffleDown";
20581SubgroupFunctionNode.QUAD_BROADCAST = "quadBroadcast";
20582var subgroupElect = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_ELECT).setParameterLength(0);
20583var subgroupBallot = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_BALLOT).setParameterLength(1);
20584var subgroupAdd = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_ADD).setParameterLength(1);
20585var subgroupInclusiveAdd = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_INCLUSIVE_ADD).setParameterLength(1);
20586var subgroupExclusiveAdd = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_AND).setParameterLength(1);
20587var subgroupMul = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_MUL).setParameterLength(1);
20588var subgroupInclusiveMul = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_INCLUSIVE_MUL).setParameterLength(1);
20589var subgroupExclusiveMul = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_MUL).setParameterLength(1);
20590var subgroupAnd = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_AND).setParameterLength(1);
20591var subgroupOr = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_OR).setParameterLength(1);
20592var subgroupXor = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_XOR).setParameterLength(1);
20593var subgroupMin = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_MIN).setParameterLength(1);
20594var subgroupMax = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_MAX).setParameterLength(1);
20595var subgroupAll = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_ALL).setParameterLength(0);
20596var subgroupAny = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_ANY).setParameterLength(0);
20597var subgroupBroadcastFirst = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_BROADCAST_FIRST).setParameterLength(2);
20598var quadSwapX = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.QUAD_SWAP_X).setParameterLength(1);
20599var quadSwapY = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.QUAD_SWAP_Y).setParameterLength(1);
20600var quadSwapDiagonal = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.QUAD_SWAP_DIAGONAL).setParameterLength(1);
20601var subgroupBroadcast = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_BROADCAST).setParameterLength(2);
20602var subgroupShuffle = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_SHUFFLE).setParameterLength(2);
20603var subgroupShuffleXor = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_SHUFFLE_XOR).setParameterLength(2);
20604var subgroupShuffleUp = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_SHUFFLE_UP).setParameterLength(2);
20605var subgroupShuffleDown = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.SUBGROUP_SHUFFLE_DOWN).setParameterLength(2);
20606var quadBroadcast = /* @__PURE__ */ nodeProxyIntent(SubgroupFunctionNode, SubgroupFunctionNode.QUAD_BROADCAST).setParameterLength(1);
20607var uniformsLib;
20608function getLightData(light) {
20609  uniformsLib = uniformsLib || /* @__PURE__ */ new WeakMap();
20610  let uniforms = uniformsLib.get(light);
20611  if (uniforms === void 0) uniformsLib.set(light, uniforms = {});
20612  return uniforms;
20613}
20614function lightShadowMatrix(light) {
20615  const data = getLightData(light);
20616  return data.shadowMatrix || (data.shadowMatrix = uniform("mat4").setGroup(renderGroup).onRenderUpdate((frame) => {
20617    if (light.castShadow !== true || frame.renderer.shadowMap.enabled === false) {
20618      if (light.shadow.camera.coordinateSystem !== frame.camera.coordinateSystem) {
20619        light.shadow.camera.coordinateSystem = frame.camera.coordinateSystem;
20620        light.shadow.camera.updateProjectionMatrix();
20621      }
20622      light.shadow.updateMatrices(light);
20623    }
20624    return light.shadow.matrix;
20625  }));
20626}
20627function lightProjectionUV(light, position = positionWorld) {
20628  const spotLightCoord = lightShadowMatrix(light).mul(position);
20629  const projectionUV = spotLightCoord.xyz.div(spotLightCoord.w);
20630  return projectionUV;
20631}
20632function lightPosition(light) {
20633  const data = getLightData(light);
20634  return data.position || (data.position = uniform(new Vector3()).setGroup(renderGroup).onRenderUpdate((_, self2) => self2.value.setFromMatrixPosition(light.matrixWorld)));
20635}
20636function lightTargetPosition(light) {
20637  const data = getLightData(light);
20638  return data.targetPosition || (data.targetPosition = uniform(new Vector3()).setGroup(renderGroup).onRenderUpdate((_, self2) => self2.value.setFromMatrixPosition(light.target.matrixWorld)));
20639}
20640function lightViewPosition(light) {
20641  const data = getLightData(light);
20642  return data.viewPosition || (data.viewPosition = uniform(new Vector3()).setGroup(renderGroup).onRenderUpdate(({ camera }, self2) => {
20643    self2.value = self2.value || new Vector3();
20644    self2.value.setFromMatrixPosition(light.matrixWorld);
20645    self2.value.applyMatrix4(camera.matrixWorldInverse);
20646  }));
20647}
20648var lightTargetDirection = (light) => cameraViewMatrix.transformDirection(lightPosition(light).sub(lightTargetPosition(light)));
20649var sortLights = (lights3) => {
20650  return lights3.sort((a, b) => a.id - b.id);
20651};
20652var getLightNodeById = (id, lightNodes) => {
20653  for (const lightNode of lightNodes) {
20654    if (lightNode.isAnalyticLightNode && lightNode.light.id === id) {
20655      return lightNode;
20656    }
20657  }
20658  return null;
20659};
20660var _lightsNodeRef = /* @__PURE__ */ new WeakMap();
20661var _hashData = [];
20662var LightsNode = class extends Node2 {
20663  static get type() {
20664    return "LightsNode";
20665  }
20666  /**
20667   * Constructs a new lights node.
20668   */
20669  constructor() {
20670    super("vec3");
20671    this.totalDiffuseNode = property("vec3", "totalDiffuse");
20672    this.totalSpecularNode = property("vec3", "totalSpecular");
20673    this.outgoingLightNode = property("vec3", "outgoingLight");
20674    this._lights = [];
20675    this._lightNodes = null;
20676    this._lightNodesHash = null;
20677    this.global = true;
20678  }
20679  /**
20680   * Overwrites the default {@link Node#customCacheKey} implementation by including
20681   * light data into the cache key.
20682   *
20683   * @return {number} The custom cache key.
20684   */
20685  customCacheKey() {
20686    const lights3 = this._lights;
20687    for (let i = 0; i < lights3.length; i++) {
20688      const light = lights3[i];
20689      _hashData.push(light.id);
20690      _hashData.push(light.castShadow ? 1 : 0);
20691      if (light.isSpotLight === true) {
20692        const hashMap = light.map !== null ? light.map.id : -1;
20693        const hashColorNode = light.colorNode ? light.colorNode.getCacheKey() : -1;
20694        _hashData.push(hashMap, hashColorNode);
20695      }
20696    }
20697    const cacheKey = hashArray(_hashData);
20698    _hashData.length = 0;
20699    return cacheKey;
20700  }
20701  /**
20702   * Computes a hash value for identifying the current light nodes setup.
20703   *
20704   * @param {NodeBuilder} builder - A reference to the current node builder.
20705   * @return {string} The computed hash.
20706   */
20707  getHash(builder) {
20708    if (this._lightNodesHash === null) {
20709      if (this._lightNodes === null) this.setupLightsNode(builder);
20710      const hash3 = [];
20711      for (const lightNode of this._lightNodes) {
20712        hash3.push(lightNode.getHash());
20713      }
20714      this._lightNodesHash = "lights-" + hash3.join(",");
20715    }
20716    return this._lightNodesHash;
20717  }
20718  analyze(builder) {
20719    const properties = builder.getNodeProperties(this);
20720    for (const node of properties.nodes) {
20721      node.build(builder);
20722    }
20723    properties.outputNode.build(builder);
20724  }
20725  /**
20726   * Creates lighting nodes for each scene light. This makes it possible to further
20727   * process lights in the node system.
20728   *
20729   * @param {NodeBuilder} builder - A reference to the current node builder.
20730   */
20731  setupLightsNode(builder) {
20732    const lightNodes = [];
20733    const previousLightNodes = this._lightNodes;
20734    const lights3 = sortLights(this._lights);
20735    const nodeLibrary = builder.renderer.library;
20736    for (const light of lights3) {
20737      if (light.isNode) {
20738        lightNodes.push(nodeObject(light));
20739      } else {
20740        let lightNode = null;
20741        if (previousLightNodes !== null) {
20742          lightNode = getLightNodeById(light.id, previousLightNodes);
20743        }
20744        if (lightNode === null) {
20745          const lightNodeClass = nodeLibrary.getLightNodeClass(light.constructor);
20746          if (lightNodeClass === null) {
20747            warn(`LightsNode.setupNodeLights: Light node not found for ${light.constructor.name}`);
20748            continue;
20749          }
20750          if (_lightsNodeRef.has(light) === false) {
20751            _lightsNodeRef.set(light, new lightNodeClass(light));
20752          }
20753          lightNode = _lightsNodeRef.get(light);
20754        }
20755        lightNodes.push(lightNode);
20756      }
20757    }
20758    this._lightNodes = lightNodes;
20759  }
20760  /**
20761   * Sets up a direct light in the lighting model.
20762   *
20763   * @param {Object} builder - The builder object containing the context and stack.
20764   * @param {Object} lightNode - The light node.
20765   * @param {Object} lightData - The light object containing color and direction properties.
20766   */
20767  setupDirectLight(builder, lightNode, lightData) {
20768    const { lightingModel, reflectedLight } = builder.context;
20769    lightingModel.direct({
20770      ...lightData,
20771      lightNode,
20772      reflectedLight
20773    }, builder);
20774  }
20775  setupDirectRectAreaLight(builder, lightNode, lightData) {
20776    const { lightingModel, reflectedLight } = builder.context;
20777    lightingModel.directRectArea({
20778      ...lightData,
20779      lightNode,
20780      reflectedLight
20781    }, builder);
20782  }
20783  /**
20784   * Setups the internal lights by building all respective
20785   * light nodes.
20786   *
20787   * @param {NodeBuilder} builder - A reference to the current node builder.
20788   * @param {Array<LightingNode>} lightNodes - An array of lighting nodes.
20789   */
20790  setupLights(builder, lightNodes) {
20791    for (const lightNode of lightNodes) {
20792      lightNode.build(builder);
20793    }
20794  }
20795  getLightNodes(builder) {
20796    if (this._lightNodes === null) this.setupLightsNode(builder);
20797    return this._lightNodes;
20798  }
20799  /**
20800   * The implementation makes sure that for each light in the scene
20801   * there is a corresponding light node. By building the light nodes
20802   * and evaluating the lighting model the outgoing light is computed.
20803   *
20804   * @param {NodeBuilder} builder - A reference to the current node builder.
20805   * @return {Node<vec3>} A node representing the outgoing light.
20806   */
20807  setup(builder) {
20808    const currentLightsNode = builder.lightsNode;
20809    builder.lightsNode = this;
20810    let outgoingLightNode = this.outgoingLightNode;
20811    const context3 = builder.context;
20812    const lightingModel = context3.lightingModel;
20813    const properties = builder.getNodeProperties(this);
20814    if (lightingModel) {
20815      const { totalDiffuseNode, totalSpecularNode } = this;
20816      context3.outgoingLight = outgoingLightNode;
20817      const stack3 = builder.addStack();
20818      properties.nodes = stack3.nodes;
20819      lightingModel.start(builder);
20820      const { backdrop, backdropAlpha } = context3;
20821      const { directDiffuse, directSpecular, indirectDiffuse, indirectSpecular } = context3.reflectedLight;
20822      let totalDiffuse = directDiffuse.add(indirectDiffuse);
20823      if (backdrop !== null) {
20824        if (backdropAlpha !== null) {
20825          totalDiffuse = vec3(backdropAlpha.mix(totalDiffuse, backdrop));
20826        } else {
20827          totalDiffuse = vec3(backdrop);
20828        }
20829      }
20830      totalDiffuseNode.assign(totalDiffuse);
20831      totalSpecularNode.assign(directSpecular.add(indirectSpecular));
20832      outgoingLightNode.assign(totalDiffuseNode.add(totalSpecularNode));
20833      lightingModel.finish(builder);
20834      outgoingLightNode = outgoingLightNode.bypass(builder.removeStack());
20835    } else {
20836      properties.nodes = [];
20837    }
20838    builder.lightsNode = currentLightsNode;
20839    return outgoingLightNode;
20840  }
20841  /**
20842   * Configures this node with an array of lights.
20843   *
20844   * @param {Array<Light>} lights - An array of lights.
20845   * @return {LightsNode} A reference to this node.
20846   */
20847  setLights(lights3) {
20848    this._lights = lights3;
20849    this._lightNodes = null;
20850    this._lightNodesHash = null;
20851    return this;
20852  }
20853  /**
20854   * Returns an array of the scene's lights.
20855   *
20856   * @return {Array<Light>} The scene's lights.
20857   */
20858  getLights() {
20859    return this._lights;
20860  }
20861  /**
20862   * Whether the scene has lights or not.
20863   *
20864   * @type {boolean}
20865   */
20866  get hasLights() {
20867    return this._lights.length > 0;
20868  }
20869};
20870var lights = (lights3 = []) => new LightsNode().setLights(lights3);
20871var ShadowBaseNode = class extends Node2 {
20872  static get type() {
20873    return "ShadowBaseNode";
20874  }
20875  /**
20876   * Constructs a new shadow base node.
20877   *
20878   * @param {Light} light - The shadow casting light.
20879   */
20880  constructor(light) {
20881    super();
20882    this.light = light;
20883    this.updateBeforeType = NodeUpdateType.RENDER;
20884    this.isShadowBaseNode = true;
20885  }
20886  /**
20887   * Setups the shadow position node which is by default the predefined TSL node object `shadowPositionWorld`.
20888   *
20889   * @param {NodeBuilder} object - A configuration object that must at least hold a material reference.
20890   */
20891  setupShadowPosition({ context: context3, material }) {
20892    shadowPositionWorld.assign(material.receivedShadowPositionNode || context3.shadowPositionWorld || positionWorld);
20893  }
20894};
20895var shadowPositionWorld = /* @__PURE__ */ property("vec3", "shadowPositionWorld");
20896function saveRendererState(renderer, state = {}) {
20897  state.toneMapping = renderer.toneMapping;
20898  state.toneMappingExposure = renderer.toneMappingExposure;
20899  state.outputColorSpace = renderer.outputColorSpace;
20900  state.renderTarget = renderer.getRenderTarget();
20901  state.activeCubeFace = renderer.getActiveCubeFace();
20902  state.activeMipmapLevel = renderer.getActiveMipmapLevel();
20903  state.renderObjectFunction = renderer.getRenderObjectFunction();
20904  state.pixelRatio = renderer.getPixelRatio();
20905  state.mrt = renderer.getMRT();
20906  state.clearColor = renderer.getClearColor(state.clearColor || new Color());
20907  state.clearAlpha = renderer.getClearAlpha();
20908  state.autoClear = renderer.autoClear;
20909  state.scissorTest = renderer.getScissorTest();
20910  return state;
20911}
20912function resetRendererState(renderer, state) {
20913  state = saveRendererState(renderer, state);
20914  renderer.setMRT(null);
20915  renderer.setRenderObjectFunction(null);
20916  renderer.setClearColor(0, 1);
20917  renderer.autoClear = true;
20918  return state;
20919}
20920function restoreRendererState(renderer, state) {
20921  renderer.toneMapping = state.toneMapping;
20922  renderer.toneMappingExposure = state.toneMappingExposure;
20923  renderer.outputColorSpace = state.outputColorSpace;
20924  renderer.setRenderTarget(state.renderTarget, state.activeCubeFace, state.activeMipmapLevel);
20925  renderer.setRenderObjectFunction(state.renderObjectFunction);
20926  renderer.setPixelRatio(state.pixelRatio);
20927  renderer.setMRT(state.mrt);
20928  renderer.setClearColor(state.clearColor, state.clearAlpha);
20929  renderer.autoClear = state.autoClear;
20930  renderer.setScissorTest(state.scissorTest);
20931}
20932function saveSceneState(scene, state = {}) {
20933  state.background = scene.background;
20934  state.backgroundNode = scene.backgroundNode;
20935  state.overrideMaterial = scene.overrideMaterial;
20936  return state;
20937}
20938function resetSceneState(scene, state) {
20939  state = saveSceneState(scene, state);
20940  scene.background = null;
20941  scene.backgroundNode = null;
20942  scene.overrideMaterial = null;
20943  return state;
20944}
20945function restoreSceneState(scene, state) {
20946  scene.background = state.background;
20947  scene.backgroundNode = state.backgroundNode;
20948  scene.overrideMaterial = state.overrideMaterial;
20949}
20950function resetRendererAndSceneState(renderer, scene, state) {
20951  state = resetRendererState(renderer, state);
20952  state = resetSceneState(scene, state);
20953  return state;
20954}
20955function restoreRendererAndSceneState(renderer, scene, state) {
20956  restoreRendererState(renderer, state);
20957  restoreSceneState(scene, state);
20958}
20959var shadowMaterialLib = /* @__PURE__ */ new WeakMap();
20960var BasicShadowFilter = /* @__PURE__ */ Fn(({ depthTexture, shadowCoord, depthLayer }) => {
20961  let basic = texture(depthTexture, shadowCoord.xy).setName("t_basic");
20962  if (depthTexture.isArrayTexture) {
20963    basic = basic.depth(depthLayer);
20964  }
20965  return basic.compare(shadowCoord.z);
20966});
20967var PCFShadowFilter = /* @__PURE__ */ Fn(({ depthTexture, shadowCoord, shadow: shadow3, depthLayer }) => {
20968  const depthCompare = (uv3, compare5) => {
20969    let depth3 = texture(depthTexture, uv3);
20970    if (depthTexture.isArrayTexture) {
20971      depth3 = depth3.depth(depthLayer);
20972    }
20973    return depth3.compare(compare5);
20974  };
20975  const mapSize = reference("mapSize", "vec2", shadow3).setGroup(renderGroup);
20976  const radius = reference("radius", "float", shadow3).setGroup(renderGroup);
20977  const texelSize = vec2(1).div(mapSize);
20978  const radiusScaled = radius.mul(texelSize.x);
20979  const phi = interleavedGradientNoise(screenCoordinate.xy).mul(6.28318530718);
20980  return add(
20981    depthCompare(shadowCoord.xy.add(vogelDiskSample(0, 5, phi).mul(radiusScaled)), shadowCoord.z),
20982    depthCompare(shadowCoord.xy.add(vogelDiskSample(1, 5, phi).mul(radiusScaled)), shadowCoord.z),
20983    depthCompare(shadowCoord.xy.add(vogelDiskSample(2, 5, phi).mul(radiusScaled)), shadowCoord.z),
20984    depthCompare(shadowCoord.xy.add(vogelDiskSample(3, 5, phi).mul(radiusScaled)), shadowCoord.z),
20985    depthCompare(shadowCoord.xy.add(vogelDiskSample(4, 5, phi).mul(radiusScaled)), shadowCoord.z)
20986  ).mul(1 / 5);
20987});
20988var PCFSoftShadowFilter = /* @__PURE__ */ Fn(({ depthTexture, shadowCoord, shadow: shadow3, depthLayer }) => {
20989  const depthCompare = (uv4, compare5) => {
20990    let depth3 = texture(depthTexture, uv4);
20991    if (depthTexture.isArrayTexture) {
20992      depth3 = depth3.depth(depthLayer);
20993    }
20994    return depth3.compare(compare5);
20995  };
20996  const mapSize = reference("mapSize", "vec2", shadow3).setGroup(renderGroup);
20997  const texelSize = vec2(1).div(mapSize);
20998  const dx = texelSize.x;
20999  const dy = texelSize.y;
21000  const uv3 = shadowCoord.xy;
21001  const f = fract(uv3.mul(mapSize).add(0.5));
21002  uv3.subAssign(f.mul(texelSize));
21003  return add(
21004    depthCompare(uv3, shadowCoord.z),
21005    depthCompare(uv3.add(vec2(dx, 0)), shadowCoord.z),
21006    depthCompare(uv3.add(vec2(0, dy)), shadowCoord.z),
21007    depthCompare(uv3.add(texelSize), shadowCoord.z),
21008    mix(
21009      depthCompare(uv3.add(vec2(dx.negate(), 0)), shadowCoord.z),
21010      depthCompare(uv3.add(vec2(dx.mul(2), 0)), shadowCoord.z),
21011      f.x
21012    ),
21013    mix(
21014      depthCompare(uv3.add(vec2(dx.negate(), dy)), shadowCoord.z),
21015      depthCompare(uv3.add(vec2(dx.mul(2), dy)), shadowCoord.z),
21016      f.x
21017    ),
21018    mix(
21019      depthCompare(uv3.add(vec2(0, dy.negate())), shadowCoord.z),
21020      depthCompare(uv3.add(vec2(0, dy.mul(2))), shadowCoord.z),
21021      f.y
21022    ),
21023    mix(
21024      depthCompare(uv3.add(vec2(dx, dy.negate())), shadowCoord.z),
21025      depthCompare(uv3.add(vec2(dx, dy.mul(2))), shadowCoord.z),
21026      f.y
21027    ),
21028    mix(
21029      mix(
21030        depthCompare(uv3.add(vec2(dx.negate(), dy.negate())), shadowCoord.z),
21031        depthCompare(uv3.add(vec2(dx.mul(2), dy.negate())), shadowCoord.z),
21032        f.x
21033      ),
21034      mix(
21035        depthCompare(uv3.add(vec2(dx.negate(), dy.mul(2))), shadowCoord.z),
21036        depthCompare(uv3.add(vec2(dx.mul(2), dy.mul(2))), shadowCoord.z),
21037        f.x
21038      ),
21039      f.y
21040    )
21041  ).mul(1 / 9);
21042});
21043var VSMShadowFilter = /* @__PURE__ */ Fn(({ depthTexture, shadowCoord, depthLayer }, builder) => {
21044  let distribution = texture(depthTexture).sample(shadowCoord.xy);
21045  if (depthTexture.isArrayTexture) {
21046    distribution = distribution.depth(depthLayer);
21047  }
21048  distribution = distribution.rg;
21049  const mean = distribution.x;
21050  const variance = max$1(1e-7, distribution.y.mul(distribution.y));
21051  const hardShadow = builder.renderer.reversedDepthBuffer ? step(mean, shadowCoord.z) : step(shadowCoord.z, mean);
21052  const output3 = float(1).toVar();
21053  If(hardShadow.notEqual(1), () => {
21054    const d = shadowCoord.z.sub(mean);
21055    let p_max = variance.div(variance.add(d.mul(d)));
21056    p_max = clamp(sub(p_max, 0.3).div(0.65));
21057    output3.assign(max$1(hardShadow, p_max));
21058  });
21059  return output3;
21060});
21061var getShadowMaterial = (light) => {
21062  let material = shadowMaterialLib.get(light);
21063  if (material === void 0) {
21064    material = new NodeMaterial();
21065    material.colorNode = vec4(0, 0, 0, 1);
21066    material.isShadowPassMaterial = true;
21067    material.name = "ShadowMaterial";
21068    material.blending = NoBlending;
21069    material.fog = false;
21070    shadowMaterialLib.set(light, material);
21071  }
21072  return material;
21073};
21074var disposeShadowMaterial = (light) => {
21075  const material = shadowMaterialLib.get(light);
21076  if (material !== void 0) {
21077    material.dispose();
21078    shadowMaterialLib.delete(light);
21079  }
21080};
21081var _shadowRenderObjectLibrary = /* @__PURE__ */ new ChainMap();
21082var _shadowRenderObjectKeys = [];
21083var getShadowRenderObjectFunction = (renderer, shadow3, shadowType, useVelocity) => {
21084  _shadowRenderObjectKeys[0] = renderer;
21085  _shadowRenderObjectKeys[1] = shadow3;
21086  let renderObjectFunction = _shadowRenderObjectLibrary.get(_shadowRenderObjectKeys);
21087  if (renderObjectFunction === void 0 || (renderObjectFunction.shadowType !== shadowType || renderObjectFunction.useVelocity !== useVelocity)) {
21088    renderObjectFunction = (object, scene, _camera2, geometry, material, group, ...params) => {
21089      if (object.castShadow === true || object.receiveShadow && shadowType === VSMShadowMap) {
21090        if (useVelocity) {
21091          getDataFromObject(object).useVelocity = true;
21092        }
21093        object.onBeforeShadow(renderer, object, _camera2, shadow3.camera, geometry, scene.overrideMaterial, group);
21094        renderer.renderObject(object, scene, _camera2, geometry, material, group, ...params);
21095        object.onAfterShadow(renderer, object, _camera2, shadow3.camera, geometry, scene.overrideMaterial, group);
21096      }
21097    };
21098    renderObjectFunction.shadowType = shadowType;
21099    renderObjectFunction.useVelocity = useVelocity;
21100    _shadowRenderObjectLibrary.set(_shadowRenderObjectKeys, renderObjectFunction);
21101  }
21102  _shadowRenderObjectKeys[0] = null;
21103  _shadowRenderObjectKeys[1] = null;
21104  return renderObjectFunction;
21105};
21106var VSMPassVertical = /* @__PURE__ */ Fn(({ samples, radius, size: size3, shadowPass, depthLayer }) => {
21107  const mean = float(0).toVar("meanVertical");
21108  const squaredMean = float(0).toVar("squareMeanVertical");
21109  const uvStride = samples.lessThanEqual(float(1)).select(float(0), float(2).div(samples.sub(1)));
21110  const uvStart = samples.lessThanEqual(float(1)).select(float(0), float(-1));
21111  Loop({ start: int(0), end: int(samples), type: "int", condition: "<" }, ({ i }) => {
21112    const uvOffset = uvStart.add(float(i).mul(uvStride));
21113    let depth3 = shadowPass.sample(add(screenCoordinate.xy, vec2(0, uvOffset).mul(radius)).div(size3));
21114    if (shadowPass.value.isArrayTexture) {
21115      depth3 = depth3.depth(depthLayer);
21116    }
21117    depth3 = depth3.x;
21118    mean.addAssign(depth3);
21119    squaredMean.addAssign(depth3.mul(depth3));
21120  });
21121  mean.divAssign(samples);
21122  squaredMean.divAssign(samples);
21123  const std_dev = sqrt(squaredMean.sub(mean.mul(mean)).max(0));
21124  return vec2(mean, std_dev);
21125});
21126var VSMPassHorizontal = /* @__PURE__ */ Fn(({ samples, radius, size: size3, shadowPass, depthLayer }) => {
21127  const mean = float(0).toVar("meanHorizontal");
21128  const squaredMean = float(0).toVar("squareMeanHorizontal");
21129  const uvStride = samples.lessThanEqual(float(1)).select(float(0), float(2).div(samples.sub(1)));
21130  const uvStart = samples.lessThanEqual(float(1)).select(float(0), float(-1));
21131  Loop({ start: int(0), end: int(samples), type: "int", condition: "<" }, ({ i }) => {
21132    const uvOffset = uvStart.add(float(i).mul(uvStride));
21133    let distribution = shadowPass.sample(add(screenCoordinate.xy, vec2(uvOffset, 0).mul(radius)).div(size3));
21134    if (shadowPass.value.isArrayTexture) {
21135      distribution = distribution.depth(depthLayer);
21136    }
21137    mean.addAssign(distribution.x);
21138    squaredMean.addAssign(add(distribution.y.mul(distribution.y), distribution.x.mul(distribution.x)));
21139  });
21140  mean.divAssign(samples);
21141  squaredMean.divAssign(samples);
21142  const std_dev = sqrt(squaredMean.sub(mean.mul(mean)).max(0));
21143  return vec2(mean, std_dev);
21144});
21145var _shadowFilterLib = [BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilter, VSMShadowFilter];
21146var _rendererState;
21147var _quadMesh = /* @__PURE__ */ new QuadMesh();
21148var ShadowNode = class extends ShadowBaseNode {
21149  static get type() {
21150    return "ShadowNode";
21151  }
21152  /**
21153   * Constructs a new shadow node.
21154   *
21155   * @param {Light} light - The shadow casting light.
21156   * @param {?LightShadow} [shadow=null] - An optional light shadow.
21157   */
21158  constructor(light, shadow3 = null) {
21159    super(light);
21160    this.shadow = shadow3 || light.shadow;
21161    this.shadowMap = null;
21162    this.vsmShadowMapVertical = null;
21163    this.vsmShadowMapHorizontal = null;
21164    this.vsmMaterialVertical = null;
21165    this.vsmMaterialHorizontal = null;
21166    this._node = null;
21167    this._currentShadowType = null;
21168    this._cameraFrameId = /* @__PURE__ */ new WeakMap();
21169    this.isShadowNode = true;
21170    this.depthLayer = 0;
21171  }
21172  /**
21173   * Setups the shadow filtering.
21174   *
21175   * @param {NodeBuilder} builder - A reference to the current node builder.
21176   * @param {Object} inputs - A configuration object that defines the shadow filtering.
21177   * @param {Function} inputs.filterFn - This function defines the filtering type of the shadow map e.g. PCF.
21178   * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
21179   * @param {Node<vec3>} inputs.shadowCoord - Shadow coordinates which are used to sample from the shadow map.
21180   * @param {LightShadow} inputs.shadow - The light shadow.
21181   * @return {Node<float>} The result node of the shadow filtering.
21182   */
21183  setupShadowFilter(builder, { filterFn, depthTexture, shadowCoord, shadow: shadow3, depthLayer }) {
21184    const frustumTest = shadowCoord.x.greaterThanEqual(0).and(shadowCoord.x.lessThanEqual(1)).and(shadowCoord.y.greaterThanEqual(0)).and(shadowCoord.y.lessThanEqual(1)).and(shadowCoord.z.lessThanEqual(1));
21185    const shadowNode = filterFn({ depthTexture, shadowCoord, shadow: shadow3, depthLayer });
21186    return frustumTest.select(shadowNode, float(1));
21187  }
21188  /**
21189   * Setups the shadow coordinates.
21190   *
21191   * @param {NodeBuilder} builder - A reference to the current node builder.
21192   * @param {Node<vec3>} shadowPosition - A node representing the shadow position.
21193   * @return {Node<vec3>} The shadow coordinates.
21194   */
21195  setupShadowCoord(builder, shadowPosition) {
21196    const { shadow: shadow3 } = this;
21197    const { renderer } = builder;
21198    const bias = shadow3.biasNode || reference("bias", "float", shadow3).setGroup(renderGroup);
21199    let shadowCoord = shadowPosition;
21200    let coordZ;
21201    if (shadow3.camera.isOrthographicCamera || renderer.logarithmicDepthBuffer !== true) {
21202      shadowCoord = shadowCoord.xyz.div(shadowCoord.w);
21203      coordZ = shadowCoord.z;
21204    } else {
21205      const w = shadowCoord.w;
21206      shadowCoord = shadowCoord.xy.div(w);
21207      const cameraNearLocal = reference("near", "float", shadow3.camera).setGroup(renderGroup);
21208      const cameraFarLocal = reference("far", "float", shadow3.camera).setGroup(renderGroup);
21209      coordZ = viewZToLogarithmicDepth(w.negate(), cameraNearLocal, cameraFarLocal);
21210    }
21211    shadowCoord = vec3(
21212      shadowCoord.x,
21213      shadowCoord.y.oneMinus(),
21214      // follow webgpu standards
21215      renderer.reversedDepthBuffer ? coordZ.sub(bias) : coordZ.add(bias)
21216    );
21217    return shadowCoord;
21218  }
21219  /**
21220   * Returns the shadow filtering function for the given shadow type.
21221   *
21222   * @param {number} type - The shadow type.
21223   * @return {Function} The filtering function.
21224   */
21225  getShadowFilterFn(type) {
21226    return _shadowFilterLib[type];
21227  }
21228  setupRenderTarget(shadow3, builder) {
21229    const depthTexture = new DepthTexture(shadow3.mapSize.width, shadow3.mapSize.height);
21230    depthTexture.name = "ShadowDepthTexture";
21231    depthTexture.compareFunction = builder.renderer.reversedDepthBuffer ? GreaterEqualCompare : LessEqualCompare;
21232    const shadowMap = builder.createRenderTarget(shadow3.mapSize.width, shadow3.mapSize.height);
21233    shadowMap.texture.name = "ShadowMap";
21234    shadowMap.texture.type = shadow3.mapType;
21235    shadowMap.depthTexture = depthTexture;
21236    return { shadowMap, depthTexture };
21237  }
21238  /**
21239   * Setups the shadow output node.
21240   *
21241   * @param {NodeBuilder} builder - A reference to the current node builder.
21242   * @return {Node<vec3>} The shadow output node.
21243   */
21244  setupShadow(builder) {
21245    const { renderer, camera } = builder;
21246    const { light, shadow: shadow3 } = this;
21247    const { depthTexture, shadowMap } = this.setupRenderTarget(shadow3, builder);
21248    const shadowMapType = renderer.shadowMap.type;
21249    const hasTextureCompare = renderer.hasCompatibility(Compatibility.TEXTURE_COMPARE);
21250    if ((shadowMapType === PCFShadowMap || shadowMapType === PCFSoftShadowMap) && hasTextureCompare) {
21251      depthTexture.minFilter = LinearFilter;
21252      depthTexture.magFilter = LinearFilter;
21253    } else {
21254      depthTexture.minFilter = NearestFilter;
21255      depthTexture.magFilter = NearestFilter;
21256    }
21257    shadow3.camera.coordinateSystem = camera.coordinateSystem;
21258    shadow3.camera.updateProjectionMatrix();
21259    if (shadowMapType === VSMShadowMap && shadow3.isPointLightShadow !== true) {
21260      depthTexture.compareFunction = null;
21261      if (shadowMap.depth > 1) {
21262        if (!shadowMap._vsmShadowMapVertical) {
21263          shadowMap._vsmShadowMapVertical = builder.createRenderTarget(shadow3.mapSize.width, shadow3.mapSize.height, { format: RGFormat, type: HalfFloatType, depth: shadowMap.depth, depthBuffer: false });
21264          shadowMap._vsmShadowMapVertical.texture.name = "VSMVertical";
21265        }
21266        this.vsmShadowMapVertical = shadowMap._vsmShadowMapVertical;
21267        if (!shadowMap._vsmShadowMapHorizontal) {
21268          shadowMap._vsmShadowMapHorizontal = builder.createRenderTarget(shadow3.mapSize.width, shadow3.mapSize.height, { format: RGFormat, type: HalfFloatType, depth: shadowMap.depth, depthBuffer: false });
21269          shadowMap._vsmShadowMapHorizontal.texture.name = "VSMHorizontal";
21270        }
21271        this.vsmShadowMapHorizontal = shadowMap._vsmShadowMapHorizontal;
21272      } else {
21273        this.vsmShadowMapVertical = builder.createRenderTarget(shadow3.mapSize.width, shadow3.mapSize.height, { format: RGFormat, type: HalfFloatType, depthBuffer: false });
21274        this.vsmShadowMapHorizontal = builder.createRenderTarget(shadow3.mapSize.width, shadow3.mapSize.height, { format: RGFormat, type: HalfFloatType, depthBuffer: false });
21275      }
21276      let shadowPassVertical = texture(depthTexture);
21277      if (depthTexture.isArrayTexture) {
21278        shadowPassVertical = shadowPassVertical.depth(this.depthLayer);
21279      }
21280      let shadowPassHorizontal = texture(this.vsmShadowMapVertical.texture);
21281      if (depthTexture.isArrayTexture) {
21282        shadowPassHorizontal = shadowPassHorizontal.depth(this.depthLayer);
21283      }
21284      const samples = reference("blurSamples", "float", shadow3).setGroup(renderGroup);
21285      const radius = reference("radius", "float", shadow3).setGroup(renderGroup);
21286      const size3 = reference("mapSize", "vec2", shadow3).setGroup(renderGroup);
21287      let material = this.vsmMaterialVertical || (this.vsmMaterialVertical = new NodeMaterial());
21288      material.fragmentNode = VSMPassVertical({ samples, radius, size: size3, shadowPass: shadowPassVertical, depthLayer: this.depthLayer }).context(builder.getSharedContext());
21289      material.name = "VSMVertical";
21290      material = this.vsmMaterialHorizontal || (this.vsmMaterialHorizontal = new NodeMaterial());
21291      material.fragmentNode = VSMPassHorizontal({ samples, radius, size: size3, shadowPass: shadowPassHorizontal, depthLayer: this.depthLayer }).context(builder.getSharedContext());
21292      material.name = "VSMHorizontal";
21293    }
21294    const shadowIntensity = reference("intensity", "float", shadow3).setGroup(renderGroup);
21295    const normalBias = reference("normalBias", "float", shadow3).setGroup(renderGroup);
21296    const shadowMatrix = lightShadowMatrix(light);
21297    const shadowNormalBias = normalWorld.mul(normalBias);
21298    let shadowPosition;
21299    if (!renderer.highPrecision || builder.material.receivedShadowPositionNode || builder.context.shadowPositionWorld) {
21300      shadowPosition = shadowMatrix.mul(shadowPositionWorld.add(shadowNormalBias));
21301    } else {
21302      const highpShadowModelMatrix = uniform("mat4").onObjectUpdate(({ object }, self2) => {
21303        return self2.value.multiplyMatrices(shadowMatrix.value, object.matrixWorld);
21304      });
21305      shadowPosition = highpShadowModelMatrix.mul(positionLocal).add(shadowMatrix.mul(vec4(shadowNormalBias, 0)));
21306    }
21307    const shadowCoord = this.setupShadowCoord(builder, shadowPosition);
21308    const filterFn = shadow3.filterNode || this.getShadowFilterFn(renderer.shadowMap.type) || null;
21309    if (filterFn === null) {
21310      throw new Error("THREE.WebGPURenderer: Shadow map type not supported yet.");
21311    }
21312    const shadowDepthTexture = shadowMapType === VSMShadowMap && shadow3.isPointLightShadow !== true ? this.vsmShadowMapHorizontal.texture : depthTexture;
21313    const shadowNode = this.setupShadowFilter(builder, { filterFn, shadowTexture: shadowMap.texture, depthTexture: shadowDepthTexture, shadowCoord, shadow: shadow3, depthLayer: this.depthLayer });
21314    let shadowColor;
21315    if (renderer.shadowMap.transmitted === true) {
21316      if (shadowMap.texture.isCubeTexture) {
21317        shadowColor = cubeTexture(shadowMap.texture, shadowCoord.xyz);
21318      } else {
21319        shadowColor = texture(shadowMap.texture, shadowCoord);
21320        if (depthTexture.isArrayTexture) {
21321          shadowColor = shadowColor.depth(this.depthLayer);
21322        }
21323      }
21324    }
21325    let shadowOutput;
21326    if (shadowColor) {
21327      shadowOutput = mix(1, shadowNode.rgb.mix(shadowColor, 1), shadowIntensity.mul(shadowColor.a)).toVar();
21328    } else {
21329      shadowOutput = mix(1, shadowNode, shadowIntensity).toVar();
21330    }
21331    this.shadowMap = shadowMap;
21332    this.shadow.map = shadowMap;
21333    const inspectName = `${this.light.type} Shadow [ ${this.light.name || "ID: " + this.light.id} ]`;
21334    if (shadowColor) {
21335      shadowOutput.toInspector(`${inspectName} / Color`, () => {
21336        if (this.shadowMap.texture.isCubeTexture) {
21337          return cubeTexture(this.shadowMap.texture);
21338        }
21339        return texture(this.shadowMap.texture);
21340      });
21341    }
21342    return shadowOutput.toInspector(`${inspectName} / Depth`, () => {
21343      if (this.shadowMap.texture.isCubeTexture) {
21344        return cubeTexture(this.shadowMap.texture).r.oneMinus();
21345      }
21346      return textureLoad(this.shadowMap.depthTexture, uv$1().mul(textureSize(texture(this.shadowMap.depthTexture)))).r.oneMinus();
21347    });
21348  }
21349  /**
21350   * The implementation performs the setup of the output node. An output is only
21351   * produces if shadow mapping is globally enabled in the renderer.
21352   *
21353   * @param {NodeBuilder} builder - A reference to the current node builder.
21354   * @return {ShaderCallNodeInternal} The output node.
21355   */
21356  setup(builder) {
21357    if (builder.renderer.shadowMap.enabled === false) return;
21358    return Fn(() => {
21359      const currentShadowType = builder.renderer.shadowMap.type;
21360      if (this._currentShadowType !== currentShadowType) {
21361        this._reset();
21362        this._node = null;
21363      }
21364      let node = this._node;
21365      this.setupShadowPosition(builder);
21366      if (node === null) {
21367        this._node = node = this.setupShadow(builder);
21368        this._currentShadowType = currentShadowType;
21369      }
21370      if (builder.material.receivedShadowNode) {
21371        node = builder.material.receivedShadowNode(node);
21372      }
21373      return node;
21374    })();
21375  }
21376  /**
21377   * Renders the shadow. The logic of this function could be included
21378   * into {@link ShadowNode#updateShadow} however more specialized shadow
21379   * nodes might require a custom shadow map rendering. By having a
21380   * dedicated method, it's easier to overwrite the default behavior.
21381   *
21382   * @param {NodeFrame} frame - A reference to the current node frame.
21383   */
21384  renderShadow(frame) {
21385    const { shadow: shadow3, shadowMap, light } = this;
21386    const { renderer, scene } = frame;
21387    shadow3.updateMatrices(light);
21388    shadowMap.setSize(shadow3.mapSize.width, shadow3.mapSize.height, shadowMap.depth);
21389    const currentSceneName = scene.name;
21390    scene.name = `Shadow Map [ ${light.name || "ID: " + light.id} ]`;
21391    renderer.render(scene, shadow3.camera);
21392    scene.name = currentSceneName;
21393  }
21394  /**
21395   * Updates the shadow.
21396   *
21397   * @param {NodeFrame} frame - A reference to the current node frame.
21398   */
21399  updateShadow(frame) {
21400    const { shadowMap, light, shadow: shadow3 } = this;
21401    const { renderer, scene, camera } = frame;
21402    const shadowType = renderer.shadowMap.type;
21403    const depthVersion = shadowMap.depthTexture.version;
21404    this._depthVersionCached = depthVersion;
21405    const _shadowCameraLayer = shadow3.camera.layers.mask;
21406    if ((shadow3.camera.layers.mask & 4294967294) === 0) {
21407      shadow3.camera.layers.mask = camera.layers.mask;
21408    }
21409    const currentRenderObjectFunction = renderer.getRenderObjectFunction();
21410    const currentMRT = renderer.getMRT();
21411    const useVelocity = currentMRT ? currentMRT.has("velocity") : false;
21412    _rendererState = resetRendererAndSceneState(renderer, scene, _rendererState);
21413    scene.overrideMaterial = getShadowMaterial(light);
21414    renderer.setRenderObjectFunction(getShadowRenderObjectFunction(renderer, shadow3, shadowType, useVelocity));
21415    renderer.setClearColor(0, 0);
21416    renderer.setRenderTarget(shadowMap);
21417    this.renderShadow(frame);
21418    renderer.setRenderObjectFunction(currentRenderObjectFunction);
21419    if (shadowType === VSMShadowMap && shadow3.isPointLightShadow !== true) {
21420      this.vsmPass(renderer);
21421    }
21422    shadow3.camera.layers.mask = _shadowCameraLayer;
21423    restoreRendererAndSceneState(renderer, scene, _rendererState);
21424  }
21425  /**
21426   * For VSM additional render passes are required.
21427   *
21428   * @param {Renderer} renderer - A reference to the current renderer.
21429   */
21430  vsmPass(renderer) {
21431    const { shadow: shadow3 } = this;
21432    const depth3 = this.shadowMap.depth;
21433    this.vsmShadowMapVertical.setSize(shadow3.mapSize.width, shadow3.mapSize.height, depth3);
21434    this.vsmShadowMapHorizontal.setSize(shadow3.mapSize.width, shadow3.mapSize.height, depth3);
21435    renderer.setRenderTarget(this.vsmShadowMapVertical);
21436    _quadMesh.material = this.vsmMaterialVertical;
21437    _quadMesh.render(renderer);
21438    renderer.setRenderTarget(this.vsmShadowMapHorizontal);
21439    _quadMesh.material = this.vsmMaterialHorizontal;
21440    _quadMesh.render(renderer);
21441  }
21442  /**
21443   * Frees the internal resources of this shadow node.
21444   */
21445  dispose() {
21446    this._reset();
21447    super.dispose();
21448  }
21449  /**
21450   * Resets the resouce state of this shadow node.
21451   *
21452   * @private
21453   */
21454  _reset() {
21455    this._currentShadowType = null;
21456    disposeShadowMaterial(this.light);
21457    if (this.shadowMap) {
21458      this.shadowMap.dispose();
21459      this.shadowMap = null;
21460    }
21461    if (this.vsmShadowMapVertical !== null) {
21462      this.vsmShadowMapVertical.dispose();
21463      this.vsmShadowMapVertical = null;
21464      this.vsmMaterialVertical.dispose();
21465      this.vsmMaterialVertical = null;
21466    }
21467    if (this.vsmShadowMapHorizontal !== null) {
21468      this.vsmShadowMapHorizontal.dispose();
21469      this.vsmShadowMapHorizontal = null;
21470      this.vsmMaterialHorizontal.dispose();
21471      this.vsmMaterialHorizontal = null;
21472    }
21473  }
21474  /**
21475   * The implementation performs the update of the shadow map if necessary.
21476   *
21477   * @param {NodeFrame} frame - A reference to the current node frame.
21478   */
21479  updateBefore(frame) {
21480    const { shadow: shadow3 } = this;
21481    let needsUpdate = shadow3.needsUpdate || shadow3.autoUpdate;
21482    if (needsUpdate) {
21483      if (this._cameraFrameId[frame.camera] === frame.frameId) {
21484        needsUpdate = false;
21485      }
21486      this._cameraFrameId[frame.camera] = frame.frameId;
21487    }
21488    if (needsUpdate) {
21489      this.updateShadow(frame);
21490      if (this.shadowMap.depthTexture.version === this._depthVersionCached) {
21491        shadow3.needsUpdate = false;
21492      }
21493    }
21494  }
21495};
21496var shadow = (light, shadow3) => new ShadowNode(light, shadow3);
21497var _clearColor$1 = /* @__PURE__ */ new Color();
21498var _projScreenMatrix$1 = /* @__PURE__ */ new Matrix4();
21499var _lightPositionWorld = /* @__PURE__ */ new Vector3();
21500var _lookTarget = /* @__PURE__ */ new Vector3();
21501var _cubeDirectionsWebGPU = [
21502  /* @__PURE__ */ new Vector3(1, 0, 0),
21503  /* @__PURE__ */ new Vector3(-1, 0, 0),
21504  /* @__PURE__ */ new Vector3(0, -1, 0),
21505  /* @__PURE__ */ new Vector3(0, 1, 0),
21506  /* @__PURE__ */ new Vector3(0, 0, 1),
21507  /* @__PURE__ */ new Vector3(0, 0, -1)
21508];
21509var _cubeUpsWebGPU = [
21510  /* @__PURE__ */ new Vector3(0, -1, 0),
21511  /* @__PURE__ */ new Vector3(0, -1, 0),
21512  /* @__PURE__ */ new Vector3(0, 0, -1),
21513  /* @__PURE__ */ new Vector3(0, 0, 1),
21514  /* @__PURE__ */ new Vector3(0, -1, 0),
21515  /* @__PURE__ */ new Vector3(0, -1, 0)
21516];
21517var _cubeDirectionsWebGL = [
21518  /* @__PURE__ */ new Vector3(1, 0, 0),
21519  /* @__PURE__ */ new Vector3(-1, 0, 0),
21520  /* @__PURE__ */ new Vector3(0, 1, 0),
21521  /* @__PURE__ */ new Vector3(0, -1, 0),
21522  /* @__PURE__ */ new Vector3(0, 0, 1),
21523  /* @__PURE__ */ new Vector3(0, 0, -1)
21524];
21525var _cubeUpsWebGL = [
21526  /* @__PURE__ */ new Vector3(0, -1, 0),
21527  /* @__PURE__ */ new Vector3(0, -1, 0),
21528  /* @__PURE__ */ new Vector3(0, 0, 1),
21529  /* @__PURE__ */ new Vector3(0, 0, -1),
21530  /* @__PURE__ */ new Vector3(0, -1, 0),
21531  /* @__PURE__ */ new Vector3(0, -1, 0)
21532];
21533var BasicPointShadowFilter = /* @__PURE__ */ Fn(({ depthTexture, bd3D, dp }) => {
21534  return cubeTexture(depthTexture, bd3D).compare(dp);
21535});
21536var PointShadowFilter = /* @__PURE__ */ Fn(({ depthTexture, bd3D, dp, shadow: shadow3 }) => {
21537  const radius = reference("radius", "float", shadow3).setGroup(renderGroup);
21538  const mapSize = reference("mapSize", "vec2", shadow3).setGroup(renderGroup);
21539  const texelSize = radius.div(mapSize.x);
21540  const absDir = abs(bd3D);
21541  const tangent = normalize(cross(bd3D, absDir.x.greaterThan(absDir.z).select(vec3(0, 1, 0), vec3(1, 0, 0))));
21542  const bitangent = cross(bd3D, tangent);
21543  const phi = interleavedGradientNoise(screenCoordinate.xy).mul(6.28318530718);
21544  const sample0 = vogelDiskSample(0, 5, phi);
21545  const sample1 = vogelDiskSample(1, 5, phi);
21546  const sample22 = vogelDiskSample(2, 5, phi);
21547  const sample3 = vogelDiskSample(3, 5, phi);
21548  const sample4 = vogelDiskSample(4, 5, phi);
21549  return cubeTexture(depthTexture, bd3D.add(tangent.mul(sample0.x).add(bitangent.mul(sample0.y)).mul(texelSize))).compare(dp).add(cubeTexture(depthTexture, bd3D.add(tangent.mul(sample1.x).add(bitangent.mul(sample1.y)).mul(texelSize))).compare(dp)).add(cubeTexture(depthTexture, bd3D.add(tangent.mul(sample22.x).add(bitangent.mul(sample22.y)).mul(texelSize))).compare(dp)).add(cubeTexture(depthTexture, bd3D.add(tangent.mul(sample3.x).add(bitangent.mul(sample3.y)).mul(texelSize))).compare(dp)).add(cubeTexture(depthTexture, bd3D.add(tangent.mul(sample4.x).add(bitangent.mul(sample4.y)).mul(texelSize))).compare(dp)).mul(1 / 5);
21550});
21551var pointShadowFilter = /* @__PURE__ */ Fn(({ filterFn, depthTexture, shadowCoord, shadow: shadow3 }, builder) => {
21552  const shadowPosition = shadowCoord.xyz.toConst();
21553  const shadowPositionAbs = shadowPosition.abs().toConst();
21554  const viewZ = shadowPositionAbs.x.max(shadowPositionAbs.y).max(shadowPositionAbs.z);
21555  const shadowCameraNear = uniform("float").setGroup(renderGroup).onRenderUpdate(() => shadow3.camera.near);
21556  const shadowCameraFar = uniform("float").setGroup(renderGroup).onRenderUpdate(() => shadow3.camera.far);
21557  const bias = reference("bias", "float", shadow3).setGroup(renderGroup);
21558  const result = float(1).toVar();
21559  If(viewZ.sub(shadowCameraFar).lessThanEqual(0).and(viewZ.sub(shadowCameraNear).greaterThanEqual(0)), () => {
21560    let dp;
21561    if (builder.renderer.reversedDepthBuffer) {
21562      dp = viewZToReversedPerspectiveDepth(viewZ.negate(), shadowCameraNear, shadowCameraFar);
21563      dp.subAssign(bias);
21564    } else {
21565      dp = viewZToPerspectiveDepth(viewZ.negate(), shadowCameraNear, shadowCameraFar);
21566      dp.addAssign(bias);
21567    }
21568    const bd3D = shadowPosition.normalize();
21569    result.assign(filterFn({ depthTexture, bd3D, dp, shadow: shadow3 }));
21570  });
21571  return result;
21572});
21573var PointShadowNode = class extends ShadowNode {
21574  static get type() {
21575    return "PointShadowNode";
21576  }
21577  /**
21578   * Constructs a new point shadow node.
21579   *
21580   * @param {PointLight} light - The shadow casting point light.
21581   * @param {?PointLightShadow} [shadow=null] - An optional point light shadow.
21582   */
21583  constructor(light, shadow3 = null) {
21584    super(light, shadow3);
21585  }
21586  /**
21587   * Overwrites the default implementation to return point light shadow specific
21588   * filtering functions.
21589   *
21590   * @param {number} type - The shadow type.
21591   * @return {Function} The filtering function.
21592   */
21593  getShadowFilterFn(type) {
21594    return type === BasicShadowMap ? BasicPointShadowFilter : PointShadowFilter;
21595  }
21596  /**
21597   * Overwrites the default implementation so the unaltered shadow position is used.
21598   *
21599   * @param {NodeBuilder} builder - A reference to the current node builder.
21600   * @param {Node<vec3>} shadowPosition - A node representing the shadow position.
21601   * @return {Node<vec3>} The shadow coordinates.
21602   */
21603  setupShadowCoord(builder, shadowPosition) {
21604    return shadowPosition;
21605  }
21606  /**
21607   * Overwrites the default implementation to only use point light specific
21608   * shadow filter functions.
21609   *
21610   * @param {NodeBuilder} builder - A reference to the current node builder.
21611   * @param {Object} inputs - A configuration object that defines the shadow filtering.
21612   * @param {Function} inputs.filterFn - This function defines the filtering type of the shadow map e.g. PCF.
21613   * @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's depth texture.
21614   * @param {Node<vec3>} inputs.shadowCoord - Shadow coordinates which are used to sample from the shadow map.
21615   * @param {LightShadow} inputs.shadow - The light shadow.
21616   * @return {Node<float>} The result node of the shadow filtering.
21617   */
21618  setupShadowFilter(builder, { filterFn, depthTexture, shadowCoord, shadow: shadow3 }) {
21619    return pointShadowFilter({ filterFn, depthTexture, shadowCoord, shadow: shadow3 });
21620  }
21621  /**
21622   * Overwrites the default implementation to create a CubeRenderTarget with CubeDepthTexture.
21623   *
21624   * @param {LightShadow} shadow - The light shadow object.
21625   * @param {NodeBuilder} builder - A reference to the current node builder.
21626   * @return {Object} An object containing the shadow map and depth texture.
21627   */
21628  setupRenderTarget(shadow3, builder) {
21629    const depthTexture = new CubeDepthTexture(shadow3.mapSize.width);
21630    depthTexture.name = "PointShadowDepthTexture";
21631    depthTexture.compareFunction = builder.renderer.reversedDepthBuffer ? GreaterEqualCompare : LessEqualCompare;
21632    const shadowMap = builder.createCubeRenderTarget(shadow3.mapSize.width);
21633    shadowMap.texture.name = "PointShadowMap";
21634    shadowMap.depthTexture = depthTexture;
21635    return { shadowMap, depthTexture };
21636  }
21637  /**
21638   * Overwrites the default implementation with point light specific
21639   * rendering code.
21640   *
21641   * @param {NodeFrame} frame - A reference to the current node frame.
21642   */
21643  renderShadow(frame) {
21644    const { shadow: shadow3, shadowMap, light } = this;
21645    const { renderer, scene } = frame;
21646    const camera = shadow3.camera;
21647    const shadowMatrix = shadow3.matrix;
21648    const isWebGPU = renderer.coordinateSystem === WebGPUCoordinateSystem;
21649    const cubeDirections = isWebGPU ? _cubeDirectionsWebGPU : _cubeDirectionsWebGL;
21650    const cubeUps = isWebGPU ? _cubeUpsWebGPU : _cubeUpsWebGL;
21651    shadowMap.setSize(shadow3.mapSize.width, shadow3.mapSize.width);
21652    const previousAutoClear = renderer.autoClear;
21653    const previousClearColor = renderer.getClearColor(_clearColor$1);
21654    const previousClearAlpha = renderer.getClearAlpha();
21655    renderer.autoClear = false;
21656    renderer.setClearColor(shadow3.clearColor, shadow3.clearAlpha);
21657    for (let face = 0; face < 6; face++) {
21658      renderer.setRenderTarget(shadowMap, face);
21659      renderer.clear();
21660      const far = light.distance || camera.far;
21661      if (far !== camera.far) {
21662        camera.far = far;
21663        camera.updateProjectionMatrix();
21664      }
21665      _lightPositionWorld.setFromMatrixPosition(light.matrixWorld);
21666      camera.position.copy(_lightPositionWorld);
21667      _lookTarget.copy(camera.position);
21668      _lookTarget.add(cubeDirections[face]);
21669      camera.up.copy(cubeUps[face]);
21670      camera.lookAt(_lookTarget);
21671      camera.updateMatrixWorld();
21672      shadowMatrix.makeTranslation(-_lightPositionWorld.x, -_lightPositionWorld.y, -_lightPositionWorld.z);
21673      _projScreenMatrix$1.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
21674      shadow3._frustum.setFromProjectionMatrix(_projScreenMatrix$1, camera.coordinateSystem, camera.reversedDepth);
21675      const currentSceneName = scene.name;
21676      scene.name = `Point Light Shadow [ ${light.name || "ID: " + light.id} ] - Face ${face + 1}`;
21677      renderer.render(scene, camera);
21678      scene.name = currentSceneName;
21679    }
21680    renderer.autoClear = previousAutoClear;
21681    renderer.setClearColor(previousClearColor, previousClearAlpha);
21682  }
21683};
21684var pointShadow = (light, shadow3) => new PointShadowNode(light, shadow3);
21685var AnalyticLightNode = class extends LightingNode {
21686  static get type() {
21687    return "AnalyticLightNode";
21688  }
21689  /**
21690   * Constructs a new analytic light node.
21691   *
21692   * @param {?Light} [light=null] - The light source.
21693   */
21694  constructor(light = null) {
21695    super();
21696    this.light = light;
21697    this.color = new Color();
21698    this.colorNode = light && light.colorNode || uniform(this.color).setGroup(renderGroup);
21699    this.baseColorNode = null;
21700    this.shadowNode = null;
21701    this.shadowColorNode = null;
21702    this.isAnalyticLightNode = true;
21703    this.updateType = NodeUpdateType.FRAME;
21704    if (light && light.shadow) {
21705      this._shadowDisposeListener = () => {
21706        this.disposeShadow();
21707      };
21708      light.addEventListener("dispose", this._shadowDisposeListener);
21709    }
21710  }
21711  dispose() {
21712    if (this._shadowDisposeListener) {
21713      this.light.removeEventListener("dispose", this._shadowDisposeListener);
21714    }
21715    super.dispose();
21716  }
21717  /**
21718   * Frees internal resources related to shadows.
21719   */
21720  disposeShadow() {
21721    if (this.shadowNode !== null) {
21722      this.shadowNode.dispose();
21723      this.shadowNode = null;
21724    }
21725    this.shadowColorNode = null;
21726    if (this.baseColorNode !== null) {
21727      this.colorNode = this.baseColorNode;
21728      this.baseColorNode = null;
21729    }
21730  }
21731  getHash() {
21732    return this.light.uuid;
21733  }
21734  /**
21735   * Returns a node representing a direction vector which points from the current
21736   * position in view space to the light's position in view space.
21737   *
21738   * @param {NodeBuilder} builder - The builder object used for setting up the light.
21739   * @return {Node<vec3>} The light vector node.
21740   */
21741  getLightVector(builder) {
21742    return lightViewPosition(this.light).sub(builder.context.positionView || positionView);
21743  }
21744  /**
21745   * Sets up the direct lighting for the analytic light node.
21746   *
21747   * @abstract
21748   * @param {NodeBuilder} builder - The builder object used for setting up the light.
21749   * @return {Object|undefined} The direct light data (color and direction).
21750   */
21751  setupDirect() {
21752  }
21753  /**
21754   * Sets up the direct rect area lighting for the analytic light node.
21755   *
21756   * @abstract
21757   * @param {NodeBuilder} builder - The builder object used for setting up the light.
21758   * @return {Object|undefined} The direct rect area light data.
21759   */
21760  setupDirectRectArea() {
21761  }
21762  /**
21763   * Setups the shadow node for this light. The method exists so concrete light classes
21764   * can setup different types of shadow nodes.
21765   *
21766   * @return {ShadowNode} The created shadow node.
21767   */
21768  setupShadowNode() {
21769    return shadow(this.light);
21770  }
21771  /**
21772   * Setups the shadow for this light. This method is only executed if the light
21773   * cast shadows and the current build object receives shadows. It incorporates
21774   * shadows into the lighting computation.
21775   *
21776   * @param {NodeBuilder} builder - The current node builder.
21777   */
21778  setupShadow(builder) {
21779    const { renderer } = builder;
21780    if (renderer.shadowMap.enabled === false) return;
21781    let shadowColorNode = this.shadowColorNode;
21782    if (shadowColorNode === null) {
21783      const customShadowNode = this.light.shadow.shadowNode;
21784      let shadowNode;
21785      if (customShadowNode !== void 0) {
21786        shadowNode = nodeObject(customShadowNode);
21787      } else {
21788        shadowNode = this.setupShadowNode();
21789      }
21790      this.shadowNode = shadowNode;
21791      this.shadowColorNode = shadowColorNode = this.colorNode.mul(shadowNode);
21792      this.baseColorNode = this.colorNode;
21793    }
21794    if (builder.context.getShadow) {
21795      shadowColorNode = builder.context.getShadow(this, builder);
21796    }
21797    this.colorNode = shadowColorNode;
21798  }
21799  /**
21800   * Unlike most other nodes, lighting nodes do not return a output node in {@link Node#setup}.
21801   * The main purpose of lighting nodes is to configure the current {@link LightingModel} and/or
21802   * invocate the respective interface methods.
21803   *
21804   * @param {NodeBuilder} builder - The current node builder.
21805   */
21806  setup(builder) {
21807    this.colorNode = this.baseColorNode || this.colorNode;
21808    if (this.light.castShadow) {
21809      if (builder.object.receiveShadow) {
21810        this.setupShadow(builder);
21811      }
21812    } else if (this.shadowNode !== null) {
21813      this.shadowNode.dispose();
21814      this.shadowNode = null;
21815      this.shadowColorNode = null;
21816    }
21817    const directLightData = this.setupDirect(builder);
21818    const directRectAreaLightData = this.setupDirectRectArea(builder);
21819    if (directLightData) {
21820      builder.lightsNode.setupDirectLight(builder, this, directLightData);
21821    }
21822    if (directRectAreaLightData) {
21823      builder.lightsNode.setupDirectRectAreaLight(builder, this, directRectAreaLightData);
21824    }
21825  }
21826  /**
21827   * The update method is used to update light uniforms per frame.
21828   * Potentially overwritten in concrete light nodes to update light
21829   * specific uniforms.
21830   *
21831   * @param {NodeFrame} frame - A reference to the current node frame.
21832   */
21833  update() {
21834    const { light } = this;
21835    this.color.copy(light.color).multiplyScalar(light.intensity);
21836  }
21837};
21838var getDistanceAttenuation = /* @__PURE__ */ Fn(({ lightDistance, cutoffDistance, decayExponent }) => {
21839  const distanceFalloff = lightDistance.pow(decayExponent).max(0.01).reciprocal();
21840  return cutoffDistance.greaterThan(0).select(
21841    distanceFalloff.mul(lightDistance.div(cutoffDistance).pow4().oneMinus().clamp().pow2()),
21842    distanceFalloff
21843  );
21844});
21845var directPointLight = ({ color: color3, lightVector, cutoffDistance, decayExponent }) => {
21846  const lightDirection = lightVector.normalize();
21847  const lightDistance = lightVector.length();
21848  const attenuation = getDistanceAttenuation({
21849    lightDistance,
21850    cutoffDistance,
21851    decayExponent
21852  });
21853  const lightColor = color3.mul(attenuation);
21854  return { lightDirection, lightColor };
21855};
21856var PointLightNode = class extends AnalyticLightNode {
21857  static get type() {
21858    return "PointLightNode";
21859  }
21860  /**
21861   * Constructs a new point light node.
21862   *
21863   * @param {?PointLight} [light=null] - The point light source.
21864   */
21865  constructor(light = null) {
21866    super(light);
21867    this.cutoffDistanceNode = uniform(0).setGroup(renderGroup);
21868    this.decayExponentNode = uniform(2).setGroup(renderGroup);
21869  }
21870  /**
21871   * Overwritten to updated point light specific uniforms.
21872   *
21873   * @param {NodeFrame} frame - A reference to the current node frame.
21874   */
21875  update(frame) {
21876    const { light } = this;
21877    super.update(frame);
21878    this.cutoffDistanceNode.value = light.distance;
21879    this.decayExponentNode.value = light.decay;
21880  }
21881  /**
21882   * Overwritten to setup point light specific shadow.
21883   *
21884   * @return {PointShadowNode}
21885   */
21886  setupShadowNode() {
21887    return pointShadow(this.light);
21888  }
21889  setupDirect(builder) {
21890    return directPointLight({
21891      color: this.colorNode,
21892      lightVector: this.getLightVector(builder),
21893      cutoffDistance: this.cutoffDistanceNode,
21894      decayExponent: this.decayExponentNode
21895    });
21896  }
21897};
21898var checker = /* @__PURE__ */ Fn(([coord = uv$1()]) => {
21899  const uv3 = coord.mul(2);
21900  const cx = uv3.x.floor();
21901  const cy = uv3.y.floor();
21902  const result = cx.add(cy).mod(2);
21903  return result.sign();
21904});
21905var shapeCircle = Fn(([coord = uv$1()], { renderer, material }) => {
21906  const len2 = lengthSq(coord.mul(2).sub(1));
21907  let alpha;
21908  if (material.alphaToCoverage && renderer.currentSamples > 0) {
21909    const dlen = float(len2.fwidth()).toVar();
21910    alpha = smoothstep(dlen.oneMinus(), dlen.add(1), len2).oneMinus();
21911  } else {
21912    alpha = select(len2.greaterThan(1), 0, 1);
21913  }
21914  return alpha;
21915});
21916var mx_select = /* @__PURE__ */ Fn(([b_immutable, t_immutable, f_immutable]) => {
21917  const f = float(f_immutable).toVar();
21918  const t = float(t_immutable).toVar();
21919  const b = bool(b_immutable).toVar();
21920  return select(b, t, f);
21921}).setLayout({
21922  name: "mx_select",
21923  type: "float",
21924  inputs: [
21925    { name: "b", type: "bool" },
21926    { name: "t", type: "float" },
21927    { name: "f", type: "float" }
21928  ]
21929});
21930var mx_negate_if = /* @__PURE__ */ Fn(([val_immutable, b_immutable]) => {
21931  const b = bool(b_immutable).toVar();
21932  const val = float(val_immutable).toVar();
21933  return select(b, val.negate(), val);
21934}).setLayout({
21935  name: "mx_negate_if",
21936  type: "float",
21937  inputs: [
21938    { name: "val", type: "float" },
21939    { name: "b", type: "bool" }
21940  ]
21941});
21942var mx_floor = /* @__PURE__ */ Fn(([x_immutable]) => {
21943  const x = float(x_immutable).toVar();
21944  return int(floor(x));
21945}).setLayout({
21946  name: "mx_floor",
21947  type: "int",
21948  inputs: [
21949    { name: "x", type: "float" }
21950  ]
21951});
21952var mx_floorfrac = /* @__PURE__ */ Fn(([x_immutable, i]) => {
21953  const x = float(x_immutable).toVar();
21954  i.assign(mx_floor(x));
21955  return x.sub(float(i));
21956});
21957var mx_bilerp_0 = /* @__PURE__ */ Fn(([v0_immutable, v1_immutable, v2_immutable, v3_immutable, s_immutable, t_immutable]) => {
21958  const t = float(t_immutable).toVar();
21959  const s = float(s_immutable).toVar();
21960  const v3 = float(v3_immutable).toVar();
21961  const v2 = float(v2_immutable).toVar();
21962  const v1 = float(v1_immutable).toVar();
21963  const v0 = float(v0_immutable).toVar();
21964  const s1 = float(sub(1, s)).toVar();
21965  return sub(1, t).mul(v0.mul(s1).add(v1.mul(s))).add(t.mul(v2.mul(s1).add(v3.mul(s))));
21966}).setLayout({
21967  name: "mx_bilerp_0",
21968  type: "float",
21969  inputs: [
21970    { name: "v0", type: "float" },
21971    { name: "v1", type: "float" },
21972    { name: "v2", type: "float" },
21973    { name: "v3", type: "float" },
21974    { name: "s", type: "float" },
21975    { name: "t", type: "float" }
21976  ]
21977});
21978var mx_bilerp_1 = /* @__PURE__ */ Fn(([v0_immutable, v1_immutable, v2_immutable, v3_immutable, s_immutable, t_immutable]) => {
21979  const t = float(t_immutable).toVar();
21980  const s = float(s_immutable).toVar();
21981  const v3 = vec3(v3_immutable).toVar();
21982  const v2 = vec3(v2_immutable).toVar();
21983  const v1 = vec3(v1_immutable).toVar();
21984  const v0 = vec3(v0_immutable).toVar();
21985  const s1 = float(sub(1, s)).toVar();
21986  return sub(1, t).mul(v0.mul(s1).add(v1.mul(s))).add(t.mul(v2.mul(s1).add(v3.mul(s))));
21987}).setLayout({
21988  name: "mx_bilerp_1",
21989  type: "vec3",
21990  inputs: [
21991    { name: "v0", type: "vec3" },
21992    { name: "v1", type: "vec3" },
21993    { name: "v2", type: "vec3" },
21994    { name: "v3", type: "vec3" },
21995    { name: "s", type: "float" },
21996    { name: "t", type: "float" }
21997  ]
21998});
21999var mx_bilerp = /* @__PURE__ */ overloadingFn([mx_bilerp_0, mx_bilerp_1]);
22000var mx_trilerp_0 = /* @__PURE__ */ Fn(([v0_immutable, v1_immutable, v2_immutable, v3_immutable, v4_immutable, v5_immutable, v6_immutable, v7_immutable, s_immutable, t_immutable, r_immutable]) => {
22001  const r = float(r_immutable).toVar();
22002  const t = float(t_immutable).toVar();
22003  const s = float(s_immutable).toVar();
22004  const v7 = float(v7_immutable).toVar();
22005  const v6 = float(v6_immutable).toVar();
22006  const v5 = float(v5_immutable).toVar();
22007  const v4 = float(v4_immutable).toVar();
22008  const v3 = float(v3_immutable).toVar();
22009  const v2 = float(v2_immutable).toVar();
22010  const v1 = float(v1_immutable).toVar();
22011  const v0 = float(v0_immutable).toVar();
22012  const s1 = float(sub(1, s)).toVar();
22013  const t1 = float(sub(1, t)).toVar();
22014  const r1 = float(sub(1, r)).toVar();
22015  return r1.mul(t1.mul(v0.mul(s1).add(v1.mul(s))).add(t.mul(v2.mul(s1).add(v3.mul(s))))).add(r.mul(t1.mul(v4.mul(s1).add(v5.mul(s))).add(t.mul(v6.mul(s1).add(v7.mul(s))))));
22016}).setLayout({
22017  name: "mx_trilerp_0",
22018  type: "float",
22019  inputs: [
22020    { name: "v0", type: "float" },
22021    { name: "v1", type: "float" },
22022    { name: "v2", type: "float" },
22023    { name: "v3", type: "float" },
22024    { name: "v4", type: "float" },
22025    { name: "v5", type: "float" },
22026    { name: "v6", type: "float" },
22027    { name: "v7", type: "float" },
22028    { name: "s", type: "float" },
22029    { name: "t", type: "float" },
22030    { name: "r", type: "float" }
22031  ]
22032});
22033var mx_trilerp_1 = /* @__PURE__ */ Fn(([v0_immutable, v1_immutable, v2_immutable, v3_immutable, v4_immutable, v5_immutable, v6_immutable, v7_immutable, s_immutable, t_immutable, r_immutable]) => {
22034  const r = float(r_immutable).toVar();
22035  const t = float(t_immutable).toVar();
22036  const s = float(s_immutable).toVar();
22037  const v7 = vec3(v7_immutable).toVar();
22038  const v6 = vec3(v6_immutable).toVar();
22039  const v5 = vec3(v5_immutable).toVar();
22040  const v4 = vec3(v4_immutable).toVar();
22041  const v3 = vec3(v3_immutable).toVar();
22042  const v2 = vec3(v2_immutable).toVar();
22043  const v1 = vec3(v1_immutable).toVar();
22044  const v0 = vec3(v0_immutable).toVar();
22045  const s1 = float(sub(1, s)).toVar();
22046  const t1 = float(sub(1, t)).toVar();
22047  const r1 = float(sub(1, r)).toVar();
22048  return r1.mul(t1.mul(v0.mul(s1).add(v1.mul(s))).add(t.mul(v2.mul(s1).add(v3.mul(s))))).add(r.mul(t1.mul(v4.mul(s1).add(v5.mul(s))).add(t.mul(v6.mul(s1).add(v7.mul(s))))));
22049}).setLayout({
22050  name: "mx_trilerp_1",
22051  type: "vec3",
22052  inputs: [
22053    { name: "v0", type: "vec3" },
22054    { name: "v1", type: "vec3" },
22055    { name: "v2", type: "vec3" },
22056    { name: "v3", type: "vec3" },
22057    { name: "v4", type: "vec3" },
22058    { name: "v5", type: "vec3" },
22059    { name: "v6", type: "vec3" },
22060    { name: "v7", type: "vec3" },
22061    { name: "s", type: "float" },
22062    { name: "t", type: "float" },
22063    { name: "r", type: "float" }
22064  ]
22065});
22066var mx_trilerp = /* @__PURE__ */ overloadingFn([mx_trilerp_0, mx_trilerp_1]);
22067var mx_gradient_float_0 = /* @__PURE__ */ Fn(([hash_immutable, x_immutable, y_immutable]) => {
22068  const y = float(y_immutable).toVar();
22069  const x = float(x_immutable).toVar();
22070  const hash3 = uint(hash_immutable).toVar();
22071  const h = uint(hash3.bitAnd(uint(7))).toVar();
22072  const u = float(mx_select(h.lessThan(uint(4)), x, y)).toVar();
22073  const v = float(mul(2, mx_select(h.lessThan(uint(4)), y, x))).toVar();
22074  return mx_negate_if(u, bool(h.bitAnd(uint(1)))).add(mx_negate_if(v, bool(h.bitAnd(uint(2)))));
22075}).setLayout({
22076  name: "mx_gradient_float_0",
22077  type: "float",
22078  inputs: [
22079    { name: "hash", type: "uint" },
22080    { name: "x", type: "float" },
22081    { name: "y", type: "float" }
22082  ]
22083});
22084var mx_gradient_float_1 = /* @__PURE__ */ Fn(([hash_immutable, x_immutable, y_immutable, z_immutable]) => {
22085  const z = float(z_immutable).toVar();
22086  const y = float(y_immutable).toVar();
22087  const x = float(x_immutable).toVar();
22088  const hash3 = uint(hash_immutable).toVar();
22089  const h = uint(hash3.bitAnd(uint(15))).toVar();
22090  const u = float(mx_select(h.lessThan(uint(8)), x, y)).toVar();
22091  const v = float(mx_select(h.lessThan(uint(4)), y, mx_select(h.equal(uint(12)).or(h.equal(uint(14))), x, z))).toVar();
22092  return mx_negate_if(u, bool(h.bitAnd(uint(1)))).add(mx_negate_if(v, bool(h.bitAnd(uint(2)))));
22093}).setLayout({
22094  name: "mx_gradient_float_1",
22095  type: "float",
22096  inputs: [
22097    { name: "hash", type: "uint" },
22098    { name: "x", type: "float" },
22099    { name: "y", type: "float" },
22100    { name: "z", type: "float" }
22101  ]
22102});
22103var mx_gradient_float = /* @__PURE__ */ overloadingFn([mx_gradient_float_0, mx_gradient_float_1]);
22104var mx_gradient_vec3_0 = /* @__PURE__ */ Fn(([hash_immutable, x_immutable, y_immutable]) => {
22105  const y = float(y_immutable).toVar();
22106  const x = float(x_immutable).toVar();
22107  const hash3 = uvec3(hash_immutable).toVar();
22108  return vec3(mx_gradient_float(hash3.x, x, y), mx_gradient_float(hash3.y, x, y), mx_gradient_float(hash3.z, x, y));
22109}).setLayout({
22110  name: "mx_gradient_vec3_0",
22111  type: "vec3",
22112  inputs: [
22113    { name: "hash", type: "uvec3" },
22114    { name: "x", type: "float" },
22115    { name: "y", type: "float" }
22116  ]
22117});
22118var mx_gradient_vec3_1 = /* @__PURE__ */ Fn(([hash_immutable, x_immutable, y_immutable, z_immutable]) => {
22119  const z = float(z_immutable).toVar();
22120  const y = float(y_immutable).toVar();
22121  const x = float(x_immutable).toVar();
22122  const hash3 = uvec3(hash_immutable).toVar();
22123  return vec3(mx_gradient_float(hash3.x, x, y, z), mx_gradient_float(hash3.y, x, y, z), mx_gradient_float(hash3.z, x, y, z));
22124}).setLayout({
22125  name: "mx_gradient_vec3_1",
22126  type: "vec3",
22127  inputs: [
22128    { name: "hash", type: "uvec3" },
22129    { name: "x", type: "float" },
22130    { name: "y", type: "float" },
22131    { name: "z", type: "float" }
22132  ]
22133});
22134var mx_gradient_vec3 = /* @__PURE__ */ overloadingFn([mx_gradient_vec3_0, mx_gradient_vec3_1]);
22135var mx_gradient_scale2d_0 = /* @__PURE__ */ Fn(([v_immutable]) => {
22136  const v = float(v_immutable).toVar();
22137  return mul(0.6616, v);
22138}).setLayout({
22139  name: "mx_gradient_scale2d_0",
22140  type: "float",
22141  inputs: [
22142    { name: "v", type: "float" }
22143  ]
22144});
22145var mx_gradient_scale3d_0 = /* @__PURE__ */ Fn(([v_immutable]) => {
22146  const v = float(v_immutable).toVar();
22147  return mul(0.982, v);
22148}).setLayout({
22149  name: "mx_gradient_scale3d_0",
22150  type: "float",
22151  inputs: [
22152    { name: "v", type: "float" }
22153  ]
22154});
22155var mx_gradient_scale2d_1 = /* @__PURE__ */ Fn(([v_immutable]) => {
22156  const v = vec3(v_immutable).toVar();
22157  return mul(0.6616, v);
22158}).setLayout({
22159  name: "mx_gradient_scale2d_1",
22160  type: "vec3",
22161  inputs: [
22162    { name: "v", type: "vec3" }
22163  ]
22164});
22165var mx_gradient_scale2d = /* @__PURE__ */ overloadingFn([mx_gradient_scale2d_0, mx_gradient_scale2d_1]);
22166var mx_gradient_scale3d_1 = /* @__PURE__ */ Fn(([v_immutable]) => {
22167  const v = vec3(v_immutable).toVar();
22168  return mul(0.982, v);
22169}).setLayout({
22170  name: "mx_gradient_scale3d_1",
22171  type: "vec3",
22172  inputs: [
22173    { name: "v", type: "vec3" }
22174  ]
22175});
22176var mx_gradient_scale3d = /* @__PURE__ */ overloadingFn([mx_gradient_scale3d_0, mx_gradient_scale3d_1]);
22177var mx_rotl32 = /* @__PURE__ */ Fn(([x_immutable, k_immutable]) => {
22178  const k = int(k_immutable).toVar();
22179  const x = uint(x_immutable).toVar();
22180  return x.shiftLeft(k).bitOr(x.shiftRight(int(32).sub(k)));
22181}).setLayout({
22182  name: "mx_rotl32",
22183  type: "uint",
22184  inputs: [
22185    { name: "x", type: "uint" },
22186    { name: "k", type: "int" }
22187  ]
22188});
22189var mx_bjmix = /* @__PURE__ */ Fn(([a, b, c]) => {
22190  a.subAssign(c);
22191  a.bitXorAssign(mx_rotl32(c, int(4)));
22192  c.addAssign(b);
22193  b.subAssign(a);
22194  b.bitXorAssign(mx_rotl32(a, int(6)));
22195  a.addAssign(c);
22196  c.subAssign(b);
22197  c.bitXorAssign(mx_rotl32(b, int(8)));
22198  b.addAssign(a);
22199  a.subAssign(c);
22200  a.bitXorAssign(mx_rotl32(c, int(16)));
22201  c.addAssign(b);
22202  b.subAssign(a);
22203  b.bitXorAssign(mx_rotl32(a, int(19)));
22204  a.addAssign(c);
22205  c.subAssign(b);
22206  c.bitXorAssign(mx_rotl32(b, int(4)));
22207  b.addAssign(a);
22208});
22209var mx_bjfinal = /* @__PURE__ */ Fn(([a_immutable, b_immutable, c_immutable]) => {
22210  const c = uint(c_immutable).toVar();
22211  const b = uint(b_immutable).toVar();
22212  const a = uint(a_immutable).toVar();
22213  c.bitXorAssign(b);
22214  c.subAssign(mx_rotl32(b, int(14)));
22215  a.bitXorAssign(c);
22216  a.subAssign(mx_rotl32(c, int(11)));
22217  b.bitXorAssign(a);
22218  b.subAssign(mx_rotl32(a, int(25)));
22219  c.bitXorAssign(b);
22220  c.subAssign(mx_rotl32(b, int(16)));
22221  a.bitXorAssign(c);
22222  a.subAssign(mx_rotl32(c, int(4)));
22223  b.bitXorAssign(a);
22224  b.subAssign(mx_rotl32(a, int(14)));
22225  c.bitXorAssign(b);
22226  c.subAssign(mx_rotl32(b, int(24)));
22227  return c;
22228}).setLayout({
22229  name: "mx_bjfinal",
22230  type: "uint",
22231  inputs: [
22232    { name: "a", type: "uint" },
22233    { name: "b", type: "uint" },
22234    { name: "c", type: "uint" }
22235  ]
22236});
22237var mx_bits_to_01 = /* @__PURE__ */ Fn(([bits_immutable]) => {
22238  const bits = uint(bits_immutable).toVar();
22239  return float(bits).div(float(uint(int(4294967295))));
22240}).setLayout({
22241  name: "mx_bits_to_01",
22242  type: "float",
22243  inputs: [
22244    { name: "bits", type: "uint" }
22245  ]
22246});
22247var mx_fade = /* @__PURE__ */ Fn(([t_immutable]) => {
22248  const t = float(t_immutable).toVar();
22249  return t.mul(t).mul(t).mul(t.mul(t.mul(6).sub(15)).add(10));
22250}).setLayout({
22251  name: "mx_fade",
22252  type: "float",
22253  inputs: [
22254    { name: "t", type: "float" }
22255  ]
22256});
22257var mx_hash_int_0 = /* @__PURE__ */ Fn(([x_immutable]) => {
22258  const x = int(x_immutable).toVar();
22259  const len = uint(uint(1)).toVar();
22260  const seed = uint(uint(int(3735928559)).add(len.shiftLeft(uint(2))).add(uint(13))).toVar();
22261  return mx_bjfinal(seed.add(uint(x)), seed, seed);
22262}).setLayout({
22263  name: "mx_hash_int_0",
22264  type: "uint",
22265  inputs: [
22266    { name: "x", type: "int" }
22267  ]
22268});
22269var mx_hash_int_1 = /* @__PURE__ */ Fn(([x_immutable, y_immutable]) => {
22270  const y = int(y_immutable).toVar();
22271  const x = int(x_immutable).toVar();
22272  const len = uint(uint(2)).toVar();
22273  const a = uint().toVar(), b = uint().toVar(), c = uint().toVar();
22274  a.assign(b.assign(c.assign(uint(int(3735928559)).add(len.shiftLeft(uint(2))).add(uint(13)))));
22275  a.addAssign(uint(x));
22276  b.addAssign(uint(y));
22277  return mx_bjfinal(a, b, c);
22278}).setLayout({
22279  name: "mx_hash_int_1",
22280  type: "uint",
22281  inputs: [
22282    { name: "x", type: "int" },
22283    { name: "y", type: "int" }
22284  ]
22285});
22286var mx_hash_int_2 = /* @__PURE__ */ Fn(([x_immutable, y_immutable, z_immutable]) => {
22287  const z = int(z_immutable).toVar();
22288  const y = int(y_immutable).toVar();
22289  const x = int(x_immutable).toVar();
22290  const len = uint(uint(3)).toVar();
22291  const a = uint().toVar(), b = uint().toVar(), c = uint().toVar();
22292  a.assign(b.assign(c.assign(uint(int(3735928559)).add(len.shiftLeft(uint(2))).add(uint(13)))));
22293  a.addAssign(uint(x));
22294  b.addAssign(uint(y));
22295  c.addAssign(uint(z));
22296  return mx_bjfinal(a, b, c);
22297}).setLayout({
22298  name: "mx_hash_int_2",
22299  type: "uint",
22300  inputs: [
22301    { name: "x", type: "int" },
22302    { name: "y", type: "int" },
22303    { name: "z", type: "int" }
22304  ]
22305});
22306var mx_hash_int_3 = /* @__PURE__ */ Fn(([x_immutable, y_immutable, z_immutable, xx_immutable]) => {
22307  const xx = int(xx_immutable).toVar();
22308  const z = int(z_immutable).toVar();
22309  const y = int(y_immutable).toVar();
22310  const x = int(x_immutable).toVar();
22311  const len = uint(uint(4)).toVar();
22312  const a = uint().toVar(), b = uint().toVar(), c = uint().toVar();
22313  a.assign(b.assign(c.assign(uint(int(3735928559)).add(len.shiftLeft(uint(2))).add(uint(13)))));
22314  a.addAssign(uint(x));
22315  b.addAssign(uint(y));
22316  c.addAssign(uint(z));
22317  mx_bjmix(a, b, c);
22318  a.addAssign(uint(xx));
22319  return mx_bjfinal(a, b, c);
22320}).setLayout({
22321  name: "mx_hash_int_3",
22322  type: "uint",
22323  inputs: [
22324    { name: "x", type: "int" },
22325    { name: "y", type: "int" },
22326    { name: "z", type: "int" },
22327    { name: "xx", type: "int" }
22328  ]
22329});
22330var mx_hash_int_4 = /* @__PURE__ */ Fn(([x_immutable, y_immutable, z_immutable, xx_immutable, yy_immutable]) => {
22331  const yy = int(yy_immutable).toVar();
22332  const xx = int(xx_immutable).toVar();
22333  const z = int(z_immutable).toVar();
22334  const y = int(y_immutable).toVar();
22335  const x = int(x_immutable).toVar();
22336  const len = uint(uint(5)).toVar();
22337  const a = uint().toVar(), b = uint().toVar(), c = uint().toVar();
22338  a.assign(b.assign(c.assign(uint(int(3735928559)).add(len.shiftLeft(uint(2))).add(uint(13)))));
22339  a.addAssign(uint(x));
22340  b.addAssign(uint(y));
22341  c.addAssign(uint(z));
22342  mx_bjmix(a, b, c);
22343  a.addAssign(uint(xx));
22344  b.addAssign(uint(yy));
22345  return mx_bjfinal(a, b, c);
22346}).setLayout({
22347  name: "mx_hash_int_4",
22348  type: "uint",
22349  inputs: [
22350    { name: "x", type: "int" },
22351    { name: "y", type: "int" },
22352    { name: "z", type: "int" },
22353    { name: "xx", type: "int" },
22354    { name: "yy", type: "int" }
22355  ]
22356});
22357var mx_hash_int = /* @__PURE__ */ overloadingFn([mx_hash_int_0, mx_hash_int_1, mx_hash_int_2, mx_hash_int_3, mx_hash_int_4]);
22358var mx_hash_vec3_0 = /* @__PURE__ */ Fn(([x_immutable, y_immutable]) => {
22359  const y = int(y_immutable).toVar();
22360  const x = int(x_immutable).toVar();
22361  const h = uint(mx_hash_int(x, y)).toVar();
22362  const result = uvec3().toVar();
22363  result.x.assign(h.bitAnd(int(255)));
22364  result.y.assign(h.shiftRight(int(8)).bitAnd(int(255)));
22365  result.z.assign(h.shiftRight(int(16)).bitAnd(int(255)));
22366  return result;
22367}).setLayout({
22368  name: "mx_hash_vec3_0",
22369  type: "uvec3",
22370  inputs: [
22371    { name: "x", type: "int" },
22372    { name: "y", type: "int" }
22373  ]
22374});
22375var mx_hash_vec3_1 = /* @__PURE__ */ Fn(([x_immutable, y_immutable, z_immutable]) => {
22376  const z = int(z_immutable).toVar();
22377  const y = int(y_immutable).toVar();
22378  const x = int(x_immutable).toVar();
22379  const h = uint(mx_hash_int(x, y, z)).toVar();
22380  const result = uvec3().toVar();
22381  result.x.assign(h.bitAnd(int(255)));
22382  result.y.assign(h.shiftRight(int(8)).bitAnd(int(255)));
22383  result.z.assign(h.shiftRight(int(16)).bitAnd(int(255)));
22384  return result;
22385}).setLayout({
22386  name: "mx_hash_vec3_1",
22387  type: "uvec3",
22388  inputs: [
22389    { name: "x", type: "int" },
22390    { name: "y", type: "int" },
22391    { name: "z", type: "int" }
22392  ]
22393});
22394var mx_hash_vec3 = /* @__PURE__ */ overloadingFn([mx_hash_vec3_0, mx_hash_vec3_1]);
22395var mx_perlin_noise_float_0 = /* @__PURE__ */ Fn(([p_immutable]) => {
22396  const p = vec2(p_immutable).toVar();
22397  const X = int().toVar(), Y = int().toVar();
22398  const fx = float(mx_floorfrac(p.x, X)).toVar();
22399  const fy = float(mx_floorfrac(p.y, Y)).toVar();
22400  const u = float(mx_fade(fx)).toVar();
22401  const v = float(mx_fade(fy)).toVar();
22402  const result = float(mx_bilerp(mx_gradient_float(mx_hash_int(X, Y), fx, fy), mx_gradient_float(mx_hash_int(X.add(int(1)), Y), fx.sub(1), fy), mx_gradient_float(mx_hash_int(X, Y.add(int(1))), fx, fy.sub(1)), mx_gradient_float(mx_hash_int(X.add(int(1)), Y.add(int(1))), fx.sub(1), fy.sub(1)), u, v)).toVar();
22403  return mx_gradient_scale2d(result);
22404}).setLayout({
22405  name: "mx_perlin_noise_float_0",
22406  type: "float",
22407  inputs: [
22408    { name: "p", type: "vec2" }
22409  ]
22410});
22411var mx_perlin_noise_float_1 = /* @__PURE__ */ Fn(([p_immutable]) => {
22412  const p = vec3(p_immutable).toVar();
22413  const X = int().toVar(), Y = int().toVar(), Z = int().toVar();
22414  const fx = float(mx_floorfrac(p.x, X)).toVar();
22415  const fy = float(mx_floorfrac(p.y, Y)).toVar();
22416  const fz = float(mx_floorfrac(p.z, Z)).toVar();
22417  const u = float(mx_fade(fx)).toVar();
22418  const v = float(mx_fade(fy)).toVar();
22419  const w = float(mx_fade(fz)).toVar();
22420  const result = float(mx_trilerp(mx_gradient_float(mx_hash_int(X, Y, Z), fx, fy, fz), mx_gradient_float(mx_hash_int(X.add(int(1)), Y, Z), fx.sub(1), fy, fz), mx_gradient_float(mx_hash_int(X, Y.add(int(1)), Z), fx, fy.sub(1), fz), mx_gradient_float(mx_hash_int(X.add(int(1)), Y.add(int(1)), Z), fx.sub(1), fy.sub(1), fz), mx_gradient_float(mx_hash_int(X, Y, Z.add(int(1))), fx, fy, fz.sub(1)), mx_gradient_float(mx_hash_int(X.add(int(1)), Y, Z.add(int(1))), fx.sub(1), fy, fz.sub(1)), mx_gradient_float(mx_hash_int(X, Y.add(int(1)), Z.add(int(1))), fx, fy.sub(1), fz.sub(1)), mx_gradient_float(mx_hash_int(X.add(int(1)), Y.add(int(1)), Z.add(int(1))), fx.sub(1), fy.sub(1), fz.sub(1)), u, v, w)).toVar();
22421  return mx_gradient_scale3d(result);
22422}).setLayout({
22423  name: "mx_perlin_noise_float_1",
22424  type: "float",
22425  inputs: [
22426    { name: "p", type: "vec3" }
22427  ]
22428});
22429var mx_perlin_noise_float = /* @__PURE__ */ overloadingFn([mx_perlin_noise_float_0, mx_perlin_noise_float_1]);
22430var mx_perlin_noise_vec3_0 = /* @__PURE__ */ Fn(([p_immutable]) => {
22431  const p = vec2(p_immutable).toVar();
22432  const X = int().toVar(), Y = int().toVar();
22433  const fx = float(mx_floorfrac(p.x, X)).toVar();
22434  const fy = float(mx_floorfrac(p.y, Y)).toVar();
22435  const u = float(mx_fade(fx)).toVar();
22436  const v = float(mx_fade(fy)).toVar();
22437  const result = vec3(mx_bilerp(mx_gradient_vec3(mx_hash_vec3(X, Y), fx, fy), mx_gradient_vec3(mx_hash_vec3(X.add(int(1)), Y), fx.sub(1), fy), mx_gradient_vec3(mx_hash_vec3(X, Y.add(int(1))), fx, fy.sub(1)), mx_gradient_vec3(mx_hash_vec3(X.add(int(1)), Y.add(int(1))), fx.sub(1), fy.sub(1)), u, v)).toVar();
22438  return mx_gradient_scale2d(result);
22439}).setLayout({
22440  name: "mx_perlin_noise_vec3_0",
22441  type: "vec3",
22442  inputs: [
22443    { name: "p", type: "vec2" }
22444  ]
22445});
22446var mx_perlin_noise_vec3_1 = /* @__PURE__ */ Fn(([p_immutable]) => {
22447  const p = vec3(p_immutable).toVar();
22448  const X = int().toVar(), Y = int().toVar(), Z = int().toVar();
22449  const fx = float(mx_floorfrac(p.x, X)).toVar();
22450  const fy = float(mx_floorfrac(p.y, Y)).toVar();
22451  const fz = float(mx_floorfrac(p.z, Z)).toVar();
22452  const u = float(mx_fade(fx)).toVar();
22453  const v = float(mx_fade(fy)).toVar();
22454  const w = float(mx_fade(fz)).toVar();
22455  const result = vec3(mx_trilerp(mx_gradient_vec3(mx_hash_vec3(X, Y, Z), fx, fy, fz), mx_gradient_vec3(mx_hash_vec3(X.add(int(1)), Y, Z), fx.sub(1), fy, fz), mx_gradient_vec3(mx_hash_vec3(X, Y.add(int(1)), Z), fx, fy.sub(1), fz), mx_gradient_vec3(mx_hash_vec3(X.add(int(1)), Y.add(int(1)), Z), fx.sub(1), fy.sub(1), fz), mx_gradient_vec3(mx_hash_vec3(X, Y, Z.add(int(1))), fx, fy, fz.sub(1)), mx_gradient_vec3(mx_hash_vec3(X.add(int(1)), Y, Z.add(int(1))), fx.sub(1), fy, fz.sub(1)), mx_gradient_vec3(mx_hash_vec3(X, Y.add(int(1)), Z.add(int(1))), fx, fy.sub(1), fz.sub(1)), mx_gradient_vec3(mx_hash_vec3(X.add(int(1)), Y.add(int(1)), Z.add(int(1))), fx.sub(1), fy.sub(1), fz.sub(1)), u, v, w)).toVar();
22456  return mx_gradient_scale3d(result);
22457}).setLayout({
22458  name: "mx_perlin_noise_vec3_1",
22459  type: "vec3",
22460  inputs: [
22461    { name: "p", type: "vec3" }
22462  ]
22463});
22464var mx_perlin_noise_vec3 = /* @__PURE__ */ overloadingFn([mx_perlin_noise_vec3_0, mx_perlin_noise_vec3_1]);
22465var mx_cell_noise_float_0 = /* @__PURE__ */ Fn(([p_immutable]) => {
22466  const p = float(p_immutable).toVar();
22467  const ix = int(mx_floor(p)).toVar();
22468  return mx_bits_to_01(mx_hash_int(ix));
22469}).setLayout({
22470  name: "mx_cell_noise_float_0",
22471  type: "float",
22472  inputs: [
22473    { name: "p", type: "float" }
22474  ]
22475});
22476var mx_cell_noise_float_1 = /* @__PURE__ */ Fn(([p_immutable]) => {
22477  const p = vec2(p_immutable).toVar();
22478  const ix = int(mx_floor(p.x)).toVar();
22479  const iy = int(mx_floor(p.y)).toVar();
22480  return mx_bits_to_01(mx_hash_int(ix, iy));
22481}).setLayout({
22482  name: "mx_cell_noise_float_1",
22483  type: "float",
22484  inputs: [
22485    { name: "p", type: "vec2" }
22486  ]
22487});
22488var mx_cell_noise_float_2 = /* @__PURE__ */ Fn(([p_immutable]) => {
22489  const p = vec3(p_immutable).toVar();
22490  const ix = int(mx_floor(p.x)).toVar();
22491  const iy = int(mx_floor(p.y)).toVar();
22492  const iz = int(mx_floor(p.z)).toVar();
22493  return mx_bits_to_01(mx_hash_int(ix, iy, iz));
22494}).setLayout({
22495  name: "mx_cell_noise_float_2",
22496  type: "float",
22497  inputs: [
22498    { name: "p", type: "vec3" }
22499  ]
22500});
22501var mx_cell_noise_float_3 = /* @__PURE__ */ Fn(([p_immutable]) => {
22502  const p = vec4(p_immutable).toVar();
22503  const ix = int(mx_floor(p.x)).toVar();
22504  const iy = int(mx_floor(p.y)).toVar();
22505  const iz = int(mx_floor(p.z)).toVar();
22506  const iw = int(mx_floor(p.w)).toVar();
22507  return mx_bits_to_01(mx_hash_int(ix, iy, iz, iw));
22508}).setLayout({
22509  name: "mx_cell_noise_float_3",
22510  type: "float",
22511  inputs: [
22512    { name: "p", type: "vec4" }
22513  ]
22514});
22515var mx_cell_noise_float$1 = /* @__PURE__ */ overloadingFn([mx_cell_noise_float_0, mx_cell_noise_float_1, mx_cell_noise_float_2, mx_cell_noise_float_3]);
22516var mx_cell_noise_vec3_0 = /* @__PURE__ */ Fn(([p_immutable]) => {
22517  const p = float(p_immutable).toVar();
22518  const ix = int(mx_floor(p)).toVar();
22519  return vec3(mx_bits_to_01(mx_hash_int(ix, int(0))), mx_bits_to_01(mx_hash_int(ix, int(1))), mx_bits_to_01(mx_hash_int(ix, int(2))));
22520}).setLayout({
22521  name: "mx_cell_noise_vec3_0",
22522  type: "vec3",
22523  inputs: [
22524    { name: "p", type: "float" }
22525  ]
22526});
22527var mx_cell_noise_vec3_1 = /* @__PURE__ */ Fn(([p_immutable]) => {
22528  const p = vec2(p_immutable).toVar();
22529  const ix = int(mx_floor(p.x)).toVar();
22530  const iy = int(mx_floor(p.y)).toVar();
22531  return vec3(mx_bits_to_01(mx_hash_int(ix, iy, int(0))), mx_bits_to_01(mx_hash_int(ix, iy, int(1))), mx_bits_to_01(mx_hash_int(ix, iy, int(2))));
22532}).setLayout({
22533  name: "mx_cell_noise_vec3_1",
22534  type: "vec3",
22535  inputs: [
22536    { name: "p", type: "vec2" }
22537  ]
22538});
22539var mx_cell_noise_vec3_2 = /* @__PURE__ */ Fn(([p_immutable]) => {
22540  const p = vec3(p_immutable).toVar();
22541  const ix = int(mx_floor(p.x)).toVar();
22542  const iy = int(mx_floor(p.y)).toVar();
22543  const iz = int(mx_floor(p.z)).toVar();
22544  return vec3(mx_bits_to_01(mx_hash_int(ix, iy, iz, int(0))), mx_bits_to_01(mx_hash_int(ix, iy, iz, int(1))), mx_bits_to_01(mx_hash_int(ix, iy, iz, int(2))));
22545}).setLayout({
22546  name: "mx_cell_noise_vec3_2",
22547  type: "vec3",
22548  inputs: [
22549    { name: "p", type: "vec3" }
22550  ]
22551});
22552var mx_cell_noise_vec3_3 = /* @__PURE__ */ Fn(([p_immutable]) => {
22553  const p = vec4(p_immutable).toVar();
22554  const ix = int(mx_floor(p.x)).toVar();
22555  const iy = int(mx_floor(p.y)).toVar();
22556  const iz = int(mx_floor(p.z)).toVar();
22557  const iw = int(mx_floor(p.w)).toVar();
22558  return vec3(mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, int(0))), mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, int(1))), mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, int(2))));
22559}).setLayout({
22560  name: "mx_cell_noise_vec3_3",
22561  type: "vec3",
22562  inputs: [
22563    { name: "p", type: "vec4" }
22564  ]
22565});
22566var mx_cell_noise_vec3 = /* @__PURE__ */ overloadingFn([mx_cell_noise_vec3_0, mx_cell_noise_vec3_1, mx_cell_noise_vec3_2, mx_cell_noise_vec3_3]);
22567var mx_fractal_noise_float$1 = /* @__PURE__ */ Fn(([p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable]) => {
22568  const diminish = float(diminish_immutable).toVar();
22569  const lacunarity = float(lacunarity_immutable).toVar();
22570  const octaves = int(octaves_immutable).toVar();
22571  const p = vec3(p_immutable).toVar();
22572  const result = float(0).toVar();
22573  const amplitude = float(1).toVar();
22574  Loop(octaves, () => {
22575    result.addAssign(amplitude.mul(mx_perlin_noise_float(p)));
22576    amplitude.mulAssign(diminish);
22577    p.mulAssign(lacunarity);
22578  });
22579  return result;
22580}).setLayout({
22581  name: "mx_fractal_noise_float",
22582  type: "float",
22583  inputs: [
22584    { name: "p", type: "vec3" },
22585    { name: "octaves", type: "int" },
22586    { name: "lacunarity", type: "float" },
22587    { name: "diminish", type: "float" }
22588  ]
22589});
22590var mx_fractal_noise_vec3$1 = /* @__PURE__ */ Fn(([p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable]) => {
22591  const diminish = float(diminish_immutable).toVar();
22592  const lacunarity = float(lacunarity_immutable).toVar();
22593  const octaves = int(octaves_immutable).toVar();
22594  const p = vec3(p_immutable).toVar();
22595  const result = vec3(0).toVar();
22596  const amplitude = float(1).toVar();
22597  Loop(octaves, () => {
22598    result.addAssign(amplitude.mul(mx_perlin_noise_vec3(p)));
22599    amplitude.mulAssign(diminish);
22600    p.mulAssign(lacunarity);
22601  });
22602  return result;
22603}).setLayout({
22604  name: "mx_fractal_noise_vec3",
22605  type: "vec3",
22606  inputs: [
22607    { name: "p", type: "vec3" },
22608    { name: "octaves", type: "int" },
22609    { name: "lacunarity", type: "float" },
22610    { name: "diminish", type: "float" }
22611  ]
22612});
22613var mx_fractal_noise_vec2$1 = /* @__PURE__ */ Fn(([p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable]) => {
22614  const diminish = float(diminish_immutable).toVar();
22615  const lacunarity = float(lacunarity_immutable).toVar();
22616  const octaves = int(octaves_immutable).toVar();
22617  const p = vec3(p_immutable).toVar();
22618  return vec2(mx_fractal_noise_float$1(p, octaves, lacunarity, diminish), mx_fractal_noise_float$1(p.add(vec3(int(19), int(193), int(17))), octaves, lacunarity, diminish));
22619}).setLayout({
22620  name: "mx_fractal_noise_vec2",
22621  type: "vec2",
22622  inputs: [
22623    { name: "p", type: "vec3" },
22624    { name: "octaves", type: "int" },
22625    { name: "lacunarity", type: "float" },
22626    { name: "diminish", type: "float" }
22627  ]
22628});
22629var mx_fractal_noise_vec4$1 = /* @__PURE__ */ Fn(([p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable]) => {
22630  const diminish = float(diminish_immutable).toVar();
22631  const lacunarity = float(lacunarity_immutable).toVar();
22632  const octaves = int(octaves_immutable).toVar();
22633  const p = vec3(p_immutable).toVar();
22634  const c = vec3(mx_fractal_noise_vec3$1(p, octaves, lacunarity, diminish)).toVar();
22635  const f = float(mx_fractal_noise_float$1(p.add(vec3(int(19), int(193), int(17))), octaves, lacunarity, diminish)).toVar();
22636  return vec4(c, f);
22637}).setLayout({
22638  name: "mx_fractal_noise_vec4",
22639  type: "vec4",
22640  inputs: [
22641    { name: "p", type: "vec3" },
22642    { name: "octaves", type: "int" },
22643    { name: "lacunarity", type: "float" },
22644    { name: "diminish", type: "float" }
22645  ]
22646});
22647var mx_worley_distance_0 = /* @__PURE__ */ Fn(([p_immutable, x_immutable, y_immutable, xoff_immutable, yoff_immutable, jitter_immutable, metric_immutable]) => {
22648  const metric = int(metric_immutable).toVar();
22649  const jitter = float(jitter_immutable).toVar();
22650  const yoff = int(yoff_immutable).toVar();
22651  const xoff = int(xoff_immutable).toVar();
22652  const y = int(y_immutable).toVar();
22653  const x = int(x_immutable).toVar();
22654  const p = vec2(p_immutable).toVar();
22655  const tmp = vec3(mx_cell_noise_vec3(vec2(x.add(xoff), y.add(yoff)))).toVar();
22656  const off = vec2(tmp.x, tmp.y).toVar();
22657  off.subAssign(0.5);
22658  off.mulAssign(jitter);
22659  off.addAssign(0.5);
22660  const cellpos = vec2(vec2(float(x), float(y)).add(off)).toVar();
22661  const diff = vec2(cellpos.sub(p)).toVar();
22662  If(metric.equal(int(2)), () => {
22663    return abs(diff.x).add(abs(diff.y));
22664  });
22665  If(metric.equal(int(3)), () => {
22666    return max$1(abs(diff.x), abs(diff.y));
22667  });
22668  return dot(diff, diff);
22669}).setLayout({
22670  name: "mx_worley_distance_0",
22671  type: "float",
22672  inputs: [
22673    { name: "p", type: "vec2" },
22674    { name: "x", type: "int" },
22675    { name: "y", type: "int" },
22676    { name: "xoff", type: "int" },
22677    { name: "yoff", type: "int" },
22678    { name: "jitter", type: "float" },
22679    { name: "metric", type: "int" }
22680  ]
22681});
22682var mx_worley_distance_1 = /* @__PURE__ */ Fn(([p_immutable, x_immutable, y_immutable, z_immutable, xoff_immutable, yoff_immutable, zoff_immutable, jitter_immutable, metric_immutable]) => {
22683  const metric = int(metric_immutable).toVar();
22684  const jitter = float(jitter_immutable).toVar();
22685  const zoff = int(zoff_immutable).toVar();
22686  const yoff = int(yoff_immutable).toVar();
22687  const xoff = int(xoff_immutable).toVar();
22688  const z = int(z_immutable).toVar();
22689  const y = int(y_immutable).toVar();
22690  const x = int(x_immutable).toVar();
22691  const p = vec3(p_immutable).toVar();
22692  const off = vec3(mx_cell_noise_vec3(vec3(x.add(xoff), y.add(yoff), z.add(zoff)))).toVar();
22693  off.subAssign(0.5);
22694  off.mulAssign(jitter);
22695  off.addAssign(0.5);
22696  const cellpos = vec3(vec3(float(x), float(y), float(z)).add(off)).toVar();
22697  const diff = vec3(cellpos.sub(p)).toVar();
22698  If(metric.equal(int(2)), () => {
22699    return abs(diff.x).add(abs(diff.y)).add(abs(diff.z));
22700  });
22701  If(metric.equal(int(3)), () => {
22702    return max$1(abs(diff.x), abs(diff.y), abs(diff.z));
22703  });
22704  return dot(diff, diff);
22705}).setLayout({
22706  name: "mx_worley_distance_1",
22707  type: "float",
22708  inputs: [
22709    { name: "p", type: "vec3" },
22710    { name: "x", type: "int" },
22711    { name: "y", type: "int" },
22712    { name: "z", type: "int" },
22713    { name: "xoff", type: "int" },
22714    { name: "yoff", type: "int" },
22715    { name: "zoff", type: "int" },
22716    { name: "jitter", type: "float" },
22717    { name: "metric", type: "int" }
22718  ]
22719});
22720var mx_worley_distance = /* @__PURE__ */ overloadingFn([mx_worley_distance_0, mx_worley_distance_1]);
22721var mx_worley_noise_float_0 = /* @__PURE__ */ Fn(([p_immutable, jitter_immutable, metric_immutable]) => {
22722  const metric = int(metric_immutable).toVar();
22723  const jitter = float(jitter_immutable).toVar();
22724  const p = vec2(p_immutable).toVar();
22725  const X = int().toVar(), Y = int().toVar();
22726  const localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)).toVar();
22727  const sqdist = float(1e6).toVar();
22728  Loop({ start: -1, end: int(1), name: "x", condition: "<=" }, ({ x }) => {
22729    Loop({ start: -1, end: int(1), name: "y", condition: "<=" }, ({ y }) => {
22730      const dist = float(mx_worley_distance(localpos, x, y, X, Y, jitter, metric)).toVar();
22731      sqdist.assign(min$1(sqdist, dist));
22732    });
22733  });
22734  If(metric.equal(int(0)), () => {
22735    sqdist.assign(sqrt(sqdist));
22736  });
22737  return sqdist;
22738}).setLayout({
22739  name: "mx_worley_noise_float_0",
22740  type: "float",
22741  inputs: [
22742    { name: "p", type: "vec2" },
22743    { name: "jitter", type: "float" },
22744    { name: "metric", type: "int" }
22745  ]
22746});
22747var mx_worley_noise_vec2_0 = /* @__PURE__ */ Fn(([p_immutable, jitter_immutable, metric_immutable]) => {
22748  const metric = int(metric_immutable).toVar();
22749  const jitter = float(jitter_immutable).toVar();
22750  const p = vec2(p_immutable).toVar();
22751  const X = int().toVar(), Y = int().toVar();
22752  const localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)).toVar();
22753  const sqdist = vec2(1e6, 1e6).toVar();
22754  Loop({ start: -1, end: int(1), name: "x", condition: "<=" }, ({ x }) => {
22755    Loop({ start: -1, end: int(1), name: "y", condition: "<=" }, ({ y }) => {
22756      const dist = float(mx_worley_distance(localpos, x, y, X, Y, jitter, metric)).toVar();
22757      If(dist.lessThan(sqdist.x), () => {
22758        sqdist.y.assign(sqdist.x);
22759        sqdist.x.assign(dist);
22760      }).ElseIf(dist.lessThan(sqdist.y), () => {
22761        sqdist.y.assign(dist);
22762      });
22763    });
22764  });
22765  If(metric.equal(int(0)), () => {
22766    sqdist.assign(sqrt(sqdist));
22767  });
22768  return sqdist;
22769}).setLayout({
22770  name: "mx_worley_noise_vec2_0",
22771  type: "vec2",
22772  inputs: [
22773    { name: "p", type: "vec2" },
22774    { name: "jitter", type: "float" },
22775    { name: "metric", type: "int" }
22776  ]
22777});
22778var mx_worley_noise_vec3_0 = /* @__PURE__ */ Fn(([p_immutable, jitter_immutable, metric_immutable]) => {
22779  const metric = int(metric_immutable).toVar();
22780  const jitter = float(jitter_immutable).toVar();
22781  const p = vec2(p_immutable).toVar();
22782  const X = int().toVar(), Y = int().toVar();
22783  const localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)).toVar();
22784  const sqdist = vec3(1e6, 1e6, 1e6).toVar();
22785  Loop({ start: -1, end: int(1), name: "x", condition: "<=" }, ({ x }) => {
22786    Loop({ start: -1, end: int(1), name: "y", condition: "<=" }, ({ y }) => {
22787      const dist = float(mx_worley_distance(localpos, x, y, X, Y, jitter, metric)).toVar();
22788      If(dist.lessThan(sqdist.x), () => {
22789        sqdist.z.assign(sqdist.y);
22790        sqdist.y.assign(sqdist.x);
22791        sqdist.x.assign(dist);
22792      }).ElseIf(dist.lessThan(sqdist.y), () => {
22793        sqdist.z.assign(sqdist.y);
22794        sqdist.y.assign(dist);
22795      }).ElseIf(dist.lessThan(sqdist.z), () => {
22796        sqdist.z.assign(dist);
22797      });
22798    });
22799  });
22800  If(metric.equal(int(0)), () => {
22801    sqdist.assign(sqrt(sqdist));
22802  });
22803  return sqdist;
22804}).setLayout({
22805  name: "mx_worley_noise_vec3_0",
22806  type: "vec3",
22807  inputs: [
22808    { name: "p", type: "vec2" },
22809    { name: "jitter", type: "float" },
22810    { name: "metric", type: "int" }
22811  ]
22812});
22813var mx_worley_noise_float_1 = /* @__PURE__ */ Fn(([p_immutable, jitter_immutable, metric_immutable]) => {
22814  const metric = int(metric_immutable).toVar();
22815  const jitter = float(jitter_immutable).toVar();
22816  const p = vec3(p_immutable).toVar();
22817  const X = int().toVar(), Y = int().toVar(), Z = int().toVar();
22818  const localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)).toVar();
22819  const sqdist = float(1e6).toVar();
22820  Loop({ start: -1, end: int(1), name: "x", condition: "<=" }, ({ x }) => {
22821    Loop({ start: -1, end: int(1), name: "y", condition: "<=" }, ({ y }) => {
22822      Loop({ start: -1, end: int(1), name: "z", condition: "<=" }, ({ z }) => {
22823        const dist = float(mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric)).toVar();
22824        sqdist.assign(min$1(sqdist, dist));
22825      });
22826    });
22827  });
22828  If(metric.equal(int(0)), () => {
22829    sqdist.assign(sqrt(sqdist));
22830  });
22831  return sqdist;
22832}).setLayout({
22833  name: "mx_worley_noise_float_1",
22834  type: "float",
22835  inputs: [
22836    { name: "p", type: "vec3" },
22837    { name: "jitter", type: "float" },
22838    { name: "metric", type: "int" }
22839  ]
22840});
22841var mx_worley_noise_float$1 = /* @__PURE__ */ overloadingFn([mx_worley_noise_float_0, mx_worley_noise_float_1]);
22842var mx_worley_noise_vec2_1 = /* @__PURE__ */ Fn(([p_immutable, jitter_immutable, metric_immutable]) => {
22843  const metric = int(metric_immutable).toVar();
22844  const jitter = float(jitter_immutable).toVar();
22845  const p = vec3(p_immutable).toVar();
22846  const X = int().toVar(), Y = int().toVar(), Z = int().toVar();
22847  const localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)).toVar();
22848  const sqdist = vec2(1e6, 1e6).toVar();
22849  Loop({ start: -1, end: int(1), name: "x", condition: "<=" }, ({ x }) => {
22850    Loop({ start: -1, end: int(1), name: "y", condition: "<=" }, ({ y }) => {
22851      Loop({ start: -1, end: int(1), name: "z", condition: "<=" }, ({ z }) => {
22852        const dist = float(mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric)).toVar();
22853        If(dist.lessThan(sqdist.x), () => {
22854          sqdist.y.assign(sqdist.x);
22855          sqdist.x.assign(dist);
22856        }).ElseIf(dist.lessThan(sqdist.y), () => {
22857          sqdist.y.assign(dist);
22858        });
22859      });
22860    });
22861  });
22862  If(metric.equal(int(0)), () => {
22863    sqdist.assign(sqrt(sqdist));
22864  });
22865  return sqdist;
22866}).setLayout({
22867  name: "mx_worley_noise_vec2_1",
22868  type: "vec2",
22869  inputs: [
22870    { name: "p", type: "vec3" },
22871    { name: "jitter", type: "float" },
22872    { name: "metric", type: "int" }
22873  ]
22874});
22875var mx_worley_noise_vec2$1 = /* @__PURE__ */ overloadingFn([mx_worley_noise_vec2_0, mx_worley_noise_vec2_1]);
22876var mx_worley_noise_vec3_1 = /* @__PURE__ */ Fn(([p_immutable, jitter_immutable, metric_immutable]) => {
22877  const metric = int(metric_immutable).toVar();
22878  const jitter = float(jitter_immutable).toVar();
22879  const p = vec3(p_immutable).toVar();
22880  const X = int().toVar(), Y = int().toVar(), Z = int().toVar();
22881  const localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)).toVar();
22882  const sqdist = vec3(1e6, 1e6, 1e6).toVar();
22883  Loop({ start: -1, end: int(1), name: "x", condition: "<=" }, ({ x }) => {
22884    Loop({ start: -1, end: int(1), name: "y", condition: "<=" }, ({ y }) => {
22885      Loop({ start: -1, end: int(1), name: "z", condition: "<=" }, ({ z }) => {
22886        const dist = float(mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric)).toVar();
22887        If(dist.lessThan(sqdist.x), () => {
22888          sqdist.z.assign(sqdist.y);
22889          sqdist.y.assign(sqdist.x);
22890          sqdist.x.assign(dist);
22891        }).ElseIf(dist.lessThan(sqdist.y), () => {
22892          sqdist.z.assign(sqdist.y);
22893          sqdist.y.assign(dist);
22894        }).ElseIf(dist.lessThan(sqdist.z), () => {
22895          sqdist.z.assign(dist);
22896        });
22897      });
22898    });
22899  });
22900  If(metric.equal(int(0)), () => {
22901    sqdist.assign(sqrt(sqdist));
22902  });
22903  return sqdist;
22904}).setLayout({
22905  name: "mx_worley_noise_vec3_1",
22906  type: "vec3",
22907  inputs: [
22908    { name: "p", type: "vec3" },
22909    { name: "jitter", type: "float" },
22910    { name: "metric", type: "int" }
22911  ]
22912});
22913var mx_worley_noise_vec3$1 = /* @__PURE__ */ overloadingFn([mx_worley_noise_vec3_0, mx_worley_noise_vec3_1]);
22914var mx_unifiednoise2d$1 = /* @__PURE__ */ Fn(([
22915  noiseType_immutable,
22916  texcoord_immutable,
22917  freq_immutable,
22918  offset_immutable,
22919  jitter_immutable,
22920  outmin_immutable,
22921  outmax_immutable,
22922  clampoutput_immutable,
22923  octaves_immutable,
22924  lacunarity_immutable,
22925  diminish_immutable
22926]) => {
22927  const noiseType = int(noiseType_immutable).toVar();
22928  const texcoord = vec2(texcoord_immutable).toVar();
22929  const freq = vec2(freq_immutable).toVar();
22930  const offset3 = vec2(offset_immutable).toVar();
22931  const jitter = float(jitter_immutable).toVar();
22932  const outmin = float(outmin_immutable).toVar();
22933  const outmax = float(outmax_immutable).toVar();
22934  const clampoutput = bool(clampoutput_immutable).toVar();
22935  const octaves = int(octaves_immutable).toVar();
22936  const lacunarity = float(lacunarity_immutable).toVar();
22937  const diminish = float(diminish_immutable).toVar();
22938  const p = texcoord.mul(freq).add(offset3);
22939  const result = float(0).toVar();
22940  If(noiseType.equal(int(0)), () => {
22941    result.assign(mx_perlin_noise_vec3(p));
22942  });
22943  If(noiseType.equal(int(1)), () => {
22944    result.assign(mx_cell_noise_vec3(p));
22945  });
22946  If(noiseType.equal(int(2)), () => {
22947    result.assign(mx_worley_noise_vec3$1(p, jitter, int(0)));
22948  });
22949  If(noiseType.equal(int(3)), () => {
22950    result.assign(mx_fractal_noise_vec3$1(vec3(p, 0), octaves, lacunarity, diminish));
22951  });
22952  result.assign(result.mul(outmax.sub(outmin)).add(outmin));
22953  If(clampoutput, () => {
22954    result.assign(clamp(result, outmin, outmax));
22955  });
22956  return result;
22957}).setLayout({
22958  name: "mx_unifiednoise2d",
22959  type: "float",
22960  inputs: [
22961    { name: "noiseType", type: "int" },
22962    { name: "texcoord", type: "vec2" },
22963    { name: "freq", type: "vec2" },
22964    { name: "offset", type: "vec2" },
22965    { name: "jitter", type: "float" },
22966    { name: "outmin", type: "float" },
22967    { name: "outmax", type: "float" },
22968    { name: "clampoutput", type: "bool" },
22969    { name: "octaves", type: "int" },
22970    { name: "lacunarity", type: "float" },
22971    { name: "diminish", type: "float" }
22972  ]
22973});
22974var mx_unifiednoise3d$1 = /* @__PURE__ */ Fn(([
22975  noiseType_immutable,
22976  position_immutable,
22977  freq_immutable,
22978  offset_immutable,
22979  jitter_immutable,
22980  outmin_immutable,
22981  outmax_immutable,
22982  clampoutput_immutable,
22983  octaves_immutable,
22984  lacunarity_immutable,
22985  diminish_immutable
22986]) => {
22987  const noiseType = int(noiseType_immutable).toVar();
22988  const position = vec3(position_immutable).toVar();
22989  const freq = vec3(freq_immutable).toVar();
22990  const offset3 = vec3(offset_immutable).toVar();
22991  const jitter = float(jitter_immutable).toVar();
22992  const outmin = float(outmin_immutable).toVar();
22993  const outmax = float(outmax_immutable).toVar();
22994  const clampoutput = bool(clampoutput_immutable).toVar();
22995  const octaves = int(octaves_immutable).toVar();
22996  const lacunarity = float(lacunarity_immutable).toVar();
22997  const diminish = float(diminish_immutable).toVar();
22998  const p = position.mul(freq).add(offset3);
22999  const result = float(0).toVar();
23000  If(noiseType.equal(int(0)), () => {
23001    result.assign(mx_perlin_noise_vec3(p));
23002  });
23003  If(noiseType.equal(int(1)), () => {
23004    result.assign(mx_cell_noise_vec3(p));
23005  });
23006  If(noiseType.equal(int(2)), () => {
23007    result.assign(mx_worley_noise_vec3$1(p, jitter, int(0)));
23008  });
23009  If(noiseType.equal(int(3)), () => {
23010    result.assign(mx_fractal_noise_vec3$1(p, octaves, lacunarity, diminish));
23011  });
23012  result.assign(result.mul(outmax.sub(outmin)).add(outmin));
23013  If(clampoutput, () => {
23014    result.assign(clamp(result, outmin, outmax));
23015  });
23016  return result;
23017}).setLayout({
23018  name: "mx_unifiednoise3d",
23019  type: "float",
23020  inputs: [
23021    { name: "noiseType", type: "int" },
23022    { name: "position", type: "vec3" },
23023    { name: "freq", type: "vec3" },
23024    { name: "offset", type: "vec3" },
23025    { name: "jitter", type: "float" },
23026    { name: "outmin", type: "float" },
23027    { name: "outmax", type: "float" },
23028    { name: "clampoutput", type: "bool" },
23029    { name: "octaves", type: "int" },
23030    { name: "lacunarity", type: "float" },
23031    { name: "diminish", type: "float" }
23032  ]
23033});
23034var mx_hsvtorgb = /* @__PURE__ */ Fn(([hsv]) => {
23035  const s = hsv.y;
23036  const v = hsv.z;
23037  const result = vec3().toVar();
23038  If(s.lessThan(1e-4), () => {
23039    result.assign(vec3(v, v, v));
23040  }).Else(() => {
23041    let h = hsv.x;
23042    h = h.sub(floor(h)).mul(6).toVar();
23043    const hi = int(trunc(h));
23044    const f = h.sub(float(hi));
23045    const p = v.mul(s.oneMinus());
23046    const q = v.mul(s.mul(f).oneMinus());
23047    const t = v.mul(s.mul(f.oneMinus()).oneMinus());
23048    If(hi.equal(int(0)), () => {
23049      result.assign(vec3(v, t, p));
23050    }).ElseIf(hi.equal(int(1)), () => {
23051      result.assign(vec3(q, v, p));
23052    }).ElseIf(hi.equal(int(2)), () => {
23053      result.assign(vec3(p, v, t));
23054    }).ElseIf(hi.equal(int(3)), () => {
23055      result.assign(vec3(p, q, v));
23056    }).ElseIf(hi.equal(int(4)), () => {
23057      result.assign(vec3(t, p, v));
23058    }).Else(() => {
23059      result.assign(vec3(v, p, q));
23060    });
23061  });
23062  return result;
23063}).setLayout({
23064  name: "mx_hsvtorgb",
23065  type: "vec3",
23066  inputs: [
23067    { name: "hsv", type: "vec3" }
23068  ]
23069});
23070var mx_rgbtohsv = /* @__PURE__ */ Fn(([c_immutable]) => {
23071  const c = vec3(c_immutable).toVar();
23072  const r = float(c.x).toVar();
23073  const g = float(c.y).toVar();
23074  const b = float(c.z).toVar();
23075  const mincomp = float(min$1(r, min$1(g, b))).toVar();
23076  const maxcomp = float(max$1(r, max$1(g, b))).toVar();
23077  const delta = float(maxcomp.sub(mincomp)).toVar();
23078  const h = float().toVar(), s = float().toVar(), v = float().toVar();
23079  v.assign(maxcomp);
23080  If(maxcomp.greaterThan(0), () => {
23081    s.assign(delta.div(maxcomp));
23082  }).Else(() => {
23083    s.assign(0);
23084  });
23085  If(s.lessThanEqual(0), () => {
23086    h.assign(0);
23087  }).Else(() => {
23088    If(r.greaterThanEqual(maxcomp), () => {
23089      h.assign(g.sub(b).div(delta));
23090    }).ElseIf(g.greaterThanEqual(maxcomp), () => {
23091      h.assign(add(2, b.sub(r).div(delta)));
23092    }).Else(() => {
23093      h.assign(add(4, r.sub(g).div(delta)));
23094    });
23095    h.mulAssign(1 / 6);
23096    If(h.lessThan(0), () => {
23097      h.addAssign(1);
23098    });
23099  });
23100  return vec3(h, s, v);
23101}).setLayout({
23102  name: "mx_rgbtohsv",
23103  type: "vec3",
23104  inputs: [
23105    { name: "c", type: "vec3" }
23106  ]
23107});
23108var mx_srgb_texture_to_lin_rec709 = /* @__PURE__ */ Fn(([color_immutable]) => {
23109  const color3 = vec3(color_immutable).toVar();
23110  const isAbove = bvec3(greaterThan(color3, vec3(0.04045))).toVar();
23111  const linSeg = vec3(color3.div(12.92)).toVar();
23112  const powSeg = vec3(pow(max$1(color3.add(vec3(0.055)), vec3(0)).div(1.055), vec3(2.4))).toVar();
23113  return mix(linSeg, powSeg, isAbove);
23114}).setLayout({
23115  name: "mx_srgb_texture_to_lin_rec709",
23116  type: "vec3",
23117  inputs: [
23118    { name: "color", type: "vec3" }
23119  ]
23120});
23121var mx_aastep = (threshold, value) => {
23122  threshold = float(threshold);
23123  value = float(value);
23124  const afwidth = vec2(value.dFdx(), value.dFdy()).length().mul(0.7071067811865476);
23125  return smoothstep(threshold.sub(afwidth), threshold.add(afwidth), value);
23126};
23127var _ramp = (a, b, uv3, p) => mix(a, b, uv3[p].clamp());
23128var mx_ramplr = (valuel, valuer, texcoord = uv$1()) => _ramp(valuel, valuer, texcoord, "x");
23129var mx_ramptb = (valuet, valueb, texcoord = uv$1()) => _ramp(valuet, valueb, texcoord, "y");
23130var mx_ramp4 = (valuetl, valuetr, valuebl, valuebr, texcoord = uv$1()) => {
23131  const u = texcoord.x.clamp();
23132  const v = texcoord.y.clamp();
23133  const top = mix(valuetl, valuetr, u);
23134  const bottom = mix(valuebl, valuebr, u);
23135  return mix(top, bottom, v);
23136};
23137var _split = (a, b, center, uv3, p) => mix(a, b, mx_aastep(center, uv3[p]));
23138var mx_splitlr = (valuel, valuer, center, texcoord = uv$1()) => _split(valuel, valuer, center, texcoord, "x");
23139var mx_splittb = (valuet, valueb, center, texcoord = uv$1()) => _split(valuet, valueb, center, texcoord, "y");
23140var mx_transform_uv = (uv_scale = 1, uv_offset = 0, uv_geo = uv$1()) => uv_geo.mul(uv_scale).add(uv_offset);
23141var mx_safepower = (in1, in2 = 1) => {
23142  in1 = float(in1);
23143  return in1.abs().pow(in2).mul(in1.sign());
23144};
23145var mx_contrast = (input, amount = 1, pivot = 0.5) => float(input).sub(pivot).mul(amount).add(pivot);
23146var mx_noise_float = (texcoord = uv$1(), amplitude = 1, pivot = 0) => mx_perlin_noise_float(texcoord.convert("vec2|vec3")).mul(amplitude).add(pivot);
23147var mx_noise_vec3 = (texcoord = uv$1(), amplitude = 1, pivot = 0) => mx_perlin_noise_vec3(texcoord.convert("vec2|vec3")).mul(amplitude).add(pivot);
23148var mx_noise_vec4 = (texcoord = uv$1(), amplitude = 1, pivot = 0) => {
23149  texcoord = texcoord.convert("vec2|vec3");
23150  const noise_vec4 = vec4(mx_perlin_noise_vec3(texcoord), mx_perlin_noise_float(texcoord.add(vec2(19, 73))));
23151  return noise_vec4.mul(amplitude).add(pivot);
23152};
23153var mx_unifiednoise2d = (noiseType, texcoord = uv$1(), freq = vec2(1, 1), offset3 = vec2(0, 0), jitter = 1, outmin = 0, outmax = 1, clampoutput = false, octaves = 1, lacunarity = 2, diminish = 0.5) => mx_unifiednoise2d$1(noiseType, texcoord.convert("vec2|vec3"), freq, offset3, jitter, outmin, outmax, clampoutput, octaves, lacunarity, diminish);
23154var mx_unifiednoise3d = (noiseType, texcoord = uv$1(), freq = vec2(1, 1), offset3 = vec2(0, 0), jitter = 1, outmin = 0, outmax = 1, clampoutput = false, octaves = 1, lacunarity = 2, diminish = 0.5) => mx_unifiednoise3d$1(noiseType, texcoord.convert("vec2|vec3"), freq, offset3, jitter, outmin, outmax, clampoutput, octaves, lacunarity, diminish);
23155var mx_worley_noise_float = (texcoord = uv$1(), jitter = 1) => mx_worley_noise_float$1(texcoord.convert("vec2|vec3"), jitter, int(1));
23156var mx_worley_noise_vec2 = (texcoord = uv$1(), jitter = 1) => mx_worley_noise_vec2$1(texcoord.convert("vec2|vec3"), jitter, int(1));
23157var mx_worley_noise_vec3 = (texcoord = uv$1(), jitter = 1) => mx_worley_noise_vec3$1(texcoord.convert("vec2|vec3"), jitter, int(1));
23158var mx_cell_noise_float = (texcoord = uv$1()) => mx_cell_noise_float$1(texcoord.convert("vec2|vec3"));
23159var mx_fractal_noise_float = (position = uv$1(), octaves = 3, lacunarity = 2, diminish = 0.5, amplitude = 1) => mx_fractal_noise_float$1(position, int(octaves), lacunarity, diminish).mul(amplitude);
23160var mx_fractal_noise_vec2 = (position = uv$1(), octaves = 3, lacunarity = 2, diminish = 0.5, amplitude = 1) => mx_fractal_noise_vec2$1(position, int(octaves), lacunarity, diminish).mul(amplitude);
23161var mx_fractal_noise_vec3 = (position = uv$1(), octaves = 3, lacunarity = 2, diminish = 0.5, amplitude = 1) => mx_fractal_noise_vec3$1(position, int(octaves), lacunarity, diminish).mul(amplitude);
23162var mx_fractal_noise_vec4 = (position = uv$1(), octaves = 3, lacunarity = 2, diminish = 0.5, amplitude = 1) => mx_fractal_noise_vec4$1(position, int(octaves), lacunarity, diminish).mul(amplitude);
23163var mx_add = (in1, in2 = float(0)) => add(in1, in2);
23164var mx_subtract = (in1, in2 = float(0)) => sub(in1, in2);
23165var mx_multiply = (in1, in2 = float(1)) => mul(in1, in2);
23166var mx_divide = (in1, in2 = float(1)) => div(in1, in2);
23167var mx_modulo = (in1, in2 = float(1)) => mod(in1, in2);
23168var mx_power = (in1, in2 = float(1)) => pow(in1, in2);
23169var mx_atan2 = (in1 = float(0), in2 = float(1)) => atan(in1, in2);
23170var mx_timer = () => time;
23171var mx_frame = () => frameId;
23172var mx_invert = (in1, amount = float(1)) => sub(amount, in1);
23173var mx_ifgreater = (value1, value2, in1, in2) => value1.greaterThan(value2).mix(in1, in2);
23174var mx_ifgreatereq = (value1, value2, in1, in2) => value1.greaterThanEqual(value2).mix(in1, in2);
23175var mx_ifequal = (value1, value2, in1, in2) => value1.equal(value2).mix(in1, in2);
23176var mx_separate = (in1, channelOrOut = null) => {
23177  if (typeof channelOrOut === "string") {
23178    const map = { x: 0, r: 0, y: 1, g: 1, z: 2, b: 2, w: 3, a: 3 };
23179    const c = channelOrOut.replace(/^out/, "").toLowerCase();
23180    if (map[c] !== void 0) return in1.element(map[c]);
23181  }
23182  if (typeof channelOrOut === "number") {
23183    return in1.element(channelOrOut);
23184  }
23185  if (typeof channelOrOut === "string" && channelOrOut.length === 1) {
23186    const map = { x: 0, r: 0, y: 1, g: 1, z: 2, b: 2, w: 3, a: 3 };
23187    if (map[channelOrOut] !== void 0) return in1.element(map[channelOrOut]);
23188  }
23189  return in1;
23190};
23191var mx_place2d = (texcoord, pivot = vec2(0.5, 0.5), scale2 = vec2(1, 1), rotate3 = float(0), offset3 = vec2(0, 0)) => {
23192  let uv3 = texcoord;
23193  if (pivot) uv3 = uv3.sub(pivot);
23194  if (scale2) uv3 = uv3.mul(scale2);
23195  if (rotate3) {
23196    const rad = rotate3.mul(Math.PI / 180);
23197    const cosR = rad.cos();
23198    const sinR = rad.sin();
23199    uv3 = vec2(
23200      uv3.x.mul(cosR).sub(uv3.y.mul(sinR)),
23201      uv3.x.mul(sinR).add(uv3.y.mul(cosR))
23202    );
23203  }
23204  if (pivot) uv3 = uv3.add(pivot);
23205  if (offset3) uv3 = uv3.add(offset3);
23206  return uv3;
23207};
23208var mx_rotate2d = (input, amount) => {
23209  input = vec2(input);
23210  amount = float(amount);
23211  const radians3 = amount.mul(Math.PI / 180);
23212  return rotate(input, radians3);
23213};
23214var mx_rotate3d = (input, amount, axis) => {
23215  input = vec3(input);
23216  amount = float(amount);
23217  axis = vec3(axis);
23218  const radians3 = amount.mul(Math.PI / 180);
23219  const nAxis = axis.normalize();
23220  const cosA = radians3.cos();
23221  const sinA = radians3.sin();
23222  const oneMinusCosA = float(1).sub(cosA);
23223  const rot = input.mul(cosA).add(nAxis.cross(input).mul(sinA)).add(nAxis.mul(nAxis.dot(input)).mul(oneMinusCosA));
23224  return rot;
23225};
23226var mx_heighttonormal = (input, scale2) => {
23227  input = vec3(input);
23228  scale2 = float(scale2);
23229  return bumpMap(input, scale2);
23230};
23231var getParallaxCorrectNormal = /* @__PURE__ */ Fn(([normal2, cubeSize, cubePos]) => {
23232  const nDir = normalize(normal2).toVar();
23233  const rbmax = sub(float(0.5).mul(cubeSize.sub(cubePos)), positionWorld).div(nDir).toVar();
23234  const rbmin = sub(float(-0.5).mul(cubeSize.sub(cubePos)), positionWorld).div(nDir).toVar();
23235  const rbminmax = vec3().toVar();
23236  rbminmax.x = nDir.x.greaterThan(float(0)).select(rbmax.x, rbmin.x);
23237  rbminmax.y = nDir.y.greaterThan(float(0)).select(rbmax.y, rbmin.y);
23238  rbminmax.z = nDir.z.greaterThan(float(0)).select(rbmax.z, rbmin.z);
23239  const correction = min$1(rbminmax.x, rbminmax.y, rbminmax.z).toVar();
23240  const boxIntersection = positionWorld.add(nDir.mul(correction)).toVar();
23241  return boxIntersection.sub(cubePos);
23242});
23243var getShIrradianceAt = /* @__PURE__ */ Fn(([normal2, shCoefficients]) => {
23244  const x = normal2.x, y = normal2.y, z = normal2.z;
23245  let result = shCoefficients.element(0).mul(0.886227);
23246  result = result.add(shCoefficients.element(1).mul(2 * 0.511664).mul(y));
23247  result = result.add(shCoefficients.element(2).mul(2 * 0.511664).mul(z));
23248  result = result.add(shCoefficients.element(3).mul(2 * 0.511664).mul(x));
23249  result = result.add(shCoefficients.element(4).mul(2 * 0.429043).mul(x).mul(y));
23250  result = result.add(shCoefficients.element(5).mul(2 * 0.429043).mul(y).mul(z));
23251  result = result.add(shCoefficients.element(6).mul(z.mul(z).mul(0.743125).sub(0.247708)));
23252  result = result.add(shCoefficients.element(7).mul(2 * 0.429043).mul(x).mul(z));
23253  result = result.add(shCoefficients.element(8).mul(0.429043).mul(mul(x, x).sub(mul(y, y))));
23254  return result;
23255});
23256var TSL = /* @__PURE__ */ Object.freeze({
23257  __proto__: null,
23258  BRDF_GGX,
23259  BRDF_Lambert,
23260  BasicPointShadowFilter,
23261  BasicShadowFilter,
23262  Break,
23263  Const,
23264  Continue,
23265  DFGLUT,
23266  D_GGX,
23267  Discard,
23268  EPSILON,
23269  F_Schlick,
23270  Fn,
23271  HALF_PI,
23272  INFINITY,
23273  If,
23274  Loop,
23275  NodeAccess,
23276  NodeShaderStage,
23277  NodeType,
23278  NodeUpdateType,
23279  OnBeforeFrameUpdate,
23280  OnBeforeMaterialUpdate,
23281  OnBeforeObjectUpdate,
23282  OnFrameUpdate,
23283  OnMaterialUpdate,
23284  OnObjectUpdate,
23285  PCFShadowFilter,
23286  PCFSoftShadowFilter,
23287  PI,
23288  PI2,
23289  PointShadowFilter,
23290  Return,
23291  Schlick_to_F0,
23292  ShaderNode,
23293  Stack,
23294  Switch,
23295  TBNViewMatrix,
23296  TWO_PI,
23297  VSMShadowFilter,
23298  V_GGX_SmithCorrelated,
23299  Var,
23300  VarIntent,
23301  abs,
23302  acesFilmicToneMapping,
23303  acos,
23304  acosh,
23305  add,
23306  addMethodChaining,
23307  addNodeElement,
23308  agxToneMapping,
23309  all,
23310  alphaT,
23311  and,
23312  anisotropy,
23313  anisotropyB,
23314  anisotropyT,
23315  any,
23316  append,
23317  array,
23318  arrayBuffer,
23319  asin,
23320  asinh,
23321  assign,
23322  atan,
23323  atanh,
23324  atomicAdd,
23325  atomicAnd,
23326  atomicFunc,
23327  atomicLoad,
23328  atomicMax,
23329  atomicMin,
23330  atomicOr,
23331  atomicStore,
23332  atomicSub,
23333  atomicXor,
23334  attenuationColor,
23335  attenuationDistance,
23336  attribute,
23337  attributeArray,
23338  backgroundBlurriness,
23339  backgroundIntensity,
23340  backgroundRotation,
23341  batch: batch2,
23342  bentNormalView,
23343  billboarding,
23344  bitAnd,
23345  bitNot,
23346  bitOr,
23347  bitXor,
23348  bitangentGeometry,
23349  bitangentLocal,
23350  bitangentView,
23351  bitangentWorld,
23352  bitcast,
23353  blendBurn,
23354  blendColor,
23355  blendDodge,
23356  blendOverlay,
23357  blendScreen,
23358  blur,
23359  bool,
23360  buffer,
23361  bufferAttribute,
23362  builtin,
23363  builtinAOContext,
23364  builtinShadowContext,
23365  bumpMap,
23366  bvec2,
23367  bvec3,
23368  bvec4,
23369  bypass,
23370  cache,
23371  call,
23372  cameraFar,
23373  cameraIndex,
23374  cameraNear,
23375  cameraNormalMatrix,
23376  cameraPosition,
23377  cameraProjectionMatrix,
23378  cameraProjectionMatrixInverse,
23379  cameraViewMatrix,
23380  cameraViewport,
23381  cameraWorldMatrix,
23382  cbrt,
23383  cdl,
23384  ceil,
23385  checker,
23386  cineonToneMapping,
23387  clamp,
23388  clearcoat,
23389  clearcoatNormalView,
23390  clearcoatRoughness,
23391  clipSpace,
23392  code,
23393  color,
23394  colorSpaceToWorking,
23395  colorToDirection,
23396  compute,
23397  computeKernel,
23398  computeSkinning,
23399  context,
23400  convert,
23401  convertColorSpace,
23402  convertToTexture,
23403  cos,
23404  cosh,
23405  countLeadingZeros,
23406  countOneBits,
23407  countTrailingZeros,
23408  cross,
23409  cubeTexture,
23410  cubeTextureBase,
23411  dFdx,
23412  dFdy,
23413  dashSize,
23414  debug,
23415  decrement,
23416  decrementBefore,
23417  defaultBuildStages,
23418  defaultShaderStages,
23419  defined,
23420  degrees,
23421  deltaTime,
23422  densityFogFactor,
23423  depth,
23424  depthPass,
23425  determinant,
23426  difference,
23427  diffuseColor,
23428  diffuseContribution,
23429  directPointLight,
23430  directionToColor,
23431  directionToFaceDirection,
23432  dispersion,
23433  disposeShadowMaterial,
23434  distance,
23435  div,
23436  dot,
23437  drawIndex,
23438  dynamicBufferAttribute,
23439  element,
23440  emissive,
23441  equal,
23442  equirectUV,
23443  exp,
23444  exp2,
23445  exponentialHeightFogFactor,
23446  expression,
23447  faceDirection,
23448  faceForward,
23449  faceforward,
23450  float,
23451  floatBitsToInt,
23452  floatBitsToUint,
23453  floor,
23454  fog,
23455  fract,
23456  frameGroup,
23457  frameId,
23458  frontFacing,
23459  fwidth,
23460  gain,
23461  gapSize,
23462  getConstNodeType,
23463  getCurrentStack,
23464  getDirection,
23465  getDistanceAttenuation,
23466  getGeometryRoughness,
23467  getNormalFromDepth,
23468  getParallaxCorrectNormal,
23469  getRoughness,
23470  getScreenPosition,
23471  getShIrradianceAt,
23472  getShadowMaterial,
23473  getShadowRenderObjectFunction,
23474  getTextureIndex,
23475  getViewPosition,
23476  ggxConvolution,
23477  globalId,
23478  glsl,
23479  glslFn,
23480  grayscale,
23481  greaterThan,
23482  greaterThanEqual,
23483  hash,
23484  highpModelNormalViewMatrix,
23485  highpModelViewMatrix,
23486  hue,
23487  increment,
23488  incrementBefore,
23489  inspector,
23490  instance,
23491  instanceIndex,
23492  instancedArray,
23493  instancedBufferAttribute,
23494  instancedDynamicBufferAttribute,
23495  instancedMesh,
23496  int,
23497  intBitsToFloat,
23498  interleavedGradientNoise,
23499  inverse,
23500  inverseSqrt,
23501  inversesqrt,
23502  invocationLocalIndex,
23503  invocationSubgroupIndex,
23504  ior,
23505  iridescence,
23506  iridescenceIOR,
23507  iridescenceThickness,
23508  isolate,
23509  ivec2,
23510  ivec3,
23511  ivec4,
23512  js,
23513  label,
23514  length,
23515  lengthSq,
23516  lessThan,
23517  lessThanEqual,
23518  lightPosition,
23519  lightProjectionUV,
23520  lightShadowMatrix,
23521  lightTargetDirection,
23522  lightTargetPosition,
23523  lightViewPosition,
23524  lightingContext,
23525  lights,
23526  linearDepth,
23527  linearToneMapping,
23528  localId,
23529  log: log2,
23530  log2: log22,
23531  logarithmicDepthToViewZ,
23532  luminance,
23533  mat2,
23534  mat3,
23535  mat4,
23536  matcapUV,
23537  materialAO,
23538  materialAlphaTest,
23539  materialAnisotropy,
23540  materialAnisotropyVector,
23541  materialAttenuationColor,
23542  materialAttenuationDistance,
23543  materialClearcoat,
23544  materialClearcoatNormal,
23545  materialClearcoatRoughness,
23546  materialColor,
23547  materialDispersion,
23548  materialEmissive,
23549  materialEnvIntensity,
23550  materialEnvRotation,
23551  materialIOR,
23552  materialIridescence,
23553  materialIridescenceIOR,
23554  materialIridescenceThickness,
23555  materialLightMap,
23556  materialLineDashOffset,
23557  materialLineDashSize,
23558  materialLineGapSize,
23559  materialLineScale,
23560  materialLineWidth,
23561  materialMetalness,
23562  materialNormal,
23563  materialOpacity,
23564  materialPointSize,
23565  materialReference,
23566  materialReflectivity,
23567  materialRefractionRatio,
23568  materialRotation,
23569  materialRoughness,
23570  materialSheen,
23571  materialSheenRoughness,
23572  materialShininess,
23573  materialSpecular,
23574  materialSpecularColor,
23575  materialSpecularIntensity,
23576  materialSpecularStrength,
23577  materialThickness,
23578  materialTransmission,
23579  max: max$1,
23580  maxMipLevel,
23581  mediumpModelViewMatrix,
23582  metalness,
23583  min: min$1,
23584  mix,
23585  mixElement,
23586  mod,
23587  modInt,
23588  modelDirection,
23589  modelNormalMatrix,
23590  modelPosition,
23591  modelRadius,
23592  modelScale,
23593  modelViewMatrix,
23594  modelViewPosition,
23595  modelViewProjection,
23596  modelWorldMatrix,
23597  modelWorldMatrixInverse,
23598  morphReference,
23599  mrt,
23600  mul,
23601  mx_aastep,
23602  mx_add,
23603  mx_atan2,
23604  mx_cell_noise_float,
23605  mx_contrast,
23606  mx_divide,
23607  mx_fractal_noise_float,
23608  mx_fractal_noise_vec2,
23609  mx_fractal_noise_vec3,
23610  mx_fractal_noise_vec4,
23611  mx_frame,
23612  mx_heighttonormal,
23613  mx_hsvtorgb,
23614  mx_ifequal,
23615  mx_ifgreater,
23616  mx_ifgreatereq,
23617  mx_invert,
23618  mx_modulo,
23619  mx_multiply,
23620  mx_noise_float,
23621  mx_noise_vec3,
23622  mx_noise_vec4,
23623  mx_place2d,
23624  mx_power,
23625  mx_ramp4,
23626  mx_ramplr,
23627  mx_ramptb,
23628  mx_rgbtohsv,
23629  mx_rotate2d,
23630  mx_rotate3d,
23631  mx_safepower,
23632  mx_separate,
23633  mx_splitlr,
23634  mx_splittb,
23635  mx_srgb_texture_to_lin_rec709,
23636  mx_subtract,
23637  mx_timer,
23638  mx_transform_uv,
23639  mx_unifiednoise2d,
23640  mx_unifiednoise3d,
23641  mx_worley_noise_float,
23642  mx_worley_noise_vec2,
23643  mx_worley_noise_vec3,
23644  negate,
23645  neutralToneMapping,
23646  nodeArray,
23647  nodeImmutable,
23648  nodeObject,
23649  nodeObjectIntent,
23650  nodeObjects,
23651  nodeProxy,
23652  nodeProxyIntent,
23653  normalFlat,
23654  normalGeometry,
23655  normalLocal,
23656  normalMap,
23657  normalView,
23658  normalViewGeometry,
23659  normalWorld,
23660  normalWorldGeometry,
23661  normalize,
23662  not,
23663  notEqual,
23664  numWorkgroups,
23665  objectDirection,
23666  objectGroup,
23667  objectPosition,
23668  objectRadius,
23669  objectScale,
23670  objectViewPosition,
23671  objectWorldMatrix,
23672  oneMinus,
23673  or,
23674  orthographicDepthToViewZ,
23675  oscSawtooth,
23676  oscSine,
23677  oscSquare,
23678  oscTriangle,
23679  output,
23680  outputStruct,
23681  overloadingFn,
23682  packHalf2x16,
23683  packSnorm2x16,
23684  packUnorm2x16,
23685  parabola,
23686  parallaxDirection,
23687  parallaxUV,
23688  parameter,
23689  pass,
23690  passTexture,
23691  pcurve,
23692  perspectiveDepthToViewZ,
23693  pmremTexture,
23694  pointShadow,
23695  pointUV,
23696  pointWidth,
23697  positionGeometry,
23698  positionLocal,
23699  positionPrevious,
23700  positionView,
23701  positionViewDirection,
23702  positionWorld,
23703  positionWorldDirection,
23704  posterize,
23705  pow,
23706  pow2,
23707  pow3,
23708  pow4,
23709  premultiplyAlpha,
23710  property,
23711  quadBroadcast,
23712  quadSwapDiagonal,
23713  quadSwapX,
23714  quadSwapY,
23715  radians,
23716  rand,
23717  range,
23718  rangeFogFactor,
23719  reciprocal,
23720  reference,
23721  referenceBuffer,
23722  reflect,
23723  reflectVector,
23724  reflectView,
23725  reflector,
23726  refract,
23727  refractVector,
23728  refractView,
23729  reinhardToneMapping,
23730  remap,
23731  remapClamp,
23732  renderGroup,
23733  renderOutput,
23734  rendererReference,
23735  replaceDefaultUV,
23736  rotate,
23737  rotateUV,
23738  roughness,
23739  round,
23740  rtt,
23741  sRGBTransferEOTF,
23742  sRGBTransferOETF,
23743  sample,
23744  sampler,
23745  samplerComparison,
23746  saturate,
23747  saturation,
23748  screenCoordinate,
23749  screenDPR,
23750  screenSize,
23751  screenUV,
23752  select,
23753  setCurrentStack,
23754  setName,
23755  shaderStages,
23756  shadow,
23757  shadowPositionWorld,
23758  shapeCircle,
23759  sharedUniformGroup,
23760  sheen,
23761  sheenRoughness,
23762  shiftLeft,
23763  shiftRight,
23764  shininess,
23765  sign,
23766  sin,
23767  sinc,
23768  sinh,
23769  skinning,
23770  smoothstep,
23771  smoothstepElement,
23772  specularColor,
23773  specularColorBlended,
23774  specularF90,
23775  spherizeUV,
23776  split,
23777  spritesheetUV,
23778  sqrt,
23779  stack,
23780  step,
23781  stepElement,
23782  storage,
23783  storageBarrier,
23784  storageTexture,
23785  string,
23786  struct,
23787  sub,
23788  subBuild,
23789  subgroupAdd,
23790  subgroupAll,
23791  subgroupAnd,
23792  subgroupAny,
23793  subgroupBallot,
23794  subgroupBroadcast,
23795  subgroupBroadcastFirst,
23796  subgroupElect,
23797  subgroupExclusiveAdd,
23798  subgroupExclusiveMul,
23799  subgroupInclusiveAdd,
23800  subgroupInclusiveMul,
23801  subgroupIndex,
23802  subgroupMax,
23803  subgroupMin,
23804  subgroupMul,
23805  subgroupOr,
23806  subgroupShuffle,
23807  subgroupShuffleDown,
23808  subgroupShuffleUp,
23809  subgroupShuffleXor,
23810  subgroupSize,
23811  subgroupXor,
23812  tan,
23813  tangentGeometry,
23814  tangentLocal,
23815  tangentView,
23816  tangentWorld,
23817  tanh,
23818  texture,
23819  texture3D,
23820  texture3DLevel,
23821  texture3DLoad,
23822  textureBarrier,
23823  textureBicubic,
23824  textureBicubicLevel,
23825  textureCubeUV,
23826  textureLevel,
23827  textureLoad,
23828  textureSize,
23829  textureStore,
23830  thickness,
23831  time,
23832  toneMapping,
23833  toneMappingExposure,
23834  toonOutlinePass,
23835  transformDirection,
23836  transformNormal,
23837  transformNormalToView,
23838  transformedClearcoatNormalView,
23839  transformedNormalView,
23840  transformedNormalWorld,
23841  transmission,
23842  transpose,
23843  triNoise3D,
23844  triplanarTexture,
23845  triplanarTextures,
23846  trunc,
23847  uint,
23848  uintBitsToFloat,
23849  uniform,
23850  uniformArray,
23851  uniformCubeTexture,
23852  uniformFlow,
23853  uniformGroup,
23854  uniformTexture,
23855  unpackHalf2x16,
23856  unpackNormal,
23857  unpackSnorm2x16,
23858  unpackUnorm2x16,
23859  unpremultiplyAlpha,
23860  userData,
23861  uv: uv$1,
23862  uvec2,
23863  uvec3,
23864  uvec4,
23865  varying,
23866  varyingProperty,
23867  vec2,
23868  vec3,
23869  vec4,
23870  vectorComponents,
23871  velocity,
23872  vertexColor,
23873  vertexIndex,
23874  vertexStage,
23875  vibrance,
23876  viewZToLogarithmicDepth,
23877  viewZToOrthographicDepth,
23878  viewZToPerspectiveDepth,
23879  viewZToReversedOrthographicDepth,
23880  viewZToReversedPerspectiveDepth,
23881  viewport,
23882  viewportCoordinate,
23883  viewportDepthTexture,
23884  viewportLinearDepth,
23885  viewportMipTexture,
23886  viewportOpaqueMipTexture,
23887  viewportResolution,
23888  viewportSafeUV,
23889  viewportSharedTexture,
23890  viewportSize,
23891  viewportTexture,
23892  viewportUV,
23893  vogelDiskSample,
23894  wgsl,
23895  wgslFn,
23896  workgroupArray,
23897  workgroupBarrier,
23898  workgroupId,
23899  workingToColorSpace,
23900  xor
23901});
23902var _clearColor = /* @__PURE__ */ new Color4();
23903var Background = class extends DataMap {
23904  /**
23905   * Constructs a new background management component.
23906   *
23907   * @param {Renderer} renderer - The renderer.
23908   * @param {NodeManager} nodes - Renderer component for managing nodes related logic.
23909   */
23910  constructor(renderer, nodes) {
23911    super();
23912    this.renderer = renderer;
23913    this.nodes = nodes;
23914  }
23915  /**
23916   * Updates the background for the given scene. Depending on how `Scene.background`
23917   * or `Scene.backgroundNode` are configured, this method might configure a simple clear
23918   * or add a mesh to the render list for rendering the background as a textured plane
23919   * or skybox.
23920   *
23921   * @param {Scene} scene - The scene.
23922   * @param {RenderList} renderList - The current render list.
23923   * @param {RenderContext} renderContext - The current render context.
23924   */
23925  update(scene, renderList, renderContext) {
23926    const renderer = this.renderer;
23927    const background = this.nodes.getBackgroundNode(scene) || scene.background;
23928    let forceClear = false;
23929    if (background === null) {
23930      renderer._clearColor.getRGB(_clearColor);
23931      _clearColor.a = renderer._clearColor.a;
23932    } else if (background.isColor === true) {
23933      background.getRGB(_clearColor);
23934      _clearColor.a = 1;
23935      forceClear = true;
23936    } else if (background.isNode === true) {
23937      const sceneData = this.get(scene);
23938      const backgroundNode = background;
23939      _clearColor.copy(renderer._clearColor);
23940      let backgroundMesh = sceneData.backgroundMesh;
23941      if (backgroundMesh === void 0) {
23942        let onBackgroundDispose = function() {
23943          background.removeEventListener("dispose", onBackgroundDispose);
23944          backgroundMesh.material.dispose();
23945          backgroundMesh.geometry.dispose();
23946        };
23947        const backgroundMeshNode = vec4(backgroundNode).mul(backgroundIntensity).context({
23948          // @TODO: Add Texture2D support using node context
23949          getUV: () => backgroundRotation.mul(normalWorldGeometry),
23950          getTextureLevel: () => backgroundBlurriness
23951        });
23952        const isOrtho = cameraProjectionMatrix.element(3).element(3).equal(1);
23953        const orthoScale = div(1, cameraProjectionMatrix.element(1).element(1)).mul(3);
23954        const modifiedPosition = isOrtho.select(positionLocal.mul(orthoScale), positionLocal);
23955        const viewPosition = modelViewMatrix.mul(vec4(modifiedPosition, 0));
23956        let viewProj = cameraProjectionMatrix.mul(vec4(viewPosition.xyz, 1));
23957        viewProj = viewProj.setZ(viewProj.w);
23958        const nodeMaterial = new NodeMaterial();
23959        nodeMaterial.name = "Background.material";
23960        nodeMaterial.side = BackSide;
23961        nodeMaterial.depthTest = false;
23962        nodeMaterial.depthWrite = false;
23963        nodeMaterial.allowOverride = false;
23964        nodeMaterial.fog = false;
23965        nodeMaterial.lights = false;
23966        nodeMaterial.vertexNode = viewProj;
23967        nodeMaterial.colorNode = backgroundMeshNode;
23968        sceneData.backgroundMeshNode = backgroundMeshNode;
23969        sceneData.backgroundMesh = backgroundMesh = new Mesh(new SphereGeometry(1, 32, 32), nodeMaterial);
23970        backgroundMesh.frustumCulled = false;
23971        backgroundMesh.name = "Background.mesh";
23972        background.addEventListener("dispose", onBackgroundDispose);
23973      }
23974      const backgroundCacheKey = backgroundNode.getCacheKey();
23975      if (sceneData.backgroundCacheKey !== backgroundCacheKey) {
23976        sceneData.backgroundMeshNode.node = vec4(backgroundNode).mul(backgroundIntensity);
23977        sceneData.backgroundMeshNode.needsUpdate = true;
23978        backgroundMesh.material.needsUpdate = true;
23979        sceneData.backgroundCacheKey = backgroundCacheKey;
23980      }
23981      renderList.unshift(backgroundMesh, backgroundMesh.geometry, backgroundMesh.material, 0, 0, null, null);
23982    } else {
23983      error("Renderer: Unsupported background configuration.", background);
23984    }
23985    const environmentBlendMode = renderer.xr.getEnvironmentBlendMode();
23986    if (environmentBlendMode === "additive") {
23987      _clearColor.set(0, 0, 0, 1);
23988    } else if (environmentBlendMode === "alpha-blend") {
23989      _clearColor.set(0, 0, 0, 0);
23990    }
23991    if (renderer.autoClear === true || forceClear === true) {
23992      const clearColorValue = renderContext.clearColorValue;
23993      clearColorValue.r = _clearColor.r;
23994      clearColorValue.g = _clearColor.g;
23995      clearColorValue.b = _clearColor.b;
23996      clearColorValue.a = _clearColor.a;
23997      if (renderer.backend.isWebGLBackend === true || renderer.alpha === true) {
23998        clearColorValue.r *= clearColorValue.a;
23999        clearColorValue.g *= clearColorValue.a;
24000        clearColorValue.b *= clearColorValue.a;
24001      }
24002      renderContext.depthClearValue = renderer.getClearDepth();
24003      renderContext.stencilClearValue = renderer.getClearStencil();
24004      renderContext.clearColor = renderer.autoClearColor === true;
24005      renderContext.clearDepth = renderer.autoClearDepth === true;
24006      renderContext.clearStencil = renderer.autoClearStencil === true;
24007    } else {
24008      renderContext.clearColor = false;
24009      renderContext.clearDepth = false;
24010      renderContext.clearStencil = false;
24011    }
24012  }
24013};
24014var _id$7 = 0;
24015var BindGroup = class {
24016  /**
24017   * Constructs a new bind group.
24018   *
24019   * @param {string} name - The bind group's name.
24020   * @param {Array<Binding>} bindings - An array of bindings.
24021   * @param {number} index - The group index.
24022   */
24023  constructor(name = "", bindings = []) {
24024    this.name = name;
24025    this.bindings = bindings;
24026    this.id = _id$7++;
24027  }
24028};
24029var NodeBuilderState = class {
24030  /**
24031   * Constructs a new node builder state.
24032   *
24033   * @param {string} vertexShader - The native vertex shader code.
24034   * @param {string} fragmentShader - The native fragment shader code.
24035   * @param {string} computeShader - The native compute shader code.
24036   * @param {Array<NodeAttribute>} nodeAttributes - An array of node attributes.
24037   * @param {Array<BindGroup>} bindings - An array of bind groups.
24038   * @param {Array<Node>} updateNodes - An array of nodes that implement their `update()` method.
24039   * @param {Array<Node>} updateBeforeNodes - An array of nodes that implement their `updateBefore()` method.
24040   * @param {Array<Node>} updateAfterNodes - An array of nodes that implement their `updateAfter()` method.
24041   * @param {NodeMaterialObserver} observer - A node material observer.
24042   * @param {Array<Object>} transforms - An array with transform attribute objects. Only relevant when using compute shaders with WebGL 2.
24043   */
24044  constructor(vertexShader, fragmentShader, computeShader, nodeAttributes, bindings, updateNodes, updateBeforeNodes, updateAfterNodes, observer, transforms = []) {
24045    this.vertexShader = vertexShader;
24046    this.fragmentShader = fragmentShader;
24047    this.computeShader = computeShader;
24048    this.transforms = transforms;
24049    this.nodeAttributes = nodeAttributes;
24050    this.bindings = bindings;
24051    this.updateNodes = updateNodes;
24052    this.updateBeforeNodes = updateBeforeNodes;
24053    this.updateAfterNodes = updateAfterNodes;
24054    this.observer = observer;
24055    this.usedTimes = 0;
24056  }
24057  /**
24058   * This method is used to create a array of bind groups based
24059   * on the existing bind groups of this state. Shared groups are
24060   * not cloned.
24061   *
24062   * @return {Array<BindGroup>} A array of bind groups.
24063   */
24064  createBindings() {
24065    const bindings = [];
24066    for (const instanceGroup of this.bindings) {
24067      const shared = instanceGroup.bindings[0].groupNode.shared;
24068      if (shared !== true) {
24069        const bindingsGroup = new BindGroup(instanceGroup.name, []);
24070        bindings.push(bindingsGroup);
24071        for (const instanceBinding of instanceGroup.bindings) {
24072          bindingsGroup.bindings.push(instanceBinding.clone());
24073        }
24074      } else {
24075        bindings.push(instanceGroup);
24076      }
24077    }
24078    return bindings;
24079  }
24080};
24081var NodeAttribute = class {
24082  /**
24083   * Constructs a new node attribute.
24084   *
24085   * @param {string} name - The name of the attribute.
24086   * @param {string} type - The type of the attribute.
24087   * @param {?Node} node - An optional reference to the node.
24088   */
24089  constructor(name, type, node = null) {
24090    this.isNodeAttribute = true;
24091    this.name = name;
24092    this.type = type;
24093    this.node = node;
24094  }
24095};
24096var NodeUniform = class {
24097  /**
24098   * Constructs a new node uniform.
24099   *
24100   * @param {string} name - The name of the uniform.
24101   * @param {string} type - The type of the uniform.
24102   * @param {UniformNode} node - An reference to the node.
24103   */
24104  constructor(name, type, node) {
24105    this.isNodeUniform = true;
24106    this.name = name;
24107    this.type = type;
24108    this.node = node;
24109  }
24110  /**
24111   * The value of the uniform node.
24112   *
24113   * @type {any}
24114   */
24115  get value() {
24116    return this.node.value;
24117  }
24118  set value(val) {
24119    this.node.value = val;
24120  }
24121  /**
24122   * The id of the uniform node.
24123   *
24124   * @type {number}
24125   */
24126  get id() {
24127    return this.node.id;
24128  }
24129  /**
24130   * The uniform node's group.
24131   *
24132   * @type {UniformGroupNode}
24133   */
24134  get groupNode() {
24135    return this.node.groupNode;
24136  }
24137};
24138var NodeVar = class {
24139  /**
24140   * Constructs a new node variable.
24141   *
24142   * @param {string} name - The name of the variable.
24143   * @param {string} type - The type of the variable.
24144   * @param {boolean} [readOnly=false] - The read-only flag.
24145   * @param {?number} [count=null] - The size.
24146   */
24147  constructor(name, type, readOnly = false, count = null) {
24148    this.isNodeVar = true;
24149    this.name = name;
24150    this.type = type;
24151    this.readOnly = readOnly;
24152    this.count = count;
24153  }
24154};
24155var NodeVarying = class extends NodeVar {
24156  /**
24157   * Constructs a new node varying.
24158   *
24159   * @param {string} name - The name of the varying.
24160   * @param {string} type - The type of the varying.
24161   * @param {?string} interpolationType - The interpolation type of the varying.
24162   * @param {?string} interpolationSampling - The interpolation sampling type of the varying.
24163   */
24164  constructor(name, type, interpolationType = null, interpolationSampling = null) {
24165    super(name, type);
24166    this.needsInterpolation = false;
24167    this.isNodeVarying = true;
24168    this.interpolationType = interpolationType;
24169    this.interpolationSampling = interpolationSampling;
24170  }
24171};
24172var NodeCode = class {
24173  /**
24174   * Constructs a new code node.
24175   *
24176   * @param {string} name - The name of the code.
24177   * @param {string} type - The node type.
24178   * @param {string} [code=''] - The native shader code.
24179   */
24180  constructor(name, type, code3 = "") {
24181    this.name = name;
24182    this.type = type;
24183    this.code = code3;
24184    Object.defineProperty(this, "isNodeCode", { value: true });
24185  }
24186};
24187var _id$6 = 0;
24188var NodeCache = class {
24189  /**
24190   * Constructs a new node cache.
24191   *
24192   * @param {?NodeCache} parent - A reference to a parent cache.
24193   */
24194  constructor(parent = null) {
24195    this.id = _id$6++;
24196    this.nodesData = /* @__PURE__ */ new WeakMap();
24197    this.parent = parent;
24198  }
24199  /**
24200   * Returns the data for the given node.
24201   *
24202   * @param {Node} node - The node.
24203   * @return {?Object} The data for the node.
24204   */
24205  getData(node) {
24206    let data = this.nodesData.get(node);
24207    if (data === void 0 && this.parent !== null) {
24208      data = this.parent.getData(node);
24209    }
24210    return data;
24211  }
24212  /**
24213   * Sets the data for a given node.
24214   *
24215   * @param {Node} node - The node.
24216   * @param {Object} data - The data that should be cached.
24217   */
24218  setData(node, data) {
24219    this.nodesData.set(node, data);
24220  }
24221};
24222var StructType = class {
24223  constructor(name, members) {
24224    this.name = name;
24225    this.members = members;
24226    this.output = false;
24227  }
24228};
24229var Uniform2 = class {
24230  /**
24231   * Constructs a new uniform.
24232   *
24233   * @param {string} name - The uniform's name.
24234   * @param {any} value - The uniform's value.
24235   */
24236  constructor(name, value) {
24237    this.name = name;
24238    this.value = value;
24239    this.boundary = 0;
24240    this.itemSize = 0;
24241    this.offset = 0;
24242    this.index = -1;
24243  }
24244  /**
24245   * Sets the uniform's value.
24246   *
24247   * @param {any} value - The value to set.
24248   */
24249  setValue(value) {
24250    this.value = value;
24251  }
24252  /**
24253   * Returns the uniform's value.
24254   *
24255   * @return {any} The value.
24256   */
24257  getValue() {
24258    return this.value;
24259  }
24260};
24261var NumberUniform = class extends Uniform2 {
24262  /**
24263   * Constructs a new Number uniform.
24264   *
24265   * @param {string} name - The uniform's name.
24266   * @param {number} value - The uniform's value.
24267   */
24268  constructor(name, value = 0) {
24269    super(name, value);
24270    this.isNumberUniform = true;
24271    this.boundary = 4;
24272    this.itemSize = 1;
24273  }
24274};
24275var Vector2Uniform = class extends Uniform2 {
24276  /**
24277   * Constructs a new Number uniform.
24278   *
24279   * @param {string} name - The uniform's name.
24280   * @param {Vector2} value - The uniform's value.
24281   */
24282  constructor(name, value = new Vector2()) {
24283    super(name, value);
24284    this.isVector2Uniform = true;
24285    this.boundary = 8;
24286    this.itemSize = 2;
24287  }
24288};
24289var Vector3Uniform = class extends Uniform2 {
24290  /**
24291   * Constructs a new Number uniform.
24292   *
24293   * @param {string} name - The uniform's name.
24294   * @param {Vector3} value - The uniform's value.
24295   */
24296  constructor(name, value = new Vector3()) {
24297    super(name, value);
24298    this.isVector3Uniform = true;
24299    this.boundary = 16;
24300    this.itemSize = 3;
24301  }
24302};
24303var Vector4Uniform = class extends Uniform2 {
24304  /**
24305   * Constructs a new Number uniform.
24306   *
24307   * @param {string} name - The uniform's name.
24308   * @param {Vector4} value - The uniform's value.
24309   */
24310  constructor(name, value = new Vector4()) {
24311    super(name, value);
24312    this.isVector4Uniform = true;
24313    this.boundary = 16;
24314    this.itemSize = 4;
24315  }
24316};
24317var ColorUniform = class extends Uniform2 {
24318  /**
24319   * Constructs a new Number uniform.
24320   *
24321   * @param {string} name - The uniform's name.
24322   * @param {Color} value - The uniform's value.
24323   */
24324  constructor(name, value = new Color()) {
24325    super(name, value);
24326    this.isColorUniform = true;
24327    this.boundary = 16;
24328    this.itemSize = 3;
24329  }
24330};
24331var Matrix2Uniform = class extends Uniform2 {
24332  /**
24333   * Constructs a new Number uniform.
24334   *
24335   * @param {string} name - The uniform's name.
24336   * @param {Matrix2} value - The uniform's value.
24337   */
24338  constructor(name, value = new Matrix2()) {
24339    super(name, value);
24340    this.isMatrix2Uniform = true;
24341    this.boundary = 8;
24342    this.itemSize = 4;
24343  }
24344};
24345var Matrix3Uniform = class extends Uniform2 {
24346  /**
24347   * Constructs a new Number uniform.
24348   *
24349   * @param {string} name - The uniform's name.
24350   * @param {Matrix3} value - The uniform's value.
24351   */
24352  constructor(name, value = new Matrix3()) {
24353    super(name, value);
24354    this.isMatrix3Uniform = true;
24355    this.boundary = 48;
24356    this.itemSize = 12;
24357  }
24358};
24359var Matrix4Uniform = class extends Uniform2 {
24360  /**
24361   * Constructs a new Number uniform.
24362   *
24363   * @param {string} name - The uniform's name.
24364   * @param {Matrix4} value - The uniform's value.
24365   */
24366  constructor(name, value = new Matrix4()) {
24367    super(name, value);
24368    this.isMatrix4Uniform = true;
24369    this.boundary = 64;
24370    this.itemSize = 16;
24371  }
24372};
24373var NumberNodeUniform = class extends NumberUniform {
24374  /**
24375   * Constructs a new node-based Number uniform.
24376   *
24377   * @param {NodeUniform} nodeUniform - The node uniform.
24378   */
24379  constructor(nodeUniform) {
24380    super(nodeUniform.name, nodeUniform.value);
24381    this.nodeUniform = nodeUniform;
24382  }
24383  /**
24384   * Overwritten to return the value of the node uniform.
24385   *
24386   * @return {number} The value.
24387   */
24388  getValue() {
24389    return this.nodeUniform.value;
24390  }
24391  /**
24392   * Returns the node uniform data type.
24393   *
24394   * @return {string} The data type.
24395   */
24396  getType() {
24397    return this.nodeUniform.type;
24398  }
24399};
24400var Vector2NodeUniform = class extends Vector2Uniform {
24401  /**
24402   * Constructs a new node-based Vector2 uniform.
24403   *
24404   * @param {NodeUniform} nodeUniform - The node uniform.
24405   */
24406  constructor(nodeUniform) {
24407    super(nodeUniform.name, nodeUniform.value);
24408    this.nodeUniform = nodeUniform;
24409  }
24410  /**
24411   * Overwritten to return the value of the node uniform.
24412   *
24413   * @return {Vector2} The value.
24414   */
24415  getValue() {
24416    return this.nodeUniform.value;
24417  }
24418  /**
24419   * Returns the node uniform data type.
24420   *
24421   * @return {string} The data type.
24422   */
24423  getType() {
24424    return this.nodeUniform.type;
24425  }
24426};
24427var Vector3NodeUniform = class extends Vector3Uniform {
24428  /**
24429   * Constructs a new node-based Vector3 uniform.
24430   *
24431   * @param {NodeUniform} nodeUniform - The node uniform.
24432   */
24433  constructor(nodeUniform) {
24434    super(nodeUniform.name, nodeUniform.value);
24435    this.nodeUniform = nodeUniform;
24436  }
24437  /**
24438   * Overwritten to return the value of the node uniform.
24439   *
24440   * @return {Vector3} The value.
24441   */
24442  getValue() {
24443    return this.nodeUniform.value;
24444  }
24445  /**
24446   * Returns the node uniform data type.
24447   *
24448   * @return {string} The data type.
24449   */
24450  getType() {
24451    return this.nodeUniform.type;
24452  }
24453};
24454var Vector4NodeUniform = class extends Vector4Uniform {
24455  /**
24456   * Constructs a new node-based Vector4 uniform.
24457   *
24458   * @param {NodeUniform} nodeUniform - The node uniform.
24459   */
24460  constructor(nodeUniform) {
24461    super(nodeUniform.name, nodeUniform.value);
24462    this.nodeUniform = nodeUniform;
24463  }
24464  /**
24465   * Overwritten to return the value of the node uniform.
24466   *
24467   * @return {Vector4} The value.
24468   */
24469  getValue() {
24470    return this.nodeUniform.value;
24471  }
24472  /**
24473   * Returns the node uniform data type.
24474   *
24475   * @return {string} The data type.
24476   */
24477  getType() {
24478    return this.nodeUniform.type;
24479  }
24480};
24481var ColorNodeUniform = class extends ColorUniform {
24482  /**
24483   * Constructs a new node-based Color uniform.
24484   *
24485   * @param {NodeUniform} nodeUniform - The node uniform.
24486   */
24487  constructor(nodeUniform) {
24488    super(nodeUniform.name, nodeUniform.value);
24489    this.nodeUniform = nodeUniform;
24490  }
24491  /**
24492   * Overwritten to return the value of the node uniform.
24493   *
24494   * @return {Color} The value.
24495   */
24496  getValue() {
24497    return this.nodeUniform.value;
24498  }
24499  /**
24500   * Returns the node uniform data type.
24501   *
24502   * @return {string} The data type.
24503   */
24504  getType() {
24505    return this.nodeUniform.type;
24506  }
24507};
24508var Matrix2NodeUniform = class extends Matrix2Uniform {
24509  /**
24510   * Constructs a new node-based Matrix2 uniform.
24511   *
24512   * @param {NodeUniform} nodeUniform - The node uniform.
24513   */
24514  constructor(nodeUniform) {
24515    super(nodeUniform.name, nodeUniform.value);
24516    this.nodeUniform = nodeUniform;
24517  }
24518  /**
24519   * Overwritten to return the value of the node uniform.
24520   *
24521   * @return {Matrix2} The value.
24522   */
24523  getValue() {
24524    return this.nodeUniform.value;
24525  }
24526  /**
24527   * Returns the node uniform data type.
24528   *
24529   * @return {string} The data type.
24530   */
24531  getType() {
24532    return this.nodeUniform.type;
24533  }
24534};
24535var Matrix3NodeUniform = class extends Matrix3Uniform {
24536  /**
24537   * Constructs a new node-based Matrix3 uniform.
24538   *
24539   * @param {NodeUniform} nodeUniform - The node uniform.
24540   */
24541  constructor(nodeUniform) {
24542    super(nodeUniform.name, nodeUniform.value);
24543    this.nodeUniform = nodeUniform;
24544  }
24545  /**
24546   * Overwritten to return the value of the node uniform.
24547   *
24548   * @return {Matrix3} The value.
24549   */
24550  getValue() {
24551    return this.nodeUniform.value;
24552  }
24553  /**
24554   * Returns the node uniform data type.
24555   *
24556   * @return {string} The data type.
24557   */
24558  getType() {
24559    return this.nodeUniform.type;
24560  }
24561};
24562var Matrix4NodeUniform = class extends Matrix4Uniform {
24563  /**
24564   * Constructs a new node-based Matrix4 uniform.
24565   *
24566   * @param {NodeUniform} nodeUniform - The node uniform.
24567   */
24568  constructor(nodeUniform) {
24569    super(nodeUniform.name, nodeUniform.value);
24570    this.nodeUniform = nodeUniform;
24571  }
24572  /**
24573   * Overwritten to return the value of the node uniform.
24574   *
24575   * @return {Matrix4} The value.
24576   */
24577  getValue() {
24578    return this.nodeUniform.value;
24579  }
24580  /**
24581   * Returns the node uniform data type.
24582   *
24583   * @return {string} The data type.
24584   */
24585  getType() {
24586    return this.nodeUniform.type;
24587  }
24588};
24589var _id$5 = 0;
24590var _bindingGroupsCache = /* @__PURE__ */ new WeakMap();
24591var sharedNodeData = /* @__PURE__ */ new WeakMap();
24592var typeFromArray = /* @__PURE__ */ new Map([
24593  [Int8Array, "int"],
24594  [Int16Array, "int"],
24595  [Int32Array, "int"],
24596  [Uint8Array, "uint"],
24597  [Uint16Array, "uint"],
24598  [Uint32Array, "uint"],
24599  [Float32Array, "float"]
24600]);
24601var toFloat = (value) => {
24602  if (/e/g.test(value)) {
24603    return String(value).replace(/\+/g, "");
24604  } else {
24605    value = Number(value);
24606    return value + (value % 1 ? "" : ".0");
24607  }
24608};
24609var NodeBuilder = class {
24610  /**
24611   * Constructs a new node builder.
24612   *
24613   * @param {Object3D} object - The 3D object.
24614   * @param {Renderer} renderer - The current renderer.
24615   * @param {NodeParser} parser - A reference to a node parser.
24616   */
24617  constructor(object, renderer, parser) {
24618    this.object = object;
24619    this.material = object && object.material || null;
24620    this.geometry = object && object.geometry || null;
24621    this.renderer = renderer;
24622    this.parser = parser;
24623    this.scene = null;
24624    this.camera = null;
24625    this.nodes = [];
24626    this.sequentialNodes = [];
24627    this.updateNodes = [];
24628    this.updateBeforeNodes = [];
24629    this.updateAfterNodes = [];
24630    this.hashNodes = {};
24631    this.observer = null;
24632    this.lightsNode = null;
24633    this.environmentNode = null;
24634    this.fogNode = null;
24635    this.clippingContext = null;
24636    this.vertexShader = null;
24637    this.fragmentShader = null;
24638    this.computeShader = null;
24639    this.flowNodes = { vertex: [], fragment: [], compute: [] };
24640    this.flowCode = { vertex: "", fragment: "", compute: "" };
24641    this.uniforms = { vertex: [], fragment: [], compute: [], index: 0 };
24642    this.structs = { vertex: [], fragment: [], compute: [], index: 0 };
24643    this.types = { vertex: [], fragment: [], compute: [], index: 0 };
24644    this.bindings = { vertex: {}, fragment: {}, compute: {} };
24645    this.bindingsIndexes = {};
24646    this.bindGroups = null;
24647    this.attributes = [];
24648    this.bufferAttributes = [];
24649    this.varyings = [];
24650    this.codes = {};
24651    this.vars = {};
24652    this.declarations = {};
24653    this.flow = { code: "" };
24654    this.chaining = [];
24655    this.stack = stack();
24656    this.stacks = [];
24657    this.tab = "	";
24658    this.currentFunctionNode = null;
24659    this.context = {
24660      material: this.material
24661    };
24662    this.cache = new NodeCache();
24663    this.globalCache = this.cache;
24664    this.flowsData = /* @__PURE__ */ new WeakMap();
24665    this.shaderStage = null;
24666    this.buildStage = null;
24667    this.subBuildLayers = [];
24668    this.activeStacks = [];
24669    this.subBuildFn = null;
24670    this.fnCall = null;
24671    Object.defineProperty(this, "id", { value: _id$5++ });
24672  }
24673  /**
24674   * Whether the material is using flat shading or not.
24675   *
24676   * @returns {boolean} Whether the material is using flat shading or not.
24677   */
24678  isFlatShading() {
24679    return this.material.flatShading === true || this.geometry.hasAttribute("normal") === false;
24680  }
24681  /**
24682   * Whether the material is opaque or not.
24683   *
24684   * @return {boolean} Whether the material is opaque or not.
24685   */
24686  isOpaque() {
24687    const material = this.material;
24688    return material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false;
24689  }
24690  /**
24691   * Factory method for creating an instance of {@link RenderTarget} with the given
24692   * dimensions and options.
24693   *
24694   * @param {number} width - The width of the render target.
24695   * @param {number} height - The height of the render target.
24696   * @param {Object} options - The options of the render target.
24697   * @return {RenderTarget} The render target.
24698   */
24699  createRenderTarget(width, height, options) {
24700    return new RenderTarget(width, height, options);
24701  }
24702  /**
24703   * Factory method for creating an instance of {@link CubeRenderTarget} with the given
24704   * dimensions and options.
24705   *
24706   * @param {number} size - The size of the cube render target.
24707   * @param {Object} options - The options of the cube render target.
24708   * @return {CubeRenderTarget} The cube render target.
24709   */
24710  createCubeRenderTarget(size3, options) {
24711    return new CubeRenderTarget(size3, options);
24712  }
24713  /**
24714   * Whether the given node is included in the internal array of nodes or not.
24715   *
24716   * @param {Node} node - The node to test.
24717   * @return {boolean} Whether the given node is included in the internal array of nodes or not.
24718   */
24719  includes(node) {
24720    return this.nodes.includes(node);
24721  }
24722  /**
24723   * Returns the output struct name which is required by
24724   * {@link OutputStructNode}.
24725   *
24726   * @abstract
24727   * @return {string} The name of the output struct.
24728   */
24729  getOutputStructName() {
24730  }
24731  /**
24732   * Returns a bind group for the given group name and binding.
24733   *
24734   * @private
24735   * @param {string} groupName - The group name.
24736   * @param {Array<NodeUniformsGroup>} bindings - List of bindings.
24737   * @return {BindGroup} The bind group
24738   */
24739  _getBindGroup(groupName, bindings) {
24740    const groupNode = bindings[0].groupNode;
24741    let sharedGroup = groupNode.shared;
24742    if (sharedGroup) {
24743      for (let i = 1; i < bindings.length; i++) {
24744        if (groupNode !== bindings[i].groupNode) {
24745          sharedGroup = false;
24746        }
24747      }
24748    }
24749    let bindGroup;
24750    if (sharedGroup) {
24751      let cacheKeyString = "";
24752      for (const binding of bindings) {
24753        if (binding.isNodeUniformsGroup) {
24754          binding.uniforms.sort((a, b) => a.nodeUniform.node.id - b.nodeUniform.node.id);
24755          for (const uniform3 of binding.uniforms) {
24756            cacheKeyString += uniform3.nodeUniform.node.id;
24757          }
24758        } else {
24759          cacheKeyString += binding.nodeUniform.id;
24760        }
24761      }
24762      const currentContext = this.renderer._currentRenderContext || this.renderer;
24763      let bindingGroupsCache = _bindingGroupsCache.get(currentContext);
24764      if (bindingGroupsCache === void 0) {
24765        bindingGroupsCache = /* @__PURE__ */ new Map();
24766        _bindingGroupsCache.set(currentContext, bindingGroupsCache);
24767      }
24768      const cacheKey = hashString(cacheKeyString);
24769      bindGroup = bindingGroupsCache.get(cacheKey);
24770      if (bindGroup === void 0) {
24771        bindGroup = new BindGroup(groupName, bindings);
24772        bindingGroupsCache.set(cacheKey, bindGroup);
24773      }
24774    } else {
24775      bindGroup = new BindGroup(groupName, bindings);
24776    }
24777    return bindGroup;
24778  }
24779  /**
24780   * Returns an array of node uniform groups for the given group name and shader stage.
24781   *
24782   * @param {string} groupName - The group name.
24783   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
24784   * @return {Array<NodeUniformsGroup>} The array of node uniform groups.
24785   */
24786  getBindGroupArray(groupName, shaderStage) {
24787    const bindings = this.bindings[shaderStage];
24788    let bindGroup = bindings[groupName];
24789    if (bindGroup === void 0) {
24790      if (this.bindingsIndexes[groupName] === void 0) {
24791        this.bindingsIndexes[groupName] = { binding: 0, group: Object.keys(this.bindingsIndexes).length };
24792      }
24793      bindings[groupName] = bindGroup = [];
24794    }
24795    return bindGroup;
24796  }
24797  /**
24798   * Returns a list bindings of all shader stages separated by groups.
24799   *
24800   * @return {Array<BindGroup>} The list of bindings.
24801   */
24802  getBindings() {
24803    let bindingsGroups = this.bindGroups;
24804    if (bindingsGroups === null) {
24805      const groups = {};
24806      const bindings = this.bindings;
24807      for (const shaderStage of shaderStages) {
24808        for (const groupName in bindings[shaderStage]) {
24809          const uniforms = bindings[shaderStage][groupName];
24810          const groupUniforms = groups[groupName] || (groups[groupName] = []);
24811          for (const uniform3 of uniforms) {
24812            if (groupUniforms.includes(uniform3) === false) {
24813              groupUniforms.push(uniform3);
24814            }
24815          }
24816        }
24817      }
24818      bindingsGroups = [];
24819      for (const groupName in groups) {
24820        const group = groups[groupName];
24821        const bindingsGroup = this._getBindGroup(groupName, group);
24822        bindingsGroups.push(bindingsGroup);
24823      }
24824      this.bindGroups = bindingsGroups;
24825    }
24826    return bindingsGroups;
24827  }
24828  /**
24829   * Sorts the bind groups and updates {@link NodeBuilder#bindingsIndexes}.
24830   */
24831  sortBindingGroups() {
24832    const bindingsGroups = this.getBindings();
24833    bindingsGroups.sort((a, b) => a.bindings[0].groupNode.order - b.bindings[0].groupNode.order);
24834    for (let i = 0; i < bindingsGroups.length; i++) {
24835      const bindingGroup = bindingsGroups[i];
24836      this.bindingsIndexes[bindingGroup.name].group = i;
24837    }
24838  }
24839  /**
24840   * The builder maintains each node in a hash-based dictionary.
24841   * This method sets the given node (value) with the given hash (key) into this dictionary.
24842   *
24843   * @param {Node} node - The node to add.
24844   * @param {number} hash - The hash of the node.
24845   */
24846  setHashNode(node, hash3) {
24847    this.hashNodes[hash3] = node;
24848  }
24849  /**
24850   * Adds a node to this builder.
24851   *
24852   * @param {Node} node - The node to add.
24853   */
24854  addNode(node) {
24855    if (this.nodes.includes(node) === false) {
24856      this.nodes.push(node);
24857      this.setHashNode(node, node.getHash(this));
24858    }
24859  }
24860  /**
24861   * It is used to add Nodes that will be used as FRAME and RENDER events,
24862   * and need to follow a certain sequence in the calls to work correctly.
24863   * This function should be called after 'setup()' in the 'build()' process to ensure that the child nodes are processed first.
24864   *
24865   * @param {Node} node - The node to add.
24866   */
24867  addSequentialNode(node) {
24868    const updateBeforeType = node.getUpdateBeforeType();
24869    const updateAfterType = node.getUpdateAfterType();
24870    if (updateBeforeType !== NodeUpdateType.NONE || updateAfterType !== NodeUpdateType.NONE) {
24871      if (this.sequentialNodes.includes(node) === false) {
24872        this.sequentialNodes.push(node);
24873      }
24874    }
24875  }
24876  /**
24877   * Checks the update types of nodes
24878   */
24879  buildUpdateNodes() {
24880    for (const node of this.nodes) {
24881      const updateType = node.getUpdateType();
24882      if (updateType !== NodeUpdateType.NONE) {
24883        this.updateNodes.push(node);
24884      }
24885    }
24886    for (const node of this.sequentialNodes) {
24887      const updateBeforeType = node.getUpdateBeforeType();
24888      const updateAfterType = node.getUpdateAfterType();
24889      if (updateBeforeType !== NodeUpdateType.NONE) {
24890        this.updateBeforeNodes.push(node);
24891      }
24892      if (updateAfterType !== NodeUpdateType.NONE) {
24893        this.updateAfterNodes.push(node);
24894      }
24895    }
24896  }
24897  /**
24898   * A reference the current node which is the
24899   * last node in the chain of nodes.
24900   *
24901   * @type {Node}
24902   */
24903  get currentNode() {
24904    return this.chaining[this.chaining.length - 1];
24905  }
24906  /**
24907   * Whether the given texture is filtered or not.
24908   *
24909   * @param {Texture} texture - The texture to check.
24910   * @return {boolean} Whether the given texture is filtered or not.
24911   */
24912  isFilteredTexture(texture3) {
24913    return texture3.magFilter === LinearFilter || texture3.magFilter === LinearMipmapNearestFilter || texture3.magFilter === NearestMipmapLinearFilter || texture3.magFilter === LinearMipmapLinearFilter || texture3.minFilter === LinearFilter || texture3.minFilter === LinearMipmapNearestFilter || texture3.minFilter === NearestMipmapLinearFilter || texture3.minFilter === LinearMipmapLinearFilter;
24914  }
24915  /**
24916   * Returns the maximum number of bytes available for uniform buffers.
24917   *
24918   * @return {number} The maximum number of bytes available for uniform buffers.
24919   */
24920  getUniformBufferLimit() {
24921    return this.renderer.backend.capabilities.getUniformBufferLimit();
24922  }
24923  /**
24924   * Adds the given node to the internal node chain.
24925   * This is used to check recursive calls in node-graph.
24926   *
24927   * @param {Node} node - The node to add.
24928   */
24929  addChain(node) {
24930    this.chaining.push(node);
24931  }
24932  /**
24933   * Removes the given node from the internal node chain.
24934   *
24935   * @param {Node} node - The node to remove.
24936   */
24937  removeChain(node) {
24938    const lastChain = this.chaining.pop();
24939    if (lastChain !== node) {
24940      throw new Error("NodeBuilder: Invalid node chaining!");
24941    }
24942  }
24943  /**
24944   * Returns the native shader method name for a given generic name. E.g.
24945   * the method name `textureDimensions` matches the WGSL name but must be
24946   * resolved to `textureSize` in GLSL.
24947   *
24948   * @abstract
24949   * @param {string} method - The method name to resolve.
24950   * @return {string} The resolved method name.
24951   */
24952  getMethod(method) {
24953    return method;
24954  }
24955  /**
24956   * Returns the native snippet for a ternary operation. E.g. GLSL would output
24957   * a ternary op as `cond ? x : y` whereas WGSL would output it as `select(y, x, cond)`
24958   *
24959   * @abstract
24960   * @param {string} condSnippet - The condition determining which expression gets resolved.
24961   * @param {string} ifSnippet - The expression to resolve to if the condition is true.
24962   * @param {string} elseSnippet - The expression to resolve to if the condition is false.
24963   * @return {string} The resolved method name.
24964   */
24965  getTernary() {
24966    return null;
24967  }
24968  /**
24969   * Returns a node for the given hash, see {@link NodeBuilder#setHashNode}.
24970   *
24971   * @param {number} hash - The hash of the node.
24972   * @return {Node} The found node.
24973   */
24974  getNodeFromHash(hash3) {
24975    return this.hashNodes[hash3];
24976  }
24977  /**
24978   * Adds the Node to a target flow so that it can generate code in the 'generate' process.
24979   *
24980   * @param {('vertex'|'fragment'|'compute')} shaderStage - The shader stage.
24981   * @param {Node} node - The node to add.
24982   * @return {Node} The node.
24983   */
24984  addFlow(shaderStage, node) {
24985    this.flowNodes[shaderStage].push(node);
24986    return node;
24987  }
24988  /**
24989   * Sets builder's context.
24990   *
24991   * @param {Object} context - The context to set.
24992   */
24993  setContext(context3) {
24994    this.context = context3;
24995  }
24996  /**
24997   * Returns the builder's current context.
24998   *
24999   * @return {Object} The builder's current context.
25000   */
25001  getContext() {
25002    return this.context;
25003  }
25004  /**
25005   * Adds context data to the builder's current context.
25006   *
25007   * @param {Object} context - The context to add.
25008   * @return {Object} The previous context.
25009   */
25010  addContext(context3) {
25011    const previousContext = this.getContext();
25012    this.setContext({ ...this.context, ...context3 });
25013    return previousContext;
25014  }
25015  /**
25016   * Gets a context used in shader construction that can be shared across different materials.
25017   * This is necessary since the renderer cache can reuse shaders generated in one material and use them in another.
25018   *
25019   * @return {Object} The builder's current context without material.
25020   */
25021  getSharedContext() {
25022    const context3 = { ...this.context };
25023    delete context3.material;
25024    delete context3.getUV;
25025    delete context3.getOutput;
25026    delete context3.getTextureLevel;
25027    delete context3.getAO;
25028    delete context3.getShadow;
25029    return context3;
25030  }
25031  /**
25032   * Sets builder's cache.
25033   *
25034   * @param {NodeCache} cache - The cache to set.
25035   */
25036  setCache(cache4) {
25037    this.cache = cache4;
25038  }
25039  /**
25040   * Returns the builder's current cache.
25041   *
25042   * @return {NodeCache} The builder's current cache.
25043   */
25044  getCache() {
25045    return this.cache;
25046  }
25047  /**
25048   * Returns a cache for the given node.
25049   *
25050   * @param {Node} node - The node.
25051   * @param {boolean} [parent=true] - Whether this node refers to a shared parent cache or not.
25052   * @return {NodeCache} The cache.
25053   */
25054  getCacheFromNode(node, parent = true) {
25055    const data = this.getDataFromNode(node);
25056    if (data.cache === void 0) data.cache = new NodeCache(parent ? this.getCache() : null);
25057    return data.cache;
25058  }
25059  /**
25060   * Whether the requested feature is available or not.
25061   *
25062   * @abstract
25063   * @param {string} name - The requested feature.
25064   * @return {boolean} Whether the requested feature is supported or not.
25065   */
25066  isAvailable() {
25067    return false;
25068  }
25069  /**
25070   * Returns the vertexIndex input variable as a native shader string.
25071   *
25072   * @abstract
25073   * @return {string} The instanceIndex shader string.
25074   */
25075  getVertexIndex() {
25076    warn("Abstract function.");
25077  }
25078  /**
25079   * Contextually returns either the vertex stage instance index builtin
25080   * or the linearized index of an compute invocation within a grid of workgroups.
25081   *
25082   * @abstract
25083   * @return {string} The instanceIndex shader string.
25084   */
25085  getInstanceIndex() {
25086    warn("Abstract function.");
25087  }
25088  /**
25089   * Returns the drawIndex input variable as a native shader string.
25090   * Only relevant for WebGL and its `WEBGL_multi_draw` extension.
25091   *
25092   * @abstract
25093   * @return {?string} The drawIndex shader string.
25094   */
25095  getDrawIndex() {
25096    warn("Abstract function.");
25097  }
25098  /**
25099   * Returns the frontFacing input variable as a native shader string.
25100   *
25101   * @abstract
25102   * @return {string} The frontFacing shader string.
25103   */
25104  getFrontFacing() {
25105    warn("Abstract function.");
25106  }
25107  /**
25108   * Returns the fragCoord input variable as a native shader string.
25109   *
25110   * @abstract
25111   * @return {string} The fragCoord shader string.
25112   */
25113  getFragCoord() {
25114    warn("Abstract function.");
25115  }
25116  /**
25117   * Whether to flip texture data along its vertical axis or not. WebGL needs
25118   * this method evaluate to `true`, WebGPU to `false`.
25119   *
25120   * @abstract
25121   * @return {boolean} Whether to flip texture data along its vertical axis or not.
25122   */
25123  isFlipY() {
25124    return false;
25125  }
25126  /**
25127   * Calling this method increases the usage count for the given node by one.
25128   *
25129   * @param {Node} node - The node to increase the usage count for.
25130   * @return {number} The updated usage count.
25131   */
25132  increaseUsage(node) {
25133    const nodeData = this.getDataFromNode(node);
25134    nodeData.usageCount = nodeData.usageCount === void 0 ? 1 : nodeData.usageCount + 1;
25135    return nodeData.usageCount;
25136  }
25137  /**
25138   * Generates a texture sample shader string for the given texture data.
25139   *
25140   * @abstract
25141   * @param {Texture} texture - The texture.
25142   * @param {string} textureProperty - The texture property name.
25143   * @param {string} uvSnippet - Snippet defining the texture coordinates.
25144   * @return {string} The generated shader string.
25145   */
25146  generateTexture() {
25147    warn("Abstract function.");
25148  }
25149  /**
25150   * Generates a texture LOD shader string for the given texture data.
25151   *
25152   * @abstract
25153   * @param {Texture} texture - The texture.
25154   * @param {string} textureProperty - The texture property name.
25155   * @param {string} uvSnippet - Snippet defining the texture coordinates.
25156   * @param {?string} depthSnippet - Snippet defining the 0-based texture array index to sample.
25157   * @param {string} levelSnippet - Snippet defining the mip level.
25158   * @return {string} The generated shader string.
25159   */
25160  generateTextureLod() {
25161    warn("Abstract function.");
25162  }
25163  /**
25164   * Generates the array declaration string.
25165   *
25166   * @param {string} type - The type.
25167   * @param {?number} [count] - The count.
25168   * @return {string} The generated value as a shader string.
25169   */
25170  generateArrayDeclaration(type, count) {
25171    return this.getType(type) + "[ " + count + " ]";
25172  }
25173  /**
25174   * Generates the array shader string for the given type and value.
25175   *
25176   * @param {string} type - The type.
25177   * @param {?number} [count] - The count.
25178   * @param {?Array<Node>} [values=null] - The default values.
25179   * @return {string} The generated value as a shader string.
25180   */
25181  generateArray(type, count, values = null) {
25182    let snippet = this.generateArrayDeclaration(type, count) + "( ";
25183    for (let i = 0; i < count; i++) {
25184      const value = values ? values[i] : null;
25185      if (value !== null) {
25186        snippet += value.build(this, type);
25187      } else {
25188        snippet += this.generateConst(type);
25189      }
25190      if (i < count - 1) snippet += ", ";
25191    }
25192    snippet += " )";
25193    return snippet;
25194  }
25195  /**
25196   * Generates the struct shader string.
25197   *
25198   * @param {string} type - The type.
25199   * @param {Array<Object>} [membersLayout] - The count.
25200   * @param {?Array<Node>} [values=null] - The default values.
25201   * @return {string} The generated value as a shader string.
25202   */
25203  generateStruct(type, membersLayout, values = null) {
25204    const snippets = [];
25205    for (const member of membersLayout) {
25206      const { name, type: type2 } = member;
25207      if (values && values[name] && values[name].isNode) {
25208        snippets.push(values[name].build(this, type2));
25209      } else {
25210        snippets.push(this.generateConst(type2));
25211      }
25212    }
25213    return type + "( " + snippets.join(", ") + " )";
25214  }
25215  /**
25216   * Generates the shader string for the given type and value.
25217   *
25218   * @param {string} type - The type.
25219   * @param {?any} [value=null] - The value.
25220   * @return {string} The generated value as a shader string.
25221   */
25222  generateConst(type, value = null) {
25223    if (value === null) {
25224      if (type === "float" || type === "int" || type === "uint") value = 0;
25225      else if (type === "bool") value = false;
25226      else if (type === "color") value = new Color();
25227      else if (type === "vec2" || type === "uvec2" || type === "ivec2") value = new Vector2();
25228      else if (type === "vec3" || type === "uvec3" || type === "ivec3") value = new Vector3();
25229      else if (type === "vec4" || type === "uvec4" || type === "ivec4") value = new Vector4();
25230    }
25231    if (type === "float") return toFloat(value);
25232    if (type === "int") return `${Math.round(value)}`;
25233    if (type === "uint") return value >= 0 ? `${Math.round(value)}u` : "0u";
25234    if (type === "bool") return value ? "true" : "false";
25235    if (type === "color") return `${this.getType("vec3")}( ${toFloat(value.r)}, ${toFloat(value.g)}, ${toFloat(value.b)} )`;
25236    const typeLength = this.getTypeLength(type);
25237    const componentType = this.getComponentType(type);
25238    const generateConst = (value2) => this.generateConst(componentType, value2);
25239    if (typeLength === 2) {
25240      return `${this.getType(type)}( ${generateConst(value.x)}, ${generateConst(value.y)} )`;
25241    } else if (typeLength === 3) {
25242      return `${this.getType(type)}( ${generateConst(value.x)}, ${generateConst(value.y)}, ${generateConst(value.z)} )`;
25243    } else if (typeLength === 4 && type !== "mat2") {
25244      return `${this.getType(type)}( ${generateConst(value.x)}, ${generateConst(value.y)}, ${generateConst(value.z)}, ${generateConst(value.w)} )`;
25245    } else if (typeLength >= 4 && value && (value.isMatrix2 || value.isMatrix3 || value.isMatrix4)) {
25246      return `${this.getType(type)}( ${value.elements.map(generateConst).join(", ")} )`;
25247    } else if (typeLength > 4) {
25248      return `${this.getType(type)}()`;
25249    }
25250    throw new Error(`NodeBuilder: Type '${type}' not found in generate constant attempt.`);
25251  }
25252  /**
25253   * It might be necessary to convert certain data types to different ones
25254   * so this method can be used to hide the conversion.
25255   *
25256   * @param {string} type - The type.
25257   * @return {string} The updated type.
25258   */
25259  getType(type) {
25260    if (type === "color") return "vec3";
25261    return type;
25262  }
25263  /**
25264   * Whether the given attribute name is defined in the geometry or not.
25265   *
25266   * @param {string} name - The attribute name.
25267   * @return {boolean} Whether the given attribute name is defined in the geometry.
25268   */
25269  hasGeometryAttribute(name) {
25270    return this.geometry && this.geometry.getAttribute(name) !== void 0;
25271  }
25272  /**
25273   * Returns a node attribute for the given name and type.
25274   *
25275   * @param {string} name - The attribute's name.
25276   * @param {string} type - The attribute's type.
25277   * @return {NodeAttribute} The node attribute.
25278   */
25279  getAttribute(name, type) {
25280    const attributes = this.attributes;
25281    for (const attribute4 of attributes) {
25282      if (attribute4.name === name) {
25283        return attribute4;
25284      }
25285    }
25286    const attribute3 = new NodeAttribute(name, type);
25287    this.registerDeclaration(attribute3);
25288    attributes.push(attribute3);
25289    return attribute3;
25290  }
25291  /**
25292   * Returns for the given node and shader stage the property name for the shader.
25293   *
25294   * @param {Node} node - The node.
25295   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
25296   * @return {string} The property name.
25297   */
25298  getPropertyName(node) {
25299    return node.name;
25300  }
25301  /**
25302   * Whether the given type is a vector type or not.
25303   *
25304   * @param {string} type - The type to check.
25305   * @return {boolean} Whether the given type is a vector type or not.
25306   */
25307  isVector(type) {
25308    return /vec\d/.test(type);
25309  }
25310  /**
25311   * Whether the given type is a matrix type or not.
25312   *
25313   * @param {string} type - The type to check.
25314   * @return {boolean} Whether the given type is a matrix type or not.
25315   */
25316  isMatrix(type) {
25317    return /mat\d/.test(type);
25318  }
25319  /**
25320   * Whether the given type is a reference type or not.
25321   *
25322   * @param {string} type - The type to check.
25323   * @return {boolean} Whether the given type is a reference type or not.
25324   */
25325  isReference(type) {
25326    return type === "void" || type === "property" || type === "sampler" || type === "samplerComparison" || type === "texture" || type === "cubeTexture" || type === "storageTexture" || type === "depthTexture" || type === "texture3D";
25327  }
25328  /**
25329   * Checks if the given texture requires a manual conversion to the working color space.
25330   *
25331   * @abstract
25332   * @param {Texture} texture - The texture to check.
25333   * @return {boolean} Whether the given texture requires a conversion to working color space or not.
25334   */
25335  needsToWorkingColorSpace() {
25336    return false;
25337  }
25338  /**
25339   * Returns the component type of a given texture.
25340   *
25341   * @param {Texture} texture - The texture.
25342   * @return {string} The component type.
25343   */
25344  getComponentTypeFromTexture(texture3) {
25345    const type = texture3.type;
25346    if (texture3.isDataTexture) {
25347      if (type === IntType) return "int";
25348      if (type === UnsignedIntType) return "uint";
25349    }
25350    return "float";
25351  }
25352  /**
25353   * Returns the element type for a given type.
25354   *
25355   * @param {string} type - The type.
25356   * @return {string} The element type.
25357   */
25358  getElementType(type) {
25359    if (type === "mat2") return "vec2";
25360    if (type === "mat3") return "vec3";
25361    if (type === "mat4") return "vec4";
25362    return this.getComponentType(type);
25363  }
25364  /**
25365   * Returns the component type for a given type.
25366   *
25367   * @param {string} type - The type.
25368   * @return {string} The component type.
25369   */
25370  getComponentType(type) {
25371    type = this.getVectorType(type);
25372    if (type === "float" || type === "bool" || type === "int" || type === "uint") return type;
25373    const componentType = /(b|i|u|)(vec|mat)([2-4])/.exec(type);
25374    if (componentType === null) return null;
25375    if (componentType[1] === "b") return "bool";
25376    if (componentType[1] === "i") return "int";
25377    if (componentType[1] === "u") return "uint";
25378    return "float";
25379  }
25380  /**
25381   * Returns the vector type for a given type.
25382   *
25383   * @param {string} type - The type.
25384   * @return {string} The vector type.
25385   */
25386  getVectorType(type) {
25387    if (type === "color") return "vec3";
25388    if (type === "texture" || type === "cubeTexture" || type === "storageTexture" || type === "texture3D") return "vec4";
25389    return type;
25390  }
25391  /**
25392   * Returns the data type for the given the length and component type.
25393   *
25394   * @param {number} length - The length.
25395   * @param {string} [componentType='float'] - The component type.
25396   * @return {string} The type.
25397   */
25398  getTypeFromLength(length3, componentType = "float") {
25399    if (length3 === 1) return componentType;
25400    let baseType = getTypeFromLength(length3);
25401    const prefix = componentType === "float" ? "" : componentType[0];
25402    if (/mat2/.test(componentType) === true) {
25403      baseType = baseType.replace("vec", "mat");
25404    }
25405    return prefix + baseType;
25406  }
25407  /**
25408   * Returns the type for a given typed array.
25409   *
25410   * @param {TypedArray} array - The typed array.
25411   * @return {string} The type.
25412   */
25413  getTypeFromArray(array3) {
25414    return typeFromArray.get(array3.constructor);
25415  }
25416  /**
25417   * Returns the type is an integer type.
25418   *
25419   * @param {string} type - The type.
25420   * @return {boolean} Whether the type is an integer type or not.
25421   */
25422  isInteger(type) {
25423    return /int|uint|(i|u)vec/.test(type);
25424  }
25425  /**
25426   * Returns the type for a given buffer attribute.
25427   *
25428   * @param {BufferAttribute} attribute - The buffer attribute.
25429   * @return {string} The type.
25430   */
25431  getTypeFromAttribute(attribute3) {
25432    let dataAttribute = attribute3;
25433    if (attribute3.isInterleavedBufferAttribute) dataAttribute = attribute3.data;
25434    const array3 = dataAttribute.array;
25435    const itemSize = attribute3.itemSize;
25436    const normalized = attribute3.normalized;
25437    let arrayType;
25438    if (!(attribute3 instanceof Float16BufferAttribute) && normalized !== true) {
25439      arrayType = this.getTypeFromArray(array3);
25440    }
25441    return this.getTypeFromLength(itemSize, arrayType);
25442  }
25443  /**
25444   * Returns the length for the given data type.
25445   *
25446   * @param {string} type - The data type.
25447   * @return {number} The length.
25448   */
25449  getTypeLength(type) {
25450    const vecType = this.getVectorType(type);
25451    const vecNum = /vec([2-4])/.exec(vecType);
25452    if (vecNum !== null) return Number(vecNum[1]);
25453    if (vecType === "float" || vecType === "bool" || vecType === "int" || vecType === "uint") return 1;
25454    if (/mat2/.test(type) === true) return 4;
25455    if (/mat3/.test(type) === true) return 9;
25456    if (/mat4/.test(type) === true) return 16;
25457    return 0;
25458  }
25459  /**
25460   * Returns the vector type for a given matrix type.
25461   *
25462   * @param {string} type - The matrix type.
25463   * @return {string} The vector type.
25464   */
25465  getVectorFromMatrix(type) {
25466    return type.replace("mat", "vec");
25467  }
25468  /**
25469   * For a given type this method changes the component type to the
25470   * given value. E.g. `vec4` should be changed to the new component type
25471   * `uint` which results in `uvec4`.
25472   *
25473   * @param {string} type - The type.
25474   * @param {string} newComponentType - The new component type.
25475   * @return {string} The new type.
25476   */
25477  changeComponentType(type, newComponentType) {
25478    return this.getTypeFromLength(this.getTypeLength(type), newComponentType);
25479  }
25480  /**
25481   * Returns the integer type pendant for the given type.
25482   *
25483   * @param {string} type - The type.
25484   * @return {string} The integer type.
25485   */
25486  getIntegerType(type) {
25487    const componentType = this.getComponentType(type);
25488    if (componentType === "int" || componentType === "uint") return type;
25489    return this.changeComponentType(type, "int");
25490  }
25491  /**
25492   * Adds an active stack to the internal stack.
25493   *
25494   * @param {StackNode} stack - The stack node to add.
25495   */
25496  setActiveStack(stack3) {
25497    this.activeStacks.push(stack3);
25498  }
25499  /**
25500   * Removes the active stack from the internal stack.
25501   *
25502   * @param {StackNode} stack - The stack node to remove.
25503   */
25504  removeActiveStack(stack3) {
25505    if (this.activeStacks[this.activeStacks.length - 1] === stack3) {
25506      this.activeStacks.pop();
25507    } else {
25508      throw new Error("NodeBuilder: Invalid active stack removal.");
25509    }
25510  }
25511  /**
25512   * Returns the active stack.
25513   *
25514   * @return {StackNode} The active stack.
25515   */
25516  getActiveStack() {
25517    return this.activeStacks[this.activeStacks.length - 1];
25518  }
25519  /**
25520   * Returns the base stack.
25521   *
25522   * @return {StackNode} The base stack.
25523   */
25524  getBaseStack() {
25525    return this.activeStacks[0];
25526  }
25527  /**
25528   * Adds a stack node to the internal stack.
25529   *
25530   * @return {StackNode} The added stack node.
25531   */
25532  addStack() {
25533    this.stack = stack(this.stack);
25534    const previousStack = getCurrentStack();
25535    this.stacks.push(previousStack);
25536    setCurrentStack(this.stack);
25537    return this.stack;
25538  }
25539  /**
25540   * Removes the last stack node from the internal stack.
25541   *
25542   * @return {StackNode} The removed stack node.
25543   */
25544  removeStack() {
25545    const lastStack = this.stack;
25546    for (const node of lastStack.nodes) {
25547      const nodeData = this.getDataFromNode(node);
25548      nodeData.stack = lastStack;
25549    }
25550    this.stack = lastStack.parent;
25551    setCurrentStack(this.stacks.pop());
25552    return lastStack;
25553  }
25554  /**
25555   * The builder maintains (cached) data for each node during the building process. This method
25556   * can be used to get these data for a specific shader stage and cache.
25557   *
25558   * @param {Node} node - The node to get the data for.
25559   * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
25560   * @param {?NodeCache} cache - An optional cache.
25561   * @return {Object} The node data.
25562   */
25563  getDataFromNode(node, shaderStage = this.shaderStage, cache4 = null) {
25564    cache4 = cache4 === null ? node.isGlobal(this) ? this.globalCache : this.cache : cache4;
25565    let nodeData = cache4.getData(node);
25566    if (nodeData === void 0) {
25567      nodeData = {};
25568      cache4.setData(node, nodeData);
25569    }
25570    if (nodeData[shaderStage] === void 0) nodeData[shaderStage] = {};
25571    let data = nodeData[shaderStage];
25572    const subBuilds = nodeData.any ? nodeData.any.subBuilds : null;
25573    const subBuild3 = this.getClosestSubBuild(subBuilds);
25574    if (subBuild3) {
25575      if (data.subBuildsCache === void 0) data.subBuildsCache = {};
25576      data = data.subBuildsCache[subBuild3] || (data.subBuildsCache[subBuild3] = {});
25577      data.subBuilds = subBuilds;
25578    }
25579    return data;
25580  }
25581  /**
25582   * Returns the properties for the given node and shader stage.
25583   *
25584   * Properties are typically used within a build stage to reference a node's
25585   * child node or nodes manually assigned to the properties in a separate build stage.
25586   * A typical usage pattern for defining nodes manually would be assigning dependency nodes
25587   * to the current node's properties in the setup stage and building those properties in the generate stage.
25588   *
25589   * @param {Node} node - The node to get the properties for.
25590   * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage='any'] - The shader stage.
25591   * @return {Object} The node properties.
25592   */
25593  getNodeProperties(node, shaderStage = "any") {
25594    const nodeData = this.getDataFromNode(node, shaderStage);
25595    return nodeData.properties || (nodeData.properties = { outputNode: null });
25596  }
25597  /**
25598   * Returns an instance of {@link NodeAttribute} for the given buffer attribute node.
25599   *
25600   * @param {BufferAttributeNode} node - The buffer attribute node.
25601   * @param {string} type - The node type.
25602   * @return {NodeAttribute} The node attribute.
25603   */
25604  getBufferAttributeFromNode(node, type) {
25605    const nodeData = this.getDataFromNode(node, "vertex");
25606    let bufferAttribute3 = nodeData.bufferAttribute;
25607    if (bufferAttribute3 === void 0) {
25608      const index = this.uniforms.index++;
25609      bufferAttribute3 = new NodeAttribute("nodeAttribute" + index, type, node);
25610      this.bufferAttributes.push(bufferAttribute3);
25611      nodeData.bufferAttribute = bufferAttribute3;
25612    }
25613    return bufferAttribute3;
25614  }
25615  /**
25616   * Returns an instance of {@link StructType} for the given struct name and shader stage
25617   * or null if not found.
25618   *
25619   * @param {string} name - The name of the struct.
25620   * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
25621   * @return {?StructType} The struct type or null if not found.
25622   */
25623  getStructTypeNode(name, shaderStage = this.shaderStage) {
25624    return this.types[shaderStage][name] || null;
25625  }
25626  /**
25627   * Returns an instance of {@link StructType} for the given output struct node.
25628   *
25629   * @param {OutputStructNode} node - The output struct node.
25630   * @param {Array<Object>} membersLayout - The output struct types.
25631   * @param {?string} [name=null] - The name of the struct.
25632   * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
25633   * @return {StructType} The struct type attribute.
25634   */
25635  getStructTypeFromNode(node, membersLayout, name = null, shaderStage = this.shaderStage) {
25636    const nodeData = this.getDataFromNode(node, shaderStage, this.globalCache);
25637    let structType = nodeData.structType;
25638    if (structType === void 0) {
25639      const index = this.structs.index++;
25640      if (name === null) name = "StructType" + index;
25641      structType = new StructType(name, membersLayout);
25642      this.structs[shaderStage].push(structType);
25643      this.types[shaderStage][name] = node;
25644      nodeData.structType = structType;
25645    }
25646    return structType;
25647  }
25648  /**
25649   * Returns an instance of {@link StructType} for the given output struct node.
25650   *
25651   * @param {OutputStructNode} node - The output struct node.
25652   * @param {Array<Object>} membersLayout - The output struct types.
25653   * @return {StructType} The struct type attribute.
25654   */
25655  getOutputStructTypeFromNode(node, membersLayout) {
25656    const structType = this.getStructTypeFromNode(node, membersLayout, "OutputType", "fragment");
25657    structType.output = true;
25658    return structType;
25659  }
25660  /**
25661   * Returns an instance of {@link NodeUniform} for the given uniform node.
25662   *
25663   * @param {UniformNode} node - The uniform node.
25664   * @param {string} type - The uniform type.
25665   * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
25666   * @param {?string} name - The name of the uniform.
25667   * @return {NodeUniform} The node uniform.
25668   */
25669  getUniformFromNode(node, type, shaderStage = this.shaderStage, name = null) {
25670    const nodeData = this.getDataFromNode(node, shaderStage, this.globalCache);
25671    let nodeUniform = nodeData.uniform;
25672    if (nodeUniform === void 0) {
25673      const index = this.uniforms.index++;
25674      nodeUniform = new NodeUniform(name || "nodeUniform" + index, type, node);
25675      this.uniforms[shaderStage].push(nodeUniform);
25676      this.registerDeclaration(nodeUniform);
25677      nodeData.uniform = nodeUniform;
25678    }
25679    return nodeUniform;
25680  }
25681  /**
25682   * Returns an instance of {@link NodeVar} for the given variable node.
25683   *
25684   * @param {VarNode} node - The variable node.
25685   * @param {?string} name - The variable's name.
25686   * @param {string} [type=node.getNodeType( this )] - The variable's type.
25687   * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
25688   * @param {boolean} [readOnly=false] - Whether the variable is read-only or not.
25689   *
25690   * @return {NodeVar} The node variable.
25691   */
25692  getVarFromNode(node, name = null, type = node.getNodeType(this), shaderStage = this.shaderStage, readOnly = false) {
25693    const nodeData = this.getDataFromNode(node, shaderStage);
25694    const subBuildVariable = this.getSubBuildProperty("variable", nodeData.subBuilds);
25695    let nodeVar = nodeData[subBuildVariable];
25696    if (nodeVar === void 0) {
25697      const idNS = readOnly ? "_const" : "_var";
25698      const vars = this.vars[shaderStage] || (this.vars[shaderStage] = []);
25699      const id = this.vars[idNS] || (this.vars[idNS] = 0);
25700      if (name === null) {
25701        name = (readOnly ? "nodeConst" : "nodeVar") + id;
25702        this.vars[idNS]++;
25703      }
25704      if (subBuildVariable !== "variable") {
25705        name = this.getSubBuildProperty(name, nodeData.subBuilds);
25706      }
25707      const count = node.getArrayCount(this);
25708      nodeVar = new NodeVar(name, type, readOnly, count);
25709      if (!readOnly) {
25710        vars.push(nodeVar);
25711      }
25712      this.registerDeclaration(nodeVar);
25713      nodeData[subBuildVariable] = nodeVar;
25714    }
25715    return nodeVar;
25716  }
25717  /**
25718   * Returns whether a Node or its flow is deterministic, useful for use in `const`.
25719   *
25720   * @param {Node} node - The varying node.
25721   * @return {boolean} Returns true if deterministic.
25722   */
25723  isDeterministic(node) {
25724    if (node.isMathNode) {
25725      return this.isDeterministic(node.aNode) && (node.bNode ? this.isDeterministic(node.bNode) : true) && (node.cNode ? this.isDeterministic(node.cNode) : true);
25726    } else if (node.isOperatorNode) {
25727      return this.isDeterministic(node.aNode) && (node.bNode ? this.isDeterministic(node.bNode) : true);
25728    } else if (node.isArrayNode) {
25729      if (node.values !== null) {
25730        for (const n of node.values) {
25731          if (!this.isDeterministic(n)) {
25732            return false;
25733          }
25734        }
25735      }
25736      return true;
25737    } else if (node.isConstNode) {
25738      return true;
25739    }
25740    return false;
25741  }
25742  /**
25743   * Returns an instance of {@link NodeVarying} for the given varying node.
25744   *
25745   * @param {(VaryingNode|PropertyNode)} node - The varying node.
25746   * @param {?string} name - The varying's name.
25747   * @param {string} [type=node.getNodeType( this )] - The varying's type.
25748   * @param {?string} interpolationType - The interpolation type of the varying.
25749   * @param {?string} interpolationSampling - The interpolation sampling type of the varying.
25750   * @return {NodeVar} The node varying.
25751   */
25752  getVaryingFromNode(node, name = null, type = node.getNodeType(this), interpolationType = null, interpolationSampling = null) {
25753    const nodeData = this.getDataFromNode(node, "any");
25754    const subBuildVarying = this.getSubBuildProperty("varying", nodeData.subBuilds);
25755    let nodeVarying = nodeData[subBuildVarying];
25756    if (nodeVarying === void 0) {
25757      const varyings = this.varyings;
25758      const index = varyings.length;
25759      if (name === null) name = "nodeVarying" + index;
25760      if (subBuildVarying !== "varying") {
25761        name = this.getSubBuildProperty(name, nodeData.subBuilds);
25762      }
25763      nodeVarying = new NodeVarying(name, type, interpolationType, interpolationSampling);
25764      varyings.push(nodeVarying);
25765      this.registerDeclaration(nodeVarying);
25766      nodeData[subBuildVarying] = nodeVarying;
25767    }
25768    return nodeVarying;
25769  }
25770  /**
25771   * Registers a node declaration in the current shader stage.
25772   *
25773   * @param {Object} node - The node to be registered.
25774   */
25775  registerDeclaration(node) {
25776    const shaderStage = this.shaderStage;
25777    const declarations = this.declarations[shaderStage] || (this.declarations[shaderStage] = {});
25778    const property3 = this.getPropertyName(node);
25779    let index = 1;
25780    let name = property3;
25781    while (declarations[name] !== void 0) {
25782      name = property3 + "_" + index++;
25783    }
25784    if (index > 1) {
25785      node.name = name;
25786      warn(`TSL: Declaration name '${property3}' of '${node.type}' already in use. Renamed to '${name}'.`);
25787    }
25788    declarations[name] = node;
25789  }
25790  /**
25791   * Returns an instance of {@link NodeCode} for the given code node.
25792   *
25793   * @param {CodeNode} node - The code node.
25794   * @param {string} type - The node type.
25795   * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
25796   * @return {NodeCode} The node code.
25797   */
25798  getCodeFromNode(node, type, shaderStage = this.shaderStage) {
25799    const nodeData = this.getDataFromNode(node);
25800    let nodeCode = nodeData.code;
25801    if (nodeCode === void 0) {
25802      const codes = this.codes[shaderStage] || (this.codes[shaderStage] = []);
25803      const index = codes.length;
25804      nodeCode = new NodeCode("nodeCode" + index, type);
25805      codes.push(nodeCode);
25806      nodeData.code = nodeCode;
25807    }
25808    return nodeCode;
25809  }
25810  /**
25811  	 * Adds a code flow based on the code-block hierarchy.
25812  
25813  	 * This is used so that code-blocks like If,Else create their variables locally if the Node
25814  	 * is only used inside one of these conditionals in the current shader stage.
25815  	 *
25816  	 * @param {Node} node - The node to add.
25817  	 * @param {Node} nodeBlock - Node-based code-block. Usually 'ConditionalNode'.
25818  	 */
25819  addFlowCodeHierarchy(node, nodeBlock) {
25820    const { flowCodes, flowCodeBlock } = this.getDataFromNode(node);
25821    let needsFlowCode = true;
25822    let nodeBlockHierarchy = nodeBlock;
25823    while (nodeBlockHierarchy) {
25824      if (flowCodeBlock.get(nodeBlockHierarchy) === true) {
25825        needsFlowCode = false;
25826        break;
25827      }
25828      nodeBlockHierarchy = this.getDataFromNode(nodeBlockHierarchy).parentNodeBlock;
25829    }
25830    if (needsFlowCode) {
25831      for (const flowCode of flowCodes) {
25832        this.addLineFlowCode(flowCode);
25833      }
25834    }
25835  }
25836  /**
25837   * Add a inline-code to the current flow code-block.
25838   *
25839   * @param {Node} node - The node to add.
25840   * @param {string} code - The code to add.
25841   * @param {Node} nodeBlock - Current ConditionalNode
25842   */
25843  addLineFlowCodeBlock(node, code3, nodeBlock) {
25844    const nodeData = this.getDataFromNode(node);
25845    const flowCodes = nodeData.flowCodes || (nodeData.flowCodes = []);
25846    const codeBlock = nodeData.flowCodeBlock || (nodeData.flowCodeBlock = /* @__PURE__ */ new WeakMap());
25847    flowCodes.push(code3);
25848    codeBlock.set(nodeBlock, true);
25849  }
25850  /**
25851   * Add a inline-code to the current flow.
25852   *
25853   * @param {string} code - The code to add.
25854   * @param {?Node} [node= null] - Optional Node, can help the system understand if the Node is part of a code-block.
25855   * @return {NodeBuilder} A reference to this node builder.
25856   */
25857  addLineFlowCode(code3, node = null) {
25858    if (code3 === "") return this;
25859    if (node !== null && this.context.nodeBlock) {
25860      this.addLineFlowCodeBlock(node, code3, this.context.nodeBlock);
25861    }
25862    code3 = this.tab + code3;
25863    if (!/;\s*$/.test(code3)) {
25864      code3 = code3 + ";\n";
25865    }
25866    this.flow.code += code3;
25867    return this;
25868  }
25869  /**
25870   * Adds a code to the current code flow.
25871   *
25872   * @param {string} code - Shader code.
25873   * @return {NodeBuilder} A reference to this node builder.
25874   */
25875  addFlowCode(code3) {
25876    this.flow.code += code3;
25877    return this;
25878  }
25879  /**
25880   * Add tab in the code that will be generated so that other snippets respect the current tabulation.
25881   * Typically used in codes with If,Else.
25882   *
25883   * @return {NodeBuilder} A reference to this node builder.
25884   */
25885  addFlowTab() {
25886    this.tab += "	";
25887    return this;
25888  }
25889  /**
25890   * Removes a tab.
25891   *
25892   * @return {NodeBuilder} A reference to this node builder.
25893   */
25894  removeFlowTab() {
25895    this.tab = this.tab.slice(0, -1);
25896    return this;
25897  }
25898  /**
25899   * Gets the current flow data based on a Node.
25900   *
25901   * @param {Node} node - Node that the flow was started.
25902   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
25903   * @return {Object} The flow data.
25904   */
25905  getFlowData(node) {
25906    return this.flowsData.get(node);
25907  }
25908  /**
25909   * Executes the node flow based on a root node to generate the final shader code.
25910   *
25911   * @param {Node} node - The node to execute.
25912   * @return {Object} The code flow.
25913   */
25914  flowNode(node) {
25915    const output3 = node.getNodeType(this);
25916    const flowData = this.flowChildNode(node, output3);
25917    this.flowsData.set(node, flowData);
25918    return flowData;
25919  }
25920  /**
25921   * Includes a node in the current function node.
25922   *
25923   * @param {Node} node - The node to include.
25924   * @returns {void}
25925   */
25926  addInclude(node) {
25927    if (this.currentFunctionNode !== null) {
25928      this.currentFunctionNode.includes.push(node);
25929    }
25930  }
25931  /**
25932   * Returns the native shader operator name for a given generic name.
25933   * It is a similar type of method like {@link NodeBuilder#getMethod}.
25934   *
25935   * @param {ShaderNodeInternal} shaderNode - The shader node to build the function node with.
25936   * @return {FunctionNode} The build function node.
25937   */
25938  buildFunctionNode(shaderNode) {
25939    const fn = new FunctionNode();
25940    const previous = this.currentFunctionNode;
25941    this.currentFunctionNode = fn;
25942    fn.code = this.buildFunctionCode(shaderNode);
25943    this.currentFunctionNode = previous;
25944    return fn;
25945  }
25946  /**
25947   * Generates a code flow based on a TSL function: Fn().
25948   *
25949   * @param {ShaderNodeInternal} shaderNode - A function code will be generated based on the input.
25950   * @return {Object}
25951   */
25952  flowShaderNode(shaderNode) {
25953    const layout = shaderNode.layout;
25954    const inputs = {
25955      [Symbol.iterator]() {
25956        let index = 0;
25957        const values = Object.values(this);
25958        return {
25959          next: () => ({
25960            value: values[index],
25961            done: index++ >= values.length
25962          })
25963        };
25964      }
25965    };
25966    for (const input of layout.inputs) {
25967      inputs[input.name] = new ParameterNode(input.type, input.name);
25968    }
25969    shaderNode.layout = null;
25970    const callNode = shaderNode.call(inputs);
25971    const flowData = this.flowStagesNode(callNode, layout.type);
25972    shaderNode.layout = layout;
25973    return flowData;
25974  }
25975  /**
25976   * Executes the node in a specific build stage.
25977   *
25978   * This function can be used to arbitrarily execute the specified build stage
25979   * outside of the standard build process. For instance, if a node's type depends
25980   * on properties created by the 'setup' stage, then flowBuildStage(node, 'setup')
25981   * can be used to execute the setup build stage and access its generated nodes
25982   * before the standard build process begins.
25983   *
25984   * @param {Node} node - The node to execute.
25985   * @param {string} buildStage - The build stage to execute the node in.
25986   * @param {?(Node|string)} [output=null] - Expected output type. For example 'vec3'.
25987   * @return {?(Node|string)} The result of the node build.
25988   */
25989  flowBuildStage(node, buildStage, output3 = null) {
25990    const previousBuildStage = this.getBuildStage();
25991    this.setBuildStage(buildStage);
25992    const result = node.build(this, output3);
25993    this.setBuildStage(previousBuildStage);
25994    return result;
25995  }
25996  /**
25997   * Runs the node flow through all the steps of creation, 'setup', 'analyze', 'generate'.
25998   *
25999   * @param {Node} node - The node to execute.
26000   * @param {?string} output - Expected output type. For example 'vec3'.
26001   * @return {Object}
26002   */
26003  flowStagesNode(node, output3 = null) {
26004    const previousFlow = this.flow;
26005    const previousVars = this.vars;
26006    const previousDeclarations = this.declarations;
26007    const previousCache = this.cache;
26008    const previousBuildStage = this.buildStage;
26009    const previousStack = this.stack;
26010    const flow = {
26011      code: ""
26012    };
26013    this.flow = flow;
26014    this.vars = {};
26015    this.declarations = {};
26016    this.cache = new NodeCache();
26017    this.stack = stack();
26018    for (const buildStage of defaultBuildStages) {
26019      this.setBuildStage(buildStage);
26020      flow.result = node.build(this, output3);
26021    }
26022    flow.vars = this.getVars(this.shaderStage);
26023    this.flow = previousFlow;
26024    this.vars = previousVars;
26025    this.declarations = previousDeclarations;
26026    this.cache = previousCache;
26027    this.stack = previousStack;
26028    this.setBuildStage(previousBuildStage);
26029    return flow;
26030  }
26031  /**
26032   * Returns the native shader operator name for a given generic name.
26033   * It is a similar type of method like {@link NodeBuilder#getMethod}.
26034   *
26035   * @abstract
26036   * @param {string} op - The operator name to resolve.
26037   * @return {?string} The resolved operator name.
26038   */
26039  getFunctionOperator() {
26040    return null;
26041  }
26042  /**
26043   * Builds the given shader node.
26044   *
26045   * @abstract
26046   * @param {ShaderNodeInternal} shaderNode - The shader node.
26047   * @return {string} The function code.
26048   */
26049  buildFunctionCode() {
26050    warn("Abstract function.");
26051  }
26052  /**
26053   * Generates a code flow based on a child Node.
26054   *
26055   * @param {Node} node - The node to execute.
26056   * @param {?string} output - Expected output type. For example 'vec3'.
26057   * @return {Object} The code flow.
26058   */
26059  flowChildNode(node, output3 = null) {
26060    const previousFlow = this.flow;
26061    const flow = {
26062      code: ""
26063    };
26064    this.flow = flow;
26065    flow.result = node.build(this, output3);
26066    this.flow = previousFlow;
26067    return flow;
26068  }
26069  /**
26070   * Executes a flow of code in a different stage.
26071   *
26072   * Some nodes like `varying()` have the ability to compute code in vertex-stage and
26073   * return the value in fragment-stage even if it is being executed in an input fragment.
26074   *
26075   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
26076   * @param {Node} node - The node to execute.
26077   * @param {?string} output - Expected output type. For example 'vec3'.
26078   * @param {?string} propertyName - The property name to assign the result.
26079   * @return {?(Object|Node)} The code flow or node.build() result.
26080   */
26081  flowNodeFromShaderStage(shaderStage, node, output3 = null, propertyName = null) {
26082    const previousTab = this.tab;
26083    const previousCache = this.cache;
26084    const previousShaderStage = this.shaderStage;
26085    const previousContext = this.context;
26086    this.setShaderStage(shaderStage);
26087    const context3 = { ...this.context };
26088    delete context3.nodeBlock;
26089    this.cache = this.globalCache;
26090    this.tab = "	";
26091    this.context = context3;
26092    let result = null;
26093    if (this.buildStage === "generate") {
26094      const flowData = this.flowChildNode(node, output3);
26095      if (propertyName !== null) {
26096        flowData.code += `${this.tab + propertyName} = ${flowData.result};
26097`;
26098      }
26099      this.flowCode[shaderStage] = this.flowCode[shaderStage] + flowData.code;
26100      result = flowData;
26101    } else {
26102      result = node.build(this);
26103    }
26104    this.setShaderStage(previousShaderStage);
26105    this.cache = previousCache;
26106    this.tab = previousTab;
26107    this.context = previousContext;
26108    return result;
26109  }
26110  /**
26111   * Returns an array holding all node attributes of this node builder.
26112   *
26113   * @return {Array<NodeAttribute>} The node attributes of this builder.
26114   */
26115  getAttributesArray() {
26116    return this.attributes.concat(this.bufferAttributes);
26117  }
26118  /**
26119   * Returns the attribute definitions as a shader string for the given shader stage.
26120   *
26121   * @abstract
26122   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
26123   * @return {string} The attribute code section.
26124   */
26125  getAttributes() {
26126    warn("Abstract function.");
26127  }
26128  /**
26129   * Returns the varying definitions as a shader string for the given shader stage.
26130   *
26131   * @abstract
26132   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
26133   * @return {string} The varying code section.
26134   */
26135  getVaryings() {
26136    warn("Abstract function.");
26137  }
26138  /**
26139   * Returns a single variable definition as a shader string for the given variable type and name.
26140   *
26141   * @param {string} type - The variable's type.
26142   * @param {string} name - The variable's name.
26143   * @param {?number} [count=null] - The array length.
26144   * @return {string} The shader string.
26145   */
26146  getVar(type, name, count = null) {
26147    return `${count !== null ? this.generateArrayDeclaration(type, count) : this.getType(type)} ${name}`;
26148  }
26149  /**
26150   * Returns the variable definitions as a shader string for the given shader stage.
26151   *
26152   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
26153   * @param {boolean} [global=false] - Whether the variables are global.
26154   * @return {string} The variable code section.
26155   */
26156  getVars(shaderStage, global = false) {
26157    const snippets = [];
26158    const vars = this.vars[shaderStage];
26159    if (vars !== void 0) {
26160      for (const variable of vars) {
26161        snippets.push(`${this.getVar(variable.type, variable.name, variable.count)};`);
26162      }
26163    }
26164    return snippets.join(global ? "\n" : "\n	");
26165  }
26166  /**
26167   * Returns the uniform definitions as a shader string for the given shader stage.
26168   *
26169   * @abstract
26170   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
26171   * @return {string} The uniform code section.
26172   */
26173  getUniforms() {
26174    warn("Abstract function.");
26175  }
26176  /**
26177   * Returns the native code definitions as a shader string for the given shader stage.
26178   *
26179   * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
26180   * @return {string} The native code section.
26181   */
26182  getCodes(shaderStage) {
26183    const codes = this.codes[shaderStage];
26184    let code3 = "";
26185    if (codes !== void 0) {
26186      for (const nodeCode of codes) {
26187        code3 += nodeCode.code + "\n";
26188      }
26189    }
26190    return code3;
26191  }
26192  /**
26193   * Returns the hash of this node builder.
26194   *
26195   * @return {string} The hash.
26196   */
26197  getHash() {
26198    return this.vertexShader + this.fragmentShader + this.computeShader;
26199  }
26200  /**
26201   * Sets the current shader stage.
26202   *
26203   * @param {?('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage to set.
26204   */
26205  setShaderStage(shaderStage) {
26206    this.shaderStage = shaderStage;
26207  }
26208  /**
26209   * Returns the current shader stage.
26210   *
26211   * @return {?('vertex'|'fragment'|'compute'|'any')} The current shader stage.
26212   */
26213  getShaderStage() {
26214    return this.shaderStage;
26215  }
26216  /**
26217   * Sets the current build stage.
26218   *
26219   * @param {?('setup'|'analyze'|'generate')} buildStage - The build stage to set.
26220   */
26221  setBuildStage(buildStage) {
26222    this.buildStage = buildStage;
26223  }
26224  /**
26225   * Returns the current build stage.
26226   *
26227   * @return {?('setup'|'analyze'|'generate')} The current build stage.
26228   */
26229  getBuildStage() {
26230    return this.buildStage;
26231  }
26232  /**
26233   * Controls the code build of the shader stages.
26234   *
26235   * @abstract
26236   */
26237  buildCode() {
26238    warn("Abstract function.");
26239  }
26240  /**
26241   * Returns the current sub-build layer.
26242   *
26243   * @return {SubBuildNode} The current sub-build layers.
26244   */
26245  get subBuild() {
26246    return this.subBuildLayers[this.subBuildLayers.length - 1] || null;
26247  }
26248  /**
26249   * Adds a sub-build layer to the node builder.
26250   *
26251   * @param {SubBuildNode} subBuild - The sub-build layer to add.
26252   */
26253  addSubBuild(subBuild3) {
26254    this.subBuildLayers.push(subBuild3);
26255  }
26256  /**
26257   * Removes the last sub-build layer from the node builder.
26258   *
26259   * @return {SubBuildNode} The removed sub-build layer.
26260   */
26261  removeSubBuild() {
26262    return this.subBuildLayers.pop();
26263  }
26264  /**
26265   * Returns the closest sub-build layer for the given data.
26266   *
26267   * @param {Node|Set<string>|Array<string>} data - The data to get the closest sub-build layer from.
26268   * @return {?string} The closest sub-build name or null if none found.
26269   */
26270  getClosestSubBuild(data) {
26271    let subBuilds;
26272    if (data && data.isNode) {
26273      if (data.isShaderCallNodeInternal) {
26274        subBuilds = data.shaderNode.subBuilds;
26275      } else if (data.isStackNode) {
26276        subBuilds = [data.subBuild];
26277      } else {
26278        subBuilds = this.getDataFromNode(data, "any").subBuilds;
26279      }
26280    } else if (data instanceof Set) {
26281      subBuilds = [...data];
26282    } else {
26283      subBuilds = data;
26284    }
26285    if (!subBuilds) return null;
26286    const subBuildLayers = this.subBuildLayers;
26287    for (let i = subBuilds.length - 1; i >= 0; i--) {
26288      const subBuild3 = subBuilds[i];
26289      if (subBuildLayers.includes(subBuild3)) {
26290        return subBuild3;
26291      }
26292    }
26293    return null;
26294  }
26295  /**
26296   * Returns the output node of a sub-build layer.
26297   *
26298   * @param {Node} node - The node to get the output from.
26299   * @return {string} The output node name.
26300   */
26301  getSubBuildOutput(node) {
26302    return this.getSubBuildProperty("outputNode", node);
26303  }
26304  /**
26305   * Returns the sub-build property name for the given property and node.
26306   *
26307   * @param {string} [property=''] - The property name.
26308   * @param {?Node} [node=null] - The node to get the sub-build from.
26309   * @return {string} The sub-build property name.
26310   */
26311  getSubBuildProperty(property3 = "", node = null) {
26312    let subBuild3;
26313    if (node !== null) {
26314      subBuild3 = this.getClosestSubBuild(node);
26315    } else {
26316      subBuild3 = this.subBuildFn;
26317    }
26318    let result;
26319    if (subBuild3) {
26320      result = property3 ? subBuild3 + "_" + property3 : subBuild3;
26321    } else {
26322      result = property3;
26323    }
26324    return result;
26325  }
26326  /**
26327   * Prebuild the node builder.
26328   */
26329  prebuild() {
26330    const { object, renderer, material } = this;
26331    if (renderer.contextNode.isContextNode === true) {
26332      this.context = { ...this.context, ...renderer.contextNode.getFlowContextData() };
26333    } else {
26334      error('NodeBuilder: "renderer.contextNode" must be an instance of `context()`.');
26335    }
26336    if (material && material.contextNode) {
26337      if (material.contextNode.isContextNode === true) {
26338        this.context = { ...this.context, ...material.contextNode.getFlowContextData() };
26339      } else {
26340        error('NodeBuilder: "material.contextNode" must be an instance of `context()`.');
26341      }
26342    }
26343    if (material !== null) {
26344      let nodeMaterial = renderer.library.fromMaterial(material);
26345      if (nodeMaterial === null) {
26346        error(`NodeBuilder: Material "${material.type}" is not compatible.`);
26347        nodeMaterial = new NodeMaterial();
26348      }
26349      nodeMaterial.build(this);
26350    } else {
26351      this.addFlow("compute", object);
26352    }
26353  }
26354  /**
26355   * Central build method which controls the build for the given object.
26356   *
26357   * @return {NodeBuilder} A reference to this node builder.
26358   */
26359  build() {
26360    this.prebuild();
26361    for (const buildStage of defaultBuildStages) {
26362      this.setBuildStage(buildStage);
26363      if (this.context.position && this.context.position.isNode) {
26364        this.flowNodeFromShaderStage("vertex", this.context.position);
26365      }
26366      for (const shaderStage of shaderStages) {
26367        this.setShaderStage(shaderStage);
26368        const flowNodes = this.flowNodes[shaderStage];
26369        for (const node of flowNodes) {
26370          if (buildStage === "generate") {
26371            this.flowNode(node);
26372          } else {
26373            node.build(this);
26374          }
26375        }
26376      }
26377    }
26378    this.setBuildStage(null);
26379    this.setShaderStage(null);
26380    this.buildCode();
26381    this.buildUpdateNodes();
26382    return this;
26383  }
26384  /**
26385   * Async version of build() that yields to main thread between shader stages.
26386   * Use this in compileAsync() to prevent blocking the main thread.
26387   *
26388   * @return {Promise<NodeBuilder>} A promise that resolves to this node builder.
26389   */
26390  async buildAsync() {
26391    this.prebuild();
26392    for (const buildStage of defaultBuildStages) {
26393      this.setBuildStage(buildStage);
26394      if (this.context.position && this.context.position.isNode) {
26395        this.flowNodeFromShaderStage("vertex", this.context.position);
26396      }
26397      for (const shaderStage of shaderStages) {
26398        this.setShaderStage(shaderStage);
26399        const flowNodes = this.flowNodes[shaderStage];
26400        for (const node of flowNodes) {
26401          if (buildStage === "generate") {
26402            this.flowNode(node);
26403          } else {
26404            node.build(this);
26405          }
26406        }
26407        await yieldToMain();
26408      }
26409    }
26410    this.setBuildStage(null);
26411    this.setShaderStage(null);
26412    this.buildCode();
26413    this.buildUpdateNodes();
26414    return this;
26415  }
26416  /**
26417   * Returns shared data object for the given node.
26418   *
26419   * @param {Node} node - The node to get shared data from.
26420   * @return {Object} The shared data.
26421   */
26422  getSharedDataFromNode(node) {
26423    let data = sharedNodeData.get(node);
26424    if (data === void 0) {
26425      data = {};
26426    }
26427    return data;
26428  }
26429  /**
26430   * Returns a uniform representation which is later used for UBO generation and rendering.
26431   *
26432   * @param {NodeUniform} uniformNode - The uniform node.
26433   * @param {string} type - The requested type.
26434   * @return {Uniform} The uniform.
26435   */
26436  getNodeUniform(uniformNode, type) {
26437    const nodeData = this.getSharedDataFromNode(uniformNode);
26438    let node = nodeData.cache;
26439    if (node === void 0) {
26440      if (type === "float" || type === "int" || type === "uint") node = new NumberNodeUniform(uniformNode);
26441      else if (type === "vec2" || type === "ivec2" || type === "uvec2") node = new Vector2NodeUniform(uniformNode);
26442      else if (type === "vec3" || type === "ivec3" || type === "uvec3") node = new Vector3NodeUniform(uniformNode);
26443      else if (type === "vec4" || type === "ivec4" || type === "uvec4") node = new Vector4NodeUniform(uniformNode);
26444      else if (type === "color") node = new ColorNodeUniform(uniformNode);
26445      else if (type === "mat2") node = new Matrix2NodeUniform(uniformNode);
26446      else if (type === "mat3") node = new Matrix3NodeUniform(uniformNode);
26447      else if (type === "mat4") node = new Matrix4NodeUniform(uniformNode);
26448      else {
26449        throw new Error(`Uniform "${type}" not implemented.`);
26450      }
26451      nodeData.cache = node;
26452    }
26453    return node;
26454  }
26455  /**
26456   * Formats the given shader snippet from a given type into another one. E.g.
26457   * this method might be used to convert a simple float string `"1.0"` into a
26458   * `vec3` representation: `"vec3<f32>( 1.0 )"`.
26459   *
26460   * @param {string} snippet - The shader snippet.
26461   * @param {string} fromType - The source type.
26462   * @param {string} toType - The target type.
26463   * @return {string} The updated shader string.
26464   */
26465  format(snippet, fromType, toType) {
26466    fromType = this.getVectorType(fromType);
26467    toType = this.getVectorType(toType);
26468    if (fromType === toType || toType === null || this.isReference(toType)) {
26469      return snippet;
26470    }
26471    const fromTypeLength = this.getTypeLength(fromType);
26472    const toTypeLength = this.getTypeLength(toType);
26473    if (fromTypeLength === 16 && toTypeLength === 9) {
26474      return `${this.getType(toType)}( ${snippet}[ 0 ].xyz, ${snippet}[ 1 ].xyz, ${snippet}[ 2 ].xyz )`;
26475    }
26476    if (fromTypeLength === 9 && toTypeLength === 4) {
26477      return `${this.getType(toType)}( ${snippet}[ 0 ].xy, ${snippet}[ 1 ].xy )`;
26478    }
26479    if (fromTypeLength > 4) {
26480      return snippet;
26481    }
26482    if (toTypeLength > 4 || toTypeLength === 0) {
26483      return snippet;
26484    }
26485    if (fromTypeLength === toTypeLength) {
26486      return `${this.getType(toType)}( ${snippet} )`;
26487    }
26488    if (fromTypeLength > toTypeLength) {
26489      snippet = toType === "bool" ? `all( ${snippet} )` : `${snippet}.${"xyz".slice(0, toTypeLength)}`;
26490      return this.format(snippet, this.getTypeFromLength(toTypeLength, this.getComponentType(fromType)), toType);
26491    }
26492    if (toTypeLength === 4 && fromTypeLength > 1) {
26493      return `${this.getType(toType)}( ${this.format(snippet, fromType, "vec3")}, 1.0 )`;
26494    }
26495    if (fromTypeLength === 2) {
26496      return `${this.getType(toType)}( ${this.format(snippet, fromType, "vec2")}, 0.0 )`;
26497    }
26498    if (fromTypeLength === 1 && toTypeLength > 1 && fromType !== this.getComponentType(toType)) {
26499      snippet = `${this.getType(this.getComponentType(toType))}( ${snippet} )`;
26500    }
26501    return `${this.getType(toType)}( ${snippet} )`;
26502  }
26503  /**
26504   * Returns a signature with the engine's current revision.
26505   *
26506   * @return {string} The signature.
26507   */
26508  getSignature() {
26509    return `// Three.js r${REVISION} - Node System
26510`;
26511  }
26512  /**
26513   * Returns `true` if data from the previous frame are required. Relevant
26514   * when computing motion vectors with {@link VelocityNode}.
26515   *
26516   * @return {boolean} Whether data from the previous frame are required or not.
26517   */
26518  needsPreviousData() {
26519    const mrt3 = this.renderer.getMRT();
26520    return mrt3 && mrt3.has("velocity") || getDataFromObject(this.object).useVelocity === true;
26521  }
26522};
26523var NodeFrame = class {
26524  /**
26525   * Constructs a new node fame.
26526   */
26527  constructor() {
26528    this.time = 0;
26529    this.deltaTime = 0;
26530    this.frameId = 0;
26531    this.renderId = 0;
26532    this.updateMap = /* @__PURE__ */ new WeakMap();
26533    this.updateBeforeMap = /* @__PURE__ */ new WeakMap();
26534    this.updateAfterMap = /* @__PURE__ */ new WeakMap();
26535    this.renderer = null;
26536    this.material = null;
26537    this.camera = null;
26538    this.object = null;
26539    this.scene = null;
26540  }
26541  /**
26542   * Returns a dictionary for a given node and update map which
26543   * is used to correctly call node update methods per frame or render.
26544   *
26545   * @private
26546   * @param {WeakMap<Node, Object>} referenceMap - The reference weak map.
26547   * @param {Node} nodeRef - The reference to the current node.
26548   * @return {Object<string,WeakMap<Object, number>>} The dictionary.
26549   */
26550  _getMaps(referenceMap, nodeRef) {
26551    let maps = referenceMap.get(nodeRef);
26552    if (maps === void 0) {
26553      maps = {
26554        renderId: 0,
26555        frameId: 0
26556      };
26557      referenceMap.set(nodeRef, maps);
26558    }
26559    return maps;
26560  }
26561  /**
26562   * This method executes the {@link Node#updateBefore} for the given node.
26563   * It makes sure {@link Node#updateBeforeType} is honored meaning the update
26564   * is only executed once per frame, render or object depending on the update
26565   * type.
26566   *
26567   * @param {Node} node - The node that should be updated.
26568   */
26569  updateBeforeNode(node) {
26570    const updateType = node.getUpdateBeforeType();
26571    const reference3 = node.updateReference(this);
26572    if (updateType === NodeUpdateType.FRAME) {
26573      const nodeUpdateBeforeMap = this._getMaps(this.updateBeforeMap, reference3);
26574      if (nodeUpdateBeforeMap.frameId !== this.frameId) {
26575        const previousFrameId = nodeUpdateBeforeMap.frameId;
26576        nodeUpdateBeforeMap.frameId = this.frameId;
26577        if (node.updateBefore(this) === false) {
26578          nodeUpdateBeforeMap.frameId = previousFrameId;
26579        }
26580      }
26581    } else if (updateType === NodeUpdateType.RENDER) {
26582      const nodeUpdateBeforeMap = this._getMaps(this.updateBeforeMap, reference3);
26583      if (nodeUpdateBeforeMap.renderId !== this.renderId) {
26584        const previousRenderId = nodeUpdateBeforeMap.renderId;
26585        nodeUpdateBeforeMap.renderId = this.renderId;
26586        if (node.updateBefore(this) === false) {
26587          nodeUpdateBeforeMap.renderId = previousRenderId;
26588        }
26589      }
26590    } else if (updateType === NodeUpdateType.OBJECT) {
26591      node.updateBefore(this);
26592    }
26593  }
26594  /**
26595   * This method executes the {@link Node#updateAfter} for the given node.
26596   * It makes sure {@link Node#updateAfterType} is honored meaning the update
26597   * is only executed once per frame, render or object depending on the update
26598   * type.
26599   *
26600   * @param {Node} node - The node that should be updated.
26601   */
26602  updateAfterNode(node) {
26603    const updateType = node.getUpdateAfterType();
26604    const reference3 = node.updateReference(this);
26605    if (updateType === NodeUpdateType.FRAME) {
26606      const nodeUpdateAfterMap = this._getMaps(this.updateAfterMap, reference3);
26607      if (nodeUpdateAfterMap.frameId !== this.frameId) {
26608        if (node.updateAfter(this) !== false) {
26609          nodeUpdateAfterMap.frameId = this.frameId;
26610        }
26611      }
26612    } else if (updateType === NodeUpdateType.RENDER) {
26613      const nodeUpdateAfterMap = this._getMaps(this.updateAfterMap, reference3);
26614      if (nodeUpdateAfterMap.renderId !== this.renderId) {
26615        if (node.updateAfter(this) !== false) {
26616          nodeUpdateAfterMap.renderId = this.renderId;
26617        }
26618      }
26619    } else if (updateType === NodeUpdateType.OBJECT) {
26620      node.updateAfter(this);
26621    }
26622  }
26623  /**
26624   * This method executes the {@link Node#update} for the given node.
26625   * It makes sure {@link Node#updateType} is honored meaning the update
26626   * is only executed once per frame, render or object depending on the update
26627   * type.
26628   *
26629   * @param {Node} node - The node that should be updated.
26630   */
26631  updateNode(node) {
26632    const updateType = node.getUpdateType();
26633    const reference3 = node.updateReference(this);
26634    if (updateType === NodeUpdateType.FRAME) {
26635      const nodeUpdateMap = this._getMaps(this.updateMap, reference3);
26636      if (nodeUpdateMap.frameId !== this.frameId) {
26637        if (node.update(this) !== false) {
26638          nodeUpdateMap.frameId = this.frameId;
26639        }
26640      }
26641    } else if (updateType === NodeUpdateType.RENDER) {
26642      const nodeUpdateMap = this._getMaps(this.updateMap, reference3);
26643      if (nodeUpdateMap.renderId !== this.renderId) {
26644        if (node.update(this) !== false) {
26645          nodeUpdateMap.renderId = this.renderId;
26646        }
26647      }
26648    } else if (updateType === NodeUpdateType.OBJECT) {
26649      node.update(this);
26650    }
26651  }
26652  /**
26653   * Updates the internal state of the node frame. This method is
26654   * called by the renderer in its internal animation loop.
26655   */
26656  update() {
26657    this.frameId++;
26658    if (this.lastTime === void 0) this.lastTime = performance.now();
26659    this.deltaTime = (performance.now() - this.lastTime) / 1e3;
26660    this.lastTime = performance.now();
26661    this.time += this.deltaTime;
26662  }
26663};
26664var NodeFunctionInput = class {
26665  /**
26666   * Constructs a new node function input.
26667   *
26668   * @param {string} type - The input type.
26669   * @param {string} name - The input name.
26670   * @param {?number} [count=null] - If the input is an Array, count will be the length.
26671   * @param {('in'|'out'|'inout')} [qualifier=''] - The parameter qualifier (only relevant for GLSL).
26672   * @param {boolean} [isConst=false] - Whether the input uses a const qualifier or not (only relevant for GLSL).
26673   */
26674  constructor(type, name, count = null, qualifier = "", isConst = false) {
26675    this.type = type;
26676    this.name = name;
26677    this.count = count;
26678    this.qualifier = qualifier;
26679    this.isConst = isConst;
26680  }
26681};
26682NodeFunctionInput.isNodeFunctionInput = true;
26683var AmbientLightNode = class extends AnalyticLightNode {
26684  static get type() {
26685    return "AmbientLightNode";
26686  }
26687  /**
26688   * Constructs a new ambient light node.
26689   *
26690   * @param {?AmbientLight} [light=null] - The ambient light source.
26691   */
26692  constructor(light = null) {
26693    super(light);
26694  }
26695  setup({ context: context3 }) {
26696    context3.irradiance.addAssign(this.colorNode);
26697  }
26698};
26699var DirectionalLightNode = class extends AnalyticLightNode {
26700  static get type() {
26701    return "DirectionalLightNode";
26702  }
26703  /**
26704   * Constructs a new directional light node.
26705   *
26706   * @param {?DirectionalLight} [light=null] - The directional light source.
26707   */
26708  constructor(light = null) {
26709    super(light);
26710  }
26711  setupDirect() {
26712    const lightColor = this.colorNode;
26713    const lightDirection = lightTargetDirection(this.light);
26714    return { lightDirection, lightColor };
26715  }
26716};
26717var HemisphereLightNode = class extends AnalyticLightNode {
26718  static get type() {
26719    return "HemisphereLightNode";
26720  }
26721  /**
26722   * Constructs a new hemisphere light node.
26723   *
26724   * @param {?HemisphereLight} [light=null] - The hemisphere light source.
26725   */
26726  constructor(light = null) {
26727    super(light);
26728    this.lightPositionNode = lightPosition(light);
26729    this.lightDirectionNode = this.lightPositionNode.normalize();
26730    this.groundColorNode = uniform(new Color()).setGroup(renderGroup);
26731  }
26732  /**
26733   * Overwritten to updated hemisphere light specific uniforms.
26734   *
26735   * @param {NodeFrame} frame - A reference to the current node frame.
26736   */
26737  update(frame) {
26738    const { light } = this;
26739    super.update(frame);
26740    this.lightPositionNode.object3d = light;
26741    this.groundColorNode.value.copy(light.groundColor).multiplyScalar(light.intensity);
26742  }
26743  setup(builder) {
26744    const { colorNode, groundColorNode, lightDirectionNode } = this;
26745    const dotNL = normalWorld.dot(lightDirectionNode);
26746    const hemiDiffuseWeight = dotNL.mul(0.5).add(0.5);
26747    const irradiance = mix(groundColorNode, colorNode, hemiDiffuseWeight);
26748    builder.context.irradiance.addAssign(irradiance);
26749  }
26750};
26751var SpotLightNode = class extends AnalyticLightNode {
26752  static get type() {
26753    return "SpotLightNode";
26754  }
26755  /**
26756   * Constructs a new spot light node.
26757   *
26758   * @param {?SpotLight} [light=null] - The spot light source.
26759   */
26760  constructor(light = null) {
26761    super(light);
26762    this.coneCosNode = uniform(0).setGroup(renderGroup);
26763    this.penumbraCosNode = uniform(0).setGroup(renderGroup);
26764    this.cutoffDistanceNode = uniform(0).setGroup(renderGroup);
26765    this.decayExponentNode = uniform(0).setGroup(renderGroup);
26766    this.colorNode = uniform(this.color).setGroup(renderGroup);
26767  }
26768  /**
26769   * Overwritten to updated spot light specific uniforms.
26770   *
26771   * @param {NodeFrame} frame - A reference to the current node frame.
26772   */
26773  update(frame) {
26774    super.update(frame);
26775    const { light } = this;
26776    this.coneCosNode.value = Math.cos(light.angle);
26777    this.penumbraCosNode.value = Math.cos(light.angle * (1 - light.penumbra));
26778    this.cutoffDistanceNode.value = light.distance;
26779    this.decayExponentNode.value = light.decay;
26780  }
26781  /**
26782   * Computes the spot attenuation for the given angle.
26783   *
26784   * @param {NodeBuilder} builder - The node builder.
26785   * @param {Node<float>} angleCosine - The angle to compute the spot attenuation for.
26786   * @return {Node<float>} The spot attenuation.
26787   */
26788  getSpotAttenuation(builder, angleCosine) {
26789    const { coneCosNode, penumbraCosNode } = this;
26790    return smoothstep(coneCosNode, penumbraCosNode, angleCosine);
26791  }
26792  getLightCoord(builder) {
26793    const properties = builder.getNodeProperties(this);
26794    let projectionUV = properties.projectionUV;
26795    if (projectionUV === void 0) {
26796      projectionUV = lightProjectionUV(this.light, builder.context.positionWorld);
26797      properties.projectionUV = projectionUV;
26798    }
26799    return projectionUV;
26800  }
26801  setupDirect(builder) {
26802    const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this;
26803    const lightVector = this.getLightVector(builder);
26804    const lightDirection = lightVector.normalize();
26805    const angleCos = lightDirection.dot(lightTargetDirection(light));
26806    const spotAttenuation = this.getSpotAttenuation(builder, angleCos);
26807    const lightDistance = lightVector.length();
26808    const lightAttenuation = getDistanceAttenuation({
26809      lightDistance,
26810      cutoffDistance: cutoffDistanceNode,
26811      decayExponent: decayExponentNode
26812    });
26813    let lightColor = colorNode.mul(spotAttenuation).mul(lightAttenuation);
26814    let projected, lightCoord;
26815    if (light.colorNode) {
26816      lightCoord = this.getLightCoord(builder);
26817      projected = light.colorNode(lightCoord);
26818    } else if (light.map) {
26819      lightCoord = this.getLightCoord(builder);
26820      projected = texture(light.map, lightCoord.xy).onRenderUpdate(() => light.map);
26821    }
26822    if (projected) {
26823      const inSpotLightMap = lightCoord.mul(2).sub(1).abs().lessThan(1).all();
26824      lightColor = inSpotLightMap.select(lightColor.mul(projected), lightColor);
26825    }
26826    return { lightColor, lightDirection };
26827  }
26828};
26829var IESSpotLightNode = class extends SpotLightNode {
26830  static get type() {
26831    return "IESSpotLightNode";
26832  }
26833  /**
26834   * Overwrites the default implementation to compute an IES conform spot attenuation.
26835   *
26836   * @param {NodeBuilder} builder - The node builder.
26837   * @param {Node<float>} angleCosine - The angle to compute the spot attenuation for.
26838   * @return {Node<float>} The spot attenuation.
26839   */
26840  getSpotAttenuation(builder, angleCosine) {
26841    const iesMap = this.light.iesMap;
26842    let spotAttenuation = null;
26843    if (iesMap && iesMap.isTexture === true) {
26844      const angle = angleCosine.acos().mul(1 / Math.PI);
26845      spotAttenuation = texture(iesMap, vec2(angle, 0), 0).r;
26846    } else {
26847      spotAttenuation = super.getSpotAttenuation(angleCosine);
26848    }
26849    return spotAttenuation;
26850  }
26851};
26852var LightProbeNode = class extends AnalyticLightNode {
26853  static get type() {
26854    return "LightProbeNode";
26855  }
26856  /**
26857   * Constructs a new light probe node.
26858   *
26859   * @param {?LightProbe} [light=null] - The light probe.
26860   */
26861  constructor(light = null) {
26862    super(light);
26863    const array3 = [];
26864    for (let i = 0; i < 9; i++) array3.push(new Vector3());
26865    this.lightProbe = uniformArray(array3);
26866  }
26867  /**
26868   * Overwritten to updated light probe specific uniforms.
26869   *
26870   * @param {NodeFrame} frame - A reference to the current node frame.
26871   */
26872  update(frame) {
26873    const { light } = this;
26874    super.update(frame);
26875    for (let i = 0; i < 9; i++) {
26876      this.lightProbe.array[i].copy(light.sh.coefficients[i]).multiplyScalar(light.intensity);
26877    }
26878  }
26879  setup(builder) {
26880    const irradiance = getShIrradianceAt(normalWorld, this.lightProbe);
26881    builder.context.irradiance.addAssign(irradiance);
26882  }
26883};
26884var sdBox = /* @__PURE__ */ Fn(([p, b]) => {
26885  const d = p.abs().sub(b);
26886  return length(max$1(d, 0)).add(min$1(max$1(d.x, d.y), 0));
26887});
26888var ProjectorLightNode = class extends SpotLightNode {
26889  static get type() {
26890    return "ProjectorLightNode";
26891  }
26892  update(frame) {
26893    super.update(frame);
26894    const light = this.light;
26895    this.penumbraCosNode.value = Math.min(Math.cos(light.angle * (1 - light.penumbra)), 0.99999);
26896    if (light.aspect === null) {
26897      let aspect = 1;
26898      if (light.map !== null) {
26899        aspect = light.map.width / light.map.height;
26900      }
26901      light.shadow.aspect = aspect;
26902    } else {
26903      light.shadow.aspect = light.aspect;
26904    }
26905  }
26906  /**
26907   * Overwrites the default implementation to compute projection attenuation.
26908   *
26909   * @param {NodeBuilder} builder - The node builder.
26910   * @return {Node<float>} The spot attenuation.
26911   */
26912  getSpotAttenuation(builder) {
26913    const attenuation = float(0);
26914    const penumbraCos = this.penumbraCosNode;
26915    const spotLightCoord = lightShadowMatrix(this.light).mul(builder.context.positionWorld || positionWorld);
26916    If(spotLightCoord.w.greaterThan(0), () => {
26917      const projectionUV = spotLightCoord.xyz.div(spotLightCoord.w);
26918      const boxDist = sdBox(projectionUV.xy.sub(vec2(0.5)), vec2(0.5));
26919      const angleFactor = div(-1, sub(1, acos(penumbraCos)).sub(1));
26920      attenuation.assign(saturate(boxDist.mul(-2).mul(angleFactor)));
26921    });
26922    return attenuation;
26923  }
26924};
26925var _matrix41 = /* @__PURE__ */ new Matrix4();
26926var _matrix42 = /* @__PURE__ */ new Matrix4();
26927var _ltcLib = null;
26928var RectAreaLightNode = class extends AnalyticLightNode {
26929  static get type() {
26930    return "RectAreaLightNode";
26931  }
26932  /**
26933   * Constructs a new rect area light node.
26934   *
26935   * @param {?RectAreaLight} [light=null] - The rect area light source.
26936   */
26937  constructor(light = null) {
26938    super(light);
26939    this.halfHeight = uniform(new Vector3()).setGroup(renderGroup);
26940    this.halfWidth = uniform(new Vector3()).setGroup(renderGroup);
26941    this.updateType = NodeUpdateType.RENDER;
26942  }
26943  /**
26944   * Overwritten to updated rect area light specific uniforms.
26945   *
26946   * @param {NodeFrame} frame - A reference to the current node frame.
26947   */
26948  update(frame) {
26949    super.update(frame);
26950    const { light } = this;
26951    const viewMatrix = frame.camera.matrixWorldInverse;
26952    _matrix42.identity();
26953    _matrix41.copy(light.matrixWorld);
26954    _matrix41.premultiply(viewMatrix);
26955    _matrix42.extractRotation(_matrix41);
26956    this.halfWidth.value.set(light.width * 0.5, 0, 0);
26957    this.halfHeight.value.set(0, light.height * 0.5, 0);
26958    this.halfWidth.value.applyMatrix4(_matrix42);
26959    this.halfHeight.value.applyMatrix4(_matrix42);
26960  }
26961  setupDirectRectArea(builder) {
26962    let ltc_1, ltc_2;
26963    if (builder.isAvailable("float32Filterable")) {
26964      ltc_1 = texture(_ltcLib.LTC_FLOAT_1);
26965      ltc_2 = texture(_ltcLib.LTC_FLOAT_2);
26966    } else {
26967      ltc_1 = texture(_ltcLib.LTC_HALF_1);
26968      ltc_2 = texture(_ltcLib.LTC_HALF_2);
26969    }
26970    const { colorNode, light } = this;
26971    const lightPosition3 = lightViewPosition(light);
26972    return {
26973      lightColor: colorNode,
26974      lightPosition: lightPosition3,
26975      halfWidth: this.halfWidth,
26976      halfHeight: this.halfHeight,
26977      ltc_1,
26978      ltc_2
26979    };
26980  }
26981  /**
26982   * Used to configure the internal BRDF approximation texture data.
26983   *
26984   * @param {RectAreaLightTexturesLib} ltc - The BRDF approximation texture data.
26985   */
26986  static setLTC(ltc) {
26987    _ltcLib = ltc;
26988  }
26989};
26990var NodeParser = class {
26991  /**
26992   * The method parses the given native code an returns a node function.
26993   *
26994   * @abstract
26995   * @param {string} source - The native shader code.
26996   * @return {NodeFunction} A node function.
26997   */
26998  parseFunction() {
26999    warn("Abstract function.");
27000  }
27001};
27002var NodeFunction = class {
27003  /**
27004   * Constructs a new node function.
27005   *
27006   * @param {string} type - The node type. This type is the return type of the node function.
27007   * @param {Array<NodeFunctionInput>} inputs - The function's inputs.
27008   * @param {string} [name=''] - The function's name.
27009   * @param {string} [precision=''] - The precision qualifier.
27010   */
27011  constructor(type, inputs, name = "", precision = "") {
27012    this.type = type;
27013    this.inputs = inputs;
27014    this.name = name;
27015    this.precision = precision;
27016  }
27017  /**
27018   * This method returns the native code of the node function.
27019   *
27020   * @abstract
27021   * @param {string} name - The function's name.
27022   * @return {string} A shader code.
27023   */
27024  getCode() {
27025    warn("Abstract function.");
27026  }
27027};
27028NodeFunction.isNodeFunction = true;
27029var declarationRegexp$1 = /^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i;
27030var propertiesRegexp$1 = /[a-z_0-9]+/ig;
27031var pragmaMain = "#pragma main";
27032var parse$1 = (source) => {
27033  source = source.trim();
27034  const pragmaMainIndex = source.indexOf(pragmaMain);
27035  const mainCode = pragmaMainIndex !== -1 ? source.slice(pragmaMainIndex + pragmaMain.length) : source;
27036  const declaration = mainCode.match(declarationRegexp$1);
27037  if (declaration !== null && declaration.length === 5) {
27038    const inputsCode = declaration[4];
27039    const propsMatches = [];
27040    let nameMatch = null;
27041    while ((nameMatch = propertiesRegexp$1.exec(inputsCode)) !== null) {
27042      propsMatches.push(nameMatch);
27043    }
27044    const inputs = [];
27045    let i = 0;
27046    while (i < propsMatches.length) {
27047      const isConst = propsMatches[i][0] === "const";
27048      if (isConst === true) {
27049        i++;
27050      }
27051      let qualifier = propsMatches[i][0];
27052      if (qualifier === "in" || qualifier === "out" || qualifier === "inout") {
27053        i++;
27054      } else {
27055        qualifier = "";
27056      }
27057      const type2 = propsMatches[i++][0];
27058      let count = Number.parseInt(propsMatches[i][0]);
27059      if (Number.isNaN(count) === false) i++;
27060      else count = null;
27061      const name2 = propsMatches[i++][0];
27062      inputs.push(new NodeFunctionInput(type2, name2, count, qualifier, isConst));
27063    }
27064    const blockCode = mainCode.substring(declaration[0].length);
27065    const name = declaration[3] !== void 0 ? declaration[3] : "";
27066    const type = declaration[2];
27067    const precision = declaration[1] !== void 0 ? declaration[1] : "";
27068    const headerCode = pragmaMainIndex !== -1 ? source.slice(0, pragmaMainIndex) : "";
27069    return {
27070      type,
27071      inputs,
27072      name,
27073      precision,
27074      inputsCode,
27075      blockCode,
27076      headerCode
27077    };
27078  } else {
27079    throw new Error("FunctionNode: Function is not a GLSL code.");
27080  }
27081};
27082var GLSLNodeFunction = class extends NodeFunction {
27083  /**
27084   * Constructs a new GLSL node function.
27085   *
27086   * @param {string} source - The GLSL source.
27087   */
27088  constructor(source) {
27089    const { type, inputs, name, precision, inputsCode, blockCode, headerCode } = parse$1(source);
27090    super(type, inputs, name, precision);
27091    this.inputsCode = inputsCode;
27092    this.blockCode = blockCode;
27093    this.headerCode = headerCode;
27094  }
27095  /**
27096   * This method returns the GLSL code of the node function.
27097   *
27098   * @param {string} [name=this.name] - The function's name.
27099   * @return {string} The shader code.
27100   */
27101  getCode(name = this.name) {
27102    let code3;
27103    const blockCode = this.blockCode;
27104    if (blockCode !== "") {
27105      const { type, inputsCode, headerCode, precision } = this;
27106      let declarationCode = `${type} ${name} ( ${inputsCode.trim()} )`;
27107      if (precision !== "") {
27108        declarationCode = `${precision} ${declarationCode}`;
27109      }
27110      code3 = headerCode + declarationCode + blockCode;
27111    } else {
27112      code3 = "";
27113    }
27114    return code3;
27115  }
27116};
27117var GLSLNodeParser = class extends NodeParser {
27118  /**
27119   * The method parses the given GLSL code an returns a node function.
27120   *
27121   * @param {string} source - The GLSL code.
27122   * @return {GLSLNodeFunction} A node function.
27123   */
27124  parseFunction(source) {
27125    return new GLSLNodeFunction(source);
27126  }
27127};
27128var _chainKeys$1 = [];
27129var _cacheKeyValues = [];
27130var NodeManager = class extends DataMap {
27131  /**
27132   * Constructs a new nodes management component.
27133   *
27134   * @param {Renderer} renderer - The renderer.
27135   * @param {Backend} backend - The renderer's backend.
27136   */
27137  constructor(renderer, backend) {
27138    super();
27139    this.renderer = renderer;
27140    this.backend = backend;
27141    this.nodeFrame = new NodeFrame();
27142    this.nodeBuilderCache = /* @__PURE__ */ new Map();
27143    this.callHashCache = new ChainMap();
27144    this.groupsData = new ChainMap();
27145    this._buildQueue = [];
27146    this._buildInProgress = false;
27147    this.cacheLib = {};
27148  }
27149  /**
27150   * Returns `true` if the given node uniforms group must be updated or not.
27151   *
27152   * @param {NodeUniformsGroup} nodeUniformsGroup - The node uniforms group.
27153   * @return {boolean} Whether the node uniforms group requires an update or not.
27154   */
27155  updateGroup(nodeUniformsGroup) {
27156    const groupNode = nodeUniformsGroup.groupNode;
27157    _chainKeys$1[0] = groupNode;
27158    _chainKeys$1[1] = nodeUniformsGroup;
27159    let groupData = this.groupsData.get(_chainKeys$1);
27160    if (groupData === void 0) this.groupsData.set(_chainKeys$1, groupData = {});
27161    _chainKeys$1[0] = null;
27162    _chainKeys$1[1] = null;
27163    if (groupData.version !== groupNode.version) {
27164      groupData.version = groupNode.version;
27165      return true;
27166    }
27167    return false;
27168  }
27169  /**
27170   * Returns the cache key for the given render object.
27171   *
27172   * @param {RenderObject} renderObject - The render object.
27173   * @return {number} The cache key.
27174   */
27175  getForRenderCacheKey(renderObject) {
27176    return renderObject.initialCacheKey;
27177  }
27178  /**
27179   * Creates a node builder configured for the given render object and material.
27180   *
27181   * @private
27182   * @param {RenderObject} renderObject - The render object.
27183   * @param {Material} material - The material to use.
27184   * @return {NodeBuilder} The configured node builder.
27185   */
27186  _createNodeBuilder(renderObject, material) {
27187    const nodeBuilder = this.backend.createNodeBuilder(renderObject.object, this.renderer);
27188    nodeBuilder.scene = renderObject.scene;
27189    nodeBuilder.material = material;
27190    nodeBuilder.camera = renderObject.camera;
27191    nodeBuilder.context.material = material;
27192    nodeBuilder.lightsNode = renderObject.lightsNode;
27193    nodeBuilder.environmentNode = this.getEnvironmentNode(renderObject.scene);
27194    nodeBuilder.fogNode = this.getFogNode(renderObject.scene);
27195    nodeBuilder.clippingContext = renderObject.clippingContext;
27196    if (this.renderer.getOutputRenderTarget() ? this.renderer.getOutputRenderTarget().multiview : false) {
27197      nodeBuilder.enableMultiview();
27198    }
27199    return nodeBuilder;
27200  }
27201  /**
27202   * Returns a node builder state for the given render object.
27203   *
27204   * @param {RenderObject} renderObject - The render object.
27205   * @param {boolean} [useAsync=false] - Whether to use async build with yielding.
27206   * @return {NodeBuilderState|Promise<NodeBuilderState>} The node builder state (or Promise if async).
27207   */
27208  getForRender(renderObject, useAsync = false) {
27209    const renderObjectData = this.get(renderObject);
27210    let nodeBuilderState = renderObjectData.nodeBuilderState;
27211    if (nodeBuilderState === void 0) {
27212      const { nodeBuilderCache } = this;
27213      const cacheKey = this.getForRenderCacheKey(renderObject);
27214      nodeBuilderState = nodeBuilderCache.get(cacheKey);
27215      if (nodeBuilderState === void 0) {
27216        const buildNodeBuilder = async () => {
27217          let nodeBuilder = this._createNodeBuilder(renderObject, renderObject.material);
27218          try {
27219            if (useAsync) {
27220              await nodeBuilder.buildAsync();
27221            } else {
27222              nodeBuilder.build();
27223            }
27224          } catch (e) {
27225            nodeBuilder = this._createNodeBuilder(renderObject, new NodeMaterial());
27226            if (useAsync) {
27227              await nodeBuilder.buildAsync();
27228            } else {
27229              nodeBuilder.build();
27230            }
27231            error("TSL: " + e);
27232          }
27233          return nodeBuilder;
27234        };
27235        if (useAsync) {
27236          return buildNodeBuilder().then((nodeBuilder) => {
27237            nodeBuilderState = this._createNodeBuilderState(nodeBuilder);
27238            nodeBuilderCache.set(cacheKey, nodeBuilderState);
27239            nodeBuilderState.usedTimes++;
27240            renderObjectData.nodeBuilderState = nodeBuilderState;
27241            return nodeBuilderState;
27242          });
27243        } else {
27244          let nodeBuilder = this._createNodeBuilder(renderObject, renderObject.material);
27245          try {
27246            nodeBuilder.build();
27247          } catch (e) {
27248            nodeBuilder = this._createNodeBuilder(renderObject, new NodeMaterial());
27249            nodeBuilder.build();
27250            let stackTrace = e.stackTrace;
27251            if (!stackTrace && e.stack) {
27252              stackTrace = new StackTrace(e.stack);
27253            }
27254            error("TSL: " + e, stackTrace);
27255          }
27256          nodeBuilderState = this._createNodeBuilderState(nodeBuilder);
27257          nodeBuilderCache.set(cacheKey, nodeBuilderState);
27258        }
27259      }
27260      nodeBuilderState.usedTimes++;
27261      renderObjectData.nodeBuilderState = nodeBuilderState;
27262    }
27263    return nodeBuilderState;
27264  }
27265  /**
27266   * Async version of getForRender() that yields to main thread during build.
27267   * Use this in compileAsync() to prevent blocking the main thread.
27268   *
27269   * @param {RenderObject} renderObject - The render object.
27270   * @return {Promise<NodeBuilderState>} A promise that resolves to the node builder state.
27271   */
27272  getForRenderAsync(renderObject) {
27273    const result = this.getForRender(renderObject, true);
27274    if (result.then) {
27275      return result;
27276    }
27277    return Promise.resolve(result);
27278  }
27279  /**
27280   * Returns nodeBuilderState if ready, null if pending async build.
27281   * Queues async build on first call for cache miss.
27282   * Use this in render() path to enable non-blocking compilation.
27283   *
27284   * @param {RenderObject} renderObject - The render object.
27285   * @return {?NodeBuilderState} The node builder state, or null if still building.
27286   */
27287  getForRenderDeferred(renderObject) {
27288    const renderObjectData = this.get(renderObject);
27289    if (renderObjectData.nodeBuilderState !== void 0) {
27290      return renderObjectData.nodeBuilderState;
27291    }
27292    const cacheKey = this.getForRenderCacheKey(renderObject);
27293    const nodeBuilderState = this.nodeBuilderCache.get(cacheKey);
27294    if (nodeBuilderState !== void 0) {
27295      nodeBuilderState.usedTimes++;
27296      renderObjectData.nodeBuilderState = nodeBuilderState;
27297      return nodeBuilderState;
27298    }
27299    if (renderObjectData.pendingBuild !== true) {
27300      renderObjectData.pendingBuild = true;
27301      this._buildQueue.push(() => {
27302        return this.getForRenderAsync(renderObject).then(() => {
27303          renderObjectData.pendingBuild = false;
27304        });
27305      });
27306      this._processBuildQueue();
27307    }
27308    return null;
27309  }
27310  /**
27311   * Processes the build queue one item at a time.
27312   * This ensures builds don't all run simultaneously and freeze the main thread.
27313   *
27314   * @private
27315   */
27316  _processBuildQueue() {
27317    if (this._buildInProgress || this._buildQueue.length === 0) {
27318      return;
27319    }
27320    this._buildInProgress = true;
27321    const buildFn = this._buildQueue.shift();
27322    buildFn().then(() => {
27323      this._buildInProgress = false;
27324      this._processBuildQueue();
27325    });
27326  }
27327  /**
27328   * Deletes the given object from the internal data map
27329   *
27330   * @param {any} object - The object to delete.
27331   * @return {?Object} The deleted dictionary.
27332   */
27333  delete(object) {
27334    if (object.isRenderObject) {
27335      const nodeBuilderState = this.get(object).nodeBuilderState;
27336      if (nodeBuilderState !== void 0) {
27337        nodeBuilderState.usedTimes--;
27338        if (nodeBuilderState.usedTimes === 0) {
27339          this.nodeBuilderCache.delete(this.getForRenderCacheKey(object));
27340        }
27341      }
27342    }
27343    return super.delete(object);
27344  }
27345  /**
27346   * Returns a node builder state for the given compute node.
27347   *
27348   * @param {Node} computeNode - The compute node.
27349   * @return {NodeBuilderState} The node builder state.
27350   */
27351  getForCompute(computeNode) {
27352    const computeData = this.get(computeNode);
27353    let nodeBuilderState = computeData.nodeBuilderState;
27354    if (nodeBuilderState === void 0) {
27355      const nodeBuilder = this.backend.createNodeBuilder(computeNode, this.renderer);
27356      nodeBuilder.build();
27357      nodeBuilderState = this._createNodeBuilderState(nodeBuilder);
27358      computeData.nodeBuilderState = nodeBuilderState;
27359    }
27360    return nodeBuilderState;
27361  }
27362  /**
27363   * Creates a node builder state for the given node builder.
27364   *
27365   * @private
27366   * @param {NodeBuilder} nodeBuilder - The node builder.
27367   * @return {NodeBuilderState} The node builder state.
27368   */
27369  _createNodeBuilderState(nodeBuilder) {
27370    return new NodeBuilderState(
27371      nodeBuilder.vertexShader,
27372      nodeBuilder.fragmentShader,
27373      nodeBuilder.computeShader,
27374      nodeBuilder.getAttributesArray(),
27375      nodeBuilder.getBindings(),
27376      nodeBuilder.updateNodes,
27377      nodeBuilder.updateBeforeNodes,
27378      nodeBuilder.updateAfterNodes,
27379      nodeBuilder.observer,
27380      nodeBuilder.transforms
27381    );
27382  }
27383  /**
27384   * Returns an environment node for the current configured
27385   * scene environment.
27386   *
27387   * @param {Scene} scene - The scene.
27388   * @return {Node} A node representing the current scene environment.
27389   */
27390  getEnvironmentNode(scene) {
27391    this.updateEnvironment(scene);
27392    let environmentNode = null;
27393    if (scene.environmentNode && scene.environmentNode.isNode) {
27394      environmentNode = scene.environmentNode;
27395    } else {
27396      const sceneData = this.get(scene);
27397      if (sceneData.environmentNode) {
27398        environmentNode = sceneData.environmentNode;
27399      }
27400    }
27401    return environmentNode;
27402  }
27403  /**
27404   * Returns a background node for the current configured
27405   * scene background.
27406   *
27407   * @param {Scene} scene - The scene.
27408   * @return {Node} A node representing the current scene background.
27409   */
27410  getBackgroundNode(scene) {
27411    this.updateBackground(scene);
27412    let backgroundNode = null;
27413    if (scene.backgroundNode && scene.backgroundNode.isNode) {
27414      backgroundNode = scene.backgroundNode;
27415    } else {
27416      const sceneData = this.get(scene);
27417      if (sceneData.backgroundNode) {
27418        backgroundNode = sceneData.backgroundNode;
27419      }
27420    }
27421    return backgroundNode;
27422  }
27423  /**
27424   * Returns a fog node for the current configured scene fog.
27425   *
27426   * @param {Scene} scene - The scene.
27427   * @return {Node} A node representing the current scene fog.
27428   */
27429  getFogNode(scene) {
27430    this.updateFog(scene);
27431    return scene.fogNode || this.get(scene).fogNode || null;
27432  }
27433  /**
27434   * Returns a cache key for the given scene and lights node.
27435   * This key is used by `RenderObject` as a part of the dynamic
27436   * cache key (a key that must be checked every time the render
27437   * objects is drawn).
27438   *
27439   * @param {Scene} scene - The scene.
27440   * @param {LightsNode} lightsNode - The lights node.
27441   * @return {number} The cache key.
27442   */
27443  getCacheKey(scene, lightsNode) {
27444    _chainKeys$1[0] = scene;
27445    _chainKeys$1[1] = lightsNode;
27446    const callId = this.renderer.info.calls;
27447    const cacheKeyData = this.callHashCache.get(_chainKeys$1) || {};
27448    if (cacheKeyData.callId !== callId) {
27449      const environmentNode = this.getEnvironmentNode(scene);
27450      const fogNode = this.getFogNode(scene);
27451      if (lightsNode) _cacheKeyValues.push(lightsNode.getCacheKey(true));
27452      if (environmentNode) _cacheKeyValues.push(environmentNode.getCacheKey());
27453      if (fogNode) _cacheKeyValues.push(fogNode.getCacheKey());
27454      _cacheKeyValues.push(this.renderer.getOutputRenderTarget() && this.renderer.getOutputRenderTarget().multiview ? 1 : 0);
27455      _cacheKeyValues.push(this.renderer.shadowMap.enabled ? 1 : 0);
27456      _cacheKeyValues.push(this.renderer.shadowMap.type);
27457      cacheKeyData.callId = callId;
27458      cacheKeyData.cacheKey = hashArray(_cacheKeyValues);
27459      this.callHashCache.set(_chainKeys$1, cacheKeyData);
27460      _cacheKeyValues.length = 0;
27461    }
27462    _chainKeys$1[0] = null;
27463    _chainKeys$1[1] = null;
27464    return cacheKeyData.cacheKey;
27465  }
27466  /**
27467   * A boolean that indicates whether tone mapping should be enabled
27468   * or not.
27469   *
27470   * @type {boolean}
27471   */
27472  get isToneMappingState() {
27473    return this.renderer.getRenderTarget() ? false : true;
27474  }
27475  /**
27476   * If a scene background is configured, this method makes sure to
27477   * represent the background with a corresponding node-based implementation.
27478   *
27479   * @param {Scene} scene - The scene.
27480   */
27481  updateBackground(scene) {
27482    const sceneData = this.get(scene);
27483    const background = scene.background;
27484    if (background) {
27485      const forceUpdate = scene.backgroundBlurriness === 0 && sceneData.backgroundBlurriness > 0 || scene.backgroundBlurriness > 0 && sceneData.backgroundBlurriness === 0;
27486      if (sceneData.background !== background || forceUpdate) {
27487        const backgroundNode = this.getCacheNode("background", background, () => {
27488          if (background.isCubeTexture === true || (background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping)) {
27489            if (scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping) {
27490              return pmremTexture(background);
27491            } else {
27492              let envMap;
27493              if (background.isCubeTexture === true) {
27494                envMap = cubeTexture(background);
27495              } else {
27496                envMap = texture(background);
27497              }
27498              return cubeMapNode(envMap);
27499            }
27500          } else if (background.isTexture === true) {
27501            return texture(background, screenUV.flipY()).setUpdateMatrix(true);
27502          } else if (background.isColor !== true) {
27503            error("WebGPUNodes: Unsupported background configuration.", background);
27504          }
27505        }, forceUpdate);
27506        sceneData.backgroundNode = backgroundNode;
27507        sceneData.background = background;
27508        sceneData.backgroundBlurriness = scene.backgroundBlurriness;
27509      }
27510    } else if (sceneData.backgroundNode) {
27511      delete sceneData.backgroundNode;
27512      delete sceneData.background;
27513    }
27514  }
27515  /**
27516   * This method is part of the caching of nodes which are used to represents the
27517   * scene's background, fog or environment.
27518   *
27519   * @param {string} type - The type of object to cache.
27520   * @param {Object} object - The object.
27521   * @param {Function} callback - A callback that produces a node representation for the given object.
27522   * @param {boolean} [forceUpdate=false] - Whether an update should be enforced or not.
27523   * @return {Node} The node representation.
27524   */
27525  getCacheNode(type, object, callback, forceUpdate = false) {
27526    const nodeCache = this.cacheLib[type] || (this.cacheLib[type] = /* @__PURE__ */ new WeakMap());
27527    let node = nodeCache.get(object);
27528    if (node === void 0 || forceUpdate) {
27529      node = callback();
27530      nodeCache.set(object, node);
27531    }
27532    return node;
27533  }
27534  /**
27535   * If a scene fog is configured, this method makes sure to
27536   * represent the fog with a corresponding node-based implementation.
27537   *
27538   * @param {Scene} scene - The scene.
27539   */
27540  updateFog(scene) {
27541    const sceneData = this.get(scene);
27542    const sceneFog = scene.fog;
27543    if (sceneFog) {
27544      if (sceneData.fog !== sceneFog) {
27545        const fogNode = this.getCacheNode("fog", sceneFog, () => {
27546          if (sceneFog.isFogExp2) {
27547            const color3 = reference("color", "color", sceneFog).setGroup(renderGroup);
27548            const density = reference("density", "float", sceneFog).setGroup(renderGroup);
27549            return fog(color3, densityFogFactor(density));
27550          } else if (sceneFog.isFog) {
27551            const color3 = reference("color", "color", sceneFog).setGroup(renderGroup);
27552            const near = reference("near", "float", sceneFog).setGroup(renderGroup);
27553            const far = reference("far", "float", sceneFog).setGroup(renderGroup);
27554            return fog(color3, rangeFogFactor(near, far));
27555          } else {
27556            error("Renderer: Unsupported fog configuration.", sceneFog);
27557          }
27558        });
27559        sceneData.fogNode = fogNode;
27560        sceneData.fog = sceneFog;
27561      }
27562    } else {
27563      delete sceneData.fogNode;
27564      delete sceneData.fog;
27565    }
27566  }
27567  /**
27568   * If a scene environment is configured, this method makes sure to
27569   * represent the environment with a corresponding node-based implementation.
27570   *
27571   * @param {Scene} scene - The scene.
27572   */
27573  updateEnvironment(scene) {
27574    const sceneData = this.get(scene);
27575    const environment = scene.environment;
27576    if (environment) {
27577      if (sceneData.environment !== environment) {
27578        const environmentNode = this.getCacheNode("environment", environment, () => {
27579          if (environment.isCubeTexture === true) {
27580            return cubeTexture(environment);
27581          } else if (environment.isTexture === true) {
27582            return texture(environment);
27583          } else {
27584            error("Nodes: Unsupported environment configuration.", environment);
27585          }
27586        });
27587        sceneData.environmentNode = environmentNode;
27588        sceneData.environment = environment;
27589      }
27590    } else if (sceneData.environmentNode) {
27591      delete sceneData.environmentNode;
27592      delete sceneData.environment;
27593    }
27594  }
27595  getNodeFrame(renderer = this.renderer, scene = null, object = null, camera = null, material = null) {
27596    const nodeFrame = this.nodeFrame;
27597    nodeFrame.renderer = renderer;
27598    nodeFrame.scene = scene;
27599    nodeFrame.object = object;
27600    nodeFrame.camera = camera;
27601    nodeFrame.material = material;
27602    return nodeFrame;
27603  }
27604  getNodeFrameForRender(renderObject) {
27605    return this.getNodeFrame(renderObject.renderer, renderObject.scene, renderObject.object, renderObject.camera, renderObject.material);
27606  }
27607  /**
27608   * Returns the current output cache key.
27609   *
27610   * @return {string} The output cache key.
27611   */
27612  getOutputCacheKey() {
27613    const renderer = this.renderer;
27614    return renderer.toneMapping + "," + renderer.currentColorSpace + "," + renderer.xr.isPresenting;
27615  }
27616  /**
27617   * Returns a node that represents the output configuration (tone mapping and
27618   * color space) for the current target.
27619   *
27620   * @param {Texture} outputTarget - The output target.
27621   * @return {Node} The output node.
27622   */
27623  getOutputNode(outputTarget) {
27624    const renderer = this.renderer;
27625    const output3 = outputTarget.isArrayTexture ? texture(outputTarget, screenUV).depth(builtin("gl_ViewID_OVR")).renderOutput(renderer.toneMapping, renderer.currentColorSpace) : texture(outputTarget, screenUV).renderOutput(renderer.toneMapping, renderer.currentColorSpace);
27626    return output3;
27627  }
27628  /**
27629   * Triggers the call of `updateBefore()` methods
27630   * for all nodes of the given render object.
27631   *
27632   * @param {RenderObject} renderObject - The render object.
27633   */
27634  updateBefore(renderObject) {
27635    const nodeBuilder = renderObject.getNodeBuilderState();
27636    for (const node of nodeBuilder.updateBeforeNodes) {
27637      this.getNodeFrameForRender(renderObject).updateBeforeNode(node);
27638    }
27639  }
27640  /**
27641   * Triggers the call of `updateAfter()` methods
27642   * for all nodes of the given render object.
27643   *
27644   * @param {RenderObject} renderObject - The render object.
27645   */
27646  updateAfter(renderObject) {
27647    const nodeBuilder = renderObject.getNodeBuilderState();
27648    for (const node of nodeBuilder.updateAfterNodes) {
27649      this.getNodeFrameForRender(renderObject).updateAfterNode(node);
27650    }
27651  }
27652  /**
27653   * Triggers the call of `update()` methods
27654   * for all nodes of the given compute node.
27655   *
27656   * @param {Node} computeNode - The compute node.
27657   */
27658  updateForCompute(computeNode) {
27659    const nodeFrame = this.getNodeFrame();
27660    const nodeBuilder = this.getForCompute(computeNode);
27661    for (const node of nodeBuilder.updateNodes) {
27662      nodeFrame.updateNode(node);
27663    }
27664  }
27665  /**
27666   * Triggers the call of `update()` methods
27667   * for all nodes of the given render object.
27668   *
27669   * @param {RenderObject} renderObject - The render object.
27670   */
27671  updateForRender(renderObject) {
27672    const nodeFrame = this.getNodeFrameForRender(renderObject);
27673    const nodeBuilder = renderObject.getNodeBuilderState();
27674    for (const node of nodeBuilder.updateNodes) {
27675      nodeFrame.updateNode(node);
27676    }
27677  }
27678  /**
27679   * Returns `true` if the given render object requires a refresh.
27680   *
27681   * @param {RenderObject} renderObject - The render object.
27682   * @return {boolean} Whether the given render object requires a refresh or not.
27683   */
27684  needsRefresh(renderObject) {
27685    const nodeFrame = this.getNodeFrameForRender(renderObject);
27686    const monitor = renderObject.getMonitor();
27687    return monitor.needsRefresh(renderObject, nodeFrame);
27688  }
27689  /**
27690   * Frees the internal resources.
27691   */
27692  dispose() {
27693    super.dispose();
27694    this.nodeFrame = new NodeFrame();
27695    this.nodeBuilderCache = /* @__PURE__ */ new Map();
27696    this.cacheLib = {};
27697  }
27698};
27699var _plane = /* @__PURE__ */ new Plane();
27700var ClippingContext = class _ClippingContext {
27701  /**
27702   * Constructs a new clipping context.
27703   *
27704   * @param {?ClippingContext} [parentContext=null] - A reference to the parent clipping context.
27705   */
27706  constructor(parentContext = null) {
27707    this.version = 0;
27708    this.clipIntersection = null;
27709    this.cacheKey = "";
27710    this.shadowPass = false;
27711    this.viewNormalMatrix = new Matrix3();
27712    this.clippingGroupContexts = /* @__PURE__ */ new WeakMap();
27713    this.intersectionPlanes = [];
27714    this.unionPlanes = [];
27715    this.parentVersion = null;
27716    if (parentContext !== null) {
27717      this.viewNormalMatrix = parentContext.viewNormalMatrix;
27718      this.clippingGroupContexts = parentContext.clippingGroupContexts;
27719      this.shadowPass = parentContext.shadowPass;
27720      this.viewMatrix = parentContext.viewMatrix;
27721    }
27722  }
27723  /**
27724   * Projects the given source clipping planes and writes the result into the
27725   * destination array.
27726   *
27727   * @param {Array<Plane>} source - The source clipping planes.
27728   * @param {Array<Vector4>} destination - The destination.
27729   * @param {number} offset - The offset.
27730   */
27731  projectPlanes(source, destination, offset3) {
27732    const l = source.length;
27733    for (let i = 0; i < l; i++) {
27734      _plane.copy(source[i]).applyMatrix4(this.viewMatrix, this.viewNormalMatrix);
27735      const v = destination[offset3 + i];
27736      const normal2 = _plane.normal;
27737      v.x = -normal2.x;
27738      v.y = -normal2.y;
27739      v.z = -normal2.z;
27740      v.w = _plane.constant;
27741    }
27742  }
27743  /**
27744   * Updates the root clipping context of a scene.
27745   *
27746   * @param {Scene} scene - The scene.
27747   * @param {Camera} camera - The camera that is used to render the scene.
27748   */
27749  updateGlobal(scene, camera) {
27750    this.shadowPass = scene.overrideMaterial !== null && scene.overrideMaterial.isShadowPassMaterial;
27751    this.viewMatrix = camera.matrixWorldInverse;
27752    this.viewNormalMatrix.getNormalMatrix(this.viewMatrix);
27753  }
27754  /**
27755   * Updates the clipping context.
27756   *
27757   * @param {ClippingContext} parentContext - The parent context.
27758   * @param {ClippingGroup} clippingGroup - The clipping group this context belongs to.
27759   */
27760  update(parentContext, clippingGroup) {
27761    let update = false;
27762    if (parentContext.version !== this.parentVersion) {
27763      this.intersectionPlanes = Array.from(parentContext.intersectionPlanes);
27764      this.unionPlanes = Array.from(parentContext.unionPlanes);
27765      this.parentVersion = parentContext.version;
27766    }
27767    if (this.clipIntersection !== clippingGroup.clipIntersection) {
27768      this.clipIntersection = clippingGroup.clipIntersection;
27769      if (this.clipIntersection) {
27770        this.unionPlanes.length = parentContext.unionPlanes.length;
27771      } else {
27772        this.intersectionPlanes.length = parentContext.intersectionPlanes.length;
27773      }
27774    }
27775    const srcClippingPlanes = clippingGroup.clippingPlanes;
27776    const l = srcClippingPlanes.length;
27777    let dstClippingPlanes;
27778    let offset3;
27779    if (this.clipIntersection) {
27780      dstClippingPlanes = this.intersectionPlanes;
27781      offset3 = parentContext.intersectionPlanes.length;
27782    } else {
27783      dstClippingPlanes = this.unionPlanes;
27784      offset3 = parentContext.unionPlanes.length;
27785    }
27786    if (dstClippingPlanes.length !== offset3 + l) {
27787      dstClippingPlanes.length = offset3 + l;
27788      for (let i = 0; i < l; i++) {
27789        dstClippingPlanes[offset3 + i] = new Vector4();
27790      }
27791      update = true;
27792    }
27793    this.projectPlanes(srcClippingPlanes, dstClippingPlanes, offset3);
27794    if (update) {
27795      this.version++;
27796      this.cacheKey = `${this.intersectionPlanes.length}:${this.unionPlanes.length}`;
27797    }
27798  }
27799  /**
27800   * Returns a clipping context for the given clipping group.
27801   *
27802   * @param {ClippingGroup} clippingGroup - The clipping group.
27803   * @return {ClippingContext} The clipping context.
27804   */
27805  getGroupContext(clippingGroup) {
27806    if (this.shadowPass && !clippingGroup.clipShadows) return this;
27807    let context3 = this.clippingGroupContexts.get(clippingGroup);
27808    if (context3 === void 0) {
27809      context3 = new _ClippingContext(this);
27810      this.clippingGroupContexts.set(clippingGroup, context3);
27811    }
27812    context3.update(this, clippingGroup);
27813    return context3;
27814  }
27815  /**
27816   * The count of union clipping planes.
27817   *
27818   * @type {number}
27819   * @readonly
27820   */
27821  get unionClippingCount() {
27822    return this.unionPlanes.length;
27823  }
27824};
27825var RenderBundle = class {
27826  /**
27827   * Constructs a new bundle group.
27828   *
27829   * @param {BundleGroup} bundleGroup - The bundle group.
27830   * @param {Camera} camera - The camera the bundle group is rendered with.
27831   * @param {RenderContext} renderContext - The render context the bundle is rendered with.
27832   */
27833  constructor(bundleGroup, camera, renderContext) {
27834    this.bundleGroup = bundleGroup;
27835    this.camera = camera;
27836    this.renderContext = renderContext;
27837  }
27838};
27839var _chainKeys = [];
27840var RenderBundles = class {
27841  /**
27842   * Constructs a new render bundle management component.
27843   */
27844  constructor() {
27845    this.bundles = new ChainMap();
27846  }
27847  /**
27848   * Returns a render bundle for the given bundle group and camera.
27849   *
27850   * @param {BundleGroup} bundleGroup - The bundle group.
27851   * @param {Camera} camera - The camera the bundle group is rendered with.
27852   * @param {RenderContext} renderContext - The render context the bundle is rendered with.
27853   * @return {RenderBundle} The render bundle.
27854   */
27855  get(bundleGroup, camera, renderContext) {
27856    const bundles = this.bundles;
27857    _chainKeys[0] = bundleGroup;
27858    _chainKeys[1] = camera;
27859    _chainKeys[2] = renderContext;
27860    let bundle = bundles.get(_chainKeys);
27861    if (bundle === void 0) {
27862      bundle = new RenderBundle(bundleGroup, camera, renderContext);
27863      bundles.set(_chainKeys, bundle);
27864    }
27865    _chainKeys[0] = null;
27866    _chainKeys[1] = null;
27867    _chainKeys[2] = null;
27868    return bundle;
27869  }
27870  /**
27871   * Frees all internal resources.
27872   */
27873  dispose() {
27874    this.bundles = new ChainMap();
27875  }
27876};
27877var NodeLibrary = class {
27878  /**
27879   * Constructs a new node library.
27880   */
27881  constructor() {
27882    this.lightNodes = /* @__PURE__ */ new WeakMap();
27883    this.materialNodes = /* @__PURE__ */ new Map();
27884    this.toneMappingNodes = /* @__PURE__ */ new Map();
27885  }
27886  /**
27887   * Returns a matching node material instance for the given material object.
27888   *
27889   * This method also assigns/copies the properties of the given material object
27890   * to the node material. This is done to make sure the current material
27891   * configuration carries over to the node version.
27892   *
27893   * @param {Material} material - A material.
27894   * @return {NodeMaterial} The corresponding node material.
27895   */
27896  fromMaterial(material) {
27897    if (material.isNodeMaterial) return material;
27898    let nodeMaterial = null;
27899    const nodeMaterialClass = this.getMaterialNodeClass(material.type);
27900    if (nodeMaterialClass !== null) {
27901      nodeMaterial = new nodeMaterialClass();
27902      for (const key in material) {
27903        nodeMaterial[key] = material[key];
27904      }
27905    }
27906    return nodeMaterial;
27907  }
27908  /**
27909   * Adds a tone mapping node function for a tone mapping technique (constant).
27910   *
27911   * @param {Function} toneMappingNode - The tone mapping node function.
27912   * @param {number} toneMapping - The tone mapping.
27913   */
27914  addToneMapping(toneMappingNode, toneMapping3) {
27915    this.addType(toneMappingNode, toneMapping3, this.toneMappingNodes);
27916  }
27917  /**
27918   * Returns a tone mapping node function for a tone mapping technique (constant).
27919   *
27920   * @param {number} toneMapping - The tone mapping.
27921   * @return {?Function} The tone mapping node function. Returns `null` if no node function is found.
27922   */
27923  getToneMappingFunction(toneMapping3) {
27924    return this.toneMappingNodes.get(toneMapping3) || null;
27925  }
27926  /**
27927   * Returns a node material class definition for a material type.
27928   *
27929   * @param {string} materialType - The material type.
27930   * @return {?NodeMaterial.constructor} The node material class definition. Returns `null` if no node material is found.
27931   */
27932  getMaterialNodeClass(materialType) {
27933    return this.materialNodes.get(materialType) || null;
27934  }
27935  /**
27936   * Adds a node material class definition for a given material type.
27937   *
27938   * @param {NodeMaterial.constructor} materialNodeClass - The node material class definition.
27939   * @param {string} materialClassType - The material type.
27940   */
27941  addMaterial(materialNodeClass, materialClassType) {
27942    this.addType(materialNodeClass, materialClassType, this.materialNodes);
27943  }
27944  /**
27945   * Returns a light node class definition for a light class definition.
27946   *
27947   * @param {Light.constructor} light - The light class definition.
27948   * @return {?AnalyticLightNode.constructor} The light node class definition. Returns `null` if no light node is found.
27949   */
27950  getLightNodeClass(light) {
27951    return this.lightNodes.get(light) || null;
27952  }
27953  /**
27954   * Adds a light node class definition for a given light class definition.
27955   *
27956   * @param {AnalyticLightNode.constructor} lightNodeClass - The light node class definition.
27957   * @param {Light.constructor} lightClass - The light class definition.
27958   */
27959  addLight(lightNodeClass, lightClass) {
27960    this.addClass(lightNodeClass, lightClass, this.lightNodes);
27961  }
27962  /**
27963   * Adds a node class definition for the given type to the provided type library.
27964   *
27965   * @param {Node.constructor} nodeClass - The node class definition.
27966   * @param {number|string} type - The object type.
27967   * @param {Map<number|string,Node.constructor>} library - The type library.
27968   */
27969  addType(nodeClass, type, library) {
27970    if (library.has(type)) {
27971      warn(`Redefinition of node ${type}`);
27972      return;
27973    }
27974    if (typeof nodeClass !== "function") throw new Error(`Node class ${nodeClass.name} is not a class.`);
27975    if (typeof type === "function" || typeof type === "object") throw new Error(`Base class ${type} is not a class.`);
27976    library.set(type, nodeClass);
27977  }
27978  /**
27979   * Adds a node class definition for the given class definition to the provided type library.
27980   *
27981   * @param {Node.constructor} nodeClass - The node class definition.
27982   * @param {Node.constructor} baseClass - The class definition.
27983   * @param {WeakMap<Node.constructor, Node.constructor>} library - The type library.
27984   */
27985  addClass(nodeClass, baseClass, library) {
27986    if (library.has(baseClass)) {
27987      warn(`Redefinition of node ${baseClass.name}`);
27988      return;
27989    }
27990    if (typeof nodeClass !== "function") throw new Error(`Node class ${nodeClass.name} is not a class.`);
27991    if (typeof baseClass !== "function") throw new Error(`Base class ${baseClass.name} is not a class.`);
27992    library.set(baseClass, nodeClass);
27993  }
27994};
27995var _defaultLights = /* @__PURE__ */ new LightsNode();
27996var _weakMap = /* @__PURE__ */ new WeakMap();
27997var Lighting = class {
27998  /**
27999   * Creates a new lights node for the given array of lights.
28000   *
28001   * @param {Array<Light>} lights - The render object.
28002   * @return {LightsNode} The lights node.
28003   */
28004  createNode(lights3 = []) {
28005    return new LightsNode().setLights(lights3);
28006  }
28007  /**
28008   * Returns a lights node for the given scene and camera.
28009   *
28010   * @param {Scene} scene - The scene.
28011   * @param {Camera} camera - The camera.
28012   * @return {LightsNode} The lights node.
28013   */
28014  getNode(scene) {
28015    if (scene.isQuadMesh) return _defaultLights;
28016    let node = _weakMap.get(scene);
28017    if (node === void 0) {
28018      node = this.createNode();
28019      _weakMap.set(scene, node);
28020    }
28021    return node;
28022  }
28023};
28024var XRRenderTarget = class extends RenderTarget {
28025  /**
28026   * Constructs a new XR render target.
28027   *
28028   * @param {number} [width=1] - The width of the render target.
28029   * @param {number} [height=1] - The height of the render target.
28030   * @param {Object} [options={}] - The configuration options.
28031   */
28032  constructor(width = 1, height = 1, options = {}) {
28033    super(width, height, options);
28034    this.isXRRenderTarget = true;
28035    this._hasExternalTextures = false;
28036    this._autoAllocateDepthBuffer = true;
28037    this._isOpaqueFramebuffer = false;
28038  }
28039  copy(source) {
28040    super.copy(source);
28041    this._hasExternalTextures = source._hasExternalTextures;
28042    this._autoAllocateDepthBuffer = source._autoAllocateDepthBuffer;
28043    this._isOpaqueFramebuffer = source._isOpaqueFramebuffer;
28044    return this;
28045  }
28046};
28047var _cameraLPos = /* @__PURE__ */ new Vector3();
28048var _cameraRPos = /* @__PURE__ */ new Vector3();
28049var _contextNodeLib = /* @__PURE__ */ new WeakMap();
28050var XRManager = class extends EventDispatcher {
28051  /**
28052   * Constructs a new XR manager.
28053   *
28054   * @param {Renderer} renderer - The renderer.
28055   * @param {boolean} [multiview=false] - Enables multiview if the device supports it.
28056   */
28057  constructor(renderer, multiview = false) {
28058    super();
28059    this.enabled = false;
28060    this.isPresenting = false;
28061    this.cameraAutoUpdate = true;
28062    this._renderer = renderer;
28063    this._cameraL = new PerspectiveCamera();
28064    this._cameraL.viewport = new Vector4();
28065    this._cameraR = new PerspectiveCamera();
28066    this._cameraR.viewport = new Vector4();
28067    this._cameras = [this._cameraL, this._cameraR];
28068    this._cameraXR = new ArrayCamera();
28069    this._currentDepthNear = null;
28070    this._currentDepthFar = null;
28071    this._controllers = [];
28072    this._controllerInputSources = [];
28073    this._xrRenderTarget = null;
28074    this._layers = [];
28075    this._sessionUsesLayers = false;
28076    this._supportsGlBinding = typeof XRWebGLBinding !== "undefined";
28077    this._createXRLayer = createXRLayer.bind(this);
28078    this._gl = null;
28079    this._currentAnimationContext = null;
28080    this._currentAnimationLoop = null;
28081    this._currentPixelRatio = null;
28082    this._currentSize = new Vector2();
28083    this._onSessionEvent = onSessionEvent.bind(this);
28084    this._onSessionEnd = onSessionEnd.bind(this);
28085    this._onInputSourcesChange = onInputSourcesChange.bind(this);
28086    this._onAnimationFrame = onAnimationFrame.bind(this);
28087    this._referenceSpace = null;
28088    this._referenceSpaceType = "local-floor";
28089    this._customReferenceSpace = null;
28090    this._framebufferScaleFactor = 1;
28091    this._foveation = 1;
28092    this._session = null;
28093    this._glBaseLayer = null;
28094    this._glBinding = null;
28095    this._glProjLayer = null;
28096    this._xrFrame = null;
28097    this._supportsLayers = this._supportsGlBinding && "createProjectionLayer" in XRWebGLBinding.prototype;
28098    this._useMultiviewIfPossible = multiview;
28099    this._useMultiview = false;
28100  }
28101  /**
28102   * Returns an instance of `THREE.Group` that represents the transformation
28103   * of a XR controller in target ray space. The requested controller is defined
28104   * by the given index.
28105   *
28106   * @param {number} index - The index of the XR controller.
28107   * @return {Group} A group that represents the controller's transformation.
28108   */
28109  getController(index) {
28110    const controller = this._getController(index);
28111    return controller.getTargetRaySpace();
28112  }
28113  /**
28114   * Returns an instance of `THREE.Group` that represents the transformation
28115   * of a XR controller in grip space. The requested controller is defined
28116   * by the given index.
28117   *
28118   * @param {number} index - The index of the XR controller.
28119   * @return {Group} A group that represents the controller's transformation.
28120   */
28121  getControllerGrip(index) {
28122    const controller = this._getController(index);
28123    return controller.getGripSpace();
28124  }
28125  /**
28126   * Returns an instance of `THREE.Group` that represents the transformation
28127   * of a XR controller in hand space. The requested controller is defined
28128   * by the given index.
28129   *
28130   * @param {number} index - The index of the XR controller.
28131   * @return {Group} A group that represents the controller's transformation.
28132   */
28133  getHand(index) {
28134    const controller = this._getController(index);
28135    return controller.getHandSpace();
28136  }
28137  /**
28138   * Returns the foveation value.
28139   *
28140   * @return {number|undefined} The foveation value. Returns `undefined` if no base or projection layer is defined.
28141   */
28142  getFoveation() {
28143    if (this._glProjLayer === null && this._glBaseLayer === null) {
28144      return void 0;
28145    }
28146    return this._foveation;
28147  }
28148  /**
28149   * Sets the foveation value.
28150   *
28151   * @param {number} foveation - A number in the range `[0,1]` where `0` means no foveation (full resolution)
28152   * and `1` means maximum foveation (the edges render at lower resolution).
28153   */
28154  setFoveation(foveation) {
28155    this._foveation = foveation;
28156    if (this._glProjLayer !== null) {
28157      this._glProjLayer.fixedFoveation = foveation;
28158    }
28159    if (this._glBaseLayer !== null && this._glBaseLayer.fixedFoveation !== void 0) {
28160      this._glBaseLayer.fixedFoveation = foveation;
28161    }
28162  }
28163  /**
28164   * Returns the framebuffer scale factor.
28165   *
28166   * @return {number} The framebuffer scale factor.
28167   */
28168  getFramebufferScaleFactor() {
28169    return this._framebufferScaleFactor;
28170  }
28171  /**
28172   * Sets the framebuffer scale factor.
28173   *
28174   * This method can not be used during a XR session.
28175   *
28176   * @param {number} factor - The framebuffer scale factor.
28177   */
28178  setFramebufferScaleFactor(factor) {
28179    this._framebufferScaleFactor = factor;
28180    if (this.isPresenting === true) {
28181      warn("XRManager: Cannot change framebuffer scale while presenting.");
28182    }
28183  }
28184  /**
28185   * Returns the reference space type.
28186   *
28187   * @return {XRReferenceSpaceType} The reference space type.
28188   */
28189  getReferenceSpaceType() {
28190    return this._referenceSpaceType;
28191  }
28192  /**
28193   * Sets the reference space type.
28194   *
28195   * This method can not be used during a XR session.
28196   *
28197   * @param {XRReferenceSpaceType} type - The reference space type.
28198   */
28199  setReferenceSpaceType(type) {
28200    this._referenceSpaceType = type;
28201    if (this.isPresenting === true) {
28202      warn("XRManager: Cannot change reference space type while presenting.");
28203    }
28204  }
28205  /**
28206   * Returns the XR reference space.
28207   *
28208   * @return {XRReferenceSpace} The XR reference space.
28209   */
28210  getReferenceSpace() {
28211    return this._customReferenceSpace || this._referenceSpace;
28212  }
28213  /**
28214   * Sets a custom XR reference space.
28215   *
28216   * @param {XRReferenceSpace} space - The XR reference space.
28217   */
28218  setReferenceSpace(space) {
28219    this._customReferenceSpace = space;
28220  }
28221  /**
28222   * Returns the XR camera.
28223   *
28224   * @return {ArrayCamera} The XR camera.
28225   */
28226  getCamera() {
28227    return this._cameraXR;
28228  }
28229  /**
28230   * Returns the environment blend mode from the current XR session.
28231   *
28232   * @return {'opaque'|'additive'|'alpha-blend'|undefined} The environment blend mode. Returns `undefined` when used outside of a XR session.
28233   */
28234  getEnvironmentBlendMode() {
28235    if (this._session !== null) {
28236      return this._session.environmentBlendMode;
28237    }
28238  }
28239  /**
28240   * Returns the current XR binding.
28241   *
28242   * Creates a new binding if needed and the browser is
28243   * capable of doing so.
28244   *
28245   * @return {?XRWebGLBinding} The XR binding. Returns `null` if one cannot be created.
28246   */
28247  getBinding() {
28248    if (this._glBinding === null && this._supportsGlBinding) {
28249      this._glBinding = new XRWebGLBinding(this._session, this._gl);
28250    }
28251    return this._glBinding;
28252  }
28253  /**
28254   * Returns the current XR frame.
28255   *
28256   * @return {?XRFrame} The XR frame. Returns `null` when used outside a XR session.
28257   */
28258  getFrame() {
28259    return this._xrFrame;
28260  }
28261  /**
28262   * Returns `true` if the engine renders to a multiview target.
28263   *
28264   * @return {boolean} Whether the engine renders to a multiview render target or not.
28265   */
28266  useMultiview() {
28267    return this._useMultiview;
28268  }
28269  /**
28270   * This method can be used in XR applications to create a quadratic layer that presents a separate
28271   * rendered scene.
28272   *
28273   * @param {number} width - The width of the layer plane in world units.
28274   * @param {number} height - The height of the layer plane in world units.
28275   * @param {Vector3} translation - The position/translation of the layer plane in world units.
28276   * @param {Quaternion} quaternion - The orientation of the layer plane expressed as a quaternion.
28277   * @param {number} pixelwidth - The width of the layer's render target in pixels.
28278   * @param {number} pixelheight - The height of the layer's render target in pixels.
28279   * @param {Function} rendercall - A callback function that renders the layer. Similar to code in
28280   * the default animation loop, this method can be used to update/transform 3D object in the layer's scene.
28281   * @param {Object} [attributes={}] - Allows to configure the layer's render target.
28282   * @return {Mesh} A mesh representing the quadratic XR layer. This mesh should be added to the XR scene.
28283   */
28284  createQuadLayer(width, height, translation, quaternion, pixelwidth, pixelheight, rendercall, attributes = {}) {
28285    const geometry = new PlaneGeometry(width, height);
28286    const renderTarget = new XRRenderTarget(
28287      pixelwidth,
28288      pixelheight,
28289      {
28290        format: RGBAFormat,
28291        type: UnsignedByteType,
28292        depthTexture: new DepthTexture(
28293          pixelwidth,
28294          pixelheight,
28295          attributes.stencil ? UnsignedInt248Type : UnsignedIntType,
28296          void 0,
28297          void 0,
28298          void 0,
28299          void 0,
28300          void 0,
28301          void 0,
28302          attributes.stencil ? DepthStencilFormat : DepthFormat
28303        ),
28304        stencilBuffer: attributes.stencil,
28305        resolveDepthBuffer: false,
28306        resolveStencilBuffer: false
28307      }
28308    );
28309    renderTarget._autoAllocateDepthBuffer = true;
28310    const material = new MeshBasicMaterial({ color: 16777215, side: FrontSide });
28311    material.map = renderTarget.texture;
28312    material.map.offset.y = 1;
28313    material.map.repeat.y = -1;
28314    const plane = new Mesh(geometry, material);
28315    plane.position.copy(translation);
28316    plane.quaternion.copy(quaternion);
28317    const layer = {
28318      type: "quad",
28319      width,
28320      height,
28321      translation,
28322      quaternion,
28323      pixelwidth,
28324      pixelheight,
28325      plane,
28326      material,
28327      rendercall,
28328      renderTarget
28329    };
28330    this._layers.push(layer);
28331    if (this._session !== null) {
28332      layer.plane.material = new MeshBasicMaterial({ color: 16777215, side: FrontSide });
28333      layer.plane.material.blending = CustomBlending;
28334      layer.plane.material.blendEquation = AddEquation;
28335      layer.plane.material.blendSrc = ZeroFactor;
28336      layer.plane.material.blendDst = ZeroFactor;
28337      layer.xrlayer = this._createXRLayer(layer);
28338      const xrlayers = this._session.renderState.layers;
28339      xrlayers.unshift(layer.xrlayer);
28340      this._session.updateRenderState({ layers: xrlayers });
28341    } else {
28342      renderTarget.isXRRenderTarget = false;
28343    }
28344    return plane;
28345  }
28346  /**
28347   * This method can be used in XR applications to create a cylindrical layer that presents a separate
28348   * rendered scene.
28349   *
28350   * @param {number} radius - The radius of the cylinder in world units.
28351   * @param {number} centralAngle - The central angle of the cylinder in radians.
28352   * @param {number} aspectratio - The aspect ratio.
28353   * @param {Vector3} translation - The position/translation of the layer plane in world units.
28354   * @param {Quaternion} quaternion - The orientation of the layer plane expressed as a quaternion.
28355   * @param {number} pixelwidth - The width of the layer's render target in pixels.
28356   * @param {number} pixelheight - The height of the layer's render target in pixels.
28357   * @param {Function} rendercall - A callback function that renders the layer. Similar to code in
28358   * the default animation loop, this method can be used to update/transform 3D object in the layer's scene.
28359   * @param {Object} [attributes={}] - Allows to configure the layer's render target.
28360   * @return {Mesh} A mesh representing the cylindrical XR layer. This mesh should be added to the XR scene.
28361   */
28362  createCylinderLayer(radius, centralAngle, aspectratio, translation, quaternion, pixelwidth, pixelheight, rendercall, attributes = {}) {
28363    const geometry = new CylinderGeometry(radius, radius, radius * centralAngle / aspectratio, 64, 64, true, Math.PI - centralAngle / 2, centralAngle);
28364    const renderTarget = new XRRenderTarget(
28365      pixelwidth,
28366      pixelheight,
28367      {
28368        format: RGBAFormat,
28369        type: UnsignedByteType,
28370        depthTexture: new DepthTexture(
28371          pixelwidth,
28372          pixelheight,
28373          attributes.stencil ? UnsignedInt248Type : UnsignedIntType,
28374          void 0,
28375          void 0,
28376          void 0,
28377          void 0,
28378          void 0,
28379          void 0,
28380          attributes.stencil ? DepthStencilFormat : DepthFormat
28381        ),
28382        stencilBuffer: attributes.stencil,
28383        resolveDepthBuffer: false,
28384        resolveStencilBuffer: false
28385      }
28386    );
28387    renderTarget._autoAllocateDepthBuffer = true;
28388    const material = new MeshBasicMaterial({ color: 16777215, side: BackSide });
28389    material.map = renderTarget.texture;
28390    material.map.offset.y = 1;
28391    material.map.repeat.y = -1;
28392    const plane = new Mesh(geometry, material);
28393    plane.position.copy(translation);
28394    plane.quaternion.copy(quaternion);
28395    const layer = {
28396      type: "cylinder",
28397      radius,
28398      centralAngle,
28399      aspectratio,
28400      translation,
28401      quaternion,
28402      pixelwidth,
28403      pixelheight,
28404      plane,
28405      material,
28406      rendercall,
28407      renderTarget
28408    };
28409    this._layers.push(layer);
28410    if (this._session !== null) {
28411      layer.plane.material = new MeshBasicMaterial({ color: 16777215, side: BackSide });
28412      layer.plane.material.blending = CustomBlending;
28413      layer.plane.material.blendEquation = AddEquation;
28414      layer.plane.material.blendSrc = ZeroFactor;
28415      layer.plane.material.blendDst = ZeroFactor;
28416      layer.xrlayer = this._createXRLayer(layer);
28417      const xrlayers = this._session.renderState.layers;
28418      xrlayers.unshift(layer.xrlayer);
28419      this._session.updateRenderState({ layers: xrlayers });
28420    } else {
28421      renderTarget.isXRRenderTarget = false;
28422    }
28423    return plane;
28424  }
28425  /**
28426   * Renders the XR layers that have been previously added to the scene.
28427   *
28428   * This method is usually called in your animation loop before rendering
28429   * the actual scene via `renderer.render( scene, camera );`.
28430   */
28431  renderLayers() {
28432    const translationObject = new Vector3();
28433    const quaternionObject = new Quaternion();
28434    const renderer = this._renderer;
28435    const wasPresenting = this.isPresenting;
28436    this.isPresenting = false;
28437    const rendererSize = new Vector2();
28438    renderer.getSize(rendererSize);
28439    const currentRenderTarget = renderer.getRenderTarget();
28440    for (const layer of this._layers) {
28441      layer.renderTarget.isXRRenderTarget = this._session !== null;
28442      layer.renderTarget._hasExternalTextures = layer.renderTarget.isXRRenderTarget;
28443      const currentContextNode = renderer.contextNode;
28444      let contextNode;
28445      if (layer.renderTarget.isXRRenderTarget && this._sessionUsesLayers) {
28446        layer.xrlayer.transform = new XRRigidTransform(layer.plane.getWorldPosition(translationObject), layer.plane.getWorldQuaternion(quaternionObject));
28447        const glSubImage = this._glBinding.getSubImage(layer.xrlayer, this._xrFrame);
28448        renderer.backend.setXRRenderTargetTextures(
28449          layer.renderTarget,
28450          glSubImage.colorTexture,
28451          void 0
28452        );
28453        renderer._setXRLayerSize(layer.renderTarget.width, layer.renderTarget.height);
28454        contextNode = _contextNodeLib.get(currentContextNode);
28455        if (contextNode === void 0) {
28456          contextNode = currentContextNode.context({
28457            getOutput: (outputNode) => {
28458              return renderOutput(outputNode, renderer.toneMapping, renderer.outputColorSpace);
28459            }
28460          });
28461          _contextNodeLib.set(currentContextNode, contextNode);
28462        }
28463      } else {
28464        contextNode = currentContextNode;
28465      }
28466      renderer.contextNode = contextNode;
28467      renderer.setRenderTarget(layer.renderTarget);
28468      layer.rendercall();
28469      renderer.contextNode = currentContextNode;
28470    }
28471    renderer.setRenderTarget(currentRenderTarget);
28472    renderer._setXRLayerSize(rendererSize.x, rendererSize.y);
28473    this.isPresenting = wasPresenting;
28474  }
28475  /**
28476   * Returns the current XR session.
28477   *
28478   * @return {?XRSession} The XR session. Returns `null` when used outside a XR session.
28479   */
28480  getSession() {
28481    return this._session;
28482  }
28483  /**
28484   * After a XR session has been requested usually with one of the `*Button` modules, it
28485   * is injected into the renderer with this method. This method triggers the start of
28486   * the actual XR rendering.
28487   *
28488   * @async
28489   * @param {XRSession} session - The XR session to set.
28490   * @return {Promise} A Promise that resolves when the session has been set.
28491   */
28492  async setSession(session) {
28493    const renderer = this._renderer;
28494    const backend = renderer.backend;
28495    this._gl = renderer.getContext();
28496    const gl = this._gl;
28497    const attributes = gl.getContextAttributes();
28498    this._session = session;
28499    if (session !== null) {
28500      if (backend.isWebGPUBackend === true) throw new Error('THREE.XRManager: XR is currently not supported with a WebGPU backend. Use WebGL by passing "{ forceWebGL: true }" to the constructor of the renderer.');
28501      session.addEventListener("select", this._onSessionEvent);
28502      session.addEventListener("selectstart", this._onSessionEvent);
28503      session.addEventListener("selectend", this._onSessionEvent);
28504      session.addEventListener("squeeze", this._onSessionEvent);
28505      session.addEventListener("squeezestart", this._onSessionEvent);
28506      session.addEventListener("squeezeend", this._onSessionEvent);
28507      session.addEventListener("end", this._onSessionEnd);
28508      session.addEventListener("inputsourceschange", this._onInputSourcesChange);
28509      await backend.makeXRCompatible();
28510      this._currentPixelRatio = renderer.getPixelRatio();
28511      renderer.getSize(this._currentSize);
28512      this._currentAnimationContext = renderer._animation.getContext();
28513      this._currentAnimationLoop = renderer._animation.getAnimationLoop();
28514      renderer._animation.stop();
28515      if (this._supportsLayers === true) {
28516        let depthFormat = null;
28517        let depthType = null;
28518        let glDepthFormat = null;
28519        if (renderer.depth) {
28520          glDepthFormat = renderer.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
28521          depthFormat = renderer.stencil ? DepthStencilFormat : DepthFormat;
28522          depthType = renderer.stencil ? UnsignedInt248Type : UnsignedIntType;
28523        }
28524        const projectionlayerInit = {
28525          colorFormat: gl.RGBA8,
28526          depthFormat: glDepthFormat,
28527          scaleFactor: this._framebufferScaleFactor,
28528          clearOnAccess: false
28529        };
28530        if (this._useMultiviewIfPossible && renderer.hasFeature("OVR_multiview2")) {
28531          projectionlayerInit.textureType = "texture-array";
28532          this._useMultiview = true;
28533        }
28534        this._glBinding = this.getBinding();
28535        const glProjLayer = this._glBinding.createProjectionLayer(projectionlayerInit);
28536        const layersArray = [glProjLayer];
28537        this._glProjLayer = glProjLayer;
28538        renderer.setPixelRatio(1);
28539        renderer._setXRLayerSize(glProjLayer.textureWidth, glProjLayer.textureHeight);
28540        const depth3 = this._useMultiview ? 2 : 1;
28541        const depthTexture = new DepthTexture(glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, void 0, void 0, void 0, void 0, void 0, void 0, depthFormat, depth3);
28542        this._xrRenderTarget = new XRRenderTarget(
28543          glProjLayer.textureWidth,
28544          glProjLayer.textureHeight,
28545          {
28546            format: RGBAFormat,
28547            type: UnsignedByteType,
28548            colorSpace: renderer.outputColorSpace,
28549            depthTexture,
28550            stencilBuffer: renderer.stencil,
28551            samples: attributes.antialias ? 4 : 0,
28552            resolveDepthBuffer: glProjLayer.ignoreDepthValues === false,
28553            resolveStencilBuffer: glProjLayer.ignoreDepthValues === false,
28554            depth: this._useMultiview ? 2 : 1,
28555            multiview: this._useMultiview
28556          }
28557        );
28558        this._xrRenderTarget._hasExternalTextures = true;
28559        this._xrRenderTarget.depth = this._useMultiview ? 2 : 1;
28560        this._sessionUsesLayers = session.enabledFeatures.includes("layers");
28561        this._referenceSpace = await session.requestReferenceSpace(this.getReferenceSpaceType());
28562        if (this._sessionUsesLayers) {
28563          for (const layer of this._layers) {
28564            layer.plane.material = new MeshBasicMaterial({ color: 16777215, side: layer.type === "cylinder" ? BackSide : FrontSide });
28565            layer.plane.material.blending = CustomBlending;
28566            layer.plane.material.blendEquation = AddEquation;
28567            layer.plane.material.blendSrc = ZeroFactor;
28568            layer.plane.material.blendDst = ZeroFactor;
28569            layer.xrlayer = this._createXRLayer(layer);
28570            layersArray.unshift(layer.xrlayer);
28571          }
28572        }
28573        session.updateRenderState({ layers: layersArray });
28574      } else {
28575        const layerInit = {
28576          antialias: renderer.currentSamples > 0,
28577          alpha: true,
28578          depth: renderer.depth,
28579          stencil: renderer.stencil,
28580          framebufferScaleFactor: this.getFramebufferScaleFactor()
28581        };
28582        const glBaseLayer = new XRWebGLLayer(session, gl, layerInit);
28583        this._glBaseLayer = glBaseLayer;
28584        session.updateRenderState({ baseLayer: glBaseLayer });
28585        renderer.setPixelRatio(1);
28586        renderer._setXRLayerSize(glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight);
28587        this._xrRenderTarget = new XRRenderTarget(
28588          glBaseLayer.framebufferWidth,
28589          glBaseLayer.framebufferHeight,
28590          {
28591            format: RGBAFormat,
28592            type: UnsignedByteType,
28593            colorSpace: renderer.outputColorSpace,
28594            stencilBuffer: renderer.stencil,
28595            resolveDepthBuffer: glBaseLayer.ignoreDepthValues === false,
28596            resolveStencilBuffer: glBaseLayer.ignoreDepthValues === false
28597          }
28598        );
28599        this._xrRenderTarget._isOpaqueFramebuffer = true;
28600        this._referenceSpace = await session.requestReferenceSpace(this.getReferenceSpaceType());
28601      }
28602      this.setFoveation(this.getFoveation());
28603      renderer._animation.setAnimationLoop(this._onAnimationFrame);
28604      renderer._animation.setContext(session);
28605      renderer._animation.start();
28606      this.isPresenting = true;
28607      this.dispatchEvent({ type: "sessionstart" });
28608    }
28609  }
28610  /**
28611   * This method is called by the renderer per frame and updates the XR camera
28612   * and it sub cameras based on the given camera. The given camera is the "user"
28613   * camera created on application level and used for non-XR rendering.
28614   *
28615   * @param {PerspectiveCamera} camera - The camera.
28616   */
28617  updateCamera(camera) {
28618    const session = this._session;
28619    if (session === null) return;
28620    const depthNear = camera.near;
28621    const depthFar = camera.far;
28622    const cameraXR = this._cameraXR;
28623    const cameraL = this._cameraL;
28624    const cameraR = this._cameraR;
28625    cameraXR.near = cameraR.near = cameraL.near = depthNear;
28626    cameraXR.far = cameraR.far = cameraL.far = depthFar;
28627    cameraXR.isMultiViewCamera = this._useMultiview;
28628    if (this._currentDepthNear !== cameraXR.near || this._currentDepthFar !== cameraXR.far) {
28629      session.updateRenderState({
28630        depthNear: cameraXR.near,
28631        depthFar: cameraXR.far
28632      });
28633      this._currentDepthNear = cameraXR.near;
28634      this._currentDepthFar = cameraXR.far;
28635    }
28636    cameraXR.layers.mask = camera.layers.mask | 6;
28637    cameraL.layers.mask = cameraXR.layers.mask & -5;
28638    cameraR.layers.mask = cameraXR.layers.mask & -3;
28639    const parent = camera.parent;
28640    const cameras = cameraXR.cameras;
28641    updateCamera(cameraXR, parent);
28642    for (let i = 0; i < cameras.length; i++) {
28643      updateCamera(cameras[i], parent);
28644    }
28645    if (cameras.length === 2) {
28646      setProjectionFromUnion(cameraXR, cameraL, cameraR);
28647    } else {
28648      cameraXR.projectionMatrix.copy(cameraL.projectionMatrix);
28649    }
28650    updateUserCamera(camera, cameraXR, parent);
28651  }
28652  /**
28653   * Returns a WebXR controller for the given controller index.
28654   *
28655   * @private
28656   * @param {number} index - The controller index.
28657   * @return {WebXRController} The XR controller.
28658   */
28659  _getController(index) {
28660    let controller = this._controllers[index];
28661    if (controller === void 0) {
28662      controller = new WebXRController();
28663      this._controllers[index] = controller;
28664    }
28665    return controller;
28666  }
28667};
28668function setProjectionFromUnion(camera, cameraL, cameraR) {
28669  _cameraLPos.setFromMatrixPosition(cameraL.matrixWorld);
28670  _cameraRPos.setFromMatrixPosition(cameraR.matrixWorld);
28671  const ipd = _cameraLPos.distanceTo(_cameraRPos);
28672  const projL = cameraL.projectionMatrix.elements;
28673  const projR = cameraR.projectionMatrix.elements;
28674  const near = projL[14] / (projL[10] - 1);
28675  const far = projL[14] / (projL[10] + 1);
28676  const topFov = (projL[9] + 1) / projL[5];
28677  const bottomFov = (projL[9] - 1) / projL[5];
28678  const leftFov = (projL[8] - 1) / projL[0];
28679  const rightFov = (projR[8] + 1) / projR[0];
28680  const left = near * leftFov;
28681  const right = near * rightFov;
28682  const zOffset = ipd / (-leftFov + rightFov);
28683  const xOffset = zOffset * -leftFov;
28684  cameraL.matrixWorld.decompose(camera.position, camera.quaternion, camera.scale);
28685  camera.translateX(xOffset);
28686  camera.translateZ(zOffset);
28687  camera.matrixWorld.compose(camera.position, camera.quaternion, camera.scale);
28688  camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
28689  if (projL[10] === -1) {
28690    camera.projectionMatrix.copy(cameraL.projectionMatrix);
28691    camera.projectionMatrixInverse.copy(cameraL.projectionMatrixInverse);
28692  } else {
28693    const near2 = near + zOffset;
28694    const far2 = far + zOffset;
28695    const left2 = left - xOffset;
28696    const right2 = right + (ipd - xOffset);
28697    const top2 = topFov * far / far2 * near2;
28698    const bottom2 = bottomFov * far / far2 * near2;
28699    camera.projectionMatrix.makePerspective(left2, right2, top2, bottom2, near2, far2);
28700    camera.projectionMatrixInverse.copy(camera.projectionMatrix).invert();
28701  }
28702}
28703function updateCamera(camera, parent) {
28704  if (parent === null) {
28705    camera.matrixWorld.copy(camera.matrix);
28706  } else {
28707    camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix);
28708  }
28709  camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
28710}
28711function updateUserCamera(camera, cameraXR, parent) {
28712  if (parent === null) {
28713    camera.matrix.copy(cameraXR.matrixWorld);
28714  } else {
28715    camera.matrix.copy(parent.matrixWorld);
28716    camera.matrix.invert();
28717    camera.matrix.multiply(cameraXR.matrixWorld);
28718  }
28719  camera.matrix.decompose(camera.position, camera.quaternion, camera.scale);
28720  camera.updateMatrixWorld(true);
28721  camera.projectionMatrix.copy(cameraXR.projectionMatrix);
28722  camera.projectionMatrixInverse.copy(cameraXR.projectionMatrixInverse);
28723  if (camera.isPerspectiveCamera) {
28724    camera.fov = RAD2DEG * 2 * Math.atan(1 / camera.projectionMatrix.elements[5]);
28725    camera.zoom = 1;
28726  }
28727}
28728function onSessionEvent(event) {
28729  const controllerIndex = this._controllerInputSources.indexOf(event.inputSource);
28730  if (controllerIndex === -1) {
28731    return;
28732  }
28733  const controller = this._controllers[controllerIndex];
28734  if (controller !== void 0) {
28735    const referenceSpace = this.getReferenceSpace();
28736    controller.update(event.inputSource, event.frame, referenceSpace);
28737    controller.dispatchEvent({ type: event.type, data: event.inputSource });
28738  }
28739}
28740function onSessionEnd() {
28741  const session = this._session;
28742  const renderer = this._renderer;
28743  session.removeEventListener("select", this._onSessionEvent);
28744  session.removeEventListener("selectstart", this._onSessionEvent);
28745  session.removeEventListener("selectend", this._onSessionEvent);
28746  session.removeEventListener("squeeze", this._onSessionEvent);
28747  session.removeEventListener("squeezestart", this._onSessionEvent);
28748  session.removeEventListener("squeezeend", this._onSessionEvent);
28749  session.removeEventListener("end", this._onSessionEnd);
28750  session.removeEventListener("inputsourceschange", this._onInputSourcesChange);
28751  for (let i = 0; i < this._controllers.length; i++) {
28752    const inputSource = this._controllerInputSources[i];
28753    if (inputSource === null) continue;
28754    this._controllerInputSources[i] = null;
28755    this._controllers[i].disconnect(inputSource);
28756  }
28757  this._currentDepthNear = null;
28758  this._currentDepthFar = null;
28759  renderer._resetXRState();
28760  this._session = null;
28761  this._xrRenderTarget = null;
28762  this._glBinding = null;
28763  this._glBaseLayer = null;
28764  this._glProjLayer = null;
28765  if (this._sessionUsesLayers === true) {
28766    for (const layer of this._layers) {
28767      layer.renderTarget = new XRRenderTarget(
28768        layer.pixelwidth,
28769        layer.pixelheight,
28770        {
28771          format: RGBAFormat,
28772          type: UnsignedByteType,
28773          depthTexture: new DepthTexture(
28774            layer.pixelwidth,
28775            layer.pixelheight,
28776            layer.stencilBuffer ? UnsignedInt248Type : UnsignedIntType,
28777            void 0,
28778            void 0,
28779            void 0,
28780            void 0,
28781            void 0,
28782            void 0,
28783            layer.stencilBuffer ? DepthStencilFormat : DepthFormat
28784          ),
28785          stencilBuffer: layer.stencilBuffer,
28786          resolveDepthBuffer: false,
28787          resolveStencilBuffer: false
28788        }
28789      );
28790      layer.renderTarget.isXRRenderTarget = false;
28791      layer.plane.material = layer.material;
28792      layer.material.map = layer.renderTarget.texture;
28793      layer.material.map.offset.y = 1;
28794      layer.material.map.repeat.y = -1;
28795      delete layer.xrlayer;
28796    }
28797  }
28798  this.isPresenting = false;
28799  this._useMultiview = false;
28800  renderer._animation.stop();
28801  renderer._animation.setAnimationLoop(this._currentAnimationLoop);
28802  renderer._animation.setContext(this._currentAnimationContext);
28803  renderer._animation.start();
28804  renderer.setPixelRatio(this._currentPixelRatio);
28805  renderer.setSize(this._currentSize.width, this._currentSize.height, false);
28806  this.dispatchEvent({ type: "sessionend" });
28807}
28808function onInputSourcesChange(event) {
28809  const controllers = this._controllers;
28810  const controllerInputSources = this._controllerInputSources;
28811  for (let i = 0; i < event.removed.length; i++) {
28812    const inputSource = event.removed[i];
28813    const index = controllerInputSources.indexOf(inputSource);
28814    if (index >= 0) {
28815      controllerInputSources[index] = null;
28816      controllers[index].disconnect(inputSource);
28817    }
28818  }
28819  for (let i = 0; i < event.added.length; i++) {
28820    const inputSource = event.added[i];
28821    let controllerIndex = controllerInputSources.indexOf(inputSource);
28822    if (controllerIndex === -1) {
28823      for (let i2 = 0; i2 < controllers.length; i2++) {
28824        if (i2 >= controllerInputSources.length) {
28825          controllerInputSources.push(inputSource);
28826          controllerIndex = i2;
28827          break;
28828        } else if (controllerInputSources[i2] === null) {
28829          controllerInputSources[i2] = inputSource;
28830          controllerIndex = i2;
28831          break;
28832        }
28833      }
28834      if (controllerIndex === -1) break;
28835    }
28836    const controller = controllers[controllerIndex];
28837    if (controller) {
28838      controller.connect(inputSource);
28839    }
28840  }
28841}
28842function createXRLayer(layer) {
28843  if (layer.type === "quad") {
28844    return this._glBinding.createQuadLayer({
28845      transform: new XRRigidTransform(layer.translation, layer.quaternion),
28846      width: layer.width / 2,
28847      height: layer.height / 2,
28848      space: this._referenceSpace,
28849      viewPixelWidth: layer.pixelwidth,
28850      viewPixelHeight: layer.pixelheight,
28851      clearOnAccess: false
28852    });
28853  } else {
28854    return this._glBinding.createCylinderLayer({
28855      transform: new XRRigidTransform(layer.translation, layer.quaternion),
28856      radius: layer.radius,
28857      centralAngle: layer.centralAngle,
28858      aspectRatio: layer.aspectRatio,
28859      space: this._referenceSpace,
28860      viewPixelWidth: layer.pixelwidth,
28861      viewPixelHeight: layer.pixelheight,
28862      clearOnAccess: false
28863    });
28864  }
28865}
28866function onAnimationFrame(time3, frame) {
28867  if (frame === void 0) return;
28868  const cameraXR = this._cameraXR;
28869  const renderer = this._renderer;
28870  const backend = renderer.backend;
28871  const glBaseLayer = this._glBaseLayer;
28872  const referenceSpace = this.getReferenceSpace();
28873  const pose = frame.getViewerPose(referenceSpace);
28874  this._xrFrame = frame;
28875  if (pose !== null) {
28876    const views = pose.views;
28877    if (this._glBaseLayer !== null) {
28878      backend.setXRTarget(glBaseLayer.framebuffer);
28879    }
28880    let cameraXRNeedsUpdate = false;
28881    if (views.length !== cameraXR.cameras.length) {
28882      cameraXR.cameras.length = 0;
28883      cameraXRNeedsUpdate = true;
28884    }
28885    for (let i = 0; i < views.length; i++) {
28886      const view = views[i];
28887      let viewport3;
28888      if (this._supportsLayers === true) {
28889        const glSubImage = this._glBinding.getViewSubImage(this._glProjLayer, view);
28890        viewport3 = glSubImage.viewport;
28891        if (i === 0) {
28892          backend.setXRRenderTargetTextures(
28893            this._xrRenderTarget,
28894            glSubImage.colorTexture,
28895            this._glProjLayer.ignoreDepthValues && !this._useMultiview ? void 0 : glSubImage.depthStencilTexture
28896          );
28897        }
28898      } else {
28899        viewport3 = glBaseLayer.getViewport(view);
28900      }
28901      let camera = this._cameras[i];
28902      if (camera === void 0) {
28903        camera = new PerspectiveCamera();
28904        camera.layers.enable(i);
28905        camera.viewport = new Vector4();
28906        this._cameras[i] = camera;
28907      }
28908      camera.matrix.fromArray(view.transform.matrix);
28909      camera.matrix.decompose(camera.position, camera.quaternion, camera.scale);
28910      camera.projectionMatrix.fromArray(view.projectionMatrix);
28911      camera.projectionMatrixInverse.copy(camera.projectionMatrix).invert();
28912      camera.viewport.set(viewport3.x, viewport3.y, viewport3.width, viewport3.height);
28913      if (i === 0) {
28914        cameraXR.matrix.copy(camera.matrix);
28915        cameraXR.matrix.decompose(cameraXR.position, cameraXR.quaternion, cameraXR.scale);
28916      }
28917      if (cameraXRNeedsUpdate === true) {
28918        cameraXR.cameras.push(camera);
28919      }
28920    }
28921    renderer.setOutputRenderTarget(this._xrRenderTarget);
28922  }
28923  for (let i = 0; i < this._controllers.length; i++) {
28924    const inputSource = this._controllerInputSources[i];
28925    const controller = this._controllers[i];
28926    if (inputSource !== null && controller !== void 0) {
28927      controller.update(inputSource, frame, referenceSpace);
28928    }
28929  }
28930  if (this._currentAnimationLoop) this._currentAnimationLoop(time3, frame);
28931  if (frame.detectedPlanes) {
28932    this.dispatchEvent({ type: "planesdetected", data: frame });
28933  }
28934  this._xrFrame = null;
28935}
28936var CanvasTarget = class extends EventDispatcher {
28937  /**
28938   * Constructs a new CanvasTarget.
28939   *
28940   * @param {HTMLCanvasElement|OffscreenCanvas} domElement - The canvas element to render to.
28941   */
28942  constructor(domElement) {
28943    super();
28944    this.domElement = domElement;
28945    this._pixelRatio = 1;
28946    this._width = this.domElement.width;
28947    this._height = this.domElement.height;
28948    this._viewport = new Vector4(0, 0, this._width, this._height);
28949    this._scissor = new Vector4(0, 0, this._width, this._height);
28950    this._scissorTest = false;
28951    this.colorTexture = new FramebufferTexture();
28952    this.depthTexture = new DepthTexture();
28953  }
28954  /**
28955   * Returns the pixel ratio.
28956   *
28957   * @return {number} The pixel ratio.
28958   */
28959  getPixelRatio() {
28960    return this._pixelRatio;
28961  }
28962  /**
28963   * Returns the drawing buffer size in physical pixels. This method honors the pixel ratio.
28964   *
28965   * @param {Vector2} target - The method writes the result in this target object.
28966   * @return {Vector2} The drawing buffer size.
28967   */
28968  getDrawingBufferSize(target) {
28969    return target.set(this._width * this._pixelRatio, this._height * this._pixelRatio).floor();
28970  }
28971  /**
28972   * Returns the renderer's size in logical pixels. This method does not honor the pixel ratio.
28973   *
28974   * @param {Vector2} target - The method writes the result in this target object.
28975   * @return {Vector2} The renderer's size in logical pixels.
28976   */
28977  getSize(target) {
28978    return target.set(this._width, this._height);
28979  }
28980  /**
28981   * Sets the given pixel ratio and resizes the canvas if necessary.
28982   *
28983   * @param {number} [value=1] - The pixel ratio.
28984   */
28985  setPixelRatio(value = 1) {
28986    if (this._pixelRatio === value) return;
28987    this._pixelRatio = value;
28988    this.setSize(this._width, this._height, false);
28989  }
28990  /**
28991   * This method allows to define the drawing buffer size by specifying
28992   * width, height and pixel ratio all at once. The size of the drawing
28993   * buffer is computed with this formula:
28994   * ```js
28995   * size.x = width * pixelRatio;
28996   * size.y = height * pixelRatio;
28997   * ```
28998   *
28999   * @param {number} width - The width in logical pixels.
29000   * @param {number} height - The height in logical pixels.
29001   * @param {number} pixelRatio - The pixel ratio.
29002   */
29003  setDrawingBufferSize(width, height, pixelRatio) {
29004    if (this.xr && this.xr.isPresenting) return;
29005    this._width = width;
29006    this._height = height;
29007    this._pixelRatio = pixelRatio;
29008    this.domElement.width = Math.floor(width * pixelRatio);
29009    this.domElement.height = Math.floor(height * pixelRatio);
29010    this.setViewport(0, 0, width, height);
29011    this._dispatchResize();
29012  }
29013  /**
29014   * Sets the size of the renderer.
29015   *
29016   * @param {number} width - The width in logical pixels.
29017   * @param {number} height - The height in logical pixels.
29018   * @param {boolean} [updateStyle=true] - Whether to update the `style` attribute of the canvas or not.
29019   */
29020  setSize(width, height, updateStyle = true) {
29021    if (this.xr && this.xr.isPresenting) return;
29022    this._width = width;
29023    this._height = height;
29024    this.domElement.width = Math.floor(width * this._pixelRatio);
29025    this.domElement.height = Math.floor(height * this._pixelRatio);
29026    if (updateStyle === true) {
29027      this.domElement.style.width = width + "px";
29028      this.domElement.style.height = height + "px";
29029    }
29030    this.setViewport(0, 0, width, height);
29031    this._dispatchResize();
29032  }
29033  /**
29034   * Returns the scissor rectangle.
29035   *
29036   * @param {Vector4} target - The method writes the result in this target object.
29037   * @return {Vector4} The scissor rectangle.
29038   */
29039  getScissor(target) {
29040    const scissor = this._scissor;
29041    target.x = scissor.x;
29042    target.y = scissor.y;
29043    target.width = scissor.width;
29044    target.height = scissor.height;
29045    return target;
29046  }
29047  /**
29048   * Defines the scissor rectangle.
29049   *
29050   * @param {number | Vector4} x - The horizontal coordinate for the lower left corner of the box in logical pixel unit.
29051   * Instead of passing four arguments, the method also works with a single four-dimensional vector.
29052   * @param {number} y - The vertical coordinate for the lower left corner of the box in logical pixel unit.
29053   * @param {number} width - The width of the scissor box in logical pixel unit.
29054   * @param {number} height - The height of the scissor box in logical pixel unit.
29055   */
29056  setScissor(x, y, width, height) {
29057    const scissor = this._scissor;
29058    if (x.isVector4) {
29059      scissor.copy(x);
29060    } else {
29061      scissor.set(x, y, width, height);
29062    }
29063  }
29064  /**
29065   * Returns the scissor test value.
29066   *
29067   * @return {boolean} Whether the scissor test should be enabled or not.
29068   */
29069  getScissorTest() {
29070    return this._scissorTest;
29071  }
29072  /**
29073   * Defines the scissor test.
29074   *
29075   * @param {boolean} boolean - Whether the scissor test should be enabled or not.
29076   */
29077  setScissorTest(boolean) {
29078    this._scissorTest = boolean;
29079  }
29080  /**
29081   * Returns the viewport definition.
29082   *
29083   * @param {Vector4} target - The method writes the result in this target object.
29084   * @return {Vector4} The viewport definition.
29085   */
29086  getViewport(target) {
29087    return target.copy(this._viewport);
29088  }
29089  /**
29090   * Defines the viewport.
29091   *
29092   * @param {number | Vector4} x - The horizontal coordinate for the lower left corner of the viewport origin in logical pixel unit.
29093   * @param {number} y - The vertical coordinate for the lower left corner of the viewport origin  in logical pixel unit.
29094   * @param {number} width - The width of the viewport in logical pixel unit.
29095   * @param {number} height - The height of the viewport in logical pixel unit.
29096   * @param {number} minDepth - The minimum depth value of the viewport. WebGPU only.
29097   * @param {number} maxDepth - The maximum depth value of the viewport. WebGPU only.
29098   */
29099  setViewport(x, y, width, height, minDepth = 0, maxDepth = 1) {
29100    const viewport3 = this._viewport;
29101    if (x.isVector4) {
29102      viewport3.copy(x);
29103    } else {
29104      viewport3.set(x, y, width, height);
29105    }
29106    viewport3.minDepth = minDepth;
29107    viewport3.maxDepth = maxDepth;
29108  }
29109  /**
29110   * Dispatches the resize event.
29111   *
29112   * @private
29113   */
29114  _dispatchResize() {
29115    this.dispatchEvent({ type: "resize" });
29116  }
29117  /**
29118   * Frees the GPU-related resources allocated by this instance. Call this
29119   * method whenever this instance is no longer used in your app.
29120   *
29121   * @fires RenderTarget#dispose
29122   */
29123  dispose() {
29124    this.dispatchEvent({ type: "dispose" });
29125  }
29126};
29127var _scene = /* @__PURE__ */ new Scene();
29128var _drawingBufferSize = /* @__PURE__ */ new Vector2();
29129var _screen = /* @__PURE__ */ new Vector4();
29130var _frustum = /* @__PURE__ */ new Frustum();
29131var _frustumArray = /* @__PURE__ */ new FrustumArray();
29132var _projScreenMatrix = /* @__PURE__ */ new Matrix4();
29133var _vector4 = /* @__PURE__ */ new Vector4();
29134var _shadowSide = { [FrontSide]: BackSide, [BackSide]: FrontSide, [DoubleSide]: DoubleSide };
29135var Renderer = class {
29136  /**
29137   * Renderer options.
29138   *
29139   * @typedef {Object} Renderer~Options
29140   * @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
29141   * @property {boolean} [reversedDepthBuffer=false] - Whether reversed depth buffer is enabled or not.
29142   * @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
29143   * @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
29144   * @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
29145   * @property {boolean} [antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
29146   * @property {number} [samples=0] - When `antialias` is `true`, `4` samples are used by default. This parameter can set to any other integer value than 0
29147   * to overwrite the default.
29148   * @property {?Function} [getFallback=null] - This callback function can be used to provide a fallback backend, if the primary backend can't be targeted.
29149   * @property {number} [outputBufferType=HalfFloatType] - Defines the type of output buffers. The default `HalfFloatType` is recommend for best
29150   * quality. To save memory and bandwidth, `UnsignedByteType` might be used. This will reduce rendering quality though.
29151   * @property {boolean} [multiview=false] - If set to `true`, the renderer will use multiview during WebXR rendering if supported.
29152   */
29153  /**
29154  	 * Constructs a new renderer.
29155  	 *
29156  	 * @param {Backend} backend - The backend the renderer is targeting (e.g. WebGPU or WebGL 2).
29157  	 * @param {Renderer~Options} [parameters] - The configuration parameter.
29158  
29159  	 */
29160  constructor(backend, parameters = {}) {
29161    this.isRenderer = true;
29162    const {
29163      logarithmicDepthBuffer = false,
29164      reversedDepthBuffer = false,
29165      alpha = true,
29166      depth: depth3 = true,
29167      stencil = false,
29168      antialias = false,
29169      samples = 0,
29170      getFallback = null,
29171      outputBufferType = HalfFloatType,
29172      multiview = false
29173    } = parameters;
29174    this.backend = backend;
29175    this.autoClear = true;
29176    this.autoClearColor = true;
29177    this.autoClearDepth = true;
29178    this.autoClearStencil = true;
29179    this.alpha = alpha;
29180    this.logarithmicDepthBuffer = logarithmicDepthBuffer;
29181    this.reversedDepthBuffer = reversedDepthBuffer;
29182    this.outputColorSpace = SRGBColorSpace;
29183    this.toneMapping = NoToneMapping;
29184    this.toneMappingExposure = 1;
29185    this.sortObjects = true;
29186    this.depth = depth3;
29187    this.stencil = stencil;
29188    this.info = new Info();
29189    this.contextNode = context();
29190    this.library = new NodeLibrary();
29191    this.lighting = new Lighting();
29192    this._samples = samples || antialias === true ? 4 : 0;
29193    this._onCanvasTargetResize = this._onCanvasTargetResize.bind(this);
29194    this._canvasTarget = new CanvasTarget(backend.getDomElement());
29195    this._canvasTarget.addEventListener("resize", this._onCanvasTargetResize);
29196    this._canvasTarget.isDefaultCanvasTarget = true;
29197    this._inspector = new InspectorBase();
29198    this._inspector.setRenderer(this);
29199    this._getFallback = getFallback;
29200    this._attributes = null;
29201    this._geometries = null;
29202    this._nodes = null;
29203    this._animation = null;
29204    this._bindings = null;
29205    this._objects = null;
29206    this._pipelines = null;
29207    this._bundles = null;
29208    this._renderLists = null;
29209    this._renderContexts = null;
29210    this._textures = null;
29211    this._background = null;
29212    this._quadCache = /* @__PURE__ */ new Map();
29213    this._currentRenderContext = null;
29214    this._opaqueSort = null;
29215    this._transparentSort = null;
29216    this._frameBufferTargets = /* @__PURE__ */ new Map();
29217    const alphaClear = this.alpha === true ? 0 : 1;
29218    this._clearColor = new Color4(0, 0, 0, alphaClear);
29219    this._clearDepth = 1;
29220    this._clearStencil = 0;
29221    this._renderTarget = null;
29222    this._activeCubeFace = 0;
29223    this._activeMipmapLevel = 0;
29224    this._outputRenderTarget = null;
29225    this._mrt = null;
29226    this._renderObjectFunction = null;
29227    this._currentRenderObjectFunction = null;
29228    this._currentRenderBundle = null;
29229    this._handleObjectFunction = this._renderObjectDirect;
29230    this._isDeviceLost = false;
29231    this.onDeviceLost = this._onDeviceLost;
29232    this._outputBufferType = outputBufferType;
29233    this._cacheShadowNodes = /* @__PURE__ */ new WeakMap();
29234    this._initialized = false;
29235    this._callDepth = -1;
29236    this._initPromise = null;
29237    this._compilationPromises = null;
29238    this.transparent = true;
29239    this.opaque = true;
29240    this.shadowMap = {
29241      enabled: false,
29242      transmitted: false,
29243      type: PCFShadowMap
29244    };
29245    this.xr = new XRManager(this, multiview);
29246    this.debug = {
29247      checkShaderErrors: true,
29248      onShaderError: null,
29249      getShaderAsync: async (scene, camera, object) => {
29250        await this.compileAsync(scene, camera);
29251        const renderList = this._renderLists.get(scene, camera);
29252        const renderContext = this._renderContexts.get(this._renderTarget, this._mrt);
29253        const material = scene.overrideMaterial || object.material;
29254        const renderObject = this._objects.get(object, material, scene, camera, renderList.lightsNode, renderContext, renderContext.clippingContext);
29255        const { fragmentShader, vertexShader } = renderObject.getNodeBuilderState();
29256        return { fragmentShader, vertexShader };
29257      }
29258    };
29259  }
29260  /**
29261   * Initializes the renderer so it is ready for usage.
29262   *
29263   * @async
29264   * @return {Promise<this>} A Promise that resolves when the renderer has been initialized.
29265   */
29266  async init() {
29267    if (this._initPromise !== null) {
29268      return this._initPromise;
29269    }
29270    this._initPromise = new Promise(async (resolve, reject) => {
29271      let backend = this.backend;
29272      try {
29273        await backend.init(this);
29274      } catch (error2) {
29275        if (this._getFallback !== null) {
29276          try {
29277            this.backend = backend = this._getFallback(error2);
29278            await backend.init(this);
29279          } catch (error3) {
29280            reject(error3);
29281            return;
29282          }
29283        } else {
29284          reject(error2);
29285          return;
29286        }
29287      }
29288      this._nodes = new NodeManager(this, backend);
29289      this._animation = new Animation(this, this._nodes, this.info);
29290      this._attributes = new Attributes(backend, this.info);
29291      this._background = new Background(this, this._nodes);
29292      this._geometries = new Geometries(this._attributes, this.info);
29293      this._textures = new Textures(this, backend, this.info);
29294      this._pipelines = new Pipelines(backend, this._nodes, this.info);
29295      this._bindings = new Bindings(backend, this._nodes, this._textures, this._attributes, this._pipelines, this.info);
29296      this._objects = new RenderObjects(this, this._nodes, this._geometries, this._pipelines, this._bindings, this.info);
29297      this._renderLists = new RenderLists(this.lighting);
29298      this._bundles = new RenderBundles();
29299      this._renderContexts = new RenderContexts(this);
29300      this._animation.start();
29301      this._initialized = true;
29302      this._inspector.init();
29303      resolve(this);
29304    });
29305    return this._initPromise;
29306  }
29307  /**
29308   * A reference to the canvas element the renderer is drawing to.
29309   * This value of this property will automatically be created by
29310   * the renderer.
29311   *
29312   * @type {HTMLCanvasElement|OffscreenCanvas}
29313   */
29314  get domElement() {
29315    return this._canvasTarget.domElement;
29316  }
29317  /**
29318   * The coordinate system of the renderer. The value of this property
29319   * depends on the selected backend. Either `THREE.WebGLCoordinateSystem` or
29320   * `THREE.WebGPUCoordinateSystem`.
29321   *
29322   * @readonly
29323   * @type {number}
29324   */
29325  get coordinateSystem() {
29326    return this.backend.coordinateSystem;
29327  }
29328  /**
29329   * Compiles all materials in the given scene. This can be useful to avoid a
29330   * phenomenon which is called "shader compilation stutter", which occurs when
29331   * rendering an object with a new shader for the first time.
29332   *
29333   * If you want to add a 3D object to an existing scene, use the third optional
29334   * parameter for applying the target scene. Note that the (target) scene's lighting
29335   * and environment must be configured before calling this method.
29336   *
29337   * @async
29338   * @param {Object3D} scene - The scene or 3D object to precompile.
29339   * @param {Camera} camera - The camera that is used to render the scene.
29340   * @param {?Scene} targetScene - If the first argument is a 3D object, this parameter must represent the scene the 3D object is going to be added.
29341   * @return {Promise} A Promise that resolves when the compile has been finished.
29342   */
29343  async compileAsync(scene, camera, targetScene = null) {
29344    if (this._isDeviceLost === true) return;
29345    if (this._initialized === false) await this.init();
29346    const nodeFrame = this._nodes.nodeFrame;
29347    const previousRenderId = nodeFrame.renderId;
29348    const previousRenderContext = this._currentRenderContext;
29349    const previousRenderObjectFunction = this._currentRenderObjectFunction;
29350    const previousHandleObjectFunction = this._handleObjectFunction;
29351    const previousCompilationPromises = this._compilationPromises;
29352    if (targetScene === null) targetScene = scene;
29353    const sceneRef = scene.isScene === true ? scene : targetScene.isScene === true ? targetScene : _scene;
29354    const useFrameBufferTarget = this.needsFrameBufferTarget && this._renderTarget === null;
29355    const renderTarget = useFrameBufferTarget ? this._getFrameBufferTarget() : this._renderTarget || this._outputRenderTarget;
29356    const renderContext = this._renderContexts.get(renderTarget, this._mrt);
29357    const activeMipmapLevel = this._activeMipmapLevel;
29358    const compilationPromises = [];
29359    this._currentRenderContext = renderContext;
29360    this._currentRenderObjectFunction = this.renderObject;
29361    this._handleObjectFunction = this._createObjectPipeline;
29362    this._compilationPromises = compilationPromises;
29363    nodeFrame.renderId++;
29364    nodeFrame.update();
29365    renderContext.depth = this.depth;
29366    renderContext.stencil = this.stencil;
29367    if (!renderContext.clippingContext) renderContext.clippingContext = new ClippingContext();
29368    renderContext.clippingContext.updateGlobal(sceneRef, camera);
29369    sceneRef.onBeforeRender(this, scene, camera, renderTarget);
29370    const renderList = this._renderLists.get(sceneRef, camera);
29371    renderList.begin();
29372    this._projectObject(scene, camera, 0, renderList, renderContext.clippingContext);
29373    if (targetScene !== scene) {
29374      targetScene.traverseVisible(function(object) {
29375        if (object.isLight && object.layers.test(camera.layers)) {
29376          renderList.pushLight(object);
29377        }
29378      });
29379    }
29380    renderList.finish();
29381    if (renderTarget !== null) {
29382      this._textures.updateRenderTarget(renderTarget, activeMipmapLevel);
29383      const renderTargetData = this._textures.get(renderTarget);
29384      renderContext.textures = renderTargetData.textures;
29385      renderContext.depthTexture = renderTargetData.depthTexture;
29386    } else {
29387      renderContext.textures = null;
29388      renderContext.depthTexture = null;
29389    }
29390    if (targetScene !== scene) {
29391      this._background.update(targetScene, renderList, renderContext);
29392    } else {
29393      this._background.update(sceneRef, renderList, renderContext);
29394    }
29395    const opaqueObjects = renderList.opaque;
29396    const transparentObjects = renderList.transparent;
29397    const transparentDoublePassObjects = renderList.transparentDoublePass;
29398    const lightsNode = renderList.lightsNode;
29399    if (this.opaque === true && opaqueObjects.length > 0) this._renderObjects(opaqueObjects, camera, sceneRef, lightsNode);
29400    if (this.transparent === true && transparentObjects.length > 0) this._renderTransparents(transparentObjects, transparentDoublePassObjects, camera, sceneRef, lightsNode);
29401    nodeFrame.renderId = previousRenderId;
29402    this._currentRenderContext = previousRenderContext;
29403    this._currentRenderObjectFunction = previousRenderObjectFunction;
29404    this._handleObjectFunction = previousHandleObjectFunction;
29405    this._compilationPromises = previousCompilationPromises;
29406    for (const item of compilationPromises) {
29407      const renderObject = this._objects.get(item.object, item.material, item.scene, item.camera, item.lightsNode, item.renderContext, item.clippingContext, item.passId);
29408      renderObject.drawRange = item.object.geometry.drawRange;
29409      renderObject.group = item.group;
29410      this._geometries.updateForRender(renderObject);
29411      await this._nodes.getForRenderAsync(renderObject);
29412      this._nodes.updateBefore(renderObject);
29413      this._nodes.updateForRender(renderObject);
29414      this._bindings.updateForRender(renderObject);
29415      const pipelinePromises = [];
29416      this._pipelines.getForRender(renderObject, pipelinePromises);
29417      if (pipelinePromises.length > 0) {
29418        await Promise.all(pipelinePromises);
29419      }
29420      this._nodes.updateAfter(renderObject);
29421      await yieldToMain();
29422    }
29423  }
29424  /**
29425   * Renders the scene in an async fashion.
29426   *
29427   * @async
29428   * @deprecated
29429   * @param {Object3D} scene - The scene or 3D object to render.
29430   * @param {Camera} camera - The camera.
29431   * @return {Promise} A Promise that resolves when the render has been finished.
29432   */
29433  async renderAsync(scene, camera) {
29434    warnOnce('Renderer: "renderAsync()" has been deprecated. Use "render()" and "await renderer.init();" when creating the renderer.');
29435    await this.init();
29436    this.render(scene, camera);
29437  }
29438  /**
29439   * Can be used to synchronize CPU operations with GPU tasks. So when this method is called,
29440   * the CPU waits for the GPU to complete its operation (e.g. a compute task).
29441   *
29442   * @async
29443   * @deprecated
29444   * @return {Promise} A Promise that resolves when synchronization has been finished.
29445   */
29446  async waitForGPU() {
29447    error("Renderer: waitForGPU() has been removed. Read https://github.com/mrdoob/three.js/issues/32012 for more information.");
29448  }
29449  //
29450  set inspector(value) {
29451    if (this._inspector !== null) {
29452      this._inspector.setRenderer(null);
29453    }
29454    this._inspector = value;
29455    this._inspector.setRenderer(this);
29456  }
29457  /**
29458   * The inspector instance. The inspector can be any class that extends from `InspectorBase`.
29459   *
29460   * @type {InspectorBase}
29461   */
29462  get inspector() {
29463    return this._inspector;
29464  }
29465  /**
29466   * Enables or disables high precision for model-view and normal-view matrices.
29467   * When enabled, will use CPU 64-bit precision for higher precision instead of GPU 32-bit for higher performance.
29468   *
29469   * NOTE: 64-bit precision is not compatible with `InstancedMesh` and `SkinnedMesh`.
29470   *
29471   * @param {boolean} value - Whether to enable or disable high precision.
29472   * @type {boolean}
29473   */
29474  set highPrecision(value) {
29475    const contextNodeData = this.contextNode.value;
29476    if (value === true) {
29477      contextNodeData.modelViewMatrix = highpModelViewMatrix;
29478      contextNodeData.modelNormalViewMatrix = highpModelNormalViewMatrix;
29479    } else if (this.highPrecision) {
29480      delete contextNodeData.modelViewMatrix;
29481      delete contextNodeData.modelNormalViewMatrix;
29482    }
29483  }
29484  /**
29485   * Returns whether high precision is enabled or not.
29486   *
29487   * @return {boolean} Whether high precision is enabled or not.
29488   * @type {boolean}
29489   */
29490  get highPrecision() {
29491    const contextNodeData = this.contextNode.value;
29492    return contextNodeData.modelViewMatrix === highpModelViewMatrix && contextNodeData.modelNormalViewMatrix === highpModelNormalViewMatrix;
29493  }
29494  /**
29495   * Sets the given MRT configuration.
29496   *
29497   * @param {MRTNode} mrt - The MRT node to set.
29498   * @return {Renderer} A reference to this renderer.
29499   */
29500  setMRT(mrt3) {
29501    this._mrt = mrt3;
29502    return this;
29503  }
29504  /**
29505   * Returns the MRT configuration.
29506   *
29507   * @return {MRTNode} The MRT configuration.
29508   */
29509  getMRT() {
29510    return this._mrt;
29511  }
29512  /**
29513   * Returns the output buffer type.
29514   *
29515   * @return {number} The output buffer type.
29516   */
29517  getOutputBufferType() {
29518    return this._outputBufferType;
29519  }
29520  /**
29521   * Returns the output buffer type.
29522   *
29523   * @deprecated since r182. Use `.getOutputBufferType()` instead.
29524   * @return {number} The output buffer type.
29525   */
29526  getColorBufferType() {
29527    warnOnce('Renderer: ".getColorBufferType()" has been renamed to ".getOutputBufferType()".');
29528    return this.getOutputBufferType();
29529  }
29530  /**
29531   * Default implementation of the device lost callback.
29532   *
29533   * @private
29534   * @param {Object} info - Information about the context lost.
29535   */
29536  _onDeviceLost(info) {
29537    let errorMessage = `THREE.WebGPURenderer: ${info.api} Device Lost:
29538
29539Message: ${info.message}`;
29540    if (info.reason) {
29541      errorMessage += `
29542Reason: ${info.reason}`;
29543    }
29544    error(errorMessage);
29545    this._isDeviceLost = true;
29546  }
29547  /**
29548   * Renders the given render bundle.
29549   *
29550   * @private
29551   * @param {Object} bundle - Render bundle data.
29552   * @param {Scene} sceneRef - The scene the render bundle belongs to.
29553   * @param {LightsNode} lightsNode - The lights node.
29554   */
29555  _renderBundle(bundle, sceneRef, lightsNode) {
29556    const { bundleGroup, camera, renderList } = bundle;
29557    const renderContext = this._currentRenderContext;
29558    const renderBundle = this._bundles.get(bundleGroup, camera, renderContext);
29559    const renderBundleData = this.backend.get(renderBundle);
29560    const needsUpdate = bundleGroup.version !== renderBundleData.version;
29561    const renderBundleNeedsUpdate = needsUpdate || renderBundleData.bundleGPU === void 0;
29562    if (renderBundleNeedsUpdate) {
29563      this.backend.beginBundle(renderContext);
29564      if (renderBundleData.renderObjects === void 0 || needsUpdate) {
29565        renderBundleData.renderObjects = [];
29566      }
29567      this._currentRenderBundle = renderBundle;
29568      const {
29569        transparentDoublePass: transparentDoublePassObjects,
29570        transparent: transparentObjects,
29571        opaque: opaqueObjects
29572      } = renderList;
29573      if (this.opaque === true && opaqueObjects.length > 0) this._renderObjects(opaqueObjects, camera, sceneRef, lightsNode);
29574      if (this.transparent === true && transparentObjects.length > 0) this._renderTransparents(transparentObjects, transparentDoublePassObjects, camera, sceneRef, lightsNode);
29575      this._currentRenderBundle = null;
29576      this.backend.finishBundle(renderContext, renderBundle);
29577      renderBundleData.version = bundleGroup.version;
29578    } else {
29579      const { renderObjects } = renderBundleData;
29580      for (let i = 0, l = renderObjects.length; i < l; i++) {
29581        const renderObject = renderObjects[i];
29582        if (this._nodes.needsRefresh(renderObject)) {
29583          this._nodes.updateBefore(renderObject);
29584          this._nodes.updateForRender(renderObject);
29585          this._bindings.updateForRender(renderObject);
29586          this._nodes.updateAfter(renderObject);
29587        }
29588      }
29589    }
29590    this.backend.addBundle(renderContext, renderBundle);
29591  }
29592  /**
29593   * Renders the scene or 3D object with the given camera. This method can only be called
29594   * if the renderer has been initialized. When using `render()` inside an animation loop,
29595   * it's guaranteed the renderer will be initialized. The animation loop must be defined
29596   * with {@link Renderer#setAnimationLoop} though.
29597   *
29598   * For all other use cases (like when using on-demand rendering), you must call
29599   * {@link Renderer#init} before rendering.
29600   *
29601   * The target of the method is the default framebuffer (meaning the canvas)
29602   * or alternatively a render target when specified via `setRenderTarget()`.
29603   *
29604   * @param {Object3D} scene - The scene or 3D object to render.
29605   * @param {Camera} camera - The camera to render the scene with.
29606   */
29607  render(scene, camera) {
29608    if (this._initialized === false) {
29609      throw new Error('Renderer: .render() called before the backend is initialized. Use "await renderer.init();" before rendering.');
29610    }
29611    this._renderScene(scene, camera);
29612  }
29613  /**
29614   * Returns whether the renderer has been initialized or not.
29615   *
29616   * @readonly
29617   * @return {boolean} Whether the renderer has been initialized or not.
29618   */
29619  get initialized() {
29620    return this._initialized;
29621  }
29622  /**
29623   * Returns an internal render target which is used when computing the output tone mapping
29624   * and color space conversion. Unlike in `WebGLRenderer`, this is done in a separate render
29625   * pass and not inline to achieve more correct results.
29626   *
29627   * @private
29628   * @return {?RenderTarget} The render target. The method returns `null` if no output conversion should be applied.
29629   */
29630  _getFrameBufferTarget() {
29631    const { currentToneMapping, currentColorSpace } = this;
29632    const useToneMapping = currentToneMapping !== NoToneMapping;
29633    const useColorSpace = currentColorSpace !== ColorManagement.workingColorSpace;
29634    if (useToneMapping === false && useColorSpace === false) return null;
29635    const { width, height } = this.getDrawingBufferSize(_drawingBufferSize);
29636    const { depth: depth3, stencil } = this;
29637    const target = this._outputRenderTarget || this._canvasTarget;
29638    let frameBufferTarget = this._frameBufferTargets.get(target);
29639    if (frameBufferTarget === void 0) {
29640      frameBufferTarget = new RenderTarget(width, height, {
29641        depthBuffer: depth3,
29642        stencilBuffer: stencil,
29643        type: this._outputBufferType,
29644        format: RGBAFormat,
29645        colorSpace: ColorManagement.workingColorSpace,
29646        generateMipmaps: false,
29647        minFilter: LinearFilter,
29648        magFilter: LinearFilter,
29649        samples: this.samples
29650      });
29651      frameBufferTarget.isPostProcessingRenderTarget = true;
29652      const dispose2 = () => {
29653        target.removeEventListener("dispose", dispose2);
29654        frameBufferTarget.dispose();
29655        this._frameBufferTargets.delete(target);
29656      };
29657      target.addEventListener("dispose", dispose2);
29658      this._frameBufferTargets.set(target, frameBufferTarget);
29659    }
29660    const outputRenderTarget = this.getOutputRenderTarget();
29661    frameBufferTarget.depthBuffer = depth3;
29662    frameBufferTarget.stencilBuffer = stencil;
29663    if (outputRenderTarget !== null) {
29664      frameBufferTarget.setSize(outputRenderTarget.width, outputRenderTarget.height, outputRenderTarget.depth);
29665    } else {
29666      frameBufferTarget.setSize(width, height, 1);
29667    }
29668    const viewport3 = this._outputRenderTarget ? this._outputRenderTarget.viewport : target._viewport;
29669    const scissor = this._outputRenderTarget ? this._outputRenderTarget.scissor : target._scissor;
29670    const pixelRatio = this._outputRenderTarget ? 1 : target._pixelRatio;
29671    const scissorTest = this._outputRenderTarget ? this._outputRenderTarget.scissorTest : target._scissorTest;
29672    frameBufferTarget.viewport.copy(viewport3);
29673    frameBufferTarget.scissor.copy(scissor);
29674    frameBufferTarget.viewport.multiplyScalar(pixelRatio);
29675    frameBufferTarget.scissor.multiplyScalar(pixelRatio);
29676    frameBufferTarget.scissorTest = scissorTest;
29677    frameBufferTarget.multiview = outputRenderTarget !== null ? outputRenderTarget.multiview : false;
29678    frameBufferTarget.resolveDepthBuffer = outputRenderTarget !== null ? outputRenderTarget.resolveDepthBuffer : true;
29679    frameBufferTarget._autoAllocateDepthBuffer = outputRenderTarget !== null ? outputRenderTarget._autoAllocateDepthBuffer : false;
29680    return frameBufferTarget;
29681  }
29682  /**
29683   * Renders the scene or 3D object with the given camera.
29684   *
29685   * @private
29686   * @param {Object3D} scene - The scene or 3D object to render.
29687   * @param {Camera} camera - The camera to render the scene with.
29688   * @param {boolean} [useFrameBufferTarget=true] - Whether to use a framebuffer target or not.
29689   * @return {RenderContext} The current render context.
29690   */
29691  _renderScene(scene, camera, useFrameBufferTarget = true) {
29692    if (this._isDeviceLost === true) return;
29693    const frameBufferTarget = useFrameBufferTarget ? this._getFrameBufferTarget() : null;
29694    const nodeFrame = this._nodes.nodeFrame;
29695    const previousRenderId = nodeFrame.renderId;
29696    const previousRenderContext = this._currentRenderContext;
29697    const previousRenderObjectFunction = this._currentRenderObjectFunction;
29698    const previousHandleObjectFunction = this._handleObjectFunction;
29699    this._callDepth++;
29700    const sceneRef = scene.isScene === true ? scene : _scene;
29701    const outputRenderTarget = this._renderTarget || this._outputRenderTarget;
29702    const activeCubeFace = this._activeCubeFace;
29703    const activeMipmapLevel = this._activeMipmapLevel;
29704    let renderTarget;
29705    if (frameBufferTarget !== null) {
29706      renderTarget = frameBufferTarget;
29707      this.setRenderTarget(renderTarget);
29708    } else {
29709      renderTarget = outputRenderTarget;
29710    }
29711    if (renderTarget !== null && renderTarget.depthBuffer === true) {
29712      const renderTargetData = this._textures.get(renderTarget);
29713      if (renderTargetData.depthInitialized !== true) {
29714        if (this.autoClear === false || this.autoClear === true && this.autoClearDepth === false) {
29715          this.clearDepth();
29716        }
29717        renderTargetData.depthInitialized = true;
29718      }
29719    }
29720    const renderContext = this._renderContexts.get(renderTarget, this._mrt, this._callDepth);
29721    this._currentRenderContext = renderContext;
29722    this._currentRenderObjectFunction = this._renderObjectFunction || this.renderObject;
29723    this._handleObjectFunction = this._renderObjectDirect;
29724    this.info.calls++;
29725    this.info.render.calls++;
29726    this.info.render.frameCalls++;
29727    nodeFrame.renderId = this.info.calls;
29728    this.backend.updateTimeStampUID(renderContext);
29729    this.inspector.beginRender(this.backend.getTimestampUID(renderContext), scene, camera, renderTarget);
29730    const xr = this.xr;
29731    if (xr.isPresenting === false) {
29732      let projectionMatrixNeedsUpdate = false;
29733      if (this.reversedDepthBuffer === true && camera.reversedDepth !== true) {
29734        camera._reversedDepth = true;
29735        if (camera.isArrayCamera) {
29736          for (const subCamera of camera.cameras) {
29737            subCamera._reversedDepth = true;
29738          }
29739        }
29740        projectionMatrixNeedsUpdate = true;
29741      }
29742      const coordinateSystem = this.coordinateSystem;
29743      if (camera.coordinateSystem !== coordinateSystem) {
29744        camera.coordinateSystem = coordinateSystem;
29745        if (camera.isArrayCamera) {
29746          for (const subCamera of camera.cameras) {
29747            subCamera.coordinateSystem = coordinateSystem;
29748          }
29749        }
29750        projectionMatrixNeedsUpdate = true;
29751      }
29752      if (projectionMatrixNeedsUpdate === true) {
29753        camera.updateProjectionMatrix();
29754        if (camera.isArrayCamera) {
29755          for (const subCamera of camera.cameras) {
29756            subCamera.updateProjectionMatrix();
29757          }
29758        }
29759      }
29760    }
29761    if (scene.matrixWorldAutoUpdate === true) scene.updateMatrixWorld();
29762    if (camera.parent === null && camera.matrixWorldAutoUpdate === true) camera.updateMatrixWorld();
29763    if (xr.enabled === true && xr.isPresenting === true) {
29764      if (xr.cameraAutoUpdate === true) xr.updateCamera(camera);
29765      camera = xr.getCamera();
29766    }
29767    const canvasTarget = this._canvasTarget;
29768    let viewport3 = canvasTarget._viewport;
29769    let scissor = canvasTarget._scissor;
29770    let pixelRatio = canvasTarget._pixelRatio;
29771    if (renderTarget !== null) {
29772      viewport3 = renderTarget.viewport;
29773      scissor = renderTarget.scissor;
29774      pixelRatio = 1;
29775    }
29776    this.getDrawingBufferSize(_drawingBufferSize);
29777    _screen.set(0, 0, _drawingBufferSize.width, _drawingBufferSize.height);
29778    const minDepth = viewport3.minDepth === void 0 ? 0 : viewport3.minDepth;
29779    const maxDepth = viewport3.maxDepth === void 0 ? 1 : viewport3.maxDepth;
29780    renderContext.viewportValue.copy(viewport3).multiplyScalar(pixelRatio).floor();
29781    renderContext.viewportValue.width >>= activeMipmapLevel;
29782    renderContext.viewportValue.height >>= activeMipmapLevel;
29783    renderContext.viewportValue.minDepth = minDepth;
29784    renderContext.viewportValue.maxDepth = maxDepth;
29785    renderContext.viewport = renderContext.viewportValue.equals(_screen) === false;
29786    renderContext.scissorValue.copy(scissor).multiplyScalar(pixelRatio).floor();
29787    renderContext.scissor = canvasTarget._scissorTest && renderContext.scissorValue.equals(_screen) === false;
29788    renderContext.scissorValue.width >>= activeMipmapLevel;
29789    renderContext.scissorValue.height >>= activeMipmapLevel;
29790    if (!renderContext.clippingContext) renderContext.clippingContext = new ClippingContext();
29791    renderContext.clippingContext.updateGlobal(sceneRef, camera);
29792    sceneRef.onBeforeRender(this, scene, camera, renderTarget);
29793    const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
29794    if (!camera.isArrayCamera) {
29795      _projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
29796      frustum.setFromProjectionMatrix(_projScreenMatrix, camera.coordinateSystem, camera.reversedDepth);
29797    }
29798    const renderList = this._renderLists.get(scene, camera);
29799    renderList.begin();
29800    this._projectObject(scene, camera, 0, renderList, renderContext.clippingContext);
29801    renderList.finish();
29802    if (this.sortObjects === true) {
29803      renderList.sort(this._opaqueSort, this._transparentSort);
29804    }
29805    if (renderTarget !== null) {
29806      this._textures.updateRenderTarget(renderTarget, activeMipmapLevel);
29807      const renderTargetData = this._textures.get(renderTarget);
29808      renderContext.textures = renderTargetData.textures;
29809      renderContext.depthTexture = renderTargetData.depthTexture;
29810      renderContext.width = renderTargetData.width;
29811      renderContext.height = renderTargetData.height;
29812      renderContext.renderTarget = renderTarget;
29813      renderContext.depth = renderTarget.depthBuffer;
29814      renderContext.stencil = renderTarget.stencilBuffer;
29815    } else {
29816      renderContext.textures = null;
29817      renderContext.depthTexture = null;
29818      renderContext.width = _drawingBufferSize.width;
29819      renderContext.height = _drawingBufferSize.height;
29820      renderContext.depth = this.depth;
29821      renderContext.stencil = this.stencil;
29822    }
29823    renderContext.width >>= activeMipmapLevel;
29824    renderContext.height >>= activeMipmapLevel;
29825    renderContext.activeCubeFace = activeCubeFace;
29826    renderContext.activeMipmapLevel = activeMipmapLevel;
29827    renderContext.occlusionQueryCount = renderList.occlusionQueryCount;
29828    renderContext.scissorValue.max(_vector4.set(0, 0, 0, 0));
29829    if (renderContext.scissorValue.x + renderContext.scissorValue.width > renderContext.width) {
29830      renderContext.scissorValue.width = Math.max(renderContext.width - renderContext.scissorValue.x, 0);
29831    }
29832    if (renderContext.scissorValue.y + renderContext.scissorValue.height > renderContext.height) {
29833      renderContext.scissorValue.height = Math.max(renderContext.height - renderContext.scissorValue.y, 0);
29834    }
29835    this._background.update(sceneRef, renderList, renderContext);
29836    renderContext.camera = camera;
29837    this.backend.beginRender(renderContext);
29838    const {
29839      bundles,
29840      lightsNode,
29841      transparentDoublePass: transparentDoublePassObjects,
29842      transparent: transparentObjects,
29843      opaque: opaqueObjects
29844    } = renderList;
29845    if (bundles.length > 0) this._renderBundles(bundles, sceneRef, lightsNode);
29846    if (this.opaque === true && opaqueObjects.length > 0) this._renderObjects(opaqueObjects, camera, sceneRef, lightsNode);
29847    if (this.transparent === true && transparentObjects.length > 0) this._renderTransparents(transparentObjects, transparentDoublePassObjects, camera, sceneRef, lightsNode);
29848    this.backend.finishRender(renderContext);
29849    nodeFrame.renderId = previousRenderId;
29850    this._currentRenderContext = previousRenderContext;
29851    this._currentRenderObjectFunction = previousRenderObjectFunction;
29852    this._handleObjectFunction = previousHandleObjectFunction;
29853    this._callDepth--;
29854    if (frameBufferTarget !== null) {
29855      this.setRenderTarget(outputRenderTarget, activeCubeFace, activeMipmapLevel);
29856      this._renderOutput(renderTarget);
29857    }
29858    sceneRef.onAfterRender(this, scene, camera, renderTarget);
29859    this.inspector.finishRender(this.backend.getTimestampUID(renderContext));
29860    return renderContext;
29861  }
29862  _setXRLayerSize(width, height) {
29863    this._canvasTarget._width = width;
29864    this._canvasTarget._height = height;
29865    this.setViewport(0, 0, width, height);
29866  }
29867  /**
29868   * The output pass performs tone mapping and color space conversion.
29869   *
29870   * @private
29871   * @param {RenderTarget} renderTarget - The current render target.
29872   */
29873  _renderOutput(renderTarget) {
29874    const cacheKey = this._nodes.getOutputCacheKey();
29875    let quadData = this._quadCache.get(renderTarget.texture);
29876    let quad;
29877    if (quadData === void 0) {
29878      quad = new QuadMesh(new NodeMaterial());
29879      quad.name = "Output Color Transform";
29880      quad.material.name = "outputColorTransform";
29881      quad.material.fragmentNode = this._nodes.getOutputNode(renderTarget.texture);
29882      quadData = {
29883        quad,
29884        cacheKey
29885      };
29886      this._quadCache.set(renderTarget.texture, quadData);
29887      const dispose2 = () => {
29888        quad.material.dispose();
29889        this._quadCache.delete(renderTarget.texture);
29890        renderTarget.texture.removeEventListener("dispose", dispose2);
29891      };
29892      renderTarget.texture.addEventListener("dispose", dispose2);
29893    } else {
29894      quad = quadData.quad;
29895      if (quadData.cacheKey !== cacheKey) {
29896        quad.material.fragmentNode = this._nodes.getOutputNode(renderTarget.texture);
29897        quad.material.needsUpdate = true;
29898        quadData.cacheKey = cacheKey;
29899      }
29900    }
29901    const currentAutoClear = this.autoClear;
29902    const currentXR = this.xr.enabled;
29903    this.autoClear = false;
29904    this.xr.enabled = false;
29905    this._renderScene(quad, quad.camera, false);
29906    this.autoClear = currentAutoClear;
29907    this.xr.enabled = currentXR;
29908  }
29909  /**
29910   * Returns the maximum available anisotropy for texture filtering.
29911   *
29912   * @return {number} The maximum available anisotropy.
29913   */
29914  getMaxAnisotropy() {
29915    return this.backend.capabilities.getMaxAnisotropy();
29916  }
29917  /**
29918   * Returns the active cube face.
29919   *
29920   * @return {number} The active cube face.
29921   */
29922  getActiveCubeFace() {
29923    return this._activeCubeFace;
29924  }
29925  /**
29926   * Returns the active mipmap level.
29927   *
29928   * @return {number} The active mipmap level.
29929   */
29930  getActiveMipmapLevel() {
29931    return this._activeMipmapLevel;
29932  }
29933  /**
29934   * Applications are advised to always define the animation loop
29935   * with this method and not manually with `requestAnimationFrame()`
29936   * for best compatibility.
29937   *
29938   * @async
29939   * @param {?onAnimationCallback} callback - The application's animation loop.
29940   * @return {Promise} A Promise that resolves when the set has been executed.
29941   */
29942  async setAnimationLoop(callback) {
29943    if (this._initialized === false) await this.init();
29944    this._animation.setAnimationLoop(callback);
29945  }
29946  /**
29947   * Returns the current animation loop callback.
29948   *
29949   * @return {?Function} The current animation loop callback.
29950   */
29951  getAnimationLoop() {
29952    return this._animation.getAnimationLoop();
29953  }
29954  /**
29955   * Can be used to transfer buffer data from a storage buffer attribute
29956   * from the GPU to the CPU in context of compute shaders.
29957   *
29958   * @async
29959   * @param {BufferAttribute} attribute - The storage buffer attribute to read frm.
29960   * @param {ReadbackBuffer|ArrayBuffer} target - The storage buffer attribute.
29961   * @param {number} offset - The storage buffer attribute.
29962   * @param {number} count - The offset from which to start reading the
29963   * @return {Promise<ArrayBuffer|ReadbackBuffer>} A promise that resolves with the buffer data when the data are ready.
29964   */
29965  async getArrayBufferAsync(attribute3, target = null, offset3 = 0, count = -1) {
29966    if (target !== null && target.isReadbackBuffer) {
29967      if (this.info.memoryMap.has(target) === false) {
29968        this.info.createReadbackBuffer(target);
29969        const disposeInfo = () => {
29970          target.removeEventListener("dispose", disposeInfo);
29971          this.info.destroyReadbackBuffer(target);
29972        };
29973        target.addEventListener("dispose", disposeInfo);
29974      }
29975    }
29976    if (offset3 % 4 !== 0 || count > 0 && count % 4 !== 0) {
29977      throw new Error('THREE.Renderer: "getArrayBufferAsync()" offset and count must be a multiple of 4.');
29978    }
29979    return await this.backend.getArrayBufferAsync(attribute3, target, offset3, count);
29980  }
29981  /**
29982   * Returns the rendering context.
29983   *
29984   * @return {GPUCanvasContext|WebGL2RenderingContext} The rendering context.
29985   */
29986  getContext() {
29987    return this.backend.getContext();
29988  }
29989  /**
29990   * Returns the pixel ratio.
29991   *
29992   * @return {number} The pixel ratio.
29993   */
29994  getPixelRatio() {
29995    return this._canvasTarget.getPixelRatio();
29996  }
29997  /**
29998   * Returns the drawing buffer size in physical pixels. This method honors the pixel ratio.
29999   *
30000   * @param {Vector2} target - The method writes the result in this target object.
30001   * @return {Vector2} The drawing buffer size.
30002   */
30003  getDrawingBufferSize(target) {
30004    return this._canvasTarget.getDrawingBufferSize(target);
30005  }
30006  /**
30007   * Returns the renderer's size in logical pixels. This method does not honor the pixel ratio.
30008   *
30009   * @param {Vector2} target - The method writes the result in this target object.
30010   * @return {Vector2} The renderer's size in logical pixels.
30011   */
30012  getSize(target) {
30013    return this._canvasTarget.getSize(target);
30014  }
30015  /**
30016   * Sets the given pixel ratio and resizes the canvas if necessary.
30017   *
30018   * @param {number} [value=1] - The pixel ratio.
30019   */
30020  setPixelRatio(value = 1) {
30021    this._canvasTarget.setPixelRatio(value);
30022  }
30023  /**
30024   * This method allows to define the drawing buffer size by specifying
30025   * width, height and pixel ratio all at once. The size of the drawing
30026   * buffer is computed with this formula:
30027   * ```js
30028   * size.x = width * pixelRatio;
30029   * size.y = height * pixelRatio;
30030   * ```
30031   *
30032   * @param {number} width - The width in logical pixels.
30033   * @param {number} height - The height in logical pixels.
30034   * @param {number} pixelRatio - The pixel ratio.
30035   */
30036  setDrawingBufferSize(width, height, pixelRatio) {
30037    if (this.xr && this.xr.isPresenting) return;
30038    this._canvasTarget.setDrawingBufferSize(width, height, pixelRatio);
30039  }
30040  /**
30041   * Sets the size of the renderer.
30042   *
30043   * @param {number} width - The width in logical pixels.
30044   * @param {number} height - The height in logical pixels.
30045   * @param {boolean} [updateStyle=true] - Whether to update the `style` attribute of the canvas or not.
30046   */
30047  setSize(width, height, updateStyle = true) {
30048    if (this.xr && this.xr.isPresenting) return;
30049    this._canvasTarget.setSize(width, height, updateStyle);
30050  }
30051  /**
30052   * Defines a manual sort function for the opaque render list.
30053   * Pass `null` to use the default sort.
30054   *
30055   * @param {Function} method - The sort function.
30056   */
30057  setOpaqueSort(method) {
30058    this._opaqueSort = method;
30059  }
30060  /**
30061   * Defines a manual sort function for the transparent render list.
30062   * Pass `null` to use the default sort.
30063   *
30064   * @param {Function} method - The sort function.
30065   */
30066  setTransparentSort(method) {
30067    this._transparentSort = method;
30068  }
30069  /**
30070   * Returns the scissor rectangle.
30071   *
30072   * @param {Vector4} target - The method writes the result in this target object.
30073   * @return {Vector4} The scissor rectangle.
30074   */
30075  getScissor(target) {
30076    return this._canvasTarget.getScissor(target);
30077  }
30078  /**
30079   * Defines the scissor rectangle.
30080   *
30081   * @param {number | Vector4} x - The horizontal coordinate for the upper left corner of the box in logical pixel unit.
30082   * Instead of passing four arguments, the method also works with a single four-dimensional vector.
30083   * @param {number} y - The vertical coordinate for the upper left corner of the box in logical pixel unit.
30084   * @param {number} width - The width of the scissor box in logical pixel unit.
30085   * @param {number} height - The height of the scissor box in logical pixel unit.
30086   */
30087  setScissor(x, y, width, height) {
30088    this._canvasTarget.setScissor(x, y, width, height);
30089  }
30090  /**
30091   * Returns the scissor test value.
30092   *
30093   * @return {boolean} Whether the scissor test should be enabled or not.
30094   */
30095  getScissorTest() {
30096    return this._canvasTarget.getScissorTest();
30097  }
30098  /**
30099   * Defines the scissor test.
30100   *
30101   * @param {boolean} boolean - Whether the scissor test should be enabled or not.
30102   */
30103  setScissorTest(boolean) {
30104    this._canvasTarget.setScissorTest(boolean);
30105    this.backend.setScissorTest(boolean);
30106  }
30107  /**
30108   * Returns the viewport definition.
30109   *
30110   * @param {Vector4} target - The method writes the result in this target object.
30111   * @return {Vector4} The viewport definition.
30112   */
30113  getViewport(target) {
30114    return this._canvasTarget.getViewport(target);
30115  }
30116  /**
30117   * Defines the viewport.
30118   *
30119   * @param {number | Vector4} x - The horizontal coordinate for the upper left corner of the viewport origin in logical pixel unit.
30120   * @param {number} y - The vertical coordinate for the upper left corner of the viewport origin in logical pixel unit.
30121   * @param {number} width - The width of the viewport in logical pixel unit.
30122   * @param {number} height - The height of the viewport in logical pixel unit.
30123   * @param {number} minDepth - The minimum depth value of the viewport. WebGPU only.
30124   * @param {number} maxDepth - The maximum depth value of the viewport. WebGPU only.
30125   */
30126  setViewport(x, y, width, height, minDepth = 0, maxDepth = 1) {
30127    this._canvasTarget.setViewport(x, y, width, height, minDepth, maxDepth);
30128  }
30129  /**
30130   * Returns the clear color.
30131   *
30132   * @param {Color} target - The method writes the result in this target object.
30133   * @return {Color} The clear color.
30134   */
30135  getClearColor(target) {
30136    return target.copy(this._clearColor);
30137  }
30138  /**
30139   * Defines the clear color and optionally the clear alpha.
30140   *
30141   * @param {Color} color - The clear color.
30142   * @param {number} [alpha=1] - The clear alpha.
30143   */
30144  setClearColor(color3, alpha = 1) {
30145    this._clearColor.set(color3);
30146    this._clearColor.a = alpha;
30147  }
30148  /**
30149   * Returns the clear alpha.
30150   *
30151   * @return {number} The clear alpha.
30152   */
30153  getClearAlpha() {
30154    return this._clearColor.a;
30155  }
30156  /**
30157   * Defines the clear alpha.
30158   *
30159   * @param {number} alpha - The clear alpha.
30160   */
30161  setClearAlpha(alpha) {
30162    this._clearColor.a = alpha;
30163  }
30164  /**
30165   * Returns the clear depth.
30166   *
30167   * @return {number} The clear depth.
30168   */
30169  getClearDepth() {
30170    return this.reversedDepthBuffer === true ? 1 - this._clearDepth : this._clearDepth;
30171  }
30172  /**
30173   * Defines the clear depth.
30174   *
30175   * @param {number} depth - The clear depth.
30176   */
30177  setClearDepth(depth3) {
30178    this._clearDepth = depth3;
30179  }
30180  /**
30181   * Returns the clear stencil.
30182   *
30183   * @return {number} The clear stencil.
30184   */
30185  getClearStencil() {
30186    return this._clearStencil;
30187  }
30188  /**
30189   * Defines the clear stencil.
30190   *
30191   * @param {number} stencil - The clear stencil.
30192   */
30193  setClearStencil(stencil) {
30194    this._clearStencil = stencil;
30195  }
30196  /**
30197   * This method performs an occlusion query for the given 3D object.
30198   * It returns `true` if the given 3D object is fully occluded by other
30199   * 3D objects in the scene.
30200   *
30201   * @param {Object3D} object - The 3D object to test.
30202   * @return {boolean} Whether the 3D object is fully occluded or not.
30203   */
30204  isOccluded(object) {
30205    const renderContext = this._currentRenderContext;
30206    return renderContext && this.backend.isOccluded(renderContext, object);
30207  }
30208  /**
30209   * Performs a manual clear operation. This method ignores `autoClear` properties.
30210   *
30211   * @param {boolean} [color=true] - Whether the color buffer should be cleared or not.
30212   * @param {boolean} [depth=true] - Whether the depth buffer should be cleared or not.
30213   * @param {boolean} [stencil=true] - Whether the stencil buffer should be cleared or not.
30214   */
30215  clear(color3 = true, depth3 = true, stencil = true) {
30216    if (this._initialized === false) {
30217      throw new Error('Renderer: .clear() called before the backend is initialized. Use "await renderer.init();" before before using this method.');
30218    }
30219    const renderTarget = this._renderTarget || this._getFrameBufferTarget();
30220    let renderContext = null;
30221    if (renderTarget !== null) {
30222      this._textures.updateRenderTarget(renderTarget);
30223      const renderTargetData = this._textures.get(renderTarget);
30224      renderContext = this._renderContexts.get(renderTarget, null, -1);
30225      renderContext.textures = renderTargetData.textures;
30226      renderContext.depthTexture = renderTargetData.depthTexture;
30227      renderContext.width = renderTargetData.width;
30228      renderContext.height = renderTargetData.height;
30229      renderContext.renderTarget = renderTarget;
30230      renderContext.depth = renderTarget.depthBuffer;
30231      renderContext.stencil = renderTarget.stencilBuffer;
30232      const color4 = this.backend.getClearColor();
30233      renderContext.clearColorValue.r = color4.r;
30234      renderContext.clearColorValue.g = color4.g;
30235      renderContext.clearColorValue.b = color4.b;
30236      renderContext.clearColorValue.a = color4.a;
30237      renderContext.clearDepthValue = this.getClearDepth();
30238      renderContext.clearStencilValue = this.getClearStencil();
30239      renderContext.activeCubeFace = this.getActiveCubeFace();
30240      renderContext.activeMipmapLevel = this.getActiveMipmapLevel();
30241      if (renderTarget.depthBuffer === true) renderTargetData.depthInitialized = true;
30242    }
30243    this.backend.clear(color3, depth3, stencil, renderContext);
30244    if (renderTarget !== null && this._renderTarget === null) {
30245      this._renderOutput(renderTarget);
30246    }
30247  }
30248  /**
30249   * Performs a manual clear operation of the color buffer. This method ignores `autoClear` properties.
30250   */
30251  clearColor() {
30252    this.clear(true, false, false);
30253  }
30254  /**
30255   * Performs a manual clear operation of the depth buffer. This method ignores `autoClear` properties.
30256   */
30257  clearDepth() {
30258    this.clear(false, true, false);
30259  }
30260  /**
30261   * Performs a manual clear operation of the stencil buffer. This method ignores `autoClear` properties.
30262   */
30263  clearStencil() {
30264    this.clear(false, false, true);
30265  }
30266  /**
30267   * Async version of {@link Renderer#clear}.
30268   *
30269   * @async
30270   * @deprecated
30271   * @param {boolean} [color=true] - Whether the color buffer should be cleared or not.
30272   * @param {boolean} [depth=true] - Whether the depth buffer should be cleared or not.
30273   * @param {boolean} [stencil=true] - Whether the stencil buffer should be cleared or not.
30274   * @return {Promise} A Promise that resolves when the clear operation has been executed.
30275   */
30276  async clearAsync(color3 = true, depth3 = true, stencil = true) {
30277    warnOnce('Renderer: "clearAsync()" has been deprecated. Use "clear()" and "await renderer.init();" when creating the renderer.');
30278    await this.init();
30279    this.clear(color3, depth3, stencil);
30280  }
30281  /**
30282   * Async version of {@link Renderer#clearColor}.
30283   *
30284   * @async
30285   * @deprecated
30286   * @return {Promise} A Promise that resolves when the clear operation has been executed.
30287   */
30288  async clearColorAsync() {
30289    warnOnce('Renderer: "clearColorAsync()" has been deprecated. Use "clearColor()" and "await renderer.init();" when creating the renderer.');
30290    this.clear(true, false, false);
30291  }
30292  /**
30293   * Async version of {@link Renderer#clearDepth}.
30294   *
30295   * @async
30296   * @deprecated
30297   * @return {Promise} A Promise that resolves when the clear operation has been executed.
30298   */
30299  async clearDepthAsync() {
30300    warnOnce('Renderer: "clearDepthAsync()" has been deprecated. Use "clearDepth()" and "await renderer.init();" when creating the renderer.');
30301    this.clear(false, true, false);
30302  }
30303  /**
30304   * Async version of {@link Renderer#clearStencil}.
30305   *
30306   * @async
30307   * @deprecated
30308   * @return {Promise} A Promise that resolves when the clear operation has been executed.
30309   */
30310  async clearStencilAsync() {
30311    warnOnce('Renderer: "clearStencilAsync()" has been deprecated. Use "clearStencil()" and "await renderer.init();" when creating the renderer.');
30312    this.clear(false, false, true);
30313  }
30314  /**
30315   * Returns `true` if a framebuffer target is needed to perform tone mapping or color space conversion.
30316   * If this is the case, the renderer allocates an internal render target for that purpose.
30317   *
30318   */
30319  get needsFrameBufferTarget() {
30320    const useToneMapping = this.currentToneMapping !== NoToneMapping;
30321    const useColorSpace = this.currentColorSpace !== ColorManagement.workingColorSpace;
30322    return useToneMapping || useColorSpace;
30323  }
30324  /**
30325   * The number of samples used for multi-sample anti-aliasing (MSAA).
30326   *
30327   * @type {number}
30328   * @default 0
30329   */
30330  get samples() {
30331    return this._samples;
30332  }
30333  /**
30334   * The current number of samples used for multi-sample anti-aliasing (MSAA).
30335   *
30336   * When rendering to a custom render target, the number of samples of that render target is used.
30337   * If the renderer needs an internal framebuffer target for tone mapping or color space conversion,
30338   * the number of samples is set to 0.
30339   *
30340   * @type {number}
30341   */
30342  get currentSamples() {
30343    let samples = this._samples;
30344    if (this._renderTarget !== null) {
30345      samples = this._renderTarget.samples;
30346    } else if (this.needsFrameBufferTarget) {
30347      samples = 0;
30348    }
30349    return samples;
30350  }
30351  /**
30352   * The current tone mapping of the renderer. When not producing screen output,
30353   * the tone mapping is always `NoToneMapping`.
30354   *
30355   * @type {number}
30356   */
30357  get currentToneMapping() {
30358    return this.isOutputTarget ? this.toneMapping : NoToneMapping;
30359  }
30360  /**
30361   * The current color space of the renderer. When not producing screen output,
30362   * the color space is always the working color space.
30363   *
30364   * @type {string}
30365   */
30366  get currentColorSpace() {
30367    return this.isOutputTarget ? this.outputColorSpace : ColorManagement.workingColorSpace;
30368  }
30369  /**
30370   * Returns `true` if the rendering settings are set to screen output.
30371   *
30372   * @returns {boolean} True if the current render target is the same of output render target or `null`, otherwise false.
30373   */
30374  get isOutputTarget() {
30375    return this._renderTarget === this._outputRenderTarget || this._renderTarget === null;
30376  }
30377  /**
30378   * Frees all internal resources of the renderer. Call this method if the renderer
30379   * is no longer in use by your app.
30380   */
30381  dispose() {
30382    if (this._initialized === true) {
30383      this.info.dispose();
30384      this.backend.dispose();
30385      this._animation.dispose();
30386      this._objects.dispose();
30387      this._geometries.dispose();
30388      this._pipelines.dispose();
30389      this._nodes.dispose();
30390      this._bindings.dispose();
30391      this._renderLists.dispose();
30392      this._renderContexts.dispose();
30393      this._textures.dispose();
30394      for (const canvasTarget of this._frameBufferTargets.keys()) {
30395        canvasTarget.dispose();
30396      }
30397      Object.values(this.backend.timestampQueryPool).forEach((queryPool) => {
30398        if (queryPool !== null) queryPool.dispose();
30399      });
30400    }
30401    this.setRenderTarget(null);
30402    this.setAnimationLoop(null);
30403  }
30404  /**
30405   * Sets the given render target. Calling this method means the renderer does not
30406   * target the default framebuffer (meaning the canvas) anymore but a custom framebuffer.
30407   * Use `null` as the first argument to reset the state.
30408   *
30409   * @param {?RenderTarget} renderTarget - The render target to set.
30410   * @param {number} [activeCubeFace=0] - The active cube face.
30411   * @param {number} [activeMipmapLevel=0] - The active mipmap level.
30412   */
30413  setRenderTarget(renderTarget, activeCubeFace = 0, activeMipmapLevel = 0) {
30414    this._renderTarget = renderTarget;
30415    this._activeCubeFace = activeCubeFace;
30416    this._activeMipmapLevel = activeMipmapLevel;
30417  }
30418  /**
30419   * Returns the current render target.
30420   *
30421   * @return {?RenderTarget} The render target. Returns `null` if no render target is set.
30422   */
30423  getRenderTarget() {
30424    return this._renderTarget;
30425  }
30426  /**
30427   * Sets the output render target for the renderer.
30428   *
30429   * @param {?RenderTarget} renderTarget - The render target to set as the output target.
30430   */
30431  setOutputRenderTarget(renderTarget) {
30432    this._outputRenderTarget = renderTarget;
30433  }
30434  /**
30435   * Returns the current output target.
30436   *
30437   * @return {?RenderTarget} The current output render target. Returns `null` if no output target is set.
30438   */
30439  getOutputRenderTarget() {
30440    return this._outputRenderTarget;
30441  }
30442  /**
30443   * Sets the canvas target. The canvas target manages the HTML canvas
30444   * or the offscreen canvas the renderer draws into.
30445   *
30446   * @param {CanvasTarget} canvasTarget - The canvas target.
30447   */
30448  setCanvasTarget(canvasTarget) {
30449    this._canvasTarget.removeEventListener("resize", this._onCanvasTargetResize);
30450    this._canvasTarget = canvasTarget;
30451    this._canvasTarget.addEventListener("resize", this._onCanvasTargetResize);
30452  }
30453  /**
30454   * Returns the current canvas target.
30455   *
30456   * @return {CanvasTarget} The current canvas target.
30457   */
30458  getCanvasTarget() {
30459    return this._canvasTarget;
30460  }
30461  /**
30462   * Resets the renderer to the initial state before WebXR started.
30463   *
30464   * @private
30465   */
30466  _resetXRState() {
30467    this.backend.setXRTarget(null);
30468    this.setOutputRenderTarget(null);
30469    this.setRenderTarget(null);
30470    for (const canvasTarget of this._frameBufferTargets.keys()) {
30471      canvasTarget.dispose();
30472    }
30473  }
30474  /**
30475   * Callback for {@link Renderer#setRenderObjectFunction}.
30476   *
30477   * @callback renderObjectFunction
30478   * @param {Object3D} object - The 3D object.
30479   * @param {Scene} scene - The scene the 3D object belongs to.
30480   * @param {Camera} camera - The camera the object should be rendered with.
30481   * @param {BufferGeometry} geometry - The object's geometry.
30482   * @param {Material} material - The object's material.
30483   * @param {?Object} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
30484   * @param {LightsNode} lightsNode - The current lights node.
30485   * @param {ClippingContext} clippingContext - The clipping context.
30486   * @param {?string} [passId=null] - An optional ID for identifying the pass.
30487   */
30488  /**
30489   * Sets the given render object function. Calling this method overwrites the default implementation
30490   * which is {@link Renderer#renderObject}. Defining a custom function can be useful
30491   * if you want to modify the way objects are rendered. For example you can define things like "every
30492   * object that has material of a certain type should perform a pre-pass with a special overwrite material".
30493   * The custom function must always call `renderObject()` in its implementation.
30494   *
30495   * Use `null` as the first argument to reset the state.
30496   *
30497   * @param {?renderObjectFunction} renderObjectFunction - The render object function.
30498   */
30499  setRenderObjectFunction(renderObjectFunction) {
30500    this._renderObjectFunction = renderObjectFunction;
30501  }
30502  /**
30503   * Returns the current render object function.
30504   *
30505   * @return {?Function} The current render object function. Returns `null` if no function is set.
30506   */
30507  getRenderObjectFunction() {
30508    return this._renderObjectFunction;
30509  }
30510  /**
30511   * Execute a single or an array of compute nodes. This method can only be called
30512   * if the renderer has been initialized.
30513   *
30514   * @param {Node|Array<Node>} computeNodes - The compute node(s).
30515   * @param {number|Array<number>|IndirectStorageBufferAttribute} [dispatchSize=null]
30516   * - A single number representing count, or
30517   * - An array [x, y, z] representing dispatch size, or
30518   * - A IndirectStorageBufferAttribute for indirect dispatch size.
30519   * @return {Promise|undefined} A Promise that resolve when the compute has finished. Only returned when the renderer has not been initialized.
30520   */
30521  compute(computeNodes, dispatchSize = null) {
30522    if (this._isDeviceLost === true) return;
30523    if (this._initialized === false) {
30524      warn("Renderer: .compute() called before the backend is initialized. Try using .computeAsync() instead.");
30525      return this.computeAsync(computeNodes, dispatchSize);
30526    }
30527    const nodeFrame = this._nodes.nodeFrame;
30528    const previousRenderId = nodeFrame.renderId;
30529    this.info.calls++;
30530    this.info.compute.calls++;
30531    this.info.compute.frameCalls++;
30532    nodeFrame.renderId = this.info.calls;
30533    this.backend.updateTimeStampUID(computeNodes);
30534    this.inspector.beginCompute(this.backend.getTimestampUID(computeNodes), computeNodes);
30535    const backend = this.backend;
30536    const pipelines = this._pipelines;
30537    const bindings = this._bindings;
30538    const nodes = this._nodes;
30539    const computeList = Array.isArray(computeNodes) ? computeNodes : [computeNodes];
30540    if (computeList[0] === void 0 || computeList[0].isComputeNode !== true) {
30541      throw new Error("THREE.Renderer: .compute() expects a ComputeNode.");
30542    }
30543    backend.beginCompute(computeNodes);
30544    for (const computeNode of computeList) {
30545      if (pipelines.has(computeNode) === false) {
30546        const dispose2 = () => {
30547          computeNode.removeEventListener("dispose", dispose2);
30548          pipelines.delete(computeNode);
30549          bindings.deleteForCompute(computeNode);
30550          nodes.delete(computeNode);
30551        };
30552        computeNode.addEventListener("dispose", dispose2);
30553        const onInitFn = computeNode.onInitFunction;
30554        if (onInitFn !== null) {
30555          onInitFn.call(computeNode, { renderer: this });
30556        }
30557      }
30558      nodes.updateForCompute(computeNode);
30559      bindings.updateForCompute(computeNode);
30560      const computeBindings = bindings.getForCompute(computeNode);
30561      const computePipeline = pipelines.getForCompute(computeNode, computeBindings);
30562      backend.compute(computeNodes, computeNode, computeBindings, computePipeline, dispatchSize);
30563    }
30564    backend.finishCompute(computeNodes);
30565    nodeFrame.renderId = previousRenderId;
30566    this.inspector.finishCompute(this.backend.getTimestampUID(computeNodes));
30567  }
30568  /**
30569   * Execute a single or an array of compute nodes.
30570   *
30571   * @async
30572   * @param {Node|Array<Node>} computeNodes - The compute node(s).
30573   * @param {number|Array<number>|IndirectStorageBufferAttribute} [dispatchSize=null]
30574   * - A single number representing count, or
30575   * - An array [x, y, z] representing dispatch size, or
30576   * - A IndirectStorageBufferAttribute for indirect dispatch size.
30577   * @return {Promise} A Promise that resolve when the compute has finished.
30578   */
30579  async computeAsync(computeNodes, dispatchSize = null) {
30580    if (this._initialized === false) await this.init();
30581    this.compute(computeNodes, dispatchSize);
30582  }
30583  /**
30584   * Checks if the given feature is supported by the selected backend.
30585   *
30586   * @async
30587   * @deprecated
30588   * @param {string} name - The feature's name.
30589   * @return {Promise<boolean>} A Promise that resolves with a bool that indicates whether the feature is supported or not.
30590   */
30591  async hasFeatureAsync(name) {
30592    warnOnce('Renderer: "hasFeatureAsync()" has been deprecated. Use "hasFeature()" and "await renderer.init();" when creating the renderer.');
30593    await this.init();
30594    return this.hasFeature(name);
30595  }
30596  async resolveTimestampsAsync(type = "render") {
30597    if (this._initialized === false) await this.init();
30598    return this.backend.resolveTimestampsAsync(type);
30599  }
30600  /**
30601   * Checks if the given feature is supported by the selected backend. If the
30602   * renderer has not been initialized, this method always returns `false`.
30603   *
30604   * @param {string} name - The feature's name.
30605   * @return {boolean} Whether the feature is supported or not.
30606   */
30607  hasFeature(name) {
30608    if (this._initialized === false) {
30609      throw new Error('Renderer: .hasFeature() called before the backend is initialized. Use "await renderer.init();" before before using this method.');
30610    }
30611    return this.backend.hasFeature(name);
30612  }
30613  /**
30614   * Returns `true` when the renderer has been initialized.
30615   *
30616   * @return {boolean} Whether the renderer has been initialized or not.
30617   */
30618  hasInitialized() {
30619    return this._initialized;
30620  }
30621  /**
30622   * Initializes the given textures. Useful for preloading a texture rather than waiting until first render
30623   * (which can cause noticeable lags due to decode and GPU upload overhead).
30624   *
30625   * @async
30626   * @deprecated
30627   * @param {Texture} texture - The texture.
30628   * @return {Promise} A Promise that resolves when the texture has been initialized.
30629   */
30630  async initTextureAsync(texture3) {
30631    warnOnce('Renderer: "initTextureAsync()" has been deprecated. Use "initTexture()" and "await renderer.init();" when creating the renderer.');
30632    await this.init();
30633    this.initTexture(texture3);
30634  }
30635  /**
30636   * Initializes the given texture. Useful for preloading a texture rather than waiting until first render
30637   * (which can cause noticeable lags due to decode and GPU upload overhead).
30638   *
30639   * This method can only be used if the renderer has been initialized.
30640   *
30641   * @param {Texture} texture - The texture.
30642   */
30643  initTexture(texture3) {
30644    if (this._initialized === false) {
30645      throw new Error('Renderer: .initTexture() called before the backend is initialized. Use "await renderer.init();" before before using this method.');
30646    }
30647    this._textures.updateTexture(texture3);
30648  }
30649  /**
30650   * Initializes the given render target.
30651   *
30652   * @param {RenderTarget} renderTarget - The render target to intialize.
30653   */
30654  initRenderTarget(renderTarget) {
30655    if (this._initialized === false) {
30656      throw new Error('Renderer: .initRenderTarget() called before the backend is initialized. Use "await renderer.init();" before before using this method.');
30657    }
30658    this._textures.updateRenderTarget(renderTarget);
30659    const renderTargetData = this._textures.get(renderTarget);
30660    const renderContext = this._renderContexts.get(renderTarget);
30661    renderContext.textures = renderTargetData.textures;
30662    renderContext.depthTexture = renderTargetData.depthTexture;
30663    renderContext.width = renderTargetData.width;
30664    renderContext.height = renderTargetData.height;
30665    renderContext.renderTarget = renderTarget;
30666    renderContext.depth = renderTarget.depthBuffer;
30667    renderContext.stencil = renderTarget.stencilBuffer;
30668    this.backend.initRenderTarget(renderContext);
30669  }
30670  /**
30671   * Copies the current bound framebuffer into the given texture.
30672   *
30673   * @param {FramebufferTexture} framebufferTexture - The texture.
30674   * @param {?(Vector2|Vector4)} [rectangle=null] - A two or four dimensional vector that defines the rectangular portion of the framebuffer that should be copied.
30675   */
30676  copyFramebufferToTexture(framebufferTexture, rectangle = null) {
30677    if (rectangle !== null) {
30678      if (rectangle.isVector2) {
30679        rectangle = _vector4.set(rectangle.x, rectangle.y, framebufferTexture.image.width, framebufferTexture.image.height).floor();
30680      } else if (rectangle.isVector4) {
30681        rectangle = _vector4.copy(rectangle).floor();
30682      } else {
30683        error("Renderer.copyFramebufferToTexture: Invalid rectangle.");
30684        return;
30685      }
30686    } else {
30687      rectangle = _vector4.set(0, 0, framebufferTexture.image.width, framebufferTexture.image.height);
30688    }
30689    let renderContext = this._currentRenderContext;
30690    let renderTarget;
30691    if (renderContext !== null) {
30692      renderTarget = renderContext.renderTarget;
30693    } else {
30694      renderTarget = this._renderTarget || this._getFrameBufferTarget();
30695      if (renderTarget !== null) {
30696        this._textures.updateRenderTarget(renderTarget);
30697        renderContext = this._textures.get(renderTarget);
30698      }
30699    }
30700    this._textures.updateTexture(framebufferTexture, { renderTarget });
30701    this.backend.copyFramebufferToTexture(framebufferTexture, renderContext, rectangle);
30702    this._inspector.copyFramebufferToTexture(framebufferTexture);
30703  }
30704  /**
30705   * Copies data of the given source texture into a destination texture.
30706   *
30707   * @param {Texture} srcTexture - The source texture.
30708   * @param {Texture} dstTexture - The destination texture.
30709   * @param {Box2|Box3} [srcRegion=null] - A bounding box which describes the source region. Can be two or three-dimensional.
30710   * @param {Vector2|Vector3} [dstPosition=null] - A vector that represents the origin of the destination region. Can be two or three-dimensional.
30711   * @param {number} [srcLevel=0] - The source mip level to copy from.
30712   * @param {number} [dstLevel=0] - The destination mip level to copy to.
30713   */
30714  copyTextureToTexture(srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0) {
30715    this._textures.updateTexture(srcTexture);
30716    this._textures.updateTexture(dstTexture);
30717    this.backend.copyTextureToTexture(srcTexture, dstTexture, srcRegion, dstPosition, srcLevel, dstLevel);
30718    this._inspector.copyTextureToTexture(srcTexture, dstTexture);
30719  }
30720  /**
30721   * Reads pixel data from the given render target.
30722   *
30723   * @async
30724   * @param {RenderTarget} renderTarget - The render target to read from.
30725   * @param {number} x - The `x` coordinate of the copy region's origin.
30726   * @param {number} y - The `y` coordinate of the copy region's origin.
30727   * @param {number} width - The width of the copy region.
30728   * @param {number} height - The height of the copy region.
30729   * @param {number} [textureIndex=0] - The texture index of a MRT render target.
30730   * @param {number} [faceIndex=0] - The active cube face index.
30731   * @return {Promise<TypedArray>} A Promise that resolves when the read has been finished. The resolve provides the read data as a typed array.
30732   */
30733  async readRenderTargetPixelsAsync(renderTarget, x, y, width, height, textureIndex = 0, faceIndex = 0) {
30734    return this.backend.copyTextureToBuffer(renderTarget.textures[textureIndex], x, y, width, height, faceIndex);
30735  }
30736  /**
30737   * Analyzes the given 3D object's hierarchy and builds render lists from the
30738   * processed hierarchy.
30739   *
30740   * @private
30741   * @param {Object3D} object - The 3D object to process (usually a scene).
30742   * @param {Camera} camera - The camera the object is rendered with.
30743   * @param {number} groupOrder - The group order is derived from the `renderOrder` of groups and is used to group 3D objects within groups.
30744   * @param {RenderList} renderList - The current render list.
30745   * @param {ClippingContext} clippingContext - The current clipping context.
30746   */
30747  _projectObject(object, camera, groupOrder, renderList, clippingContext) {
30748    if (object.visible === false) return;
30749    const visible = object.layers.test(camera.layers);
30750    if (visible) {
30751      if (object.isGroup) {
30752        groupOrder = object.renderOrder;
30753        if (object.isClippingGroup && object.enabled) clippingContext = clippingContext.getGroupContext(object);
30754      } else if (object.isLOD) {
30755        if (object.autoUpdate === true) object.update(camera);
30756      } else if (object.isLight) {
30757        renderList.pushLight(object);
30758      } else if (object.isSprite) {
30759        const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
30760        if (!object.frustumCulled || frustum.intersectsSprite(object, camera)) {
30761          if (this.sortObjects === true) {
30762            _vector4.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix);
30763          }
30764          const { geometry, material } = object;
30765          if (material.visible) {
30766            renderList.push(object, geometry, material, groupOrder, _vector4.z, null, clippingContext);
30767          }
30768        }
30769      } else if (object.isLineLoop) {
30770        error("Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.");
30771      } else if (object.isMesh || object.isLine || object.isPoints) {
30772        const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
30773        if (!object.frustumCulled || frustum.intersectsObject(object, camera)) {
30774          const { geometry, material } = object;
30775          if (this.sortObjects === true) {
30776            if (geometry.boundingSphere === null) geometry.computeBoundingSphere();
30777            _vector4.copy(geometry.boundingSphere.center).applyMatrix4(object.matrixWorld).applyMatrix4(_projScreenMatrix);
30778          }
30779          if (Array.isArray(material)) {
30780            const groups = geometry.groups;
30781            for (let i = 0, l = groups.length; i < l; i++) {
30782              const group = groups[i];
30783              const groupMaterial = material[group.materialIndex];
30784              if (groupMaterial && groupMaterial.visible) {
30785                renderList.push(object, geometry, groupMaterial, groupOrder, _vector4.z, group, clippingContext);
30786              }
30787            }
30788          } else if (material.visible) {
30789            renderList.push(object, geometry, material, groupOrder, _vector4.z, null, clippingContext);
30790          }
30791        }
30792      }
30793    }
30794    if (object.isBundleGroup === true && this.backend.beginBundle !== void 0) {
30795      const baseRenderList = renderList;
30796      renderList = this._renderLists.get(object, camera);
30797      renderList.begin();
30798      baseRenderList.pushBundle({
30799        bundleGroup: object,
30800        camera,
30801        renderList
30802      });
30803      renderList.finish();
30804    }
30805    const children2 = object.children;
30806    for (let i = 0, l = children2.length; i < l; i++) {
30807      this._projectObject(children2[i], camera, groupOrder, renderList, clippingContext);
30808    }
30809  }
30810  /**
30811   * Renders the given render bundles.
30812   *
30813   * @private
30814   * @param {Array<Object>} bundles - Array with render bundle data.
30815   * @param {Scene} sceneRef - The scene the render bundles belong to.
30816   * @param {LightsNode} lightsNode - The current lights node.
30817   */
30818  _renderBundles(bundles, sceneRef, lightsNode) {
30819    for (const bundle of bundles) {
30820      this._renderBundle(bundle, sceneRef, lightsNode);
30821    }
30822  }
30823  /**
30824   * Renders the transparent objects from the given render lists.
30825   *
30826   * @private
30827   * @param {Array<Object>} renderList - The transparent render list.
30828   * @param {Array<Object>} doublePassList - The list of transparent objects which require a double pass (e.g. because of transmission).
30829   * @param {Camera} camera - The camera the render list should be rendered with.
30830   * @param {Scene} scene - The scene the render list belongs to.
30831   * @param {LightsNode} lightsNode - The current lights node.
30832   */
30833  _renderTransparents(renderList, doublePassList, camera, scene, lightsNode) {
30834    if (doublePassList.length > 0) {
30835      for (const { material } of doublePassList) {
30836        material.side = BackSide;
30837      }
30838      this._renderObjects(doublePassList, camera, scene, lightsNode, "backSide");
30839      for (const { material } of doublePassList) {
30840        material.side = FrontSide;
30841      }
30842      this._renderObjects(renderList, camera, scene, lightsNode);
30843      for (const { material } of doublePassList) {
30844        material.side = DoubleSide;
30845      }
30846    } else {
30847      this._renderObjects(renderList, camera, scene, lightsNode);
30848    }
30849  }
30850  /**
30851   * Renders the objects from the given render list.
30852   *
30853   * @private
30854   * @param {Array<Object>} renderList - The render list.
30855   * @param {Camera} camera - The camera the render list should be rendered with.
30856   * @param {Scene} scene - The scene the render list belongs to.
30857   * @param {LightsNode} lightsNode - The current lights node.
30858   * @param {?string} [passId=null] - An optional ID for identifying the pass.
30859   */
30860  _renderObjects(renderList, camera, scene, lightsNode, passId = null) {
30861    for (let i = 0, il = renderList.length; i < il; i++) {
30862      const { object, geometry, material, group, clippingContext } = renderList[i];
30863      this._currentRenderObjectFunction(object, scene, camera, geometry, material, group, lightsNode, clippingContext, passId);
30864    }
30865  }
30866  /**
30867   * Retrieves shadow nodes for the given material. This is used to setup shadow passes.
30868   * The result is cached per material and updated when the material's version changes.
30869   *
30870   * @private
30871   * @param {Material} material
30872   * @returns {Object} - The shadow nodes for the material.
30873   */
30874  _getShadowNodes(material) {
30875    const version = material.version;
30876    let cache4 = this._cacheShadowNodes.get(material);
30877    if (cache4 === void 0 || cache4.version !== version) {
30878      const hasMap = material.map !== null;
30879      const hasColorNode = material.colorNode && material.colorNode.isNode;
30880      const hasCastShadowNode = material.castShadowNode && material.castShadowNode.isNode;
30881      const hasMaskNode = material.maskShadowNode && material.maskShadowNode.isNode || material.maskNode && material.maskNode.isNode;
30882      let positionNode = null;
30883      let colorNode = null;
30884      let depthNode = null;
30885      if (hasMap || hasColorNode || hasCastShadowNode || hasMaskNode) {
30886        let shadowRGB;
30887        let shadowAlpha;
30888        if (hasCastShadowNode) {
30889          shadowRGB = material.castShadowNode.rgb;
30890          shadowAlpha = material.castShadowNode.a;
30891          if (this.shadowMap.transmitted !== true) {
30892            warnOnce("Renderer: `shadowMap.transmitted` needs to be set to `true` when using `material.castShadowNode`.");
30893          }
30894        } else {
30895          shadowRGB = vec3(0);
30896          shadowAlpha = float(1);
30897        }
30898        if (hasMap) {
30899          shadowAlpha = shadowAlpha.mul(reference("map", "texture", material).a);
30900        }
30901        if (hasColorNode) {
30902          shadowAlpha = shadowAlpha.mul(material.colorNode.a);
30903        }
30904        colorNode = vec4(shadowRGB, shadowAlpha);
30905        if (hasMaskNode) {
30906          const maskNode = material.maskShadowNode || material.maskNode;
30907          colorNode = Fn(([color3]) => {
30908            maskNode.not().discard();
30909            return color3;
30910          })(colorNode);
30911        }
30912      }
30913      if (material.depthNode && material.depthNode.isNode) {
30914        depthNode = material.depthNode;
30915      }
30916      if (material.castShadowPositionNode && material.castShadowPositionNode.isNode) {
30917        positionNode = material.castShadowPositionNode;
30918      } else if (material.positionNode && material.positionNode.isNode) {
30919        positionNode = material.positionNode;
30920      }
30921      cache4 = {
30922        version,
30923        colorNode,
30924        depthNode,
30925        positionNode
30926      };
30927      this._cacheShadowNodes.set(material, cache4);
30928    }
30929    return cache4;
30930  }
30931  /**
30932   * This method represents the default render object function that manages the render lifecycle
30933   * of the object.
30934   *
30935   * @param {Object3D} object - The 3D object.
30936   * @param {Scene} scene - The scene the 3D object belongs to.
30937   * @param {Camera} camera - The camera the object should be rendered with.
30938   * @param {BufferGeometry} geometry - The object's geometry.
30939   * @param {Material} material - The object's material.
30940   * @param {?Object} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
30941   * @param {LightsNode} lightsNode - The current lights node.
30942   * @param {?ClippingContext} clippingContext - The clipping context.
30943   * @param {?string} [passId=null] - An optional ID for identifying the pass.
30944   */
30945  renderObject(object, scene, camera, geometry, material, group, lightsNode, clippingContext = null, passId = null) {
30946    let materialOverride = false;
30947    let materialColorNode;
30948    let materialDepthNode;
30949    let materialPositionNode;
30950    let materialSide;
30951    object.onBeforeRender(this, scene, camera, geometry, material, group);
30952    if (material.allowOverride === true && scene.overrideMaterial !== null) {
30953      const overrideMaterial = scene.overrideMaterial;
30954      materialOverride = true;
30955      materialColorNode = overrideMaterial.isNodeMaterial ? overrideMaterial.colorNode : null;
30956      materialDepthNode = overrideMaterial.isNodeMaterial ? overrideMaterial.depthNode : null;
30957      materialPositionNode = overrideMaterial.isNodeMaterial ? overrideMaterial.positionNode : null;
30958      materialSide = scene.overrideMaterial.side;
30959      if (material.positionNode && material.positionNode.isNode) {
30960        overrideMaterial.positionNode = material.positionNode;
30961      }
30962      overrideMaterial.alphaTest = material.alphaTest;
30963      overrideMaterial.alphaMap = material.alphaMap;
30964      overrideMaterial.transparent = material.transparent || material.transmission > 0 || material.transmissionNode && material.transmissionNode.isNode || material.backdropNode && material.backdropNode.isNode;
30965      if (overrideMaterial.isShadowPassMaterial) {
30966        const { colorNode, depthNode, positionNode } = this._getShadowNodes(material);
30967        if (this.shadowMap.type === VSMShadowMap) {
30968          overrideMaterial.side = material.shadowSide !== null ? material.shadowSide : material.side;
30969        } else {
30970          overrideMaterial.side = material.shadowSide !== null ? material.shadowSide : _shadowSide[material.side];
30971        }
30972        if (colorNode !== null) overrideMaterial.colorNode = colorNode;
30973        if (depthNode !== null) overrideMaterial.depthNode = depthNode;
30974        if (positionNode !== null) overrideMaterial.positionNode = positionNode;
30975      }
30976      material = overrideMaterial;
30977    }
30978    if (material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false) {
30979      material.side = BackSide;
30980      this._handleObjectFunction(object, material, scene, camera, lightsNode, group, clippingContext, "backSide");
30981      material.side = FrontSide;
30982      this._handleObjectFunction(object, material, scene, camera, lightsNode, group, clippingContext, passId);
30983      material.side = DoubleSide;
30984    } else {
30985      this._handleObjectFunction(object, material, scene, camera, lightsNode, group, clippingContext, passId);
30986    }
30987    if (materialOverride) {
30988      scene.overrideMaterial.colorNode = materialColorNode;
30989      scene.overrideMaterial.depthNode = materialDepthNode;
30990      scene.overrideMaterial.positionNode = materialPositionNode;
30991      scene.overrideMaterial.side = materialSide;
30992    }
30993    object.onAfterRender(this, scene, camera, geometry, material, group);
30994  }
30995  /**
30996   * Checks if the given compatibility is supported by the selected backend.
30997   *
30998   * @param {string} name - The compatibility's name.
30999   * @return {boolean} Whether the compatibility is supported or not.
31000   */
31001  hasCompatibility(name) {
31002    if (this._initialized === false) {
31003      throw new Error('Renderer: .hasCompatibility() called before the backend is initialized. Use "await renderer.init();" before using this method.');
31004    }
31005    return this.backend.hasCompatibility(name);
31006  }
31007  /**
31008   * This method represents the default `_handleObjectFunction` implementation which creates
31009   * a render object from the given data and performs the draw command with the selected backend.
31010   *
31011   * @private
31012   * @param {Object3D} object - The 3D object.
31013   * @param {Material} material - The object's material.
31014   * @param {Scene} scene - The scene the 3D object belongs to.
31015   * @param {Camera} camera - The camera the object should be rendered with.
31016   * @param {LightsNode} lightsNode - The current lights node.
31017   * @param {?{start: number, count: number}} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
31018   * @param {ClippingContext} clippingContext - The clipping context.
31019   * @param {string} [passId] - An optional ID for identifying the pass.
31020   */
31021  _renderObjectDirect(object, material, scene, camera, lightsNode, group, clippingContext, passId) {
31022    const renderObject = this._objects.get(object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId);
31023    renderObject.drawRange = object.geometry.drawRange;
31024    renderObject.group = group;
31025    if (this._currentRenderBundle !== null) {
31026      const renderBundleData = this.backend.get(this._currentRenderBundle);
31027      renderBundleData.renderObjects.push(renderObject);
31028      renderObject.bundle = this._currentRenderBundle.bundleGroup;
31029    }
31030    const needsRefresh = this._nodes.needsRefresh(renderObject);
31031    if (needsRefresh) {
31032      this._nodes.updateBefore(renderObject);
31033      this._geometries.updateForRender(renderObject);
31034      this._nodes.updateForRender(renderObject);
31035      this._bindings.updateForRender(renderObject);
31036    }
31037    this._pipelines.updateForRender(renderObject);
31038    if (this._pipelines.isReady(renderObject)) {
31039      this.backend.draw(renderObject, this.info);
31040      if (needsRefresh) this._nodes.updateAfter(renderObject);
31041    }
31042  }
31043  /**
31044   * A different implementation for `_handleObjectFunction` which only makes sure the object is ready for rendering.
31045   * Used in `compileAsync()`.
31046   *
31047   * @private
31048   * @param {Object3D} object - The 3D object.
31049   * @param {Material} material - The object's material.
31050   * @param {Scene} scene - The scene the 3D object belongs to.
31051   * @param {Camera} camera - The camera the object should be rendered with.
31052   * @param {LightsNode} lightsNode - The current lights node.
31053   * @param {?{start: number, count: number}} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
31054   * @param {ClippingContext} clippingContext - The clipping context.
31055   * @param {string} [passId] - An optional ID for identifying the pass.
31056   */
31057  _createObjectPipeline(object, material, scene, camera, lightsNode, group, clippingContext, passId) {
31058    if (this._compilationPromises !== null) {
31059      this._compilationPromises.push({
31060        object,
31061        material,
31062        scene,
31063        camera,
31064        lightsNode,
31065        group,
31066        clippingContext,
31067        passId,
31068        renderContext: this._currentRenderContext
31069      });
31070      return;
31071    }
31072    const renderObject = this._objects.get(object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId);
31073    renderObject.drawRange = object.geometry.drawRange;
31074    renderObject.group = group;
31075    this._nodes.updateBefore(renderObject);
31076    this._geometries.updateForRender(renderObject);
31077    this._nodes.updateForRender(renderObject);
31078    this._bindings.updateForRender(renderObject);
31079    this._pipelines.getForRender(renderObject, this._compilationPromises);
31080    this._nodes.updateAfter(renderObject);
31081  }
31082  /**
31083   * Callback when the canvas has been resized.
31084   *
31085   * @private
31086   */
31087  _onCanvasTargetResize() {
31088    if (this._initialized) this.backend.updateSize();
31089  }
31090  /**
31091   * Alias for `compileAsync()`.
31092   *
31093   * @method
31094   * @param {Object3D} scene - The scene or 3D object to precompile.
31095   * @param {Camera} camera - The camera that is used to render the scene.
31096   * @param {Scene} targetScene - If the first argument is a 3D object, this parameter must represent the scene the 3D object is going to be added.
31097   * @return {function(Object3D, Camera, ?Scene): Promise|undefined} A Promise that resolves when the compile has been finished.
31098   */
31099  get compile() {
31100    return this.compileAsync;
31101  }
31102};
31103var Binding = class {
31104  /**
31105   * Constructs a new binding.
31106   *
31107   * @param {string} [name=''] - The binding's name.
31108   */
31109  constructor(name = "") {
31110    this.name = name;
31111    this.visibility = 0;
31112  }
31113  /**
31114   * Makes sure binding's resource is visible for the given shader stage.
31115   *
31116   * @param {number} visibility - The shader stage.
31117   */
31118  setVisibility(visibility) {
31119    this.visibility |= visibility;
31120  }
31121  /**
31122   * The shader stages in which the binding's resource is visible.
31123   *
31124   * @return {number} The visibility bitmask.
31125   */
31126  getVisibility() {
31127    return this.visibility;
31128  }
31129  /**
31130   * Clones the binding.
31131   *
31132   * @return {Binding} The cloned binding.
31133   */
31134  clone() {
31135    return Object.assign(new this.constructor(), this);
31136  }
31137};
31138function getFloatLength(floatLength) {
31139  return floatLength + (GPU_CHUNK_BYTES - floatLength % GPU_CHUNK_BYTES) % GPU_CHUNK_BYTES;
31140}
31141var Buffer = class extends Binding {
31142  /**
31143   * Constructs a new buffer.
31144   *
31145   * @param {string} name - The buffer's name.
31146   * @param {TypedArray} [buffer=null] - The buffer.
31147   */
31148  constructor(name, buffer3 = null) {
31149    super(name);
31150    this.isBuffer = true;
31151    this.bytesPerElement = Float32Array.BYTES_PER_ELEMENT;
31152    this._buffer = buffer3;
31153    this._updateRanges = [];
31154  }
31155  /**
31156   * The array of update ranges.
31157   *
31158   * @type {Array<{start: number, count: number}>}
31159   */
31160  get updateRanges() {
31161    return this._updateRanges;
31162  }
31163  /**
31164   * Adds an update range.
31165   *
31166   * @param {number} start - The start index.
31167   * @param {number} count - The number of elements.
31168   */
31169  addUpdateRange(start, count) {
31170    this.updateRanges.push({ start, count });
31171  }
31172  /**
31173   * Clears all update ranges.
31174   */
31175  clearUpdateRanges() {
31176    this.updateRanges.length = 0;
31177  }
31178  /**
31179   * The buffer's byte length.
31180   *
31181   * @type {number}
31182   * @readonly
31183   */
31184  get byteLength() {
31185    return getFloatLength(this._buffer.byteLength);
31186  }
31187  /**
31188   * A reference to the internal buffer.
31189   *
31190   * @type {Float32Array}
31191   * @readonly
31192   */
31193  get buffer() {
31194    return this._buffer;
31195  }
31196  /**
31197   * Updates the binding.
31198   *
31199   * @return {boolean} Whether the buffer has been updated and must be
31200   * uploaded to the GPU.
31201   */
31202  update() {
31203    return true;
31204  }
31205};
31206var UniformBuffer = class extends Buffer {
31207  /**
31208   * Constructs a new uniform buffer.
31209   *
31210   * @param {string} name - The buffer's name.
31211   * @param {TypedArray} [buffer=null] - The buffer.
31212   */
31213  constructor(name, buffer3 = null) {
31214    super(name, buffer3);
31215    this.isUniformBuffer = true;
31216  }
31217};
31218var _id$4 = 0;
31219var NodeUniformBuffer = class extends UniformBuffer {
31220  /**
31221   * Constructs a new node-based uniform buffer.
31222   *
31223   * @param {BufferNode} nodeUniform - The uniform buffer node.
31224   * @param {UniformGroupNode} groupNode - The uniform group node.
31225   */
31226  constructor(nodeUniform, groupNode) {
31227    super("UniformBuffer_" + _id$4++, nodeUniform ? nodeUniform.value : null);
31228    this.nodeUniform = nodeUniform;
31229    this.groupNode = groupNode;
31230    this.isNodeUniformBuffer = true;
31231  }
31232  /**
31233   * The array of update ranges.
31234   *
31235   * @param {Array<{start: number, count: number}>} value - The update ranges.
31236   */
31237  set updateRanges(value) {
31238    this.nodeUniform.updateRanges = value;
31239  }
31240  /**
31241   * The array of update ranges.
31242   *
31243   * @type {Array<{start: number, count: number}>}
31244   */
31245  get updateRanges() {
31246    return this.nodeUniform.updateRanges;
31247  }
31248  /**
31249   * Adds a range of data in the data array to be updated on the GPU.
31250   *
31251   * @param {number} start - Position at which to start update.
31252   * @param {number} count - The number of components to update.
31253   */
31254  addUpdateRange(start, count) {
31255    this.nodeUniform.addUpdateRange(start, count);
31256  }
31257  /**
31258   * Clears all update ranges.
31259   */
31260  clearUpdateRanges() {
31261    this.nodeUniform.clearUpdateRanges();
31262  }
31263  /**
31264   * The uniform buffer.
31265   *
31266   * @type {Float32Array}
31267   */
31268  get buffer() {
31269    return this.nodeUniform.value;
31270  }
31271};
31272var UniformsGroup2 = class extends UniformBuffer {
31273  /**
31274   * Constructs a new uniforms group.
31275   *
31276   * @param {string} name - The group's name.
31277   */
31278  constructor(name) {
31279    super(name);
31280    this.isUniformsGroup = true;
31281    this._values = null;
31282    this.uniforms = [];
31283    this._updateRangeCache = /* @__PURE__ */ new Map();
31284  }
31285  /**
31286   * Adds a uniform's update range to this buffer.
31287   *
31288   * @param {Uniform} uniform - The uniform.
31289   */
31290  addUniformUpdateRange(uniform3) {
31291    const index = uniform3.index;
31292    if (this._updateRangeCache.has(index) !== true) {
31293      const updateRanges = this.updateRanges;
31294      const start = uniform3.offset;
31295      const count = uniform3.itemSize;
31296      const range3 = { start, count };
31297      updateRanges.push(range3);
31298      this._updateRangeCache.set(index, range3);
31299    }
31300  }
31301  /**
31302   * Clears all update ranges of this buffer.
31303   */
31304  clearUpdateRanges() {
31305    this._updateRangeCache.clear();
31306    super.clearUpdateRanges();
31307  }
31308  /**
31309   * Adds a uniform to this group.
31310   *
31311   * @param {Uniform} uniform - The uniform to add.
31312   * @return {UniformsGroup} A reference to this group.
31313   */
31314  addUniform(uniform3) {
31315    this.uniforms.push(uniform3);
31316    return this;
31317  }
31318  /**
31319   * Removes a uniform from this group.
31320   *
31321   * @param {Uniform} uniform - The uniform to remove.
31322   * @return {UniformsGroup} A reference to this group.
31323   */
31324  removeUniform(uniform3) {
31325    const index = this.uniforms.indexOf(uniform3);
31326    if (index !== -1) {
31327      this.uniforms.splice(index, 1);
31328    }
31329    return this;
31330  }
31331  /**
31332   * An array with the raw uniform values.
31333   *
31334   * @type {Array<number>}
31335   */
31336  get values() {
31337    if (this._values === null) {
31338      this._values = Array.from(this.buffer);
31339    }
31340    return this._values;
31341  }
31342  /**
31343   * A Float32 array buffer with the uniform values.
31344   *
31345   * @type {Float32Array}
31346   */
31347  get buffer() {
31348    let buffer3 = this._buffer;
31349    if (buffer3 === null) {
31350      const byteLength = this.byteLength;
31351      buffer3 = new Float32Array(new ArrayBuffer(byteLength));
31352      this._buffer = buffer3;
31353    }
31354    return buffer3;
31355  }
31356  /**
31357   * The byte length of the buffer with correct buffer alignment.
31358   *
31359   * @type {number}
31360   */
31361  get byteLength() {
31362    const bytesPerElement = this.bytesPerElement;
31363    let offset3 = 0;
31364    for (let i = 0, l = this.uniforms.length; i < l; i++) {
31365      const uniform3 = this.uniforms[i];
31366      const boundary = uniform3.boundary;
31367      const itemSize = uniform3.itemSize * bytesPerElement;
31368      const chunkOffset = offset3 % GPU_CHUNK_BYTES;
31369      const chunkPadding = chunkOffset % boundary;
31370      const chunkStart = chunkOffset + chunkPadding;
31371      offset3 += chunkPadding;
31372      if (chunkStart !== 0 && GPU_CHUNK_BYTES - chunkStart < itemSize) {
31373        offset3 += GPU_CHUNK_BYTES - chunkStart;
31374      }
31375      uniform3.offset = offset3 / bytesPerElement;
31376      uniform3.index = i;
31377      offset3 += itemSize;
31378    }
31379    return Math.ceil(offset3 / GPU_CHUNK_BYTES) * GPU_CHUNK_BYTES;
31380  }
31381  /**
31382   * Updates this group by updating each uniform object of
31383   * the internal uniform list. The uniform objects check if their
31384   * values has actually changed so this method only returns
31385   * `true` if there is a real value change.
31386   *
31387   * @return {boolean} Whether the uniforms have been updated and
31388   * must be uploaded to the GPU.
31389   */
31390  update() {
31391    let updated = false;
31392    for (const uniform3 of this.uniforms) {
31393      if (this.updateByType(uniform3) === true) {
31394        updated = true;
31395      }
31396    }
31397    return updated;
31398  }
31399  /**
31400   * Updates a given uniform by calling an update method matching
31401   * the uniforms type.
31402   *
31403   * @param {Uniform} uniform - The uniform to update.
31404   * @return {boolean} Whether the uniform has been updated or not.
31405   */
31406  updateByType(uniform3) {
31407    if (uniform3.isNumberUniform) return this.updateNumber(uniform3);
31408    if (uniform3.isVector2Uniform) return this.updateVector2(uniform3);
31409    if (uniform3.isVector3Uniform) return this.updateVector3(uniform3);
31410    if (uniform3.isVector4Uniform) return this.updateVector4(uniform3);
31411    if (uniform3.isColorUniform) return this.updateColor(uniform3);
31412    if (uniform3.isMatrix3Uniform) return this.updateMatrix3(uniform3);
31413    if (uniform3.isMatrix4Uniform) return this.updateMatrix4(uniform3);
31414    error("WebGPUUniformsGroup: Unsupported uniform type.", uniform3);
31415  }
31416  /**
31417   * Updates a given Number uniform.
31418   *
31419   * @param {NumberUniform} uniform - The Number uniform.
31420   * @return {boolean} Whether the uniform has been updated or not.
31421   */
31422  updateNumber(uniform3) {
31423    let updated = false;
31424    const a = this.values;
31425    const v = uniform3.getValue();
31426    const offset3 = uniform3.offset;
31427    const type = uniform3.getType();
31428    if (a[offset3] !== v) {
31429      const b = this._getBufferForType(type);
31430      b[offset3] = a[offset3] = v;
31431      updated = true;
31432      this.addUniformUpdateRange(uniform3);
31433    }
31434    return updated;
31435  }
31436  /**
31437   * Updates a given Vector2 uniform.
31438   *
31439   * @param {Vector2Uniform} uniform - The Vector2 uniform.
31440   * @return {boolean} Whether the uniform has been updated or not.
31441   */
31442  updateVector2(uniform3) {
31443    let updated = false;
31444    const a = this.values;
31445    const v = uniform3.getValue();
31446    const offset3 = uniform3.offset;
31447    const type = uniform3.getType();
31448    if (a[offset3 + 0] !== v.x || a[offset3 + 1] !== v.y) {
31449      const b = this._getBufferForType(type);
31450      b[offset3 + 0] = a[offset3 + 0] = v.x;
31451      b[offset3 + 1] = a[offset3 + 1] = v.y;
31452      updated = true;
31453      this.addUniformUpdateRange(uniform3);
31454    }
31455    return updated;
31456  }
31457  /**
31458   * Updates a given Vector3 uniform.
31459   *
31460   * @param {Vector3Uniform} uniform - The Vector3 uniform.
31461   * @return {boolean} Whether the uniform has been updated or not.
31462   */
31463  updateVector3(uniform3) {
31464    let updated = false;
31465    const a = this.values;
31466    const v = uniform3.getValue();
31467    const offset3 = uniform3.offset;
31468    const type = uniform3.getType();
31469    if (a[offset3 + 0] !== v.x || a[offset3 + 1] !== v.y || a[offset3 + 2] !== v.z) {
31470      const b = this._getBufferForType(type);
31471      b[offset3 + 0] = a[offset3 + 0] = v.x;
31472      b[offset3 + 1] = a[offset3 + 1] = v.y;
31473      b[offset3 + 2] = a[offset3 + 2] = v.z;
31474      updated = true;
31475      this.addUniformUpdateRange(uniform3);
31476    }
31477    return updated;
31478  }
31479  /**
31480   * Updates a given Vector4 uniform.
31481   *
31482   * @param {Vector4Uniform} uniform - The Vector4 uniform.
31483   * @return {boolean} Whether the uniform has been updated or not.
31484   */
31485  updateVector4(uniform3) {
31486    let updated = false;
31487    const a = this.values;
31488    const v = uniform3.getValue();
31489    const offset3 = uniform3.offset;
31490    const type = uniform3.getType();
31491    if (a[offset3 + 0] !== v.x || a[offset3 + 1] !== v.y || a[offset3 + 2] !== v.z || a[offset3 + 3] !== v.w) {
31492      const b = this._getBufferForType(type);
31493      b[offset3 + 0] = a[offset3 + 0] = v.x;
31494      b[offset3 + 1] = a[offset3 + 1] = v.y;
31495      b[offset3 + 2] = a[offset3 + 2] = v.z;
31496      b[offset3 + 3] = a[offset3 + 3] = v.w;
31497      updated = true;
31498      this.addUniformUpdateRange(uniform3);
31499    }
31500    return updated;
31501  }
31502  /**
31503   * Updates a given Color uniform.
31504   *
31505   * @param {ColorUniform} uniform - The Color uniform.
31506   * @return {boolean} Whether the uniform has been updated or not.
31507   */
31508  updateColor(uniform3) {
31509    let updated = false;
31510    const a = this.values;
31511    const c = uniform3.getValue();
31512    const offset3 = uniform3.offset;
31513    if (a[offset3 + 0] !== c.r || a[offset3 + 1] !== c.g || a[offset3 + 2] !== c.b) {
31514      const b = this.buffer;
31515      b[offset3 + 0] = a[offset3 + 0] = c.r;
31516      b[offset3 + 1] = a[offset3 + 1] = c.g;
31517      b[offset3 + 2] = a[offset3 + 2] = c.b;
31518      updated = true;
31519      this.addUniformUpdateRange(uniform3);
31520    }
31521    return updated;
31522  }
31523  /**
31524   * Updates a given Matrix3 uniform.
31525   *
31526   * @param {Matrix3Uniform} uniform - The Matrix3 uniform.
31527   * @return {boolean} Whether the uniform has been updated or not.
31528   */
31529  updateMatrix3(uniform3) {
31530    let updated = false;
31531    const a = this.values;
31532    const e = uniform3.getValue().elements;
31533    const offset3 = uniform3.offset;
31534    if (a[offset3 + 0] !== e[0] || a[offset3 + 1] !== e[1] || a[offset3 + 2] !== e[2] || a[offset3 + 4] !== e[3] || a[offset3 + 5] !== e[4] || a[offset3 + 6] !== e[5] || a[offset3 + 8] !== e[6] || a[offset3 + 9] !== e[7] || a[offset3 + 10] !== e[8]) {
31535      const b = this.buffer;
31536      b[offset3 + 0] = a[offset3 + 0] = e[0];
31537      b[offset3 + 1] = a[offset3 + 1] = e[1];
31538      b[offset3 + 2] = a[offset3 + 2] = e[2];
31539      b[offset3 + 4] = a[offset3 + 4] = e[3];
31540      b[offset3 + 5] = a[offset3 + 5] = e[4];
31541      b[offset3 + 6] = a[offset3 + 6] = e[5];
31542      b[offset3 + 8] = a[offset3 + 8] = e[6];
31543      b[offset3 + 9] = a[offset3 + 9] = e[7];
31544      b[offset3 + 10] = a[offset3 + 10] = e[8];
31545      updated = true;
31546      this.addUniformUpdateRange(uniform3);
31547    }
31548    return updated;
31549  }
31550  /**
31551   * Updates a given Matrix4 uniform.
31552   *
31553   * @param {Matrix4Uniform} uniform - The Matrix4 uniform.
31554   * @return {boolean} Whether the uniform has been updated or not.
31555   */
31556  updateMatrix4(uniform3) {
31557    let updated = false;
31558    const a = this.values;
31559    const e = uniform3.getValue().elements;
31560    const offset3 = uniform3.offset;
31561    if (arraysEqual(a, e, offset3) === false) {
31562      const b = this.buffer;
31563      b.set(e, offset3);
31564      setArray(a, e, offset3);
31565      updated = true;
31566      this.addUniformUpdateRange(uniform3);
31567    }
31568    return updated;
31569  }
31570  /**
31571   * Returns a typed array that matches the given data type.
31572   *
31573   * @private
31574   * @param {string} type - The data type.
31575   * @return {TypedArray} The typed array.
31576   */
31577  _getBufferForType(type) {
31578    if (type === "int" || type === "ivec2" || type === "ivec3" || type === "ivec4") return new Int32Array(this.buffer.buffer);
31579    if (type === "uint" || type === "uvec2" || type === "uvec3" || type === "uvec4") return new Uint32Array(this.buffer.buffer);
31580    return this.buffer;
31581  }
31582};
31583function setArray(a, b, offset3) {
31584  for (let i = 0, l = b.length; i < l; i++) {
31585    a[offset3 + i] = b[i];
31586  }
31587}
31588function arraysEqual(a, b, offset3) {
31589  for (let i = 0, l = b.length; i < l; i++) {
31590    if (a[offset3 + i] !== b[i]) return false;
31591  }
31592  return true;
31593}
31594var _id$3 = 0;
31595var NodeUniformsGroup = class extends UniformsGroup2 {
31596  /**
31597   * Constructs a new node-based uniforms group.
31598   *
31599   * @param {string} name - The group's name.
31600   * @param {UniformGroupNode} groupNode - The uniform group node.
31601   */
31602  constructor(name, groupNode) {
31603    super(name);
31604    this.id = _id$3++;
31605    this.groupNode = groupNode;
31606    this.isNodeUniformsGroup = true;
31607  }
31608};
31609var Sampler = class extends Binding {
31610  /**
31611   * Constructs a new sampler.
31612   *
31613   * @param {string} name - The samplers's name.
31614   * @param {?Texture} texture - The texture this binding is referring to.
31615   */
31616  constructor(name, texture3) {
31617    super(name);
31618    this._texture = null;
31619    this._onTextureDispose = () => {
31620      this.generation = null;
31621      this.version = -1;
31622    };
31623    this.texture = texture3;
31624    this.version = texture3 ? texture3.version : -1;
31625    this.generation = null;
31626    this.samplerKey = "";
31627    this.isSampler = true;
31628  }
31629  /**
31630   * Sets the texture of this sampler.
31631   *
31632   * @param {Texture} value - The texture to set.
31633   */
31634  set texture(value) {
31635    if (this._texture === value) return;
31636    if (this._texture) {
31637      this._texture.removeEventListener("dispose", this._onTextureDispose);
31638    }
31639    this._texture = value;
31640    this.generation = null;
31641    this.version = -1;
31642    if (this._texture) {
31643      this._texture.addEventListener("dispose", this._onTextureDispose);
31644    }
31645  }
31646  /**
31647   * Gets the texture of this sampler.
31648   * @return {?Texture} The texture.
31649   */
31650  get texture() {
31651    return this._texture;
31652  }
31653  /**
31654   * Updates the binding.
31655   *
31656   * @return {boolean} Whether the texture has been updated and must be
31657   * uploaded to the GPU.
31658   */
31659  update() {
31660    const { texture: texture3, version } = this;
31661    if (version !== texture3.version) {
31662      this.version = texture3.version;
31663      return true;
31664    }
31665    return false;
31666  }
31667  clone() {
31668    const clonedSampler = super.clone();
31669    clonedSampler._texture = null;
31670    clonedSampler._onTextureDispose = () => {
31671      clonedSampler.generation = null;
31672      clonedSampler.version = -1;
31673    };
31674    clonedSampler.texture = this.texture;
31675    return clonedSampler;
31676  }
31677};
31678var _id$2 = 0;
31679var SampledTexture = class extends Sampler {
31680  /**
31681   * Constructs a new sampled texture.
31682   *
31683   * @param {string} name - The sampled texture's name.
31684   * @param {?Texture} texture - The texture this binding is referring to.
31685   */
31686  constructor(name, texture3) {
31687    super(name, texture3);
31688    this.id = _id$2++;
31689    this.store = false;
31690    this.mipLevel = 0;
31691    this.isSampledTexture = true;
31692  }
31693};
31694var NodeSampledTexture = class extends SampledTexture {
31695  /**
31696   * Constructs a new node-based sampled texture.
31697   *
31698   * @param {string} name - The textures's name.
31699   * @param {TextureNode} textureNode - The texture node.
31700   * @param {UniformGroupNode} groupNode - The uniform group node.
31701   * @param {?string} [access=null] - The access type.
31702   */
31703  constructor(name, textureNode, groupNode, access6 = null) {
31704    super(name, textureNode ? textureNode.value : null);
31705    this.textureNode = textureNode;
31706    this.groupNode = groupNode;
31707    this.access = access6;
31708  }
31709  /**
31710   * Updates the binding.
31711   *
31712   * @return {boolean} Whether the texture has been updated and must be
31713   * uploaded to the GPU.
31714   */
31715  update() {
31716    const { textureNode } = this;
31717    if (this.texture !== textureNode.value) {
31718      this.texture = textureNode.value;
31719      return true;
31720    }
31721    return super.update();
31722  }
31723};
31724var NodeSampledCubeTexture = class extends NodeSampledTexture {
31725  /**
31726   * Constructs a new node-based sampled cube texture.
31727   *
31728   * @param {string} name - The textures's name.
31729   * @param {TextureNode} textureNode - The texture node.
31730   * @param {UniformGroupNode} groupNode - The uniform group node.
31731   * @param {?string} [access=null] - The access type.
31732   */
31733  constructor(name, textureNode, groupNode, access6 = null) {
31734    super(name, textureNode, groupNode, access6);
31735    this.isSampledCubeTexture = true;
31736  }
31737};
31738var NodeSampledTexture3D = class extends NodeSampledTexture {
31739  /**
31740   * Constructs a new node-based sampled 3D texture.
31741   *
31742   * @param {string} name - The textures's name.
31743   * @param {TextureNode} textureNode - The texture node.
31744   * @param {UniformGroupNode} groupNode - The uniform group node.
31745   * @param {?string} [access=null] - The access type.
31746   */
31747  constructor(name, textureNode, groupNode, access6 = null) {
31748    super(name, textureNode, groupNode, access6);
31749    this.isSampledTexture3D = true;
31750  }
31751};
31752var glslPolyfills = {
31753  bitcast_int_uint: new CodeNode(
31754    /* glsl */
31755    "uint tsl_bitcast_int_to_uint ( int x ) { return floatBitsToUint( intBitsToFloat ( x ) ); }"
31756  ),
31757  bitcast_uint_int: new CodeNode(
31758    /* glsl */
31759    "uint tsl_bitcast_uint_to_int ( uint x ) { return floatBitsToInt( uintBitsToFloat ( x ) ); }"
31760  )
31761};
31762var glslMethods = {
31763  textureDimensions: "textureSize",
31764  equals: "equal",
31765  bitcast_float_int: "floatBitsToInt",
31766  bitcast_int_float: "intBitsToFloat",
31767  bitcast_uint_float: "uintBitsToFloat",
31768  bitcast_float_uint: "floatBitsToUint",
31769  bitcast_uint_int: "tsl_bitcast_uint_to_int",
31770  bitcast_int_uint: "tsl_bitcast_int_to_uint",
31771  floatpack_snorm_2x16: "packSnorm2x16",
31772  floatpack_unorm_2x16: "packUnorm2x16",
31773  floatpack_float16_2x16: "packHalf2x16",
31774  floatunpack_snorm_2x16: "unpackSnorm2x16",
31775  floatunpack_unorm_2x16: "unpackUnorm2x16",
31776  floatunpack_float16_2x16: "unpackHalf2x16"
31777};
31778var precisionLib = {
31779  low: "lowp",
31780  medium: "mediump",
31781  high: "highp"
31782};
31783var supports$1 = {
31784  swizzleAssign: true,
31785  storageBuffer: false
31786};
31787var interpolationTypeMap = {
31788  perspective: "smooth",
31789  linear: "noperspective"
31790};
31791var interpolationModeMap = {
31792  "centroid": "centroid"
31793};
31794var defaultPrecisions = `
31795precision highp float;
31796precision highp int;
31797precision highp sampler2D;
31798precision highp sampler3D;
31799precision highp samplerCube;
31800precision highp sampler2DArray;
31801
31802precision highp usampler2D;
31803precision highp usampler3D;
31804precision highp usamplerCube;
31805precision highp usampler2DArray;
31806
31807precision highp isampler2D;
31808precision highp isampler3D;
31809precision highp isamplerCube;
31810precision highp isampler2DArray;
31811
31812precision highp sampler2DShadow;
31813precision highp sampler2DArrayShadow;
31814precision highp samplerCubeShadow;
31815`;
31816var GLSLNodeBuilder = class extends NodeBuilder {
31817  /**
31818   * Constructs a new GLSL node builder renderer.
31819   *
31820   * @param {Object3D} object - The 3D object.
31821   * @param {Renderer} renderer - The renderer.
31822   */
31823  constructor(object, renderer) {
31824    super(object, renderer, new GLSLNodeParser());
31825    this.uniformGroups = {};
31826    this.transforms = [];
31827    this.extensions = {};
31828    this.builtins = { vertex: [], fragment: [], compute: [] };
31829  }
31830  /**
31831   * Checks if the given texture requires a manual conversion to the working color space.
31832   *
31833   * @param {Texture} texture - The texture to check.
31834   * @return {boolean} Whether the given texture requires a conversion to working color space or not.
31835   */
31836  needsToWorkingColorSpace(texture3) {
31837    return texture3.isVideoTexture === true && texture3.colorSpace !== NoColorSpace;
31838  }
31839  /**
31840   * Includes the given method name into the current
31841   * function node.
31842   *
31843   * @private
31844   * @param {string} name - The method name to include.
31845   * @return {CodeNode} The respective code node.
31846   */
31847  _include(name) {
31848    const codeNode = glslPolyfills[name];
31849    codeNode.build(this);
31850    this.addInclude(codeNode);
31851    return codeNode;
31852  }
31853  /**
31854   * Returns the native shader method name for a given generic name.
31855   *
31856   * @param {string} method - The method name to resolve.
31857   * @return {string} The resolved GLSL method name.
31858   */
31859  getMethod(method) {
31860    if (glslPolyfills[method] !== void 0) {
31861      this._include(method);
31862    }
31863    return glslMethods[method] || method;
31864  }
31865  /**
31866   * Returns the bitcast method name for a given input and outputType.
31867   *
31868   * @param {string} type - The output type to bitcast to.
31869   * @param {string} inputType - The input type of the.
31870   * @return {string} The resolved WGSL bitcast invocation.
31871   */
31872  getBitcastMethod(type, inputType) {
31873    return this.getMethod(`bitcast_${inputType}_${type}`);
31874  }
31875  /**
31876   * Returns the float packing method name for a given numeric encoding.
31877   *
31878   * @param {string} encoding - The numeric encoding that describes how the float values are mapped to the integer range.
31879   * @returns {string} The resolved GLSL float packing method name.
31880   */
31881  getFloatPackingMethod(encoding) {
31882    return this.getMethod(`floatpack_${encoding}_2x16`);
31883  }
31884  /**
31885   * Returns the float unpacking method name for a given numeric encoding.
31886   *
31887   * @param {string} encoding - The numeric encoding that describes how the integer values are mapped to the float range.
31888   * @returns {string} The resolved GLSL float unpacking method name.
31889   */
31890  getFloatUnpackingMethod(encoding) {
31891    return this.getMethod(`floatunpack_${encoding}_2x16`);
31892  }
31893  /**
31894   * Returns the native snippet for a ternary operation.
31895   *
31896   * @param {string} condSnippet - The condition determining which expression gets resolved.
31897   * @param {string} ifSnippet - The expression to resolve to if the condition is true.
31898   * @param {string} elseSnippet - The expression to resolve to if the condition is false.
31899   * @return {string} The resolved method name.
31900   */
31901  getTernary(condSnippet, ifSnippet, elseSnippet) {
31902    return `${condSnippet} ? ${ifSnippet} : ${elseSnippet}`;
31903  }
31904  /**
31905   * Returns the output struct name. Not relevant for GLSL.
31906   *
31907   * @return {string}
31908   */
31909  getOutputStructName() {
31910    return "";
31911  }
31912  /**
31913   * Builds the given shader node.
31914   *
31915   * @param {ShaderNodeInternal} shaderNode - The shader node.
31916   * @return {string} The GLSL function code.
31917   */
31918  buildFunctionCode(shaderNode) {
31919    const layout = shaderNode.layout;
31920    const flowData = this.flowShaderNode(shaderNode);
31921    const parameters = [];
31922    for (const input of layout.inputs) {
31923      parameters.push(this.getType(input.type) + " " + input.name);
31924    }
31925    const code3 = `${this.getType(layout.type)} ${layout.name}( ${parameters.join(", ")} ) {
31926
31927	${flowData.vars}
31928
31929${flowData.code}
31930	return ${flowData.result};
31931
31932}`;
31933    return code3;
31934  }
31935  /**
31936   * Setups the Pixel Buffer Object (PBO) for the given storage
31937   * buffer node.
31938   *
31939   * @param {StorageBufferNode} storageBufferNode - The storage buffer node.
31940   */
31941  setupPBO(storageBufferNode) {
31942    const attribute3 = storageBufferNode.value;
31943    if (attribute3.pbo === void 0) {
31944      const originalArray = attribute3.array;
31945      const numElements = attribute3.count * attribute3.itemSize;
31946      const { itemSize } = attribute3;
31947      const isInteger = attribute3.array.constructor.name.toLowerCase().includes("int");
31948      let format = isInteger ? RedIntegerFormat : RedFormat;
31949      if (itemSize === 2) {
31950        format = isInteger ? RGIntegerFormat : RGFormat;
31951      } else if (itemSize === 3) {
31952        format = isInteger ? RGBIntegerFormat : RGBFormat;
31953      } else if (itemSize === 4) {
31954        format = isInteger ? RGBAIntegerFormat : RGBAFormat;
31955      }
31956      const typeMap = {
31957        Float32Array: FloatType,
31958        Uint8Array: UnsignedByteType,
31959        Uint16Array: UnsignedShortType,
31960        Uint32Array: UnsignedIntType,
31961        Int8Array: ByteType,
31962        Int16Array: ShortType,
31963        Int32Array: IntType,
31964        Uint8ClampedArray: UnsignedByteType
31965      };
31966      const width = Math.pow(2, Math.ceil(Math.log2(Math.sqrt(numElements / itemSize))));
31967      let height = Math.ceil(numElements / itemSize / width);
31968      if (width * height * itemSize < numElements) height++;
31969      const newSize = width * height * itemSize;
31970      const newArray = new originalArray.constructor(newSize);
31971      newArray.set(originalArray, 0);
31972      attribute3.array = newArray;
31973      const pboTexture = new DataTexture(attribute3.array, width, height, format, typeMap[attribute3.array.constructor.name] || FloatType);
31974      pboTexture.needsUpdate = true;
31975      pboTexture.isPBOTexture = true;
31976      const pbo = new TextureNode(pboTexture, null, null);
31977      pbo.setPrecision("high");
31978      attribute3.pboNode = pbo;
31979      attribute3.pbo = pbo.value;
31980      this.getUniformFromNode(attribute3.pboNode, "texture", this.shaderStage, this.context.nodeName);
31981    }
31982  }
31983  /**
31984   * Returns a GLSL snippet that represents the property name of the given node.
31985   *
31986   * @param {Node} node - The node.
31987   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
31988   * @return {string} The property name.
31989   */
31990  getPropertyName(node, shaderStage = this.shaderStage) {
31991    if (node.isNodeUniform && node.node.isTextureNode !== true && node.node.isBufferNode !== true) {
31992      return node.name;
31993    }
31994    return super.getPropertyName(node, shaderStage);
31995  }
31996  /**
31997   * Setups the Pixel Buffer Object (PBO) for the given storage
31998   * buffer node.
31999   *
32000   * @param {StorageArrayElementNode} storageArrayElementNode - The storage array element node.
32001   * @return {string} The property name.
32002   */
32003  generatePBO(storageArrayElementNode) {
32004    const { node, indexNode } = storageArrayElementNode;
32005    const attribute3 = node.value;
32006    if (this.renderer.backend.has(attribute3)) {
32007      const attributeData = this.renderer.backend.get(attribute3);
32008      attributeData.pbo = attribute3.pbo;
32009    }
32010    const nodeUniform = this.getUniformFromNode(attribute3.pboNode, "texture", this.shaderStage, this.context.nodeName);
32011    const textureName = this.getPropertyName(nodeUniform);
32012    this.increaseUsage(indexNode);
32013    const indexSnippet = indexNode.build(this, "uint");
32014    const elementNodeData = this.getDataFromNode(storageArrayElementNode);
32015    let propertyName = elementNodeData.propertyName;
32016    if (propertyName === void 0) {
32017      const nodeVar = this.getVarFromNode(storageArrayElementNode);
32018      propertyName = this.getPropertyName(nodeVar);
32019      const bufferNodeData = this.getDataFromNode(node);
32020      let propertySizeName = bufferNodeData.propertySizeName;
32021      if (propertySizeName === void 0) {
32022        propertySizeName = propertyName + "Size";
32023        this.getVarFromNode(node, propertySizeName, "uint");
32024        this.addLineFlowCode(`${propertySizeName} = uint( textureSize( ${textureName}, 0 ).x )`, storageArrayElementNode);
32025        bufferNodeData.propertySizeName = propertySizeName;
32026      }
32027      const { itemSize } = attribute3;
32028      const channel = "." + vectorComponents.join("").slice(0, itemSize);
32029      const uvSnippet = `ivec2(${indexSnippet} % ${propertySizeName}, ${indexSnippet} / ${propertySizeName})`;
32030      const snippet = this.generateTextureLoad(null, textureName, uvSnippet, "0", null, null);
32031      let prefix = "vec4";
32032      if (attribute3.pbo.type === UnsignedIntType) {
32033        prefix = "uvec4";
32034      } else if (attribute3.pbo.type === IntType) {
32035        prefix = "ivec4";
32036      }
32037      this.addLineFlowCode(`${propertyName} = ${prefix}(${snippet})${channel}`, storageArrayElementNode);
32038      elementNodeData.propertyName = propertyName;
32039    }
32040    return propertyName;
32041  }
32042  /**
32043   * Generates the GLSL snippet that reads a single texel from a texture without sampling or filtering.
32044   *
32045   * @param {?Texture} texture - The texture.
32046   * @param {string} textureProperty - The name of the texture uniform in the shader.
32047   * @param {string} uvIndexSnippet - A GLSL snippet that represents texture coordinates used for sampling.
32048   * @param {?string} levelSnippet - A GLSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
32049   * @param {?string} depthSnippet - A GLSL snippet that represents the 0-based texture array index to sample.
32050   * @param {?string} offsetSnippet - A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
32051   * @return {string} The GLSL snippet.
32052   */
32053  generateTextureLoad(texture3, textureProperty, uvIndexSnippet, levelSnippet, depthSnippet, offsetSnippet) {
32054    if (levelSnippet === null) levelSnippet = "0";
32055    let snippet;
32056    if (depthSnippet) {
32057      if (offsetSnippet) {
32058        snippet = `texelFetchOffset( ${textureProperty}, ivec3( ${uvIndexSnippet}, ${depthSnippet} ), int( ${levelSnippet} ), ${offsetSnippet} )`;
32059      } else {
32060        snippet = `texelFetch( ${textureProperty}, ivec3( ${uvIndexSnippet}, ${depthSnippet} ), int( ${levelSnippet} ) )`;
32061      }
32062    } else {
32063      if (offsetSnippet) {
32064        snippet = `texelFetchOffset( ${textureProperty}, ${uvIndexSnippet}, int( ${levelSnippet} ), ${offsetSnippet} )`;
32065      } else {
32066        snippet = `texelFetch( ${textureProperty}, ${uvIndexSnippet}, int( ${levelSnippet} ) )`;
32067      }
32068    }
32069    if (texture3 !== null && texture3.isDepthTexture) {
32070      snippet += ".x";
32071    }
32072    return snippet;
32073  }
32074  /**
32075   * Generates the GLSL snippet for sampling/loading the given texture.
32076   *
32077   * @param {Texture} texture - The texture.
32078   * @param {string} textureProperty - The name of the texture uniform in the shader.
32079   * @param {string} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling.
32080   * @param {?string} depthSnippet -  A GLSL snippet that represents the 0-based texture array index to sample.
32081   * @param {?string} offsetSnippet - A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
32082   * @return {string} The GLSL snippet.
32083   */
32084  generateTexture(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet) {
32085    if (depthSnippet) uvSnippet = `vec3( ${uvSnippet}, ${depthSnippet} )`;
32086    if (texture3.isDepthTexture) {
32087      if (offsetSnippet) return `textureOffset( ${textureProperty}, ${uvSnippet}, ${offsetSnippet} ).x`;
32088      return `texture( ${textureProperty}, ${uvSnippet} ).x`;
32089    }
32090    if (offsetSnippet) return `textureOffset( ${textureProperty}, ${uvSnippet}, ${offsetSnippet} )`;
32091    return `texture( ${textureProperty}, ${uvSnippet} )`;
32092  }
32093  /**
32094   * Generates the GLSL snippet when sampling textures with explicit mip level.
32095   *
32096   * @param {Texture} texture - The texture.
32097   * @param {string} textureProperty - The name of the texture uniform in the shader.
32098   * @param {string} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling.
32099   * @param {string} levelSnippet - A GLSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
32100   * @param {?string} depthSnippet - A GLSL snippet that represents 0-based texture array index to sample.
32101   * @param {?string} offsetSnippet - A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
32102   * @return {string} The GLSL snippet.
32103   */
32104  generateTextureLevel(texture3, textureProperty, uvSnippet, levelSnippet, depthSnippet, offsetSnippet) {
32105    if (depthSnippet) uvSnippet = `vec3( ${uvSnippet}, ${depthSnippet} )`;
32106    if (offsetSnippet) {
32107      return `textureLodOffset( ${textureProperty}, ${uvSnippet}, ${levelSnippet}, ${offsetSnippet} )`;
32108    }
32109    return `textureLod( ${textureProperty}, ${uvSnippet}, ${levelSnippet} )`;
32110  }
32111  /**
32112   * Generates the GLSL snippet when sampling textures with a bias to the mip level.
32113   *
32114   * @param {Texture} texture - The texture.
32115   * @param {string} textureProperty - The name of the texture uniform in the shader.
32116   * @param {string} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling.
32117   * @param {string} biasSnippet - A GLSL snippet that represents the bias to apply to the mip level before sampling.
32118   * @param {?string} depthSnippet - A GLSL snippet that represents 0-based texture array index to sample.
32119   * @param {?string} offsetSnippet - A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
32120   * @return {string} The GLSL snippet.
32121   */
32122  generateTextureBias(texture3, textureProperty, uvSnippet, biasSnippet, depthSnippet, offsetSnippet) {
32123    if (depthSnippet) uvSnippet = `vec3( ${uvSnippet}, ${depthSnippet} )`;
32124    if (offsetSnippet) {
32125      return `textureOffset( ${textureProperty}, ${uvSnippet}, ${offsetSnippet}, ${biasSnippet} )`;
32126    }
32127    return `texture( ${textureProperty}, ${uvSnippet}, ${biasSnippet} )`;
32128  }
32129  /**
32130   * Generates the GLSL snippet for sampling/loading the given texture using explicit gradients.
32131   *
32132   * @param {Texture} texture - The texture.
32133   * @param {string} textureProperty - The name of the texture uniform in the shader.
32134   * @param {string} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling.
32135   * @param {Array<string>} gradSnippet - An array holding both gradient GLSL snippets.
32136   * @param {?string} depthSnippet - A GLSL snippet that represents 0-based texture array index to sample.
32137   * @param {?string} offsetSnippet - A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
32138   * @return {string} The GLSL snippet.
32139   */
32140  generateTextureGrad(texture3, textureProperty, uvSnippet, gradSnippet, depthSnippet, offsetSnippet) {
32141    if (depthSnippet) uvSnippet = `vec3( ${uvSnippet}, ${depthSnippet} )`;
32142    if (offsetSnippet) {
32143      return `textureGradOffset( ${textureProperty}, ${uvSnippet}, ${gradSnippet[0]}, ${gradSnippet[1]}, ${offsetSnippet} )`;
32144    }
32145    return `textureGrad( ${textureProperty}, ${uvSnippet}, ${gradSnippet[0]}, ${gradSnippet[1]} )`;
32146  }
32147  /**
32148   * Generates the GLSL snippet for sampling a depth texture and comparing the sampled depth values
32149   * against a reference value.
32150   *
32151   * @param {Texture} texture - The texture.
32152   * @param {string} textureProperty - The name of the texture uniform in the shader.
32153   * @param {string} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling.
32154   * @param {string} compareSnippet -  A GLSL snippet that represents the reference value.
32155   * @param {?string} depthSnippet - A GLSL snippet that represents 0-based texture array index to sample.
32156   * @param {?string} offsetSnippet - A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
32157   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
32158   * @return {string} The GLSL snippet.
32159   */
32160  generateTextureCompare(texture3, textureProperty, uvSnippet, compareSnippet, depthSnippet, offsetSnippet, shaderStage = this.shaderStage) {
32161    if (shaderStage === "fragment") {
32162      if (texture3.isCubeTexture) {
32163        return `texture( ${textureProperty}, vec4( ${uvSnippet}, ${compareSnippet} ) )`;
32164      }
32165      if (depthSnippet) {
32166        if (offsetSnippet) {
32167          return `textureOffset( ${textureProperty}, vec4( ${uvSnippet}, ${depthSnippet}, ${compareSnippet} ), ${offsetSnippet} )`;
32168        }
32169        return `texture( ${textureProperty}, vec4( ${uvSnippet}, ${depthSnippet}, ${compareSnippet} ) )`;
32170      }
32171      if (offsetSnippet) {
32172        return `textureOffset( ${textureProperty}, vec3( ${uvSnippet}, ${compareSnippet} ), ${offsetSnippet} )`;
32173      }
32174      return `texture( ${textureProperty}, vec3( ${uvSnippet}, ${compareSnippet} ) )`;
32175    } else {
32176      error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${shaderStage} shader.`);
32177    }
32178  }
32179  /**
32180   * Returns the uniforms of the given shader stage as a GLSL string.
32181   *
32182   * @param {string} shaderStage - The shader stage.
32183   * @return {string} The GLSL snippet that defines the uniforms.
32184   */
32185  getUniforms(shaderStage) {
32186    const uniforms = this.uniforms[shaderStage];
32187    const bindingSnippets = [];
32188    const uniformGroups = {};
32189    for (const uniform3 of uniforms) {
32190      let snippet = null;
32191      let group = false;
32192      if (uniform3.type === "texture" || uniform3.type === "texture3D") {
32193        const texture3 = uniform3.node.value;
32194        let typePrefix = "";
32195        if (texture3.isDataTexture === true || texture3.isData3DTexture === true) {
32196          if (texture3.type === UnsignedIntType) {
32197            typePrefix = "u";
32198          } else if (texture3.type === IntType) {
32199            typePrefix = "i";
32200          }
32201        }
32202        if (uniform3.type === "texture3D" && texture3.isArrayTexture === false) {
32203          snippet = `${typePrefix}sampler3D ${uniform3.name};`;
32204        } else if (texture3.compareFunction) {
32205          if (texture3.isArrayTexture === true) {
32206            snippet = `sampler2DArrayShadow ${uniform3.name};`;
32207          } else {
32208            snippet = `sampler2DShadow ${uniform3.name};`;
32209          }
32210        } else if (texture3.isArrayTexture === true || texture3.isDataArrayTexture === true || texture3.isCompressedArrayTexture === true) {
32211          snippet = `${typePrefix}sampler2DArray ${uniform3.name};`;
32212        } else {
32213          snippet = `${typePrefix}sampler2D ${uniform3.name};`;
32214        }
32215      } else if (uniform3.type === "cubeTexture") {
32216        snippet = `samplerCube ${uniform3.name};`;
32217      } else if (uniform3.type === "cubeDepthTexture") {
32218        const texture3 = uniform3.node.value;
32219        if (texture3.compareFunction) {
32220          snippet = `samplerCubeShadow ${uniform3.name};`;
32221        } else {
32222          snippet = `samplerCube ${uniform3.name};`;
32223        }
32224      } else if (uniform3.type === "buffer") {
32225        const bufferNode = uniform3.node;
32226        const bufferType = this.getType(bufferNode.bufferType);
32227        const bufferCount = bufferNode.bufferCount;
32228        const bufferCountSnippet = bufferCount > 0 ? bufferCount : "";
32229        snippet = `${bufferNode.name} {
32230	${bufferType} ${uniform3.name}[${bufferCountSnippet}];
32231};
32232`;
32233      } else {
32234        const groupName = uniform3.groupNode.name;
32235        if (uniformGroups[groupName] === void 0) {
32236          const sharedUniformGroup3 = this.uniformGroups[groupName];
32237          if (sharedUniformGroup3 !== void 0) {
32238            const snippets = [];
32239            for (const sharedUniform of sharedUniformGroup3.uniforms) {
32240              const type = sharedUniform.getType();
32241              const vectorType = this.getVectorType(type);
32242              const precision = sharedUniform.nodeUniform.node.precision;
32243              let uniformSnippet = `${vectorType} ${sharedUniform.name};`;
32244              if (precision !== null) {
32245                uniformSnippet = precisionLib[precision] + " " + uniformSnippet;
32246              }
32247              snippets.push("	" + uniformSnippet);
32248            }
32249            uniformGroups[groupName] = snippets;
32250          }
32251        }
32252        group = true;
32253      }
32254      if (!group) {
32255        const precision = uniform3.node.precision;
32256        if (precision !== null) {
32257          snippet = precisionLib[precision] + " " + snippet;
32258        }
32259        snippet = "uniform " + snippet;
32260        bindingSnippets.push(snippet);
32261      }
32262    }
32263    let output3 = "";
32264    for (const name in uniformGroups) {
32265      const groupSnippets = uniformGroups[name];
32266      output3 += this._getGLSLUniformStruct(name, groupSnippets.join("\n")) + "\n";
32267    }
32268    output3 += bindingSnippets.join("\n");
32269    return output3;
32270  }
32271  /**
32272   * Returns the type for a given buffer attribute.
32273   *
32274   * @param {BufferAttribute} attribute - The buffer attribute.
32275   * @return {string} The type.
32276   */
32277  getTypeFromAttribute(attribute3) {
32278    let nodeType = super.getTypeFromAttribute(attribute3);
32279    if (/^[iu]/.test(nodeType) && attribute3.gpuType !== IntType) {
32280      let dataAttribute = attribute3;
32281      if (attribute3.isInterleavedBufferAttribute) dataAttribute = attribute3.data;
32282      const array3 = dataAttribute.array;
32283      if ((array3 instanceof Uint32Array || array3 instanceof Int32Array) === false) {
32284        nodeType = nodeType.slice(1);
32285      }
32286    }
32287    return nodeType;
32288  }
32289  /**
32290   * Returns the shader attributes of the given shader stage as a GLSL string.
32291   *
32292   * @param {string} shaderStage - The shader stage.
32293   * @return {string} The GLSL snippet that defines the shader attributes.
32294   */
32295  getAttributes(shaderStage) {
32296    let snippet = "";
32297    if (shaderStage === "vertex" || shaderStage === "compute") {
32298      const attributes = this.getAttributesArray();
32299      let location = 0;
32300      for (const attribute3 of attributes) {
32301        snippet += `layout( location = ${location++} ) in ${attribute3.type} ${attribute3.name};
32302`;
32303      }
32304    }
32305    return snippet;
32306  }
32307  /**
32308   * Returns the members of the given struct type node as a GLSL string.
32309   *
32310   * @param {StructTypeNode} struct - The struct type node.
32311   * @return {string} The GLSL snippet that defines the struct members.
32312   */
32313  getStructMembers(struct3) {
32314    const snippets = [];
32315    for (const member of struct3.members) {
32316      snippets.push(`	${member.type} ${member.name};`);
32317    }
32318    return snippets.join("\n");
32319  }
32320  /**
32321   * Returns the structs of the given shader stage as a GLSL string.
32322   *
32323   * @param {string} shaderStage - The shader stage.
32324   * @return {string} The GLSL snippet that defines the structs.
32325   */
32326  getStructs(shaderStage) {
32327    const snippets = [];
32328    const structs = this.structs[shaderStage];
32329    const outputSnippet = [];
32330    for (const struct3 of structs) {
32331      if (struct3.output) {
32332        for (const member of struct3.members) {
32333          outputSnippet.push(`layout( location = ${member.index} ) out ${member.type} ${member.name};`);
32334        }
32335      } else {
32336        let snippet = "struct " + struct3.name + " {\n";
32337        snippet += this.getStructMembers(struct3);
32338        snippet += "\n};\n";
32339        snippets.push(snippet);
32340      }
32341    }
32342    if (outputSnippet.length === 0) {
32343      outputSnippet.push("layout( location = 0 ) out vec4 fragColor;");
32344    }
32345    return "\n" + outputSnippet.join("\n") + "\n\n" + snippets.join("\n");
32346  }
32347  /**
32348   * Returns the varyings of the given shader stage as a GLSL string.
32349   *
32350   * @param {string} shaderStage - The shader stage.
32351   * @return {string} The GLSL snippet that defines the varyings.
32352   */
32353  getVaryings(shaderStage) {
32354    let snippet = "";
32355    const varyings = this.varyings;
32356    if (shaderStage === "vertex" || shaderStage === "compute") {
32357      for (const varying3 of varyings) {
32358        if (shaderStage === "compute") varying3.needsInterpolation = true;
32359        const type = this.getType(varying3.type);
32360        if (varying3.needsInterpolation) {
32361          if (varying3.interpolationType) {
32362            const interpolationType = interpolationTypeMap[varying3.interpolationType] || varying3.interpolationType;
32363            const sampling = interpolationModeMap[varying3.interpolationSampling] || "";
32364            snippet += `${interpolationType} ${sampling} out ${type} ${varying3.name};
32365`;
32366          } else {
32367            const flat = type.includes("int") || type.includes("uv") || type.includes("iv") ? "flat " : "";
32368            snippet += `${flat}out ${type} ${varying3.name};
32369`;
32370          }
32371        } else {
32372          snippet += `${type} ${varying3.name};
32373`;
32374        }
32375      }
32376    } else if (shaderStage === "fragment") {
32377      for (const varying3 of varyings) {
32378        if (varying3.needsInterpolation) {
32379          const type = this.getType(varying3.type);
32380          if (varying3.interpolationType) {
32381            const interpolationType = interpolationTypeMap[varying3.interpolationType] || varying3.interpolationType;
32382            const sampling = interpolationModeMap[varying3.interpolationSampling] || "";
32383            snippet += `${interpolationType} ${sampling} in ${type} ${varying3.name};
32384`;
32385          } else {
32386            const flat = type.includes("int") || type.includes("uv") || type.includes("iv") ? "flat " : "";
32387            snippet += `${flat}in ${type} ${varying3.name};
32388`;
32389          }
32390        }
32391      }
32392    }
32393    for (const builtin3 of this.builtins[shaderStage]) {
32394      snippet += `${builtin3};
32395`;
32396    }
32397    return snippet;
32398  }
32399  /**
32400   * Returns the vertex index builtin.
32401   *
32402   * @return {string} The vertex index.
32403   */
32404  getVertexIndex() {
32405    return "uint( gl_VertexID )";
32406  }
32407  /**
32408   * Contextually returns either the vertex stage instance index builtin
32409   * or the linearized index of an compute invocation within a grid of workgroups.
32410   *
32411   * @return {string} The instance index.
32412   */
32413  getInstanceIndex() {
32414    return "uint( gl_InstanceID )";
32415  }
32416  /**
32417   * Returns a builtin representing the index of an invocation within its workgroup.
32418   *
32419   * @return {string} The invocation local index.
32420   */
32421  getInvocationLocalIndex() {
32422    const workgroupSize = this.object.workgroupSize;
32423    const size3 = workgroupSize.reduce((acc, curr) => acc * curr, 1);
32424    return `uint( gl_InstanceID ) % ${size3}u`;
32425  }
32426  /**
32427   * Returns a builtin representing the size of a subgroup within the current shader.
32428   */
32429  getSubgroupSize() {
32430    error("GLSLNodeBuilder: WebGLBackend does not support the subgroupSize node");
32431  }
32432  /**
32433   * Returns a builtin representing the index of an invocation within its subgroup.
32434   */
32435  getInvocationSubgroupIndex() {
32436    error("GLSLNodeBuilder: WebGLBackend does not support the invocationSubgroupIndex node");
32437  }
32438  /**
32439   * Returns a builtin representing the index of the current invocation's subgroup within its workgroup.
32440   */
32441  getSubgroupIndex() {
32442    error("GLSLNodeBuilder: WebGLBackend does not support the subgroupIndex node");
32443  }
32444  /**
32445   * Returns the draw index builtin.
32446   *
32447   * @return {?string} The drawIndex shader string. Returns `null` if `WEBGL_multi_draw` isn't supported by the device.
32448   */
32449  getDrawIndex() {
32450    const extensions = this.renderer.backend.extensions;
32451    if (extensions.has("WEBGL_multi_draw")) {
32452      return "uint( gl_DrawID )";
32453    } else {
32454      return "nodeUniformDrawId";
32455    }
32456  }
32457  /**
32458   * Returns the front facing builtin.
32459   *
32460   * @return {string} The front facing builtin.
32461   */
32462  getFrontFacing() {
32463    return "gl_FrontFacing";
32464  }
32465  /**
32466   * Returns the frag coord builtin.
32467   *
32468   * @return {string} The frag coord builtin.
32469   */
32470  getFragCoord() {
32471    return "gl_FragCoord.xy";
32472  }
32473  /**
32474   * Returns the frag depth builtin.
32475   *
32476   * @return {string} The frag depth builtin.
32477   */
32478  getFragDepth() {
32479    return "gl_FragDepth";
32480  }
32481  /**
32482   * Enables the given extension.
32483   *
32484   * @param {string} name - The extension name.
32485   * @param {string} behavior - The extension behavior.
32486   * @param {string} [shaderStage=this.shaderStage] - The shader stage.
32487   */
32488  enableExtension(name, behavior, shaderStage = this.shaderStage) {
32489    const map = this.extensions[shaderStage] || (this.extensions[shaderStage] = /* @__PURE__ */ new Map());
32490    if (map.has(name) === false) {
32491      map.set(name, {
32492        name,
32493        behavior
32494      });
32495    }
32496  }
32497  /**
32498   * Returns the enabled extensions of the given shader stage as a GLSL string.
32499   *
32500   * @param {string} shaderStage - The shader stage.
32501   * @return {string} The GLSL snippet that defines the enabled extensions.
32502   */
32503  getExtensions(shaderStage) {
32504    const snippets = [];
32505    if (shaderStage === "vertex") {
32506      const ext = this.renderer.backend.extensions;
32507      const isBatchedMesh = this.object.isBatchedMesh;
32508      if (isBatchedMesh && ext.has("WEBGL_multi_draw")) {
32509        this.enableExtension("GL_ANGLE_multi_draw", "require", shaderStage);
32510      }
32511    }
32512    const extensions = this.extensions[shaderStage];
32513    if (extensions !== void 0) {
32514      for (const { name, behavior } of extensions.values()) {
32515        snippets.push(`#extension ${name} : ${behavior}`);
32516      }
32517    }
32518    return snippets.join("\n");
32519  }
32520  /**
32521   * Returns the clip distances builtin.
32522   *
32523   * @return {string} The clip distances builtin.
32524   */
32525  getClipDistance() {
32526    return "gl_ClipDistance";
32527  }
32528  /**
32529   * Whether the requested feature is available or not.
32530   *
32531   * @param {string} name - The requested feature.
32532   * @return {boolean} Whether the requested feature is supported or not.
32533   */
32534  isAvailable(name) {
32535    let result = supports$1[name];
32536    if (result === void 0) {
32537      let extensionName;
32538      result = false;
32539      switch (name) {
32540        case "float32Filterable":
32541          extensionName = "OES_texture_float_linear";
32542          break;
32543        case "clipDistance":
32544          extensionName = "WEBGL_clip_cull_distance";
32545          break;
32546      }
32547      if (extensionName !== void 0) {
32548        const extensions = this.renderer.backend.extensions;
32549        if (extensions.has(extensionName)) {
32550          extensions.get(extensionName);
32551          result = true;
32552        }
32553      }
32554      supports$1[name] = result;
32555    }
32556    return result;
32557  }
32558  /**
32559   * Whether to flip texture data along its vertical axis or not.
32560   *
32561   * @return {boolean} Returns always `true` in context of GLSL.
32562   */
32563  isFlipY() {
32564    return true;
32565  }
32566  /**
32567   * Enables hardware clipping.
32568   *
32569   * @param {string} planeCount - The clipping plane count.
32570   */
32571  enableHardwareClipping(planeCount) {
32572    this.enableExtension("GL_ANGLE_clip_cull_distance", "require");
32573    this.builtins["vertex"].push(`out float gl_ClipDistance[ ${planeCount} ]`);
32574  }
32575  /**
32576   * Enables multiview.
32577   */
32578  enableMultiview() {
32579    this.enableExtension("GL_OVR_multiview2", "require", "fragment");
32580    this.enableExtension("GL_OVR_multiview2", "require", "vertex");
32581    this.builtins["vertex"].push("layout(num_views = 2) in");
32582  }
32583  /**
32584   * Registers a transform in context of Transform Feedback.
32585   *
32586   * @param {string} varyingName - The varying name.
32587   * @param {AttributeNode} attributeNode - The attribute node.
32588   */
32589  registerTransform(varyingName, attributeNode) {
32590    this.transforms.push({ varyingName, attributeNode });
32591  }
32592  /**
32593   * Returns the transforms of the given shader stage as a GLSL string.
32594   *
32595   * @param {string} shaderStage - The shader stage.
32596   * @return {string} The GLSL snippet that defines the transforms.
32597   */
32598  getTransforms() {
32599    const transforms = this.transforms;
32600    let snippet = "";
32601    for (let i = 0; i < transforms.length; i++) {
32602      const transform = transforms[i];
32603      const attributeName = this.getPropertyName(transform.attributeNode);
32604      if (attributeName) snippet += `${transform.varyingName} = ${attributeName};
32605	`;
32606    }
32607    return snippet;
32608  }
32609  /**
32610   * Returns a GLSL struct based on the given name and variables.
32611   *
32612   * @private
32613   * @param {string} name - The struct name.
32614   * @param {string} vars - The struct variables.
32615   * @return {string} The GLSL snippet representing a struct.
32616   */
32617  _getGLSLUniformStruct(name, vars) {
32618    return `
32619layout( std140 ) uniform ${name} {
32620${vars}
32621};`;
32622  }
32623  /**
32624   * Returns a GLSL vertex shader based on the given shader data.
32625   *
32626   * @private
32627   * @param {Object} shaderData - The shader data.
32628   * @return {string} The vertex shader.
32629   */
32630  _getGLSLVertexCode(shaderData) {
32631    return `#version 300 es
32632
32633${this.getSignature()}
32634
32635// extensions
32636${shaderData.extensions}
32637
32638// precision
32639${defaultPrecisions}
32640
32641// uniforms
32642${shaderData.uniforms}
32643
32644// varyings
32645${shaderData.varyings}
32646
32647// attributes
32648${shaderData.attributes}
32649
32650// vars
32651${shaderData.vars}
32652
32653// codes
32654${shaderData.codes}
32655
32656void main() {
32657
32658	// transforms
32659	${shaderData.transforms}
32660
32661	// flow
32662	${shaderData.flow}
32663
32664	gl_PointSize = 1.0;
32665
32666}
32667`;
32668  }
32669  /**
32670   * Returns a GLSL fragment shader based on the given shader data.
32671   *
32672   * @private
32673   * @param {Object} shaderData - The shader data.
32674   * @return {string} The vertex shader.
32675   */
32676  _getGLSLFragmentCode(shaderData) {
32677    return `#version 300 es
32678
32679${this.getSignature()}
32680
32681// extensions
32682${shaderData.extensions}
32683
32684// precision
32685${defaultPrecisions}
32686
32687// structs
32688${shaderData.structs}
32689
32690// uniforms
32691${shaderData.uniforms}
32692
32693// varyings
32694${shaderData.varyings}
32695
32696// vars
32697${shaderData.vars}
32698
32699// codes
32700${shaderData.codes}
32701
32702void main() {
32703
32704	// flow
32705	${shaderData.flow}
32706
32707}
32708`;
32709  }
32710  /**
32711   * Controls the code build of the shader stages.
32712   */
32713  buildCode() {
32714    const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} };
32715    this.sortBindingGroups();
32716    for (const shaderStage in shadersData) {
32717      let flow = "// code\n\n";
32718      flow += this.flowCode[shaderStage];
32719      const flowNodes = this.flowNodes[shaderStage];
32720      const mainNode = flowNodes[flowNodes.length - 1];
32721      for (const node of flowNodes) {
32722        const flowSlotData = this.getFlowData(
32723          node
32724          /*, shaderStage*/
32725        );
32726        const slotName = node.name;
32727        if (slotName) {
32728          if (flow.length > 0) flow += "\n";
32729          flow += `	// flow -> ${slotName}
32730	`;
32731        }
32732        flow += `${flowSlotData.code}
32733	`;
32734        if (node === mainNode && shaderStage !== "compute") {
32735          flow += "// result\n	";
32736          if (shaderStage === "vertex") {
32737            flow += "gl_Position = ";
32738            flow += `${flowSlotData.result};`;
32739          } else if (shaderStage === "fragment") {
32740            if (!node.outputNode.isOutputStructNode) {
32741              flow += "fragColor = ";
32742              flow += `${flowSlotData.result};`;
32743            }
32744          }
32745        }
32746      }
32747      const stageData = shadersData[shaderStage];
32748      stageData.extensions = this.getExtensions(shaderStage);
32749      stageData.uniforms = this.getUniforms(shaderStage);
32750      stageData.attributes = this.getAttributes(shaderStage);
32751      stageData.varyings = this.getVaryings(shaderStage);
32752      stageData.vars = this.getVars(shaderStage, true);
32753      stageData.structs = this.getStructs(shaderStage);
32754      stageData.codes = this.getCodes(shaderStage);
32755      stageData.transforms = this.getTransforms(shaderStage);
32756      stageData.flow = flow;
32757      if (shaderStage === "vertex") {
32758        const ext = this.renderer.backend.extensions;
32759        if (this.object.isBatchedMesh && ext.has("WEBGL_multi_draw") === false) {
32760          stageData.uniforms += "\nuniform uint nodeUniformDrawId;\n";
32761        }
32762      }
32763    }
32764    if (this.material !== null) {
32765      this.vertexShader = this._getGLSLVertexCode(shadersData.vertex);
32766      this.fragmentShader = this._getGLSLFragmentCode(shadersData.fragment);
32767    } else {
32768      this.computeShader = this._getGLSLVertexCode(shadersData.compute);
32769    }
32770  }
32771  /**
32772   * This method is one of the more important ones since it's responsible
32773   * for generating a matching binding instance for the given uniform node.
32774   *
32775   * These bindings are later used in the renderer to create bind groups
32776   * and layouts.
32777   *
32778   * @param {UniformNode} node - The uniform node.
32779   * @param {string} type - The node data type.
32780   * @param {string} shaderStage - The shader stage.
32781   * @param {?string} [name=null] - An optional uniform name.
32782   * @return {NodeUniform} The node uniform object.
32783   */
32784  getUniformFromNode(node, type, shaderStage, name = null) {
32785    const uniformNode = super.getUniformFromNode(node, type, shaderStage, name);
32786    const nodeData = this.getDataFromNode(node, shaderStage, this.globalCache);
32787    let uniformGPU = nodeData.uniformGPU;
32788    if (uniformGPU === void 0) {
32789      const group = node.groupNode;
32790      const groupName = group.name;
32791      const bindings = this.getBindGroupArray(groupName, shaderStage);
32792      if (type === "texture") {
32793        uniformGPU = new NodeSampledTexture(uniformNode.name, uniformNode.node, group);
32794        bindings.push(uniformGPU);
32795      } else if (type === "cubeTexture" || type === "cubeDepthTexture") {
32796        uniformGPU = new NodeSampledCubeTexture(uniformNode.name, uniformNode.node, group);
32797        bindings.push(uniformGPU);
32798      } else if (type === "texture3D") {
32799        uniformGPU = new NodeSampledTexture3D(uniformNode.name, uniformNode.node, group);
32800        bindings.push(uniformGPU);
32801      } else if (type === "buffer") {
32802        uniformNode.name = `buffer${node.id}`;
32803        const sharedData = this.getSharedDataFromNode(node);
32804        let buffer3 = sharedData.buffer;
32805        if (buffer3 === void 0) {
32806          node.name = `NodeBuffer_${node.id}`;
32807          buffer3 = new NodeUniformBuffer(node, group);
32808          buffer3.name = node.name;
32809          sharedData.buffer = buffer3;
32810        }
32811        bindings.push(buffer3);
32812        uniformGPU = buffer3;
32813      } else {
32814        let uniformsGroup = this.uniformGroups[groupName];
32815        if (uniformsGroup === void 0) {
32816          uniformsGroup = new NodeUniformsGroup(groupName, group);
32817          this.uniformGroups[groupName] = uniformsGroup;
32818          bindings.push(uniformsGroup);
32819        } else {
32820          if (bindings.indexOf(uniformsGroup) === -1) {
32821            bindings.push(uniformsGroup);
32822          }
32823        }
32824        uniformGPU = this.getNodeUniform(uniformNode, type);
32825        const uniformName = uniformGPU.name;
32826        const alreadyExists = uniformsGroup.uniforms.some((u) => u.name === uniformName);
32827        if (!alreadyExists) {
32828          uniformsGroup.addUniform(uniformGPU);
32829        }
32830      }
32831      nodeData.uniformGPU = uniformGPU;
32832    }
32833    return uniformNode;
32834  }
32835};
32836var _vector2 = null;
32837var _color4 = null;
32838var Backend = class {
32839  /**
32840   * Constructs a new backend.
32841   *
32842   * @param {Object} parameters - An object holding parameters for the backend.
32843   */
32844  constructor(parameters = {}) {
32845    this.parameters = Object.assign({}, parameters);
32846    this.data = /* @__PURE__ */ new WeakMap();
32847    this.renderer = null;
32848    this.domElement = null;
32849    this.timestampQueryPool = {
32850      [TimestampQuery.RENDER]: null,
32851      [TimestampQuery.COMPUTE]: null
32852    };
32853    this.trackTimestamp = parameters.trackTimestamp === true;
32854  }
32855  /**
32856   * Initializes the backend so it is ready for usage. Concrete backends
32857   * are supposed to implement their rendering context creation and related
32858   * operations in this method.
32859   *
32860   * @async
32861   * @param {Renderer} renderer - The renderer.
32862   * @return {Promise} A Promise that resolves when the backend has been initialized.
32863   */
32864  async init(renderer) {
32865    this.renderer = renderer;
32866  }
32867  /**
32868   * The coordinate system of the backend.
32869   *
32870   * @abstract
32871   * @type {number}
32872   * @readonly
32873   */
32874  get coordinateSystem() {
32875  }
32876  // render context
32877  /**
32878   * This method is executed at the beginning of a render call and
32879   * can be used by the backend to prepare the state for upcoming
32880   * draw calls.
32881   *
32882   * @abstract
32883   * @param {RenderContext} renderContext - The render context.
32884   */
32885  beginRender() {
32886  }
32887  /**
32888   * This method is executed at the end of a render call and
32889   * can be used by the backend to finalize work after draw
32890   * calls.
32891   *
32892   * @abstract
32893   * @param {RenderContext} renderContext - The render context.
32894   */
32895  finishRender() {
32896  }
32897  /**
32898   * This method is executed at the beginning of a compute call and
32899   * can be used by the backend to prepare the state for upcoming
32900   * compute tasks.
32901   *
32902   * @abstract
32903   * @param {Node|Array<Node>} computeGroup - The compute node(s).
32904   */
32905  beginCompute() {
32906  }
32907  /**
32908   * This method is executed at the end of a compute call and
32909   * can be used by the backend to finalize work after compute
32910   * tasks.
32911   *
32912   * @abstract
32913   * @param {Node|Array<Node>} computeGroup - The compute node(s).
32914   */
32915  finishCompute() {
32916  }
32917  // render object
32918  /**
32919   * Executes a draw command for the given render object.
32920   *
32921   * @abstract
32922   * @param {RenderObject} renderObject - The render object to draw.
32923   * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process.
32924   */
32925  draw() {
32926  }
32927  // compute node
32928  /**
32929   * Executes a compute command for the given compute node.
32930   *
32931   * @abstract
32932   * @param {Node|Array<Node>} computeGroup - The group of compute nodes of a compute call. Can be a single compute node.
32933   * @param {Node} computeNode - The compute node.
32934   * @param {Array<BindGroup>} bindings - The bindings.
32935   * @param {ComputePipeline} computePipeline - The compute pipeline.
32936   */
32937  compute() {
32938  }
32939  // program
32940  /**
32941   * Creates a shader program from the given programmable stage.
32942   *
32943   * @abstract
32944   * @param {ProgrammableStage} program - The programmable stage.
32945   */
32946  createProgram() {
32947  }
32948  /**
32949   * Destroys the shader program of the given programmable stage.
32950   *
32951   * @abstract
32952   * @param {ProgrammableStage} program - The programmable stage.
32953   */
32954  destroyProgram() {
32955  }
32956  // bindings
32957  /**
32958   * Creates bindings from the given bind group definition.
32959   *
32960   * @abstract
32961   * @param {BindGroup} bindGroup - The bind group.
32962   * @param {Array<BindGroup>} bindings - Array of bind groups.
32963   * @param {number} cacheIndex - The cache index.
32964   * @param {number} version - The version.
32965   */
32966  createBindings() {
32967  }
32968  /**
32969   * Updates the given bind group definition.
32970   *
32971   * @abstract
32972   * @param {BindGroup} bindGroup - The bind group.
32973   * @param {Array<BindGroup>} bindings - Array of bind groups.
32974   * @param {number} cacheIndex - The cache index.
32975   * @param {number} version - The version.
32976   */
32977  updateBindings() {
32978  }
32979  /**
32980   * Updates a buffer binding.
32981   *
32982   * @abstract
32983   * @param {Buffer} binding - The buffer binding to update.
32984   */
32985  updateBinding() {
32986  }
32987  // pipeline
32988  /**
32989   * Creates a render pipeline for the given render object.
32990   *
32991   * @abstract
32992   * @param {RenderObject} renderObject - The render object.
32993   * @param {Array<Promise>} promises - An array of compilation promises which are used in `compileAsync()`.
32994   */
32995  createRenderPipeline() {
32996  }
32997  /**
32998   * Creates a compute pipeline for the given compute node.
32999   *
33000   * @abstract
33001   * @param {ComputePipeline} computePipeline - The compute pipeline.
33002   * @param {Array<BindGroup>} bindings - The bindings.
33003   */
33004  createComputePipeline() {
33005  }
33006  // cache key
33007  /**
33008   * Returns `true` if the render pipeline requires an update.
33009   *
33010   * @abstract
33011   * @param {RenderObject} renderObject - The render object.
33012   * @return {boolean} Whether the render pipeline requires an update or not.
33013   */
33014  needsRenderUpdate() {
33015  }
33016  /**
33017   * Returns a cache key that is used to identify render pipelines.
33018   *
33019   * @abstract
33020   * @param {RenderObject} renderObject - The render object.
33021   * @return {string} The cache key.
33022   */
33023  getRenderCacheKey() {
33024  }
33025  // node builder
33026  /**
33027   * Returns a node builder for the given render object.
33028   *
33029   * @abstract
33030   * @param {RenderObject} renderObject - The render object.
33031   * @param {Renderer} renderer - The renderer.
33032   * @return {NodeBuilder} The node builder.
33033   */
33034  createNodeBuilder() {
33035  }
33036  // textures
33037  /**
33038   * Updates a GPU sampler for the given texture.
33039   *
33040   * @abstract
33041   * @param {Texture} texture - The texture to update the sampler for.
33042   * @return {string} The current sampler key.
33043   */
33044  updateSampler() {
33045  }
33046  /**
33047   * Creates a default texture for the given texture that can be used
33048   * as a placeholder until the actual texture is ready for usage.
33049   *
33050   * @abstract
33051   * @param {Texture} texture - The texture to create a default texture for.
33052   */
33053  createDefaultTexture() {
33054  }
33055  /**
33056   * Defines a texture on the GPU for the given texture object.
33057   *
33058   * @abstract
33059   * @param {Texture} texture - The texture.
33060   * @param {Object} [options={}] - Optional configuration parameter.
33061   */
33062  createTexture() {
33063  }
33064  /**
33065   * Uploads the updated texture data to the GPU.
33066   *
33067   * @abstract
33068   * @param {Texture} texture - The texture.
33069   * @param {Object} [options={}] - Optional configuration parameter.
33070   */
33071  updateTexture() {
33072  }
33073  /**
33074   * Generates mipmaps for the given texture.
33075   *
33076   * @abstract
33077   * @param {Texture} texture - The texture.
33078   */
33079  generateMipmaps() {
33080  }
33081  /**
33082   * Destroys the GPU data for the given texture object.
33083   *
33084   * @abstract
33085   * @param {Texture} texture - The texture.
33086   * @param {boolean} [isDefaultTexture=false] - Whether the texture uses a default GPU texture or not.
33087   */
33088  destroyTexture() {
33089  }
33090  /**
33091   * Returns texture data as a typed array.
33092   *
33093   * @abstract
33094   * @async
33095   * @param {Texture} texture - The texture to copy.
33096   * @param {number} x - The x coordinate of the copy origin.
33097   * @param {number} y - The y coordinate of the copy origin.
33098   * @param {number} width - The width of the copy.
33099   * @param {number} height - The height of the copy.
33100   * @param {number} faceIndex - The face index.
33101   * @return {Promise<TypedArray>} A Promise that resolves with a typed array when the copy operation has finished.
33102   */
33103  async copyTextureToBuffer() {
33104  }
33105  /**
33106   * Copies data of the given source texture to the given destination texture.
33107   *
33108   * @abstract
33109   * @param {Texture} srcTexture - The source texture.
33110   * @param {Texture} dstTexture - The destination texture.
33111   * @param {?(Box3|Box2)} [srcRegion=null] - The region of the source texture to copy.
33112   * @param {?(Vector2|Vector3)} [dstPosition=null] - The destination position of the copy.
33113   * @param {number} [srcLevel=0] - The source mip level to copy from.
33114   * @param {number} [dstLevel=0] - The destination mip level to copy to.
33115   */
33116  copyTextureToTexture() {
33117  }
33118  /**
33119  * Copies the current bound framebuffer to the given texture.
33120  *
33121  * @abstract
33122  * @param {Texture} texture - The destination texture.
33123  * @param {RenderContext} renderContext - The render context.
33124  * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy.
33125  */
33126  copyFramebufferToTexture() {
33127  }
33128  // attributes
33129  /**
33130   * Creates the GPU buffer of a shader attribute.
33131   *
33132   * @abstract
33133   * @param {BufferAttribute} attribute - The buffer attribute.
33134   */
33135  createAttribute() {
33136  }
33137  /**
33138   * Creates the GPU buffer of an indexed shader attribute.
33139   *
33140   * @abstract
33141   * @param {BufferAttribute} attribute - The indexed buffer attribute.
33142   */
33143  createIndexAttribute() {
33144  }
33145  /**
33146   * Creates the GPU buffer of a storage attribute.
33147   *
33148   * @abstract
33149   * @param {BufferAttribute} attribute - The buffer attribute.
33150   */
33151  createStorageAttribute() {
33152  }
33153  /**
33154   * Updates the GPU buffer of a shader attribute.
33155   *
33156   * @abstract
33157   * @param {BufferAttribute} attribute - The buffer attribute to update.
33158   */
33159  updateAttribute() {
33160  }
33161  /**
33162   * Destroys the GPU buffer of a shader attribute.
33163   *
33164   * @abstract
33165   * @param {BufferAttribute} attribute - The buffer attribute to destroy.
33166   */
33167  destroyAttribute() {
33168  }
33169  // canvas
33170  /**
33171   * Returns the backend's rendering context.
33172   *
33173   * @abstract
33174   * @return {Object} The rendering context.
33175   */
33176  getContext() {
33177  }
33178  /**
33179   * Backends can use this method if they have to run
33180   * logic when the renderer gets resized.
33181   *
33182   * @abstract
33183   */
33184  updateSize() {
33185  }
33186  /**
33187   * Updates the viewport with the values from the given render context.
33188   *
33189   * @abstract
33190   * @param {RenderContext} renderContext - The render context.
33191   */
33192  updateViewport() {
33193  }
33194  // utils
33195  /**
33196   * Updates a unique identifier for the given render context that can be used
33197   * to allocate resources like occlusion queries or timestamp queries.
33198   *
33199   * @param {RenderContext|ComputeNode} abstractRenderContext - The render context.
33200   */
33201  updateTimeStampUID(abstractRenderContext) {
33202    const contextData = this.get(abstractRenderContext);
33203    const frame = this.renderer.info.frame;
33204    let prefix;
33205    if (abstractRenderContext.isComputeNode === true) {
33206      prefix = "c:" + this.renderer.info.compute.frameCalls;
33207    } else {
33208      prefix = "r:" + this.renderer.info.render.frameCalls;
33209    }
33210    contextData.timestampUID = prefix + ":" + abstractRenderContext.id + ":f" + frame;
33211  }
33212  /**
33213   * Returns a unique identifier for the given render context that can be used
33214   * to allocate resources like occlusion queries or timestamp queries.
33215   *
33216   * @param {RenderContext|ComputeNode} abstractRenderContext - The render context.
33217   * @return {string} The unique identifier.
33218   */
33219  getTimestampUID(abstractRenderContext) {
33220    return this.get(abstractRenderContext).timestampUID;
33221  }
33222  /**
33223   * Returns all timestamp frames for the given type.
33224   *
33225   * @param {string} type - The type of the time stamp.
33226   * @return {Array<number>} The timestamp frames.
33227   */
33228  getTimestampFrames(type) {
33229    const queryPool = this.timestampQueryPool[type];
33230    return queryPool ? queryPool.getTimestampFrames() : [];
33231  }
33232  /**
33233   * Returns the query pool for the given uid.
33234   *
33235   * @param {string} uid - The unique identifier.
33236   * @return {TimestampQueryPool} The query pool.
33237   */
33238  _getQueryPool(uid) {
33239    const type = uid.startsWith("c:") ? TimestampQuery.COMPUTE : TimestampQuery.RENDER;
33240    const queryPool = this.timestampQueryPool[type];
33241    return queryPool;
33242  }
33243  /**
33244   * Returns the timestamp for the given uid.
33245   *
33246   * @param {string} uid - The unique identifier.
33247   * @return {number} The timestamp.
33248   */
33249  getTimestamp(uid) {
33250    const queryPool = this._getQueryPool(uid);
33251    return queryPool.getTimestamp(uid);
33252  }
33253  /**
33254   * Returns `true` if a timestamp for the given uid is available.
33255   *
33256   * @param {string} uid - The unique identifier.
33257   * @return {boolean} Whether the timestamp is available or not.
33258   */
33259  hasTimestamp(uid) {
33260    const queryPool = this._getQueryPool(uid);
33261    return queryPool.hasTimestamp(uid);
33262  }
33263  /**
33264   * Returns `true` if the given 3D object is fully occluded by other
33265   * 3D objects in the scene. Backends must implement this method by using
33266   * a Occlusion Query API.
33267   *
33268   * @abstract
33269   * @param {RenderContext} renderContext - The render context.
33270   * @param {Object3D} object - The 3D object to test.
33271   * @return {boolean} Whether the 3D object is fully occluded or not.
33272   */
33273  isOccluded() {
33274  }
33275  /**
33276   * Resolves the time stamp for the given render context and type.
33277   *
33278   * @async
33279   * @abstract
33280   * @param {string} [type='render'] - The type of the time stamp.
33281   * @return {Promise<number>} A Promise that resolves with the time stamp.
33282   */
33283  async resolveTimestampsAsync(type = "render") {
33284    if (!this.trackTimestamp) {
33285      warnOnce("WebGPURenderer: Timestamp tracking is disabled.");
33286      return;
33287    }
33288    const queryPool = this.timestampQueryPool[type];
33289    if (!queryPool) {
33290      return;
33291    }
33292    const duration = await queryPool.resolveQueriesAsync();
33293    this.renderer.info[type].timestamp = duration;
33294    return duration;
33295  }
33296  /**
33297   * This method performs a readback operation by moving buffer data from
33298   * a storage buffer attribute from the GPU to the CPU.
33299   *
33300   * @async
33301   * @param {StorageBufferAttribute} attribute - The storage buffer attribute.
33302   * @return {Promise<ArrayBuffer>} A promise that resolves with the buffer data when the data are ready.
33303   */
33304  async getArrayBufferAsync() {
33305  }
33306  /**
33307   * Checks if the given feature is supported by the backend.
33308   *
33309   * @async
33310   * @abstract
33311   * @param {string} name - The feature's name.
33312   * @return {Promise<boolean>} A Promise that resolves with a bool that indicates whether the feature is supported or not.
33313   */
33314  async hasFeatureAsync() {
33315  }
33316  /**
33317   * Checks if the given feature is supported  by the backend.
33318   *
33319   * @abstract
33320   * @param {string} name - The feature's name.
33321   * @return {boolean} Whether the feature is supported or not.
33322   */
33323  hasFeature() {
33324  }
33325  /**
33326   * Returns the drawing buffer size.
33327   *
33328   * @return {Vector2} The drawing buffer size.
33329   */
33330  getDrawingBufferSize() {
33331    _vector2 = _vector2 || new Vector2();
33332    return this.renderer.getDrawingBufferSize(_vector2);
33333  }
33334  /**
33335   * Defines the scissor test.
33336   *
33337   * @abstract
33338   * @param {boolean} boolean - Whether the scissor test should be enabled or not.
33339   */
33340  setScissorTest() {
33341  }
33342  /**
33343   * Returns the clear color and alpha into a single
33344   * color object.
33345   *
33346   * @return {Color4} The clear color.
33347   */
33348  getClearColor() {
33349    const renderer = this.renderer;
33350    _color4 = _color4 || new Color4();
33351    renderer.getClearColor(_color4);
33352    _color4.getRGB(_color4);
33353    return _color4;
33354  }
33355  /**
33356   * Returns the DOM element. If no DOM element exists, the backend
33357   * creates a new one.
33358   *
33359   * @return {HTMLCanvasElement} The DOM element.
33360   */
33361  getDomElement() {
33362    let domElement = this.domElement;
33363    if (domElement === null) {
33364      domElement = this.parameters.canvas !== void 0 ? this.parameters.canvas : createCanvasElement();
33365      if ("setAttribute" in domElement) domElement.setAttribute("data-engine", `three.js r${REVISION} webgpu`);
33366      this.domElement = domElement;
33367    }
33368    return domElement;
33369  }
33370  /**
33371   * Checks if the backend has the given compatibility.
33372   *
33373   * @abstract
33374   * @param {string} name - The compatibility.
33375   * @return {boolean} Whether the backend has the given compatibility or not.
33376   */
33377  hasCompatibility() {
33378    return false;
33379  }
33380  /**
33381   * Initializes the render target defined in the given render context.
33382   *
33383   * @abstract
33384   * @param {RenderContext} renderContext - The render context.
33385   */
33386  initRenderTarget() {
33387  }
33388  /**
33389   * Sets a dictionary for the given object into the
33390   * internal data structure.
33391   *
33392   * @param {Object} object - The object.
33393   * @param {Object} value - The dictionary to set.
33394   */
33395  set(object, value) {
33396    this.data.set(object, value);
33397  }
33398  /**
33399   * Returns the dictionary for the given object.
33400   *
33401   * @param {Object} object - The object.
33402   * @return {Object} The object's dictionary.
33403   */
33404  get(object) {
33405    let map = this.data.get(object);
33406    if (map === void 0) {
33407      map = {};
33408      this.data.set(object, map);
33409    }
33410    return map;
33411  }
33412  /**
33413   * Checks if the given object has a dictionary
33414   * with data defined.
33415   *
33416   * @param {Object} object - The object.
33417   * @return {boolean} Whether a dictionary for the given object as been defined or not.
33418   */
33419  has(object) {
33420    return this.data.has(object);
33421  }
33422  /**
33423   * Deletes an object from the internal data structure.
33424   *
33425   * @param {Object} object - The object to delete.
33426   */
33427  delete(object) {
33428    this.data.delete(object);
33429  }
33430  /**
33431   * Delete GPU data associated with a bind group.
33432   *
33433   * @abstract
33434   * @param {BindGroup} bindGroup - The bind group.
33435   */
33436  deleteBindGroupData() {
33437  }
33438  /**
33439   * Frees internal resources.
33440   *
33441   * @abstract
33442   */
33443  dispose() {
33444  }
33445};
33446var _id$1 = 0;
33447var DualAttributeData = class {
33448  constructor(attributeData, dualBuffer) {
33449    this.buffers = [attributeData.bufferGPU, dualBuffer];
33450    this.type = attributeData.type;
33451    this.bufferType = attributeData.bufferType;
33452    this.pbo = attributeData.pbo;
33453    this.byteLength = attributeData.byteLength;
33454    this.bytesPerElement = attributeData.BYTES_PER_ELEMENT;
33455    this.version = attributeData.version;
33456    this.isInteger = attributeData.isInteger;
33457    this.activeBufferIndex = 0;
33458    this.baseId = attributeData.id;
33459  }
33460  get id() {
33461    return `${this.baseId}|${this.activeBufferIndex}`;
33462  }
33463  get bufferGPU() {
33464    return this.buffers[this.activeBufferIndex];
33465  }
33466  get transformBuffer() {
33467    return this.buffers[this.activeBufferIndex ^ 1];
33468  }
33469  switchBuffers() {
33470    this.activeBufferIndex ^= 1;
33471  }
33472};
33473var WebGLAttributeUtils = class {
33474  /**
33475   * Constructs a new utility object.
33476   *
33477   * @param {WebGLBackend} backend - The WebGL 2 backend.
33478   */
33479  constructor(backend) {
33480    this.backend = backend;
33481  }
33482  /**
33483   * Creates the GPU buffer for the given buffer attribute.
33484   *
33485   * @param {BufferAttribute} attribute - The buffer attribute.
33486   * @param {GLenum } bufferType - A flag that indicates the buffer type and thus binding point target.
33487   */
33488  createAttribute(attribute3, bufferType) {
33489    const backend = this.backend;
33490    const { gl } = backend;
33491    const array3 = attribute3.array;
33492    const usage = attribute3.usage || gl.STATIC_DRAW;
33493    const bufferAttribute3 = attribute3.isInterleavedBufferAttribute ? attribute3.data : attribute3;
33494    const bufferData = backend.get(bufferAttribute3);
33495    let bufferGPU = bufferData.bufferGPU;
33496    if (bufferGPU === void 0) {
33497      bufferGPU = this._createBuffer(gl, bufferType, array3, usage);
33498      bufferData.bufferGPU = bufferGPU;
33499      bufferData.bufferType = bufferType;
33500      bufferData.version = bufferAttribute3.version;
33501    }
33502    let type;
33503    if (array3 instanceof Float32Array) {
33504      type = gl.FLOAT;
33505    } else if (typeof Float16Array !== "undefined" && array3 instanceof Float16Array) {
33506      type = gl.HALF_FLOAT;
33507    } else if (array3 instanceof Uint16Array) {
33508      if (attribute3.isFloat16BufferAttribute) {
33509        type = gl.HALF_FLOAT;
33510      } else {
33511        type = gl.UNSIGNED_SHORT;
33512      }
33513    } else if (array3 instanceof Int16Array) {
33514      type = gl.SHORT;
33515    } else if (array3 instanceof Uint32Array) {
33516      type = gl.UNSIGNED_INT;
33517    } else if (array3 instanceof Int32Array) {
33518      type = gl.INT;
33519    } else if (array3 instanceof Int8Array) {
33520      type = gl.BYTE;
33521    } else if (array3 instanceof Uint8Array) {
33522      type = gl.UNSIGNED_BYTE;
33523    } else if (array3 instanceof Uint8ClampedArray) {
33524      type = gl.UNSIGNED_BYTE;
33525    } else {
33526      throw new Error("THREE.WebGLBackend: Unsupported buffer data format: " + array3);
33527    }
33528    let attributeData = {
33529      bufferGPU,
33530      bufferType,
33531      type,
33532      byteLength: array3.byteLength,
33533      bytesPerElement: array3.BYTES_PER_ELEMENT,
33534      version: attribute3.version,
33535      pbo: attribute3.pbo,
33536      isInteger: type === gl.INT || type === gl.UNSIGNED_INT || attribute3.gpuType === IntType,
33537      id: _id$1++
33538    };
33539    if (attribute3.isStorageBufferAttribute || attribute3.isStorageInstancedBufferAttribute) {
33540      const bufferGPUDual = this._createBuffer(gl, bufferType, array3, usage);
33541      attributeData = new DualAttributeData(attributeData, bufferGPUDual);
33542    }
33543    backend.set(attribute3, attributeData);
33544  }
33545  /**
33546   * Updates the GPU buffer of the given buffer attribute.
33547   *
33548   * @param {BufferAttribute} attribute - The buffer attribute.
33549   */
33550  updateAttribute(attribute3) {
33551    const backend = this.backend;
33552    const { gl } = backend;
33553    const array3 = attribute3.array;
33554    const bufferAttribute3 = attribute3.isInterleavedBufferAttribute ? attribute3.data : attribute3;
33555    const bufferData = backend.get(bufferAttribute3);
33556    const bufferType = bufferData.bufferType;
33557    const updateRanges = attribute3.isInterleavedBufferAttribute ? attribute3.data.updateRanges : attribute3.updateRanges;
33558    gl.bindBuffer(bufferType, bufferData.bufferGPU);
33559    if (updateRanges.length === 0) {
33560      gl.bufferSubData(bufferType, 0, array3);
33561    } else {
33562      for (let i = 0, l = updateRanges.length; i < l; i++) {
33563        const range3 = updateRanges[i];
33564        gl.bufferSubData(
33565          bufferType,
33566          range3.start * array3.BYTES_PER_ELEMENT,
33567          array3,
33568          range3.start,
33569          range3.count
33570        );
33571      }
33572      bufferAttribute3.clearUpdateRanges();
33573    }
33574    gl.bindBuffer(bufferType, null);
33575    bufferData.version = bufferAttribute3.version;
33576  }
33577  /**
33578   * Destroys the GPU buffer of the given buffer attribute.
33579   *
33580   * @param {BufferAttribute} attribute - The buffer attribute.
33581   */
33582  destroyAttribute(attribute3) {
33583    const backend = this.backend;
33584    const { gl } = backend;
33585    if (attribute3.isInterleavedBufferAttribute) {
33586      backend.delete(attribute3.data);
33587    }
33588    const attributeData = backend.get(attribute3);
33589    gl.deleteBuffer(attributeData.bufferGPU);
33590    backend.delete(attribute3);
33591  }
33592  /**
33593   * This method performs a readback operation by moving buffer data from
33594   * a storage buffer attribute from the GPU to the CPU. ReadbackBuffer can
33595   * be used to retain and reuse handles to the intermediate buffers and prevent
33596   * new allocation.
33597   *
33598   * @async
33599   * @param {BufferAttribute} attribute - The storage buffer attribute to read frm.
33600   * @param {ReadbackBuffer|ArrayBuffer} target - The storage buffer attribute.
33601   * @param {number} offset - The storage buffer attribute.
33602   * @param {number} count - The offset from which to start reading the
33603   * @return {Promise<ArrayBuffer|ReadbackBuffer>} A promise that resolves with the buffer data when the data are ready.
33604   */
33605  async getArrayBufferAsync(attribute3, target = null, offset3 = 0, count = -1) {
33606    const backend = this.backend;
33607    const { gl } = backend;
33608    const bufferAttribute3 = attribute3.isInterleavedBufferAttribute ? attribute3.data : attribute3;
33609    const attributeInfo = backend.get(bufferAttribute3);
33610    const { bufferGPU } = attributeInfo;
33611    const byteLength = count === -1 ? attributeInfo.byteLength - offset3 : count;
33612    let dstBuffer;
33613    if (target === null) {
33614      dstBuffer = new Uint8Array(new ArrayBuffer(byteLength));
33615    } else if (target.isReadbackBuffer) {
33616      if (target._mapped === true) {
33617        throw new Error("WebGPURenderer: ReadbackBuffer must be released before being used again.");
33618      }
33619      const releaseCallback = () => {
33620        target.buffer = null;
33621        target._mapped = false;
33622        target.removeEventListener("release", releaseCallback);
33623        target.removeEventListener("dispose", releaseCallback);
33624      };
33625      target.addEventListener("release", releaseCallback);
33626      target.addEventListener("dispose", releaseCallback);
33627      dstBuffer = new Uint8Array(new ArrayBuffer(byteLength));
33628      target.buffer = dstBuffer.buffer;
33629    } else {
33630      dstBuffer = new Uint8Array(target);
33631    }
33632    gl.bindBuffer(gl.COPY_READ_BUFFER, bufferGPU);
33633    gl.getBufferSubData(gl.COPY_READ_BUFFER, offset3, dstBuffer);
33634    gl.bindBuffer(gl.COPY_READ_BUFFER, null);
33635    gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
33636    if (target && target.isReadbackBuffer) {
33637      return target;
33638    } else {
33639      return dstBuffer.buffer;
33640    }
33641  }
33642  /**
33643   * Creates a WebGL buffer with the given data.
33644   *
33645   * @private
33646   * @param {WebGL2RenderingContext} gl - The rendering context.
33647   * @param {GLenum } bufferType - A flag that indicates the buffer type and thus binding point target.
33648   * @param {TypedArray} array - The array of the buffer attribute.
33649   * @param {GLenum} usage - The usage.
33650   * @return {WebGLBuffer} The WebGL buffer.
33651   */
33652  _createBuffer(gl, bufferType, array3, usage) {
33653    const bufferGPU = gl.createBuffer();
33654    gl.bindBuffer(bufferType, bufferGPU);
33655    gl.bufferData(bufferType, array3, usage);
33656    gl.bindBuffer(bufferType, null);
33657    return bufferGPU;
33658  }
33659};
33660var equationToGL;
33661var factorToGL;
33662var WebGLState = class {
33663  /**
33664   * Constructs a new utility object.
33665   *
33666   * @param {WebGLBackend} backend - The WebGL 2 backend.
33667   */
33668  constructor(backend) {
33669    this.backend = backend;
33670    this.gl = this.backend.gl;
33671    this.enabled = {};
33672    this.parameters = {};
33673    this.currentFlipSided = null;
33674    this.currentCullFace = null;
33675    this.currentProgram = null;
33676    this.currentBlendingEnabled = false;
33677    this.currentBlending = null;
33678    this.currentBlendSrc = null;
33679    this.currentBlendDst = null;
33680    this.currentBlendSrcAlpha = null;
33681    this.currentBlendDstAlpha = null;
33682    this.currentPremultipledAlpha = null;
33683    this.currentPolygonOffsetFactor = null;
33684    this.currentPolygonOffsetUnits = null;
33685    this.currentColorMask = null;
33686    this.currentDepthReversed = false;
33687    this.currentDepthFunc = null;
33688    this.currentDepthMask = null;
33689    this.currentStencilFunc = null;
33690    this.currentStencilRef = null;
33691    this.currentStencilFuncMask = null;
33692    this.currentStencilFail = null;
33693    this.currentStencilZFail = null;
33694    this.currentStencilZPass = null;
33695    this.currentStencilMask = null;
33696    this.currentLineWidth = null;
33697    this.currentClippingPlanes = 0;
33698    this.currentVAO = null;
33699    this.currentIndex = null;
33700    this.currentBoundFramebuffers = {};
33701    this.currentDrawbuffers = /* @__PURE__ */ new WeakMap();
33702    this.maxTextures = this.gl.getParameter(this.gl.MAX_TEXTURE_IMAGE_UNITS);
33703    this.currentTextureSlot = null;
33704    this.currentBoundTextures = {};
33705    this.currentBoundBufferBases = {};
33706    this._init();
33707  }
33708  /**
33709   * Inits the state of the utility.
33710   *
33711   * @private
33712   */
33713  _init() {
33714    const gl = this.gl;
33715    equationToGL = {
33716      [AddEquation]: gl.FUNC_ADD,
33717      [SubtractEquation]: gl.FUNC_SUBTRACT,
33718      [ReverseSubtractEquation]: gl.FUNC_REVERSE_SUBTRACT
33719    };
33720    factorToGL = {
33721      [ZeroFactor]: gl.ZERO,
33722      [OneFactor]: gl.ONE,
33723      [SrcColorFactor]: gl.SRC_COLOR,
33724      [SrcAlphaFactor]: gl.SRC_ALPHA,
33725      [SrcAlphaSaturateFactor]: gl.SRC_ALPHA_SATURATE,
33726      [DstColorFactor]: gl.DST_COLOR,
33727      [DstAlphaFactor]: gl.DST_ALPHA,
33728      [OneMinusSrcColorFactor]: gl.ONE_MINUS_SRC_COLOR,
33729      [OneMinusSrcAlphaFactor]: gl.ONE_MINUS_SRC_ALPHA,
33730      [OneMinusDstColorFactor]: gl.ONE_MINUS_DST_COLOR,
33731      [OneMinusDstAlphaFactor]: gl.ONE_MINUS_DST_ALPHA
33732    };
33733    const scissorParam = gl.getParameter(gl.SCISSOR_BOX);
33734    const viewportParam = gl.getParameter(gl.VIEWPORT);
33735    this.currentScissor = new Vector4().fromArray(scissorParam);
33736    this.currentViewport = new Vector4().fromArray(viewportParam);
33737    this._tempVec4 = new Vector4();
33738  }
33739  /**
33740   * Enables the given WebGL capability.
33741   *
33742   * This method caches the capability state so
33743   * `gl.enable()` is only called when necessary.
33744   *
33745   * @param {GLenum} id - The capability to enable.
33746   */
33747  enable(id) {
33748    const { enabled } = this;
33749    if (enabled[id] !== true) {
33750      this.gl.enable(id);
33751      enabled[id] = true;
33752    }
33753  }
33754  /**
33755   * Disables the given WebGL capability.
33756   *
33757   * This method caches the capability state so
33758   * `gl.disable()` is only called when necessary.
33759   *
33760   * @param {GLenum} id - The capability to enable.
33761   */
33762  disable(id) {
33763    const { enabled } = this;
33764    if (enabled[id] !== false) {
33765      this.gl.disable(id);
33766      enabled[id] = false;
33767    }
33768  }
33769  /**
33770   * Specifies whether polygons are front- or back-facing
33771   * by setting the winding orientation.
33772   *
33773   * This method caches the state so `gl.frontFace()` is only
33774   * called when necessary.
33775   *
33776   * @param {boolean} flipSided - Whether triangles flipped their sides or not.
33777   */
33778  setFlipSided(flipSided) {
33779    if (this.currentFlipSided !== flipSided) {
33780      const { gl } = this;
33781      if (flipSided) {
33782        gl.frontFace(gl.CW);
33783      } else {
33784        gl.frontFace(gl.CCW);
33785      }
33786      this.currentFlipSided = flipSided;
33787    }
33788  }
33789  /**
33790   * Specifies whether or not front- and/or back-facing
33791   * polygons can be culled.
33792   *
33793   * This method caches the state so `gl.cullFace()` is only
33794   * called when necessary.
33795   *
33796   * @param {number} cullFace - Defines which polygons are candidates for culling.
33797   */
33798  setCullFace(cullFace) {
33799    const { gl } = this;
33800    if (cullFace !== CullFaceNone) {
33801      this.enable(gl.CULL_FACE);
33802      if (cullFace !== this.currentCullFace) {
33803        if (cullFace === CullFaceBack) {
33804          gl.cullFace(gl.BACK);
33805        } else if (cullFace === CullFaceFront) {
33806          gl.cullFace(gl.FRONT);
33807        } else {
33808          gl.cullFace(gl.FRONT_AND_BACK);
33809        }
33810      }
33811    } else {
33812      this.disable(gl.CULL_FACE);
33813    }
33814    this.currentCullFace = cullFace;
33815  }
33816  /**
33817   * Specifies the width of line primitives.
33818   *
33819   * This method caches the state so `gl.lineWidth()` is only
33820   * called when necessary.
33821   *
33822   * @param {number} width - The line width.
33823   */
33824  setLineWidth(width) {
33825    const { currentLineWidth, gl } = this;
33826    if (width !== currentLineWidth) {
33827      gl.lineWidth(width);
33828      this.currentLineWidth = width;
33829    }
33830  }
33831  setMRTBlending(textures, mrt3, material) {
33832    const gl = this.gl;
33833    const drawBuffersIndexedExt = this.backend.drawBuffersIndexedExt;
33834    if (!drawBuffersIndexedExt) {
33835      warnOnce("WebGPURenderer: Multiple Render Targets (MRT) blending configuration is not fully supported in compatibility mode. The material blending will be used for all render targets.");
33836      return;
33837    }
33838    for (let i = 0; i < textures.length; i++) {
33839      const texture3 = textures[i];
33840      let blending = null;
33841      if (mrt3 !== null) {
33842        const blendMode = mrt3.getBlendMode(texture3.name);
33843        if (blendMode.blending === MaterialBlending) {
33844          blending = material;
33845        } else if (blendMode.blending !== NoBlending) {
33846          blending = blendMode;
33847        }
33848      } else {
33849        blending = material;
33850      }
33851      if (blending !== null) {
33852        this._setMRTBlendingIndex(i, blending);
33853      } else {
33854        drawBuffersIndexedExt.blendFuncSeparateiOES(i, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO);
33855      }
33856    }
33857  }
33858  /**
33859   * Applies blending configuration for a specific draw buffer index.
33860   *
33861   * @private
33862   * @param {number} index - The draw buffer index.
33863   * @param {Object} blending - The blending configuration (material or BlendMode).
33864   */
33865  _setMRTBlendingIndex(index, blending) {
33866    const { gl } = this;
33867    const drawBuffersIndexedExt = this.backend.drawBuffersIndexedExt;
33868    const blendingType = blending.blending;
33869    const blendSrc = blending.blendSrc;
33870    const blendDst = blending.blendDst;
33871    const blendEquation = blending.blendEquation;
33872    const premultipliedAlpha = blending.premultipliedAlpha;
33873    if (blendingType === CustomBlending) {
33874      const blendSrcAlpha = blending.blendSrcAlpha !== null ? blending.blendSrcAlpha : blendSrc;
33875      const blendDstAlpha = blending.blendDstAlpha !== null ? blending.blendDstAlpha : blendDst;
33876      const blendEquationAlpha = blending.blendEquationAlpha !== null ? blending.blendEquationAlpha : blendEquation;
33877      drawBuffersIndexedExt.blendEquationSeparateiOES(index, equationToGL[blendEquation], equationToGL[blendEquationAlpha]);
33878      drawBuffersIndexedExt.blendFuncSeparateiOES(index, factorToGL[blendSrc], factorToGL[blendDst], factorToGL[blendSrcAlpha], factorToGL[blendDstAlpha]);
33879    } else {
33880      drawBuffersIndexedExt.blendEquationSeparateiOES(index, gl.FUNC_ADD, gl.FUNC_ADD);
33881      if (premultipliedAlpha) {
33882        switch (blendingType) {
33883          case NormalBlending:
33884            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
33885            break;
33886          case AdditiveBlending:
33887            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.ONE, gl.ONE, gl.ONE, gl.ONE);
33888            break;
33889          case SubtractiveBlending:
33890            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE);
33891            break;
33892          case MultiplyBlending:
33893            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE);
33894            break;
33895          default:
33896            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
33897            break;
33898        }
33899      } else {
33900        switch (blendingType) {
33901          case NormalBlending:
33902            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
33903            break;
33904          case AdditiveBlending:
33905            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE);
33906            break;
33907          case SubtractiveBlending:
33908            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE);
33909            break;
33910          case MultiplyBlending:
33911            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE);
33912            break;
33913          default:
33914            drawBuffersIndexedExt.blendFuncSeparateiOES(index, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
33915            break;
33916        }
33917      }
33918    }
33919  }
33920  /**
33921   * Defines the blending.
33922   *
33923   * This method caches the state so `gl.blendEquation()`, `gl.blendEquationSeparate()`,
33924   * `gl.blendFunc()` and  `gl.blendFuncSeparate()` are only called when necessary.
33925   *
33926   * @param {number} blending - The blending type.
33927   * @param {number} blendEquation - The blending equation.
33928   * @param {number} blendSrc - Only relevant for custom blending. The RGB source blending factor.
33929   * @param {number} blendDst - Only relevant for custom blending. The RGB destination blending factor.
33930   * @param {number} blendEquationAlpha - Only relevant for custom blending. The blending equation for alpha.
33931   * @param {number} blendSrcAlpha - Only relevant for custom blending. The alpha source blending factor.
33932   * @param {number} blendDstAlpha - Only relevant for custom blending. The alpha destination blending factor.
33933   * @param {boolean} premultipliedAlpha - Whether premultiplied alpha is enabled or not.
33934   */
33935  setBlending(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha) {
33936    const { gl } = this;
33937    if (blending === NoBlending) {
33938      if (this.currentBlendingEnabled === true) {
33939        this.disable(gl.BLEND);
33940        this.currentBlendingEnabled = false;
33941      }
33942      return;
33943    }
33944    if (this.currentBlendingEnabled === false) {
33945      this.enable(gl.BLEND);
33946      this.currentBlendingEnabled = true;
33947    }
33948    if (blending !== CustomBlending) {
33949      if (blending !== this.currentBlending || premultipliedAlpha !== this.currentPremultipledAlpha) {
33950        if (this.currentBlendEquation !== AddEquation || this.currentBlendEquationAlpha !== AddEquation) {
33951          gl.blendEquation(gl.FUNC_ADD);
33952          this.currentBlendEquation = AddEquation;
33953          this.currentBlendEquationAlpha = AddEquation;
33954        }
33955        if (premultipliedAlpha) {
33956          switch (blending) {
33957            case NormalBlending:
33958              gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
33959              break;
33960            case AdditiveBlending:
33961              gl.blendFunc(gl.ONE, gl.ONE);
33962              break;
33963            case SubtractiveBlending:
33964              gl.blendFuncSeparate(gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE);
33965              break;
33966            case MultiplyBlending:
33967              gl.blendFuncSeparate(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE);
33968              break;
33969            default:
33970              error("WebGLState: Invalid blending: ", blending);
33971              break;
33972          }
33973        } else {
33974          switch (blending) {
33975            case NormalBlending:
33976              gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
33977              break;
33978            case AdditiveBlending:
33979              gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE);
33980              break;
33981            case SubtractiveBlending:
33982              error("WebGLState: SubtractiveBlending requires material.premultipliedAlpha = true");
33983              break;
33984            case MultiplyBlending:
33985              error("WebGLState: MultiplyBlending requires material.premultipliedAlpha = true");
33986              break;
33987            default:
33988              error("WebGLState: Invalid blending: ", blending);
33989              break;
33990          }
33991        }
33992        this.currentBlendSrc = null;
33993        this.currentBlendDst = null;
33994        this.currentBlendSrcAlpha = null;
33995        this.currentBlendDstAlpha = null;
33996        this.currentBlending = blending;
33997        this.currentPremultipledAlpha = premultipliedAlpha;
33998      }
33999      return;
34000    }
34001    blendEquationAlpha = blendEquationAlpha || blendEquation;
34002    blendSrcAlpha = blendSrcAlpha || blendSrc;
34003    blendDstAlpha = blendDstAlpha || blendDst;
34004    if (blendEquation !== this.currentBlendEquation || blendEquationAlpha !== this.currentBlendEquationAlpha) {
34005      gl.blendEquationSeparate(equationToGL[blendEquation], equationToGL[blendEquationAlpha]);
34006      this.currentBlendEquation = blendEquation;
34007      this.currentBlendEquationAlpha = blendEquationAlpha;
34008    }
34009    if (blendSrc !== this.currentBlendSrc || blendDst !== this.currentBlendDst || blendSrcAlpha !== this.currentBlendSrcAlpha || blendDstAlpha !== this.currentBlendDstAlpha) {
34010      gl.blendFuncSeparate(factorToGL[blendSrc], factorToGL[blendDst], factorToGL[blendSrcAlpha], factorToGL[blendDstAlpha]);
34011      this.currentBlendSrc = blendSrc;
34012      this.currentBlendDst = blendDst;
34013      this.currentBlendSrcAlpha = blendSrcAlpha;
34014      this.currentBlendDstAlpha = blendDstAlpha;
34015    }
34016    this.currentBlending = blending;
34017    this.currentPremultipledAlpha = false;
34018  }
34019  /**
34020   * Specifies whether colors can be written when rendering
34021   * into a framebuffer or not.
34022   *
34023   * This method caches the state so `gl.colorMask()` is only
34024   * called when necessary.
34025   *
34026   * @param {boolean} colorMask - The color mask.
34027   */
34028  setColorMask(colorMask) {
34029    if (this.currentColorMask !== colorMask) {
34030      this.gl.colorMask(colorMask, colorMask, colorMask, colorMask);
34031      this.currentColorMask = colorMask;
34032    }
34033  }
34034  /**
34035   * Specifies whether the depth test is enabled or not.
34036   *
34037   * @param {boolean} depthTest - Whether the depth test is enabled or not.
34038   */
34039  setDepthTest(depthTest) {
34040    const { gl } = this;
34041    if (depthTest) {
34042      this.enable(gl.DEPTH_TEST);
34043    } else {
34044      this.disable(gl.DEPTH_TEST);
34045    }
34046  }
34047  /**
34048   * Configures the WebGL state to use a reversed depth buffer.
34049   *
34050   * @param {boolean} reversed - Whether the depth buffer is reversed or not.
34051   */
34052  setReversedDepth(reversed) {
34053    if (this.currentDepthReversed !== reversed) {
34054      const ext = this.backend.extensions.get("EXT_clip_control");
34055      if (reversed) {
34056        ext.clipControlEXT(ext.LOWER_LEFT_EXT, ext.ZERO_TO_ONE_EXT);
34057      } else {
34058        ext.clipControlEXT(ext.LOWER_LEFT_EXT, ext.NEGATIVE_ONE_TO_ONE_EXT);
34059      }
34060      this.currentDepthReversed = reversed;
34061    }
34062  }
34063  /**
34064   * Specifies whether depth values can be written when rendering
34065   * into a framebuffer or not.
34066   *
34067   * This method caches the state so `gl.depthMask()` is only
34068   * called when necessary.
34069   *
34070   * @param {boolean} depthMask - The depth mask.
34071   */
34072  setDepthMask(depthMask) {
34073    if (this.currentDepthMask !== depthMask) {
34074      this.gl.depthMask(depthMask);
34075      this.currentDepthMask = depthMask;
34076    }
34077  }
34078  /**
34079   * Specifies the depth compare function.
34080   *
34081   * This method caches the state so `gl.depthFunc()` is only
34082   * called when necessary.
34083   *
34084   * @param {number} depthFunc - The depth compare function.
34085   */
34086  setDepthFunc(depthFunc) {
34087    if (this.currentDepthReversed) depthFunc = ReversedDepthFuncs[depthFunc];
34088    if (this.currentDepthFunc !== depthFunc) {
34089      const { gl } = this;
34090      switch (depthFunc) {
34091        case NeverDepth:
34092          gl.depthFunc(gl.NEVER);
34093          break;
34094        case AlwaysDepth:
34095          gl.depthFunc(gl.ALWAYS);
34096          break;
34097        case LessDepth:
34098          gl.depthFunc(gl.LESS);
34099          break;
34100        case LessEqualDepth:
34101          gl.depthFunc(gl.LEQUAL);
34102          break;
34103        case EqualDepth:
34104          gl.depthFunc(gl.EQUAL);
34105          break;
34106        case GreaterEqualDepth:
34107          gl.depthFunc(gl.GEQUAL);
34108          break;
34109        case GreaterDepth:
34110          gl.depthFunc(gl.GREATER);
34111          break;
34112        case NotEqualDepth:
34113          gl.depthFunc(gl.NOTEQUAL);
34114          break;
34115        default:
34116          gl.depthFunc(gl.LEQUAL);
34117      }
34118      this.currentDepthFunc = depthFunc;
34119    }
34120  }
34121  /**
34122   * Specifies the scissor box.
34123   *
34124   * @param {number} x - The x-coordinate of the lower left corner of the viewport.
34125   * @param {number} y - The y-coordinate of the lower left corner of the viewport.
34126   * @param {number} width - The width of the viewport.
34127   * @param {number} height - The height of the viewport.
34128   *
34129   */
34130  scissor(x, y, width, height) {
34131    const scissor = this._tempVec4.set(x, y, width, height);
34132    if (this.currentScissor.equals(scissor) === false) {
34133      const { gl } = this;
34134      gl.scissor(scissor.x, scissor.y, scissor.z, scissor.w);
34135      this.currentScissor.copy(scissor);
34136    }
34137  }
34138  /**
34139   * Specifies the viewport.
34140   *
34141   * @param {number} x - The x-coordinate of the lower left corner of the viewport.
34142   * @param {number} y - The y-coordinate of the lower left corner of the viewport.
34143   * @param {number} width - The width of the viewport.
34144   * @param {number} height - The height of the viewport.
34145   *
34146   */
34147  viewport(x, y, width, height) {
34148    const viewport3 = this._tempVec4.set(x, y, width, height);
34149    if (this.currentViewport.equals(viewport3) === false) {
34150      const { gl } = this;
34151      gl.viewport(viewport3.x, viewport3.y, viewport3.z, viewport3.w);
34152      this.currentViewport.copy(viewport3);
34153    }
34154  }
34155  /**
34156   * Defines the scissor test.
34157   *
34158   * @param {boolean} boolean - Whether the scissor test should be enabled or not.
34159   */
34160  setScissorTest(boolean) {
34161    const gl = this.gl;
34162    if (boolean) {
34163      this.enable(gl.SCISSOR_TEST);
34164    } else {
34165      this.disable(gl.SCISSOR_TEST);
34166    }
34167  }
34168  /**
34169   * Specifies whether the stencil test is enabled or not.
34170   *
34171   * @param {boolean} stencilTest - Whether the stencil test is enabled or not.
34172   */
34173  setStencilTest(stencilTest) {
34174    const { gl } = this;
34175    if (stencilTest) {
34176      this.enable(gl.STENCIL_TEST);
34177    } else {
34178      this.disable(gl.STENCIL_TEST);
34179    }
34180  }
34181  /**
34182   * Specifies whether stencil values can be written when rendering
34183   * into a framebuffer or not.
34184   *
34185   * This method caches the state so `gl.stencilMask()` is only
34186   * called when necessary.
34187   *
34188   * @param {boolean} stencilMask - The stencil mask.
34189   */
34190  setStencilMask(stencilMask) {
34191    if (this.currentStencilMask !== stencilMask) {
34192      this.gl.stencilMask(stencilMask);
34193      this.currentStencilMask = stencilMask;
34194    }
34195  }
34196  /**
34197   * Specifies whether the stencil test functions.
34198   *
34199   * This method caches the state so `gl.stencilFunc()` is only
34200   * called when necessary.
34201   *
34202   * @param {number} stencilFunc - The stencil compare function.
34203   * @param {number} stencilRef - The reference value for the stencil test.
34204   * @param {number} stencilMask - A bit-wise mask that is used to AND the reference value and the stored stencil value when the test is done.
34205   */
34206  setStencilFunc(stencilFunc, stencilRef, stencilMask) {
34207    if (this.currentStencilFunc !== stencilFunc || this.currentStencilRef !== stencilRef || this.currentStencilFuncMask !== stencilMask) {
34208      this.gl.stencilFunc(stencilFunc, stencilRef, stencilMask);
34209      this.currentStencilFunc = stencilFunc;
34210      this.currentStencilRef = stencilRef;
34211      this.currentStencilFuncMask = stencilMask;
34212    }
34213  }
34214  /**
34215   * Specifies whether the stencil test operation.
34216   *
34217   * This method caches the state so `gl.stencilOp()` is only
34218   * called when necessary.
34219   *
34220   * @param {number} stencilFail - The function to use when the stencil test fails.
34221   * @param {number} stencilZFail - The function to use when the stencil test passes, but the depth test fail.
34222   * @param {number} stencilZPass - The function to use when both the stencil test and the depth test pass,
34223   * or when the stencil test passes and there is no depth buffer or depth testing is disabled.
34224   */
34225  setStencilOp(stencilFail, stencilZFail, stencilZPass) {
34226    if (this.currentStencilFail !== stencilFail || this.currentStencilZFail !== stencilZFail || this.currentStencilZPass !== stencilZPass) {
34227      this.gl.stencilOp(stencilFail, stencilZFail, stencilZPass);
34228      this.currentStencilFail = stencilFail;
34229      this.currentStencilZFail = stencilZFail;
34230      this.currentStencilZPass = stencilZPass;
34231    }
34232  }
34233  /**
34234   * Configures the WebGL state for the given material.
34235   *
34236   * @param {Material} material - The material to configure the state for.
34237   * @param {number} frontFaceCW - Whether the front faces are counter-clockwise or not.
34238   * @param {number} hardwareClippingPlanes - The number of hardware clipping planes.
34239   */
34240  setMaterial(material, frontFaceCW, hardwareClippingPlanes) {
34241    const { gl } = this;
34242    material.side === DoubleSide ? this.disable(gl.CULL_FACE) : this.enable(gl.CULL_FACE);
34243    let flipSided = material.side === BackSide;
34244    if (frontFaceCW) flipSided = !flipSided;
34245    this.setFlipSided(flipSided);
34246    material.blending === NormalBlending && material.transparent === false ? this.setBlending(NoBlending) : this.setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha);
34247    this.setDepthFunc(material.depthFunc);
34248    this.setDepthTest(material.depthTest);
34249    this.setDepthMask(material.depthWrite);
34250    this.setColorMask(material.colorWrite);
34251    const stencilWrite = material.stencilWrite;
34252    this.setStencilTest(stencilWrite);
34253    if (stencilWrite) {
34254      this.setStencilMask(material.stencilWriteMask);
34255      this.setStencilFunc(material.stencilFunc, material.stencilRef, material.stencilFuncMask);
34256      this.setStencilOp(material.stencilFail, material.stencilZFail, material.stencilZPass);
34257    }
34258    this.setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits);
34259    material.alphaToCoverage === true && this.backend.renderer.currentSamples > 0 ? this.enable(gl.SAMPLE_ALPHA_TO_COVERAGE) : this.disable(gl.SAMPLE_ALPHA_TO_COVERAGE);
34260    if (hardwareClippingPlanes > 0) {
34261      if (this.currentClippingPlanes !== hardwareClippingPlanes) {
34262        const CLIP_DISTANCE0_WEBGL = 12288;
34263        for (let i = 0; i < 8; i++) {
34264          if (i < hardwareClippingPlanes) {
34265            this.enable(CLIP_DISTANCE0_WEBGL + i);
34266          } else {
34267            this.disable(CLIP_DISTANCE0_WEBGL + i);
34268          }
34269        }
34270      }
34271    }
34272  }
34273  /**
34274   * Specifies the polygon offset.
34275   *
34276   * This method caches the state so `gl.polygonOffset()` is only
34277   * called when necessary.
34278   *
34279   * @param {boolean} polygonOffset - Whether polygon offset is enabled or not.
34280   * @param {number} factor - The scale factor for the variable depth offset for each polygon.
34281   * @param {number} units - The multiplier by which an implementation-specific value is multiplied with to create a constant depth offset.
34282   */
34283  setPolygonOffset(polygonOffset, factor, units) {
34284    const { gl } = this;
34285    if (polygonOffset) {
34286      this.enable(gl.POLYGON_OFFSET_FILL);
34287      if (this.currentPolygonOffsetFactor !== factor || this.currentPolygonOffsetUnits !== units) {
34288        gl.polygonOffset(factor, units);
34289        this.currentPolygonOffsetFactor = factor;
34290        this.currentPolygonOffsetUnits = units;
34291      }
34292    } else {
34293      this.disable(gl.POLYGON_OFFSET_FILL);
34294    }
34295  }
34296  /**
34297   * Defines the usage of the given WebGL program.
34298   *
34299   * This method caches the state so `gl.useProgram()` is only
34300   * called when necessary.
34301   *
34302   * @param {WebGLProgram} program - The WebGL program to use.
34303   * @return {boolean} Whether a program change has been executed or not.
34304   */
34305  useProgram(program) {
34306    if (this.currentProgram !== program) {
34307      this.gl.useProgram(program);
34308      this.currentProgram = program;
34309      return true;
34310    }
34311    return false;
34312  }
34313  /**
34314   * Sets the vertex state by binding the given VAO and element buffer.
34315   *
34316   * @param {WebGLVertexArrayObject} vao - The VAO.
34317   * @param {?WebGLBuffer} indexBuffer - The index buffer.
34318   * @return {boolean} Whether a vertex state has been changed or not.
34319   */
34320  setVertexState(vao, indexBuffer = null) {
34321    const gl = this.gl;
34322    if (this.currentVAO !== vao || this.currentIndex !== indexBuffer) {
34323      gl.bindVertexArray(vao);
34324      if (indexBuffer !== null) {
34325        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
34326      }
34327      this.currentVAO = vao;
34328      this.currentIndex = indexBuffer;
34329      return true;
34330    }
34331    return false;
34332  }
34333  /**
34334   * Resets the vertex array state by resetting the VAO and element buffer.
34335   */
34336  resetVertexState() {
34337    const gl = this.gl;
34338    gl.bindVertexArray(null);
34339    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
34340    this.currentVAO = null;
34341    this.currentIndex = null;
34342  }
34343  // framebuffer
34344  /**
34345   * Binds the given framebuffer.
34346   *
34347   * This method caches the state so `gl.bindFramebuffer()` is only
34348   * called when necessary.
34349   *
34350   * @param {number} target - The binding point (target).
34351   * @param {WebGLFramebuffer} framebuffer - The WebGL framebuffer to bind.
34352   * @return {boolean} Whether a bind has been executed or not.
34353   */
34354  bindFramebuffer(target, framebuffer) {
34355    const { gl, currentBoundFramebuffers } = this;
34356    if (currentBoundFramebuffers[target] !== framebuffer) {
34357      gl.bindFramebuffer(target, framebuffer);
34358      currentBoundFramebuffers[target] = framebuffer;
34359      if (target === gl.DRAW_FRAMEBUFFER) {
34360        currentBoundFramebuffers[gl.FRAMEBUFFER] = framebuffer;
34361      }
34362      if (target === gl.FRAMEBUFFER) {
34363        currentBoundFramebuffers[gl.DRAW_FRAMEBUFFER] = framebuffer;
34364      }
34365      return true;
34366    }
34367    return false;
34368  }
34369  /**
34370   * Defines draw buffers to which fragment colors are written into.
34371   * Configures the MRT setup of custom framebuffers.
34372   *
34373   * This method caches the state so `gl.drawBuffers()` is only
34374   * called when necessary.
34375   *
34376   * @param {RenderContext} renderContext - The render context.
34377   * @param {WebGLFramebuffer} framebuffer - The WebGL framebuffer.
34378   */
34379  drawBuffers(renderContext, framebuffer) {
34380    const { gl } = this;
34381    let drawBuffers = [];
34382    let needsUpdate = false;
34383    if (renderContext.textures !== null) {
34384      drawBuffers = this.currentDrawbuffers.get(framebuffer);
34385      if (drawBuffers === void 0) {
34386        drawBuffers = [];
34387        this.currentDrawbuffers.set(framebuffer, drawBuffers);
34388      }
34389      const textures = renderContext.textures;
34390      if (drawBuffers.length !== textures.length || drawBuffers[0] !== gl.COLOR_ATTACHMENT0) {
34391        for (let i = 0, il = textures.length; i < il; i++) {
34392          drawBuffers[i] = gl.COLOR_ATTACHMENT0 + i;
34393        }
34394        drawBuffers.length = textures.length;
34395        needsUpdate = true;
34396      }
34397    } else {
34398      if (drawBuffers[0] !== gl.BACK) {
34399        drawBuffers[0] = gl.BACK;
34400        needsUpdate = true;
34401      }
34402    }
34403    if (needsUpdate) {
34404      gl.drawBuffers(drawBuffers);
34405    }
34406  }
34407  // texture
34408  /**
34409   * Makes the given texture unit active.
34410   *
34411   * This method caches the state so `gl.activeTexture()` is only
34412   * called when necessary.
34413   *
34414   * @param {number} webglSlot - The texture unit to make active.
34415   */
34416  activeTexture(webglSlot) {
34417    const { gl, currentTextureSlot, maxTextures } = this;
34418    if (webglSlot === void 0) webglSlot = gl.TEXTURE0 + maxTextures - 1;
34419    if (currentTextureSlot !== webglSlot) {
34420      gl.activeTexture(webglSlot);
34421      this.currentTextureSlot = webglSlot;
34422    }
34423  }
34424  /**
34425   * Binds the given WebGL texture to a target.
34426   *
34427   * This method caches the state so `gl.bindTexture()` is only
34428   * called when necessary.
34429   *
34430   * @param {number} webglType - The binding point (target).
34431   * @param {WebGLTexture} webglTexture - The WebGL texture to bind.
34432   * @param {number} webglSlot - The texture.
34433   */
34434  bindTexture(webglType, webglTexture, webglSlot) {
34435    const { gl, currentTextureSlot, currentBoundTextures, maxTextures } = this;
34436    if (webglSlot === void 0) {
34437      if (currentTextureSlot === null) {
34438        webglSlot = gl.TEXTURE0 + maxTextures - 1;
34439      } else {
34440        webglSlot = currentTextureSlot;
34441      }
34442    }
34443    let boundTexture = currentBoundTextures[webglSlot];
34444    if (boundTexture === void 0) {
34445      boundTexture = { type: void 0, texture: void 0 };
34446      currentBoundTextures[webglSlot] = boundTexture;
34447    }
34448    if (boundTexture.type !== webglType || boundTexture.texture !== webglTexture) {
34449      if (currentTextureSlot !== webglSlot) {
34450        gl.activeTexture(webglSlot);
34451        this.currentTextureSlot = webglSlot;
34452      }
34453      gl.bindTexture(webglType, webglTexture);
34454      boundTexture.type = webglType;
34455      boundTexture.texture = webglTexture;
34456    }
34457  }
34458  /**
34459   * Binds a given WebGL buffer to a given binding point (target) at a given index.
34460   *
34461   * This method caches the state so `gl.bindBufferBase()` is only
34462   * called when necessary.
34463   *
34464   * @param {number} target - The target for the bind operation.
34465   * @param {number} index - The index of the target.
34466   * @param {WebGLBuffer} buffer - The WebGL buffer.
34467   * @return {boolean} Whether a bind has been executed or not.
34468   */
34469  bindBufferBase(target, index, buffer3) {
34470    const { gl } = this;
34471    const key = `${target}-${index}`;
34472    if (this.currentBoundBufferBases[key] !== buffer3) {
34473      gl.bindBufferBase(target, index, buffer3);
34474      this.currentBoundBufferBases[key] = buffer3;
34475      return true;
34476    }
34477    return false;
34478  }
34479  /**
34480   * Unbinds the current bound texture.
34481   *
34482   * This method caches the state so `gl.bindTexture()` is only
34483   * called when necessary.
34484   */
34485  unbindTexture() {
34486    const { gl, currentTextureSlot, currentBoundTextures } = this;
34487    const boundTexture = currentBoundTextures[currentTextureSlot];
34488    if (boundTexture !== void 0 && boundTexture.type !== void 0) {
34489      gl.bindTexture(boundTexture.type, null);
34490      boundTexture.type = void 0;
34491      boundTexture.texture = void 0;
34492    }
34493  }
34494  /**
34495   * Returns the value for the given parameter.
34496   *
34497   * @param {number} name - The paramter to get the value for.
34498   * @return {any} The value for the given parameter.
34499   */
34500  getParameter(name) {
34501    const { gl, parameters } = this;
34502    if (parameters[name] !== void 0) {
34503      return parameters[name];
34504    } else {
34505      return gl.getParameter(name);
34506    }
34507  }
34508  /**
34509   * Specifies a pixel storage mode.
34510   *
34511   * @param {number} name - The parameter to set.
34512   * @param {any} value - A value to set the parameter to.
34513   */
34514  pixelStorei(name, value) {
34515    const { gl, parameters } = this;
34516    if (parameters[name] !== value) {
34517      gl.pixelStorei(name, value);
34518      parameters[name] = value;
34519    }
34520  }
34521};
34522var WebGLUtils = class {
34523  /**
34524   * Constructs a new utility object.
34525   *
34526   * @param {WebGLBackend} backend - The WebGL 2 backend.
34527   */
34528  constructor(backend) {
34529    this.backend = backend;
34530    this.gl = this.backend.gl;
34531    this.extensions = backend.extensions;
34532  }
34533  /**
34534   * Converts the given three.js constant into a WebGL constant.
34535   * The method currently supports the conversion of texture formats
34536   * and types.
34537   *
34538   * @param {number} p - The three.js constant.
34539   * @param {string} [colorSpace=NoColorSpace] - The color space.
34540   * @return {?number} The corresponding WebGL constant.
34541   */
34542  convert(p, colorSpace = NoColorSpace) {
34543    const { gl, extensions } = this;
34544    let extension;
34545    const transfer = ColorManagement.getTransfer(colorSpace);
34546    if (p === UnsignedByteType) return gl.UNSIGNED_BYTE;
34547    if (p === UnsignedShort4444Type) return gl.UNSIGNED_SHORT_4_4_4_4;
34548    if (p === UnsignedShort5551Type) return gl.UNSIGNED_SHORT_5_5_5_1;
34549    if (p === UnsignedInt5999Type) return gl.UNSIGNED_INT_5_9_9_9_REV;
34550    if (p === UnsignedInt101111Type) return gl.UNSIGNED_INT_10F_11F_11F_REV;
34551    if (p === ByteType) return gl.BYTE;
34552    if (p === ShortType) return gl.SHORT;
34553    if (p === UnsignedShortType) return gl.UNSIGNED_SHORT;
34554    if (p === IntType) return gl.INT;
34555    if (p === UnsignedIntType) return gl.UNSIGNED_INT;
34556    if (p === FloatType) return gl.FLOAT;
34557    if (p === HalfFloatType) {
34558      return gl.HALF_FLOAT;
34559    }
34560    if (p === AlphaFormat) return gl.ALPHA;
34561    if (p === RGBFormat) return gl.RGB;
34562    if (p === RGBAFormat) return gl.RGBA;
34563    if (p === DepthFormat) return gl.DEPTH_COMPONENT;
34564    if (p === DepthStencilFormat) return gl.DEPTH_STENCIL;
34565    if (p === RedFormat) return gl.RED;
34566    if (p === RedIntegerFormat) return gl.RED_INTEGER;
34567    if (p === RGFormat) return gl.RG;
34568    if (p === RGIntegerFormat) return gl.RG_INTEGER;
34569    if (p === RGBAIntegerFormat) return gl.RGBA_INTEGER;
34570    if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
34571      if (transfer === SRGBTransfer) {
34572        extension = extensions.get("WEBGL_compressed_texture_s3tc_srgb");
34573        if (extension !== null) {
34574          if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT;
34575          if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
34576          if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
34577          if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
34578        } else {
34579          return null;
34580        }
34581      } else {
34582        extension = extensions.get("WEBGL_compressed_texture_s3tc");
34583        if (extension !== null) {
34584          if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
34585          if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
34586          if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
34587          if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
34588        } else {
34589          return null;
34590        }
34591      }
34592    }
34593    if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
34594      extension = extensions.get("WEBGL_compressed_texture_pvrtc");
34595      if (extension !== null) {
34596        if (p === RGB_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
34597        if (p === RGB_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
34598        if (p === RGBA_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
34599        if (p === RGBA_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
34600      } else {
34601        return null;
34602      }
34603    }
34604    if (p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format || p === R11_EAC_Format || p === SIGNED_R11_EAC_Format || p === RG11_EAC_Format || p === SIGNED_RG11_EAC_Format) {
34605      extension = extensions.get("WEBGL_compressed_texture_etc");
34606      if (extension !== null) {
34607        if (p === RGB_ETC1_Format || p === RGB_ETC2_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2;
34608        if (p === RGBA_ETC2_EAC_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC;
34609        if (p === R11_EAC_Format) return extension.COMPRESSED_R11_EAC;
34610        if (p === SIGNED_R11_EAC_Format) return extension.COMPRESSED_SIGNED_R11_EAC;
34611        if (p === RG11_EAC_Format) return extension.COMPRESSED_RG11_EAC;
34612        if (p === SIGNED_RG11_EAC_Format) return extension.COMPRESSED_SIGNED_RG11_EAC;
34613      } else {
34614        return null;
34615      }
34616    }
34617    if (p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format) {
34618      extension = extensions.get("WEBGL_compressed_texture_astc");
34619      if (extension !== null) {
34620        if (p === RGBA_ASTC_4x4_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR;
34621        if (p === RGBA_ASTC_5x4_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR;
34622        if (p === RGBA_ASTC_5x5_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR;
34623        if (p === RGBA_ASTC_6x5_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR;
34624        if (p === RGBA_ASTC_6x6_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR;
34625        if (p === RGBA_ASTC_8x5_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR;
34626        if (p === RGBA_ASTC_8x6_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR;
34627        if (p === RGBA_ASTC_8x8_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR;
34628        if (p === RGBA_ASTC_10x5_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR;
34629        if (p === RGBA_ASTC_10x6_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR;
34630        if (p === RGBA_ASTC_10x8_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR;
34631        if (p === RGBA_ASTC_10x10_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR;
34632        if (p === RGBA_ASTC_12x10_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR;
34633        if (p === RGBA_ASTC_12x12_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR;
34634      } else {
34635        return null;
34636      }
34637    }
34638    if (p === RGBA_BPTC_Format) {
34639      extension = extensions.get("EXT_texture_compression_bptc");
34640      if (extension !== null) {
34641        if (p === RGBA_BPTC_Format) return transfer === SRGBTransfer ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT;
34642      } else {
34643        return null;
34644      }
34645    }
34646    if (p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format) {
34647      extension = extensions.get("EXT_texture_compression_rgtc");
34648      if (extension !== null) {
34649        if (p === RED_RGTC1_Format) return extension.COMPRESSED_RED_RGTC1_EXT;
34650        if (p === SIGNED_RED_RGTC1_Format) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT;
34651        if (p === RED_GREEN_RGTC2_Format) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT;
34652        if (p === SIGNED_RED_GREEN_RGTC2_Format) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
34653      } else {
34654        return null;
34655      }
34656    }
34657    if (p === UnsignedInt248Type) {
34658      return gl.UNSIGNED_INT_24_8;
34659    }
34660    return gl[p] !== void 0 ? gl[p] : null;
34661  }
34662  /**
34663   * This method can be used to synchronize the CPU with the GPU by waiting until
34664   * ongoing GPU commands have been completed.
34665   *
34666   * @private
34667   * @return {Promise} A promise that resolves when all ongoing GPU commands have been completed.
34668   */
34669  _clientWaitAsync() {
34670    const { gl } = this;
34671    const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
34672    gl.flush();
34673    return new Promise((resolve, reject) => {
34674      function test() {
34675        const res = gl.clientWaitSync(sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0);
34676        if (res === gl.WAIT_FAILED) {
34677          gl.deleteSync(sync);
34678          reject();
34679          return;
34680        }
34681        if (res === gl.TIMEOUT_EXPIRED) {
34682          requestAnimationFrame(test);
34683          return;
34684        }
34685        gl.deleteSync(sync);
34686        resolve();
34687      }
34688      test();
34689    });
34690  }
34691};
34692var initialized = false;
34693var wrappingToGL;
34694var filterToGL;
34695var compareToGL;
34696var WebGLTextureUtils = class {
34697  /**
34698   * Constructs a new utility object.
34699   *
34700   * @param {WebGLBackend} backend - The WebGL 2 backend.
34701   */
34702  constructor(backend) {
34703    this.backend = backend;
34704    this.gl = backend.gl;
34705    this.extensions = backend.extensions;
34706    this.defaultTextures = {};
34707    this._srcFramebuffer = null;
34708    this._dstFramebuffer = null;
34709    if (initialized === false) {
34710      this._init();
34711      initialized = true;
34712    }
34713  }
34714  /**
34715   * Inits the state of the utility.
34716   *
34717   * @private
34718   */
34719  _init() {
34720    const gl = this.gl;
34721    wrappingToGL = {
34722      [RepeatWrapping]: gl.REPEAT,
34723      [ClampToEdgeWrapping]: gl.CLAMP_TO_EDGE,
34724      [MirroredRepeatWrapping]: gl.MIRRORED_REPEAT
34725    };
34726    filterToGL = {
34727      [NearestFilter]: gl.NEAREST,
34728      [NearestMipmapNearestFilter]: gl.NEAREST_MIPMAP_NEAREST,
34729      [NearestMipmapLinearFilter]: gl.NEAREST_MIPMAP_LINEAR,
34730      [LinearFilter]: gl.LINEAR,
34731      [LinearMipmapNearestFilter]: gl.LINEAR_MIPMAP_NEAREST,
34732      [LinearMipmapLinearFilter]: gl.LINEAR_MIPMAP_LINEAR
34733    };
34734    compareToGL = {
34735      [NeverCompare]: gl.NEVER,
34736      [AlwaysCompare]: gl.ALWAYS,
34737      [LessCompare]: gl.LESS,
34738      [LessEqualCompare]: gl.LEQUAL,
34739      [EqualCompare]: gl.EQUAL,
34740      [GreaterEqualCompare]: gl.GEQUAL,
34741      [GreaterCompare]: gl.GREATER,
34742      [NotEqualCompare]: gl.NOTEQUAL
34743    };
34744  }
34745  /**
34746   * Returns the native texture type for the given texture.
34747   *
34748   * @param {Texture} texture - The texture.
34749   * @return {GLenum} The native texture type.
34750   */
34751  getGLTextureType(texture3) {
34752    const { gl } = this;
34753    let glTextureType;
34754    if (texture3.isCubeTexture === true) {
34755      glTextureType = gl.TEXTURE_CUBE_MAP;
34756    } else if (texture3.isArrayTexture === true || texture3.isDataArrayTexture === true || texture3.isCompressedArrayTexture === true) {
34757      glTextureType = gl.TEXTURE_2D_ARRAY;
34758    } else if (texture3.isData3DTexture === true) {
34759      glTextureType = gl.TEXTURE_3D;
34760    } else {
34761      glTextureType = gl.TEXTURE_2D;
34762    }
34763    return glTextureType;
34764  }
34765  /**
34766   * Returns the native texture type for the given texture.
34767   *
34768   * @param {?string} internalFormatName - The internal format name. When `null`, the internal format is derived from the subsequent parameters.
34769   * @param {GLenum} glFormat - The WebGL format.
34770   * @param {GLenum} glType - The WebGL type.
34771   * @param {string} colorSpace - The texture's color space.
34772   * @param {boolean} [forceLinearTransfer=false] - Whether to force a linear transfer or not.
34773   * @return {GLenum} The internal format.
34774   */
34775  getInternalFormat(internalFormatName, glFormat, glType, normalized, colorSpace, forceLinearTransfer = false) {
34776    const { gl, extensions } = this;
34777    if (internalFormatName !== null) {
34778      if (gl[internalFormatName] !== void 0) return gl[internalFormatName];
34779      warn("WebGLBackend: Attempt to use non-existing WebGL internal format '" + internalFormatName + "'");
34780    }
34781    let extTextureNorm16 = null;
34782    if (normalized) {
34783      extTextureNorm16 = extensions.get("EXT_texture_norm16");
34784      if (!extTextureNorm16) {
34785        warn("WebGLRenderer: Unable to use normalized textures without EXT_texture_norm16 extension");
34786      }
34787    }
34788    let internalFormat = glFormat;
34789    if (glFormat === gl.RED) {
34790      if (glType === gl.FLOAT) internalFormat = gl.R32F;
34791      if (glType === gl.HALF_FLOAT) internalFormat = gl.R16F;
34792      if (glType === gl.UNSIGNED_BYTE) internalFormat = gl.R8;
34793      if (glType === gl.BYTE) internalFormat = gl.R8_SNORM;
34794      if (glType === gl.UNSIGNED_SHORT && extTextureNorm16) internalFormat = extTextureNorm16.R16_EXT;
34795      if (glType === gl.SHORT && extTextureNorm16) internalFormat = extTextureNorm16.R16_SNORM_EXT;
34796    }
34797    if (glFormat === gl.RED_INTEGER) {
34798      if (glType === gl.UNSIGNED_BYTE) internalFormat = gl.R8UI;
34799      if (glType === gl.UNSIGNED_SHORT) internalFormat = gl.R16UI;
34800      if (glType === gl.UNSIGNED_INT) internalFormat = gl.R32UI;
34801      if (glType === gl.BYTE) internalFormat = gl.R8I;
34802      if (glType === gl.SHORT) internalFormat = gl.R16I;
34803      if (glType === gl.INT) internalFormat = gl.R32I;
34804    }
34805    if (glFormat === gl.RG) {
34806      if (glType === gl.FLOAT) internalFormat = gl.RG32F;
34807      if (glType === gl.HALF_FLOAT) internalFormat = gl.RG16F;
34808      if (glType === gl.UNSIGNED_BYTE) internalFormat = gl.RG8;
34809      if (glType === gl.BYTE) internalFormat = gl.RG8_SNORM;
34810      if (glType === gl.UNSIGNED_SHORT && extTextureNorm16) internalFormat = extTextureNorm16.RG16_EXT;
34811      if (glType === gl.SHORT && extTextureNorm16) internalFormat = extTextureNorm16.RG16_SNORM_EXT;
34812    }
34813    if (glFormat === gl.RG_INTEGER) {
34814      if (glType === gl.UNSIGNED_BYTE) internalFormat = gl.RG8UI;
34815      if (glType === gl.UNSIGNED_SHORT) internalFormat = gl.RG16UI;
34816      if (glType === gl.UNSIGNED_INT) internalFormat = gl.RG32UI;
34817      if (glType === gl.BYTE) internalFormat = gl.RG8I;
34818      if (glType === gl.SHORT) internalFormat = gl.RG16I;
34819      if (glType === gl.INT) internalFormat = gl.RG32I;
34820    }
34821    if (glFormat === gl.RGB) {
34822      const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer(colorSpace);
34823      if (glType === gl.FLOAT) internalFormat = gl.RGB32F;
34824      if (glType === gl.HALF_FLOAT) internalFormat = gl.RGB16F;
34825      if (glType === gl.UNSIGNED_BYTE) internalFormat = transfer === SRGBTransfer ? gl.SRGB8 : gl.RGB8;
34826      if (glType === gl.BYTE) internalFormat = gl.RGB8_SNORM;
34827      if (glType === gl.UNSIGNED_SHORT && extTextureNorm16) internalFormat = extTextureNorm16.RGB16_EXT;
34828      if (glType === gl.SHORT && extTextureNorm16) internalFormat = extTextureNorm16.RGB16_SNORM_EXT;
34829      if (glType === gl.UNSIGNED_SHORT_5_6_5) internalFormat = gl.RGB565;
34830      if (glType === gl.UNSIGNED_SHORT_5_5_5_1) internalFormat = gl.RGB5_A1;
34831      if (glType === gl.UNSIGNED_SHORT_4_4_4_4) internalFormat = gl.RGB4;
34832      if (glType === gl.UNSIGNED_INT_5_9_9_9_REV) internalFormat = gl.RGB9_E5;
34833      if (glType === gl.UNSIGNED_INT_10F_11F_11F_REV) internalFormat = gl.R11F_G11F_B10F;
34834    }
34835    if (glFormat === gl.RGB_INTEGER) {
34836      if (glType === gl.UNSIGNED_BYTE) internalFormat = gl.RGB8UI;
34837      if (glType === gl.UNSIGNED_SHORT) internalFormat = gl.RGB16UI;
34838      if (glType === gl.UNSIGNED_INT) internalFormat = gl.RGB32UI;
34839      if (glType === gl.BYTE) internalFormat = gl.RGB8I;
34840      if (glType === gl.SHORT) internalFormat = gl.RGB16I;
34841      if (glType === gl.INT) internalFormat = gl.RGB32I;
34842    }
34843    if (glFormat === gl.RGBA) {
34844      const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer(colorSpace);
34845      if (glType === gl.FLOAT) internalFormat = gl.RGBA32F;
34846      if (glType === gl.HALF_FLOAT) internalFormat = gl.RGBA16F;
34847      if (glType === gl.UNSIGNED_BYTE) internalFormat = transfer === SRGBTransfer ? gl.SRGB8_ALPHA8 : gl.RGBA8;
34848      if (glType === gl.BYTE) internalFormat = gl.RGBA8_SNORM;
34849      if (glType === gl.UNSIGNED_SHORT && extTextureNorm16) internalFormat = extTextureNorm16.RGBA16_EXT;
34850      if (glType === gl.SHORT && extTextureNorm16) internalFormat = extTextureNorm16.RGBA16_SNORM_EXT;
34851      if (glType === gl.UNSIGNED_SHORT_4_4_4_4) internalFormat = gl.RGBA4;
34852      if (glType === gl.UNSIGNED_SHORT_5_5_5_1) internalFormat = gl.RGB5_A1;
34853    }
34854    if (glFormat === gl.RGBA_INTEGER) {
34855      if (glType === gl.UNSIGNED_BYTE) internalFormat = gl.RGBA8UI;
34856      if (glType === gl.UNSIGNED_SHORT) internalFormat = gl.RGBA16UI;
34857      if (glType === gl.UNSIGNED_INT) internalFormat = gl.RGBA32UI;
34858      if (glType === gl.BYTE) internalFormat = gl.RGBA8I;
34859      if (glType === gl.SHORT) internalFormat = gl.RGBA16I;
34860      if (glType === gl.INT) internalFormat = gl.RGBA32I;
34861    }
34862    if (glFormat === gl.DEPTH_COMPONENT) {
34863      if (glType === gl.UNSIGNED_SHORT) internalFormat = gl.DEPTH_COMPONENT16;
34864      if (glType === gl.UNSIGNED_INT) internalFormat = gl.DEPTH_COMPONENT24;
34865      if (glType === gl.FLOAT) internalFormat = gl.DEPTH_COMPONENT32F;
34866    }
34867    if (glFormat === gl.DEPTH_STENCIL) {
34868      if (glType === gl.UNSIGNED_INT_24_8) internalFormat = gl.DEPTH24_STENCIL8;
34869    }
34870    if (internalFormat === gl.R16F || internalFormat === gl.R32F || internalFormat === gl.RG16F || internalFormat === gl.RG32F || internalFormat === gl.RGBA16F || internalFormat === gl.RGBA32F) {
34871      extensions.get("EXT_color_buffer_float");
34872    }
34873    return internalFormat;
34874  }
34875  /**
34876   * Sets the texture parameters for the given texture.
34877   *
34878   * @param {GLenum} textureType - The texture type.
34879   * @param {Texture} texture - The texture.
34880   */
34881  setTextureParameters(textureType, texture3) {
34882    const { gl, extensions, backend } = this;
34883    const { state } = this.backend;
34884    const workingPrimaries = ColorManagement.getPrimaries(ColorManagement.workingColorSpace);
34885    const texturePrimaries = texture3.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries(texture3.colorSpace);
34886    const unpackConversion = texture3.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? gl.NONE : gl.BROWSER_DEFAULT_WEBGL;
34887    state.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture3.flipY);
34888    state.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture3.premultiplyAlpha);
34889    state.pixelStorei(gl.UNPACK_ALIGNMENT, texture3.unpackAlignment);
34890    state.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion);
34891    gl.texParameteri(textureType, gl.TEXTURE_WRAP_S, wrappingToGL[texture3.wrapS]);
34892    gl.texParameteri(textureType, gl.TEXTURE_WRAP_T, wrappingToGL[texture3.wrapT]);
34893    if (textureType === gl.TEXTURE_3D || textureType === gl.TEXTURE_2D_ARRAY) {
34894      if (!texture3.isArrayTexture) {
34895        gl.texParameteri(textureType, gl.TEXTURE_WRAP_R, wrappingToGL[texture3.wrapR]);
34896      }
34897    }
34898    gl.texParameteri(textureType, gl.TEXTURE_MAG_FILTER, filterToGL[texture3.magFilter]);
34899    const hasMipmaps = texture3.mipmaps !== void 0 && texture3.mipmaps.length > 0;
34900    const minFilter = texture3.minFilter === LinearFilter && hasMipmaps ? LinearMipmapLinearFilter : texture3.minFilter;
34901    gl.texParameteri(textureType, gl.TEXTURE_MIN_FILTER, filterToGL[minFilter]);
34902    if (texture3.compareFunction) {
34903      gl.texParameteri(textureType, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
34904      gl.texParameteri(textureType, gl.TEXTURE_COMPARE_FUNC, compareToGL[texture3.compareFunction]);
34905    }
34906    if (extensions.has("EXT_texture_filter_anisotropic") === true) {
34907      if (texture3.magFilter === NearestFilter) return;
34908      if (texture3.minFilter !== NearestMipmapLinearFilter && texture3.minFilter !== LinearMipmapLinearFilter) return;
34909      if (texture3.type === FloatType && extensions.has("OES_texture_float_linear") === false) return;
34910      if (texture3.anisotropy > 1) {
34911        const extension = extensions.get("EXT_texture_filter_anisotropic");
34912        gl.texParameterf(textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture3.anisotropy, backend.capabilities.getMaxAnisotropy()));
34913      }
34914    }
34915  }
34916  /**
34917   * Creates a default texture for the given texture that can be used
34918   * as a placeholder until the actual texture is ready for usage.
34919   *
34920   * @param {Texture} texture - The texture to create a default texture for.
34921   */
34922  createDefaultTexture(texture3) {
34923    const { gl, backend, defaultTextures } = this;
34924    const glTextureType = this.getGLTextureType(texture3);
34925    let textureGPU = defaultTextures[glTextureType];
34926    if (textureGPU === void 0) {
34927      textureGPU = gl.createTexture();
34928      backend.state.bindTexture(glTextureType, textureGPU);
34929      gl.texParameteri(glTextureType, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
34930      gl.texParameteri(glTextureType, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
34931      defaultTextures[glTextureType] = textureGPU;
34932    }
34933    backend.set(texture3, {
34934      textureGPU,
34935      glTextureType
34936    });
34937  }
34938  /**
34939   * Defines a texture on the GPU for the given texture object.
34940   *
34941   * @param {Texture} texture - The texture.
34942   * @param {Object} [options={}] - Optional configuration parameter.
34943   * @return {undefined}
34944   */
34945  createTexture(texture3, options) {
34946    const { gl, backend } = this;
34947    const { levels, width, height, depth: depth3 } = options;
34948    const glFormat = backend.utils.convert(texture3.format, texture3.colorSpace);
34949    const glType = backend.utils.convert(texture3.type);
34950    const glInternalFormat = this.getInternalFormat(texture3.internalFormat, glFormat, glType, texture3.normalized, texture3.colorSpace, texture3.isVideoTexture);
34951    const textureGPU = gl.createTexture();
34952    const glTextureType = this.getGLTextureType(texture3);
34953    backend.state.bindTexture(glTextureType, textureGPU);
34954    this.setTextureParameters(glTextureType, texture3);
34955    if (texture3.isArrayTexture || texture3.isDataArrayTexture || texture3.isCompressedArrayTexture) {
34956      gl.texStorage3D(gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, width, height, depth3);
34957    } else if (texture3.isData3DTexture) {
34958      gl.texStorage3D(gl.TEXTURE_3D, levels, glInternalFormat, width, height, depth3);
34959    } else if (!texture3.isVideoTexture) {
34960      gl.texStorage2D(glTextureType, levels, glInternalFormat, width, height);
34961    }
34962    backend.set(texture3, {
34963      textureGPU,
34964      glTextureType,
34965      glFormat,
34966      glType,
34967      glInternalFormat
34968    });
34969  }
34970  /**
34971   * Uploads texture buffer data to the GPU memory.
34972   *
34973   * @param {WebGLBuffer} buffer - The buffer data.
34974   * @param {Texture} texture - The texture,
34975   */
34976  copyBufferToTexture(buffer3, texture3) {
34977    const { gl, backend } = this;
34978    const { state } = backend;
34979    const { textureGPU, glTextureType, glFormat, glType } = backend.get(texture3);
34980    const { width, height } = texture3.source.data;
34981    gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer3);
34982    backend.state.bindTexture(glTextureType, textureGPU);
34983    state.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
34984    state.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
34985    gl.texSubImage2D(glTextureType, 0, 0, 0, width, height, glFormat, glType, 0);
34986    gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
34987    backend.state.unbindTexture();
34988  }
34989  /**
34990   * Uploads the updated texture data to the GPU.
34991   *
34992   * @param {Texture} texture - The texture.
34993   * @param {Object} [options={}] - Optional configuration parameter.
34994   */
34995  updateTexture(texture3, options) {
34996    const { gl } = this;
34997    const { width, height } = options;
34998    const { textureGPU, glTextureType, glFormat, glType, glInternalFormat } = this.backend.get(texture3);
34999    if (texture3.isRenderTargetTexture || textureGPU === void 0)
35000      return;
35001    this.backend.state.bindTexture(glTextureType, textureGPU);
35002    this.setTextureParameters(glTextureType, texture3);
35003    if (texture3.isCompressedTexture) {
35004      const mipmaps = texture3.mipmaps;
35005      const image = options.image;
35006      for (let i = 0; i < mipmaps.length; i++) {
35007        const mipmap = mipmaps[i];
35008        if (texture3.isCompressedArrayTexture) {
35009          if (texture3.format !== gl.RGBA) {
35010            if (glFormat !== null) {
35011              gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data);
35012            } else {
35013              warn("WebGLBackend: Attempt to load unsupported compressed texture format in .uploadTexture()");
35014            }
35015          } else {
35016            gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data);
35017          }
35018        } else {
35019          if (glFormat !== null) {
35020            gl.compressedTexSubImage2D(gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data);
35021          } else {
35022            warn("WebGLBackend: Unsupported compressed texture format");
35023          }
35024        }
35025      }
35026    } else if (texture3.isCubeTexture) {
35027      const images = options.images;
35028      const mipmaps = texture3.mipmaps;
35029      for (let i = 0; i < 6; i++) {
35030        const image = getImage(images[i]);
35031        gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, width, height, glFormat, glType, image);
35032        for (let j = 0; j < mipmaps.length; j++) {
35033          const mipmap = mipmaps[j];
35034          const image2 = getImage(mipmap.images[i]);
35035          gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, image2.width, image2.height, glFormat, glType, image2);
35036        }
35037      }
35038    } else if (texture3.isDataArrayTexture || texture3.isArrayTexture) {
35039      const image = options.image;
35040      if (texture3.layerUpdates.size > 0) {
35041        const layerByteLength = getByteLength(image.width, image.height, texture3.format, texture3.type);
35042        for (const layerIndex of texture3.layerUpdates) {
35043          const layerData = image.data.subarray(
35044            layerIndex * layerByteLength / image.data.BYTES_PER_ELEMENT,
35045            (layerIndex + 1) * layerByteLength / image.data.BYTES_PER_ELEMENT
35046          );
35047          gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, image.width, image.height, 1, glFormat, glType, layerData);
35048        }
35049        texture3.clearLayerUpdates();
35050      } else {
35051        gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data);
35052      }
35053    } else if (texture3.isData3DTexture) {
35054      const image = options.image;
35055      gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data);
35056    } else if (texture3.isVideoTexture) {
35057      texture3.update();
35058      gl.texImage2D(glTextureType, 0, glInternalFormat, glFormat, glType, options.image);
35059    } else if (texture3.isHTMLTexture) {
35060      if (typeof gl.texElementImage2D === "function") {
35061        gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, options.image);
35062      }
35063    } else {
35064      const mipmaps = texture3.mipmaps;
35065      if (mipmaps.length > 0) {
35066        for (let i = 0, il = mipmaps.length; i < il; i++) {
35067          const mipmap = mipmaps[i];
35068          const image = getImage(mipmap);
35069          gl.texSubImage2D(glTextureType, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, image);
35070        }
35071      } else {
35072        const image = getImage(options.image);
35073        gl.texSubImage2D(glTextureType, 0, 0, 0, width, height, glFormat, glType, image);
35074      }
35075    }
35076  }
35077  /**
35078   * Generates mipmaps for the given texture.
35079   *
35080   * @param {Texture} texture - The texture.
35081   */
35082  generateMipmaps(texture3) {
35083    const { gl, backend } = this;
35084    const { textureGPU, glTextureType } = backend.get(texture3);
35085    backend.state.bindTexture(glTextureType, textureGPU);
35086    gl.generateMipmap(glTextureType);
35087  }
35088  /**
35089   * Deallocates the render buffers of the given render target.
35090   *
35091   * @param {RenderTarget} renderTarget - The render target.
35092   */
35093  deallocateRenderBuffers(renderTarget) {
35094    const { gl, backend } = this;
35095    if (renderTarget) {
35096      const renderContextData = backend.get(renderTarget);
35097      renderContextData.renderBufferStorageSetup = void 0;
35098      if (renderContextData.framebuffers) {
35099        for (const cacheKey in renderContextData.framebuffers) {
35100          gl.deleteFramebuffer(renderContextData.framebuffers[cacheKey]);
35101        }
35102        delete renderContextData.framebuffers;
35103      }
35104      if (renderContextData.depthRenderbuffer) {
35105        gl.deleteRenderbuffer(renderContextData.depthRenderbuffer);
35106        delete renderContextData.depthRenderbuffer;
35107      }
35108      if (renderContextData.stencilRenderbuffer) {
35109        gl.deleteRenderbuffer(renderContextData.stencilRenderbuffer);
35110        delete renderContextData.stencilRenderbuffer;
35111      }
35112      if (renderContextData.msaaFrameBuffer) {
35113        gl.deleteFramebuffer(renderContextData.msaaFrameBuffer);
35114        delete renderContextData.msaaFrameBuffer;
35115      }
35116      if (renderContextData.msaaRenderbuffers) {
35117        for (let i = 0; i < renderContextData.msaaRenderbuffers.length; i++) {
35118          gl.deleteRenderbuffer(renderContextData.msaaRenderbuffers[i]);
35119        }
35120        delete renderContextData.msaaRenderbuffers;
35121      }
35122    }
35123  }
35124  /**
35125   * Destroys the GPU data for the given texture object.
35126   *
35127   * @param {Texture} texture - The texture.
35128   * @param {boolean} [isDefaultTexture=false] - Whether the texture uses a default GPU texture or not.
35129   */
35130  destroyTexture(texture3, isDefaultTexture = false) {
35131    const { gl, backend } = this;
35132    const { textureGPU, renderTarget } = backend.get(texture3);
35133    this.deallocateRenderBuffers(renderTarget);
35134    if (isDefaultTexture === false) {
35135      gl.deleteTexture(textureGPU);
35136    }
35137    backend.delete(texture3);
35138  }
35139  /**
35140   * Copies data of the given source texture to the given destination texture.
35141   *
35142   * @param {Texture} srcTexture - The source texture.
35143   * @param {Texture} dstTexture - The destination texture.
35144   * @param {?(Box3|Box2)} [srcRegion=null] - The region of the source texture to copy.
35145   * @param {?(Vector2|Vector3)} [dstPosition=null] - The destination position of the copy.
35146   * @param {number} [srcLevel=0] - The source mip level to copy from.
35147   * @param {number} [dstLevel=0] - The destination mip level to copy to.
35148   */
35149  copyTextureToTexture(srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0) {
35150    const { gl, backend } = this;
35151    const { state } = this.backend;
35152    const { textureGPU: dstTextureGPU, glTextureType, glType, glFormat } = backend.get(dstTexture);
35153    state.bindTexture(glTextureType, dstTextureGPU);
35154    let width, height, depth3, minX, minY, minZ;
35155    let dstX, dstY, dstZ;
35156    const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[dstLevel] : srcTexture.image;
35157    if (srcRegion !== null) {
35158      width = srcRegion.max.x - srcRegion.min.x;
35159      height = srcRegion.max.y - srcRegion.min.y;
35160      depth3 = srcRegion.isBox3 ? srcRegion.max.z - srcRegion.min.z : 1;
35161      minX = srcRegion.min.x;
35162      minY = srcRegion.min.y;
35163      minZ = srcRegion.isBox3 ? srcRegion.min.z : 0;
35164    } else {
35165      const levelScale = Math.pow(2, -srcLevel);
35166      width = Math.floor(image.width * levelScale);
35167      height = Math.floor(image.height * levelScale);
35168      if (srcTexture.isDataArrayTexture || srcTexture.isArrayTexture) {
35169        depth3 = image.depth;
35170      } else if (srcTexture.isData3DTexture) {
35171        depth3 = Math.floor(image.depth * levelScale);
35172      } else {
35173        depth3 = 1;
35174      }
35175      minX = 0;
35176      minY = 0;
35177      minZ = 0;
35178    }
35179    if (dstPosition !== null) {
35180      dstX = dstPosition.x;
35181      dstY = dstPosition.y;
35182      dstZ = dstPosition.z;
35183    } else {
35184      dstX = 0;
35185      dstY = 0;
35186      dstZ = 0;
35187    }
35188    state.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY);
35189    state.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha);
35190    state.pixelStorei(gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment);
35191    const currentUnpackRowLen = state.getParameter(gl.UNPACK_ROW_LENGTH);
35192    const currentUnpackImageHeight = state.getParameter(gl.UNPACK_IMAGE_HEIGHT);
35193    const currentUnpackSkipPixels = state.getParameter(gl.UNPACK_SKIP_PIXELS);
35194    const currentUnpackSkipRows = state.getParameter(gl.UNPACK_SKIP_ROWS);
35195    const currentUnpackSkipImages = state.getParameter(gl.UNPACK_SKIP_IMAGES);
35196    state.pixelStorei(gl.UNPACK_ROW_LENGTH, image.width);
35197    state.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, image.height);
35198    state.pixelStorei(gl.UNPACK_SKIP_PIXELS, minX);
35199    state.pixelStorei(gl.UNPACK_SKIP_ROWS, minY);
35200    state.pixelStorei(gl.UNPACK_SKIP_IMAGES, minZ);
35201    const isSrc3D = srcTexture.isDataArrayTexture || srcTexture.isData3DTexture || dstTexture.isArrayTexture;
35202    const isDst3D = dstTexture.isDataArrayTexture || dstTexture.isData3DTexture || dstTexture.isArrayTexture;
35203    if (srcTexture.isDepthTexture) {
35204      const srcTextureData = backend.get(srcTexture);
35205      const dstTextureData = backend.get(dstTexture);
35206      const srcRenderContextData = backend.get(srcTextureData.renderTarget);
35207      const dstRenderContextData = backend.get(dstTextureData.renderTarget);
35208      const srcFramebuffer = srcRenderContextData.framebuffers[srcTextureData.cacheKey];
35209      const dstFramebuffer = dstRenderContextData.framebuffers[dstTextureData.cacheKey];
35210      state.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFramebuffer);
35211      state.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFramebuffer);
35212      for (let i = 0; i < depth3; i++) {
35213        if (isSrc3D) {
35214          gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, srcTextureData.textureGPU, srcLevel, minZ + i);
35215          gl.framebufferTextureLayer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, dstTextureGPU, dstLevel, dstZ + i);
35216        }
35217        gl.blitFramebuffer(minX, minY, width, height, dstX, dstY, width, height, gl.DEPTH_BUFFER_BIT, gl.NEAREST);
35218      }
35219      state.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
35220      state.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
35221    } else if (srcLevel !== 0 || srcTexture.isRenderTargetTexture || backend.has(srcTexture)) {
35222      const srcTextureData = backend.get(srcTexture);
35223      if (this._srcFramebuffer === null) this._srcFramebuffer = gl.createFramebuffer();
35224      if (this._dstFramebuffer === null) this._dstFramebuffer = gl.createFramebuffer();
35225      state.bindFramebuffer(gl.READ_FRAMEBUFFER, this._srcFramebuffer);
35226      state.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this._dstFramebuffer);
35227      for (let i = 0; i < depth3; i++) {
35228        if (isSrc3D) {
35229          gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, srcTextureData.textureGPU, srcLevel, minZ + i);
35230        } else {
35231          gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, srcTextureData.textureGPU, srcLevel);
35232        }
35233        if (isDst3D) {
35234          gl.framebufferTextureLayer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, dstTextureGPU, dstLevel, dstZ + i);
35235        } else {
35236          gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, dstTextureGPU, dstLevel);
35237        }
35238        if (srcLevel !== 0) {
35239          gl.blitFramebuffer(minX, minY, width, height, dstX, dstY, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);
35240        } else if (isDst3D) {
35241          gl.copyTexSubImage3D(glTextureType, dstLevel, dstX, dstY, dstZ + i, minX, minY, width, height);
35242        } else {
35243          gl.copyTexSubImage2D(glTextureType, dstLevel, dstX, dstY, minX, minY, width, height);
35244        }
35245      }
35246      state.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
35247      state.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
35248    } else {
35249      if (isDst3D) {
35250        if (srcTexture.isDataTexture || srcTexture.isData3DTexture) {
35251          gl.texSubImage3D(glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth3, glFormat, glType, image.data);
35252        } else if (dstTexture.isCompressedArrayTexture) {
35253          gl.compressedTexSubImage3D(glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth3, glFormat, image.data);
35254        } else {
35255          gl.texSubImage3D(glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth3, glFormat, glType, image);
35256        }
35257      } else {
35258        if (srcTexture.isDataTexture) {
35259          gl.texSubImage2D(gl.TEXTURE_2D, dstLevel, dstX, dstY, width, height, glFormat, glType, image.data);
35260        } else if (srcTexture.isCompressedTexture) {
35261          gl.compressedTexSubImage2D(gl.TEXTURE_2D, dstLevel, dstX, dstY, image.width, image.height, glFormat, image.data);
35262        } else {
35263          gl.texSubImage2D(gl.TEXTURE_2D, dstLevel, dstX, dstY, width, height, glFormat, glType, image);
35264        }
35265      }
35266    }
35267    state.pixelStorei(gl.UNPACK_ROW_LENGTH, currentUnpackRowLen);
35268    state.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight);
35269    state.pixelStorei(gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels);
35270    state.pixelStorei(gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows);
35271    state.pixelStorei(gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages);
35272    if (dstLevel === 0 && dstTexture.generateMipmaps) {
35273      gl.generateMipmap(glTextureType);
35274    }
35275    state.unbindTexture();
35276  }
35277  /**
35278   * Copies the current bound framebuffer to the given texture.
35279   *
35280   * @param {Texture} texture - The destination texture.
35281   * @param {RenderContext} renderContext - The render context.
35282   * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy.
35283   */
35284  copyFramebufferToTexture(texture3, renderContext, rectangle) {
35285    const { gl } = this;
35286    const { state } = this.backend;
35287    const { textureGPU } = this.backend.get(texture3);
35288    const { x, y, z: width, w: height } = rectangle;
35289    const requireDrawFrameBuffer = texture3.isDepthTexture === true || renderContext.renderTarget && renderContext.renderTarget.samples > 0;
35290    const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.getDrawingBufferSize().y;
35291    if (requireDrawFrameBuffer) {
35292      const partial = x !== 0 || y !== 0;
35293      let mask;
35294      let attachment;
35295      if (texture3.isDepthTexture === true) {
35296        mask = gl.DEPTH_BUFFER_BIT;
35297        attachment = gl.DEPTH_ATTACHMENT;
35298        if (renderContext.stencil) {
35299          mask |= gl.STENCIL_BUFFER_BIT;
35300        }
35301      } else {
35302        mask = gl.COLOR_BUFFER_BIT;
35303        attachment = gl.COLOR_ATTACHMENT0;
35304      }
35305      if (partial) {
35306        const renderTargetContextData = this.backend.get(renderContext.renderTarget);
35307        const fb = renderTargetContextData.framebuffers[renderContext.getCacheKey()];
35308        const msaaFrameBuffer = renderTargetContextData.msaaFrameBuffer;
35309        state.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
35310        state.bindFramebuffer(gl.READ_FRAMEBUFFER, msaaFrameBuffer);
35311        const flippedY = srcHeight - y - height;
35312        gl.blitFramebuffer(x, flippedY, x + width, flippedY + height, x, flippedY, x + width, flippedY + height, mask, gl.NEAREST);
35313        state.bindFramebuffer(gl.READ_FRAMEBUFFER, fb);
35314        state.bindTexture(gl.TEXTURE_2D, textureGPU);
35315        gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, x, flippedY, width, height);
35316        state.unbindTexture();
35317      } else {
35318        const fb = gl.createFramebuffer();
35319        state.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
35320        gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureGPU, 0);
35321        gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, mask, gl.NEAREST);
35322        gl.deleteFramebuffer(fb);
35323      }
35324    } else {
35325      state.bindTexture(gl.TEXTURE_2D, textureGPU);
35326      gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, x, srcHeight - height - y, width, height);
35327      state.unbindTexture();
35328    }
35329    if (texture3.generateMipmaps) this.generateMipmaps(texture3);
35330    this.backend._setFramebuffer(renderContext);
35331  }
35332  /**
35333   * SetupS storage for internal depth/stencil buffers and bind to correct framebuffer.
35334   *
35335   * @param {WebGLRenderbuffer} renderbuffer - The render buffer.
35336   * @param {RenderContext} renderContext - The render context.
35337   * @param {number} samples - The MSAA sample count.
35338   * @param {boolean} [useMultisampledRTT=false] - Whether to use WEBGL_multisampled_render_to_texture or not.
35339   */
35340  setupRenderBufferStorage(renderbuffer, renderContext, samples, useMultisampledRTT = false) {
35341    const { gl } = this;
35342    const renderTarget = renderContext.renderTarget;
35343    const { depthTexture, depthBuffer, stencilBuffer, width, height } = renderTarget;
35344    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
35345    if (depthBuffer && !stencilBuffer) {
35346      let glInternalFormat = gl.DEPTH_COMPONENT24;
35347      if (useMultisampledRTT === true) {
35348        const multisampledRTTExt = this.extensions.get("WEBGL_multisampled_render_to_texture");
35349        multisampledRTTExt.renderbufferStorageMultisampleEXT(gl.RENDERBUFFER, renderTarget.samples, glInternalFormat, width, height);
35350      } else if (samples > 0) {
35351        if (depthTexture && depthTexture.isDepthTexture) {
35352          if (depthTexture.type === gl.FLOAT) {
35353            glInternalFormat = gl.DEPTH_COMPONENT32F;
35354          }
35355        }
35356        gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, glInternalFormat, width, height);
35357      } else {
35358        gl.renderbufferStorage(gl.RENDERBUFFER, glInternalFormat, width, height);
35359      }
35360      gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
35361    } else if (depthBuffer && stencilBuffer) {
35362      if (samples > 0) {
35363        gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.DEPTH24_STENCIL8, width, height);
35364      } else {
35365        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
35366      }
35367      gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
35368    }
35369    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
35370  }
35371  /**
35372   * Returns texture data as a typed array.
35373   *
35374   * @async
35375   * @param {Texture} texture - The texture to copy.
35376   * @param {number} x - The x coordinate of the copy origin.
35377   * @param {number} y - The y coordinate of the copy origin.
35378   * @param {number} width - The width of the copy.
35379   * @param {number} height - The height of the copy.
35380   * @param {number} faceIndex - The face index.
35381   * @return {Promise<TypedArray>} A Promise that resolves with a typed array when the copy operation has finished.
35382   */
35383  async copyTextureToBuffer(texture3, x, y, width, height, faceIndex) {
35384    const { backend, gl } = this;
35385    const { textureGPU, glFormat, glType } = this.backend.get(texture3);
35386    const fb = gl.createFramebuffer();
35387    backend.state.bindFramebuffer(gl.READ_FRAMEBUFFER, fb);
35388    const target = texture3.isCubeTexture ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex : gl.TEXTURE_2D;
35389    gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, target, textureGPU, 0);
35390    const typedArrayType = this._getTypedArrayType(glType);
35391    const bytesPerTexel = this._getBytesPerTexel(glType, glFormat);
35392    const elementCount = width * height;
35393    const byteLength = elementCount * bytesPerTexel;
35394    const buffer3 = gl.createBuffer();
35395    gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buffer3);
35396    gl.bufferData(gl.PIXEL_PACK_BUFFER, byteLength, gl.STREAM_READ);
35397    gl.readPixels(x, y, width, height, glFormat, glType, 0);
35398    gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
35399    await backend.utils._clientWaitAsync();
35400    const dstBuffer = new typedArrayType(byteLength / typedArrayType.BYTES_PER_ELEMENT);
35401    gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buffer3);
35402    gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, dstBuffer);
35403    gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
35404    backend.state.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
35405    gl.deleteFramebuffer(fb);
35406    return dstBuffer;
35407  }
35408  /**
35409   * Returns the corresponding typed array type for the given WebGL data type.
35410   *
35411   * @private
35412   * @param {GLenum} glType - The WebGL data type.
35413   * @return {TypedArray.constructor} The typed array type.
35414   */
35415  _getTypedArrayType(glType) {
35416    const { gl } = this;
35417    if (glType === gl.UNSIGNED_BYTE) return Uint8Array;
35418    if (glType === gl.UNSIGNED_SHORT_4_4_4_4) return Uint16Array;
35419    if (glType === gl.UNSIGNED_SHORT_5_5_5_1) return Uint16Array;
35420    if (glType === gl.UNSIGNED_SHORT_5_6_5) return Uint16Array;
35421    if (glType === gl.UNSIGNED_SHORT) return Uint16Array;
35422    if (glType === gl.UNSIGNED_INT) return Uint32Array;
35423    if (glType === gl.HALF_FLOAT) return Uint16Array;
35424    if (glType === gl.FLOAT) return Float32Array;
35425    throw new Error(`Unsupported WebGL type: ${glType}`);
35426  }
35427  /**
35428   * Returns the bytes-per-texel value for the given WebGL data type and texture format.
35429   *
35430   * @private
35431   * @param {GLenum} glType - The WebGL data type.
35432   * @param {GLenum} glFormat - The WebGL texture format.
35433   * @return {number} The bytes-per-texel.
35434   */
35435  _getBytesPerTexel(glType, glFormat) {
35436    const { gl } = this;
35437    let bytesPerComponent = 0;
35438    if (glType === gl.UNSIGNED_BYTE) bytesPerComponent = 1;
35439    if (glType === gl.UNSIGNED_SHORT_4_4_4_4 || glType === gl.UNSIGNED_SHORT_5_5_5_1 || glType === gl.UNSIGNED_SHORT_5_6_5 || glType === gl.UNSIGNED_SHORT || glType === gl.HALF_FLOAT) bytesPerComponent = 2;
35440    if (glType === gl.UNSIGNED_INT || glType === gl.FLOAT) bytesPerComponent = 4;
35441    if (glFormat === gl.RGBA) return bytesPerComponent * 4;
35442    if (glFormat === gl.RGB) return bytesPerComponent * 3;
35443    if (glFormat === gl.ALPHA) return bytesPerComponent;
35444  }
35445  /**
35446   * Frees the internal resources.
35447   */
35448  dispose() {
35449    const { gl } = this;
35450    if (this._srcFramebuffer !== null) gl.deleteFramebuffer(this._srcFramebuffer);
35451    if (this._dstFramebuffer !== null) gl.deleteFramebuffer(this._dstFramebuffer);
35452  }
35453};
35454function getImage(source) {
35455  if (source.isDataTexture) {
35456    return source.image.data;
35457  } else if (typeof HTMLImageElement !== "undefined" && source instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && source instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && source instanceof ImageBitmap || typeof OffscreenCanvas !== "undefined" && source instanceof OffscreenCanvas) {
35458    return source;
35459  }
35460  return source.data;
35461}
35462var WebGLExtensions = class {
35463  /**
35464   * Constructs a new utility object.
35465   *
35466   * @param {WebGLBackend} backend - The WebGL 2 backend.
35467   */
35468  constructor(backend) {
35469    this.backend = backend;
35470    this.gl = this.backend.gl;
35471    this.availableExtensions = this.gl.getSupportedExtensions();
35472    this.extensions = {};
35473  }
35474  /**
35475   * Returns the extension object for the given extension name.
35476   *
35477   * @param {string} name - The extension name.
35478   * @return {Object} The extension object.
35479   */
35480  get(name) {
35481    let extension = this.extensions[name];
35482    if (extension === void 0) {
35483      extension = this.gl.getExtension(name);
35484      this.extensions[name] = extension;
35485    }
35486    return extension;
35487  }
35488  /**
35489   * Returns `true` if the requested extension is available.
35490   *
35491   * @param {string} name - The extension name.
35492   * @return {boolean} Whether the given extension is available or not.
35493   */
35494  has(name) {
35495    return this.availableExtensions.includes(name);
35496  }
35497};
35498var WebGLCapabilities = class {
35499  /**
35500   * Constructs a new utility object.
35501   *
35502   * @param {WebGLBackend} backend - The WebGL 2 backend.
35503   */
35504  constructor(backend) {
35505    this.backend = backend;
35506    this.maxAnisotropy = null;
35507    this.maxUniformBlockSize = null;
35508  }
35509  /**
35510   * Returns the maximum anisotropy texture filtering value. This value
35511   * depends on the device and is reported by the `EXT_texture_filter_anisotropic`
35512   * WebGL extension.
35513   *
35514   * @return {number} The maximum anisotropy texture filtering value.
35515   */
35516  getMaxAnisotropy() {
35517    if (this.maxAnisotropy !== null) return this.maxAnisotropy;
35518    const gl = this.backend.gl;
35519    const extensions = this.backend.extensions;
35520    if (extensions.has("EXT_texture_filter_anisotropic") === true) {
35521      const extension = extensions.get("EXT_texture_filter_anisotropic");
35522      this.maxAnisotropy = gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
35523    } else {
35524      this.maxAnisotropy = 0;
35525    }
35526    return this.maxAnisotropy;
35527  }
35528  /**
35529   * Returns the maximum number of bytes available for uniform buffers.
35530   *
35531   * @return {number} The maximum number of bytes available for uniform buffers.
35532   */
35533  getUniformBufferLimit() {
35534    if (this.maxUniformBlockSize !== null) return this.maxUniformBlockSize;
35535    const gl = this.backend.gl;
35536    this.maxUniformBlockSize = gl.getParameter(gl.MAX_UNIFORM_BLOCK_SIZE);
35537    return this.maxUniformBlockSize;
35538  }
35539};
35540var GLFeatureName = {
35541  "WEBGL_multi_draw": "WEBGL_multi_draw",
35542  "WEBGL_compressed_texture_astc": "texture-compression-astc",
35543  "WEBGL_compressed_texture_etc": "texture-compression-etc2",
35544  "WEBGL_compressed_texture_etc1": "texture-compression-etc1",
35545  "WEBGL_compressed_texture_pvrtc": "texture-compression-pvrtc",
35546  "WEBGL_compressed_texture_s3tc": "texture-compression-s3tc",
35547  "EXT_texture_compression_bptc": "texture-compression-bc",
35548  "EXT_disjoint_timer_query_webgl2": "timestamp-query",
35549  "OVR_multiview2": "OVR_multiview2"
35550};
35551var WebGLBufferRenderer = class {
35552  constructor(backend) {
35553    this.gl = backend.gl;
35554    this.extensions = backend.extensions;
35555    this.info = backend.renderer.info;
35556    this.mode = null;
35557    this.index = 0;
35558    this.type = null;
35559    this.object = null;
35560  }
35561  render(start, count) {
35562    const { gl, mode, object, type, info, index } = this;
35563    if (index !== 0) {
35564      gl.drawElements(mode, count, type, start);
35565    } else {
35566      gl.drawArrays(mode, start, count);
35567    }
35568    info.update(object, count, 1);
35569  }
35570  renderInstances(start, count, primcount) {
35571    const { gl, mode, type, index, object, info } = this;
35572    if (primcount === 0) return;
35573    if (index !== 0) {
35574      gl.drawElementsInstanced(mode, count, type, start, primcount);
35575    } else {
35576      gl.drawArraysInstanced(mode, start, count, primcount);
35577    }
35578    info.update(object, count, primcount);
35579  }
35580  renderMultiDraw(starts, counts, drawCount) {
35581    const { extensions, mode, object, info } = this;
35582    if (drawCount === 0) return;
35583    const extension = extensions.get("WEBGL_multi_draw");
35584    if (extension === null) {
35585      for (let i = 0; i < drawCount; i++) {
35586        this.render(starts[i], counts[i]);
35587      }
35588    } else {
35589      if (this.index !== 0) {
35590        extension.multiDrawElementsWEBGL(mode, counts, 0, this.type, starts, 0, drawCount);
35591      } else {
35592        extension.multiDrawArraysWEBGL(mode, starts, 0, counts, 0, drawCount);
35593      }
35594      let elementCount = 0;
35595      for (let i = 0; i < drawCount; i++) {
35596        elementCount += counts[i];
35597      }
35598      info.update(object, elementCount, 1);
35599    }
35600  }
35601  //
35602};
35603var TimestampQueryPool = class {
35604  /**
35605   * Creates a new timestamp query pool.
35606   *
35607   * @param {number} [maxQueries=256] - Maximum number of queries this pool can hold.
35608   */
35609  constructor(maxQueries = 256) {
35610    this.trackTimestamp = true;
35611    this.maxQueries = maxQueries;
35612    this.currentQueryIndex = 0;
35613    this.queryOffsets = /* @__PURE__ */ new Map();
35614    this.isDisposed = false;
35615    this.lastValue = 0;
35616    this.frames = [];
35617    this.pendingResolve = false;
35618    this.timestamps = /* @__PURE__ */ new Map();
35619  }
35620  /**
35621   * Returns all timestamp frames.
35622   *
35623   * @return {Array<number>} The timestamp frames.
35624   */
35625  getTimestampFrames() {
35626    return this.frames;
35627  }
35628  /**
35629   * Returns the timestamp for a given render context.
35630   *
35631   * @param {string} uid - A unique identifier for the render context.
35632   * @return {?number} The timestamp, or undefined if not available.
35633   */
35634  getTimestamp(uid) {
35635    let timestamp = this.timestamps.get(uid);
35636    if (timestamp === void 0) {
35637      warn(`TimestampQueryPool: No timestamp available for uid ${uid}.`);
35638      timestamp = 0;
35639    }
35640    return timestamp;
35641  }
35642  /**
35643   * Returns whether a timestamp is available for a given render context.
35644   *
35645   * @param {string} uid - A unique identifier for the render context.
35646   * @return {boolean} True if a timestamp is available, false otherwise.
35647   */
35648  hasTimestamp(uid) {
35649    return this.timestamps.has(uid);
35650  }
35651  /**
35652   * Allocate queries for a specific uid.
35653   *
35654   * @abstract
35655   * @param {string} uid - A unique identifier for the render context.
35656   * @param {number} frameId - The current frame identifier.
35657   * @returns {?number}
35658   */
35659  allocateQueriesForContext() {
35660  }
35661  /**
35662   * Resolve all timestamps and return data (or process them).
35663   *
35664   * @abstract
35665   * @async
35666   * @returns {Promise<number>|number} The resolved timestamp value.
35667   */
35668  async resolveQueriesAsync() {
35669  }
35670  /**
35671   * Dispose of the query pool.
35672   *
35673   * @abstract
35674   */
35675  dispose() {
35676  }
35677};
35678var WebGLTimestampQueryPool = class extends TimestampQueryPool {
35679  /**
35680   * Creates a new WebGL timestamp query pool.
35681   *
35682   * @param {WebGLRenderingContext|WebGL2RenderingContext} gl - The WebGL context.
35683   * @param {string} type - The type identifier for this query pool.
35684   * @param {number} [maxQueries=2048] - Maximum number of queries this pool can hold.
35685   */
35686  constructor(gl, type, maxQueries = 2048) {
35687    super(maxQueries);
35688    this.gl = gl;
35689    this.type = type;
35690    this.ext = gl.getExtension("EXT_disjoint_timer_query_webgl2") || gl.getExtension("EXT_disjoint_timer_query");
35691    if (!this.ext) {
35692      warn("EXT_disjoint_timer_query not supported; timestamps will be disabled.");
35693      this.trackTimestamp = false;
35694      return;
35695    }
35696    this.queries = [];
35697    for (let i = 0; i < this.maxQueries; i++) {
35698      this.queries.push(gl.createQuery());
35699    }
35700    this.activeQuery = null;
35701    this.queryStates = /* @__PURE__ */ new Map();
35702  }
35703  /**
35704   * Allocates a pair of queries for a given render context.
35705   *
35706   * @param {string} uid - A unique identifier for the render context.
35707   * @returns {?number} The base offset for the allocated queries, or null if allocation failed.
35708   */
35709  allocateQueriesForContext(uid) {
35710    if (!this.trackTimestamp) return null;
35711    if (this.currentQueryIndex + 2 > this.maxQueries) {
35712      warnOnce(`WebGLTimestampQueryPool [${this.type}]: Maximum number of queries exceeded, when using trackTimestamp it is necessary to resolves the queries via renderer.resolveTimestampsAsync( THREE.TimestampQuery.${this.type.toUpperCase()} ).`);
35713      return null;
35714    }
35715    const baseOffset = this.currentQueryIndex;
35716    this.currentQueryIndex += 2;
35717    this.queryStates.set(baseOffset, "inactive");
35718    this.queryOffsets.set(uid, baseOffset);
35719    return baseOffset;
35720  }
35721  /**
35722   * Begins a timestamp query for the specified render context.
35723   *
35724   * @param {string} uid - A unique identifier for the render context.
35725   */
35726  beginQuery(uid) {
35727    if (!this.trackTimestamp || this.isDisposed) {
35728      return;
35729    }
35730    const baseOffset = this.queryOffsets.get(uid);
35731    if (baseOffset == null) {
35732      return;
35733    }
35734    if (this.activeQuery !== null) {
35735      return;
35736    }
35737    const query = this.queries[baseOffset];
35738    if (!query) {
35739      return;
35740    }
35741    try {
35742      if (this.queryStates.get(baseOffset) === "inactive") {
35743        this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT, query);
35744        this.activeQuery = baseOffset;
35745        this.queryStates.set(baseOffset, "started");
35746      }
35747    } catch (e) {
35748      error("Error in beginQuery:", e);
35749      this.activeQuery = null;
35750      this.queryStates.set(baseOffset, "inactive");
35751    }
35752  }
35753  /**
35754   * Ends the active timestamp query for the specified render context.
35755   *
35756   * @param {string} uid - A unique identifier for the render context.
35757   */
35758  endQuery(uid) {
35759    if (!this.trackTimestamp || this.isDisposed) {
35760      return;
35761    }
35762    const baseOffset = this.queryOffsets.get(uid);
35763    if (baseOffset == null) {
35764      return;
35765    }
35766    if (this.activeQuery !== baseOffset) {
35767      return;
35768    }
35769    try {
35770      this.gl.endQuery(this.ext.TIME_ELAPSED_EXT);
35771      this.queryStates.set(baseOffset, "ended");
35772      this.activeQuery = null;
35773    } catch (e) {
35774      error("Error in endQuery:", e);
35775      this.queryStates.set(baseOffset, "inactive");
35776      this.activeQuery = null;
35777    }
35778  }
35779  /**
35780   * Asynchronously resolves all completed queries and returns the total duration.
35781   *
35782   * @async
35783   * @returns {Promise<number>} The total duration in milliseconds, or the last valid value if resolution fails.
35784   */
35785  async resolveQueriesAsync() {
35786    if (!this.trackTimestamp || this.pendingResolve) {
35787      return this.lastValue;
35788    }
35789    this.pendingResolve = true;
35790    try {
35791      const resolvePromises = /* @__PURE__ */ new Map();
35792      for (const [uid, baseOffset] of this.queryOffsets) {
35793        const state = this.queryStates.get(baseOffset);
35794        if (state === "ended") {
35795          const query = this.queries[baseOffset];
35796          resolvePromises.set(uid, this.resolveQuery(query));
35797        }
35798      }
35799      if (resolvePromises.size === 0) {
35800        return this.lastValue;
35801      }
35802      const framesDuration = {};
35803      const frames = [];
35804      for (const [uid, promise] of resolvePromises) {
35805        const match = uid.match(/^(.*):f(\d+)$/);
35806        const frame = parseInt(match[2]);
35807        if (frames.includes(frame) === false) {
35808          frames.push(frame);
35809        }
35810        if (framesDuration[frame] === void 0) framesDuration[frame] = 0;
35811        const duration = await promise;
35812        this.timestamps.set(uid, duration);
35813        framesDuration[frame] += duration;
35814      }
35815      const totalDuration = framesDuration[frames[frames.length - 1]];
35816      this.lastValue = totalDuration;
35817      this.frames = frames;
35818      this.currentQueryIndex = 0;
35819      this.queryOffsets.clear();
35820      this.queryStates.clear();
35821      this.activeQuery = null;
35822      return totalDuration;
35823    } catch (e) {
35824      error("Error resolving queries:", e);
35825      return this.lastValue;
35826    } finally {
35827      this.pendingResolve = false;
35828    }
35829  }
35830  /**
35831   * Resolves a single query, checking for completion and disjoint operation.
35832   *
35833   * @async
35834   * @param {WebGLQuery} query - The query object to resolve.
35835   * @returns {Promise<number>} The elapsed time in milliseconds.
35836   */
35837  async resolveQuery(query) {
35838    return new Promise((resolve) => {
35839      if (this.isDisposed) {
35840        resolve(this.lastValue);
35841        return;
35842      }
35843      let timeoutId;
35844      let isResolved = false;
35845      const cleanup = () => {
35846        if (timeoutId) {
35847          clearTimeout(timeoutId);
35848          timeoutId = null;
35849        }
35850      };
35851      const finalizeResolution = (value) => {
35852        if (!isResolved) {
35853          isResolved = true;
35854          cleanup();
35855          resolve(value);
35856        }
35857      };
35858      const checkQuery = () => {
35859        if (this.isDisposed) {
35860          finalizeResolution(this.lastValue);
35861          return;
35862        }
35863        try {
35864          const disjoint = this.gl.getParameter(this.ext.GPU_DISJOINT_EXT);
35865          if (disjoint) {
35866            finalizeResolution(this.lastValue);
35867            return;
35868          }
35869          const available = this.gl.getQueryParameter(query, this.gl.QUERY_RESULT_AVAILABLE);
35870          if (!available) {
35871            timeoutId = setTimeout(checkQuery, 1);
35872            return;
35873          }
35874          const elapsed = this.gl.getQueryParameter(query, this.gl.QUERY_RESULT);
35875          resolve(Number(elapsed) / 1e6);
35876        } catch (e) {
35877          error("Error checking query:", e);
35878          resolve(this.lastValue);
35879        }
35880      };
35881      checkQuery();
35882    });
35883  }
35884  /**
35885   * Releases all resources held by this query pool.
35886   * This includes deleting all query objects and clearing internal state.
35887   */
35888  dispose() {
35889    if (this.isDisposed) {
35890      return;
35891    }
35892    this.isDisposed = true;
35893    if (!this.trackTimestamp) return;
35894    for (const query of this.queries) {
35895      this.gl.deleteQuery(query);
35896    }
35897    this.queries = [];
35898    this.queryStates.clear();
35899    this.queryOffsets.clear();
35900    this.lastValue = 0;
35901    this.activeQuery = null;
35902  }
35903};
35904var WebGLBackend = class extends Backend {
35905  /**
35906   * WebGLBackend options.
35907   *
35908   * @typedef {Object} WebGLBackend~Options
35909   * @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
35910   * @property {boolean} [reversedDepthBuffer=false] - Whether reversed depth buffer is enabled or not.
35911   * @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
35912   * @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
35913   * @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
35914   * @property {boolean} [antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
35915   * @property {number} [samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default.
35916   * @property {boolean} [forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not.
35917   * @property {WebGL2RenderingContext} [context=undefined] - A WebGL 2 rendering context.
35918   */
35919  /**
35920   * Constructs a new WebGPU backend.
35921   *
35922   * @param {WebGLBackend~Options} [parameters] - The configuration parameter.
35923   */
35924  constructor(parameters = {}) {
35925    super(parameters);
35926    this.isWebGLBackend = true;
35927    this.attributeUtils = null;
35928    this.extensions = null;
35929    this.capabilities = null;
35930    this.textureUtils = null;
35931    this.bufferRenderer = null;
35932    this.gl = null;
35933    this.state = null;
35934    this.utils = null;
35935    this.vaoCache = {};
35936    this.transformFeedbackCache = {};
35937    this.discard = false;
35938    this.disjoint = null;
35939    this.parallel = null;
35940    this._currentContext = null;
35941    this._knownBindings = /* @__PURE__ */ new WeakSet();
35942    this._supportsInvalidateFramebuffer = typeof navigator === "undefined" ? false : /OculusBrowser/g.test(navigator.userAgent);
35943    this._xrFramebuffer = null;
35944  }
35945  /**
35946   * Initializes the backend so it is ready for usage.
35947   *
35948   * @param {Renderer} renderer - The renderer.
35949   */
35950  init(renderer) {
35951    super.init(renderer);
35952    const parameters = this.parameters;
35953    const contextAttributes = {
35954      antialias: renderer.currentSamples > 0,
35955      alpha: true,
35956      // always true for performance reasons
35957      depth: renderer.depth,
35958      stencil: renderer.stencil
35959    };
35960    const glContext = parameters.context !== void 0 ? parameters.context : renderer.domElement.getContext("webgl2", contextAttributes);
35961    function onContextLost(event) {
35962      event.preventDefault();
35963      const contextLossInfo = {
35964        api: "WebGL",
35965        message: event.statusMessage || "Unknown reason",
35966        reason: null,
35967        originalEvent: event
35968      };
35969      renderer.onDeviceLost(contextLossInfo);
35970    }
35971    this._onContextLost = onContextLost;
35972    renderer.domElement.addEventListener("webglcontextlost", onContextLost, false);
35973    this.gl = glContext;
35974    this.extensions = new WebGLExtensions(this);
35975    this.capabilities = new WebGLCapabilities(this);
35976    this.attributeUtils = new WebGLAttributeUtils(this);
35977    this.textureUtils = new WebGLTextureUtils(this);
35978    this.bufferRenderer = new WebGLBufferRenderer(this);
35979    this.state = new WebGLState(this);
35980    this.utils = new WebGLUtils(this);
35981    this.extensions.get("EXT_color_buffer_float");
35982    this.extensions.get("WEBGL_clip_cull_distance");
35983    this.extensions.get("OES_texture_float_linear");
35984    this.extensions.get("EXT_color_buffer_half_float");
35985    this.extensions.get("WEBGL_multisampled_render_to_texture");
35986    this.extensions.get("WEBGL_render_shared_exponent");
35987    this.extensions.get("WEBGL_multi_draw");
35988    this.extensions.get("OVR_multiview2");
35989    this.extensions.get("EXT_clip_control");
35990    this.disjoint = this.extensions.get("EXT_disjoint_timer_query_webgl2");
35991    this.parallel = this.extensions.get("KHR_parallel_shader_compile");
35992    this.drawBuffersIndexedExt = this.extensions.get("OES_draw_buffers_indexed");
35993    if (parameters.reversedDepthBuffer) {
35994      if (this.extensions.has("EXT_clip_control")) {
35995        renderer.reversedDepthBuffer = true;
35996      } else {
35997        warn("WebGPURenderer: Unable to use reversed depth buffer due to missing EXT_clip_control extension. Fallback to default depth buffer.");
35998        renderer.reversedDepthBuffer = false;
35999      }
36000    }
36001    if (renderer.reversedDepthBuffer) {
36002      this.state.setReversedDepth(true);
36003    }
36004  }
36005  /**
36006   * The coordinate system of the backend.
36007   *
36008   * @type {number}
36009   * @readonly
36010   */
36011  get coordinateSystem() {
36012    return WebGLCoordinateSystem;
36013  }
36014  /**
36015   * This method performs a readback operation by moving buffer data from
36016   * a storage buffer attribute from the GPU to the CPU. ReadbackBuffer can
36017   * be used to retain and reuse handles to the intermediate buffers and prevent
36018   * new allocation.
36019   *
36020   * @async
36021   * @param {BufferAttribute} attribute - The storage buffer attribute to read frm.
36022   * @param {ReadbackBuffer|ArrayBuffer} target - The storage buffer attribute.
36023   * @param {number} offset - The storage buffer attribute.
36024   * @param {number} count - The offset from which to start reading the
36025   * @return {Promise<ArrayBuffer|ReadbackBuffer>} A promise that resolves with the buffer data when the data are ready.
36026   */
36027  async getArrayBufferAsync(attribute3, target = null, offset3 = 0, count = -1) {
36028    return await this.attributeUtils.getArrayBufferAsync(attribute3, target, offset3, count);
36029  }
36030  /**
36031   * Ensures the backend is XR compatible.
36032   *
36033   * @async
36034   * @return {Promise} A Promise that resolve when the renderer is XR compatible.
36035   */
36036  async makeXRCompatible() {
36037    const attributes = this.gl.getContextAttributes();
36038    if (attributes.xrCompatible !== true) {
36039      await this.gl.makeXRCompatible();
36040    }
36041  }
36042  /**
36043   * Sets the XR rendering destination.
36044   *
36045   * @param {WebGLFramebuffer} xrFramebuffer - The XR framebuffer.
36046   */
36047  setXRTarget(xrFramebuffer) {
36048    this._xrFramebuffer = xrFramebuffer;
36049  }
36050  /**
36051   * Configures the given XR render target with external textures.
36052   *
36053   * This method is only relevant when using the WebXR Layers API.
36054   *
36055   * @param {XRRenderTarget} renderTarget - The XR render target.
36056   * @param {WebGLTexture} colorTexture - A native color texture.
36057   * @param {?WebGLTexture} [depthTexture=null] - A native depth texture.
36058   */
36059  setXRRenderTargetTextures(renderTarget, colorTexture, depthTexture = null) {
36060    const gl = this.gl;
36061    this.set(renderTarget.texture, { textureGPU: colorTexture, glInternalFormat: gl.RGBA8 });
36062    if (depthTexture !== null) {
36063      const glInternalFormat = renderTarget.stencilBuffer ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
36064      this.set(renderTarget.depthTexture, { textureGPU: depthTexture, glInternalFormat });
36065      if (this.extensions.has("WEBGL_multisampled_render_to_texture") === true && renderTarget._autoAllocateDepthBuffer === true && renderTarget.multiview === false) {
36066        warn("WebGLBackend: Render-to-texture extension was disabled because an external texture was provided");
36067      }
36068      renderTarget._autoAllocateDepthBuffer = false;
36069    }
36070  }
36071  /**
36072   * Inits a time stamp query for the given render context.
36073   *
36074   * @param {string} type - The type of the timestamp query.
36075   * @param {string} uid - A unique identifier for the timestamp query.
36076   */
36077  initTimestampQuery(type, uid) {
36078    if (!this.disjoint || !this.trackTimestamp) return;
36079    if (!this.timestampQueryPool[type]) {
36080      this.timestampQueryPool[type] = new WebGLTimestampQueryPool(this.gl, type, 2048);
36081    }
36082    const timestampQueryPool = this.timestampQueryPool[type];
36083    const baseOffset = timestampQueryPool.allocateQueriesForContext(uid);
36084    if (baseOffset !== null) {
36085      timestampQueryPool.beginQuery(uid);
36086    }
36087  }
36088  // timestamp utils
36089  /**
36090   * Prepares the timestamp buffer.
36091   *
36092   * @param {string} type - The type of the timestamp query.
36093   * @param {string} uid - A unique identifier for the timestamp query.
36094   */
36095  prepareTimestampBuffer(type, uid) {
36096    if (!this.disjoint || !this.trackTimestamp) return;
36097    const timestampQueryPool = this.timestampQueryPool[type];
36098    timestampQueryPool.endQuery(uid);
36099  }
36100  /**
36101   * Returns the backend's rendering context.
36102   *
36103   * @return {WebGL2RenderingContext} The rendering context.
36104   */
36105  getContext() {
36106    return this.gl;
36107  }
36108  /**
36109   * This method is executed at the beginning of a render call and prepares
36110   * the WebGL state for upcoming render calls
36111   *
36112   * @param {RenderContext} renderContext - The render context.
36113   */
36114  beginRender(renderContext) {
36115    const { state } = this;
36116    const renderContextData = this.get(renderContext);
36117    if (renderContext.viewport) {
36118      this.updateViewport(renderContext);
36119    } else {
36120      const { width, height } = this.getDrawingBufferSize();
36121      state.viewport(0, 0, width, height);
36122    }
36123    if (renderContext.scissor) {
36124      this.updateScissor(renderContext);
36125    } else {
36126      const { width, height } = this.getDrawingBufferSize();
36127      state.scissor(0, 0, width, height);
36128    }
36129    this.initTimestampQuery(TimestampQuery.RENDER, this.getTimestampUID(renderContext));
36130    renderContextData.previousContext = this._currentContext;
36131    this._currentContext = renderContext;
36132    this._setFramebuffer(renderContext);
36133    this.clear(renderContext.clearColor, renderContext.clearDepth, renderContext.clearStencil, renderContext, false);
36134    const occlusionQueryCount = renderContext.occlusionQueryCount;
36135    if (occlusionQueryCount > 0) {
36136      renderContextData.currentOcclusionQueries = renderContextData.occlusionQueries;
36137      renderContextData.currentOcclusionQueryObjects = renderContextData.occlusionQueryObjects;
36138      renderContextData.lastOcclusionObject = null;
36139      renderContextData.occlusionQueries = new Array(occlusionQueryCount);
36140      renderContextData.occlusionQueryObjects = new Array(occlusionQueryCount);
36141      renderContextData.occlusionQueryIndex = 0;
36142    }
36143  }
36144  /**
36145   * This method is executed at the end of a render call and finalizes work
36146   * after draw calls.
36147   *
36148   * @param {RenderContext} renderContext - The render context.
36149   */
36150  finishRender(renderContext) {
36151    const { gl, state } = this;
36152    const renderContextData = this.get(renderContext);
36153    const previousContext = renderContextData.previousContext;
36154    state.resetVertexState();
36155    const occlusionQueryCount = renderContext.occlusionQueryCount;
36156    if (occlusionQueryCount > 0) {
36157      if (occlusionQueryCount > renderContextData.occlusionQueryIndex) {
36158        gl.endQuery(gl.ANY_SAMPLES_PASSED);
36159      }
36160      this.resolveOccludedAsync(renderContext);
36161    }
36162    const textures = renderContext.textures;
36163    if (textures !== null) {
36164      for (let i = 0; i < textures.length; i++) {
36165        const texture3 = textures[i];
36166        if (texture3.generateMipmaps) {
36167          this.generateMipmaps(texture3);
36168        }
36169      }
36170    }
36171    this._currentContext = previousContext;
36172    this._resolveRenderTarget(renderContext);
36173    if (previousContext !== null) {
36174      this._setFramebuffer(previousContext);
36175      if (previousContext.viewport) {
36176        this.updateViewport(previousContext);
36177      } else {
36178        const { width, height } = this.getDrawingBufferSize();
36179        state.viewport(0, 0, width, height);
36180      }
36181      if (previousContext.scissor) {
36182        this.updateScissor(previousContext);
36183      } else {
36184        const { width, height } = this.getDrawingBufferSize();
36185        state.scissor(0, 0, width, height);
36186      }
36187    }
36188    this.prepareTimestampBuffer(TimestampQuery.RENDER, this.getTimestampUID(renderContext));
36189  }
36190  /**
36191   * This method processes the result of occlusion queries and writes it
36192   * into render context data.
36193   *
36194   * @async
36195   * @param {RenderContext} renderContext - The render context.
36196   */
36197  resolveOccludedAsync(renderContext) {
36198    const renderContextData = this.get(renderContext);
36199    const { currentOcclusionQueries, currentOcclusionQueryObjects } = renderContextData;
36200    if (currentOcclusionQueries && currentOcclusionQueryObjects) {
36201      const occluded = /* @__PURE__ */ new WeakSet();
36202      const { gl } = this;
36203      renderContextData.currentOcclusionQueryObjects = null;
36204      renderContextData.currentOcclusionQueries = null;
36205      const check = () => {
36206        let completed = 0;
36207        for (let i = 0; i < currentOcclusionQueries.length; i++) {
36208          const query = currentOcclusionQueries[i];
36209          if (query === null) continue;
36210          if (gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)) {
36211            if (gl.getQueryParameter(query, gl.QUERY_RESULT) === 0) occluded.add(currentOcclusionQueryObjects[i]);
36212            currentOcclusionQueries[i] = null;
36213            gl.deleteQuery(query);
36214            completed++;
36215          }
36216        }
36217        if (completed < currentOcclusionQueries.length) {
36218          requestAnimationFrame(check);
36219        } else {
36220          renderContextData.occluded = occluded;
36221        }
36222      };
36223      check();
36224    }
36225  }
36226  /**
36227   * Returns `true` if the given 3D object is fully occluded by other
36228   * 3D objects in the scene.
36229   *
36230   * @param {RenderContext} renderContext - The render context.
36231   * @param {Object3D} object - The 3D object to test.
36232   * @return {boolean} Whether the 3D object is fully occluded or not.
36233   */
36234  isOccluded(renderContext, object) {
36235    const renderContextData = this.get(renderContext);
36236    return renderContextData.occluded && renderContextData.occluded.has(object);
36237  }
36238  /**
36239   * Updates the viewport with the values from the given render context.
36240   *
36241   * @param {RenderContext} renderContext - The render context.
36242   */
36243  updateViewport(renderContext) {
36244    const { state } = this;
36245    const { x, y, width, height } = renderContext.viewportValue;
36246    state.viewport(x, renderContext.height - height - y, width, height);
36247  }
36248  /**
36249   * Updates the scissor with the values from the given render context.
36250   *
36251   * @param {RenderContext} renderContext - The render context.
36252   */
36253  updateScissor(renderContext) {
36254    const { state } = this;
36255    const { x, y, width, height } = renderContext.scissorValue;
36256    state.scissor(x, renderContext.height - height - y, width, height);
36257  }
36258  /**
36259   * Defines the scissor test.
36260   *
36261   * @param {boolean} boolean - Whether the scissor test should be enabled or not.
36262   */
36263  setScissorTest(boolean) {
36264    const state = this.state;
36265    state.setScissorTest(boolean);
36266  }
36267  /**
36268   * Returns the clear color and alpha into a single
36269   * color object.
36270   *
36271   * @return {Color4} The clear color.
36272   */
36273  getClearColor() {
36274    const clearColor = super.getClearColor();
36275    clearColor.r *= clearColor.a;
36276    clearColor.g *= clearColor.a;
36277    clearColor.b *= clearColor.a;
36278    return clearColor;
36279  }
36280  /**
36281   * Performs a clear operation.
36282   *
36283   * @param {boolean} color - Whether the color buffer should be cleared or not.
36284   * @param {boolean} depth - Whether the depth buffer should be cleared or not.
36285   * @param {boolean} stencil - Whether the stencil buffer should be cleared or not.
36286   * @param {?Object} [descriptor=null] - The render context of the current set render target.
36287   * @param {boolean} [setFrameBuffer=true] - Controls whether the intermediate framebuffer should be set or not.
36288   * @param {boolean} [resolveRenderTarget=true] - Controls whether an active render target should be resolved
36289   * or not. Only relevant for explicit clears.
36290   */
36291  clear(color3, depth3, stencil, descriptor = null, setFrameBuffer = true, resolveRenderTarget = true) {
36292    const { gl, renderer } = this;
36293    if (descriptor === null) {
36294      const clearColor = this.getClearColor();
36295      descriptor = {
36296        textures: null,
36297        clearColorValue: clearColor
36298      };
36299    }
36300    let clear = 0;
36301    if (color3) clear |= gl.COLOR_BUFFER_BIT;
36302    if (depth3) clear |= gl.DEPTH_BUFFER_BIT;
36303    if (stencil) clear |= gl.STENCIL_BUFFER_BIT;
36304    if (clear !== 0) {
36305      let clearColor;
36306      if (descriptor.clearColorValue) {
36307        clearColor = descriptor.clearColorValue;
36308      } else {
36309        clearColor = this.getClearColor();
36310      }
36311      const clearDepth = renderer.getClearDepth();
36312      const clearStencil = renderer.getClearStencil();
36313      if (depth3) this.state.setDepthMask(true);
36314      if (descriptor.textures === null) {
36315        gl.clearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
36316        gl.clear(clear);
36317      } else {
36318        if (setFrameBuffer) this._setFramebuffer(descriptor);
36319        if (color3) {
36320          for (let i = 0; i < descriptor.textures.length; i++) {
36321            if (i === 0) {
36322              gl.clearBufferfv(gl.COLOR, i, [clearColor.r, clearColor.g, clearColor.b, clearColor.a]);
36323            } else {
36324              gl.clearBufferfv(gl.COLOR, i, [0, 0, 0, 1]);
36325            }
36326          }
36327        }
36328        if (depth3 && stencil) {
36329          gl.clearBufferfi(gl.DEPTH_STENCIL, 0, clearDepth, clearStencil);
36330        } else if (depth3) {
36331          gl.clearBufferfv(gl.DEPTH, 0, [clearDepth]);
36332        } else if (stencil) {
36333          gl.clearBufferiv(gl.STENCIL, 0, [clearStencil]);
36334        }
36335        if (setFrameBuffer && resolveRenderTarget) this._resolveRenderTarget(descriptor);
36336      }
36337    }
36338  }
36339  /**
36340   * This method is executed at the beginning of a compute call and
36341   * prepares the state for upcoming compute tasks.
36342   *
36343   * @param {Node|Array<Node>} computeGroup - The compute node(s).
36344   */
36345  beginCompute(computeGroup) {
36346    const { state, gl } = this;
36347    state.bindFramebuffer(gl.FRAMEBUFFER, null);
36348    this.initTimestampQuery(TimestampQuery.COMPUTE, this.getTimestampUID(computeGroup));
36349  }
36350  /**
36351   * Executes a compute command for the given compute node.
36352   *
36353   * @param {Node|Array<Node>} computeGroup - The group of compute nodes of a compute call. Can be a single compute node.
36354   * @param {Node} computeNode - The compute node.
36355   * @param {Array<BindGroup>} bindings - The bindings.
36356   * @param {ComputePipeline} pipeline - The compute pipeline.
36357   * @param {?number} [count=null] - The count of compute invocations. If `null`, the count is determined by the compute node.
36358   */
36359  compute(computeGroup, computeNode, bindings, pipeline, count = null) {
36360    const { state, gl } = this;
36361    if (this.discard === false) {
36362      state.enable(gl.RASTERIZER_DISCARD);
36363      this.discard = true;
36364    }
36365    const { programGPU, transformBuffers, attributes } = this.get(pipeline);
36366    const vaoKey = this._getVaoKey(attributes);
36367    const vaoGPU = this.vaoCache[vaoKey];
36368    if (vaoGPU === void 0) {
36369      this.vaoCache[vaoKey] = this._createVao(attributes);
36370    } else {
36371      state.setVertexState(vaoGPU);
36372    }
36373    state.useProgram(programGPU);
36374    this._bindUniforms(bindings);
36375    const transformFeedbackGPU = this._getTransformFeedback(transformBuffers);
36376    gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedbackGPU);
36377    gl.beginTransformFeedback(gl.POINTS);
36378    count = count !== null ? count : computeNode.count;
36379    if (Array.isArray(count)) {
36380      warnOnce("WebGLBackend.compute(): The count parameter must be a single number, not an array.");
36381      count = count[0];
36382    } else if (count && typeof count === "object" && count.isIndirectStorageBufferAttribute) {
36383      warnOnce("WebGLBackend.compute(): The count parameter must be a single number, not IndirectStorageBufferAttribute");
36384      count = computeNode.count;
36385    }
36386    if (attributes[0].isStorageInstancedBufferAttribute) {
36387      gl.drawArraysInstanced(gl.POINTS, 0, 1, count);
36388    } else {
36389      gl.drawArrays(gl.POINTS, 0, count);
36390    }
36391    gl.endTransformFeedback();
36392    gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
36393    for (let i = 0; i < transformBuffers.length; i++) {
36394      const dualAttributeData = transformBuffers[i];
36395      if (dualAttributeData.pbo && this.has(dualAttributeData.pbo)) {
36396        this.textureUtils.copyBufferToTexture(dualAttributeData.transformBuffer, dualAttributeData.pbo);
36397      }
36398      dualAttributeData.switchBuffers();
36399    }
36400  }
36401  /**
36402   * This method is executed at the end of a compute call and
36403   * finalizes work after compute tasks.
36404   *
36405   * @param {Node|Array<Node>} computeGroup - The compute node(s).
36406   */
36407  finishCompute(computeGroup) {
36408    const { state, gl } = this;
36409    this.discard = false;
36410    state.disable(gl.RASTERIZER_DISCARD);
36411    this.prepareTimestampBuffer(TimestampQuery.COMPUTE, this.getTimestampUID(computeGroup));
36412    if (this._currentContext) {
36413      this._setFramebuffer(this._currentContext);
36414    }
36415  }
36416  /**
36417   * Internal to determine if the current render target is a render target array with depth 2D array texture.
36418   *
36419   * @param {RenderContext} renderContext - The render context.
36420   * @return {boolean} Whether the render target is a render target array with depth 2D array texture.
36421   *
36422   * @private
36423   */
36424  _isRenderCameraDepthArray(renderContext) {
36425    return renderContext.depthTexture && renderContext.depthTexture.isArrayTexture && renderContext.camera.isArrayCamera;
36426  }
36427  /**
36428   * Internal draw function.
36429   *
36430   * @private
36431   * @param {Object3D} object - The object to render.
36432   * @param {WebGLBufferRenderer} renderer - The internal renderer.
36433   * @param {number} firstVertex - The first vertex to render.
36434   * @param {number} vertexCount - The vertex count.
36435   * @param {number} instanceCount - The intance count.
36436   * @param {WebGLProgram} programGPU - The raw WebGL shader program.
36437   */
36438  _draw(object, renderer, firstVertex, vertexCount, instanceCount, programGPU) {
36439    if (object.isBatchedMesh) {
36440      if (this.hasFeature("WEBGL_multi_draw") === false) {
36441        const { gl } = this;
36442        const drawIdLocation = gl.getUniformLocation(programGPU, "nodeUniformDrawId");
36443        const starts = object._multiDrawStarts;
36444        const counts = object._multiDrawCounts;
36445        const drawCount = object._multiDrawCount;
36446        for (let i = 0; i < drawCount; i++) {
36447          gl.uniform1ui(drawIdLocation, i);
36448          renderer.render(starts[i], counts[i]);
36449        }
36450      } else {
36451        renderer.renderMultiDraw(object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount);
36452      }
36453    } else if (instanceCount > 1) {
36454      renderer.renderInstances(firstVertex, vertexCount, instanceCount);
36455    } else {
36456      renderer.render(firstVertex, vertexCount);
36457    }
36458  }
36459  /**
36460   * Executes a draw command for the given render object.
36461   *
36462   * @param {RenderObject} renderObject - The render object to draw.
36463   * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process.
36464   */
36465  draw(renderObject) {
36466    const { object, pipeline, material, context: context3, hardwareClippingPlanes } = renderObject;
36467    const { programGPU } = this.get(pipeline);
36468    const { gl, state } = this;
36469    const contextData = this.get(context3);
36470    const drawParams = renderObject.getDrawParameters();
36471    if (drawParams === null) return;
36472    this._bindUniforms(renderObject.getBindings());
36473    const frontFaceCW = object.isMesh && object.matrixWorld.determinant() < 0;
36474    state.setMaterial(material, frontFaceCW, hardwareClippingPlanes);
36475    if (context3.mrt !== null && context3.textures !== null) {
36476      state.setMRTBlending(context3.textures, context3.mrt, material);
36477    }
36478    state.useProgram(programGPU);
36479    const attributes = renderObject.getAttributes();
36480    const attributesData = this.get(attributes);
36481    let vaoGPU = attributesData.vaoGPU;
36482    if (vaoGPU === void 0) {
36483      const vaoKey = this._getVaoKey(attributes);
36484      vaoGPU = this.vaoCache[vaoKey];
36485      if (vaoGPU === void 0) {
36486        vaoGPU = this._createVao(attributes);
36487        this.vaoCache[vaoKey] = vaoGPU;
36488        attributesData.vaoGPU = vaoGPU;
36489      }
36490    }
36491    const index = renderObject.getIndex();
36492    const indexGPU = index !== null ? this.get(index).bufferGPU : null;
36493    state.setVertexState(vaoGPU, indexGPU);
36494    const lastObject = contextData.lastOcclusionObject;
36495    if (lastObject !== object && lastObject !== void 0) {
36496      if (lastObject !== null && lastObject.occlusionTest === true) {
36497        gl.endQuery(gl.ANY_SAMPLES_PASSED);
36498        contextData.occlusionQueryIndex++;
36499      }
36500      if (object.occlusionTest === true) {
36501        const query = gl.createQuery();
36502        gl.beginQuery(gl.ANY_SAMPLES_PASSED, query);
36503        contextData.occlusionQueries[contextData.occlusionQueryIndex] = query;
36504        contextData.occlusionQueryObjects[contextData.occlusionQueryIndex] = object;
36505      }
36506      contextData.lastOcclusionObject = object;
36507    }
36508    const renderer = this.bufferRenderer;
36509    if (object.isPoints) renderer.mode = gl.POINTS;
36510    else if (object.isLineSegments) renderer.mode = gl.LINES;
36511    else if (object.isLine) renderer.mode = gl.LINE_STRIP;
36512    else if (object.isLineLoop) renderer.mode = gl.LINE_LOOP;
36513    else {
36514      if (material.wireframe === true) {
36515        state.setLineWidth(material.wireframeLinewidth * this.renderer.getPixelRatio());
36516        renderer.mode = gl.LINES;
36517      } else {
36518        renderer.mode = gl.TRIANGLES;
36519      }
36520    }
36521    const { vertexCount, instanceCount } = drawParams;
36522    let { firstVertex } = drawParams;
36523    renderer.object = object;
36524    if (index !== null) {
36525      firstVertex *= index.array.BYTES_PER_ELEMENT;
36526      const indexData = this.get(index);
36527      renderer.index = index.count;
36528      renderer.type = indexData.type;
36529    } else {
36530      renderer.index = 0;
36531    }
36532    if (renderObject.camera.isArrayCamera === true && renderObject.camera.cameras.length > 0 && renderObject.camera.isMultiViewCamera === false) {
36533      const cameraData = this.get(renderObject.camera);
36534      const cameras = renderObject.camera.cameras;
36535      const cameraIndex3 = renderObject.getBindingGroup("cameraIndex").bindings[0];
36536      if (cameraData.indexesGPU === void 0 || cameraData.indexesGPU.length !== cameras.length) {
36537        const data = new Uint32Array([0, 0, 0, 0]);
36538        const indexesGPU = [];
36539        for (let i = 0, len = cameras.length; i < len; i++) {
36540          const bufferGPU = gl.createBuffer();
36541          data[0] = i;
36542          gl.bindBuffer(gl.UNIFORM_BUFFER, bufferGPU);
36543          gl.bufferData(gl.UNIFORM_BUFFER, data, gl.STATIC_DRAW);
36544          indexesGPU.push(bufferGPU);
36545        }
36546        cameraData.indexesGPU = indexesGPU;
36547      }
36548      let cameraIndexBufferIndex = 0;
36549      bindingsSearch: for (const bindGroup of renderObject.getBindings()) {
36550        for (const binding of bindGroup.bindings) {
36551          if (binding === cameraIndex3) break bindingsSearch;
36552          if (binding.isUniformsGroup || binding.isUniformBuffer) cameraIndexBufferIndex++;
36553        }
36554      }
36555      const pixelRatio = this.renderer.getPixelRatio();
36556      const renderTarget = this._currentContext.renderTarget;
36557      const isRenderCameraDepthArray = this._isRenderCameraDepthArray(this._currentContext);
36558      const prevActiveCubeFace = this._currentContext.activeCubeFace;
36559      if (isRenderCameraDepthArray) {
36560        const textureData = this.get(renderTarget.depthTexture);
36561        if (textureData.clearedRenderId !== this.renderer._nodes.nodeFrame.renderId) {
36562          textureData.clearedRenderId = this.renderer._nodes.nodeFrame.renderId;
36563          const { stencilBuffer } = renderTarget;
36564          for (let i = 0, len = cameras.length; i < len; i++) {
36565            this.renderer._activeCubeFace = i;
36566            this._currentContext.activeCubeFace = i;
36567            this._setFramebuffer(this._currentContext);
36568            this.clear(false, true, stencilBuffer, this._currentContext, false, false);
36569          }
36570          this.renderer._activeCubeFace = prevActiveCubeFace;
36571          this._currentContext.activeCubeFace = prevActiveCubeFace;
36572        }
36573      }
36574      for (let i = 0, len = cameras.length; i < len; i++) {
36575        const subCamera = cameras[i];
36576        if (object.layers.test(subCamera.layers)) {
36577          if (isRenderCameraDepthArray) {
36578            this.renderer._activeCubeFace = i;
36579            this._currentContext.activeCubeFace = i;
36580            this._setFramebuffer(this._currentContext);
36581          }
36582          const vp = subCamera.viewport;
36583          if (vp !== void 0) {
36584            const x = vp.x * pixelRatio;
36585            const y = vp.y * pixelRatio;
36586            const width = vp.width * pixelRatio;
36587            const height = vp.height * pixelRatio;
36588            state.viewport(
36589              Math.floor(x),
36590              Math.floor(renderObject.context.height - height - y),
36591              Math.floor(width),
36592              Math.floor(height)
36593            );
36594          }
36595          state.bindBufferBase(gl.UNIFORM_BUFFER, cameraIndexBufferIndex, cameraData.indexesGPU[i]);
36596          this._draw(object, renderer, firstVertex, vertexCount, instanceCount, programGPU);
36597        }
36598        this._currentContext.activeCubeFace = prevActiveCubeFace;
36599        this.renderer._activeCubeFace = prevActiveCubeFace;
36600      }
36601    } else {
36602      this._draw(object, renderer, firstVertex, vertexCount, instanceCount, programGPU);
36603    }
36604  }
36605  /**
36606   * Explain why always null is returned.
36607   *
36608   * @param {RenderObject} renderObject - The render object.
36609   * @return {boolean} Whether the render pipeline requires an update or not.
36610   */
36611  needsRenderUpdate() {
36612    return false;
36613  }
36614  /**
36615   * Explain why no cache key is computed.
36616   *
36617   * @param {RenderObject} renderObject - The render object.
36618   * @return {string} The cache key.
36619   */
36620  getRenderCacheKey() {
36621    return "";
36622  }
36623  // textures
36624  /**
36625   * Creates a default texture for the given texture that can be used
36626   * as a placeholder until the actual texture is ready for usage.
36627   *
36628   * @param {Texture} texture - The texture to create a default texture for.
36629   */
36630  createDefaultTexture(texture3) {
36631    this.textureUtils.createDefaultTexture(texture3);
36632  }
36633  /**
36634   * Defines a texture on the GPU for the given texture object.
36635   *
36636   * @param {Texture} texture - The texture.
36637   * @param {Object} [options={}] - Optional configuration parameter.
36638   */
36639  createTexture(texture3, options) {
36640    this.textureUtils.createTexture(texture3, options);
36641  }
36642  /**
36643   * Uploads the updated texture data to the GPU.
36644   *
36645   * @param {Texture} texture - The texture.
36646   * @param {Object} [options={}] - Optional configuration parameter.
36647   */
36648  updateTexture(texture3, options) {
36649    this.textureUtils.updateTexture(texture3, options);
36650  }
36651  /**
36652   * Generates mipmaps for the given texture.
36653   *
36654   * @param {Texture} texture - The texture.
36655   */
36656  generateMipmaps(texture3) {
36657    this.textureUtils.generateMipmaps(texture3);
36658  }
36659  /**
36660   * Destroys the GPU data for the given texture object.
36661   *
36662   * @param {Texture} texture - The texture.
36663   * @param {boolean} [isDefaultTexture=false] - Whether the texture uses a default GPU texture or not.
36664   */
36665  destroyTexture(texture3, isDefaultTexture = false) {
36666    this.textureUtils.destroyTexture(texture3, isDefaultTexture);
36667  }
36668  /**
36669   * Returns texture data as a typed array.
36670   *
36671   * @async
36672   * @param {Texture} texture - The texture to copy.
36673   * @param {number} x - The x coordinate of the copy origin.
36674   * @param {number} y - The y coordinate of the copy origin.
36675   * @param {number} width - The width of the copy.
36676   * @param {number} height - The height of the copy.
36677   * @param {number} faceIndex - The face index.
36678   * @return {Promise<TypedArray>} A Promise that resolves with a typed array when the copy operation has finished.
36679   */
36680  async copyTextureToBuffer(texture3, x, y, width, height, faceIndex) {
36681    return this.textureUtils.copyTextureToBuffer(texture3, x, y, width, height, faceIndex);
36682  }
36683  /**
36684   * This method does nothing since WebGL 2 has no concept of samplers.
36685   *
36686   * @param {Texture} texture - The texture to update the sampler for.
36687   * @return {string} The current sampler key.
36688   */
36689  updateSampler() {
36690    return "";
36691  }
36692  // node builder
36693  /**
36694   * Returns a node builder for the given render object.
36695   *
36696   * @param {RenderObject} object - The render object.
36697   * @param {Renderer} renderer - The renderer.
36698   * @return {GLSLNodeBuilder} The node builder.
36699   */
36700  createNodeBuilder(object, renderer) {
36701    return new GLSLNodeBuilder(object, renderer);
36702  }
36703  // program
36704  /**
36705   * Creates a shader program from the given programmable stage.
36706   *
36707   * @param {ProgrammableStage} program - The programmable stage.
36708   */
36709  createProgram(program) {
36710    const gl = this.gl;
36711    const { stage, code: code3 } = program;
36712    const shader = stage === "fragment" ? gl.createShader(gl.FRAGMENT_SHADER) : gl.createShader(gl.VERTEX_SHADER);
36713    gl.shaderSource(shader, code3);
36714    gl.compileShader(shader);
36715    this.set(program, {
36716      shaderGPU: shader
36717    });
36718  }
36719  /**
36720   * Destroys the shader program of the given programmable stage.
36721   *
36722   * @param {ProgrammableStage} program - The programmable stage.
36723   */
36724  destroyProgram(program) {
36725    this.delete(program);
36726  }
36727  /**
36728   * Creates a render pipeline for the given render object.
36729   *
36730   * @param {RenderObject} renderObject - The render object.
36731   * @param {Array<Promise>} promises - An array of compilation promises which are used in `compileAsync()`.
36732   */
36733  createRenderPipeline(renderObject, promises) {
36734    const gl = this.gl;
36735    const pipeline = renderObject.pipeline;
36736    const { fragmentProgram, vertexProgram } = pipeline;
36737    const programGPU = gl.createProgram();
36738    const fragmentShader = this.get(fragmentProgram).shaderGPU;
36739    const vertexShader = this.get(vertexProgram).shaderGPU;
36740    gl.attachShader(programGPU, fragmentShader);
36741    gl.attachShader(programGPU, vertexShader);
36742    gl.linkProgram(programGPU);
36743    this.set(pipeline, {
36744      programGPU,
36745      fragmentShader,
36746      vertexShader
36747    });
36748    if (promises !== null && this.parallel) {
36749      const p = new Promise((resolve) => {
36750        const parallel = this.parallel;
36751        const checkStatus = () => {
36752          if (gl.getProgramParameter(programGPU, parallel.COMPLETION_STATUS_KHR)) {
36753            this._completeCompile(renderObject, pipeline);
36754            resolve();
36755          } else {
36756            requestAnimationFrame(checkStatus);
36757          }
36758        };
36759        checkStatus();
36760      });
36761      promises.push(p);
36762      return;
36763    }
36764    this._completeCompile(renderObject, pipeline);
36765  }
36766  /**
36767   * Formats the source code of error messages.
36768   *
36769   * @private
36770   * @param {string} string - The code.
36771   * @param {number} errorLine - The error line.
36772   * @return {string} The formatted code.
36773   */
36774  _handleSource(string3, errorLine) {
36775    const lines = string3.split("\n");
36776    const lines2 = [];
36777    const from = Math.max(errorLine - 6, 0);
36778    const to = Math.min(errorLine + 6, lines.length);
36779    for (let i = from; i < to; i++) {
36780      const line = i + 1;
36781      lines2.push(`${line === errorLine ? ">" : " "} ${line}: ${lines[i]}`);
36782    }
36783    return lines2.join("\n");
36784  }
36785  /**
36786   * Gets the shader compilation errors from the info log.
36787   *
36788   * @private
36789   * @param {WebGL2RenderingContext} gl - The rendering context.
36790   * @param {WebGLShader} shader - The WebGL shader object.
36791   * @param {string} type - The shader type.
36792   * @return {string} The shader errors.
36793   */
36794  _getShaderErrors(gl, shader, type) {
36795    const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
36796    const shaderInfoLog = gl.getShaderInfoLog(shader) || "";
36797    const errors = shaderInfoLog.trim();
36798    if (status && errors === "") return "";
36799    const errorMatches = /ERROR: 0:(\d+)/.exec(errors);
36800    if (errorMatches) {
36801      const errorLine = parseInt(errorMatches[1]);
36802      return type.toUpperCase() + "\n\n" + errors + "\n\n" + this._handleSource(gl.getShaderSource(shader), errorLine);
36803    } else {
36804      return errors;
36805    }
36806  }
36807  /**
36808   * Logs shader compilation errors.
36809   *
36810   * @private
36811   * @param {WebGLProgram} programGPU - The WebGL program.
36812   * @param {WebGLShader} glFragmentShader - The fragment shader as a native WebGL shader object.
36813   * @param {WebGLShader} glVertexShader - The vertex shader as a native WebGL shader object.
36814   */
36815  _logProgramError(programGPU, glFragmentShader, glVertexShader) {
36816    if (this.renderer.debug.checkShaderErrors) {
36817      const gl = this.gl;
36818      const programInfoLog = gl.getProgramInfoLog(programGPU) || "";
36819      const programLog = programInfoLog.trim();
36820      if (gl.getProgramParameter(programGPU, gl.LINK_STATUS) === false) {
36821        if (typeof this.renderer.debug.onShaderError === "function") {
36822          this.renderer.debug.onShaderError(gl, programGPU, glVertexShader, glFragmentShader);
36823        } else {
36824          const vertexErrors = this._getShaderErrors(gl, glVertexShader, "vertex");
36825          const fragmentErrors = this._getShaderErrors(gl, glFragmentShader, "fragment");
36826          error(
36827            "THREE.WebGLProgram: Shader Error " + gl.getError() + " - VALIDATE_STATUS " + gl.getProgramParameter(programGPU, gl.VALIDATE_STATUS) + "\n\nProgram Info Log: " + programLog + "\n" + vertexErrors + "\n" + fragmentErrors
36828          );
36829        }
36830      } else if (programLog !== "") {
36831        warn("WebGLProgram: Program Info Log:", programLog);
36832      }
36833    }
36834  }
36835  /**
36836   * Completes the shader program setup for the given render object.
36837   *
36838   * @private
36839   * @param {RenderObject} renderObject - The render object.
36840   * @param {RenderPipeline} pipeline - The render pipeline.
36841   */
36842  _completeCompile(renderObject, pipeline) {
36843    const { state, gl } = this;
36844    const pipelineData = this.get(pipeline);
36845    const { programGPU, fragmentShader, vertexShader } = pipelineData;
36846    if (gl.getProgramParameter(programGPU, gl.LINK_STATUS) === false) {
36847      this._logProgramError(programGPU, fragmentShader, vertexShader);
36848    }
36849    state.useProgram(programGPU);
36850    const bindings = renderObject.getBindings();
36851    this._setupBindings(bindings, programGPU);
36852    this.set(pipeline, {
36853      programGPU,
36854      pipeline: programGPU
36855    });
36856  }
36857  /**
36858   * Creates a compute pipeline for the given compute node.
36859   *
36860   * @param {ComputePipeline} computePipeline - The compute pipeline.
36861   * @param {Array<BindGroup>} bindings - The bindings.
36862   */
36863  createComputePipeline(computePipeline, bindings) {
36864    const { state, gl } = this;
36865    const fragmentProgram = {
36866      stage: "fragment",
36867      code: "#version 300 es\nprecision highp float;\nvoid main() {}"
36868    };
36869    this.createProgram(fragmentProgram);
36870    const { computeProgram } = computePipeline;
36871    const programGPU = gl.createProgram();
36872    const fragmentShader = this.get(fragmentProgram).shaderGPU;
36873    const vertexShader = this.get(computeProgram).shaderGPU;
36874    const transforms = computeProgram.transforms;
36875    const transformVaryingNames = [];
36876    const transformAttributeNodes = [];
36877    for (let i = 0; i < transforms.length; i++) {
36878      const transform = transforms[i];
36879      transformVaryingNames.push(transform.varyingName);
36880      transformAttributeNodes.push(transform.attributeNode);
36881    }
36882    gl.attachShader(programGPU, fragmentShader);
36883    gl.attachShader(programGPU, vertexShader);
36884    gl.transformFeedbackVaryings(
36885      programGPU,
36886      transformVaryingNames,
36887      gl.SEPARATE_ATTRIBS
36888    );
36889    gl.linkProgram(programGPU);
36890    if (gl.getProgramParameter(programGPU, gl.LINK_STATUS) === false) {
36891      this._logProgramError(programGPU, fragmentShader, vertexShader);
36892    }
36893    state.useProgram(programGPU);
36894    this._setupBindings(bindings, programGPU);
36895    const attributeNodes = computeProgram.attributes;
36896    const attributes = [];
36897    const transformBuffers = [];
36898    for (let i = 0; i < attributeNodes.length; i++) {
36899      const attribute3 = attributeNodes[i].node.attribute;
36900      attributes.push(attribute3);
36901      if (!this.has(attribute3)) this.attributeUtils.createAttribute(attribute3, gl.ARRAY_BUFFER);
36902    }
36903    for (let i = 0; i < transformAttributeNodes.length; i++) {
36904      const attribute3 = transformAttributeNodes[i].attribute;
36905      if (!this.has(attribute3)) this.attributeUtils.createAttribute(attribute3, gl.ARRAY_BUFFER);
36906      const attributeData = this.get(attribute3);
36907      transformBuffers.push(attributeData);
36908    }
36909    this.set(computePipeline, {
36910      programGPU,
36911      transformBuffers,
36912      attributes
36913    });
36914  }
36915  /**
36916   * Creates bindings from the given bind group definition.
36917   *
36918   * @param {BindGroup} bindGroup - The bind group.
36919   * @param {Array<BindGroup>} bindings - Array of bind groups.
36920   * @param {number} cacheIndex - The cache index.
36921   * @param {number} version - The version.
36922   */
36923  createBindings(bindGroup, bindings) {
36924    if (this._knownBindings.has(bindings) === false) {
36925      this._knownBindings.add(bindings);
36926      let uniformBuffers = 0;
36927      let textures = 0;
36928      for (const bindGroup2 of bindings) {
36929        this.set(bindGroup2, {
36930          textures,
36931          uniformBuffers
36932        });
36933        for (const binding of bindGroup2.bindings) {
36934          if (binding.isUniformBuffer) uniformBuffers++;
36935          if (binding.isSampledTexture) textures++;
36936        }
36937      }
36938    }
36939    this.updateBindings(bindGroup, bindings);
36940  }
36941  /**
36942   * Updates the given bind group definition.
36943   *
36944   * @param {BindGroup} bindGroup - The bind group.
36945   * @param {Array<BindGroup>} bindings - Array of bind groups.
36946   * @param {number} cacheIndex - The cache index.
36947   * @param {number} version - The version.
36948   */
36949  updateBindings(bindGroup) {
36950    const { gl } = this;
36951    for (const binding of bindGroup.bindings) {
36952      const map = this.get(binding);
36953      if (binding.isUniformsGroup || binding.isUniformBuffer) {
36954        const array3 = binding.buffer;
36955        let { bufferGPU } = this.get(array3);
36956        if (bufferGPU === void 0) {
36957          bufferGPU = gl.createBuffer();
36958          gl.bindBuffer(gl.UNIFORM_BUFFER, bufferGPU);
36959          gl.bufferData(gl.UNIFORM_BUFFER, array3.byteLength, gl.DYNAMIC_DRAW);
36960          this.set(array3, { bufferGPU });
36961        } else {
36962          gl.bindBuffer(gl.UNIFORM_BUFFER, bufferGPU);
36963        }
36964        const updateRanges = binding.updateRanges;
36965        gl.bindBuffer(gl.UNIFORM_BUFFER, bufferGPU);
36966        if (updateRanges.length === 0) {
36967          gl.bufferData(gl.UNIFORM_BUFFER, array3, gl.DYNAMIC_DRAW);
36968        } else {
36969          const isTyped = isTypedArray(array3);
36970          const byteOffsetFactor = isTyped ? 1 : array3.BYTES_PER_ELEMENT;
36971          for (let i = 0, l = updateRanges.length; i < l; i++) {
36972            const range3 = updateRanges[i];
36973            const dataOffset = range3.start * byteOffsetFactor;
36974            const size3 = range3.count * byteOffsetFactor;
36975            const bufferOffset = dataOffset * (isTyped ? array3.BYTES_PER_ELEMENT : 1);
36976            gl.bufferSubData(gl.UNIFORM_BUFFER, bufferOffset, array3, dataOffset, size3);
36977          }
36978        }
36979        map.bufferGPU = bufferGPU;
36980        this.set(binding, map);
36981      } else if (binding.isSampledTexture) {
36982        const { textureGPU, glTextureType } = this.get(binding.texture);
36983        map.textureGPU = textureGPU;
36984        map.glTextureType = glTextureType;
36985        this.set(binding, map);
36986      }
36987    }
36988  }
36989  /**
36990   * Updates a buffer binding.
36991   *
36992   *  @param {Buffer} binding - The buffer binding to update.
36993   */
36994  updateBinding(binding) {
36995    const gl = this.gl;
36996    if (binding.isUniformsGroup || binding.isUniformBuffer) {
36997      const bindingData = this.get(binding);
36998      const bufferGPU = bindingData.bufferGPU;
36999      const array3 = binding.buffer;
37000      const updateRanges = binding.updateRanges;
37001      gl.bindBuffer(gl.UNIFORM_BUFFER, bufferGPU);
37002      if (updateRanges.length === 0) {
37003        gl.bufferData(gl.UNIFORM_BUFFER, array3, gl.DYNAMIC_DRAW);
37004      } else {
37005        const isTyped = isTypedArray(array3);
37006        const byteOffsetFactor = isTyped ? 1 : array3.BYTES_PER_ELEMENT;
37007        for (let i = 0, l = updateRanges.length; i < l; i++) {
37008          const range3 = updateRanges[i];
37009          const dataOffset = range3.start * byteOffsetFactor;
37010          const size3 = range3.count * byteOffsetFactor;
37011          const bufferOffset = dataOffset * (isTyped ? array3.BYTES_PER_ELEMENT : 1);
37012          gl.bufferSubData(gl.UNIFORM_BUFFER, bufferOffset, array3, dataOffset, size3);
37013        }
37014      }
37015    }
37016  }
37017  // attributes
37018  /**
37019   * Creates the GPU buffer of an indexed shader attribute.
37020   *
37021   * @param {BufferAttribute} attribute - The indexed buffer attribute.
37022   */
37023  createIndexAttribute(attribute3) {
37024    const gl = this.gl;
37025    this.attributeUtils.createAttribute(attribute3, gl.ELEMENT_ARRAY_BUFFER);
37026  }
37027  /**
37028   * Creates the GPU buffer of a shader attribute.
37029   *
37030   * @param {BufferAttribute} attribute - The buffer attribute.
37031   */
37032  createAttribute(attribute3) {
37033    if (this.has(attribute3)) return;
37034    const gl = this.gl;
37035    this.attributeUtils.createAttribute(attribute3, gl.ARRAY_BUFFER);
37036  }
37037  /**
37038   * Creates the GPU buffer of a storage attribute.
37039   *
37040   * @param {BufferAttribute} attribute - The buffer attribute.
37041   */
37042  createStorageAttribute(attribute3) {
37043    if (this.has(attribute3)) return;
37044    const gl = this.gl;
37045    this.attributeUtils.createAttribute(attribute3, gl.ARRAY_BUFFER);
37046  }
37047  /**
37048   * Updates the GPU buffer of a shader attribute.
37049   *
37050   * @param {BufferAttribute} attribute - The buffer attribute to update.
37051   */
37052  updateAttribute(attribute3) {
37053    this.attributeUtils.updateAttribute(attribute3);
37054  }
37055  /**
37056   * Destroys the GPU buffer of a shader attribute.
37057   *
37058   * @param {BufferAttribute} attribute - The buffer attribute to destroy.
37059   */
37060  destroyAttribute(attribute3) {
37061    this.attributeUtils.destroyAttribute(attribute3);
37062  }
37063  /**
37064   * Checks if the given feature is supported  by the backend.
37065   *
37066   * @param {string} name - The feature's name.
37067   * @return {boolean} Whether the feature is supported or not.
37068   */
37069  hasFeature(name) {
37070    const keysMatching = Object.keys(GLFeatureName).filter((key) => GLFeatureName[key] === name);
37071    const extensions = this.extensions;
37072    for (let i = 0; i < keysMatching.length; i++) {
37073      if (extensions.has(keysMatching[i])) return true;
37074    }
37075    return false;
37076  }
37077  /**
37078   * Copies data of the given source texture to the given destination texture.
37079   *
37080   * @param {Texture} srcTexture - The source texture.
37081   * @param {Texture} dstTexture - The destination texture.
37082   * @param {?(Box3|Box2)} [srcRegion=null] - The region of the source texture to copy.
37083   * @param {?(Vector2|Vector3)} [dstPosition=null] - The destination position of the copy.
37084   * @param {number} [srcLevel=0] - The source mip level to copy from.
37085   * @param {number} [dstLevel=0] - The destination mip level to copy to.
37086   */
37087  copyTextureToTexture(srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0) {
37088    this.textureUtils.copyTextureToTexture(srcTexture, dstTexture, srcRegion, dstPosition, srcLevel, dstLevel);
37089  }
37090  /**
37091   * Copies the current bound framebuffer to the given texture.
37092   *
37093   * @param {Texture} texture - The destination texture.
37094   * @param {RenderContext} renderContext - The render context.
37095   * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy.
37096   */
37097  copyFramebufferToTexture(texture3, renderContext, rectangle) {
37098    this.textureUtils.copyFramebufferToTexture(texture3, renderContext, rectangle);
37099  }
37100  /**
37101   * Checks if the given compatibility is supported by the backend.
37102   *
37103   * @param {string} name - The compatibility name.
37104   * @return {boolean} Whether the compatibility is supported or not.
37105   */
37106  hasCompatibility(name) {
37107    if (name === Compatibility.TEXTURE_COMPARE) return true;
37108    return super.hasCompatibility(name);
37109  }
37110  /**
37111   * Initializes the render target defined in the given render context.
37112   *
37113   * @param {RenderContext} renderContext - The render context.
37114   */
37115  initRenderTarget(renderContext) {
37116    const { gl, state } = this;
37117    this._setFramebuffer(renderContext);
37118    state.bindFramebuffer(gl.FRAMEBUFFER, null);
37119  }
37120  /**
37121   * Configures the active framebuffer from the given render context.
37122   *
37123   * @private
37124   * @param {RenderContext} descriptor - The render context.
37125   */
37126  _setFramebuffer(descriptor) {
37127    const { gl, state } = this;
37128    let currentFrameBuffer = null;
37129    if (descriptor.textures !== null) {
37130      const renderTarget = descriptor.renderTarget;
37131      const renderTargetContextData = this.get(renderTarget);
37132      const { samples, depthBuffer, stencilBuffer } = renderTarget;
37133      const isCube = renderTarget.isCubeRenderTarget === true;
37134      const isRenderTarget3D = renderTarget.isRenderTarget3D === true;
37135      const isRenderTargetArray = renderTarget.depth > 1;
37136      const isXRRenderTarget = renderTarget.isXRRenderTarget === true;
37137      const _hasExternalTextures = isXRRenderTarget === true && renderTarget._hasExternalTextures === true;
37138      let msaaFb = renderTargetContextData.msaaFrameBuffer;
37139      let depthRenderbuffer = renderTargetContextData.depthRenderbuffer;
37140      const multisampledRTTExt = this.extensions.get("WEBGL_multisampled_render_to_texture");
37141      const multiviewExt = this.extensions.get("OVR_multiview2");
37142      const useMultisampledRTT = this._useMultisampledExtension(renderTarget);
37143      const cacheKey = getCacheKey(descriptor);
37144      let fb;
37145      if (isCube) {
37146        renderTargetContextData.cubeFramebuffers || (renderTargetContextData.cubeFramebuffers = {});
37147        fb = renderTargetContextData.cubeFramebuffers[cacheKey];
37148      } else if (isXRRenderTarget && _hasExternalTextures === false) {
37149        fb = this._xrFramebuffer;
37150      } else {
37151        renderTargetContextData.framebuffers || (renderTargetContextData.framebuffers = {});
37152        fb = renderTargetContextData.framebuffers[cacheKey];
37153      }
37154      if (fb === void 0) {
37155        fb = gl.createFramebuffer();
37156        state.bindFramebuffer(gl.FRAMEBUFFER, fb);
37157        const textures = descriptor.textures;
37158        const depthInvalidationArray = [];
37159        if (isCube) {
37160          renderTargetContextData.cubeFramebuffers[cacheKey] = fb;
37161          const { textureGPU } = this.get(textures[0]);
37162          const cubeFace = this.renderer._activeCubeFace;
37163          const mipLevel = this.renderer._activeMipmapLevel;
37164          gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, textureGPU, mipLevel);
37165        } else {
37166          renderTargetContextData.framebuffers[cacheKey] = fb;
37167          for (let i = 0; i < textures.length; i++) {
37168            const texture3 = textures[i];
37169            const textureData = this.get(texture3);
37170            textureData.renderTarget = descriptor.renderTarget;
37171            textureData.cacheKey = cacheKey;
37172            const attachment = gl.COLOR_ATTACHMENT0 + i;
37173            if (renderTarget.multiview) {
37174              multiviewExt.framebufferTextureMultisampleMultiviewOVR(gl.FRAMEBUFFER, attachment, textureData.textureGPU, 0, samples, 0, 2);
37175            } else if (isRenderTarget3D || isRenderTargetArray) {
37176              const layer = this.renderer._activeCubeFace;
37177              const mipLevel = this.renderer._activeMipmapLevel;
37178              gl.framebufferTextureLayer(gl.FRAMEBUFFER, attachment, textureData.textureGPU, mipLevel, layer);
37179            } else {
37180              if (useMultisampledRTT) {
37181                multisampledRTTExt.framebufferTexture2DMultisampleEXT(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0, samples);
37182              } else {
37183                const mipLevel = this.renderer._activeMipmapLevel;
37184                gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, mipLevel);
37185              }
37186            }
37187          }
37188        }
37189        const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
37190        if (renderTarget._autoAllocateDepthBuffer === true) {
37191          const renderbuffer = gl.createRenderbuffer();
37192          this.textureUtils.setupRenderBufferStorage(renderbuffer, descriptor, 0, useMultisampledRTT);
37193          renderTargetContextData.xrDepthRenderbuffer = renderbuffer;
37194          depthInvalidationArray.push(stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT);
37195          gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
37196          gl.framebufferRenderbuffer(gl.FRAMEBUFFER, depthStyle, gl.RENDERBUFFER, renderbuffer);
37197        } else {
37198          if (descriptor.depthTexture !== null) {
37199            depthInvalidationArray.push(stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT);
37200            const textureData = this.get(descriptor.depthTexture);
37201            textureData.renderTarget = descriptor.renderTarget;
37202            textureData.cacheKey = cacheKey;
37203            if (renderTarget.multiview) {
37204              multiviewExt.framebufferTextureMultisampleMultiviewOVR(gl.FRAMEBUFFER, depthStyle, textureData.textureGPU, 0, samples, 0, 2);
37205            } else if (_hasExternalTextures && useMultisampledRTT) {
37206              multisampledRTTExt.framebufferTexture2DMultisampleEXT(gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0, samples);
37207            } else {
37208              if (descriptor.depthTexture.isArrayTexture) {
37209                const layer = this.renderer._activeCubeFace;
37210                gl.framebufferTextureLayer(gl.FRAMEBUFFER, depthStyle, textureData.textureGPU, 0, layer);
37211              } else if (descriptor.depthTexture.isCubeTexture) {
37212                const cubeFace = this.renderer._activeCubeFace;
37213                gl.framebufferTexture2D(gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, textureData.textureGPU, 0);
37214              } else {
37215                gl.framebufferTexture2D(gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0);
37216              }
37217            }
37218          }
37219        }
37220        renderTargetContextData.depthInvalidationArray = depthInvalidationArray;
37221      } else {
37222        const isRenderCameraDepthArray = this._isRenderCameraDepthArray(descriptor);
37223        if (isRenderCameraDepthArray) {
37224          state.bindFramebuffer(gl.FRAMEBUFFER, fb);
37225          const layer = this.renderer._activeCubeFace;
37226          const depthData = this.get(descriptor.depthTexture);
37227          const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
37228          gl.framebufferTextureLayer(
37229            gl.FRAMEBUFFER,
37230            depthStyle,
37231            depthData.textureGPU,
37232            0,
37233            layer
37234          );
37235        }
37236        if ((isXRRenderTarget || useMultisampledRTT || renderTarget.multiview) && renderTarget._isOpaqueFramebuffer !== true) {
37237          state.bindFramebuffer(gl.FRAMEBUFFER, fb);
37238          const textureData = this.get(descriptor.textures[0]);
37239          if (renderTarget.multiview) {
37240            multiviewExt.framebufferTextureMultisampleMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, textureData.textureGPU, 0, samples, 0, 2);
37241          } else if (useMultisampledRTT) {
37242            multisampledRTTExt.framebufferTexture2DMultisampleEXT(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureData.textureGPU, 0, samples);
37243          } else {
37244            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureData.textureGPU, 0);
37245          }
37246          const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
37247          if (renderTarget._autoAllocateDepthBuffer === true) {
37248            const renderbuffer = renderTargetContextData.xrDepthRenderbuffer;
37249            gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
37250            gl.framebufferRenderbuffer(gl.FRAMEBUFFER, depthStyle, gl.RENDERBUFFER, renderbuffer);
37251          } else {
37252            const textureData2 = this.get(descriptor.depthTexture);
37253            if (renderTarget.multiview) {
37254              multiviewExt.framebufferTextureMultisampleMultiviewOVR(gl.FRAMEBUFFER, depthStyle, textureData2.textureGPU, 0, samples, 0, 2);
37255            } else if (useMultisampledRTT) {
37256              multisampledRTTExt.framebufferTexture2DMultisampleEXT(gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData2.textureGPU, 0, samples);
37257            } else {
37258              gl.framebufferTexture2D(gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData2.textureGPU, 0);
37259            }
37260          }
37261        }
37262      }
37263      if (samples > 0 && useMultisampledRTT === false && !renderTarget.multiview) {
37264        if (msaaFb === void 0) {
37265          const invalidationArray = [];
37266          msaaFb = gl.createFramebuffer();
37267          state.bindFramebuffer(gl.FRAMEBUFFER, msaaFb);
37268          const msaaRenderbuffers = [];
37269          const textures = descriptor.textures;
37270          for (let i = 0; i < textures.length; i++) {
37271            msaaRenderbuffers[i] = gl.createRenderbuffer();
37272            gl.bindRenderbuffer(gl.RENDERBUFFER, msaaRenderbuffers[i]);
37273            invalidationArray.push(gl.COLOR_ATTACHMENT0 + i);
37274            const texture3 = descriptor.textures[i];
37275            const textureData = this.get(texture3);
37276            gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, textureData.glInternalFormat, descriptor.width, descriptor.height);
37277            gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, msaaRenderbuffers[i]);
37278          }
37279          gl.bindRenderbuffer(gl.RENDERBUFFER, null);
37280          renderTargetContextData.msaaFrameBuffer = msaaFb;
37281          renderTargetContextData.msaaRenderbuffers = msaaRenderbuffers;
37282          if (depthBuffer && depthRenderbuffer === void 0) {
37283            depthRenderbuffer = gl.createRenderbuffer();
37284            this.textureUtils.setupRenderBufferStorage(depthRenderbuffer, descriptor, samples);
37285            renderTargetContextData.depthRenderbuffer = depthRenderbuffer;
37286            const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
37287            invalidationArray.push(depthStyle);
37288          }
37289          renderTargetContextData.invalidationArray = invalidationArray;
37290        }
37291        currentFrameBuffer = renderTargetContextData.msaaFrameBuffer;
37292      } else {
37293        currentFrameBuffer = fb;
37294      }
37295      state.drawBuffers(descriptor, fb);
37296    }
37297    state.bindFramebuffer(gl.FRAMEBUFFER, currentFrameBuffer);
37298  }
37299  /**
37300   * Computes the VAO key for the given index and attributes.
37301   *
37302   * @private
37303   * @param {Array<BufferAttribute>} attributes - An array of buffer attributes.
37304   * @return {string} The VAO key.
37305   */
37306  _getVaoKey(attributes) {
37307    let key = "";
37308    for (let i = 0; i < attributes.length; i++) {
37309      const attributeData = this.get(attributes[i]);
37310      key += ":" + attributeData.id;
37311    }
37312    return key;
37313  }
37314  /**
37315   * Creates a VAO from the index and attributes.
37316   *
37317   * @private
37318   * @param {Array<BufferAttribute>} attributes - An array of buffer attributes.
37319   * @return {Object} The VAO data.
37320   */
37321  _createVao(attributes) {
37322    const { gl } = this;
37323    const vaoGPU = gl.createVertexArray();
37324    gl.bindVertexArray(vaoGPU);
37325    for (let i = 0; i < attributes.length; i++) {
37326      const attribute3 = attributes[i];
37327      const attributeData = this.get(attribute3);
37328      gl.bindBuffer(gl.ARRAY_BUFFER, attributeData.bufferGPU);
37329      gl.enableVertexAttribArray(i);
37330      let stride, offset3;
37331      if (attribute3.isInterleavedBufferAttribute === true) {
37332        stride = attribute3.data.stride * attributeData.bytesPerElement;
37333        offset3 = attribute3.offset * attributeData.bytesPerElement;
37334      } else {
37335        stride = 0;
37336        offset3 = 0;
37337      }
37338      if (attributeData.isInteger) {
37339        gl.vertexAttribIPointer(i, attribute3.itemSize, attributeData.type, stride, offset3);
37340      } else {
37341        gl.vertexAttribPointer(i, attribute3.itemSize, attributeData.type, attribute3.normalized, stride, offset3);
37342      }
37343      if (attribute3.isInstancedBufferAttribute && !attribute3.isInterleavedBufferAttribute) {
37344        gl.vertexAttribDivisor(i, attribute3.meshPerAttribute);
37345      } else if (attribute3.isInterleavedBufferAttribute && attribute3.data.isInstancedInterleavedBuffer) {
37346        gl.vertexAttribDivisor(i, attribute3.data.meshPerAttribute);
37347      }
37348    }
37349    gl.bindBuffer(gl.ARRAY_BUFFER, null);
37350    return vaoGPU;
37351  }
37352  /**
37353   * Creates a transform feedback from the given transform buffers.
37354   *
37355   * @private
37356   * @param {Array<DualAttributeData>} transformBuffers - The transform buffers.
37357   * @return {WebGLTransformFeedback} The transform feedback.
37358   */
37359  _getTransformFeedback(transformBuffers) {
37360    let key = "";
37361    for (let i = 0; i < transformBuffers.length; i++) {
37362      key += ":" + transformBuffers[i].id;
37363    }
37364    let transformFeedbackGPU = this.transformFeedbackCache[key];
37365    if (transformFeedbackGPU !== void 0) {
37366      return transformFeedbackGPU;
37367    }
37368    const { gl } = this;
37369    transformFeedbackGPU = gl.createTransformFeedback();
37370    gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedbackGPU);
37371    for (let i = 0; i < transformBuffers.length; i++) {
37372      const attributeData = transformBuffers[i];
37373      gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, i, attributeData.transformBuffer);
37374    }
37375    gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
37376    this.transformFeedbackCache[key] = transformFeedbackGPU;
37377    return transformFeedbackGPU;
37378  }
37379  /**
37380   * Setups the given bindings.
37381   *
37382   * @private
37383   * @param {Array<BindGroup>} bindings - The bindings.
37384   * @param {WebGLProgram} programGPU - The WebGL program.
37385   */
37386  _setupBindings(bindings, programGPU) {
37387    const gl = this.gl;
37388    let uniformBuffers = 0;
37389    let textures = 0;
37390    for (const bindGroup of bindings) {
37391      for (const binding of bindGroup.bindings) {
37392        if (binding.isUniformsGroup || binding.isUniformBuffer) {
37393          const index = uniformBuffers++;
37394          const location = gl.getUniformBlockIndex(programGPU, binding.name);
37395          gl.uniformBlockBinding(programGPU, location, index);
37396        } else if (binding.isSampledTexture) {
37397          const index = textures++;
37398          const location = gl.getUniformLocation(programGPU, binding.name);
37399          gl.uniform1i(location, index);
37400        }
37401      }
37402    }
37403  }
37404  /**
37405   * Binds the given uniforms.
37406   *
37407   * @private
37408   * @param {Array<BindGroup>} bindings - The bindings.
37409   */
37410  _bindUniforms(bindings) {
37411    const { gl, state } = this;
37412    let uniformBuffers = 0;
37413    let textures = 0;
37414    for (const bindGroup of bindings) {
37415      for (const binding of bindGroup.bindings) {
37416        const bindingData = this.get(binding);
37417        if (binding.isUniformsGroup || binding.isUniformBuffer) {
37418          const index = uniformBuffers++;
37419          state.bindBufferBase(gl.UNIFORM_BUFFER, index, bindingData.bufferGPU);
37420        } else if (binding.isSampledTexture) {
37421          const index = textures++;
37422          state.bindTexture(bindingData.glTextureType, bindingData.textureGPU, gl.TEXTURE0 + index);
37423        }
37424      }
37425    }
37426  }
37427  /**
37428   * The method ensures multisampled render targets are resolved.
37429   *
37430   * @private
37431   * @param {RenderContext} renderContext - The render context.
37432   */
37433  _resolveRenderTarget(renderContext) {
37434    const { gl, state } = this;
37435    const renderTarget = renderContext.renderTarget;
37436    if (renderContext.textures !== null && renderTarget) {
37437      const renderTargetContextData = this.get(renderTarget);
37438      if (renderTarget.samples > 0 && this._useMultisampledExtension(renderTarget) === false) {
37439        const fb = renderTargetContextData.framebuffers[renderContext.getCacheKey()];
37440        let mask = gl.COLOR_BUFFER_BIT;
37441        if (renderTarget.resolveDepthBuffer) {
37442          if (renderTarget.depthBuffer) mask |= gl.DEPTH_BUFFER_BIT;
37443          if (renderTarget.stencilBuffer && renderTarget.resolveStencilBuffer) mask |= gl.STENCIL_BUFFER_BIT;
37444        }
37445        const msaaFrameBuffer = renderTargetContextData.msaaFrameBuffer;
37446        const msaaRenderbuffers = renderTargetContextData.msaaRenderbuffers;
37447        const textures = renderContext.textures;
37448        const isMRT = textures.length > 1;
37449        state.bindFramebuffer(gl.READ_FRAMEBUFFER, msaaFrameBuffer);
37450        state.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
37451        if (isMRT) {
37452          for (let i = 0; i < textures.length; i++) {
37453            gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, null);
37454            gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, null, 0);
37455          }
37456        }
37457        for (let i = 0; i < textures.length; i++) {
37458          if (isMRT) {
37459            const { textureGPU } = this.get(textures[i]);
37460            gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msaaRenderbuffers[i]);
37461            gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureGPU, 0);
37462          }
37463          if (renderContext.scissor) {
37464            const { x, y, width, height } = renderContext.scissorValue;
37465            const viewY = renderContext.height - height - y;
37466            gl.blitFramebuffer(x, viewY, x + width, viewY + height, x, viewY, x + width, viewY + height, mask, gl.NEAREST);
37467          } else {
37468            gl.blitFramebuffer(0, 0, renderContext.width, renderContext.height, 0, 0, renderContext.width, renderContext.height, mask, gl.NEAREST);
37469          }
37470        }
37471        if (isMRT) {
37472          for (let i = 0; i < textures.length; i++) {
37473            const { textureGPU } = this.get(textures[i]);
37474            gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, msaaRenderbuffers[i]);
37475            gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, textureGPU, 0);
37476          }
37477        }
37478        if (this._supportsInvalidateFramebuffer === true) {
37479          gl.invalidateFramebuffer(gl.READ_FRAMEBUFFER, renderTargetContextData.invalidationArray);
37480        }
37481      } else if (renderTarget.resolveDepthBuffer === false && renderTargetContextData.framebuffers) {
37482        const fb = renderTargetContextData.framebuffers[renderContext.getCacheKey()];
37483        state.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
37484        gl.invalidateFramebuffer(gl.DRAW_FRAMEBUFFER, renderTargetContextData.depthInvalidationArray);
37485      }
37486    }
37487  }
37488  /**
37489   * Returns `true` if the `WEBGL_multisampled_render_to_texture` extension
37490   * should be used when MSAA is enabled.
37491   *
37492   * @private
37493   * @param {RenderTarget} renderTarget - The render target that should be multisampled.
37494   * @return {boolean} Whether to use the `WEBGL_multisampled_render_to_texture` extension for MSAA or not.
37495   */
37496  _useMultisampledExtension(renderTarget) {
37497    if (renderTarget.multiview === true) {
37498      return true;
37499    }
37500    return renderTarget.samples > 0 && this.extensions.has("WEBGL_multisampled_render_to_texture") === true && renderTarget._autoAllocateDepthBuffer !== false;
37501  }
37502  /**
37503   * Frees internal resources.
37504   */
37505  dispose() {
37506    if (this.textureUtils !== null) this.textureUtils.dispose();
37507    const extension = this.extensions.get("WEBGL_lose_context");
37508    if (extension) extension.loseContext();
37509    this.renderer.domElement.removeEventListener("webglcontextlost", this._onContextLost);
37510  }
37511};
37512var GPUPrimitiveTopology = {
37513  PointList: "point-list",
37514  LineList: "line-list",
37515  LineStrip: "line-strip",
37516  TriangleList: "triangle-list"
37517};
37518var GPUShaderStage = typeof self !== "undefined" && self.GPUShaderStage ? self.GPUShaderStage : { VERTEX: 1, FRAGMENT: 2, COMPUTE: 4 };
37519var GPUCompareFunction = {
37520  Never: "never",
37521  Less: "less",
37522  Equal: "equal",
37523  LessEqual: "less-equal",
37524  Greater: "greater",
37525  NotEqual: "not-equal",
37526  GreaterEqual: "greater-equal",
37527  Always: "always"
37528};
37529var GPUStoreOp = {
37530  Store: "store"
37531};
37532var GPULoadOp = {
37533  Load: "load",
37534  Clear: "clear"
37535};
37536var GPUFrontFace = {
37537  CCW: "ccw",
37538  CW: "cw"
37539};
37540var GPUCullMode = {
37541  None: "none",
37542  Back: "back"
37543};
37544var GPUIndexFormat = {
37545  Uint16: "uint16",
37546  Uint32: "uint32"
37547};
37548var GPUTextureFormat = {
37549  // 8-bit formats
37550  R8Unorm: "r8unorm",
37551  R8Snorm: "r8snorm",
37552  R8Uint: "r8uint",
37553  R8Sint: "r8sint",
37554  // 16-bit formats
37555  R16Uint: "r16uint",
37556  R16Sint: "r16sint",
37557  R16Float: "r16float",
37558  RG8Unorm: "rg8unorm",
37559  RG8Snorm: "rg8snorm",
37560  RG8Uint: "rg8uint",
37561  RG8Sint: "rg8sint",
37562  R16Unorm: "r16unorm",
37563  R16Snorm: "r16snorm",
37564  // 32-bit formats
37565  R32Uint: "r32uint",
37566  R32Sint: "r32sint",
37567  R32Float: "r32float",
37568  RG16Uint: "rg16uint",
37569  RG16Sint: "rg16sint",
37570  RG16Float: "rg16float",
37571  RGBA8Unorm: "rgba8unorm",
37572  RGBA8UnormSRGB: "rgba8unorm-srgb",
37573  RGBA8Snorm: "rgba8snorm",
37574  RGBA8Uint: "rgba8uint",
37575  RGBA8Sint: "rgba8sint",
37576  BGRA8Unorm: "bgra8unorm",
37577  BGRA8UnormSRGB: "bgra8unorm-srgb",
37578  RG16Unorm: "rg16unorm",
37579  RG16Snorm: "rg16snorm",
37580  // Packed 32-bit formats
37581  RGB9E5UFloat: "rgb9e5ufloat",
37582  RGB10A2Unorm: "rgb10a2unorm",
37583  RG11B10UFloat: "rg11b10ufloat",
37584  // 64-bit formats
37585  RG32Uint: "rg32uint",
37586  RG32Sint: "rg32sint",
37587  RG32Float: "rg32float",
37588  RGBA16Uint: "rgba16uint",
37589  RGBA16Sint: "rgba16sint",
37590  RGBA16Float: "rgba16float",
37591  RGBA16Unorm: "rgba16unorm",
37592  RGBA16Snorm: "rgba16snorm",
37593  // 128-bit formats
37594  RGBA32Uint: "rgba32uint",
37595  RGBA32Sint: "rgba32sint",
37596  RGBA32Float: "rgba32float",
37597  Depth16Unorm: "depth16unorm",
37598  Depth24Plus: "depth24plus",
37599  Depth24PlusStencil8: "depth24plus-stencil8",
37600  Depth32Float: "depth32float",
37601  // 'depth32float-stencil8' extension
37602  Depth32FloatStencil8: "depth32float-stencil8",
37603  // BC compressed formats usable if 'texture-compression-bc' is both
37604  // supported by the device/user agent and enabled in requestDevice.
37605  BC1RGBAUnorm: "bc1-rgba-unorm",
37606  BC1RGBAUnormSRGB: "bc1-rgba-unorm-srgb",
37607  BC2RGBAUnorm: "bc2-rgba-unorm",
37608  BC2RGBAUnormSRGB: "bc2-rgba-unorm-srgb",
37609  BC3RGBAUnorm: "bc3-rgba-unorm",
37610  BC3RGBAUnormSRGB: "bc3-rgba-unorm-srgb",
37611  BC4RUnorm: "bc4-r-unorm",
37612  BC4RSnorm: "bc4-r-snorm",
37613  BC5RGUnorm: "bc5-rg-unorm",
37614  BC5RGSnorm: "bc5-rg-snorm",
37615  BC6HRGBUFloat: "bc6h-rgb-ufloat",
37616  BC6HRGBFloat: "bc6h-rgb-float",
37617  BC7RGBAUnorm: "bc7-rgba-unorm",
37618  BC7RGBAUnormSRGB: "bc7-rgba-unorm-srgb",
37619  // ETC2 compressed formats usable if 'texture-compression-etc2' is both
37620  // supported by the device/user agent and enabled in requestDevice.
37621  ETC2RGB8Unorm: "etc2-rgb8unorm",
37622  ETC2RGB8UnormSRGB: "etc2-rgb8unorm-srgb",
37623  ETC2RGB8A1Unorm: "etc2-rgb8a1unorm",
37624  ETC2RGB8A1UnormSRGB: "etc2-rgb8a1unorm-srgb",
37625  ETC2RGBA8Unorm: "etc2-rgba8unorm",
37626  ETC2RGBA8UnormSRGB: "etc2-rgba8unorm-srgb",
37627  EACR11Unorm: "eac-r11unorm",
37628  EACR11Snorm: "eac-r11snorm",
37629  EACRG11Unorm: "eac-rg11unorm",
37630  EACRG11Snorm: "eac-rg11snorm",
37631  // ASTC compressed formats usable if 'texture-compression-astc' is both
37632  // supported by the device/user agent and enabled in requestDevice.
37633  ASTC4x4Unorm: "astc-4x4-unorm",
37634  ASTC4x4UnormSRGB: "astc-4x4-unorm-srgb",
37635  ASTC5x4Unorm: "astc-5x4-unorm",
37636  ASTC5x4UnormSRGB: "astc-5x4-unorm-srgb",
37637  ASTC5x5Unorm: "astc-5x5-unorm",
37638  ASTC5x5UnormSRGB: "astc-5x5-unorm-srgb",
37639  ASTC6x5Unorm: "astc-6x5-unorm",
37640  ASTC6x5UnormSRGB: "astc-6x5-unorm-srgb",
37641  ASTC6x6Unorm: "astc-6x6-unorm",
37642  ASTC6x6UnormSRGB: "astc-6x6-unorm-srgb",
37643  ASTC8x5Unorm: "astc-8x5-unorm",
37644  ASTC8x5UnormSRGB: "astc-8x5-unorm-srgb",
37645  ASTC8x6Unorm: "astc-8x6-unorm",
37646  ASTC8x6UnormSRGB: "astc-8x6-unorm-srgb",
37647  ASTC8x8Unorm: "astc-8x8-unorm",
37648  ASTC8x8UnormSRGB: "astc-8x8-unorm-srgb",
37649  ASTC10x5Unorm: "astc-10x5-unorm",
37650  ASTC10x5UnormSRGB: "astc-10x5-unorm-srgb",
37651  ASTC10x6Unorm: "astc-10x6-unorm",
37652  ASTC10x6UnormSRGB: "astc-10x6-unorm-srgb",
37653  ASTC10x8Unorm: "astc-10x8-unorm",
37654  ASTC10x8UnormSRGB: "astc-10x8-unorm-srgb",
37655  ASTC10x10Unorm: "astc-10x10-unorm",
37656  ASTC10x10UnormSRGB: "astc-10x10-unorm-srgb",
37657  ASTC12x10Unorm: "astc-12x10-unorm",
37658  ASTC12x10UnormSRGB: "astc-12x10-unorm-srgb",
37659  ASTC12x12Unorm: "astc-12x12-unorm",
37660  ASTC12x12UnormSRGB: "astc-12x12-unorm-srgb"
37661};
37662var GPUAddressMode = {
37663  ClampToEdge: "clamp-to-edge",
37664  Repeat: "repeat",
37665  MirrorRepeat: "mirror-repeat"
37666};
37667var GPUFilterMode = {
37668  Linear: "linear",
37669  Nearest: "nearest"
37670};
37671var GPUBlendFactor = {
37672  Zero: "zero",
37673  One: "one",
37674  Src: "src",
37675  OneMinusSrc: "one-minus-src",
37676  SrcAlpha: "src-alpha",
37677  OneMinusSrcAlpha: "one-minus-src-alpha",
37678  Dst: "dst",
37679  OneMinusDst: "one-minus-dst",
37680  DstAlpha: "dst-alpha",
37681  OneMinusDstAlpha: "one-minus-dst-alpha",
37682  SrcAlphaSaturated: "src-alpha-saturated",
37683  Constant: "constant",
37684  OneMinusConstant: "one-minus-constant"
37685};
37686var GPUBlendOperation = {
37687  Add: "add",
37688  Subtract: "subtract",
37689  ReverseSubtract: "reverse-subtract",
37690  Min: "min",
37691  Max: "max"
37692};
37693var GPUColorWriteFlags = {
37694  None: 0,
37695  All: 15
37696};
37697var GPUStencilOperation = {
37698  Keep: "keep",
37699  Zero: "zero",
37700  Replace: "replace",
37701  Invert: "invert",
37702  IncrementClamp: "increment-clamp",
37703  DecrementClamp: "decrement-clamp",
37704  IncrementWrap: "increment-wrap",
37705  DecrementWrap: "decrement-wrap"
37706};
37707var GPUBufferBindingType = {
37708  Storage: "storage",
37709  ReadOnlyStorage: "read-only-storage"
37710};
37711var GPUStorageTextureAccess = {
37712  WriteOnly: "write-only",
37713  ReadOnly: "read-only",
37714  ReadWrite: "read-write"
37715};
37716var GPUSamplerBindingType = {
37717  NonFiltering: "non-filtering",
37718  Comparison: "comparison"
37719};
37720var GPUTextureSampleType = {
37721  Float: "float",
37722  UnfilterableFloat: "unfilterable-float",
37723  Depth: "depth",
37724  SInt: "sint",
37725  UInt: "uint"
37726};
37727var GPUTextureDimension = {
37728  TwoD: "2d",
37729  ThreeD: "3d"
37730};
37731var GPUTextureViewDimension = {
37732  TwoD: "2d",
37733  TwoDArray: "2d-array",
37734  Cube: "cube",
37735  ThreeD: "3d"
37736};
37737var GPUTextureAspect = {
37738  All: "all"
37739};
37740var GPUInputStepMode = {
37741  Vertex: "vertex",
37742  Instance: "instance"
37743};
37744var GPUFeatureName = {
37745  CoreFeaturesAndLimits: "core-features-and-limits",
37746  DepthClipControl: "depth-clip-control",
37747  Depth32FloatStencil8: "depth32float-stencil8",
37748  TextureCompressionBC: "texture-compression-bc",
37749  TextureCompressionBCSliced3D: "texture-compression-bc-sliced-3d",
37750  TextureCompressionETC2: "texture-compression-etc2",
37751  TextureCompressionASTC: "texture-compression-astc",
37752  TextureCompressionASTCSliced3D: "texture-compression-astc-sliced-3d",
37753  TimestampQuery: "timestamp-query",
37754  IndirectFirstInstance: "indirect-first-instance",
37755  ShaderF16: "shader-f16",
37756  RG11B10UFloat: "rg11b10ufloat-renderable",
37757  BGRA8UNormStorage: "bgra8unorm-storage",
37758  Float32Filterable: "float32-filterable",
37759  Float32Blendable: "float32-blendable",
37760  ClipDistances: "clip-distances",
37761  DualSourceBlending: "dual-source-blending",
37762  Subgroups: "subgroups",
37763  TextureFormatsTier1: "texture-formats-tier1",
37764  TextureFormatsTier2: "texture-formats-tier2"
37765};
37766var GPUFeatureMap = {
37767  "texture-compression-s3tc": "texture-compression-bc",
37768  "texture-compression-etc1": "texture-compression-etc2"
37769};
37770var NodeSampler = class extends Sampler {
37771  /**
37772   * Constructs a new node-based sampler.
37773   *
37774   * @param {string} name - The samplers's name.
37775   * @param {TextureNode} textureNode - The texture node.
37776   * @param {UniformGroupNode} groupNode - The uniform group node.
37777   */
37778  constructor(name, textureNode, groupNode) {
37779    super(name, textureNode ? textureNode.value : null);
37780    this.textureNode = textureNode;
37781    this.groupNode = groupNode;
37782  }
37783  /**
37784   * Updates the texture value of this sampler.
37785   *
37786   * @return {boolean} Whether the sampler needs an update or not.
37787   */
37788  update() {
37789    const { textureNode } = this;
37790    if (this.texture !== textureNode.value) {
37791      this.texture = textureNode.value;
37792      return true;
37793    }
37794    return super.update();
37795  }
37796};
37797var StorageBuffer = class extends Buffer {
37798  /**
37799   * Constructs a new uniform buffer.
37800   *
37801   * @param {string} name - The buffer's name.
37802   * @param {BufferAttribute} attribute - The buffer attribute.
37803   */
37804  constructor(name, attribute3) {
37805    super(name, attribute3 ? attribute3.array : null);
37806    this._attribute = attribute3;
37807    this.isStorageBuffer = true;
37808  }
37809  /**
37810   * The storage buffer attribute.
37811   *
37812   * @type {BufferAttribute}
37813   */
37814  get attribute() {
37815    return this._attribute;
37816  }
37817};
37818var _id = 0;
37819var NodeStorageBuffer = class extends StorageBuffer {
37820  /**
37821   * Constructs a new node-based storage buffer.
37822   *
37823   * @param {StorageBufferNode} nodeUniform - The storage buffer node.
37824   * @param {UniformGroupNode} groupNode - The uniform group node.
37825   */
37826  constructor(nodeUniform, groupNode) {
37827    super("StorageBuffer_" + _id++, nodeUniform ? nodeUniform.value : null);
37828    this.nodeUniform = nodeUniform;
37829    this.access = nodeUniform ? nodeUniform.access : NodeAccess.READ_WRITE;
37830    this.groupNode = groupNode;
37831  }
37832  /**
37833   * The storage buffer attribute node.
37834   *
37835   * @type {StorageBufferAttribute}
37836   */
37837  get attribute() {
37838    return this.nodeUniform.value;
37839  }
37840  /**
37841   * The storage buffer.
37842   *
37843   * @type {Float32Array}
37844   */
37845  get buffer() {
37846    return this.nodeUniform.value.array;
37847  }
37848};
37849var WebGPUTexturePassUtils = class extends DataMap {
37850  /**
37851   * Constructs a new utility object.
37852   *
37853   * @param {GPUDevice} device - The WebGPU device.
37854   */
37855  constructor(device) {
37856    super();
37857    this.device = device;
37858    const mipmapSource = `
37859struct VarysStruct {
37860	@builtin( position ) Position: vec4f,
37861	@location( 0 ) vTex : vec2f,
37862	@location( 1 ) @interpolate(flat, either) vBaseArrayLayer: u32,
37863};
37864
37865@group( 0 ) @binding ( 2 )
37866var<uniform> flipY: u32;
37867
37868@vertex
37869fn mainVS(
37870		@builtin( vertex_index ) vertexIndex : u32,
37871		@builtin( instance_index ) instanceIndex : u32 ) -> VarysStruct {
37872
37873	var Varys : VarysStruct;
37874
37875	var pos = array(
37876		vec2f( -1, -1 ),
37877		vec2f( -1,  3 ),
37878		vec2f(  3, -1 ),
37879	);
37880
37881	let p = pos[ vertexIndex ];
37882	let mult = select( vec2f( 0.5, -0.5 ), vec2f( 0.5, 0.5 ), flipY != 0 );
37883	Varys.vTex = p * mult + vec2f( 0.5 );
37884	Varys.Position = vec4f( p, 0, 1 );
37885	Varys.vBaseArrayLayer = instanceIndex;
37886
37887	return Varys;
37888
37889}
37890
37891@group( 0 ) @binding( 0 )
37892var imgSampler : sampler;
37893
37894@group( 0 ) @binding( 1 )
37895var img2d : texture_2d<f32>;
37896
37897@fragment
37898fn main_2d( Varys: VarysStruct ) -> @location( 0 ) vec4<f32> {
37899
37900	return textureSample( img2d, imgSampler, Varys.vTex );
37901
37902}
37903
37904@group( 0 ) @binding( 1 )
37905var img2dArray : texture_2d_array<f32>;
37906
37907@fragment
37908fn main_2d_array( Varys: VarysStruct ) -> @location( 0 ) vec4<f32> {
37909
37910	return textureSample( img2dArray, imgSampler, Varys.vTex, Varys.vBaseArrayLayer );
37911
37912}
37913
37914const faceMat = array(
37915  mat3x3f(  0,  0,  -2,  0, -2,   0,  1,  1,   1 ),   // pos-x
37916  mat3x3f(  0,  0,   2,  0, -2,   0, -1,  1,  -1 ),   // neg-x
37917  mat3x3f(  2,  0,   0,  0,  0,   2, -1,  1,  -1 ),   // pos-y
37918  mat3x3f(  2,  0,   0,  0,  0,  -2, -1, -1,   1 ),   // neg-y
37919  mat3x3f(  2,  0,   0,  0, -2,   0, -1,  1,   1 ),   // pos-z
37920  mat3x3f( -2,  0,   0,  0, -2,   0,  1,  1,  -1 ),   // neg-z
37921);
37922
37923@group( 0 ) @binding( 1 )
37924var imgCube : texture_cube<f32>;
37925
37926@fragment
37927fn main_cube( Varys: VarysStruct ) -> @location( 0 ) vec4<f32> {
37928
37929	return textureSample( imgCube, imgSampler, faceMat[ Varys.vBaseArrayLayer ] * vec3f( fract( Varys.vTex ), 1 ) );
37930
37931}
37932`;
37933    this.mipmapSampler = device.createSampler({ minFilter: GPUFilterMode.Linear });
37934    this.flipYSampler = device.createSampler({ minFilter: GPUFilterMode.Nearest });
37935    this.flipUniformBuffer = device.createBuffer({
37936      size: 4,
37937      usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
37938    });
37939    device.queue.writeBuffer(this.flipUniformBuffer, 0, new Uint32Array([1]));
37940    this.noFlipUniformBuffer = device.createBuffer({
37941      size: 4,
37942      usage: GPUBufferUsage.UNIFORM
37943    });
37944    this.transferPipelines = {};
37945    this.mipmapShaderModule = device.createShaderModule({
37946      label: "mipmap",
37947      code: mipmapSource
37948    });
37949  }
37950  /**
37951   * Returns a render pipeline for the internal copy render pass. The pass
37952   * requires a unique render pipeline for each texture format.
37953   *
37954   * @param {string} format - The GPU texture format
37955   * @param {string?} textureBindingViewDimension - The GPU texture binding view dimension
37956   * @return {GPURenderPipeline} The GPU render pipeline.
37957   */
37958  getTransferPipeline(format, textureBindingViewDimension) {
37959    textureBindingViewDimension = textureBindingViewDimension || "2d-array";
37960    const key = `${format}-${textureBindingViewDimension}`;
37961    let pipeline = this.transferPipelines[key];
37962    if (pipeline === void 0) {
37963      pipeline = this.device.createRenderPipeline({
37964        label: `mipmap-${format}-${textureBindingViewDimension}`,
37965        vertex: {
37966          module: this.mipmapShaderModule
37967        },
37968        fragment: {
37969          module: this.mipmapShaderModule,
37970          entryPoint: `main_${textureBindingViewDimension.replace("-", "_")}`,
37971          targets: [{ format }]
37972        },
37973        layout: "auto"
37974      });
37975      this.transferPipelines[key] = pipeline;
37976    }
37977    return pipeline;
37978  }
37979  /**
37980   * Flip the contents of the given GPU texture along its vertical axis.
37981   *
37982   * @param {GPUTexture} textureGPU - The GPU texture object.
37983   * @param {Object} textureGPUDescriptor - The texture descriptor.
37984   * @param {number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view.
37985   */
37986  flipY(textureGPU, textureGPUDescriptor, baseArrayLayer = 0) {
37987    const format = textureGPUDescriptor.format;
37988    const { width, height } = textureGPUDescriptor.size;
37989    const tempTexture = this.device.createTexture({
37990      size: { width, height },
37991      format,
37992      usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
37993    });
37994    const copyTransferPipeline = this.getTransferPipeline(format, textureGPU.textureBindingViewDimension);
37995    const flipTransferPipeline = this.getTransferPipeline(format, tempTexture.textureBindingViewDimension);
37996    const commandEncoder = this.device.createCommandEncoder({});
37997    const pass3 = (pipeline, sourceTexture, sourceArrayLayer, destinationTexture, destinationArrayLayer, flipY) => {
37998      const bindGroupLayout = pipeline.getBindGroupLayout(0);
37999      const bindGroup = this.device.createBindGroup({
38000        layout: bindGroupLayout,
38001        entries: [{
38002          binding: 0,
38003          resource: this.flipYSampler
38004        }, {
38005          binding: 1,
38006          resource: sourceTexture.createView({
38007            dimension: sourceTexture.textureBindingViewDimension || "2d-array",
38008            baseMipLevel: 0,
38009            mipLevelCount: 1
38010          })
38011        }, {
38012          binding: 2,
38013          resource: { buffer: flipY ? this.flipUniformBuffer : this.noFlipUniformBuffer }
38014        }]
38015      });
38016      const passEncoder = commandEncoder.beginRenderPass({
38017        colorAttachments: [{
38018          view: destinationTexture.createView({
38019            dimension: "2d",
38020            baseMipLevel: 0,
38021            mipLevelCount: 1,
38022            baseArrayLayer: destinationArrayLayer,
38023            arrayLayerCount: 1
38024          }),
38025          loadOp: GPULoadOp.Clear,
38026          storeOp: GPUStoreOp.Store
38027        }]
38028      });
38029      passEncoder.setPipeline(pipeline);
38030      passEncoder.setBindGroup(0, bindGroup);
38031      passEncoder.draw(3, 1, 0, sourceArrayLayer);
38032      passEncoder.end();
38033    };
38034    pass3(copyTransferPipeline, textureGPU, baseArrayLayer, tempTexture, 0, false);
38035    pass3(flipTransferPipeline, tempTexture, 0, textureGPU, baseArrayLayer, true);
38036    this.device.queue.submit([commandEncoder.finish()]);
38037    tempTexture.destroy();
38038  }
38039  /**
38040   * Generates mipmaps for the given GPU texture.
38041   *
38042   * @param {GPUTexture} textureGPU - The GPU texture object.
38043   * @param {?GPUCommandEncoder} [encoder=null] - An optional command encoder used to generate mipmaps.
38044   */
38045  generateMipmaps(textureGPU, encoder = null) {
38046    const textureData = this.get(textureGPU);
38047    const passes = textureData.layers || this._mipmapCreateBundles(textureGPU);
38048    const commandEncoder = encoder || this.device.createCommandEncoder({ label: "mipmapEncoder" });
38049    this._mipmapRunBundles(commandEncoder, passes);
38050    if (encoder === null) this.device.queue.submit([commandEncoder.finish()]);
38051    textureData.layers = passes;
38052  }
38053  /**
38054   * Since multiple copy render passes are required to generate mipmaps, the passes
38055   * are managed as render bundles to improve performance.
38056   *
38057   * @param {GPUTexture} textureGPU - The GPU texture object.
38058   * @return {Array<Object>} An array of render bundles.
38059   */
38060  _mipmapCreateBundles(textureGPU) {
38061    const textureBindingViewDimension = textureGPU.textureBindingViewDimension || "2d-array";
38062    const pipeline = this.getTransferPipeline(textureGPU.format, textureBindingViewDimension);
38063    const bindGroupLayout = pipeline.getBindGroupLayout(0);
38064    const passes = [];
38065    for (let baseMipLevel = 1; baseMipLevel < textureGPU.mipLevelCount; baseMipLevel++) {
38066      for (let baseArrayLayer = 0; baseArrayLayer < textureGPU.depthOrArrayLayers; baseArrayLayer++) {
38067        const bindGroup = this.device.createBindGroup({
38068          layout: bindGroupLayout,
38069          entries: [{
38070            binding: 0,
38071            resource: this.mipmapSampler
38072          }, {
38073            binding: 1,
38074            resource: textureGPU.createView({
38075              dimension: textureBindingViewDimension,
38076              baseMipLevel: baseMipLevel - 1,
38077              mipLevelCount: 1
38078            })
38079          }, {
38080            binding: 2,
38081            resource: { buffer: this.noFlipUniformBuffer }
38082          }]
38083        });
38084        const passDescriptor = {
38085          colorAttachments: [{
38086            view: textureGPU.createView({
38087              dimension: "2d",
38088              baseMipLevel,
38089              mipLevelCount: 1,
38090              baseArrayLayer,
38091              arrayLayerCount: 1
38092            }),
38093            loadOp: GPULoadOp.Clear,
38094            storeOp: GPUStoreOp.Store
38095          }]
38096        };
38097        const passEncoder = this.device.createRenderBundleEncoder({
38098          colorFormats: [textureGPU.format]
38099        });
38100        passEncoder.setPipeline(pipeline);
38101        passEncoder.setBindGroup(0, bindGroup);
38102        passEncoder.draw(3, 1, 0, baseArrayLayer);
38103        passes.push({
38104          renderBundles: [passEncoder.finish()],
38105          passDescriptor
38106        });
38107      }
38108    }
38109    return passes;
38110  }
38111  /**
38112   * Executes the render bundles.
38113   *
38114   * @param {GPUCommandEncoder} commandEncoder - The GPU command encoder.
38115   * @param {Array<Object>} passes - An array of render bundles.
38116   */
38117  _mipmapRunBundles(commandEncoder, passes) {
38118    const levels = passes.length;
38119    for (let i = 0; i < levels; i++) {
38120      const pass3 = passes[i];
38121      const passEncoder = commandEncoder.beginRenderPass(pass3.passDescriptor);
38122      passEncoder.executeBundles(pass3.renderBundles);
38123      passEncoder.end();
38124    }
38125  }
38126};
38127var _compareToWebGPU = {
38128  [NeverCompare]: "never",
38129  [LessCompare]: "less",
38130  [EqualCompare]: "equal",
38131  [LessEqualCompare]: "less-equal",
38132  [GreaterCompare]: "greater",
38133  [GreaterEqualCompare]: "greater-equal",
38134  [AlwaysCompare]: "always",
38135  [NotEqualCompare]: "not-equal"
38136};
38137var _flipMap = [0, 1, 3, 2, 4, 5];
38138var WebGPUTextureUtils = class {
38139  /**
38140   * Constructs a new utility object.
38141   *
38142   * @param {WebGPUBackend} backend - The WebGPU backend.
38143   */
38144  constructor(backend) {
38145    this.backend = backend;
38146    this._passUtils = null;
38147    this.defaultTexture = {};
38148    this.defaultCubeTexture = {};
38149    this.defaultVideoFrame = null;
38150    this._samplerCache = /* @__PURE__ */ new Map();
38151  }
38152  /**
38153   * Creates a GPU sampler for the given texture.
38154   *
38155   * @param {Texture} texture - The texture to create the sampler for.
38156   * @return {string} The current sampler key.
38157   */
38158  updateSampler(texture3) {
38159    const backend = this.backend;
38160    const samplerKey = texture3.minFilter + "-" + texture3.magFilter + "-" + texture3.wrapS + "-" + texture3.wrapT + "-" + (texture3.wrapR || "0") + "-" + texture3.anisotropy + "-" + (texture3.compareFunction || 0);
38161    let samplerData = this._samplerCache.get(samplerKey);
38162    if (samplerData === void 0) {
38163      const samplerDescriptorGPU = {
38164        addressModeU: this._convertAddressMode(texture3.wrapS),
38165        addressModeV: this._convertAddressMode(texture3.wrapT),
38166        addressModeW: this._convertAddressMode(texture3.wrapR),
38167        magFilter: this._convertFilterMode(texture3.magFilter),
38168        minFilter: this._convertFilterMode(texture3.minFilter),
38169        mipmapFilter: this._convertFilterMode(texture3.minFilter),
38170        maxAnisotropy: 1
38171      };
38172      if (texture3.isDepthTexture && texture3.compareFunction === null) {
38173        samplerDescriptorGPU.magFilter = GPUFilterMode.Nearest;
38174        samplerDescriptorGPU.minFilter = GPUFilterMode.Nearest;
38175        samplerDescriptorGPU.mipmapFilter = GPUFilterMode.Nearest;
38176      }
38177      if (samplerDescriptorGPU.magFilter === GPUFilterMode.Linear && samplerDescriptorGPU.minFilter === GPUFilterMode.Linear && samplerDescriptorGPU.mipmapFilter === GPUFilterMode.Linear) {
38178        samplerDescriptorGPU.maxAnisotropy = texture3.anisotropy;
38179      }
38180      if (texture3.isDepthTexture && texture3.compareFunction !== null && backend.hasCompatibility(Compatibility.TEXTURE_COMPARE)) {
38181        samplerDescriptorGPU.compare = _compareToWebGPU[texture3.compareFunction];
38182      }
38183      const sampler3 = backend.device.createSampler(samplerDescriptorGPU);
38184      samplerData = { sampler: sampler3, usedTimes: 0 };
38185      this._samplerCache.set(samplerKey, samplerData);
38186    }
38187    const textureData = backend.get(texture3);
38188    if (textureData.sampler !== samplerData.sampler) {
38189      if (textureData.sampler !== void 0) {
38190        const oldSamplerData = this._samplerCache.get(textureData.samplerKey);
38191        oldSamplerData.usedTimes--;
38192        if (oldSamplerData.usedTimes === 0) {
38193          this._samplerCache.delete(textureData.samplerKey);
38194        }
38195      }
38196      textureData.samplerKey = samplerKey;
38197      textureData.sampler = samplerData.sampler;
38198      samplerData.usedTimes++;
38199    }
38200    return samplerKey;
38201  }
38202  /**
38203   * Creates a default texture for the given texture that can be used
38204   * as a placeholder until the actual texture is ready for usage.
38205   *
38206   * @param {Texture} texture - The texture to create a default texture for.
38207   */
38208  createDefaultTexture(texture3) {
38209    let textureGPU;
38210    const format = getFormat(texture3, this.backend.device);
38211    if (texture3.isCubeTexture) {
38212      textureGPU = this._getDefaultCubeTextureGPU(format);
38213    } else {
38214      textureGPU = this._getDefaultTextureGPU(format);
38215    }
38216    this.backend.get(texture3).texture = textureGPU;
38217  }
38218  /**
38219   * Defines a texture on the GPU for the given texture object.
38220   *
38221   * @param {Texture} texture - The texture.
38222   * @param {Object} [options={}] - Optional configuration parameter.
38223   */
38224  createTexture(texture3, options = {}) {
38225    const backend = this.backend;
38226    const textureData = backend.get(texture3);
38227    if (textureData.initialized) {
38228      throw new Error("WebGPUTextureUtils: Texture already initialized.");
38229    }
38230    if (texture3.isExternalTexture) {
38231      textureData.texture = texture3.sourceTexture;
38232      textureData.initialized = true;
38233      return;
38234    }
38235    if (options.needsMipmaps === void 0) options.needsMipmaps = false;
38236    if (options.levels === void 0) options.levels = 1;
38237    if (options.depth === void 0) options.depth = 1;
38238    const { width, height, depth: depth3, levels } = options;
38239    if (texture3.isFramebufferTexture) {
38240      if (options.renderTarget) {
38241        options.format = this.backend.utils.getCurrentColorFormat(options.renderTarget);
38242      } else {
38243        options.format = this.backend.utils.getPreferredCanvasFormat();
38244      }
38245    }
38246    const dimension = this._getDimension(texture3);
38247    const format = texture3.internalFormat || options.format || getFormat(texture3, backend.device);
38248    textureData.format = format;
38249    const { samples, primarySamples, isMSAA } = backend.utils.getTextureSampleData(texture3);
38250    let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC;
38251    if (texture3.isStorageTexture === true) {
38252      usage |= GPUTextureUsage.STORAGE_BINDING;
38253    }
38254    if (texture3.isCompressedTexture !== true && texture3.isCompressedArrayTexture !== true && format !== GPUTextureFormat.RGB9E5UFloat) {
38255      usage |= GPUTextureUsage.RENDER_ATTACHMENT;
38256    }
38257    const textureDescriptorGPU = {
38258      label: texture3.name,
38259      size: {
38260        width,
38261        height,
38262        depthOrArrayLayers: depth3
38263      },
38264      mipLevelCount: levels,
38265      sampleCount: primarySamples,
38266      dimension,
38267      format,
38268      usage
38269    };
38270    if (format === void 0) {
38271      warn("WebGPURenderer: Texture format not supported.");
38272      this.createDefaultTexture(texture3);
38273      return;
38274    }
38275    if (texture3.isCubeTexture) {
38276      textureDescriptorGPU.textureBindingViewDimension = GPUTextureViewDimension.Cube;
38277    }
38278    try {
38279      textureData.texture = backend.device.createTexture(textureDescriptorGPU);
38280    } catch (e) {
38281      warn("WebGPURenderer: Failed to create texture with descriptor:", textureDescriptorGPU);
38282      this.createDefaultTexture(texture3);
38283      return;
38284    }
38285    if (isMSAA) {
38286      const msaaTextureDescriptorGPU = Object.assign({}, textureDescriptorGPU);
38287      msaaTextureDescriptorGPU.label = msaaTextureDescriptorGPU.label + "-msaa";
38288      msaaTextureDescriptorGPU.sampleCount = samples;
38289      msaaTextureDescriptorGPU.mipLevelCount = 1;
38290      textureData.msaaTexture = backend.device.createTexture(msaaTextureDescriptorGPU);
38291    }
38292    textureData.initialized = true;
38293    textureData.textureDescriptorGPU = textureDescriptorGPU;
38294  }
38295  /**
38296   * Destroys the GPU data for the given texture object.
38297   *
38298   * @param {Texture} texture - The texture.
38299   * @param {boolean} [isDefaultTexture=false] - Whether the texture uses a default GPU texture or not.
38300   */
38301  destroyTexture(texture3, isDefaultTexture = false) {
38302    const backend = this.backend;
38303    const textureData = backend.get(texture3);
38304    if (textureData.texture !== void 0 && isDefaultTexture === false) textureData.texture.destroy();
38305    if (textureData.msaaTexture !== void 0) textureData.msaaTexture.destroy();
38306    backend.delete(texture3);
38307  }
38308  /**
38309   * Generates mipmaps for the given texture.
38310   *
38311   * @param {Texture} texture - The texture.
38312   * @param {?GPUCommandEncoder} [encoder=null] - An optional command encoder used to generate mipmaps.
38313   */
38314  generateMipmaps(texture3, encoder = null) {
38315    const textureData = this.backend.get(texture3);
38316    this._generateMipmaps(textureData.texture, encoder);
38317  }
38318  /**
38319   * Returns the color buffer representing the color
38320   * attachment of the default framebuffer.
38321   *
38322   * @return {GPUTexture} The color buffer.
38323   */
38324  getColorBuffer() {
38325    const backend = this.backend;
38326    const canvasTarget = backend.renderer.getCanvasTarget();
38327    const { width, height } = backend.getDrawingBufferSize();
38328    const samples = backend.renderer.currentSamples;
38329    const colorTexture = canvasTarget.colorTexture;
38330    const colorTextureData = backend.get(colorTexture);
38331    if (colorTexture.width === width && colorTexture.height === height && colorTexture.samples === samples) {
38332      return colorTextureData.texture;
38333    }
38334    let colorBuffer = colorTextureData.texture;
38335    if (colorBuffer) colorBuffer.destroy();
38336    colorBuffer = backend.device.createTexture({
38337      label: "colorBuffer",
38338      size: {
38339        width,
38340        height,
38341        depthOrArrayLayers: 1
38342      },
38343      sampleCount: backend.utils.getSampleCount(backend.renderer.currentSamples),
38344      format: backend.utils.getPreferredCanvasFormat(),
38345      usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC
38346    });
38347    colorTexture.source.width = width;
38348    colorTexture.source.height = height;
38349    colorTexture.samples = samples;
38350    colorTextureData.texture = colorBuffer;
38351    return colorBuffer;
38352  }
38353  /**
38354   * Returns the depth buffer representing the depth
38355   * attachment of the default framebuffer.
38356   *
38357   * @param {boolean} [depth=true] - Whether depth is enabled or not.
38358   * @param {boolean} [stencil=false] -  Whether stencil is enabled or not.
38359   * @return {GPUTexture} The depth buffer.
38360   */
38361  getDepthBuffer(depth3 = true, stencil = false) {
38362    const backend = this.backend;
38363    const canvasTarget = backend.renderer.getCanvasTarget();
38364    const { width, height } = backend.getDrawingBufferSize();
38365    const samples = backend.renderer.currentSamples;
38366    const depthTexture = canvasTarget.depthTexture;
38367    if (depthTexture.width === width && depthTexture.height === height && depthTexture.samples === samples && depthTexture.depth === depth3 && depthTexture.stencil === stencil) {
38368      return backend.get(depthTexture).texture;
38369    }
38370    const depthTextureGPU = backend.get(depthTexture).texture;
38371    let format, type;
38372    if (stencil) {
38373      format = DepthStencilFormat;
38374      type = backend.renderer.reversedDepthBuffer === true ? FloatType : UnsignedInt248Type;
38375    } else if (depth3) {
38376      format = DepthFormat;
38377      type = backend.renderer.reversedDepthBuffer === true ? FloatType : UnsignedIntType;
38378    }
38379    if (depthTextureGPU !== void 0) {
38380      if (depthTexture.image.width === width && depthTexture.image.height === height && depthTexture.format === format && depthTexture.type === type && depthTexture.samples === samples) {
38381        return depthTextureGPU;
38382      }
38383      this.destroyTexture(depthTexture);
38384    }
38385    depthTexture.name = "depthBuffer";
38386    depthTexture.format = format;
38387    depthTexture.type = type;
38388    depthTexture.image.width = width;
38389    depthTexture.image.height = height;
38390    depthTexture.samples = samples;
38391    this.createTexture(depthTexture, { width, height });
38392    return backend.get(depthTexture).texture;
38393  }
38394  /**
38395   * Uploads the updated texture data to the GPU.
38396   *
38397   * @param {Texture} texture - The texture.
38398   * @param {Object} [options={}] - Optional configuration parameter.
38399   */
38400  updateTexture(texture3, options) {
38401    const textureData = this.backend.get(texture3);
38402    const mipmaps = texture3.mipmaps;
38403    const { textureDescriptorGPU } = textureData;
38404    if (texture3.isRenderTargetTexture || textureDescriptorGPU === void 0)
38405      return;
38406    if (texture3.isDataTexture) {
38407      if (mipmaps.length > 0) {
38408        for (let i = 0, il = mipmaps.length; i < il; i++) {
38409          const mipmap = mipmaps[i];
38410          this._copyBufferToTexture(mipmap, textureData.texture, textureDescriptorGPU, 0, texture3.flipY, 0, i);
38411        }
38412      } else {
38413        this._copyBufferToTexture(options.image, textureData.texture, textureDescriptorGPU, 0, texture3.flipY);
38414      }
38415    } else if (texture3.isArrayTexture || texture3.isDataArrayTexture || texture3.isData3DTexture) {
38416      if (texture3.layerUpdates && texture3.layerUpdates.size > 0) {
38417        for (const layerIndex of texture3.layerUpdates) {
38418          this._copyBufferToTexture(options.image, textureData.texture, textureDescriptorGPU, layerIndex, texture3.flipY, layerIndex);
38419        }
38420        texture3.clearLayerUpdates();
38421      } else {
38422        for (let i = 0; i < options.image.depth; i++) {
38423          this._copyBufferToTexture(options.image, textureData.texture, textureDescriptorGPU, i, texture3.flipY, i);
38424        }
38425      }
38426    } else if (texture3.isCompressedTexture || texture3.isCompressedArrayTexture) {
38427      this._copyCompressedBufferToTexture(texture3.mipmaps, textureData.texture, textureDescriptorGPU);
38428    } else if (texture3.isCubeTexture) {
38429      this._copyCubeMapToTexture(texture3, textureData.texture, textureDescriptorGPU);
38430    } else if (texture3.isHTMLTexture) {
38431      const device = this.backend.device;
38432      const canvas = this.backend.renderer.domElement;
38433      const image = texture3.image;
38434      if (typeof device.queue.copyElementImageToTexture !== "function") return;
38435      if (!textureData.hasPaintCallback) {
38436        textureData.hasPaintCallback = true;
38437        canvas.requestPaint();
38438        return;
38439      }
38440      const width = textureDescriptorGPU.size.width;
38441      const height = textureDescriptorGPU.size.height;
38442      device.queue.copyElementImageToTexture(
38443        image,
38444        width,
38445        height,
38446        { texture: textureData.texture }
38447      );
38448      if (texture3.flipY) {
38449        this._flipY(textureData.texture, textureDescriptorGPU);
38450      }
38451    } else {
38452      if (mipmaps.length > 0) {
38453        for (let i = 0, il = mipmaps.length; i < il; i++) {
38454          const mipmap = mipmaps[i];
38455          this._copyImageToTexture(mipmap, textureData.texture, textureDescriptorGPU, 0, texture3.flipY, texture3.premultiplyAlpha, i);
38456        }
38457      } else {
38458        this._copyImageToTexture(options.image, textureData.texture, textureDescriptorGPU, 0, texture3.flipY, texture3.premultiplyAlpha);
38459      }
38460    }
38461    textureData.version = texture3.version;
38462  }
38463  /**
38464   * Returns texture data as a typed array.
38465   *
38466   * @async
38467   * @param {Texture} texture - The texture to copy.
38468   * @param {number} x - The x coordinate of the copy origin.
38469   * @param {number} y - The y coordinate of the copy origin.
38470   * @param {number} width - The width of the copy.
38471   * @param {number} height - The height of the copy.
38472   * @param {number} faceIndex - The face index.
38473   * @return {Promise<TypedArray>} A Promise that resolves with a typed array when the copy operation has finished.
38474   */
38475  async copyTextureToBuffer(texture3, x, y, width, height, faceIndex) {
38476    const device = this.backend.device;
38477    const textureData = this.backend.get(texture3);
38478    const textureGPU = textureData.texture;
38479    const format = textureData.textureDescriptorGPU.format;
38480    const bytesPerTexel = this._getBytesPerTexel(format);
38481    let bytesPerRow = width * bytesPerTexel;
38482    bytesPerRow = Math.ceil(bytesPerRow / 256) * 256;
38483    const readBuffer = device.createBuffer(
38484      {
38485        size: (height - 1) * bytesPerRow + width * bytesPerTexel,
38486        // see https://github.com/mrdoob/three.js/issues/31658#issuecomment-3229442010
38487        usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
38488      }
38489    );
38490    const encoder = device.createCommandEncoder();
38491    encoder.copyTextureToBuffer(
38492      {
38493        texture: textureGPU,
38494        origin: { x, y, z: faceIndex }
38495      },
38496      {
38497        buffer: readBuffer,
38498        bytesPerRow
38499      },
38500      {
38501        width,
38502        height
38503      }
38504    );
38505    const typedArrayType = this._getTypedArrayType(format);
38506    device.queue.submit([encoder.finish()]);
38507    await readBuffer.mapAsync(GPUMapMode.READ);
38508    const buffer3 = readBuffer.getMappedRange().slice();
38509    readBuffer.destroy();
38510    return new typedArrayType(buffer3);
38511  }
38512  /**
38513   * Frees all internal resources.
38514   */
38515  dispose() {
38516    this._samplerCache.clear();
38517  }
38518  /**
38519   * Returns the default GPU texture for the given format.
38520   *
38521   * @private
38522   * @param {string} format - The GPU format.
38523   * @return {GPUTexture} The GPU texture.
38524   */
38525  _getDefaultTextureGPU(format) {
38526    let defaultTexture = this.defaultTexture[format];
38527    if (defaultTexture === void 0) {
38528      const texture3 = new Texture();
38529      texture3.minFilter = NearestFilter;
38530      texture3.magFilter = NearestFilter;
38531      this.createTexture(texture3, { width: 1, height: 1, format });
38532      this.defaultTexture[format] = defaultTexture = texture3;
38533    }
38534    return this.backend.get(defaultTexture).texture;
38535  }
38536  /**
38537   * Returns the default GPU cube texture for the given format.
38538   *
38539   * @private
38540   * @param {string} format - The GPU format.
38541   * @return {GPUTexture} The GPU texture.
38542   */
38543  _getDefaultCubeTextureGPU(format) {
38544    let defaultCubeTexture = this.defaultCubeTexture[format];
38545    if (defaultCubeTexture === void 0) {
38546      const texture3 = new CubeTexture();
38547      texture3.minFilter = NearestFilter;
38548      texture3.magFilter = NearestFilter;
38549      this.createTexture(texture3, { width: 1, height: 1, depth: 6 });
38550      this.defaultCubeTexture[format] = defaultCubeTexture = texture3;
38551    }
38552    return this.backend.get(defaultCubeTexture).texture;
38553  }
38554  /**
38555   * Uploads cube texture image data to the GPU memory.
38556   *
38557   * @private
38558   * @param {CubeTexture} texture - The cube texture.
38559   * @param {GPUTexture} textureGPU - The GPU texture.
38560   * @param {Object} textureDescriptorGPU - The GPU texture descriptor.
38561   */
38562  _copyCubeMapToTexture(texture3, textureGPU, textureDescriptorGPU) {
38563    const images = texture3.images;
38564    const mipmaps = texture3.mipmaps;
38565    for (let i = 0; i < 6; i++) {
38566      const image = images[i];
38567      const flipIndex = texture3.flipY === true ? _flipMap[i] : i;
38568      if (image.isDataTexture) {
38569        this._copyBufferToTexture(image.image, textureGPU, textureDescriptorGPU, flipIndex, texture3.flipY);
38570      } else {
38571        this._copyImageToTexture(image, textureGPU, textureDescriptorGPU, flipIndex, texture3.flipY, texture3.premultiplyAlpha);
38572      }
38573      for (let j = 0; j < mipmaps.length; j++) {
38574        const mipmap = mipmaps[j];
38575        const image2 = mipmap.images[i];
38576        if (image2.isDataTexture) {
38577          this._copyBufferToTexture(image2.image, textureGPU, textureDescriptorGPU, flipIndex, texture3.flipY, 0, j + 1);
38578        } else {
38579          this._copyImageToTexture(image2, textureGPU, textureDescriptorGPU, flipIndex, texture3.flipY, texture3.premultiplyAlpha, j + 1);
38580        }
38581      }
38582    }
38583  }
38584  /**
38585   * Uploads texture image data to the GPU memory.
38586   *
38587   * @private
38588   * @param {HTMLImageElement|ImageBitmap|HTMLCanvasElement} image - The image data.
38589   * @param {GPUTexture} textureGPU - The GPU texture.
38590   * @param {Object} textureDescriptorGPU - The GPU texture descriptor.
38591   * @param {number} originDepth - The origin depth.
38592   * @param {boolean} flipY - Whether to flip texture data along their vertical axis or not.
38593   * @param {boolean} premultiplyAlpha - Whether the texture should have its RGB channels premultiplied by the alpha channel or not.
38594   * @param {number} [mipLevel=0] - The mip level where the data should be copied to.
38595   */
38596  _copyImageToTexture(image, textureGPU, textureDescriptorGPU, originDepth, flipY, premultiplyAlpha3, mipLevel = 0) {
38597    const device = this.backend.device;
38598    const width = mipLevel > 0 ? image.width : textureDescriptorGPU.size.width;
38599    const height = mipLevel > 0 ? image.height : textureDescriptorGPU.size.height;
38600    try {
38601      device.queue.copyExternalImageToTexture(
38602        {
38603          source: image,
38604          flipY
38605        },
38606        {
38607          texture: textureGPU,
38608          mipLevel,
38609          origin: { x: 0, y: 0, z: originDepth },
38610          premultipliedAlpha: premultiplyAlpha3
38611        },
38612        {
38613          width,
38614          height,
38615          depthOrArrayLayers: 1
38616        }
38617      );
38618    } catch (_) {
38619    }
38620  }
38621  /**
38622   * Returns the pass utils singleton.
38623   *
38624   * @private
38625   * @return {WebGPUTexturePassUtils} The utils instance.
38626   */
38627  _getPassUtils() {
38628    let passUtils = this._passUtils;
38629    if (passUtils === null) {
38630      this._passUtils = passUtils = new WebGPUTexturePassUtils(this.backend.device);
38631    }
38632    return passUtils;
38633  }
38634  /**
38635   * Generates mipmaps for the given GPU texture.
38636   *
38637   * @private
38638   * @param {GPUTexture} textureGPU - The GPU texture object.
38639   * @param {?GPUCommandEncoder} [encoder=null] - An optional command encoder used to generate mipmaps.
38640   */
38641  _generateMipmaps(textureGPU, encoder = null) {
38642    this._getPassUtils().generateMipmaps(textureGPU, encoder);
38643  }
38644  /**
38645   * Flip the contents of the given GPU texture along its vertical axis.
38646   *
38647   * @private
38648   * @param {GPUTexture} textureGPU - The GPU texture object.
38649   * @param {Object} textureDescriptorGPU - The texture descriptor.
38650   * @param {number} [originDepth=0] - The origin depth.
38651   */
38652  _flipY(textureGPU, textureDescriptorGPU, originDepth = 0) {
38653    this._getPassUtils().flipY(textureGPU, textureDescriptorGPU, originDepth);
38654  }
38655  /**
38656   * Uploads texture buffer data to the GPU memory.
38657   *
38658   * @private
38659   * @param {Object} image - An object defining the image buffer data.
38660   * @param {GPUTexture} textureGPU - The GPU texture.
38661   * @param {Object} textureDescriptorGPU - The GPU texture descriptor.
38662   * @param {number} originDepth - The origin depth.
38663   * @param {boolean} flipY - Whether to flip texture data along their vertical axis or not.
38664   * @param {number} [depth=0] - The depth offset when copying array or 3D texture data.
38665   * @param {number} [mipLevel=0] - The mip level where the data should be copied to.
38666   */
38667  _copyBufferToTexture(image, textureGPU, textureDescriptorGPU, originDepth, flipY, depth3 = 0, mipLevel = 0) {
38668    const device = this.backend.device;
38669    const data = image.data;
38670    const bytesPerTexel = this._getBytesPerTexel(textureDescriptorGPU.format);
38671    const bytesPerRow = image.width * bytesPerTexel;
38672    device.queue.writeTexture(
38673      {
38674        texture: textureGPU,
38675        mipLevel,
38676        origin: { x: 0, y: 0, z: originDepth }
38677      },
38678      data,
38679      {
38680        offset: image.width * image.height * bytesPerTexel * depth3,
38681        bytesPerRow
38682      },
38683      {
38684        width: image.width,
38685        height: image.height,
38686        depthOrArrayLayers: 1
38687      }
38688    );
38689    if (flipY === true) {
38690      this._flipY(textureGPU, textureDescriptorGPU, originDepth);
38691    }
38692  }
38693  /**
38694   * Uploads compressed texture data to the GPU memory.
38695   *
38696   * @private
38697   * @param {Array<Object>} mipmaps - An array with mipmap data.
38698   * @param {GPUTexture} textureGPU - The GPU texture.
38699   * @param {Object} textureDescriptorGPU - The GPU texture descriptor.
38700   */
38701  _copyCompressedBufferToTexture(mipmaps, textureGPU, textureDescriptorGPU) {
38702    const device = this.backend.device;
38703    const blockData = this._getBlockData(textureDescriptorGPU.format);
38704    const isArrayTexture = textureDescriptorGPU.size.depthOrArrayLayers > 1;
38705    for (let i = 0; i < mipmaps.length; i++) {
38706      const mipmap = mipmaps[i];
38707      const width = mipmap.width;
38708      const height = mipmap.height;
38709      const depth3 = isArrayTexture ? textureDescriptorGPU.size.depthOrArrayLayers : 1;
38710      const bytesPerRow = Math.ceil(width / blockData.width) * blockData.byteLength;
38711      const bytesPerImage = bytesPerRow * Math.ceil(height / blockData.height);
38712      for (let j = 0; j < depth3; j++) {
38713        device.queue.writeTexture(
38714          {
38715            texture: textureGPU,
38716            mipLevel: i,
38717            origin: { x: 0, y: 0, z: j }
38718          },
38719          mipmap.data,
38720          {
38721            offset: j * bytesPerImage,
38722            bytesPerRow,
38723            rowsPerImage: Math.ceil(height / blockData.height)
38724          },
38725          {
38726            width: Math.ceil(width / blockData.width) * blockData.width,
38727            height: Math.ceil(height / blockData.height) * blockData.height,
38728            depthOrArrayLayers: 1
38729          }
38730        );
38731      }
38732    }
38733  }
38734  /**
38735   * This method is only relevant for compressed texture formats. It returns a block
38736   * data descriptor for the given GPU compressed texture format.
38737   *
38738   * @private
38739   * @param {string} format - The GPU compressed texture format.
38740   * @return {Object} The block data descriptor.
38741   */
38742  _getBlockData(format) {
38743    if (format === GPUTextureFormat.BC1RGBAUnorm || format === GPUTextureFormat.BC1RGBAUnormSRGB) return { byteLength: 8, width: 4, height: 4 };
38744    if (format === GPUTextureFormat.BC2RGBAUnorm || format === GPUTextureFormat.BC2RGBAUnormSRGB) return { byteLength: 16, width: 4, height: 4 };
38745    if (format === GPUTextureFormat.BC3RGBAUnorm || format === GPUTextureFormat.BC3RGBAUnormSRGB) return { byteLength: 16, width: 4, height: 4 };
38746    if (format === GPUTextureFormat.BC4RUnorm || format === GPUTextureFormat.BC4RSnorm) return { byteLength: 8, width: 4, height: 4 };
38747    if (format === GPUTextureFormat.BC5RGUnorm || format === GPUTextureFormat.BC5RGSnorm) return { byteLength: 16, width: 4, height: 4 };
38748    if (format === GPUTextureFormat.BC6HRGBUFloat || format === GPUTextureFormat.BC6HRGBFloat) return { byteLength: 16, width: 4, height: 4 };
38749    if (format === GPUTextureFormat.BC7RGBAUnorm || format === GPUTextureFormat.BC7RGBAUnormSRGB) return { byteLength: 16, width: 4, height: 4 };
38750    if (format === GPUTextureFormat.ETC2RGB8Unorm || format === GPUTextureFormat.ETC2RGB8UnormSRGB) return { byteLength: 8, width: 4, height: 4 };
38751    if (format === GPUTextureFormat.ETC2RGB8A1Unorm || format === GPUTextureFormat.ETC2RGB8A1UnormSRGB) return { byteLength: 8, width: 4, height: 4 };
38752    if (format === GPUTextureFormat.ETC2RGBA8Unorm || format === GPUTextureFormat.ETC2RGBA8UnormSRGB) return { byteLength: 16, width: 4, height: 4 };
38753    if (format === GPUTextureFormat.EACR11Unorm) return { byteLength: 8, width: 4, height: 4 };
38754    if (format === GPUTextureFormat.EACR11Snorm) return { byteLength: 8, width: 4, height: 4 };
38755    if (format === GPUTextureFormat.EACRG11Unorm) return { byteLength: 16, width: 4, height: 4 };
38756    if (format === GPUTextureFormat.EACRG11Snorm) return { byteLength: 16, width: 4, height: 4 };
38757    if (format === GPUTextureFormat.ASTC4x4Unorm || format === GPUTextureFormat.ASTC4x4UnormSRGB) return { byteLength: 16, width: 4, height: 4 };
38758    if (format === GPUTextureFormat.ASTC5x4Unorm || format === GPUTextureFormat.ASTC5x4UnormSRGB) return { byteLength: 16, width: 5, height: 4 };
38759    if (format === GPUTextureFormat.ASTC5x5Unorm || format === GPUTextureFormat.ASTC5x5UnormSRGB) return { byteLength: 16, width: 5, height: 5 };
38760    if (format === GPUTextureFormat.ASTC6x5Unorm || format === GPUTextureFormat.ASTC6x5UnormSRGB) return { byteLength: 16, width: 6, height: 5 };
38761    if (format === GPUTextureFormat.ASTC6x6Unorm || format === GPUTextureFormat.ASTC6x6UnormSRGB) return { byteLength: 16, width: 6, height: 6 };
38762    if (format === GPUTextureFormat.ASTC8x5Unorm || format === GPUTextureFormat.ASTC8x5UnormSRGB) return { byteLength: 16, width: 8, height: 5 };
38763    if (format === GPUTextureFormat.ASTC8x6Unorm || format === GPUTextureFormat.ASTC8x6UnormSRGB) return { byteLength: 16, width: 8, height: 6 };
38764    if (format === GPUTextureFormat.ASTC8x8Unorm || format === GPUTextureFormat.ASTC8x8UnormSRGB) return { byteLength: 16, width: 8, height: 8 };
38765    if (format === GPUTextureFormat.ASTC10x5Unorm || format === GPUTextureFormat.ASTC10x5UnormSRGB) return { byteLength: 16, width: 10, height: 5 };
38766    if (format === GPUTextureFormat.ASTC10x6Unorm || format === GPUTextureFormat.ASTC10x6UnormSRGB) return { byteLength: 16, width: 10, height: 6 };
38767    if (format === GPUTextureFormat.ASTC10x8Unorm || format === GPUTextureFormat.ASTC10x8UnormSRGB) return { byteLength: 16, width: 10, height: 8 };
38768    if (format === GPUTextureFormat.ASTC10x10Unorm || format === GPUTextureFormat.ASTC10x10UnormSRGB) return { byteLength: 16, width: 10, height: 10 };
38769    if (format === GPUTextureFormat.ASTC12x10Unorm || format === GPUTextureFormat.ASTC12x10UnormSRGB) return { byteLength: 16, width: 12, height: 10 };
38770    if (format === GPUTextureFormat.ASTC12x12Unorm || format === GPUTextureFormat.ASTC12x12UnormSRGB) return { byteLength: 16, width: 12, height: 12 };
38771  }
38772  /**
38773   * Converts the three.js uv wrapping constants to GPU address mode constants.
38774   *
38775   * @private
38776   * @param {number} value - The three.js constant defining a uv wrapping mode.
38777   * @return {string} The GPU address mode.
38778   */
38779  _convertAddressMode(value) {
38780    let addressMode = GPUAddressMode.ClampToEdge;
38781    if (value === RepeatWrapping) {
38782      addressMode = GPUAddressMode.Repeat;
38783    } else if (value === MirroredRepeatWrapping) {
38784      addressMode = GPUAddressMode.MirrorRepeat;
38785    }
38786    return addressMode;
38787  }
38788  /**
38789   * Converts the three.js filter constants to GPU filter constants.
38790   *
38791   * @private
38792   * @param {number} value - The three.js constant defining a filter mode.
38793   * @return {string} The GPU filter mode.
38794   */
38795  _convertFilterMode(value) {
38796    let filterMode = GPUFilterMode.Linear;
38797    if (value === NearestFilter || value === NearestMipmapNearestFilter || value === NearestMipmapLinearFilter) {
38798      filterMode = GPUFilterMode.Nearest;
38799    }
38800    return filterMode;
38801  }
38802  /**
38803   * Returns the bytes-per-texel value for the given GPU texture format.
38804   *
38805   * @private
38806   * @param {string} format - The GPU texture format.
38807   * @return {number} The bytes-per-texel.
38808   */
38809  _getBytesPerTexel(format) {
38810    if (format === GPUTextureFormat.R8Unorm || format === GPUTextureFormat.R8Snorm || format === GPUTextureFormat.R8Uint || format === GPUTextureFormat.R8Sint) return 1;
38811    if (format === GPUTextureFormat.R16Uint || format === GPUTextureFormat.R16Sint || format === GPUTextureFormat.R16Float || format === GPUTextureFormat.RG8Unorm || format === GPUTextureFormat.RG8Snorm || format === GPUTextureFormat.RG8Uint || format === GPUTextureFormat.RG8Sint || format === GPUTextureFormat.R16Unorm || format === GPUTextureFormat.R16Snorm) return 2;
38812    if (format === GPUTextureFormat.R32Uint || format === GPUTextureFormat.R32Sint || format === GPUTextureFormat.R32Float || format === GPUTextureFormat.RG16Uint || format === GPUTextureFormat.RG16Sint || format === GPUTextureFormat.RG16Float || format === GPUTextureFormat.RGBA8Unorm || format === GPUTextureFormat.RGBA8UnormSRGB || format === GPUTextureFormat.RGBA8Snorm || format === GPUTextureFormat.RGBA8Uint || format === GPUTextureFormat.RGBA8Sint || format === GPUTextureFormat.BGRA8Unorm || format === GPUTextureFormat.BGRA8UnormSRGB || format === GPUTextureFormat.RG16Unorm || format === GPUTextureFormat.RG16Snorm || // Packed 32-bit formats
38813    format === GPUTextureFormat.RGB9E5UFloat || format === GPUTextureFormat.RGB10A2Unorm || format === GPUTextureFormat.RG11B10UFloat || format === GPUTextureFormat.Depth32Float || format === GPUTextureFormat.Depth24Plus || format === GPUTextureFormat.Depth24PlusStencil8 || format === GPUTextureFormat.Depth32FloatStencil8) return 4;
38814    if (format === GPUTextureFormat.RG32Uint || format === GPUTextureFormat.RG32Sint || format === GPUTextureFormat.RG32Float || format === GPUTextureFormat.RGBA16Uint || format === GPUTextureFormat.RGBA16Sint || format === GPUTextureFormat.RGBA16Float || format === GPUTextureFormat.RGBA16Unorm || format === GPUTextureFormat.RGBA16Snorm) return 8;
38815    if (format === GPUTextureFormat.RGBA32Uint || format === GPUTextureFormat.RGBA32Sint || format === GPUTextureFormat.RGBA32Float) return 16;
38816  }
38817  /**
38818   * Returns the corresponding typed array type for the given GPU texture format.
38819   *
38820   * @private
38821   * @param {string} format - The GPU texture format.
38822   * @return {TypedArray.constructor} The typed array type.
38823   */
38824  _getTypedArrayType(format) {
38825    if (format === GPUTextureFormat.R8Uint) return Uint8Array;
38826    if (format === GPUTextureFormat.R8Sint) return Int8Array;
38827    if (format === GPUTextureFormat.R8Unorm) return Uint8Array;
38828    if (format === GPUTextureFormat.R8Snorm) return Int8Array;
38829    if (format === GPUTextureFormat.RG8Uint) return Uint8Array;
38830    if (format === GPUTextureFormat.RG8Sint) return Int8Array;
38831    if (format === GPUTextureFormat.RG8Unorm) return Uint8Array;
38832    if (format === GPUTextureFormat.RG8Snorm) return Int8Array;
38833    if (format === GPUTextureFormat.RGBA8Uint) return Uint8Array;
38834    if (format === GPUTextureFormat.RGBA8Sint) return Int8Array;
38835    if (format === GPUTextureFormat.RGBA8Unorm || format === GPUTextureFormat.RGBA8UnormSRGB) return Uint8Array;
38836    if (format === GPUTextureFormat.RGBA8Snorm) return Int8Array;
38837    if (format === GPUTextureFormat.R16Uint) return Uint16Array;
38838    if (format === GPUTextureFormat.R16Sint) return Int16Array;
38839    if (format === GPUTextureFormat.RG16Uint) return Uint16Array;
38840    if (format === GPUTextureFormat.RG16Sint) return Int16Array;
38841    if (format === GPUTextureFormat.RGBA16Uint) return Uint16Array;
38842    if (format === GPUTextureFormat.RGBA16Sint) return Int16Array;
38843    if (format === GPUTextureFormat.R16Float) return Uint16Array;
38844    if (format === GPUTextureFormat.RG16Float) return Uint16Array;
38845    if (format === GPUTextureFormat.RGBA16Float) return Uint16Array;
38846    if (format === GPUTextureFormat.R16Unorm) return Uint16Array;
38847    if (format === GPUTextureFormat.R16Snorm) return Int16Array;
38848    if (format === GPUTextureFormat.RG16Unorm) return Uint16Array;
38849    if (format === GPUTextureFormat.RG16Snorm) return Int16Array;
38850    if (format === GPUTextureFormat.RGBA16Unorm) return Uint16Array;
38851    if (format === GPUTextureFormat.RGBA16Snorm) return Int16Array;
38852    if (format === GPUTextureFormat.R32Uint) return Uint32Array;
38853    if (format === GPUTextureFormat.R32Sint) return Int32Array;
38854    if (format === GPUTextureFormat.R32Float) return Float32Array;
38855    if (format === GPUTextureFormat.RG32Uint) return Uint32Array;
38856    if (format === GPUTextureFormat.RG32Sint) return Int32Array;
38857    if (format === GPUTextureFormat.RG32Float) return Float32Array;
38858    if (format === GPUTextureFormat.RGBA32Uint) return Uint32Array;
38859    if (format === GPUTextureFormat.RGBA32Sint) return Int32Array;
38860    if (format === GPUTextureFormat.RGBA32Float) return Float32Array;
38861    if (format === GPUTextureFormat.BGRA8Unorm || format === GPUTextureFormat.BGRA8UnormSRGB) return Uint8Array;
38862    if (format === GPUTextureFormat.RGB10A2Unorm) return Uint32Array;
38863    if (format === GPUTextureFormat.RGB9E5UFloat) return Uint32Array;
38864    if (format === GPUTextureFormat.RG11B10UFloat) return Uint32Array;
38865    if (format === GPUTextureFormat.Depth32Float) return Float32Array;
38866    if (format === GPUTextureFormat.Depth24Plus) return Uint32Array;
38867    if (format === GPUTextureFormat.Depth24PlusStencil8) return Uint32Array;
38868    if (format === GPUTextureFormat.Depth32FloatStencil8) return Float32Array;
38869  }
38870  /**
38871   * Returns the GPU dimensions for the given texture.
38872   *
38873   * @private
38874   * @param {Texture} texture - The texture.
38875   * @return {string} The GPU dimension.
38876   */
38877  _getDimension(texture3) {
38878    let dimension;
38879    if (texture3.is3DTexture || texture3.isData3DTexture) {
38880      dimension = GPUTextureDimension.ThreeD;
38881    } else {
38882      dimension = GPUTextureDimension.TwoD;
38883    }
38884    return dimension;
38885  }
38886};
38887function getFormat(texture3, device) {
38888  const format = texture3.format;
38889  const type = texture3.type;
38890  const normalized = texture3.normalized;
38891  const colorSpace = texture3.colorSpace;
38892  const transfer = ColorManagement.getTransfer(colorSpace);
38893  let formatGPU;
38894  let textureFormatsTier1 = false;
38895  if (normalized) {
38896    textureFormatsTier1 = device.features.has(GPUFeatureName.TextureFormatsTier1);
38897    if (textureFormatsTier1 === false) {
38898      warn("WebGPURenderer: Unable to use normalized textures without texture-formats-tier1 feature.");
38899    }
38900  }
38901  if (texture3.isCompressedTexture === true || texture3.isCompressedArrayTexture === true) {
38902    switch (format) {
38903      case RGB_S3TC_DXT1_Format:
38904      case RGBA_S3TC_DXT1_Format:
38905        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.BC1RGBAUnormSRGB : GPUTextureFormat.BC1RGBAUnorm;
38906        break;
38907      case RGBA_S3TC_DXT3_Format:
38908        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.BC2RGBAUnormSRGB : GPUTextureFormat.BC2RGBAUnorm;
38909        break;
38910      case RGBA_S3TC_DXT5_Format:
38911        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.BC3RGBAUnormSRGB : GPUTextureFormat.BC3RGBAUnorm;
38912        break;
38913      case RED_RGTC1_Format:
38914        formatGPU = GPUTextureFormat.BC4RUnorm;
38915        break;
38916      case SIGNED_RED_RGTC1_Format:
38917        formatGPU = GPUTextureFormat.BC4RSnorm;
38918        break;
38919      case RED_GREEN_RGTC2_Format:
38920        formatGPU = GPUTextureFormat.BC5RGUnorm;
38921        break;
38922      case SIGNED_RED_GREEN_RGTC2_Format:
38923        formatGPU = GPUTextureFormat.BC5RGSnorm;
38924        break;
38925      case RGBA_BPTC_Format:
38926        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.BC7RGBAUnormSRGB : GPUTextureFormat.BC7RGBAUnorm;
38927        break;
38928      case RGB_ETC2_Format:
38929      case RGB_ETC1_Format:
38930        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ETC2RGB8UnormSRGB : GPUTextureFormat.ETC2RGB8Unorm;
38931        break;
38932      case RGBA_ETC2_EAC_Format:
38933        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ETC2RGBA8UnormSRGB : GPUTextureFormat.ETC2RGBA8Unorm;
38934        break;
38935      case R11_EAC_Format:
38936        formatGPU = GPUTextureFormat.EACR11Unorm;
38937        break;
38938      case SIGNED_R11_EAC_Format:
38939        formatGPU = GPUTextureFormat.EACR11Snorm;
38940        break;
38941      case RG11_EAC_Format:
38942        formatGPU = GPUTextureFormat.EACRG11Unorm;
38943        break;
38944      case SIGNED_RG11_EAC_Format:
38945        formatGPU = GPUTextureFormat.EACRG11Snorm;
38946        break;
38947      case RGBA_ASTC_4x4_Format:
38948        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC4x4UnormSRGB : GPUTextureFormat.ASTC4x4Unorm;
38949        break;
38950      case RGBA_ASTC_5x4_Format:
38951        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC5x4UnormSRGB : GPUTextureFormat.ASTC5x4Unorm;
38952        break;
38953      case RGBA_ASTC_5x5_Format:
38954        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC5x5UnormSRGB : GPUTextureFormat.ASTC5x5Unorm;
38955        break;
38956      case RGBA_ASTC_6x5_Format:
38957        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC6x5UnormSRGB : GPUTextureFormat.ASTC6x5Unorm;
38958        break;
38959      case RGBA_ASTC_6x6_Format:
38960        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC6x6UnormSRGB : GPUTextureFormat.ASTC6x6Unorm;
38961        break;
38962      case RGBA_ASTC_8x5_Format:
38963        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC8x5UnormSRGB : GPUTextureFormat.ASTC8x5Unorm;
38964        break;
38965      case RGBA_ASTC_8x6_Format:
38966        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC8x6UnormSRGB : GPUTextureFormat.ASTC8x6Unorm;
38967        break;
38968      case RGBA_ASTC_8x8_Format:
38969        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC8x8UnormSRGB : GPUTextureFormat.ASTC8x8Unorm;
38970        break;
38971      case RGBA_ASTC_10x5_Format:
38972        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC10x5UnormSRGB : GPUTextureFormat.ASTC10x5Unorm;
38973        break;
38974      case RGBA_ASTC_10x6_Format:
38975        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC10x6UnormSRGB : GPUTextureFormat.ASTC10x6Unorm;
38976        break;
38977      case RGBA_ASTC_10x8_Format:
38978        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC10x8UnormSRGB : GPUTextureFormat.ASTC10x8Unorm;
38979        break;
38980      case RGBA_ASTC_10x10_Format:
38981        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC10x10UnormSRGB : GPUTextureFormat.ASTC10x10Unorm;
38982        break;
38983      case RGBA_ASTC_12x10_Format:
38984        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC12x10UnormSRGB : GPUTextureFormat.ASTC12x10Unorm;
38985        break;
38986      case RGBA_ASTC_12x12_Format:
38987        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.ASTC12x12UnormSRGB : GPUTextureFormat.ASTC12x12Unorm;
38988        break;
38989      case RGBAFormat:
38990        formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm;
38991        break;
38992      default:
38993        error("WebGPURenderer: Unsupported texture format.", format);
38994    }
38995  } else {
38996    switch (format) {
38997      case RGBAFormat:
38998        switch (type) {
38999          case ByteType:
39000            formatGPU = GPUTextureFormat.RGBA8Snorm;
39001            break;
39002          case ShortType:
39003            formatGPU = textureFormatsTier1 ? GPUTextureFormat.RGBA16Snorm : GPUTextureFormat.RGBA16Sint;
39004            break;
39005          case UnsignedShortType:
39006            formatGPU = textureFormatsTier1 ? GPUTextureFormat.RGBA16Unorm : GPUTextureFormat.RGBA16Uint;
39007            break;
39008          case UnsignedIntType:
39009            formatGPU = GPUTextureFormat.RGBA32Uint;
39010            break;
39011          case IntType:
39012            formatGPU = GPUTextureFormat.RGBA32Sint;
39013            break;
39014          case UnsignedByteType:
39015            formatGPU = transfer === SRGBTransfer ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm;
39016            break;
39017          case HalfFloatType:
39018            formatGPU = GPUTextureFormat.RGBA16Float;
39019            break;
39020          case FloatType:
39021            formatGPU = GPUTextureFormat.RGBA32Float;
39022            break;
39023          default:
39024            error("WebGPURenderer: Unsupported texture type with RGBAFormat.", type);
39025        }
39026        break;
39027      case RGBFormat:
39028        switch (type) {
39029          case UnsignedInt5999Type:
39030            formatGPU = GPUTextureFormat.RGB9E5UFloat;
39031            break;
39032          case UnsignedInt101111Type:
39033            formatGPU = GPUTextureFormat.RG11B10UFloat;
39034            break;
39035          default:
39036            error("WebGPURenderer: Unsupported texture type with RGBFormat.", type);
39037        }
39038        break;
39039      case RedFormat:
39040        switch (type) {
39041          case ByteType:
39042            formatGPU = GPUTextureFormat.R8Snorm;
39043            break;
39044          case ShortType:
39045            formatGPU = textureFormatsTier1 ? GPUTextureFormat.R16Snorm : GPUTextureFormat.R16Sint;
39046            break;
39047          case UnsignedShortType:
39048            formatGPU = textureFormatsTier1 ? GPUTextureFormat.R16Unorm : GPUTextureFormat.R16Uint;
39049            break;
39050          case UnsignedIntType:
39051            formatGPU = GPUTextureFormat.R32Uint;
39052            break;
39053          case IntType:
39054            formatGPU = GPUTextureFormat.R32Sint;
39055            break;
39056          case UnsignedByteType:
39057            formatGPU = GPUTextureFormat.R8Unorm;
39058            break;
39059          case HalfFloatType:
39060            formatGPU = GPUTextureFormat.R16Float;
39061            break;
39062          case FloatType:
39063            formatGPU = GPUTextureFormat.R32Float;
39064            break;
39065          default:
39066            error("WebGPURenderer: Unsupported texture type with RedFormat.", type);
39067        }
39068        break;
39069      case RGFormat:
39070        switch (type) {
39071          case ByteType:
39072            formatGPU = GPUTextureFormat.RG8Snorm;
39073            break;
39074          case ShortType:
39075            formatGPU = textureFormatsTier1 ? GPUTextureFormat.RG16Snorm : GPUTextureFormat.RG16Sint;
39076            break;
39077          case UnsignedShortType:
39078            formatGPU = textureFormatsTier1 ? GPUTextureFormat.RG16Unorm : GPUTextureFormat.RG16Uint;
39079            break;
39080          case UnsignedIntType:
39081            formatGPU = GPUTextureFormat.RG32Uint;
39082            break;
39083          case IntType:
39084            formatGPU = GPUTextureFormat.RG32Sint;
39085            break;
39086          case UnsignedByteType:
39087            formatGPU = GPUTextureFormat.RG8Unorm;
39088            break;
39089          case HalfFloatType:
39090            formatGPU = GPUTextureFormat.RG16Float;
39091            break;
39092          case FloatType:
39093            formatGPU = GPUTextureFormat.RG32Float;
39094            break;
39095          default:
39096            error("WebGPURenderer: Unsupported texture type with RGFormat.", type);
39097        }
39098        break;
39099      case DepthFormat:
39100        switch (type) {
39101          case UnsignedShortType:
39102            formatGPU = GPUTextureFormat.Depth16Unorm;
39103            break;
39104          case UnsignedIntType:
39105            formatGPU = GPUTextureFormat.Depth24Plus;
39106            break;
39107          case FloatType:
39108            formatGPU = GPUTextureFormat.Depth32Float;
39109            break;
39110          default:
39111            error("WebGPURenderer: Unsupported texture type with DepthFormat.", type);
39112        }
39113        break;
39114      case DepthStencilFormat:
39115        switch (type) {
39116          case UnsignedInt248Type:
39117            formatGPU = GPUTextureFormat.Depth24PlusStencil8;
39118            break;
39119          case FloatType:
39120            if (device && device.features.has(GPUFeatureName.Depth32FloatStencil8) === false) {
39121              error('WebGPURenderer: Depth textures with DepthStencilFormat + FloatType can only be used with the "depth32float-stencil8" GPU feature.');
39122            }
39123            formatGPU = GPUTextureFormat.Depth32FloatStencil8;
39124            break;
39125          default:
39126            error("WebGPURenderer: Unsupported texture type with DepthStencilFormat.", type);
39127        }
39128        break;
39129      case RedIntegerFormat:
39130        switch (type) {
39131          case IntType:
39132            formatGPU = GPUTextureFormat.R32Sint;
39133            break;
39134          case UnsignedIntType:
39135            formatGPU = GPUTextureFormat.R32Uint;
39136            break;
39137          default:
39138            error("WebGPURenderer: Unsupported texture type with RedIntegerFormat.", type);
39139        }
39140        break;
39141      case RGIntegerFormat:
39142        switch (type) {
39143          case IntType:
39144            formatGPU = GPUTextureFormat.RG32Sint;
39145            break;
39146          case UnsignedIntType:
39147            formatGPU = GPUTextureFormat.RG32Uint;
39148            break;
39149          default:
39150            error("WebGPURenderer: Unsupported texture type with RGIntegerFormat.", type);
39151        }
39152        break;
39153      case RGBAIntegerFormat:
39154        switch (type) {
39155          case IntType:
39156            formatGPU = GPUTextureFormat.RGBA32Sint;
39157            break;
39158          case UnsignedIntType:
39159            formatGPU = GPUTextureFormat.RGBA32Uint;
39160            break;
39161          default:
39162            error("WebGPURenderer: Unsupported texture type with RGBAIntegerFormat.", type);
39163        }
39164        break;
39165      default:
39166        error("WebGPURenderer: Unsupported texture format.", format);
39167    }
39168  }
39169  return formatGPU;
39170}
39171var declarationRegexp = /^[fn]*\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)\s*[\-\>]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i;
39172var propertiesRegexp = /([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/ig;
39173var wgslTypeLib$1 = {
39174  "f32": "float",
39175  "i32": "int",
39176  "u32": "uint",
39177  "bool": "bool",
39178  "vec2<f32>": "vec2",
39179  "vec2<i32>": "ivec2",
39180  "vec2<u32>": "uvec2",
39181  "vec2<bool>": "bvec2",
39182  "vec2f": "vec2",
39183  "vec2i": "ivec2",
39184  "vec2u": "uvec2",
39185  "vec2b": "bvec2",
39186  "vec3<f32>": "vec3",
39187  "vec3<i32>": "ivec3",
39188  "vec3<u32>": "uvec3",
39189  "vec3<bool>": "bvec3",
39190  "vec3f": "vec3",
39191  "vec3i": "ivec3",
39192  "vec3u": "uvec3",
39193  "vec3b": "bvec3",
39194  "vec4<f32>": "vec4",
39195  "vec4<i32>": "ivec4",
39196  "vec4<u32>": "uvec4",
39197  "vec4<bool>": "bvec4",
39198  "vec4f": "vec4",
39199  "vec4i": "ivec4",
39200  "vec4u": "uvec4",
39201  "vec4b": "bvec4",
39202  "mat2x2<f32>": "mat2",
39203  "mat2x2f": "mat2",
39204  "mat3x3<f32>": "mat3",
39205  "mat3x3f": "mat3",
39206  "mat4x4<f32>": "mat4",
39207  "mat4x4f": "mat4",
39208  "sampler": "sampler",
39209  "texture_1d": "texture",
39210  "texture_2d": "texture",
39211  "texture_2d_array": "texture",
39212  "texture_multisampled_2d": "cubeTexture",
39213  "texture_depth_2d": "depthTexture",
39214  "texture_depth_2d_array": "depthTexture",
39215  "texture_depth_multisampled_2d": "depthTexture",
39216  "texture_depth_cube": "depthTexture",
39217  "texture_depth_cube_array": "depthTexture",
39218  "texture_3d": "texture3D",
39219  "texture_cube": "cubeTexture",
39220  "texture_cube_array": "cubeTexture",
39221  "texture_storage_1d": "storageTexture",
39222  "texture_storage_2d": "storageTexture",
39223  "texture_storage_2d_array": "storageTexture",
39224  "texture_storage_3d": "storageTexture"
39225};
39226var parse = (source) => {
39227  source = source.trim();
39228  const declaration = source.match(declarationRegexp);
39229  if (declaration !== null && declaration.length === 4) {
39230    const inputsCode = declaration[2];
39231    const propsMatches = [];
39232    let match = null;
39233    while ((match = propertiesRegexp.exec(inputsCode)) !== null) {
39234      propsMatches.push({ name: match[1], type: match[2] });
39235    }
39236    const inputs = [];
39237    for (let i = 0; i < propsMatches.length; i++) {
39238      const { name: name2, type: type2 } = propsMatches[i];
39239      let resolvedType = type2;
39240      if (resolvedType.startsWith("ptr")) {
39241        resolvedType = "pointer";
39242      } else {
39243        if (resolvedType.startsWith("texture")) {
39244          resolvedType = type2.split("<")[0];
39245        }
39246        resolvedType = wgslTypeLib$1[resolvedType];
39247      }
39248      inputs.push(new NodeFunctionInput(resolvedType, name2));
39249    }
39250    const blockCode = source.substring(declaration[0].length);
39251    const outputType = declaration[3] || "void";
39252    const name = declaration[1] !== void 0 ? declaration[1] : "";
39253    const type = wgslTypeLib$1[outputType] || outputType;
39254    return {
39255      type,
39256      inputs,
39257      name,
39258      inputsCode,
39259      blockCode,
39260      outputType
39261    };
39262  } else {
39263    throw new Error("FunctionNode: Function is not a WGSL code.");
39264  }
39265};
39266var WGSLNodeFunction = class extends NodeFunction {
39267  /**
39268   * Constructs a new WGSL node function.
39269   *
39270   * @param {string} source - The WGSL source.
39271   */
39272  constructor(source) {
39273    const { type, inputs, name, inputsCode, blockCode, outputType } = parse(source);
39274    super(type, inputs, name);
39275    this.inputsCode = inputsCode;
39276    this.blockCode = blockCode;
39277    this.outputType = outputType;
39278  }
39279  /**
39280   * This method returns the WGSL code of the node function.
39281   *
39282   * @param {string} [name=this.name] - The function's name.
39283   * @return {string} The shader code.
39284   */
39285  getCode(name = this.name) {
39286    const outputType = this.outputType !== "void" ? "-> " + this.outputType : "";
39287    return `fn ${name} ( ${this.inputsCode.trim()} ) ${outputType}` + this.blockCode;
39288  }
39289};
39290var WGSLNodeParser = class extends NodeParser {
39291  /**
39292   * The method parses the given WGSL code an returns a node function.
39293   *
39294   * @param {string} source - The WGSL code.
39295   * @return {WGSLNodeFunction} A node function.
39296   */
39297  parseFunction(source) {
39298    return new WGSLNodeFunction(source);
39299  }
39300};
39301var accessNames = {
39302  [NodeAccess.READ_ONLY]: "read",
39303  [NodeAccess.WRITE_ONLY]: "write",
39304  [NodeAccess.READ_WRITE]: "read_write"
39305};
39306var wrapNames = {
39307  [RepeatWrapping]: "repeat",
39308  [ClampToEdgeWrapping]: "clamp",
39309  [MirroredRepeatWrapping]: "mirror"
39310};
39311var gpuShaderStageLib = {
39312  "vertex": GPUShaderStage.VERTEX,
39313  "fragment": GPUShaderStage.FRAGMENT,
39314  "compute": GPUShaderStage.COMPUTE
39315};
39316var supports = {
39317  instance: true,
39318  swizzleAssign: false,
39319  storageBuffer: true
39320};
39321var wgslFnOpLib = {
39322  "^^": "tsl_xor"
39323};
39324var wgslTypeLib = {
39325  float: "f32",
39326  int: "i32",
39327  uint: "u32",
39328  bool: "bool",
39329  color: "vec3<f32>",
39330  vec2: "vec2<f32>",
39331  ivec2: "vec2<i32>",
39332  uvec2: "vec2<u32>",
39333  bvec2: "vec2<bool>",
39334  vec3: "vec3<f32>",
39335  ivec3: "vec3<i32>",
39336  uvec3: "vec3<u32>",
39337  bvec3: "vec3<bool>",
39338  vec4: "vec4<f32>",
39339  ivec4: "vec4<i32>",
39340  uvec4: "vec4<u32>",
39341  bvec4: "vec4<bool>",
39342  mat2: "mat2x2<f32>",
39343  mat3: "mat3x3<f32>",
39344  mat4: "mat4x4<f32>"
39345};
39346var wgslCodeCache = {};
39347var wgslPolyfill = {
39348  tsl_xor: new CodeNode("fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }"),
39349  mod_float: new CodeNode("fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }"),
39350  mod_vec2: new CodeNode("fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }"),
39351  mod_vec3: new CodeNode("fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }"),
39352  mod_vec4: new CodeNode("fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }"),
39353  equals_bool: new CodeNode("fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }"),
39354  equals_bvec2: new CodeNode("fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2<bool> { return vec2<bool>( a.x == b.x, a.y == b.y ); }"),
39355  equals_bvec3: new CodeNode("fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3<bool> { return vec3<bool>( a.x == b.x, a.y == b.y, a.z == b.z ); }"),
39356  equals_bvec4: new CodeNode("fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4<bool> { return vec4<bool>( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }"),
39357  repeatWrapping_float: new CodeNode("fn tsl_repeatWrapping_float( coord: f32 ) -> f32 { return fract( coord ); }"),
39358  mirrorWrapping_float: new CodeNode("fn tsl_mirrorWrapping_float( coord: f32 ) -> f32 { let mirrored = fract( coord * 0.5 ) * 2.0; return 1.0 - abs( 1.0 - mirrored ); }"),
39359  clampWrapping_float: new CodeNode("fn tsl_clampWrapping_float( coord: f32 ) -> f32 { return clamp( coord, 0.0, 1.0 ); }"),
39360  biquadraticTexture: new CodeNode(
39361    /* wgsl */
39362    `
39363fn tsl_biquadraticTexture( map : texture_2d<f32>, coord : vec2f, iRes : vec2u, level : u32 ) -> vec4f {
39364
39365	let res = vec2f( iRes );
39366
39367	let uvScaled = coord * res;
39368	let uvWrapping = ( ( uvScaled % res ) + res ) % res;
39369
39370	// https://www.shadertoy.com/view/WtyXRy
39371
39372	let uv = uvWrapping - 0.5;
39373	let iuv = floor( uv );
39374	let f = fract( uv );
39375
39376	let rg1 = textureLoad( map, vec2u( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );
39377	let rg2 = textureLoad( map, vec2u( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );
39378	let rg3 = textureLoad( map, vec2u( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );
39379	let rg4 = textureLoad( map, vec2u( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );
39380
39381	return mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );
39382
39383}
39384`
39385  ),
39386  biquadraticTextureArray: new CodeNode(
39387    /* wgsl */
39388    `
39389fn tsl_biquadraticTexture_array( map : texture_2d_array<f32>, coord : vec2f, iRes : vec2u, layer : u32, level : u32 ) -> vec4f {
39390
39391	let res = vec2f( iRes );
39392
39393	let uvScaled = coord * res;
39394	let uvWrapping = ( ( uvScaled % res ) + res ) % res;
39395
39396	// https://www.shadertoy.com/view/WtyXRy
39397
39398	let uv = uvWrapping - 0.5;
39399	let iuv = floor( uv );
39400	let f = fract( uv );
39401
39402	let rg1 = textureLoad( map, vec2u( iuv + vec2( 0.5, 0.5 ) ) % iRes, layer, level );
39403	let rg2 = textureLoad( map, vec2u( iuv + vec2( 1.5, 0.5 ) ) % iRes, layer, level );
39404	let rg3 = textureLoad( map, vec2u( iuv + vec2( 0.5, 1.5 ) ) % iRes, layer, level );
39405	let rg4 = textureLoad( map, vec2u( iuv + vec2( 1.5, 1.5 ) ) % iRes, layer, level );
39406
39407	return mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );
39408
39409}
39410`
39411  )
39412};
39413var wgslMethods = {
39414  dFdx: "dpdx",
39415  dFdy: "- dpdy",
39416  mod_float: "tsl_mod_float",
39417  mod_vec2: "tsl_mod_vec2",
39418  mod_vec3: "tsl_mod_vec3",
39419  mod_vec4: "tsl_mod_vec4",
39420  equals_bool: "tsl_equals_bool",
39421  equals_bvec2: "tsl_equals_bvec2",
39422  equals_bvec3: "tsl_equals_bvec3",
39423  equals_bvec4: "tsl_equals_bvec4",
39424  inversesqrt: "inverseSqrt",
39425  bitcast: "bitcast<f32>",
39426  floatpack_snorm_2x16: "pack2x16snorm",
39427  floatpack_unorm_2x16: "pack2x16unorm",
39428  floatpack_float16_2x16: "pack2x16float",
39429  floatunpack_snorm_2x16: "unpack2x16snorm",
39430  floatunpack_unorm_2x16: "unpack2x16unorm",
39431  floatunpack_float16_2x16: "unpack2x16float"
39432};
39433var diagnostics = "";
39434if ((typeof navigator !== "undefined" && /Firefox|Deno/g.test(navigator.userAgent)) !== true) {
39435  diagnostics += "diagnostic( off, derivative_uniformity );\n";
39436}
39437var WGSLNodeBuilder = class extends NodeBuilder {
39438  /**
39439   * Constructs a new WGSL node builder renderer.
39440   *
39441   * @param {Object3D} object - The 3D object.
39442   * @param {Renderer} renderer - The renderer.
39443   */
39444  constructor(object, renderer) {
39445    super(object, renderer, new WGSLNodeParser());
39446    this.uniformGroups = {};
39447    this.uniformGroupsBindings = {};
39448    this.builtins = {};
39449    this.directives = {};
39450    this.scopedArrays = /* @__PURE__ */ new Map();
39451    this.allowEarlyReturns = true;
39452    this.allowGlobalVariables = true;
39453  }
39454  /**
39455   * Generates the WGSL snippet for sampled textures.
39456   *
39457   * @private
39458   * @param {Texture} texture - The texture.
39459   * @param {string} textureProperty - The name of the texture uniform in the shader.
39460   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39461   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39462   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39463   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
39464   * @return {string} The WGSL snippet.
39465   */
39466  _generateTextureSample(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet, shaderStage = this.shaderStage) {
39467    if (shaderStage === "fragment") {
39468      if (depthSnippet) {
39469        if (offsetSnippet) {
39470          return `textureSample( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${offsetSnippet} )`;
39471        }
39472        return `textureSample( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet} )`;
39473      } else {
39474        if (offsetSnippet) {
39475          return `textureSample( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${offsetSnippet} )`;
39476        }
39477        return `textureSample( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet} )`;
39478      }
39479    } else {
39480      return this.generateTextureSampleLevel(texture3, textureProperty, uvSnippet, "0", depthSnippet);
39481    }
39482  }
39483  /**
39484   * Generates the WGSL snippet when sampling textures with explicit mip level.
39485   *
39486   * @private
39487   * @param {Texture} texture - The texture.
39488   * @param {string} textureProperty - The name of the texture uniform in the shader.
39489   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39490   * @param {string} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
39491   * @param {string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39492   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39493   * @return {string} The WGSL snippet.
39494   */
39495  generateTextureSampleLevel(texture3, textureProperty, uvSnippet, levelSnippet, depthSnippet, offsetSnippet) {
39496    if (this.isUnfilterable(texture3) === false) {
39497      if (depthSnippet) {
39498        if (offsetSnippet) {
39499          return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${levelSnippet}, ${offsetSnippet} )`;
39500        }
39501        return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${levelSnippet} )`;
39502      } else {
39503        if (offsetSnippet) {
39504          return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${levelSnippet}, ${offsetSnippet} )`;
39505        }
39506        return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${levelSnippet} )`;
39507      }
39508    } else if (this.isFilteredTexture(texture3)) {
39509      return this.generateFilteredTexture(texture3, textureProperty, uvSnippet, offsetSnippet, levelSnippet, depthSnippet);
39510    } else {
39511      return this.generateTextureLod(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet, levelSnippet);
39512    }
39513  }
39514  /**
39515   * Generates a wrap function used in context of textures.
39516   *
39517   * @param {Texture} texture - The texture to generate the function for.
39518   * @return {string} The name of the generated function.
39519   */
39520  generateWrapFunction(texture3) {
39521    const functionName = `tsl_coord_${wrapNames[texture3.wrapS]}S_${wrapNames[texture3.wrapT]}_${texture3.is3DTexture || texture3.isData3DTexture ? "3d" : "2d"}T`;
39522    let nodeCode = wgslCodeCache[functionName];
39523    if (nodeCode === void 0) {
39524      const includes = [];
39525      const coordType = texture3.is3DTexture || texture3.isData3DTexture ? "vec3f" : "vec2f";
39526      let code3 = `fn ${functionName}( coord : ${coordType} ) -> ${coordType} {
39527
39528	return ${coordType}(
39529`;
39530      const addWrapSnippet = (wrap, axis) => {
39531        if (wrap === RepeatWrapping) {
39532          includes.push(wgslPolyfill.repeatWrapping_float);
39533          code3 += `		tsl_repeatWrapping_float( coord.${axis} )`;
39534        } else if (wrap === ClampToEdgeWrapping) {
39535          includes.push(wgslPolyfill.clampWrapping_float);
39536          code3 += `		tsl_clampWrapping_float( coord.${axis} )`;
39537        } else if (wrap === MirroredRepeatWrapping) {
39538          includes.push(wgslPolyfill.mirrorWrapping_float);
39539          code3 += `		tsl_mirrorWrapping_float( coord.${axis} )`;
39540        } else {
39541          code3 += `		coord.${axis}`;
39542          warn(`WebGPURenderer: Unsupported texture wrap type "${wrap}" for vertex shader.`);
39543        }
39544      };
39545      addWrapSnippet(texture3.wrapS, "x");
39546      code3 += ",\n";
39547      addWrapSnippet(texture3.wrapT, "y");
39548      if (texture3.is3DTexture || texture3.isData3DTexture) {
39549        code3 += ",\n";
39550        addWrapSnippet(texture3.wrapR, "z");
39551      }
39552      code3 += "\n	);\n\n}\n";
39553      wgslCodeCache[functionName] = nodeCode = new CodeNode(code3, includes);
39554    }
39555    nodeCode.build(this);
39556    return functionName;
39557  }
39558  /**
39559   * Generates the array declaration string.
39560   *
39561   * @param {string} type - The type.
39562   * @param {?number} [count] - The count.
39563   * @return {string} The generated value as a shader string.
39564   */
39565  generateArrayDeclaration(type, count) {
39566    return `array< ${this.getType(type)}, ${count} >`;
39567  }
39568  /**
39569   * Generates a WGSL variable that holds the texture dimension of the given texture.
39570   * It also returns information about the number of layers (elements) of an arrayed
39571   * texture as well as the cube face count of cube textures.
39572   *
39573   * @param {Texture} texture - The texture to generate the function for.
39574   * @param {string} textureProperty - The name of the video texture uniform in the shader.
39575   * @param {string} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
39576   * @return {string} The name of the dimension variable.
39577   */
39578  generateTextureDimension(texture3, textureProperty, levelSnippet) {
39579    const textureData = this.getDataFromNode(texture3, this.shaderStage, this.cache);
39580    if (textureData.dimensionsSnippet === void 0) textureData.dimensionsSnippet = {};
39581    let textureDimensionNode = textureData.dimensionsSnippet[levelSnippet];
39582    if (textureData.dimensionsSnippet[levelSnippet] === void 0) {
39583      let textureDimensionsParams;
39584      let dimensionType;
39585      const { primarySamples } = this.renderer.backend.utils.getTextureSampleData(texture3);
39586      const isMultisampled = primarySamples > 1;
39587      if (texture3.is3DTexture || texture3.isData3DTexture) {
39588        dimensionType = "vec3<u32>";
39589      } else {
39590        dimensionType = "vec2<u32>";
39591      }
39592      if (isMultisampled || texture3.isStorageTexture) {
39593        textureDimensionsParams = textureProperty;
39594      } else {
39595        textureDimensionsParams = `${textureProperty}${levelSnippet ? `, u32( ${levelSnippet} )` : ""}`;
39596      }
39597      textureDimensionNode = new VarNode(new ExpressionNode(`textureDimensions( ${textureDimensionsParams} )`, dimensionType));
39598      textureData.dimensionsSnippet[levelSnippet] = textureDimensionNode;
39599      if (texture3.isArrayTexture || texture3.isDataArrayTexture || texture3.is3DTexture || texture3.isData3DTexture) {
39600        textureData.arrayLayerCount = new VarNode(
39601          new ExpressionNode(
39602            `textureNumLayers(${textureProperty})`,
39603            "u32"
39604          )
39605        );
39606      }
39607      if (texture3.isTextureCube) {
39608        textureData.cubeFaceCount = new VarNode(
39609          new ExpressionNode("6u", "u32")
39610        );
39611      }
39612    }
39613    return textureDimensionNode.build(this);
39614  }
39615  /**
39616   * Generates the WGSL snippet for a manual filtered texture.
39617   *
39618   * @param {Texture} texture - The texture.
39619   * @param {string} textureProperty - The name of the texture uniform in the shader.
39620   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39621   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39622   * @param {string} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
39623   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39624   * @return {string} The WGSL snippet.
39625   */
39626  generateFilteredTexture(texture3, textureProperty, uvSnippet, offsetSnippet, levelSnippet = "0u", depthSnippet) {
39627    const wrapFunction = this.generateWrapFunction(texture3);
39628    const textureDimension = this.generateTextureDimension(texture3, textureProperty, levelSnippet);
39629    if (offsetSnippet) {
39630      uvSnippet = `${uvSnippet} + vec2<f32>(${offsetSnippet}) / ${textureDimension}`;
39631    }
39632    if (depthSnippet) {
39633      this._include("biquadraticTextureArray");
39634      return `tsl_biquadraticTexture_array( ${textureProperty}, ${wrapFunction}( ${uvSnippet} ), ${textureDimension}, u32( ${depthSnippet} ), u32( ${levelSnippet} ) )`;
39635    }
39636    this._include("biquadraticTexture");
39637    return `tsl_biquadraticTexture( ${textureProperty}, ${wrapFunction}( ${uvSnippet} ), ${textureDimension}, u32( ${levelSnippet} ) )`;
39638  }
39639  /**
39640   * Generates the WGSL snippet for a texture lookup with explicit level-of-detail.
39641   * Since it's a lookup, no sampling or filtering is applied.
39642   *
39643   * @param {Texture} texture - The texture.
39644   * @param {string} textureProperty - The name of the texture uniform in the shader.
39645   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39646   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39647   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39648   * @param {string} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
39649   * @return {string} The WGSL snippet.
39650   */
39651  generateTextureLod(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet, levelSnippet = "0u") {
39652    if (texture3.isCubeTexture === true) {
39653      if (offsetSnippet) {
39654        uvSnippet = `${uvSnippet} + vec3<f32>(${offsetSnippet})`;
39655      }
39656      const levelType = texture3.isDepthTexture ? "u32" : "f32";
39657      return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${levelType}( ${levelSnippet} ) )`;
39658    }
39659    const wrapFunction = this.generateWrapFunction(texture3);
39660    const textureDimension = this.generateTextureDimension(texture3, textureProperty, levelSnippet);
39661    const vecType = texture3.is3DTexture || texture3.isData3DTexture ? "vec3" : "vec2";
39662    const textureDimensionMargin = vecType === "vec3" ? "vec3<u32>( 1, 1, 1 )" : "vec2<u32>( 1, 1 )";
39663    if (offsetSnippet) {
39664      uvSnippet = `${uvSnippet} + ${vecType}<f32>(${offsetSnippet}) / ${vecType}<f32>( ${textureDimension} )`;
39665    }
39666    const clampMin = `${vecType}<f32>( 0 )`;
39667    const clampMax = `${vecType}<f32>( ${textureDimension} - ${textureDimensionMargin} )`;
39668    uvSnippet = `${vecType}<u32>( clamp( floor( ${wrapFunction}( ${uvSnippet} ) * ${vecType}<f32>( ${textureDimension} ) ), ${clampMin}, ${clampMax} ) )`;
39669    return this.generateTextureLoad(texture3, textureProperty, uvSnippet, levelSnippet, depthSnippet, null);
39670  }
39671  /**
39672   * Generates the WGSL snippet that reads a single texel from a storage texture.
39673   *
39674   * @param {Texture} texture - The texture.
39675   * @param {string} textureProperty - The name of the texture uniform in the shader.
39676   * @param {string} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39677   * @param {?string} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
39678   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39679   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39680   * @return {string} The WGSL snippet.
39681   */
39682  generateStorageTextureLoad(texture3, textureProperty, uvIndexSnippet, levelSnippet, depthSnippet, offsetSnippet) {
39683    if (offsetSnippet) {
39684      uvIndexSnippet = `${uvIndexSnippet} + ${offsetSnippet}`;
39685    }
39686    let snippet;
39687    if (depthSnippet) {
39688      snippet = `textureLoad( ${textureProperty}, ${uvIndexSnippet}, ${depthSnippet} )`;
39689    } else {
39690      snippet = `textureLoad( ${textureProperty}, ${uvIndexSnippet} )`;
39691    }
39692    return snippet;
39693  }
39694  /**
39695   * Generates the WGSL snippet that reads a single texel from a texture without sampling or filtering.
39696   *
39697   * @param {Texture} texture - The texture.
39698   * @param {string} textureProperty - The name of the texture uniform in the shader.
39699   * @param {string} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39700   * @param {?string} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
39701   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39702   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39703   * @return {string} The WGSL snippet.
39704   */
39705  generateTextureLoad(texture3, textureProperty, uvIndexSnippet, levelSnippet, depthSnippet, offsetSnippet) {
39706    if (levelSnippet === null) levelSnippet = "0u";
39707    if (offsetSnippet) {
39708      uvIndexSnippet = `${uvIndexSnippet} + ${offsetSnippet}`;
39709    }
39710    let snippet;
39711    if (depthSnippet) {
39712      snippet = `textureLoad( ${textureProperty}, ${uvIndexSnippet}, ${depthSnippet}, u32( ${levelSnippet} ) )`;
39713    } else {
39714      snippet = `textureLoad( ${textureProperty}, ${uvIndexSnippet}, u32( ${levelSnippet} ) )`;
39715      if (this.renderer.backend.compatibilityMode && texture3.isDepthTexture) {
39716        snippet += ".x";
39717      }
39718    }
39719    return snippet;
39720  }
39721  /**
39722   * Generates the WGSL snippet that writes a single texel to a texture.
39723   *
39724   * @param {Texture} texture - The texture.
39725   * @param {string} textureProperty - The name of the texture uniform in the shader.
39726   * @param {string} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39727   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39728   * @param {string} valueSnippet - A WGSL snippet that represent the new texel value.
39729   * @return {string} The WGSL snippet.
39730   */
39731  generateTextureStore(texture3, textureProperty, uvIndexSnippet, depthSnippet, valueSnippet) {
39732    let snippet;
39733    if (depthSnippet) {
39734      snippet = `textureStore( ${textureProperty}, ${uvIndexSnippet}, ${depthSnippet}, ${valueSnippet} )`;
39735    } else {
39736      snippet = `textureStore( ${textureProperty}, ${uvIndexSnippet}, ${valueSnippet} )`;
39737    }
39738    return snippet;
39739  }
39740  /**
39741   * Returns `true` if the sampled values of the given texture should be compared against a reference value.
39742   *
39743   * @param {Texture} texture - The texture.
39744   * @return {boolean} Whether the sampled values of the given texture should be compared against a reference value or not.
39745   */
39746  isSampleCompare(texture3) {
39747    return texture3.isDepthTexture === true && texture3.compareFunction !== null && this.renderer.hasCompatibility(Compatibility.TEXTURE_COMPARE);
39748  }
39749  /**
39750   * Returns `true` if the given texture is unfilterable.
39751   *
39752   * @param {Texture} texture - The texture.
39753   * @return {boolean} Whether the given texture is unfilterable or not.
39754   */
39755  isUnfilterable(texture3) {
39756    return this.getComponentTypeFromTexture(texture3) !== "float" || !this.isAvailable("float32Filterable") && texture3.type === FloatType || this.isSampleCompare(texture3) === false && texture3.minFilter === NearestFilter && texture3.magFilter === NearestFilter || this.renderer.backend.utils.getTextureSampleData(texture3).primarySamples > 1;
39757  }
39758  /**
39759   * Generates the WGSL snippet for sampling/loading the given texture.
39760   *
39761   * @param {Texture} texture - The texture.
39762   * @param {string} textureProperty - The name of the texture uniform in the shader.
39763   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39764   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39765   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39766   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
39767   * @return {string} The WGSL snippet.
39768   */
39769  generateTexture(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet, shaderStage = this.shaderStage) {
39770    let snippet = null;
39771    if (this.isUnfilterable(texture3)) {
39772      snippet = this.generateTextureLod(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet, "0", shaderStage);
39773    } else {
39774      snippet = this._generateTextureSample(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet, shaderStage);
39775    }
39776    return snippet;
39777  }
39778  /**
39779   * Generates the WGSL snippet for sampling/loading the given texture using explicit gradients.
39780   *
39781   * @param {Texture} texture - The texture.
39782   * @param {string} textureProperty - The name of the texture uniform in the shader.
39783   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39784   * @param {Array<string>} gradSnippet - An array holding both gradient WGSL snippets.
39785   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39786   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39787   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
39788   * @return {string} The WGSL snippet.
39789   */
39790  generateTextureGrad(texture3, textureProperty, uvSnippet, gradSnippet, depthSnippet, offsetSnippet, shaderStage = this.shaderStage) {
39791    if (shaderStage === "fragment") {
39792      if (depthSnippet) {
39793        if (offsetSnippet) {
39794          return `textureSampleGrad( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${gradSnippet[0]}, ${gradSnippet[1]}, ${offsetSnippet} )`;
39795        }
39796        return `textureSampleGrad( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${gradSnippet[0]}, ${gradSnippet[1]} )`;
39797      } else {
39798        if (offsetSnippet) {
39799          return `textureSampleGrad( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${gradSnippet[0]}, ${gradSnippet[1]}, ${offsetSnippet} )`;
39800        }
39801        return `textureSampleGrad( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${gradSnippet[0]}, ${gradSnippet[1]} )`;
39802      }
39803    } else {
39804      error(`WebGPURenderer: THREE.TextureNode.gradient() does not support ${shaderStage} shader.`);
39805    }
39806  }
39807  /**
39808   * Generates the WGSL snippet for sampling a depth texture and comparing the sampled depth values
39809   * against a reference value.
39810   *
39811   * @param {Texture} texture - The texture.
39812   * @param {string} textureProperty - The name of the texture uniform in the shader.
39813   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39814   * @param {string} compareSnippet -  A WGSL snippet that represents the reference value.
39815   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39816   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39817   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
39818   * @return {string} The WGSL snippet.
39819   */
39820  generateTextureCompare(texture3, textureProperty, uvSnippet, compareSnippet, depthSnippet, offsetSnippet, shaderStage = this.shaderStage) {
39821    if (shaderStage === "fragment") {
39822      if (texture3.isDepthTexture === true && texture3.isArrayTexture === true) {
39823        if (offsetSnippet) {
39824          return `textureSampleCompare( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${compareSnippet}, ${offsetSnippet} )`;
39825        }
39826        return `textureSampleCompare( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${compareSnippet} )`;
39827      }
39828      if (offsetSnippet) {
39829        return `textureSampleCompare( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${compareSnippet}, ${offsetSnippet} )`;
39830      }
39831      return `textureSampleCompare( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${compareSnippet} )`;
39832    } else {
39833      error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${shaderStage} shader.`);
39834    }
39835  }
39836  /**
39837   * Generates the WGSL snippet when sampling textures with explicit mip level.
39838   *
39839   * @param {Texture} texture - The texture.
39840   * @param {string} textureProperty - The name of the texture uniform in the shader.
39841   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39842   * @param {string} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
39843   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39844   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39845   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
39846   * @return {string} The WGSL snippet.
39847   */
39848  generateTextureLevel(texture3, textureProperty, uvSnippet, levelSnippet, depthSnippet, offsetSnippet) {
39849    if (this.isUnfilterable(texture3) === false) {
39850      if (depthSnippet) {
39851        if (offsetSnippet) {
39852          return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${levelSnippet}, ${offsetSnippet} )`;
39853        }
39854        return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${levelSnippet} )`;
39855      } else {
39856        if (offsetSnippet) {
39857          return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${levelSnippet}, ${offsetSnippet} )`;
39858        }
39859        return `textureSampleLevel( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${levelSnippet} )`;
39860      }
39861    } else if (this.isFilteredTexture(texture3)) {
39862      return this.generateFilteredTexture(texture3, textureProperty, uvSnippet, offsetSnippet, levelSnippet, depthSnippet);
39863    } else {
39864      return this.generateTextureLod(texture3, textureProperty, uvSnippet, depthSnippet, offsetSnippet, levelSnippet);
39865    }
39866  }
39867  /**
39868   * Generates the WGSL snippet when sampling textures with a bias to the mip level.
39869   *
39870   * @param {Texture} texture - The texture.
39871   * @param {string} textureProperty - The name of the texture uniform in the shader.
39872   * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
39873   * @param {string} biasSnippet - A WGSL snippet that represents the bias to apply to the mip level before sampling.
39874   * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
39875   * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
39876   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
39877   * @return {string} The WGSL snippet.
39878   */
39879  generateTextureBias(texture3, textureProperty, uvSnippet, biasSnippet, depthSnippet, offsetSnippet, shaderStage = this.shaderStage) {
39880    if (shaderStage === "fragment") {
39881      if (depthSnippet) {
39882        if (offsetSnippet) {
39883          return `textureSampleBias( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${biasSnippet}, ${offsetSnippet} )`;
39884        }
39885        return `textureSampleBias( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${depthSnippet}, ${biasSnippet} )`;
39886      } else {
39887        if (offsetSnippet) {
39888          return `textureSampleBias( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${biasSnippet}, ${offsetSnippet} )`;
39889        }
39890        return `textureSampleBias( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${biasSnippet} )`;
39891      }
39892    } else {
39893      error(`WebGPURenderer: THREE.TextureNode.biasNode does not support ${shaderStage} shader.`);
39894    }
39895  }
39896  /**
39897   * Returns a WGSL snippet that represents the property name of the given node.
39898   *
39899   * @param {Node} node - The node.
39900   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
39901   * @return {string} The property name.
39902   */
39903  getPropertyName(node, shaderStage = this.shaderStage) {
39904    if (node.isNodeVarying === true && node.needsInterpolation === true) {
39905      if (shaderStage === "vertex") {
39906        return `varyings.${node.name}`;
39907      }
39908    } else if (node.isNodeUniform === true) {
39909      const name = node.name;
39910      const type = node.type;
39911      if (type === "texture" || type === "cubeTexture" || type === "cubeDepthTexture" || type === "storageTexture" || type === "texture3D") {
39912        return name;
39913      } else if (type === "buffer" || type === "storageBuffer" || type === "indirectStorageBuffer") {
39914        if (this.isCustomStruct(node)) {
39915          return name;
39916        }
39917        return name + ".value";
39918      } else {
39919        return node.groupNode.name + "." + name;
39920      }
39921    }
39922    return super.getPropertyName(node);
39923  }
39924  /**
39925   * Returns the output struct name.
39926   *
39927   * @return {string} The name of the output struct.
39928   */
39929  getOutputStructName() {
39930    return "output";
39931  }
39932  /**
39933   * Returns the native shader operator name for a given generic name.
39934   *
39935   * @param {string} op - The operator name to resolve.
39936   * @return {?string} The resolved operator name.
39937   */
39938  getFunctionOperator(op) {
39939    const fnOp = wgslFnOpLib[op];
39940    if (fnOp !== void 0) {
39941      this._include(fnOp);
39942      return fnOp;
39943    }
39944    return null;
39945  }
39946  /**
39947   * Returns the node access for the given node and shader stage.
39948   *
39949   * @param {StorageTextureNode|StorageBufferNode} node - The storage node.
39950   * @param {string} shaderStage - The shader stage.
39951   * @return {string} The node access.
39952   */
39953  getNodeAccess(node, shaderStage) {
39954    if (shaderStage !== "compute") {
39955      if (node.isAtomic === true) {
39956        warn("WebGPURenderer: Atomic operations are only supported in compute shaders.");
39957        return NodeAccess.READ_WRITE;
39958      }
39959      return NodeAccess.READ_ONLY;
39960    }
39961    return node.access;
39962  }
39963  /**
39964   * Returns A WGSL snippet representing the storage access.
39965   *
39966   * @param {StorageTextureNode|StorageBufferNode} node - The storage node.
39967   * @param {string} shaderStage - The shader stage.
39968   * @return {string} The WGSL snippet representing the storage access.
39969   */
39970  getStorageAccess(node, shaderStage) {
39971    return accessNames[this.getNodeAccess(node, shaderStage)];
39972  }
39973  /**
39974   * This method is one of the more important ones since it's responsible
39975   * for generating a matching binding instance for the given uniform node.
39976   *
39977   * These bindings are later used in the renderer to create bind groups
39978   * and layouts.
39979   *
39980   * @param {UniformNode} node - The uniform node.
39981   * @param {string} type - The node data type.
39982   * @param {string} shaderStage - The shader stage.
39983   * @param {?string} [name=null] - An optional uniform name.
39984   * @return {NodeUniform} The node uniform object.
39985   */
39986  getUniformFromNode(node, type, shaderStage, name = null) {
39987    const uniformNode = super.getUniformFromNode(node, type, shaderStage, name);
39988    const nodeData = this.getDataFromNode(node, shaderStage, this.globalCache);
39989    if (nodeData.uniformGPU === void 0) {
39990      let uniformGPU;
39991      const group = node.groupNode;
39992      const groupName = group.name;
39993      const bindings = this.getBindGroupArray(groupName, shaderStage);
39994      if (type === "texture" || type === "cubeTexture" || type === "cubeDepthTexture" || type === "storageTexture" || type === "texture3D") {
39995        let texture3 = null;
39996        const access6 = this.getNodeAccess(node, shaderStage);
39997        if (type === "texture" || type === "storageTexture") {
39998          if (node.value.is3DTexture === true) {
39999            texture3 = new NodeSampledTexture3D(uniformNode.name, uniformNode.node, group, access6);
40000          } else {
40001            texture3 = new NodeSampledTexture(uniformNode.name, uniformNode.node, group, access6);
40002          }
40003        } else if (type === "cubeTexture" || type === "cubeDepthTexture") {
40004          texture3 = new NodeSampledCubeTexture(uniformNode.name, uniformNode.node, group, access6);
40005        } else if (type === "texture3D") {
40006          texture3 = new NodeSampledTexture3D(uniformNode.name, uniformNode.node, group, access6);
40007        }
40008        texture3.store = node.isStorageTextureNode === true;
40009        texture3.mipLevel = texture3.store ? node.mipLevel : 0;
40010        texture3.setVisibility(gpuShaderStageLib[shaderStage]);
40011        const needsSampler = node.value.isCubeTexture === true || this.isUnfilterable(node.value) === false && texture3.store === false;
40012        if (needsSampler) {
40013          const sampler3 = new NodeSampler(`${uniformNode.name}_sampler`, uniformNode.node, group);
40014          sampler3.setVisibility(gpuShaderStageLib[shaderStage]);
40015          bindings.push(sampler3, texture3);
40016          uniformGPU = [sampler3, texture3];
40017        } else {
40018          bindings.push(texture3);
40019          uniformGPU = [texture3];
40020        }
40021      } else if (type === "buffer" || type === "storageBuffer" || type === "indirectStorageBuffer") {
40022        const sharedData = this.getSharedDataFromNode(node);
40023        let buffer3 = sharedData.buffer;
40024        if (buffer3 === void 0) {
40025          const bufferClass = type === "buffer" ? NodeUniformBuffer : NodeStorageBuffer;
40026          buffer3 = new bufferClass(node, group);
40027          sharedData.buffer = buffer3;
40028        }
40029        buffer3.setVisibility(buffer3.getVisibility() | gpuShaderStageLib[shaderStage]);
40030        bindings.push(buffer3);
40031        uniformGPU = buffer3;
40032        uniformNode.name = name ? name : "NodeBuffer_" + uniformNode.id;
40033      } else {
40034        let uniformsGroup = this.uniformGroups[groupName];
40035        if (uniformsGroup === void 0) {
40036          uniformsGroup = new NodeUniformsGroup(groupName, group);
40037          uniformsGroup.setVisibility(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE);
40038          this.uniformGroups[groupName] = uniformsGroup;
40039        }
40040        if (bindings.indexOf(uniformsGroup) === -1) {
40041          bindings.push(uniformsGroup);
40042        }
40043        uniformGPU = this.getNodeUniform(uniformNode, type);
40044        const uniformName = uniformGPU.name;
40045        const alreadyExists = uniformsGroup.uniforms.some((u) => u.name === uniformName);
40046        if (!alreadyExists) {
40047          uniformsGroup.addUniform(uniformGPU);
40048        }
40049      }
40050      nodeData.uniformGPU = uniformGPU;
40051    }
40052    return uniformNode;
40053  }
40054  /**
40055   * This method should be used whenever builtins are required in nodes.
40056   * The internal builtins data structure will make sure builtins are
40057   * defined in the WGSL source.
40058   *
40059   * @param {string} name - The builtin name.
40060   * @param {string} property - The property name.
40061   * @param {string} type - The node data type.
40062   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
40063   * @return {string} The property name.
40064   */
40065  getBuiltin(name, property3, type, shaderStage = this.shaderStage) {
40066    const map = this.builtins[shaderStage] || (this.builtins[shaderStage] = /* @__PURE__ */ new Map());
40067    if (map.has(name) === false) {
40068      map.set(name, {
40069        name,
40070        property: property3,
40071        type
40072      });
40073    }
40074    return property3;
40075  }
40076  /**
40077   * Returns `true` if the given builtin is defined in the given shader stage.
40078   *
40079   * @param {string} name - The builtin name.
40080   * @param {string} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for.
40081   * @return {boolean} Whether the given builtin is defined in the given shader stage or not.
40082   */
40083  hasBuiltin(name, shaderStage = this.shaderStage) {
40084    return this.builtins[shaderStage] !== void 0 && this.builtins[shaderStage].has(name);
40085  }
40086  /**
40087   * Returns the vertex index builtin.
40088   *
40089   * @return {string} The vertex index.
40090   */
40091  getVertexIndex() {
40092    if (this.shaderStage === "vertex") {
40093      return this.getBuiltin("vertex_index", "vertexIndex", "u32", "attribute");
40094    }
40095    return "vertexIndex";
40096  }
40097  /**
40098   * Builds the given shader node.
40099   *
40100   * @param {ShaderNodeInternal} shaderNode - The shader node.
40101   * @return {string} The WGSL function code.
40102   */
40103  buildFunctionCode(shaderNode) {
40104    const layout = shaderNode.layout;
40105    const flowData = this.flowShaderNode(shaderNode);
40106    const parameters = [];
40107    for (const input of layout.inputs) {
40108      parameters.push(input.name + " : " + this.getType(input.type));
40109    }
40110    let code3 = `fn ${layout.name}( ${parameters.join(", ")} ) -> ${this.getType(layout.type)} {
40111${flowData.vars}
40112${flowData.code}
40113`;
40114    if (flowData.result) {
40115      code3 += `	return ${flowData.result};
40116`;
40117    }
40118    code3 += "\n}\n";
40119    return code3;
40120  }
40121  /**
40122   * Contextually returns either the vertex stage instance index builtin
40123   * or the linearized index of an compute invocation within a grid of workgroups.
40124   *
40125   * @return {string} The instance index.
40126   */
40127  getInstanceIndex() {
40128    if (this.shaderStage === "vertex") {
40129      return this.getBuiltin("instance_index", "instanceIndex", "u32", "attribute");
40130    }
40131    return "instanceIndex";
40132  }
40133  /**
40134   * Returns a builtin representing the index of a compute invocation within the scope of a workgroup load.
40135   *
40136   * @return {string} The invocation local index.
40137   */
40138  getInvocationLocalIndex() {
40139    return this.getBuiltin("local_invocation_index", "invocationLocalIndex", "u32", "attribute");
40140  }
40141  /**
40142   * Returns a builtin representing the size of a subgroup within the current shader.
40143   *
40144   * @return {string} The subgroup size.
40145   */
40146  getSubgroupSize() {
40147    this.enableSubGroups();
40148    return this.getBuiltin("subgroup_size", "subgroupSize", "u32", "attribute");
40149  }
40150  /**
40151   * Returns a builtin representing the index of a compute invocation within the scope of a subgroup.
40152   *
40153   * @return {string} The invocation subgroup index.
40154   */
40155  getInvocationSubgroupIndex() {
40156    this.enableSubGroups();
40157    return this.getBuiltin("subgroup_invocation_id", "invocationSubgroupIndex", "u32", "attribute");
40158  }
40159  /**
40160   * Returns a builtin representing the index of a compute invocation's subgroup within its workgroup.
40161   *
40162   * @return {string} The subgroup index.
40163   */
40164  getSubgroupIndex() {
40165    this.enableSubGroups();
40166    return this.getBuiltin("subgroup_id", "subgroupIndex", "u32", "attribute");
40167  }
40168  /**
40169   * Overwritten as a NOP since this method is intended for the WebGL 2 backend.
40170   *
40171   * @return {null} Null.
40172   */
40173  getDrawIndex() {
40174    return null;
40175  }
40176  /**
40177   * Returns the front facing builtin.
40178   *
40179   * @return {string} The front facing builtin.
40180   */
40181  getFrontFacing() {
40182    return this.getBuiltin("front_facing", "isFront", "bool");
40183  }
40184  /**
40185   * Returns the frag coord builtin.
40186   *
40187   * @return {string} The frag coord builtin.
40188   */
40189  getFragCoord() {
40190    return this.getBuiltin("position", "fragCoord", "vec4<f32>") + ".xy";
40191  }
40192  /**
40193   * Returns the frag depth builtin.
40194   *
40195   * @return {string} The frag depth builtin.
40196   */
40197  getFragDepth() {
40198    return "output." + this.getBuiltin("frag_depth", "depth", "f32", "output");
40199  }
40200  /**
40201   * Returns the clip distances builtin.
40202   *
40203   * @return {string} The clip distances builtin.
40204   */
40205  getClipDistance() {
40206    return "varyings.hw_clip_distances";
40207  }
40208  /**
40209   * Whether to flip texture data along its vertical axis or not.
40210   *
40211   * @return {boolean} Returns always `false` in context of WGSL.
40212   */
40213  isFlipY() {
40214    return false;
40215  }
40216  /**
40217   * Enables the given directive for the given shader stage.
40218   *
40219   * @param {string} name - The directive name.
40220   * @param {string} [shaderStage=this.shaderStage] - The shader stage to enable the directive for.
40221   */
40222  enableDirective(name, shaderStage = this.shaderStage) {
40223    const stage = this.directives[shaderStage] || (this.directives[shaderStage] = /* @__PURE__ */ new Set());
40224    stage.add(name);
40225  }
40226  /**
40227   * Returns the directives of the given shader stage as a WGSL string.
40228   *
40229   * @param {string} shaderStage - The shader stage.
40230   * @return {string} A WGSL snippet that enables the directives of the given stage.
40231   */
40232  getDirectives(shaderStage) {
40233    const snippets = [];
40234    const directives = this.directives[shaderStage];
40235    if (directives !== void 0) {
40236      for (const directive of directives) {
40237        snippets.push(`enable ${directive};`);
40238      }
40239    }
40240    return snippets.join("\n");
40241  }
40242  /**
40243   * Enables the 'subgroups' directive.
40244   */
40245  enableSubGroups() {
40246    this.enableDirective("subgroups");
40247  }
40248  /**
40249   * Enables the 'subgroups-f16' directive.
40250   */
40251  enableSubgroupsF16() {
40252    this.enableDirective("subgroups-f16");
40253  }
40254  /**
40255   * Enables the 'clip_distances' directive.
40256   */
40257  enableClipDistances() {
40258    this.enableDirective("clip_distances");
40259  }
40260  /**
40261   * Enables the 'f16' directive.
40262   */
40263  enableShaderF16() {
40264    this.enableDirective("f16");
40265  }
40266  /**
40267   * Enables the 'dual_source_blending' directive.
40268   */
40269  enableDualSourceBlending() {
40270    this.enableDirective("dual_source_blending");
40271  }
40272  /**
40273   * Enables hardware clipping.
40274   *
40275   * @param {string} planeCount - The clipping plane count.
40276   */
40277  enableHardwareClipping(planeCount) {
40278    this.enableClipDistances();
40279    this.getBuiltin("clip_distances", "hw_clip_distances", `array<f32, ${planeCount} >`, "vertex");
40280  }
40281  /**
40282   * Returns the builtins of the given shader stage as a WGSL string.
40283   *
40284   * @param {string} shaderStage - The shader stage.
40285   * @return {string} A WGSL snippet that represents the builtins of the given stage.
40286   */
40287  getBuiltins(shaderStage) {
40288    const snippets = [];
40289    const builtins = this.builtins[shaderStage];
40290    if (builtins !== void 0) {
40291      for (const { name, property: property3, type } of builtins.values()) {
40292        snippets.push(`@builtin( ${name} ) ${property3} : ${type}`);
40293      }
40294    }
40295    return snippets.join(",\n	");
40296  }
40297  /**
40298   * This method should be used when a new scoped buffer is used in context of
40299   * compute shaders. It adds the array to the internal data structure which is
40300   * later used to generate the respective WGSL.
40301   *
40302   * @param {string} name - The array name.
40303   * @param {string} scope - The scope.
40304   * @param {string} bufferType - The buffer type.
40305   * @param {string} bufferCount - The buffer count.
40306   * @return {string} The array name.
40307   */
40308  getScopedArray(name, scope, bufferType, bufferCount) {
40309    if (this.scopedArrays.has(name) === false) {
40310      this.scopedArrays.set(name, {
40311        name,
40312        scope,
40313        bufferType,
40314        bufferCount
40315      });
40316    }
40317    return name;
40318  }
40319  /**
40320   * Returns the scoped arrays of the given shader stage as a WGSL string.
40321   *
40322   * @param {string} shaderStage - The shader stage.
40323   * @return {string|undefined} The WGSL snippet that defines the scoped arrays.
40324   * Returns `undefined` when used in the vertex or fragment stage.
40325   */
40326  getScopedArrays(shaderStage) {
40327    if (shaderStage !== "compute") {
40328      return;
40329    }
40330    const snippets = [];
40331    for (const { name, scope, bufferType, bufferCount } of this.scopedArrays.values()) {
40332      const type = this.getType(bufferType);
40333      snippets.push(`var<${scope}> ${name}: array< ${type}, ${bufferCount} >;`);
40334    }
40335    return snippets.join("\n");
40336  }
40337  /**
40338   * Returns the shader attributes of the given shader stage as a WGSL string.
40339   *
40340   * @param {string} shaderStage - The shader stage.
40341   * @return {string} The WGSL snippet that defines the shader attributes.
40342   */
40343  getAttributes(shaderStage) {
40344    const snippets = [];
40345    if (shaderStage === "compute") {
40346      this.getBuiltin("global_invocation_id", "globalId", "vec3<u32>", "attribute");
40347      this.getBuiltin("workgroup_id", "workgroupId", "vec3<u32>", "attribute");
40348      this.getBuiltin("local_invocation_id", "localId", "vec3<u32>", "attribute");
40349      this.getBuiltin("num_workgroups", "numWorkgroups", "vec3<u32>", "attribute");
40350      if (this.renderer.hasFeature("subgroups")) {
40351        this.enableDirective("subgroups", shaderStage);
40352        this.getBuiltin("subgroup_size", "subgroupSize", "u32", "attribute");
40353      }
40354    }
40355    if (shaderStage === "vertex" || shaderStage === "compute") {
40356      const builtins = this.getBuiltins("attribute");
40357      if (builtins) snippets.push(builtins);
40358      const attributes = this.getAttributesArray();
40359      for (let index = 0, length3 = attributes.length; index < length3; index++) {
40360        const attribute3 = attributes[index];
40361        const name = attribute3.name;
40362        const type = this.getType(attribute3.type);
40363        snippets.push(`@location( ${index} ) ${name} : ${type}`);
40364      }
40365    }
40366    return snippets.join(",\n	");
40367  }
40368  /**
40369   * Returns the members of the given struct type node as a WGSL string.
40370   *
40371   * @param {StructTypeNode} struct - The struct type node.
40372   * @return {string} The WGSL snippet that defines the struct members.
40373   */
40374  getStructMembers(struct3) {
40375    const snippets = [];
40376    for (const member of struct3.members) {
40377      const prefix = struct3.output ? "@location( " + member.index + " ) " : "";
40378      let type = this.getType(member.type);
40379      if (member.atomic) {
40380        type = "atomic< " + type + " >";
40381      }
40382      snippets.push(`	${prefix + member.name} : ${type}`);
40383    }
40384    if (struct3.output) {
40385      snippets.push(`	${this.getBuiltins("output")}`);
40386    }
40387    return snippets.join(",\n");
40388  }
40389  /**
40390   * Returns the structs of the given shader stage as a WGSL string.
40391   *
40392   * @param {string} shaderStage - The shader stage.
40393   * @return {string} The WGSL snippet that defines the structs.
40394   */
40395  getStructs(shaderStage) {
40396    let result = "";
40397    const structs = this.structs[shaderStage];
40398    if (structs.length > 0) {
40399      const snippets = [];
40400      for (const struct3 of structs) {
40401        let snippet = `struct ${struct3.name} {
40402`;
40403        snippet += this.getStructMembers(struct3);
40404        snippet += "\n};";
40405        snippets.push(snippet);
40406      }
40407      result = "\n" + snippets.join("\n\n") + "\n";
40408    }
40409    return result;
40410  }
40411  /**
40412   * Returns a WGSL string representing a variable.
40413   *
40414   * @param {string} type - The variable's type.
40415   * @param {string} name - The variable's name.
40416   * @param {?number} [count=null] - The array length.
40417   * @param {string} [qualifier=''] - The variable's qualifier.
40418   * @return {string} The WGSL snippet that defines a variable.
40419   */
40420  getVar(type, name, count = null, qualifier = "") {
40421    let snippet = `var${qualifier} ${name} : `;
40422    if (count !== null) {
40423      snippet += this.generateArrayDeclaration(type, count);
40424    } else {
40425      snippet += this.getType(type);
40426    }
40427    return snippet;
40428  }
40429  /**
40430   * Returns the variables of the given shader stage as a WGSL string.
40431   *
40432   * @param {string} shaderStage - The shader stage.
40433   * @return {string} The WGSL snippet that defines the variables.
40434   */
40435  getVars(shaderStage, global = false) {
40436    let qualifier = "";
40437    if (global) {
40438      qualifier = "<private>";
40439    }
40440    const snippets = [];
40441    const vars = this.vars[shaderStage];
40442    if (vars !== void 0) {
40443      for (const variable of vars) {
40444        snippets.push(`${this.getVar(variable.type, variable.name, variable.count, qualifier)};`);
40445      }
40446    }
40447    return global ? snippets.join("\n") : `
40448	${snippets.join("\n	")}
40449`;
40450  }
40451  /**
40452   * Returns the varyings of the given shader stage as a WGSL string.
40453   *
40454   * @param {string} shaderStage - The shader stage.
40455   * @return {string} The WGSL snippet that defines the varyings.
40456   */
40457  getVaryings(shaderStage) {
40458    const snippets = [];
40459    if (shaderStage === "vertex") {
40460      this.getBuiltin("position", "builtinClipSpace", "vec4<f32>", "vertex");
40461    }
40462    if (shaderStage === "vertex" || shaderStage === "fragment") {
40463      const varyings = this.varyings;
40464      const vars = this.vars[shaderStage];
40465      let varyingIndex = 0;
40466      for (let index = 0; index < varyings.length; index++) {
40467        const varying3 = varyings[index];
40468        if (varying3.needsInterpolation) {
40469          let attributesSnippet = `@location( ${varyingIndex++} )`;
40470          if (varying3.interpolationType) {
40471            const samplingSnippet = varying3.interpolationSampling !== null ? `, ${varying3.interpolationSampling} )` : " )";
40472            attributesSnippet += ` @interpolate( ${varying3.interpolationType}${samplingSnippet}`;
40473          } else if (/^(int|uint|ivec|uvec)/.test(varying3.type)) {
40474            attributesSnippet += " @interpolate(flat, either)";
40475          }
40476          snippets.push(`${attributesSnippet} ${varying3.name} : ${this.getType(varying3.type)}`);
40477        } else if (shaderStage === "vertex" && vars.includes(varying3) === false) {
40478          vars.push(varying3);
40479        }
40480      }
40481    }
40482    const builtins = this.getBuiltins(shaderStage);
40483    if (builtins) snippets.push(builtins);
40484    const code3 = snippets.join(",\n	");
40485    return shaderStage === "vertex" ? this._getWGSLStruct("VaryingsStruct", "	" + code3) : code3;
40486  }
40487  isCustomStruct(nodeUniform) {
40488    const attribute3 = nodeUniform.value;
40489    const bufferNode = nodeUniform.node;
40490    const isAttributeStructType = (attribute3.isBufferAttribute || attribute3.isInstancedBufferAttribute) && bufferNode.structTypeNode !== null;
40491    const isStructArray = bufferNode.value && bufferNode.value.array && (typeof bufferNode.value.itemSize === "number" && bufferNode.value.array.length > bufferNode.value.itemSize);
40492    return isAttributeStructType && !isStructArray;
40493  }
40494  /**
40495   * Returns the uniforms of the given shader stage as a WGSL string.
40496   *
40497   * @param {string} shaderStage - The shader stage.
40498   * @return {string} The WGSL snippet that defines the uniforms.
40499   */
40500  getUniforms(shaderStage) {
40501    const backend = this.renderer.backend;
40502    const uniforms = this.uniforms[shaderStage];
40503    const bindingSnippets = [];
40504    const bufferSnippets = [];
40505    const structSnippets = [];
40506    const uniformGroups = {};
40507    for (const uniform3 of uniforms) {
40508      const groupName = uniform3.groupNode.name;
40509      const uniformIndexes = this.bindingsIndexes[groupName];
40510      if (uniform3.type === "texture" || uniform3.type === "cubeTexture" || uniform3.type === "cubeDepthTexture" || uniform3.type === "storageTexture" || uniform3.type === "texture3D") {
40511        const texture3 = uniform3.node.value;
40512        const needsSampler = texture3.isCubeTexture === true || this.isUnfilterable(texture3) === false && uniform3.node.isStorageTextureNode !== true;
40513        if (needsSampler) {
40514          if (this.isSampleCompare(texture3)) {
40515            bindingSnippets.push(`@binding( ${uniformIndexes.binding++} ) @group( ${uniformIndexes.group} ) var ${uniform3.name}_sampler : sampler_comparison;`);
40516          } else {
40517            bindingSnippets.push(`@binding( ${uniformIndexes.binding++} ) @group( ${uniformIndexes.group} ) var ${uniform3.name}_sampler : sampler;`);
40518          }
40519        }
40520        let textureType;
40521        let multisampled = "";
40522        const { primarySamples } = backend.utils.getTextureSampleData(texture3);
40523        if (primarySamples > 1) {
40524          multisampled = "_multisampled";
40525        }
40526        if (texture3.isCubeTexture === true && texture3.isDepthTexture === true) {
40527          textureType = "texture_depth_cube";
40528        } else if (texture3.isCubeTexture === true) {
40529          textureType = "texture_cube<f32>";
40530        } else if (texture3.isDepthTexture === true) {
40531          if (backend.compatibilityMode && texture3.compareFunction === null) {
40532            textureType = `texture${multisampled}_2d<f32>`;
40533          } else {
40534            textureType = `texture_depth${multisampled}_2d${texture3.isArrayTexture === true ? "_array" : ""}`;
40535          }
40536        } else if (uniform3.node.isStorageTextureNode === true) {
40537          const format = getFormat(texture3, backend.device);
40538          const access6 = this.getStorageAccess(uniform3.node, shaderStage);
40539          const is3D = uniform3.node.value.is3DTexture;
40540          const isArrayTexture = uniform3.node.value.isArrayTexture;
40541          const dimension = is3D ? "3d" : `2d${isArrayTexture ? "_array" : ""}`;
40542          textureType = `texture_storage_${dimension}<${format}, ${access6}>`;
40543        } else if (texture3.isArrayTexture === true || texture3.isDataArrayTexture === true || texture3.isCompressedArrayTexture === true) {
40544          textureType = "texture_2d_array<f32>";
40545        } else if (texture3.is3DTexture === true || texture3.isData3DTexture === true) {
40546          textureType = "texture_3d<f32>";
40547        } else {
40548          const componentPrefix = this.getComponentTypeFromTexture(texture3).charAt(0);
40549          textureType = `texture${multisampled}_2d<${componentPrefix}32>`;
40550        }
40551        bindingSnippets.push(`@binding( ${uniformIndexes.binding++} ) @group( ${uniformIndexes.group} ) var ${uniform3.name} : ${textureType};`);
40552      } else if (uniform3.type === "buffer" || uniform3.type === "storageBuffer" || uniform3.type === "indirectStorageBuffer") {
40553        const bufferNode = uniform3.node;
40554        const bufferType = this.getType(bufferNode.getNodeType(this));
40555        const bufferCount = bufferNode.bufferCount;
40556        const bufferCountSnippet = bufferCount > 0 && uniform3.type === "buffer" ? ", " + bufferCount : "";
40557        const bufferAccessMode = bufferNode.isStorageBufferNode ? `storage, ${this.getStorageAccess(bufferNode, shaderStage)}` : "uniform";
40558        if (this.isCustomStruct(uniform3)) {
40559          bufferSnippets.push(`@binding( ${uniformIndexes.binding++} ) @group( ${uniformIndexes.group} ) var<${bufferAccessMode}> ${uniform3.name} : ${bufferType};`);
40560        } else {
40561          const bufferTypeSnippet = bufferNode.isAtomic ? `atomic<${bufferType}>` : `${bufferType}`;
40562          const bufferSnippet = `	value : array< ${bufferTypeSnippet}${bufferCountSnippet} >`;
40563          bufferSnippets.push(this._getWGSLStructBinding(uniform3.name, bufferSnippet, bufferAccessMode, uniformIndexes.binding++, uniformIndexes.group));
40564        }
40565      } else {
40566        const groupName2 = uniform3.groupNode.name;
40567        if (uniformGroups[groupName2] === void 0) {
40568          const sharedUniformGroup3 = this.uniformGroups[groupName2];
40569          if (sharedUniformGroup3 !== void 0) {
40570            const snippets = [];
40571            for (const sharedUniform of sharedUniformGroup3.uniforms) {
40572              const type = sharedUniform.getType();
40573              const vectorType = this.getType(this.getVectorType(type));
40574              snippets.push(`	${sharedUniform.name} : ${vectorType}`);
40575            }
40576            let groupBinding = this.uniformGroupsBindings[groupName2];
40577            if (groupBinding === void 0) {
40578              groupBinding = {
40579                index: uniformIndexes.binding++,
40580                id: uniformIndexes.group
40581              };
40582              this.uniformGroupsBindings[groupName2] = groupBinding;
40583            }
40584            uniformGroups[groupName2] = {
40585              index: groupBinding.index,
40586              id: groupBinding.id,
40587              snippets
40588            };
40589          }
40590        }
40591      }
40592    }
40593    for (const name in uniformGroups) {
40594      const group = uniformGroups[name];
40595      structSnippets.push(this._getWGSLStructBinding(name, group.snippets.join(",\n"), "uniform", group.index, group.id));
40596    }
40597    const code3 = [...bindingSnippets, ...bufferSnippets, ...structSnippets].join("\n");
40598    return code3;
40599  }
40600  /**
40601   * Controls the code build of the shader stages.
40602   */
40603  buildCode() {
40604    const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} };
40605    this.sortBindingGroups();
40606    for (const shaderStage in shadersData) {
40607      this.shaderStage = shaderStage;
40608      const allowGlobal = this.allowGlobalVariables;
40609      const stageData = shadersData[shaderStage];
40610      stageData.uniforms = this.getUniforms(shaderStage);
40611      stageData.attributes = this.getAttributes(shaderStage);
40612      stageData.varyings = this.getVaryings(shaderStage);
40613      stageData.structs = this.getStructs(shaderStage);
40614      stageData.vars = this.getVars(shaderStage, allowGlobal);
40615      stageData.codes = this.getCodes(shaderStage);
40616      stageData.directives = this.getDirectives(shaderStage);
40617      stageData.scopedArrays = this.getScopedArrays(shaderStage);
40618      let flow = "// code\n\n";
40619      flow += this.flowCode[shaderStage];
40620      const flowNodes = this.flowNodes[shaderStage];
40621      const mainNode = flowNodes[flowNodes.length - 1];
40622      const outputNode = mainNode.outputNode;
40623      const isOutputStruct = outputNode !== void 0 && outputNode.isOutputStructNode === true;
40624      for (const node of flowNodes) {
40625        const flowSlotData = this.getFlowData(
40626          node
40627          /*, shaderStage*/
40628        );
40629        const slotName = node.name;
40630        if (slotName) {
40631          if (flow.length > 0) flow += "\n";
40632          flow += `	// flow -> ${slotName}
40633`;
40634        }
40635        flow += `${flowSlotData.code}
40636	`;
40637        if (node === mainNode && shaderStage !== "compute") {
40638          flow += "// result\n\n	";
40639          if (shaderStage === "vertex") {
40640            flow += `varyings.builtinClipSpace = ${flowSlotData.result};`;
40641          } else if (shaderStage === "fragment") {
40642            if (isOutputStruct) {
40643              stageData.returnType = outputNode.getNodeType(this);
40644              stageData.structs += "var<private> output : " + stageData.returnType + ";";
40645              flow += `return ${flowSlotData.result};`;
40646            } else {
40647              let structSnippet = "	@location( 0 ) color: vec4<f32>";
40648              const builtins = this.getBuiltins("output");
40649              if (builtins) structSnippet += ",\n	" + builtins;
40650              stageData.returnType = "OutputStruct";
40651              stageData.structs += this._getWGSLStruct("OutputStruct", structSnippet);
40652              stageData.structs += "\nvar<private> output : OutputStruct;";
40653              flow += `output.color = ${flowSlotData.result};
40654
40655	return output;`;
40656            }
40657          }
40658        }
40659      }
40660      stageData.flow = flow;
40661    }
40662    this.shaderStage = null;
40663    if (this.material !== null) {
40664      this.vertexShader = this._getWGSLVertexCode(shadersData.vertex);
40665      this.fragmentShader = this._getWGSLFragmentCode(shadersData.fragment);
40666    } else {
40667      const workgroupSize = this.object.workgroupSize;
40668      this.computeShader = this._getWGSLComputeCode(shadersData.compute, workgroupSize);
40669    }
40670  }
40671  /**
40672   * Returns the native shader method name for a given generic name.
40673   *
40674   * @param {string} method - The method name to resolve.
40675   * @param {?string} [output=null] - An optional output.
40676   * @return {string} The resolved WGSL method name.
40677   */
40678  getMethod(method, output3 = null) {
40679    let wgslMethod;
40680    if (output3 !== null) {
40681      wgslMethod = this._getWGSLMethod(method + "_" + output3);
40682    }
40683    if (wgslMethod === void 0) {
40684      wgslMethod = this._getWGSLMethod(method);
40685    }
40686    return wgslMethod || method;
40687  }
40688  /**
40689   * Returns the bitcast method name for a given input and outputType.
40690   *
40691   * @param {string} type - The output type to bitcast to.
40692   * @return {string} The resolved WGSL bitcast invocation.
40693   */
40694  getBitcastMethod(type) {
40695    const dataType = this.getType(type);
40696    return `bitcast<${dataType}>`;
40697  }
40698  /**
40699   * Returns the float packing method name for a given numeric encoding.
40700   *
40701   * @param {string} encoding - The numeric encoding that describes how the float values are mapped to the integer range.
40702   * @returns {string} The resolve WGSL float packing method name.
40703   */
40704  getFloatPackingMethod(encoding) {
40705    return this.getMethod(`floatpack_${encoding}_2x16`);
40706  }
40707  /**
40708   * Returns the float unpacking method name for a given numeric encoding.
40709   *
40710   * @param {string} encoding - The numeric encoding that describes how the integer values are mapped to the float range.
40711   * @returns {string} The resolve WGSL float unpacking method name.
40712   */
40713  getFloatUnpackingMethod(encoding) {
40714    return this.getMethod(`floatunpack_${encoding}_2x16`);
40715  }
40716  /**
40717   * Returns the native snippet for a ternary operation.
40718   *
40719   * @param {string} condSnippet - The condition determining which expression gets resolved.
40720   * @param {string} ifSnippet - The expression to resolve to if the condition is true.
40721   * @param {string} elseSnippet - The expression to resolve to if the condition is false.
40722   * @return {string} The resolved method name.
40723   */
40724  getTernary(condSnippet, ifSnippet, elseSnippet) {
40725    return `select( ${elseSnippet}, ${ifSnippet}, ${condSnippet} )`;
40726  }
40727  /**
40728   * Returns the WGSL type of the given node data type.
40729   *
40730   * @param {string} type - The node data type.
40731   * @return {string} The WGSL type.
40732   */
40733  getType(type) {
40734    return wgslTypeLib[type] || type;
40735  }
40736  /**
40737   * Whether the requested feature is available or not.
40738   *
40739   * @param {string} name - The requested feature.
40740   * @return {boolean} Whether the requested feature is supported or not.
40741   */
40742  isAvailable(name) {
40743    let result = supports[name];
40744    if (result === void 0) {
40745      if (name === "float32Filterable") {
40746        result = this.renderer.hasFeature("float32-filterable");
40747      } else if (name === "clipDistance") {
40748        result = this.renderer.hasFeature("clip-distances");
40749      }
40750      supports[name] = result;
40751    }
40752    return result;
40753  }
40754  /**
40755   * Returns the native shader method name for a given generic name.
40756   *
40757   * @private
40758   * @param {string} method - The method name to resolve.
40759   * @return {string} The resolved WGSL method name.
40760   */
40761  _getWGSLMethod(method) {
40762    if (wgslPolyfill[method] !== void 0) {
40763      this._include(method);
40764    }
40765    return wgslMethods[method];
40766  }
40767  /**
40768   * Includes the given method name into the current
40769   * function node.
40770   *
40771   * @private
40772   * @param {string} name - The method name to include.
40773   * @return {CodeNode} The respective code node.
40774   */
40775  _include(name) {
40776    const codeNode = wgslPolyfill[name];
40777    codeNode.build(this);
40778    this.addInclude(codeNode);
40779    return codeNode;
40780  }
40781  /**
40782   * Returns a WGSL vertex shader based on the given shader data.
40783   *
40784   * @private
40785   * @param {Object} shaderData - The shader data.
40786   * @return {string} The vertex shader.
40787   */
40788  _getWGSLVertexCode(shaderData) {
40789    return `${this.getSignature()}
40790// directives
40791${shaderData.directives}
40792
40793// structs
40794${shaderData.structs}
40795
40796// uniforms
40797${shaderData.uniforms}
40798
40799// varyings
40800${shaderData.varyings}
40801var<private> varyings : VaryingsStruct;
40802
40803// vars
40804${shaderData.vars}
40805
40806// codes
40807${shaderData.codes}
40808
40809@vertex
40810fn main( ${shaderData.attributes} ) -> VaryingsStruct {
40811
40812	// flow
40813	${shaderData.flow}
40814
40815	return varyings;
40816
40817}
40818`;
40819  }
40820  /**
40821   * Returns a WGSL fragment shader based on the given shader data.
40822   *
40823   * @private
40824   * @param {Object} shaderData - The shader data.
40825   * @return {string} The vertex shader.
40826   */
40827  _getWGSLFragmentCode(shaderData) {
40828    return `${this.getSignature()}
40829// global
40830${diagnostics}
40831
40832// structs
40833${shaderData.structs}
40834
40835// uniforms
40836${shaderData.uniforms}
40837
40838// vars
40839${shaderData.vars}
40840
40841// codes
40842${shaderData.codes}
40843
40844@fragment
40845fn main( ${shaderData.varyings} ) -> ${shaderData.returnType} {
40846
40847	// flow
40848	${shaderData.flow}
40849
40850}
40851`;
40852  }
40853  /**
40854   * Returns a WGSL compute shader based on the given shader data.
40855   *
40856   * @private
40857   * @param {Object} shaderData - The shader data.
40858   * @param {string} workgroupSize - The workgroup size.
40859   * @return {string} The vertex shader.
40860   */
40861  _getWGSLComputeCode(shaderData, workgroupSize) {
40862    const [workgroupSizeX, workgroupSizeY, workgroupSizeZ] = workgroupSize;
40863    return `${this.getSignature()}
40864// directives
40865${shaderData.directives}
40866
40867// system
40868var<private> instanceIndex : u32;
40869
40870// locals
40871${shaderData.scopedArrays}
40872
40873// structs
40874${shaderData.structs}
40875
40876// uniforms
40877${shaderData.uniforms}
40878
40879// vars
40880${this.allowGlobalVariables ? shaderData.vars : ""}
40881
40882// codes
40883${shaderData.codes}
40884
40885@compute @workgroup_size( ${workgroupSizeX}, ${workgroupSizeY}, ${workgroupSizeZ} )
40886fn main( ${shaderData.attributes} ) {
40887
40888	// local vars
40889	${this.allowGlobalVariables ? "" : shaderData.vars}
40890
40891	// system
40892	instanceIndex = globalId.x
40893		+ globalId.y * ( ${workgroupSizeX} * numWorkgroups.x )
40894		+ globalId.z * ( ${workgroupSizeX} * numWorkgroups.x ) * ( ${workgroupSizeY} * numWorkgroups.y );
40895
40896	// flow
40897	${shaderData.flow}
40898
40899}
40900`;
40901  }
40902  /**
40903   * Returns a WGSL struct based on the given name and variables.
40904   *
40905   * @private
40906   * @param {string} name - The struct name.
40907   * @param {string} vars - The struct variables.
40908   * @return {string} The WGSL snippet representing a struct.
40909   */
40910  _getWGSLStruct(name, vars) {
40911    return `
40912struct ${name} {
40913${vars}
40914};`;
40915  }
40916  /**
40917   * Returns a WGSL struct binding.
40918   *
40919   * @private
40920   * @param {string} name - The struct name.
40921   * @param {string} vars - The struct variables.
40922   * @param {string} access - The access.
40923   * @param {number} [binding=0] - The binding index.
40924   * @param {number} [group=0] - The group index.
40925   * @return {string} The WGSL snippet representing a struct binding.
40926   */
40927  _getWGSLStructBinding(name, vars, access6, binding = 0, group = 0) {
40928    const structName = name + "Struct";
40929    const structSnippet = this._getWGSLStruct(structName, vars);
40930    return `${structSnippet}
40931@binding( ${binding} ) @group( ${group} )
40932var<${access6}> ${name} : ${structName};`;
40933  }
40934};
40935var WebGPUUtils = class {
40936  /**
40937   * Constructs a new utility object.
40938   *
40939   * @param {WebGPUBackend} backend - The WebGPU backend.
40940   */
40941  constructor(backend) {
40942    this.backend = backend;
40943  }
40944  /**
40945   * Returns the depth/stencil GPU format for the given render context.
40946   *
40947   * @param {RenderContext} renderContext - The render context.
40948   * @return {string} The depth/stencil GPU texture format.
40949   */
40950  getCurrentDepthStencilFormat(renderContext) {
40951    let format;
40952    if (renderContext.depth) {
40953      if (renderContext.depthTexture !== null) {
40954        format = this.getTextureFormatGPU(renderContext.depthTexture);
40955      } else if (renderContext.stencil) {
40956        if (this.backend.renderer.reversedDepthBuffer === true) {
40957          format = GPUTextureFormat.Depth32FloatStencil8;
40958        } else {
40959          format = GPUTextureFormat.Depth24PlusStencil8;
40960        }
40961      } else {
40962        if (this.backend.renderer.reversedDepthBuffer === true) {
40963          format = GPUTextureFormat.Depth32Float;
40964        } else {
40965          format = GPUTextureFormat.Depth24Plus;
40966        }
40967      }
40968    }
40969    return format;
40970  }
40971  /**
40972   * Returns the GPU format for the given texture.
40973   *
40974   * @param {Texture} texture - The texture.
40975   * @return {string} The GPU texture format.
40976   */
40977  getTextureFormatGPU(texture3) {
40978    return this.backend.get(texture3).format;
40979  }
40980  /**
40981   * Returns an object that defines the multi-sampling state of the given texture.
40982   *
40983   * @param {Texture} texture - The texture.
40984   * @return {Object} The multi-sampling state.
40985   */
40986  getTextureSampleData(texture3) {
40987    let samples;
40988    if (texture3.isFramebufferTexture) {
40989      samples = 1;
40990    } else if (texture3.isDepthTexture && !texture3.renderTarget) {
40991      const renderer = this.backend.renderer;
40992      const renderTarget = renderer.getRenderTarget();
40993      samples = renderTarget ? renderTarget.samples : renderer.currentSamples;
40994    } else if (texture3.renderTarget) {
40995      samples = texture3.renderTarget.samples;
40996    }
40997    samples = samples || 1;
40998    const isMSAA = samples > 1 && texture3.renderTarget !== null && (texture3.isDepthTexture !== true && texture3.isFramebufferTexture !== true);
40999    const primarySamples = isMSAA ? 1 : samples;
41000    return { samples, primarySamples, isMSAA };
41001  }
41002  /**
41003   * Returns the default color attachment's GPU format of the current render context.
41004   *
41005   * @param {RenderContext} renderContext - The render context.
41006   * @return {string} The GPU texture format of the default color attachment.
41007   */
41008  getCurrentColorFormat(renderContext) {
41009    let format;
41010    if (renderContext.textures !== null) {
41011      format = this.getTextureFormatGPU(renderContext.textures[0]);
41012    } else {
41013      format = this.getPreferredCanvasFormat();
41014    }
41015    return format;
41016  }
41017  /**
41018   * Returns the GPU formats of all color attachments of the current render context.
41019   *
41020   * @param {RenderContext} renderContext - The render context.
41021   * @return {Array<string>} The GPU texture formats of all color attachments.
41022   */
41023  getCurrentColorFormats(renderContext) {
41024    if (renderContext.textures !== null) {
41025      return renderContext.textures.map((t) => this.getTextureFormatGPU(t));
41026    } else {
41027      return [this.getPreferredCanvasFormat()];
41028    }
41029  }
41030  /**
41031   * Returns the output color space of the current render context.
41032   *
41033   * @param {RenderContext} renderContext - The render context.
41034   * @return {string} The output color space.
41035   */
41036  getCurrentColorSpace(renderContext) {
41037    if (renderContext.textures !== null) {
41038      return renderContext.textures[0].colorSpace;
41039    }
41040    return this.backend.renderer.outputColorSpace;
41041  }
41042  /**
41043   * Returns GPU primitive topology for the given object and material.
41044   *
41045   * @param {Object3D} object - The 3D object.
41046   * @param {Material} material - The material.
41047   * @return {string} The GPU primitive topology.
41048   */
41049  getPrimitiveTopology(object, material) {
41050    if (object.isPoints) return GPUPrimitiveTopology.PointList;
41051    else if (object.isLineSegments || object.isMesh && material.wireframe === true) return GPUPrimitiveTopology.LineList;
41052    else if (object.isLine) return GPUPrimitiveTopology.LineStrip;
41053    else if (object.isMesh) return GPUPrimitiveTopology.TriangleList;
41054  }
41055  /**
41056   * Returns a modified sample count from the given sample count value.
41057   *
41058   * That is required since WebGPU only supports either 1 or 4.
41059   *
41060   * @param {number} sampleCount - The input sample count.
41061   * @return {number} The (potentially updated) output sample count.
41062   */
41063  getSampleCount(sampleCount) {
41064    return sampleCount >= 4 ? 4 : 1;
41065  }
41066  /**
41067   * Returns the sample count of the given render context.
41068   *
41069   * @param {RenderContext} renderContext - The render context.
41070   * @return {number} The sample count.
41071   */
41072  getSampleCountRenderContext(renderContext) {
41073    if (renderContext.textures !== null) {
41074      return this.getSampleCount(renderContext.sampleCount);
41075    }
41076    return this.getSampleCount(this.backend.renderer.currentSamples);
41077  }
41078  /**
41079   * Returns the preferred canvas format.
41080   *
41081   * There is a separate method for this so it's possible to
41082   * honor edge cases for specific devices.
41083   *
41084   * @return {string} The GPU texture format of the canvas.
41085   */
41086  getPreferredCanvasFormat() {
41087    const parameters = this.backend.parameters;
41088    const bufferType = parameters.outputType;
41089    if (bufferType === void 0) {
41090      return navigator.gpu.getPreferredCanvasFormat();
41091    } else if (bufferType === UnsignedByteType) {
41092      return GPUTextureFormat.BGRA8Unorm;
41093    } else if (bufferType === HalfFloatType) {
41094      return GPUTextureFormat.RGBA16Float;
41095    } else {
41096      throw new Error("Unsupported output buffer type.");
41097    }
41098  }
41099};
41100var typedArraysToVertexFormatPrefix = /* @__PURE__ */ new Map([
41101  [Int8Array, ["sint8", "snorm8"]],
41102  [Uint8Array, ["uint8", "unorm8"]],
41103  [Int16Array, ["sint16", "snorm16"]],
41104  [Uint16Array, ["uint16", "unorm16"]],
41105  [Int32Array, ["sint32", "snorm32"]],
41106  [Uint32Array, ["uint32", "unorm32"]],
41107  [Float32Array, ["float32"]]
41108]);
41109if (typeof Float16Array !== "undefined") {
41110  typedArraysToVertexFormatPrefix.set(Float16Array, ["float16"]);
41111}
41112var typedAttributeToVertexFormatPrefix = /* @__PURE__ */ new Map([
41113  [Float16BufferAttribute, ["float16"]]
41114]);
41115var typeArraysToVertexFormatPrefixForItemSize1 = /* @__PURE__ */ new Map([
41116  [Int32Array, "sint32"],
41117  [Int16Array, "sint32"],
41118  // patch for INT16
41119  [Uint32Array, "uint32"],
41120  [Uint16Array, "uint32"],
41121  // patch for UINT16
41122  [Float32Array, "float32"]
41123]);
41124var WebGPUAttributeUtils = class {
41125  /**
41126   * Constructs a new utility object.
41127   *
41128   * @param {WebGPUBackend} backend - The WebGPU backend.
41129   */
41130  constructor(backend) {
41131    this.backend = backend;
41132  }
41133  /**
41134   * Creates the GPU buffer for the given buffer attribute.
41135   *
41136   * @param {BufferAttribute} attribute - The buffer attribute.
41137   * @param {GPUBufferUsage} usage - A flag that indicates how the buffer may be used after its creation.
41138   */
41139  createAttribute(attribute3, usage) {
41140    const bufferAttribute3 = this._getBufferAttribute(attribute3);
41141    const backend = this.backend;
41142    const bufferData = backend.get(bufferAttribute3);
41143    let buffer3 = bufferData.buffer;
41144    if (buffer3 === void 0) {
41145      const device = backend.device;
41146      let array3 = bufferAttribute3.array;
41147      if (attribute3.normalized === false) {
41148        if (array3.constructor === Int16Array || array3.constructor === Int8Array) {
41149          array3 = new Int32Array(array3);
41150        } else if (array3.constructor === Uint16Array || array3.constructor === Uint8Array) {
41151          array3 = new Uint32Array(array3);
41152          if (usage & GPUBufferUsage.INDEX) {
41153            for (let i = 0; i < array3.length; i++) {
41154              if (array3[i] === 65535) array3[i] = 4294967295;
41155            }
41156          }
41157        }
41158      }
41159      bufferAttribute3.array = array3;
41160      if ((bufferAttribute3.isStorageBufferAttribute || bufferAttribute3.isStorageInstancedBufferAttribute) && bufferAttribute3.itemSize === 3) {
41161        array3 = new array3.constructor(bufferAttribute3.count * 4);
41162        for (let i = 0; i < bufferAttribute3.count; i++) {
41163          array3.set(bufferAttribute3.array.subarray(i * 3, i * 3 + 3), i * 4);
41164        }
41165        bufferAttribute3.itemSize = 4;
41166        bufferAttribute3.array = array3;
41167        bufferData._force3to4BytesAlignment = true;
41168      }
41169      const byteLength = array3.byteLength;
41170      const size3 = byteLength + (4 - byteLength % 4) % 4;
41171      buffer3 = device.createBuffer({
41172        label: bufferAttribute3.name,
41173        size: size3,
41174        usage,
41175        mappedAtCreation: true
41176      });
41177      new array3.constructor(buffer3.getMappedRange()).set(array3);
41178      buffer3.unmap();
41179      bufferData.buffer = buffer3;
41180    }
41181  }
41182  /**
41183   * Updates the GPU buffer of the given buffer attribute.
41184   *
41185   * @param {BufferAttribute} attribute - The buffer attribute.
41186   */
41187  updateAttribute(attribute3) {
41188    const bufferAttribute3 = this._getBufferAttribute(attribute3);
41189    const backend = this.backend;
41190    const device = backend.device;
41191    const bufferData = backend.get(bufferAttribute3);
41192    const buffer3 = backend.get(bufferAttribute3).buffer;
41193    let array3 = bufferAttribute3.array;
41194    if (bufferData._force3to4BytesAlignment === true) {
41195      array3 = new array3.constructor(bufferAttribute3.count * 4);
41196      for (let i = 0; i < bufferAttribute3.count; i++) {
41197        array3.set(bufferAttribute3.array.subarray(i * 3, i * 3 + 3), i * 4);
41198      }
41199      bufferAttribute3.array = array3;
41200    }
41201    const updateRanges = bufferAttribute3.updateRanges;
41202    if (updateRanges.length === 0) {
41203      device.queue.writeBuffer(
41204        buffer3,
41205        0,
41206        array3,
41207        0
41208      );
41209    } else {
41210      const isTyped = isTypedArray(array3);
41211      const byteOffsetFactor = isTyped ? 1 : array3.BYTES_PER_ELEMENT;
41212      for (let i = 0, l = updateRanges.length; i < l; i++) {
41213        const range3 = updateRanges[i];
41214        let dataOffset, size3;
41215        if (bufferData._force3to4BytesAlignment === true) {
41216          const vertexStart = Math.floor(range3.start / 3);
41217          const vertexCount = Math.ceil(range3.count / 3);
41218          dataOffset = vertexStart * 4 * byteOffsetFactor;
41219          size3 = vertexCount * 4 * byteOffsetFactor;
41220        } else {
41221          dataOffset = range3.start * byteOffsetFactor;
41222          size3 = range3.count * byteOffsetFactor;
41223        }
41224        const bufferOffset = dataOffset * (isTyped ? array3.BYTES_PER_ELEMENT : 1);
41225        device.queue.writeBuffer(
41226          buffer3,
41227          bufferOffset,
41228          array3,
41229          dataOffset,
41230          size3
41231        );
41232      }
41233      bufferAttribute3.clearUpdateRanges();
41234    }
41235  }
41236  /**
41237   * This method creates the vertex buffer layout data which are
41238   * require when creating a render pipeline for the given render object.
41239   *
41240   * @param {RenderObject} renderObject - The render object.
41241   * @return {Array<Object>} An array holding objects which describe the vertex buffer layout.
41242   */
41243  createShaderVertexBuffers(renderObject) {
41244    const attributes = renderObject.getAttributes();
41245    const vertexBuffers = /* @__PURE__ */ new Map();
41246    for (let slot = 0; slot < attributes.length; slot++) {
41247      const geometryAttribute = attributes[slot];
41248      const bytesPerElement = geometryAttribute.array.BYTES_PER_ELEMENT;
41249      const bufferAttribute3 = this._getBufferAttribute(geometryAttribute);
41250      let vertexBufferLayout = vertexBuffers.get(bufferAttribute3);
41251      if (vertexBufferLayout === void 0) {
41252        let arrayStride, stepMode;
41253        if (geometryAttribute.isInterleavedBufferAttribute === true) {
41254          arrayStride = geometryAttribute.data.stride * bytesPerElement;
41255          stepMode = geometryAttribute.data.isInstancedInterleavedBuffer ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
41256        } else {
41257          arrayStride = geometryAttribute.itemSize * bytesPerElement;
41258          stepMode = geometryAttribute.isInstancedBufferAttribute ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
41259        }
41260        if (geometryAttribute.normalized === false && (geometryAttribute.array.constructor === Int16Array || geometryAttribute.array.constructor === Uint16Array)) {
41261          arrayStride = 4;
41262        }
41263        vertexBufferLayout = {
41264          arrayStride,
41265          attributes: [],
41266          stepMode
41267        };
41268        vertexBuffers.set(bufferAttribute3, vertexBufferLayout);
41269      }
41270      const format = this._getVertexFormat(geometryAttribute);
41271      const offset3 = geometryAttribute.isInterleavedBufferAttribute === true ? geometryAttribute.offset * bytesPerElement : 0;
41272      vertexBufferLayout.attributes.push({
41273        shaderLocation: slot,
41274        offset: offset3,
41275        format
41276      });
41277    }
41278    return Array.from(vertexBuffers.values());
41279  }
41280  /**
41281   * Destroys the GPU buffer of the given buffer attribute.
41282   *
41283   * @param {BufferAttribute} attribute - The buffer attribute.
41284   */
41285  destroyAttribute(attribute3) {
41286    const backend = this.backend;
41287    const data = backend.get(this._getBufferAttribute(attribute3));
41288    data.buffer.destroy();
41289    backend.delete(attribute3);
41290  }
41291  /**
41292   * This method performs a readback operation by moving buffer data from
41293   * a storage buffer attribute from the GPU to the CPU. ReadbackBuffer can
41294   * be used to retain and reuse handles to the intermediate buffers and prevent
41295   * new allocation.
41296   *
41297   * @async
41298   * @param {BufferAttribute} attribute - The storage buffer attribute to read frm.
41299   * @param {number} count - The offset from which to start reading the
41300   * @param {number} offset - The storage buffer attribute.
41301   * @param {ReadbackBuffer|ArrayBuffer} target - The storage buffer attribute.
41302   * @return {Promise<ArrayBuffer|ReadbackBuffer>} A promise that resolves with the buffer data when the data are ready.
41303   */
41304  async getArrayBufferAsync(attribute3, target = null, offset3 = 0, count = -1) {
41305    const backend = this.backend;
41306    const device = backend.device;
41307    const data = backend.get(this._getBufferAttribute(attribute3));
41308    const bufferGPU = data.buffer;
41309    const byteLength = count === -1 ? bufferGPU.size - offset3 : count;
41310    let readBufferGPU;
41311    if (target !== null && target.isReadbackBuffer) {
41312      const readbackInfo = backend.get(target);
41313      if (target._mapped === true) {
41314        throw new Error("WebGPURenderer: ReadbackBuffer must be released before being used again.");
41315      }
41316      target._mapped = true;
41317      if (readbackInfo.readBufferGPU === void 0) {
41318        readBufferGPU = device.createBuffer({
41319          label: `${target.name}_readback`,
41320          size: target.maxByteLength,
41321          usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
41322        });
41323        const releaseCallback = () => {
41324          target.buffer = null;
41325          target._mapped = false;
41326          readBufferGPU.unmap();
41327        };
41328        const disposeCallback = () => {
41329          target.buffer = null;
41330          target._mapped = false;
41331          readBufferGPU.destroy();
41332          backend.delete(target);
41333          target.removeEventListener("release", releaseCallback);
41334          target.removeEventListener("dispose", disposeCallback);
41335        };
41336        target.addEventListener("release", releaseCallback);
41337        target.addEventListener("dispose", disposeCallback);
41338        readbackInfo.readBufferGPU = readBufferGPU;
41339      } else {
41340        readBufferGPU = readbackInfo.readBufferGPU;
41341      }
41342    } else {
41343      readBufferGPU = device.createBuffer({
41344        label: `${attribute3.name}_readback`,
41345        size: byteLength,
41346        usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
41347      });
41348    }
41349    const cmdEncoder = device.createCommandEncoder({
41350      label: `readback_encoder_${attribute3.name}`
41351    });
41352    cmdEncoder.copyBufferToBuffer(
41353      bufferGPU,
41354      offset3,
41355      readBufferGPU,
41356      0,
41357      byteLength
41358    );
41359    const gpuCommands = cmdEncoder.finish();
41360    device.queue.submit([gpuCommands]);
41361    await readBufferGPU.mapAsync(GPUMapMode.READ, 0, byteLength);
41362    if (target === null) {
41363      const arrayBuffer3 = readBufferGPU.getMappedRange(0, byteLength);
41364      const result = arrayBuffer3.slice();
41365      readBufferGPU.destroy();
41366      return result;
41367    } else if (target.isReadbackBuffer) {
41368      target.buffer = readBufferGPU.getMappedRange(0, byteLength);
41369      return target;
41370    } else {
41371      const arrayBuffer3 = readBufferGPU.getMappedRange(0, byteLength);
41372      new Uint8Array(target).set(new Uint8Array(arrayBuffer3));
41373      readBufferGPU.destroy();
41374      return target;
41375    }
41376  }
41377  /**
41378   * Returns the vertex format of the given buffer attribute.
41379   *
41380   * @private
41381   * @param {BufferAttribute} geometryAttribute - The buffer attribute.
41382   * @return {string|undefined} The vertex format (e.g. 'float32x3').
41383   */
41384  _getVertexFormat(geometryAttribute) {
41385    const { itemSize, normalized } = geometryAttribute;
41386    const ArrayType = geometryAttribute.array.constructor;
41387    const AttributeType2 = geometryAttribute.constructor;
41388    let format;
41389    if (itemSize === 1) {
41390      format = typeArraysToVertexFormatPrefixForItemSize1.get(ArrayType);
41391    } else {
41392      const prefixOptions = typedAttributeToVertexFormatPrefix.get(AttributeType2) || typedArraysToVertexFormatPrefix.get(ArrayType);
41393      const prefix = prefixOptions[normalized ? 1 : 0];
41394      if (prefix) {
41395        const bytesPerUnit = ArrayType.BYTES_PER_ELEMENT * itemSize;
41396        const paddedBytesPerUnit = Math.floor((bytesPerUnit + 3) / 4) * 4;
41397        const paddedItemSize = paddedBytesPerUnit / ArrayType.BYTES_PER_ELEMENT;
41398        if (paddedItemSize % 1) {
41399          throw new Error("THREE.WebGPUAttributeUtils: Bad vertex format item size.");
41400        }
41401        format = `${prefix}x${paddedItemSize}`;
41402      }
41403    }
41404    if (!format) {
41405      error("WebGPUAttributeUtils: Vertex format not supported yet.");
41406    }
41407    return format;
41408  }
41409  /**
41410   * Utility method for handling interleaved buffer attributes correctly.
41411   * To process them, their `InterleavedBuffer` is returned.
41412   *
41413   * @private
41414   * @param {BufferAttribute} attribute - The attribute.
41415   * @return {BufferAttribute|InterleavedBuffer}
41416   */
41417  _getBufferAttribute(attribute3) {
41418    if (attribute3.isInterleavedBufferAttribute) attribute3 = attribute3.data;
41419    return attribute3;
41420  }
41421};
41422var BindGroupLayout = class {
41423  /**
41424   * Constructs a new layout.
41425   *
41426   * @param {GPUBindGroupLayout} layoutGPU - A GPU Bind Group Layout.
41427   */
41428  constructor(layoutGPU) {
41429    this.layoutGPU = layoutGPU;
41430    this.usedTimes = 0;
41431  }
41432};
41433var WebGPUBindingUtils = class {
41434  /**
41435   * Constructs a new utility object.
41436   *
41437   * @param {WebGPUBackend} backend - The WebGPU backend.
41438   */
41439  constructor(backend) {
41440    this.backend = backend;
41441    this._bindGroupLayoutCache = /* @__PURE__ */ new Map();
41442  }
41443  /**
41444   * Creates a GPU bind group layout for the given bind group.
41445   *
41446   * @param {BindGroup} bindGroup - The bind group.
41447   * @return {GPUBindGroupLayout} The GPU bind group layout.
41448   */
41449  createBindingsLayout(bindGroup) {
41450    const backend = this.backend;
41451    const device = backend.device;
41452    const bindingsData = backend.get(bindGroup);
41453    if (bindingsData.layout) {
41454      return bindingsData.layout.layoutGPU;
41455    }
41456    const entries5 = this._createLayoutEntries(bindGroup);
41457    const bindGroupLayoutKey = hashString(JSON.stringify(entries5));
41458    let bindGroupLayout = this._bindGroupLayoutCache.get(bindGroupLayoutKey);
41459    if (bindGroupLayout === void 0) {
41460      bindGroupLayout = new BindGroupLayout(device.createBindGroupLayout({ entries: entries5 }));
41461      this._bindGroupLayoutCache.set(bindGroupLayoutKey, bindGroupLayout);
41462    }
41463    bindGroupLayout.usedTimes++;
41464    bindingsData.layout = bindGroupLayout;
41465    bindingsData.layoutKey = bindGroupLayoutKey;
41466    return bindGroupLayout.layoutGPU;
41467  }
41468  /**
41469   * Creates bindings from the given bind group definition.
41470   *
41471   * @param {BindGroup} bindGroup - The bind group.
41472   * @param {Array<BindGroup>} bindings - Array of bind groups.
41473   * @param {number} cacheIndex - The cache index.
41474   * @param {number} version - The version.
41475   */
41476  createBindings(bindGroup, bindings, cacheIndex, version = 0) {
41477    const { backend } = this;
41478    const bindingsData = backend.get(bindGroup);
41479    const bindLayoutGPU = this.createBindingsLayout(bindGroup);
41480    let bindGroupGPU;
41481    if (cacheIndex > 0) {
41482      if (bindingsData.groups === void 0) {
41483        bindingsData.groups = [];
41484        bindingsData.versions = [];
41485      }
41486      if (bindingsData.versions[cacheIndex] === version) {
41487        bindGroupGPU = bindingsData.groups[cacheIndex];
41488      }
41489    }
41490    if (bindGroupGPU === void 0) {
41491      bindGroupGPU = this.createBindGroup(bindGroup, bindLayoutGPU);
41492      if (cacheIndex > 0) {
41493        bindingsData.groups[cacheIndex] = bindGroupGPU;
41494        bindingsData.versions[cacheIndex] = version;
41495      }
41496    }
41497    bindingsData.group = bindGroupGPU;
41498  }
41499  /**
41500   * Updates a buffer binding.
41501   *
41502   *  @param {Buffer} binding - The buffer binding to update.
41503   */
41504  updateBinding(binding) {
41505    const backend = this.backend;
41506    const device = backend.device;
41507    const array3 = binding.buffer;
41508    const buffer3 = backend.get(binding).buffer;
41509    const updateRanges = binding.updateRanges;
41510    if (updateRanges.length === 0) {
41511      device.queue.writeBuffer(
41512        buffer3,
41513        0,
41514        array3,
41515        0
41516      );
41517    } else {
41518      const isTyped = isTypedArray(array3);
41519      const byteOffsetFactor = isTyped ? 1 : array3.BYTES_PER_ELEMENT;
41520      for (let i = 0, l = updateRanges.length; i < l; i++) {
41521        const range3 = updateRanges[i];
41522        const dataOffset = range3.start * byteOffsetFactor;
41523        const size3 = range3.count * byteOffsetFactor;
41524        const bufferOffset = dataOffset * (isTyped ? array3.BYTES_PER_ELEMENT : 1);
41525        device.queue.writeBuffer(
41526          buffer3,
41527          bufferOffset,
41528          array3,
41529          dataOffset,
41530          size3
41531        );
41532      }
41533    }
41534  }
41535  /**
41536   * Creates a GPU bind group for the camera index.
41537   *
41538   * @param {Uint32Array} data - The index data.
41539   * @param {GPUBindGroupLayout} layoutGPU - The GPU bind group layout.
41540   * @return {GPUBindGroup} The GPU bind group.
41541   */
41542  createBindGroupIndex(data, layoutGPU) {
41543    const backend = this.backend;
41544    const device = backend.device;
41545    const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
41546    const index = data[0];
41547    const buffer3 = device.createBuffer({
41548      label: "bindingCameraIndex_" + index,
41549      size: 16,
41550      // uint(4) * 4
41551      usage
41552    });
41553    device.queue.writeBuffer(buffer3, 0, data, 0);
41554    const entries5 = [{ binding: 0, resource: { buffer: buffer3 } }];
41555    return device.createBindGroup({
41556      label: "bindGroupCameraIndex_" + index,
41557      layout: layoutGPU,
41558      entries: entries5
41559    });
41560  }
41561  /**
41562   * Creates a GPU bind group for the given bind group and GPU layout.
41563   *
41564   * @param {BindGroup} bindGroup - The bind group.
41565   * @param {GPUBindGroupLayout} layoutGPU - The GPU bind group layout.
41566   * @return {GPUBindGroup} The GPU bind group.
41567   */
41568  createBindGroup(bindGroup, layoutGPU) {
41569    const backend = this.backend;
41570    const device = backend.device;
41571    let bindingPoint = 0;
41572    const entriesGPU = [];
41573    for (const binding of bindGroup.bindings) {
41574      if (binding.isUniformBuffer) {
41575        const bindingData = backend.get(binding);
41576        if (bindingData.buffer === void 0) {
41577          const byteLength = binding.byteLength;
41578          const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
41579          const visibilities = [];
41580          if (binding.visibility & GPUShaderStage.VERTEX) {
41581            visibilities.push("vertex");
41582          }
41583          if (binding.visibility & GPUShaderStage.FRAGMENT) {
41584            visibilities.push("fragment");
41585          }
41586          if (binding.visibility & GPUShaderStage.COMPUTE) {
41587            visibilities.push("compute");
41588          }
41589          const bufferVisibility = `(${visibilities.join(",")})`;
41590          const bufferGPU = device.createBuffer({
41591            label: `bindingBuffer${binding.id}_${binding.name}_${bufferVisibility}`,
41592            size: byteLength,
41593            usage
41594          });
41595          bindingData.buffer = bufferGPU;
41596        }
41597        entriesGPU.push({ binding: bindingPoint, resource: { buffer: bindingData.buffer } });
41598      } else if (binding.isStorageBuffer) {
41599        const buffer3 = backend.get(binding.attribute).buffer;
41600        entriesGPU.push({ binding: bindingPoint, resource: { buffer: buffer3 } });
41601      } else if (binding.isSampledTexture) {
41602        const textureData = backend.get(binding.texture);
41603        let resourceGPU;
41604        if (textureData.externalTexture !== void 0) {
41605          resourceGPU = device.importExternalTexture({ source: textureData.externalTexture });
41606        } else {
41607          const mipLevelCount = binding.store ? 1 : textureData.texture.mipLevelCount;
41608          const baseMipLevel = binding.store ? binding.mipLevel : 0;
41609          let propertyName = `view-${textureData.texture.width}-${textureData.texture.height}`;
41610          if (textureData.texture.depthOrArrayLayers > 1) {
41611            propertyName += `-${textureData.texture.depthOrArrayLayers}`;
41612          }
41613          propertyName += `-${mipLevelCount}-${baseMipLevel}`;
41614          resourceGPU = textureData[propertyName];
41615          if (resourceGPU === void 0) {
41616            const aspectGPU = GPUTextureAspect.All;
41617            let dimensionViewGPU;
41618            if (binding.isSampledCubeTexture) {
41619              dimensionViewGPU = GPUTextureViewDimension.Cube;
41620            } else if (binding.isSampledTexture3D) {
41621              dimensionViewGPU = GPUTextureViewDimension.ThreeD;
41622            } else if (binding.texture.isArrayTexture || binding.texture.isDataArrayTexture || binding.texture.isCompressedArrayTexture) {
41623              dimensionViewGPU = GPUTextureViewDimension.TwoDArray;
41624            } else {
41625              dimensionViewGPU = GPUTextureViewDimension.TwoD;
41626            }
41627            resourceGPU = textureData[propertyName] = textureData.texture.createView({ aspect: aspectGPU, dimension: dimensionViewGPU, mipLevelCount, baseMipLevel });
41628          }
41629        }
41630        entriesGPU.push({ binding: bindingPoint, resource: resourceGPU });
41631      } else if (binding.isSampler) {
41632        const textureGPU = backend.get(binding.texture);
41633        entriesGPU.push({ binding: bindingPoint, resource: textureGPU.sampler });
41634      }
41635      bindingPoint++;
41636    }
41637    return device.createBindGroup({
41638      label: "bindGroup_" + bindGroup.name,
41639      layout: layoutGPU,
41640      entries: entriesGPU
41641    });
41642  }
41643  /**
41644   * Creates a GPU bind group layout entries for the given bind group.
41645   *
41646   * @private
41647   * @param {BindGroup} bindGroup - The bind group.
41648   * @return {Array<GPUBindGroupLayoutEntry>} The GPU bind group layout entries.
41649   */
41650  _createLayoutEntries(bindGroup) {
41651    const entries5 = [];
41652    let index = 0;
41653    for (const binding of bindGroup.bindings) {
41654      const backend = this.backend;
41655      const bindingGPU = {
41656        binding: index,
41657        visibility: binding.visibility
41658      };
41659      if (binding.isUniformBuffer || binding.isStorageBuffer) {
41660        const buffer3 = {};
41661        if (binding.isStorageBuffer) {
41662          if (binding.visibility & GPUShaderStage.COMPUTE) {
41663            if (binding.access === NodeAccess.READ_WRITE || binding.access === NodeAccess.WRITE_ONLY) {
41664              buffer3.type = GPUBufferBindingType.Storage;
41665            } else {
41666              buffer3.type = GPUBufferBindingType.ReadOnlyStorage;
41667            }
41668          } else {
41669            buffer3.type = GPUBufferBindingType.ReadOnlyStorage;
41670          }
41671        }
41672        bindingGPU.buffer = buffer3;
41673      } else if (binding.isSampledTexture && binding.store) {
41674        const storageTexture3 = {};
41675        storageTexture3.format = this.backend.get(binding.texture).texture.format;
41676        const access6 = binding.access;
41677        if (access6 === NodeAccess.READ_WRITE) {
41678          storageTexture3.access = GPUStorageTextureAccess.ReadWrite;
41679        } else if (access6 === NodeAccess.WRITE_ONLY) {
41680          storageTexture3.access = GPUStorageTextureAccess.WriteOnly;
41681        } else {
41682          storageTexture3.access = GPUStorageTextureAccess.ReadOnly;
41683        }
41684        if (binding.texture.isArrayTexture) {
41685          storageTexture3.viewDimension = GPUTextureViewDimension.TwoDArray;
41686        } else if (binding.texture.is3DTexture) {
41687          storageTexture3.viewDimension = GPUTextureViewDimension.ThreeD;
41688        }
41689        bindingGPU.storageTexture = storageTexture3;
41690      } else if (binding.isSampledTexture) {
41691        const texture3 = {};
41692        const { primarySamples } = backend.utils.getTextureSampleData(binding.texture);
41693        if (primarySamples > 1) {
41694          texture3.multisampled = true;
41695          if (!binding.texture.isDepthTexture) {
41696            texture3.sampleType = GPUTextureSampleType.UnfilterableFloat;
41697          }
41698        }
41699        if (binding.texture.isDepthTexture) {
41700          if (backend.compatibilityMode && binding.texture.compareFunction === null) {
41701            texture3.sampleType = GPUTextureSampleType.UnfilterableFloat;
41702          } else {
41703            texture3.sampleType = GPUTextureSampleType.Depth;
41704          }
41705        } else if (binding.texture.isDataTexture || binding.texture.isDataArrayTexture || binding.texture.isData3DTexture || binding.texture.isStorageTexture) {
41706          const type = binding.texture.type;
41707          if (type === IntType) {
41708            texture3.sampleType = GPUTextureSampleType.SInt;
41709          } else if (type === UnsignedIntType) {
41710            texture3.sampleType = GPUTextureSampleType.UInt;
41711          } else if (type === FloatType) {
41712            if (this.backend.hasFeature("float32-filterable")) {
41713              texture3.sampleType = GPUTextureSampleType.Float;
41714            } else {
41715              texture3.sampleType = GPUTextureSampleType.UnfilterableFloat;
41716            }
41717          }
41718        }
41719        if (binding.isSampledCubeTexture) {
41720          texture3.viewDimension = GPUTextureViewDimension.Cube;
41721        } else if (binding.texture.isArrayTexture || binding.texture.isDataArrayTexture || binding.texture.isCompressedArrayTexture) {
41722          texture3.viewDimension = GPUTextureViewDimension.TwoDArray;
41723        } else if (binding.isSampledTexture3D) {
41724          texture3.viewDimension = GPUTextureViewDimension.ThreeD;
41725        }
41726        bindingGPU.texture = texture3;
41727      } else if (binding.isSampler) {
41728        const sampler3 = {};
41729        if (binding.texture.isDepthTexture) {
41730          if (binding.texture.compareFunction !== null && backend.hasCompatibility(Compatibility.TEXTURE_COMPARE)) {
41731            sampler3.type = GPUSamplerBindingType.Comparison;
41732          } else {
41733            sampler3.type = GPUSamplerBindingType.NonFiltering;
41734          }
41735        }
41736        bindingGPU.sampler = sampler3;
41737      } else {
41738        error(`WebGPUBindingUtils: Unsupported binding "${binding}".`);
41739      }
41740      entries5.push(bindingGPU);
41741      index++;
41742    }
41743    return entries5;
41744  }
41745  /**
41746   * Delete the data associated with a bind group.
41747   *
41748   * @param {BindGroup} bindGroup - The bind group.
41749   */
41750  deleteBindGroupData(bindGroup) {
41751    const { backend } = this;
41752    const bindingsData = backend.get(bindGroup);
41753    if (bindingsData.layout) {
41754      bindingsData.layout.usedTimes--;
41755      if (bindingsData.layout.usedTimes === 0) {
41756        this._bindGroupLayoutCache.delete(bindingsData.layoutKey);
41757      }
41758      bindingsData.layout = void 0;
41759      bindingsData.layoutKey = void 0;
41760    }
41761  }
41762  /**
41763   * Frees internal resources.
41764   */
41765  dispose() {
41766    this._bindGroupLayoutCache.clear();
41767  }
41768};
41769var WebGPUCapabilities = class {
41770  /**
41771   * Constructs a new utility object.
41772   *
41773   * @param {WebGPUBackend} backend - The WebGPU backend.
41774   */
41775  constructor(backend) {
41776    this.backend = backend;
41777  }
41778  /**
41779   * Returns the maximum anisotropy texture filtering value.
41780   *
41781   * @return {number} The maximum anisotropy texture filtering value.
41782   */
41783  getMaxAnisotropy() {
41784    return 16;
41785  }
41786  /**
41787   * Returns the maximum number of bytes available for uniform buffers.
41788   *
41789   * @return {number} The maximum number of bytes available for uniform buffers.
41790   */
41791  getUniformBufferLimit() {
41792    return this.backend.device.limits.maxUniformBufferBindingSize;
41793  }
41794};
41795var WebGPUPipelineUtils = class {
41796  /**
41797   * Constructs a new utility object.
41798   *
41799   * @param {WebGPUBackend} backend - The WebGPU backend.
41800   */
41801  constructor(backend) {
41802    this.backend = backend;
41803    this._activePipelines = /* @__PURE__ */ new WeakMap();
41804  }
41805  /**
41806   * Sets the given pipeline for the given pass. The method makes sure to only set the
41807   * pipeline when necessary.
41808   *
41809   * @param {(GPURenderPassEncoder|GPUComputePassEncoder)} pass - The pass encoder.
41810   * @param {(GPURenderPipeline|GPUComputePipeline)} pipeline - The pipeline.
41811   */
41812  setPipeline(pass3, pipeline) {
41813    const currentPipeline = this._activePipelines.get(pass3);
41814    if (currentPipeline !== pipeline) {
41815      pass3.setPipeline(pipeline);
41816      this._activePipelines.set(pass3, pipeline);
41817    }
41818  }
41819  /**
41820   * Returns the sample count derived from the given render context.
41821   *
41822   * @private
41823   * @param {RenderContext} renderContext - The render context.
41824   * @return {number} The sample count.
41825   */
41826  _getSampleCount(renderContext) {
41827    return this.backend.utils.getSampleCountRenderContext(renderContext);
41828  }
41829  /**
41830   * Creates a render pipeline for the given render object.
41831   *
41832   * @param {RenderObject} renderObject - The render object.
41833   * @param {Array<Promise>} promises - An array of compilation promises which are used in `compileAsync()`.
41834   */
41835  createRenderPipeline(renderObject, promises) {
41836    const { object, material, geometry, pipeline } = renderObject;
41837    const { vertexProgram, fragmentProgram } = pipeline;
41838    const backend = this.backend;
41839    const device = backend.device;
41840    const utils = backend.utils;
41841    const pipelineData = backend.get(pipeline);
41842    const bindGroupLayouts = [];
41843    for (const bindGroup of renderObject.getBindings()) {
41844      const bindingsData = backend.get(bindGroup);
41845      const { layoutGPU } = bindingsData.layout;
41846      bindGroupLayouts.push(layoutGPU);
41847    }
41848    const vertexBuffers = backend.attributeUtils.createShaderVertexBuffers(renderObject);
41849    let materialBlending;
41850    if (material.blending !== NoBlending && (material.blending !== NormalBlending || material.transparent !== false)) {
41851      materialBlending = this._getBlending(material);
41852    }
41853    let stencilFront = {};
41854    if (material.stencilWrite === true) {
41855      stencilFront = {
41856        compare: this._getStencilCompare(material),
41857        failOp: this._getStencilOperation(material.stencilFail),
41858        depthFailOp: this._getStencilOperation(material.stencilZFail),
41859        passOp: this._getStencilOperation(material.stencilZPass)
41860      };
41861    }
41862    const colorWriteMask = this._getColorWriteMask(material);
41863    const targets = [];
41864    if (renderObject.context.textures !== null) {
41865      const textures = renderObject.context.textures;
41866      const mrt3 = renderObject.context.mrt;
41867      for (let i = 0; i < textures.length; i++) {
41868        const texture3 = textures[i];
41869        const colorFormat = utils.getTextureFormatGPU(texture3);
41870        let blending;
41871        if (mrt3 !== null) {
41872          if (this.backend.compatibilityMode !== true) {
41873            const blendMode = mrt3.getBlendMode(texture3.name);
41874            if (blendMode.blending === MaterialBlending) {
41875              blending = materialBlending;
41876            } else if (blendMode.blending !== NoBlending) {
41877              blending = this._getBlending(blendMode);
41878            }
41879          } else {
41880            warnOnce("WebGPURenderer: Multiple Render Targets (MRT) blending configuration is not fully supported in compatibility mode. The material blending will be used for all render targets.");
41881            blending = materialBlending;
41882          }
41883        } else {
41884          blending = materialBlending;
41885        }
41886        targets.push({
41887          format: colorFormat,
41888          blend: blending,
41889          writeMask: colorWriteMask
41890        });
41891      }
41892    } else {
41893      const colorFormat = utils.getCurrentColorFormat(renderObject.context);
41894      targets.push({
41895        format: colorFormat,
41896        blend: materialBlending,
41897        writeMask: colorWriteMask
41898      });
41899    }
41900    const vertexModule = backend.get(vertexProgram).module;
41901    const fragmentModule = backend.get(fragmentProgram).module;
41902    const primitiveState = this._getPrimitiveState(object, geometry, material);
41903    const depthCompare = this._getDepthCompare(material);
41904    const depthStencilFormat = utils.getCurrentDepthStencilFormat(renderObject.context);
41905    const sampleCount = this._getSampleCount(renderObject.context);
41906    const pipelineDescriptor = {
41907      label: `renderPipeline_${material.name || material.type}_${material.id}`,
41908      vertex: Object.assign({}, vertexModule, { buffers: vertexBuffers }),
41909      fragment: Object.assign({}, fragmentModule, { targets }),
41910      primitive: primitiveState,
41911      multisample: {
41912        count: sampleCount,
41913        alphaToCoverageEnabled: material.alphaToCoverage && sampleCount > 1
41914      },
41915      layout: device.createPipelineLayout({
41916        bindGroupLayouts
41917      })
41918    };
41919    const depthStencil = {};
41920    const renderDepth = renderObject.context.depth;
41921    const renderStencil = renderObject.context.stencil;
41922    if (renderDepth === true || renderStencil === true) {
41923      if (renderDepth === true) {
41924        depthStencil.format = depthStencilFormat;
41925        depthStencil.depthWriteEnabled = material.depthWrite;
41926        depthStencil.depthCompare = depthCompare;
41927      }
41928      if (renderStencil === true) {
41929        depthStencil.stencilFront = stencilFront;
41930        depthStencil.stencilBack = stencilFront;
41931        depthStencil.stencilReadMask = material.stencilFuncMask;
41932        depthStencil.stencilWriteMask = material.stencilWriteMask;
41933      }
41934      if (material.polygonOffset === true) {
41935        depthStencil.depthBias = material.polygonOffsetUnits;
41936        depthStencil.depthBiasSlopeScale = material.polygonOffsetFactor;
41937        depthStencil.depthBiasClamp = 0;
41938      }
41939      pipelineDescriptor.depthStencil = depthStencil;
41940    }
41941    device.pushErrorScope("validation");
41942    if (promises === null) {
41943      pipelineData.pipeline = device.createRenderPipeline(pipelineDescriptor);
41944      device.popErrorScope().then((err) => {
41945        if (err !== null) {
41946          pipelineData.error = true;
41947          error(err.message);
41948        }
41949      });
41950    } else {
41951      const p = new Promise(async (resolve) => {
41952        try {
41953          pipelineData.pipeline = await device.createRenderPipelineAsync(pipelineDescriptor);
41954        } catch (err) {
41955        }
41956        const errorScope = await device.popErrorScope();
41957        if (errorScope !== null) {
41958          pipelineData.error = true;
41959          error(errorScope.message);
41960        }
41961        resolve();
41962      });
41963      promises.push(p);
41964    }
41965  }
41966  /**
41967   * Creates GPU render bundle encoder for the given render context.
41968   *
41969   * @param {RenderContext} renderContext - The render context.
41970   * @param {?string} [label='renderBundleEncoder'] - The label.
41971   * @return {GPURenderBundleEncoder} The GPU render bundle encoder.
41972   */
41973  createBundleEncoder(renderContext, label3 = "renderBundleEncoder") {
41974    const backend = this.backend;
41975    const { utils, device } = backend;
41976    const depthStencilFormat = utils.getCurrentDepthStencilFormat(renderContext);
41977    const colorFormats = utils.getCurrentColorFormats(renderContext);
41978    const sampleCount = this._getSampleCount(renderContext);
41979    const descriptor = {
41980      label: label3,
41981      colorFormats,
41982      depthStencilFormat,
41983      sampleCount
41984    };
41985    return device.createRenderBundleEncoder(descriptor);
41986  }
41987  /**
41988   * Creates a compute pipeline for the given compute node.
41989   *
41990   * @param {ComputePipeline} pipeline - The compute pipeline.
41991   * @param {Array<BindGroup>} bindings - The bindings.
41992   */
41993  createComputePipeline(pipeline, bindings) {
41994    const backend = this.backend;
41995    const device = backend.device;
41996    const computeProgram = backend.get(pipeline.computeProgram).module;
41997    const pipelineGPU = backend.get(pipeline);
41998    const bindGroupLayouts = [];
41999    for (const bindingsGroup of bindings) {
42000      const bindingsData = backend.get(bindingsGroup);
42001      const { layoutGPU } = bindingsData.layout;
42002      bindGroupLayouts.push(layoutGPU);
42003    }
42004    pipelineGPU.pipeline = device.createComputePipeline({
42005      compute: computeProgram,
42006      layout: device.createPipelineLayout({
42007        bindGroupLayouts
42008      })
42009    });
42010  }
42011  /**
42012   * Returns the blending state as a descriptor object required
42013   * for the pipeline creation.
42014   *
42015   * @private
42016   * @param {Material|BlendMode} object - The object containing blending information.
42017   * @return {Object} The blending state.
42018   */
42019  _getBlending(object) {
42020    let color3, alpha;
42021    const blending = object.blending;
42022    const blendSrc = object.blendSrc;
42023    const blendDst = object.blendDst;
42024    const blendEquation = object.blendEquation;
42025    if (blending === CustomBlending) {
42026      const blendSrcAlpha = object.blendSrcAlpha !== null ? object.blendSrcAlpha : blendSrc;
42027      const blendDstAlpha = object.blendDstAlpha !== null ? object.blendDstAlpha : blendDst;
42028      const blendEquationAlpha = object.blendEquationAlpha !== null ? object.blendEquationAlpha : blendEquation;
42029      color3 = {
42030        srcFactor: this._getBlendFactor(blendSrc),
42031        dstFactor: this._getBlendFactor(blendDst),
42032        operation: this._getBlendOperation(blendEquation)
42033      };
42034      alpha = {
42035        srcFactor: this._getBlendFactor(blendSrcAlpha),
42036        dstFactor: this._getBlendFactor(blendDstAlpha),
42037        operation: this._getBlendOperation(blendEquationAlpha)
42038      };
42039    } else {
42040      const premultipliedAlpha = object.premultipliedAlpha;
42041      const setBlend = (srcRGB, dstRGB, srcAlpha, dstAlpha) => {
42042        color3 = {
42043          srcFactor: srcRGB,
42044          dstFactor: dstRGB,
42045          operation: GPUBlendOperation.Add
42046        };
42047        alpha = {
42048          srcFactor: srcAlpha,
42049          dstFactor: dstAlpha,
42050          operation: GPUBlendOperation.Add
42051        };
42052      };
42053      if (premultipliedAlpha) {
42054        switch (blending) {
42055          case NormalBlending:
42056            setBlend(GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha);
42057            break;
42058          case AdditiveBlending:
42059            setBlend(GPUBlendFactor.One, GPUBlendFactor.One, GPUBlendFactor.One, GPUBlendFactor.One);
42060            break;
42061          case SubtractiveBlending:
42062            setBlend(GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One);
42063            break;
42064          case MultiplyBlending:
42065            setBlend(GPUBlendFactor.Dst, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.Zero, GPUBlendFactor.One);
42066            break;
42067        }
42068      } else {
42069        switch (blending) {
42070          case NormalBlending:
42071            setBlend(GPUBlendFactor.SrcAlpha, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha);
42072            break;
42073          case AdditiveBlending:
42074            setBlend(GPUBlendFactor.SrcAlpha, GPUBlendFactor.One, GPUBlendFactor.One, GPUBlendFactor.One);
42075            break;
42076          case SubtractiveBlending:
42077            error(`WebGPURenderer: "SubtractiveBlending" requires "${object.isMaterial ? "material" : "blendMode"}.premultipliedAlpha = true".`);
42078            break;
42079          case MultiplyBlending:
42080            error(`WebGPURenderer: "MultiplyBlending" requires "${object.isMaterial ? "material" : "blendMode"}.premultipliedAlpha = true".`);
42081            break;
42082        }
42083      }
42084    }
42085    if (color3 !== void 0 && alpha !== void 0) {
42086      return { color: color3, alpha };
42087    } else {
42088      error("WebGPURenderer: Invalid blending: ", blending);
42089    }
42090  }
42091  /**
42092   * Returns the GPU blend factor which is required for the pipeline creation.
42093   *
42094   * @private
42095   * @param {number} blend - The blend factor as a three.js constant.
42096   * @return {string} The GPU blend factor.
42097   */
42098  _getBlendFactor(blend) {
42099    let blendFactor;
42100    switch (blend) {
42101      case ZeroFactor:
42102        blendFactor = GPUBlendFactor.Zero;
42103        break;
42104      case OneFactor:
42105        blendFactor = GPUBlendFactor.One;
42106        break;
42107      case SrcColorFactor:
42108        blendFactor = GPUBlendFactor.Src;
42109        break;
42110      case OneMinusSrcColorFactor:
42111        blendFactor = GPUBlendFactor.OneMinusSrc;
42112        break;
42113      case SrcAlphaFactor:
42114        blendFactor = GPUBlendFactor.SrcAlpha;
42115        break;
42116      case OneMinusSrcAlphaFactor:
42117        blendFactor = GPUBlendFactor.OneMinusSrcAlpha;
42118        break;
42119      case DstColorFactor:
42120        blendFactor = GPUBlendFactor.Dst;
42121        break;
42122      case OneMinusDstColorFactor:
42123        blendFactor = GPUBlendFactor.OneMinusDst;
42124        break;
42125      case DstAlphaFactor:
42126        blendFactor = GPUBlendFactor.DstAlpha;
42127        break;
42128      case OneMinusDstAlphaFactor:
42129        blendFactor = GPUBlendFactor.OneMinusDstAlpha;
42130        break;
42131      case SrcAlphaSaturateFactor:
42132        blendFactor = GPUBlendFactor.SrcAlphaSaturated;
42133        break;
42134      case BlendColorFactor:
42135        blendFactor = GPUBlendFactor.Constant;
42136        break;
42137      case OneMinusBlendColorFactor:
42138        blendFactor = GPUBlendFactor.OneMinusConstant;
42139        break;
42140      default:
42141        error("WebGPURenderer: Blend factor not supported.", blend);
42142    }
42143    return blendFactor;
42144  }
42145  /**
42146   * Returns the GPU stencil compare function which is required for the pipeline creation.
42147   *
42148   * @private
42149   * @param {Material} material - The material.
42150   * @return {string} The GPU stencil compare function.
42151   */
42152  _getStencilCompare(material) {
42153    let stencilCompare;
42154    const stencilFunc = material.stencilFunc;
42155    switch (stencilFunc) {
42156      case NeverStencilFunc:
42157        stencilCompare = GPUCompareFunction.Never;
42158        break;
42159      case AlwaysStencilFunc:
42160        stencilCompare = GPUCompareFunction.Always;
42161        break;
42162      case LessStencilFunc:
42163        stencilCompare = GPUCompareFunction.Less;
42164        break;
42165      case LessEqualStencilFunc:
42166        stencilCompare = GPUCompareFunction.LessEqual;
42167        break;
42168      case EqualStencilFunc:
42169        stencilCompare = GPUCompareFunction.Equal;
42170        break;
42171      case GreaterEqualStencilFunc:
42172        stencilCompare = GPUCompareFunction.GreaterEqual;
42173        break;
42174      case GreaterStencilFunc:
42175        stencilCompare = GPUCompareFunction.Greater;
42176        break;
42177      case NotEqualStencilFunc:
42178        stencilCompare = GPUCompareFunction.NotEqual;
42179        break;
42180      default:
42181        error("WebGPURenderer: Invalid stencil function.", stencilFunc);
42182    }
42183    return stencilCompare;
42184  }
42185  /**
42186   * Returns the GPU stencil operation which is required for the pipeline creation.
42187   *
42188   * @private
42189   * @param {number} op - A three.js constant defining the stencil operation.
42190   * @return {string} The GPU stencil operation.
42191   */
42192  _getStencilOperation(op) {
42193    let stencilOperation;
42194    switch (op) {
42195      case KeepStencilOp:
42196        stencilOperation = GPUStencilOperation.Keep;
42197        break;
42198      case ZeroStencilOp:
42199        stencilOperation = GPUStencilOperation.Zero;
42200        break;
42201      case ReplaceStencilOp:
42202        stencilOperation = GPUStencilOperation.Replace;
42203        break;
42204      case InvertStencilOp:
42205        stencilOperation = GPUStencilOperation.Invert;
42206        break;
42207      case IncrementStencilOp:
42208        stencilOperation = GPUStencilOperation.IncrementClamp;
42209        break;
42210      case DecrementStencilOp:
42211        stencilOperation = GPUStencilOperation.DecrementClamp;
42212        break;
42213      case IncrementWrapStencilOp:
42214        stencilOperation = GPUStencilOperation.IncrementWrap;
42215        break;
42216      case DecrementWrapStencilOp:
42217        stencilOperation = GPUStencilOperation.DecrementWrap;
42218        break;
42219      default:
42220        error("WebGPURenderer: Invalid stencil operation.", stencilOperation);
42221    }
42222    return stencilOperation;
42223  }
42224  /**
42225   * Returns the GPU blend operation which is required for the pipeline creation.
42226   *
42227   * @private
42228   * @param {number} blendEquation - A three.js constant defining the blend equation.
42229   * @return {string} The GPU blend operation.
42230   */
42231  _getBlendOperation(blendEquation) {
42232    let blendOperation;
42233    switch (blendEquation) {
42234      case AddEquation:
42235        blendOperation = GPUBlendOperation.Add;
42236        break;
42237      case SubtractEquation:
42238        blendOperation = GPUBlendOperation.Subtract;
42239        break;
42240      case ReverseSubtractEquation:
42241        blendOperation = GPUBlendOperation.ReverseSubtract;
42242        break;
42243      case MinEquation:
42244        blendOperation = GPUBlendOperation.Min;
42245        break;
42246      case MaxEquation:
42247        blendOperation = GPUBlendOperation.Max;
42248        break;
42249      default:
42250        error("WebGPUPipelineUtils: Blend equation not supported.", blendEquation);
42251    }
42252    return blendOperation;
42253  }
42254  /**
42255   * Returns the primitive state as a descriptor object required
42256   * for the pipeline creation.
42257   *
42258   * @private
42259   * @param {Object3D} object - The 3D object.
42260   * @param {BufferGeometry} geometry - The geometry.
42261   * @param {Material} material - The material.
42262   * @return {Object} The primitive state.
42263   */
42264  _getPrimitiveState(object, geometry, material) {
42265    const descriptor = {};
42266    const utils = this.backend.utils;
42267    descriptor.topology = utils.getPrimitiveTopology(object, material);
42268    if (geometry.index !== null && object.isLine === true && object.isLineSegments !== true) {
42269      descriptor.stripIndexFormat = geometry.index.array instanceof Uint16Array ? GPUIndexFormat.Uint16 : GPUIndexFormat.Uint32;
42270    }
42271    let flipSided = material.side === BackSide;
42272    if (object.isMesh && object.matrixWorld.determinant() < 0) flipSided = !flipSided;
42273    descriptor.frontFace = flipSided === true ? GPUFrontFace.CW : GPUFrontFace.CCW;
42274    descriptor.cullMode = material.side === DoubleSide ? GPUCullMode.None : GPUCullMode.Back;
42275    return descriptor;
42276  }
42277  /**
42278   * Returns the GPU color write mask which is required for the pipeline creation.
42279   *
42280   * @private
42281   * @param {Material} material - The material.
42282   * @return {number} The GPU color write mask.
42283   */
42284  _getColorWriteMask(material) {
42285    return material.colorWrite === true ? GPUColorWriteFlags.All : GPUColorWriteFlags.None;
42286  }
42287  /**
42288   * Returns the GPU depth compare function which is required for the pipeline creation.
42289   *
42290   * @private
42291   * @param {Material} material - The material.
42292   * @return {string} The GPU depth compare function.
42293   */
42294  _getDepthCompare(material) {
42295    let depthCompare;
42296    if (material.depthTest === false) {
42297      depthCompare = GPUCompareFunction.Always;
42298    } else {
42299      const depthFunc = this.backend.parameters.reversedDepthBuffer ? ReversedDepthFuncs[material.depthFunc] : material.depthFunc;
42300      switch (depthFunc) {
42301        case NeverDepth:
42302          depthCompare = GPUCompareFunction.Never;
42303          break;
42304        case AlwaysDepth:
42305          depthCompare = GPUCompareFunction.Always;
42306          break;
42307        case LessDepth:
42308          depthCompare = GPUCompareFunction.Less;
42309          break;
42310        case LessEqualDepth:
42311          depthCompare = GPUCompareFunction.LessEqual;
42312          break;
42313        case EqualDepth:
42314          depthCompare = GPUCompareFunction.Equal;
42315          break;
42316        case GreaterEqualDepth:
42317          depthCompare = GPUCompareFunction.GreaterEqual;
42318          break;
42319        case GreaterDepth:
42320          depthCompare = GPUCompareFunction.Greater;
42321          break;
42322        case NotEqualDepth:
42323          depthCompare = GPUCompareFunction.NotEqual;
42324          break;
42325        default:
42326          error("WebGPUPipelineUtils: Invalid depth function.", depthFunc);
42327      }
42328    }
42329    return depthCompare;
42330  }
42331};
42332var WebGPUTimestampQueryPool = class extends TimestampQueryPool {
42333  /**
42334   * Creates a new WebGPU timestamp query pool.
42335   *
42336   * @param {GPUDevice} device - The WebGPU device to create queries on.
42337   * @param {string} type - The type identifier for this query pool.
42338   * @param {number} [maxQueries=2048] - Maximum number of queries this pool can hold.
42339   */
42340  constructor(device, type, maxQueries = 2048) {
42341    super(maxQueries);
42342    this.device = device;
42343    this.type = type;
42344    this.querySet = this.device.createQuerySet({
42345      type: "timestamp",
42346      count: this.maxQueries,
42347      label: `queryset_global_timestamp_${type}`
42348    });
42349    const bufferSize = this.maxQueries * 8;
42350    this.resolveBuffer = this.device.createBuffer({
42351      label: `buffer_timestamp_resolve_${type}`,
42352      size: bufferSize,
42353      usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC
42354    });
42355    this.resultBuffer = this.device.createBuffer({
42356      label: `buffer_timestamp_result_${type}`,
42357      size: bufferSize,
42358      usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
42359    });
42360  }
42361  /**
42362   * Allocates a pair of queries for a given render context.
42363   *
42364   * @param {string} uid - A unique identifier for the render context.
42365   * @returns {?number} The base offset for the allocated queries, or null if allocation failed.
42366   */
42367  allocateQueriesForContext(uid) {
42368    if (!this.trackTimestamp || this.isDisposed) return null;
42369    if (this.currentQueryIndex + 2 > this.maxQueries) {
42370      warnOnce(`WebGPUTimestampQueryPool [${this.type}]: Maximum number of queries exceeded, when using trackTimestamp it is necessary to resolves the queries via renderer.resolveTimestampsAsync( THREE.TimestampQuery.${this.type.toUpperCase()} ).`);
42371      return null;
42372    }
42373    const baseOffset = this.currentQueryIndex;
42374    this.currentQueryIndex += 2;
42375    this.queryOffsets.set(uid, baseOffset);
42376    return baseOffset;
42377  }
42378  /**
42379   * Asynchronously resolves all pending queries and returns the total duration.
42380   * If there's already a pending resolve operation, returns that promise instead.
42381   *
42382   * @async
42383   * @returns {Promise<number>} The total duration in milliseconds, or the last valid value if resolution fails.
42384   */
42385  async resolveQueriesAsync() {
42386    if (!this.trackTimestamp || this.currentQueryIndex === 0 || this.isDisposed) {
42387      return this.lastValue;
42388    }
42389    if (this.pendingResolve) {
42390      return this.pendingResolve;
42391    }
42392    this.pendingResolve = this._resolveQueries();
42393    try {
42394      const result = await this.pendingResolve;
42395      return result;
42396    } finally {
42397      this.pendingResolve = null;
42398    }
42399  }
42400  /**
42401   * Internal method to resolve queries and calculate total duration.
42402   *
42403   * @async
42404   * @private
42405   * @returns {Promise<number>} The total duration in milliseconds.
42406   */
42407  async _resolveQueries() {
42408    if (this.isDisposed) {
42409      return this.lastValue;
42410    }
42411    try {
42412      if (this.resultBuffer.mapState !== "unmapped") {
42413        return this.lastValue;
42414      }
42415      const currentOffsets = new Map(this.queryOffsets);
42416      const queryCount = this.currentQueryIndex;
42417      const bytesUsed = queryCount * 8;
42418      this.currentQueryIndex = 0;
42419      this.queryOffsets.clear();
42420      const commandEncoder = this.device.createCommandEncoder();
42421      commandEncoder.resolveQuerySet(
42422        this.querySet,
42423        0,
42424        queryCount,
42425        this.resolveBuffer,
42426        0
42427      );
42428      commandEncoder.copyBufferToBuffer(
42429        this.resolveBuffer,
42430        0,
42431        this.resultBuffer,
42432        0,
42433        bytesUsed
42434      );
42435      const commandBuffer = commandEncoder.finish();
42436      this.device.queue.submit([commandBuffer]);
42437      if (this.resultBuffer.mapState !== "unmapped") {
42438        return this.lastValue;
42439      }
42440      await this.resultBuffer.mapAsync(GPUMapMode.READ, 0, bytesUsed);
42441      if (this.isDisposed) {
42442        if (this.resultBuffer.mapState === "mapped") {
42443          this.resultBuffer.unmap();
42444        }
42445        return this.lastValue;
42446      }
42447      const times = new BigUint64Array(this.resultBuffer.getMappedRange(0, bytesUsed));
42448      const framesDuration = {};
42449      const frames = [];
42450      for (const [uid, baseOffset] of currentOffsets) {
42451        const match = uid.match(/^(.*):f(\d+)$/);
42452        const frame = parseInt(match[2]);
42453        if (frames.includes(frame) === false) {
42454          frames.push(frame);
42455        }
42456        if (framesDuration[frame] === void 0) framesDuration[frame] = 0;
42457        const startTime = times[baseOffset];
42458        const endTime = times[baseOffset + 1];
42459        const duration = Number(endTime - startTime) / 1e6;
42460        this.timestamps.set(uid, duration);
42461        framesDuration[frame] += duration;
42462      }
42463      const totalDuration = framesDuration[frames[frames.length - 1]];
42464      this.resultBuffer.unmap();
42465      this.lastValue = totalDuration;
42466      this.frames = frames;
42467      return totalDuration;
42468    } catch (e) {
42469      error("Error resolving queries:", e);
42470      if (this.resultBuffer.mapState === "mapped") {
42471        this.resultBuffer.unmap();
42472      }
42473      return this.lastValue;
42474    }
42475  }
42476  /**
42477   * Dispose of the query pool.
42478   *
42479   * @async
42480   * @returns {Promise} A Promise that resolves when the dispose has been executed.
42481   */
42482  async dispose() {
42483    if (this.isDisposed) {
42484      return;
42485    }
42486    this.isDisposed = true;
42487    if (this.pendingResolve) {
42488      try {
42489        await this.pendingResolve;
42490      } catch (e) {
42491        error("Error waiting for pending resolve:", e);
42492      }
42493    }
42494    if (this.resultBuffer && this.resultBuffer.mapState === "mapped") {
42495      try {
42496        this.resultBuffer.unmap();
42497      } catch (e) {
42498        error("Error unmapping buffer:", e);
42499      }
42500    }
42501    if (this.querySet) {
42502      this.querySet.destroy();
42503      this.querySet = null;
42504    }
42505    if (this.resolveBuffer) {
42506      this.resolveBuffer.destroy();
42507      this.resolveBuffer = null;
42508    }
42509    if (this.resultBuffer) {
42510      this.resultBuffer.destroy();
42511      this.resultBuffer = null;
42512    }
42513    this.queryOffsets.clear();
42514    this.pendingResolve = null;
42515  }
42516};
42517var _clearValue = { r: 0, g: 0, b: 0, a: 1 };
42518var WebGPUBackend = class extends Backend {
42519  /**
42520   * WebGPUBackend options.
42521   *
42522   * @typedef {Object} WebGPUBackend~Options
42523   * @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
42524   * @property {boolean} [reversedDepthBuffer=false] - Whether reversed depth buffer is enabled or not.
42525   * @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
42526   * @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
42527   * @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
42528   * @property {boolean} [antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
42529   * @property {number} [samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default.
42530   * @property {boolean} [forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not.
42531   * @property {boolean} [trackTimestamp=false] - Whether to track timestamps with a Timestamp Query API or not.
42532   * @property {string} [powerPreference=undefined] - The power preference.
42533   * @property {Object} [requiredLimits=undefined] - Specifies the limits that are required by the device request. The request will fail if the adapter cannot provide these limits.
42534   * @property {GPUDevice} [device=undefined] - If there is an existing GPU device on app level, it can be passed to the renderer as a parameter.
42535   * @property {number} [outputType=undefined] - Texture type for output to canvas. By default, device's preferred format is used; other formats may incur overhead.
42536   */
42537  /**
42538   * Constructs a new WebGPU backend.
42539   *
42540   * @param {WebGPUBackend~Options} [parameters] - The configuration parameter.
42541   */
42542  constructor(parameters = {}) {
42543    super(parameters);
42544    this.isWebGPUBackend = true;
42545    this.parameters.alpha = parameters.alpha === void 0 ? true : parameters.alpha;
42546    this.parameters.requiredLimits = parameters.requiredLimits === void 0 ? {} : parameters.requiredLimits;
42547    this.compatibilityMode = null;
42548    this.device = null;
42549    this.defaultRenderPassdescriptor = null;
42550    this.utils = new WebGPUUtils(this);
42551    this.attributeUtils = new WebGPUAttributeUtils(this);
42552    this.bindingUtils = new WebGPUBindingUtils(this);
42553    this.capabilities = new WebGPUCapabilities(this);
42554    this.pipelineUtils = new WebGPUPipelineUtils(this);
42555    this.textureUtils = new WebGPUTextureUtils(this);
42556    this.occludedResolveCache = /* @__PURE__ */ new Map();
42557    const compatibilityTextureCompare = typeof navigator === "undefined" ? true : /Android/.test(navigator.userAgent) === false;
42558    this._compatibility = {
42559      [Compatibility.TEXTURE_COMPARE]: compatibilityTextureCompare
42560    };
42561  }
42562  /**
42563   * Initializes the backend so it is ready for usage.
42564   *
42565   * @async
42566   * @param {Renderer} renderer - The renderer.
42567   * @return {Promise} A Promise that resolves when the backend has been initialized.
42568   */
42569  async init(renderer) {
42570    await super.init(renderer);
42571    const parameters = this.parameters;
42572    let device;
42573    if (parameters.device === void 0) {
42574      const adapterOptions = {
42575        powerPreference: parameters.powerPreference,
42576        featureLevel: "compatibility"
42577      };
42578      const adapter = typeof navigator !== "undefined" ? await navigator.gpu.requestAdapter(adapterOptions) : null;
42579      if (adapter === null) {
42580        throw new Error("WebGPUBackend: Unable to create WebGPU adapter.");
42581      }
42582      const features = Object.values(GPUFeatureName);
42583      const supportedFeatures = [];
42584      for (const name of features) {
42585        if (adapter.features.has(name)) {
42586          supportedFeatures.push(name);
42587        }
42588      }
42589      const deviceDescriptor = {
42590        requiredFeatures: supportedFeatures,
42591        requiredLimits: parameters.requiredLimits
42592      };
42593      device = await adapter.requestDevice(deviceDescriptor);
42594    } else {
42595      device = parameters.device;
42596    }
42597    this.compatibilityMode = !device.features.has("core-features-and-limits");
42598    if (this.compatibilityMode) {
42599      renderer._samples = 0;
42600    }
42601    device.lost.then((info) => {
42602      if (info.reason === "destroyed") return;
42603      const deviceLossInfo = {
42604        api: "WebGPU",
42605        message: info.message || "Unknown reason",
42606        reason: info.reason || null,
42607        originalEvent: info
42608      };
42609      renderer.onDeviceLost(deviceLossInfo);
42610    });
42611    this.device = device;
42612    this.trackTimestamp = this.trackTimestamp && this.hasFeature(GPUFeatureName.TimestampQuery);
42613    this.updateSize();
42614  }
42615  /**
42616   * A reference to the context.
42617   *
42618   * @type {?GPUCanvasContext}
42619   * @default null
42620   */
42621  get context() {
42622    const canvasTarget = this.renderer.getCanvasTarget();
42623    const canvasData = this.get(canvasTarget);
42624    let context3 = canvasData.context;
42625    if (context3 === void 0) {
42626      const parameters = this.parameters;
42627      if (canvasTarget.isDefaultCanvasTarget === true && parameters.context !== void 0) {
42628        context3 = parameters.context;
42629      } else {
42630        context3 = canvasTarget.domElement.getContext("webgpu");
42631      }
42632      if ("setAttribute" in canvasTarget.domElement) canvasTarget.domElement.setAttribute("data-engine", `three.js r${REVISION} webgpu`);
42633      const alphaMode = parameters.alpha ? "premultiplied" : "opaque";
42634      const toneMappingMode = parameters.outputType === HalfFloatType ? "extended" : "standard";
42635      context3.configure({
42636        device: this.device,
42637        format: this.utils.getPreferredCanvasFormat(),
42638        usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
42639        alphaMode,
42640        toneMapping: {
42641          mode: toneMappingMode
42642        }
42643      });
42644      canvasData.context = context3;
42645    }
42646    return context3;
42647  }
42648  /**
42649   * The coordinate system of the backend.
42650   *
42651   * @type {number}
42652   * @readonly
42653   */
42654  get coordinateSystem() {
42655    return WebGPUCoordinateSystem;
42656  }
42657  /**
42658   * This method performs a readback operation by moving buffer data from
42659   * a storage buffer attribute from the GPU to the CPU. ReadbackBuffer can
42660   * be used to retain and reuse handles to the intermediate buffers and prevent
42661   * new allocation.
42662   *
42663   * @async
42664   * @param {BufferAttribute} attribute - The storage buffer attribute to read frm.
42665   * @param {number} count - The offset from which to start reading the
42666   * @param {number} offset - The storage buffer attribute.
42667   * @param {ReadbackBuffer|ArrayBuffer} target - The storage buffer attribute.
42668   * @return {Promise<ArrayBuffer|ReadbackBuffer>} A promise that resolves with the buffer data when the data are ready.
42669   */
42670  async getArrayBufferAsync(attribute3, target = null, offset3 = 0, count = -1) {
42671    return await this.attributeUtils.getArrayBufferAsync(attribute3, target, offset3, count);
42672  }
42673  /**
42674   * Returns the backend's rendering context.
42675   *
42676   * @return {GPUCanvasContext} The rendering context.
42677   */
42678  getContext() {
42679    return this.context;
42680  }
42681  /**
42682   * Returns the default render pass descriptor.
42683   *
42684   * In WebGPU, the default framebuffer must be configured
42685   * like custom framebuffers so the backend needs a render
42686   * pass descriptor even when rendering directly to screen.
42687   *
42688   * @private
42689   * @return {Object} The render pass descriptor.
42690   */
42691  _getDefaultRenderPassDescriptor() {
42692    const renderer = this.renderer;
42693    const canvasTarget = renderer.getCanvasTarget();
42694    const canvasData = this.get(canvasTarget);
42695    const samples = renderer.currentSamples;
42696    let descriptor = canvasData.descriptor;
42697    if (descriptor === void 0 || canvasData.samples !== samples) {
42698      descriptor = {
42699        colorAttachments: [{
42700          view: null
42701        }]
42702      };
42703      if (renderer.depth === true || renderer.stencil === true) {
42704        descriptor.depthStencilAttachment = {
42705          view: this.textureUtils.getDepthBuffer(renderer.depth, renderer.stencil).createView()
42706        };
42707      }
42708      const colorAttachment2 = descriptor.colorAttachments[0];
42709      if (samples > 0) {
42710        colorAttachment2.view = this.textureUtils.getColorBuffer().createView();
42711      } else {
42712        colorAttachment2.resolveTarget = void 0;
42713      }
42714      canvasData.descriptor = descriptor;
42715      canvasData.samples = samples;
42716    }
42717    const colorAttachment = descriptor.colorAttachments[0];
42718    if (samples > 0) {
42719      colorAttachment.resolveTarget = this.context.getCurrentTexture().createView();
42720    } else {
42721      colorAttachment.view = this.context.getCurrentTexture().createView();
42722    }
42723    return descriptor;
42724  }
42725  /**
42726   * Internal to determine if the current render target is a render target array with depth 2D array texture.
42727   *
42728   * @param {RenderContext} renderContext - The render context.
42729   * @return {boolean} Whether the render target is a render target array with depth 2D array texture.
42730   *
42731   * @private
42732   */
42733  _isRenderCameraDepthArray(renderContext) {
42734    return renderContext.depthTexture && renderContext.depthTexture.image.depth > 1 && renderContext.camera.isArrayCamera;
42735  }
42736  /**
42737   * Returns the render pass descriptor for the given render context.
42738   *
42739   * @private
42740   * @param {RenderContext} renderContext - The render context.
42741   * @param {Object} colorAttachmentsConfig - Configuration object for the color attachments.
42742   * @return {Object} The render pass descriptor.
42743   */
42744  _getRenderPassDescriptor(renderContext, colorAttachmentsConfig = {}) {
42745    const renderTarget = renderContext.renderTarget;
42746    const renderTargetData = this.get(renderTarget);
42747    let descriptors = renderTargetData.descriptors;
42748    if (descriptors === void 0 || renderTargetData.width !== renderTarget.width || renderTargetData.height !== renderTarget.height || renderTargetData.samples !== renderTarget.samples) {
42749      descriptors = {};
42750      renderTargetData.descriptors = descriptors;
42751    }
42752    const cacheKey = renderContext.getCacheKey();
42753    let descriptorBase = descriptors[cacheKey];
42754    if (descriptorBase === void 0) {
42755      const textures = renderContext.textures;
42756      const textureViews = [];
42757      let sliceIndex;
42758      const isRenderCameraDepthArray = this._isRenderCameraDepthArray(renderContext);
42759      for (let i = 0; i < textures.length; i++) {
42760        const textureData = this.get(textures[i]);
42761        const viewDescriptor = {
42762          label: `colorAttachment_${i}`,
42763          baseMipLevel: renderContext.activeMipmapLevel,
42764          mipLevelCount: 1,
42765          baseArrayLayer: renderContext.activeCubeFace,
42766          arrayLayerCount: 1,
42767          dimension: GPUTextureViewDimension.TwoD
42768        };
42769        if (renderTarget.isRenderTarget3D) {
42770          sliceIndex = renderContext.activeCubeFace;
42771          viewDescriptor.baseArrayLayer = 0;
42772          viewDescriptor.dimension = GPUTextureViewDimension.ThreeD;
42773          viewDescriptor.depthOrArrayLayers = textures[i].image.depth;
42774        } else if (renderTarget.isRenderTarget && textures[i].image.depth > 1) {
42775          if (isRenderCameraDepthArray === true) {
42776            const cameras = renderContext.camera.cameras;
42777            for (let layer = 0; layer < cameras.length; layer++) {
42778              const layerViewDescriptor = {
42779                ...viewDescriptor,
42780                baseArrayLayer: layer,
42781                arrayLayerCount: 1,
42782                dimension: GPUTextureViewDimension.TwoD
42783              };
42784              const textureView = textureData.texture.createView(layerViewDescriptor);
42785              textureViews.push({
42786                view: textureView,
42787                resolveTarget: void 0,
42788                depthSlice: void 0
42789              });
42790            }
42791          } else {
42792            viewDescriptor.dimension = GPUTextureViewDimension.TwoDArray;
42793            viewDescriptor.depthOrArrayLayers = textures[i].image.depth;
42794          }
42795        }
42796        if (isRenderCameraDepthArray !== true) {
42797          const textureView = textureData.texture.createView(viewDescriptor);
42798          let view, resolveTarget;
42799          if (textureData.msaaTexture !== void 0) {
42800            view = textureData.msaaTexture.createView();
42801            resolveTarget = textureView;
42802          } else {
42803            view = textureView;
42804            resolveTarget = void 0;
42805          }
42806          textureViews.push({
42807            view,
42808            resolveTarget,
42809            depthSlice: sliceIndex
42810          });
42811        }
42812      }
42813      descriptorBase = { textureViews };
42814      if (renderContext.depth) {
42815        const depthTextureData = this.get(renderContext.depthTexture);
42816        const options = {};
42817        if (renderContext.depthTexture.isArrayTexture || renderContext.depthTexture.isCubeTexture) {
42818          options.dimension = GPUTextureViewDimension.TwoD;
42819          options.arrayLayerCount = 1;
42820          options.baseArrayLayer = renderContext.activeCubeFace;
42821        }
42822        descriptorBase.depthStencilView = depthTextureData.texture.createView(options);
42823      }
42824      descriptors[cacheKey] = descriptorBase;
42825      renderTargetData.width = renderTarget.width;
42826      renderTargetData.height = renderTarget.height;
42827      renderTargetData.samples = renderTarget.samples;
42828      renderTargetData.activeMipmapLevel = renderContext.activeMipmapLevel;
42829      renderTargetData.activeCubeFace = renderContext.activeCubeFace;
42830    }
42831    const descriptor = {
42832      colorAttachments: []
42833    };
42834    for (let i = 0; i < descriptorBase.textureViews.length; i++) {
42835      const viewInfo = descriptorBase.textureViews[i];
42836      let clearValue = { r: 0, g: 0, b: 0, a: 1 };
42837      if (i === 0 && colorAttachmentsConfig.clearValue) {
42838        clearValue = colorAttachmentsConfig.clearValue;
42839      }
42840      descriptor.colorAttachments.push({
42841        view: viewInfo.view,
42842        depthSlice: viewInfo.depthSlice,
42843        resolveTarget: viewInfo.resolveTarget,
42844        loadOp: colorAttachmentsConfig.loadOp || GPULoadOp.Load,
42845        storeOp: colorAttachmentsConfig.storeOp || GPUStoreOp.Store,
42846        clearValue
42847      });
42848    }
42849    if (descriptorBase.depthStencilView) {
42850      descriptor.depthStencilAttachment = {
42851        view: descriptorBase.depthStencilView
42852      };
42853    }
42854    return descriptor;
42855  }
42856  /**
42857   * This method is executed at the beginning of a render call and prepares
42858   * the WebGPU state for upcoming render calls
42859   *
42860   * @param {RenderContext} renderContext - The render context.
42861   */
42862  beginRender(renderContext) {
42863    const renderContextData = this.get(renderContext);
42864    const device = this.device;
42865    const occlusionQueryCount = renderContext.occlusionQueryCount;
42866    let occlusionQuerySet;
42867    if (occlusionQueryCount > 0) {
42868      if (renderContextData.currentOcclusionQuerySet) renderContextData.currentOcclusionQuerySet.destroy();
42869      if (renderContextData.currentOcclusionQueryBuffer) renderContextData.currentOcclusionQueryBuffer.destroy();
42870      renderContextData.currentOcclusionQuerySet = renderContextData.occlusionQuerySet;
42871      renderContextData.currentOcclusionQueryBuffer = renderContextData.occlusionQueryBuffer;
42872      renderContextData.currentOcclusionQueryObjects = renderContextData.occlusionQueryObjects;
42873      occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: occlusionQueryCount, label: `occlusionQuerySet_${renderContext.id}` });
42874      renderContextData.occlusionQuerySet = occlusionQuerySet;
42875      renderContextData.occlusionQueryIndex = 0;
42876      renderContextData.occlusionQueryObjects = new Array(occlusionQueryCount);
42877      renderContextData.lastOcclusionObject = null;
42878    }
42879    let descriptor;
42880    if (renderContext.textures === null) {
42881      descriptor = this._getDefaultRenderPassDescriptor();
42882    } else {
42883      descriptor = this._getRenderPassDescriptor(renderContext, { loadOp: GPULoadOp.Load });
42884    }
42885    this.initTimestampQuery(TimestampQuery.RENDER, this.getTimestampUID(renderContext), descriptor);
42886    descriptor.occlusionQuerySet = occlusionQuerySet;
42887    const depthStencilAttachment = descriptor.depthStencilAttachment;
42888    if (renderContext.textures !== null) {
42889      const colorAttachments = descriptor.colorAttachments;
42890      for (let i = 0; i < colorAttachments.length; i++) {
42891        const colorAttachment = colorAttachments[i];
42892        if (renderContext.clearColor) {
42893          if (i === 0) {
42894            colorAttachment.clearValue = renderContext.clearColorValue;
42895          } else {
42896            _clearValue.r = 0;
42897            _clearValue.g = 0;
42898            _clearValue.b = 0;
42899            _clearValue.a = 1;
42900            colorAttachment.clearValue = _clearValue;
42901          }
42902          colorAttachment.loadOp = GPULoadOp.Clear;
42903        } else {
42904          colorAttachment.loadOp = GPULoadOp.Load;
42905        }
42906        colorAttachment.storeOp = GPUStoreOp.Store;
42907      }
42908    } else {
42909      const colorAttachment = descriptor.colorAttachments[0];
42910      if (renderContext.clearColor) {
42911        colorAttachment.clearValue = renderContext.clearColorValue;
42912        colorAttachment.loadOp = GPULoadOp.Clear;
42913      } else {
42914        colorAttachment.loadOp = GPULoadOp.Load;
42915      }
42916      colorAttachment.storeOp = GPUStoreOp.Store;
42917    }
42918    if (renderContext.depth) {
42919      if (renderContext.clearDepth) {
42920        depthStencilAttachment.depthClearValue = renderContext.clearDepthValue;
42921        depthStencilAttachment.depthLoadOp = GPULoadOp.Clear;
42922      } else {
42923        depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
42924      }
42925      depthStencilAttachment.depthStoreOp = GPUStoreOp.Store;
42926    }
42927    if (renderContext.stencil) {
42928      if (renderContext.clearStencil) {
42929        depthStencilAttachment.stencilClearValue = renderContext.clearStencilValue;
42930        depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear;
42931      } else {
42932        depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
42933      }
42934      depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store;
42935    }
42936    const encoder = device.createCommandEncoder({ label: "renderContext_" + renderContext.id });
42937    if (this._isRenderCameraDepthArray(renderContext) === true) {
42938      const cameras = renderContext.camera.cameras;
42939      if (!renderContextData.layerDescriptors || renderContextData.layerDescriptors.length !== cameras.length) {
42940        this._createDepthLayerDescriptors(renderContext, renderContextData, descriptor, cameras);
42941      } else {
42942        this._updateDepthLayerDescriptors(renderContext, renderContextData, cameras);
42943      }
42944      renderContextData.bundleEncoders = [];
42945      renderContextData.bundleSets = [];
42946      for (let i = 0; i < cameras.length; i++) {
42947        const bundleEncoder = this.pipelineUtils.createBundleEncoder(
42948          renderContext,
42949          "renderBundleArrayCamera_" + i
42950        );
42951        const bundleSets = {
42952          attributes: {},
42953          bindingGroups: [],
42954          pipeline: null,
42955          index: null
42956        };
42957        renderContextData.bundleEncoders.push(bundleEncoder);
42958        renderContextData.bundleSets.push(bundleSets);
42959      }
42960      renderContextData.currentPass = null;
42961    } else {
42962      const currentPass = encoder.beginRenderPass(descriptor);
42963      renderContextData.currentPass = currentPass;
42964      if (renderContext.viewport) {
42965        this.updateViewport(renderContext);
42966      }
42967      if (renderContext.scissor) {
42968        this.updateScissor(renderContext);
42969      }
42970    }
42971    renderContextData.descriptor = descriptor;
42972    renderContextData.encoder = encoder;
42973    renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null };
42974    renderContextData.renderBundles = [];
42975  }
42976  /**
42977   * This method creates layer descriptors for each camera in an array camera
42978   * to prepare for rendering to a depth array texture.
42979   *
42980   * @param {RenderContext} renderContext - The render context.
42981   * @param {Object} renderContextData - The render context data.
42982   * @param {Object} descriptor  - The render pass descriptor.
42983   * @param {ArrayCamera} cameras - The array camera.
42984   *
42985   * @private
42986   */
42987  _createDepthLayerDescriptors(renderContext, renderContextData, descriptor, cameras) {
42988    const depthStencilAttachment = descriptor.depthStencilAttachment;
42989    renderContextData.layerDescriptors = [];
42990    const depthTextureData = this.get(renderContext.depthTexture);
42991    if (!depthTextureData.viewCache) {
42992      depthTextureData.viewCache = [];
42993    }
42994    for (let i = 0; i < cameras.length; i++) {
42995      const layerDescriptor = {
42996        ...descriptor,
42997        colorAttachments: [{
42998          ...descriptor.colorAttachments[0],
42999          view: descriptor.colorAttachments[i].view
43000        }]
43001      };
43002      if (descriptor.depthStencilAttachment) {
43003        const layerIndex = i;
43004        if (!depthTextureData.viewCache[layerIndex]) {
43005          depthTextureData.viewCache[layerIndex] = depthTextureData.texture.createView({
43006            dimension: GPUTextureViewDimension.TwoD,
43007            baseArrayLayer: i,
43008            arrayLayerCount: 1
43009          });
43010        }
43011        layerDescriptor.depthStencilAttachment = {
43012          view: depthTextureData.viewCache[layerIndex],
43013          depthLoadOp: depthStencilAttachment.depthLoadOp || GPULoadOp.Clear,
43014          depthStoreOp: depthStencilAttachment.depthStoreOp || GPUStoreOp.Store,
43015          depthClearValue: depthStencilAttachment.depthClearValue || 1
43016        };
43017        if (renderContext.stencil) {
43018          layerDescriptor.depthStencilAttachment.stencilLoadOp = depthStencilAttachment.stencilLoadOp;
43019          layerDescriptor.depthStencilAttachment.stencilStoreOp = depthStencilAttachment.stencilStoreOp;
43020          layerDescriptor.depthStencilAttachment.stencilClearValue = depthStencilAttachment.stencilClearValue;
43021        }
43022      } else {
43023        layerDescriptor.depthStencilAttachment = { ...depthStencilAttachment };
43024      }
43025      renderContextData.layerDescriptors.push(layerDescriptor);
43026    }
43027  }
43028  /**
43029   * This method updates the layer descriptors for each camera in an array camera
43030   * to prepare for rendering to a depth array texture.
43031   *
43032   * @param {RenderContext} renderContext - The render context.
43033   * @param {Object} renderContextData - The render context data.
43034   * @param {ArrayCamera} cameras - The array camera.
43035   *
43036   */
43037  _updateDepthLayerDescriptors(renderContext, renderContextData, cameras) {
43038    for (let i = 0; i < cameras.length; i++) {
43039      const layerDescriptor = renderContextData.layerDescriptors[i];
43040      if (layerDescriptor.depthStencilAttachment) {
43041        const depthAttachment = layerDescriptor.depthStencilAttachment;
43042        if (renderContext.depth) {
43043          if (renderContext.clearDepth) {
43044            depthAttachment.depthClearValue = renderContext.clearDepthValue;
43045            depthAttachment.depthLoadOp = GPULoadOp.Clear;
43046          } else {
43047            depthAttachment.depthLoadOp = GPULoadOp.Load;
43048          }
43049        }
43050        if (renderContext.stencil) {
43051          if (renderContext.clearStencil) {
43052            depthAttachment.stencilClearValue = renderContext.clearStencilValue;
43053            depthAttachment.stencilLoadOp = GPULoadOp.Clear;
43054          } else {
43055            depthAttachment.stencilLoadOp = GPULoadOp.Load;
43056          }
43057        }
43058      }
43059    }
43060  }
43061  /**
43062   * This method is executed at the end of a render call and finalizes work
43063   * after draw calls.
43064   *
43065   * @param {RenderContext} renderContext - The render context.
43066   */
43067  finishRender(renderContext) {
43068    const renderContextData = this.get(renderContext);
43069    const occlusionQueryCount = renderContext.occlusionQueryCount;
43070    if (renderContextData.renderBundles.length > 0) {
43071      renderContextData.currentPass.executeBundles(renderContextData.renderBundles);
43072    }
43073    if (occlusionQueryCount > renderContextData.occlusionQueryIndex) {
43074      renderContextData.currentPass.endOcclusionQuery();
43075    }
43076    const encoder = renderContextData.encoder;
43077    if (this._isRenderCameraDepthArray(renderContext) === true) {
43078      const bundles = [];
43079      for (let i = 0; i < renderContextData.bundleEncoders.length; i++) {
43080        const bundleEncoder = renderContextData.bundleEncoders[i];
43081        bundles.push(bundleEncoder.finish());
43082      }
43083      for (let i = 0; i < renderContextData.layerDescriptors.length; i++) {
43084        if (i < bundles.length) {
43085          const layerDescriptor = renderContextData.layerDescriptors[i];
43086          const renderPass = encoder.beginRenderPass(layerDescriptor);
43087          if (renderContext.viewport) {
43088            const { x, y, width, height, minDepth, maxDepth } = renderContext.viewportValue;
43089            renderPass.setViewport(x, y, width, height, minDepth, maxDepth);
43090          }
43091          if (renderContext.scissor) {
43092            const { x, y, width, height } = renderContext.scissorValue;
43093            renderPass.setScissorRect(x, y, width, height);
43094          }
43095          renderPass.executeBundles([bundles[i]]);
43096          renderPass.end();
43097        }
43098      }
43099    } else if (renderContextData.currentPass) {
43100      renderContextData.currentPass.end();
43101    }
43102    if (occlusionQueryCount > 0) {
43103      const bufferSize = occlusionQueryCount * 8;
43104      let queryResolveBuffer = this.occludedResolveCache.get(bufferSize);
43105      if (queryResolveBuffer === void 0) {
43106        queryResolveBuffer = this.device.createBuffer(
43107          {
43108            size: bufferSize,
43109            usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC
43110          }
43111        );
43112        this.occludedResolveCache.set(bufferSize, queryResolveBuffer);
43113      }
43114      const readBuffer = this.device.createBuffer(
43115        {
43116          size: bufferSize,
43117          usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
43118        }
43119      );
43120      renderContextData.encoder.resolveQuerySet(renderContextData.occlusionQuerySet, 0, occlusionQueryCount, queryResolveBuffer, 0);
43121      renderContextData.encoder.copyBufferToBuffer(queryResolveBuffer, 0, readBuffer, 0, bufferSize);
43122      renderContextData.occlusionQueryBuffer = readBuffer;
43123      this.resolveOccludedAsync(renderContext);
43124    }
43125    this.device.queue.submit([renderContextData.encoder.finish()]);
43126    if (renderContext.textures !== null) {
43127      const textures = renderContext.textures;
43128      for (let i = 0; i < textures.length; i++) {
43129        const texture3 = textures[i];
43130        if (texture3.generateMipmaps === true) {
43131          this.textureUtils.generateMipmaps(texture3);
43132        }
43133      }
43134    }
43135  }
43136  /**
43137   * Returns `true` if the given 3D object is fully occluded by other
43138   * 3D objects in the scene.
43139   *
43140   * @param {RenderContext} renderContext - The render context.
43141   * @param {Object3D} object - The 3D object to test.
43142   * @return {boolean} Whether the 3D object is fully occluded or not.
43143   */
43144  isOccluded(renderContext, object) {
43145    const renderContextData = this.get(renderContext);
43146    return renderContextData.occluded && renderContextData.occluded.has(object);
43147  }
43148  /**
43149   * This method processes the result of occlusion queries and writes it
43150   * into render context data.
43151   *
43152   * @async
43153   * @param {RenderContext} renderContext - The render context.
43154   * @return {Promise} A Promise that resolves when the occlusion query results have been processed.
43155   */
43156  async resolveOccludedAsync(renderContext) {
43157    const renderContextData = this.get(renderContext);
43158    const { currentOcclusionQueryBuffer, currentOcclusionQueryObjects } = renderContextData;
43159    if (currentOcclusionQueryBuffer && currentOcclusionQueryObjects) {
43160      const occluded = /* @__PURE__ */ new WeakSet();
43161      renderContextData.currentOcclusionQueryObjects = null;
43162      renderContextData.currentOcclusionQueryBuffer = null;
43163      await currentOcclusionQueryBuffer.mapAsync(GPUMapMode.READ);
43164      const buffer3 = currentOcclusionQueryBuffer.getMappedRange();
43165      const results = new BigUint64Array(buffer3);
43166      for (let i = 0; i < currentOcclusionQueryObjects.length; i++) {
43167        if (results[i] === BigInt(0)) {
43168          occluded.add(currentOcclusionQueryObjects[i]);
43169        }
43170      }
43171      currentOcclusionQueryBuffer.destroy();
43172      renderContextData.occluded = occluded;
43173    }
43174  }
43175  /**
43176   * Updates the viewport with the values from the given render context.
43177   *
43178   * @param {RenderContext} renderContext - The render context.
43179   */
43180  updateViewport(renderContext) {
43181    const { currentPass } = this.get(renderContext);
43182    const { x, y, width, height, minDepth, maxDepth } = renderContext.viewportValue;
43183    currentPass.setViewport(x, y, width, height, minDepth, maxDepth);
43184  }
43185  /**
43186   * Updates the scissor with the values from the given render context.
43187   *
43188   * @param {RenderContext} renderContext - The render context.
43189   */
43190  updateScissor(renderContext) {
43191    const { currentPass } = this.get(renderContext);
43192    const { x, y, width, height } = renderContext.scissorValue;
43193    currentPass.setScissorRect(x, y, width, height);
43194  }
43195  /**
43196   * Returns the clear color and alpha into a single
43197   * color object.
43198   *
43199   * @return {Color4} The clear color.
43200   */
43201  getClearColor() {
43202    const clearColor = super.getClearColor();
43203    if (this.renderer.alpha === true) {
43204      clearColor.r *= clearColor.a;
43205      clearColor.g *= clearColor.a;
43206      clearColor.b *= clearColor.a;
43207    }
43208    return clearColor;
43209  }
43210  /**
43211   * Performs a clear operation.
43212   *
43213   * @param {boolean} color - Whether the color buffer should be cleared or not.
43214   * @param {boolean} depth - Whether the depth buffer should be cleared or not.
43215   * @param {boolean} stencil - Whether the stencil buffer should be cleared or not.
43216   * @param {?RenderContext} [renderTargetContext=null] - The render context of the current set render target.
43217   */
43218  clear(color3, depth3, stencil, renderTargetContext = null) {
43219    const device = this.device;
43220    const renderer = this.renderer;
43221    let colorAttachments = [];
43222    let depthStencilAttachment;
43223    let supportsDepth;
43224    let supportsStencil;
43225    if (color3) {
43226      const clearColor = this.getClearColor();
43227      _clearValue.r = clearColor.r;
43228      _clearValue.g = clearColor.g;
43229      _clearValue.b = clearColor.b;
43230      _clearValue.a = clearColor.a;
43231    }
43232    if (renderTargetContext === null) {
43233      supportsDepth = renderer.depth;
43234      supportsStencil = renderer.stencil;
43235      const descriptor = this._getDefaultRenderPassDescriptor();
43236      if (color3) {
43237        colorAttachments = descriptor.colorAttachments;
43238        const colorAttachment = colorAttachments[0];
43239        colorAttachment.clearValue = _clearValue;
43240        colorAttachment.loadOp = GPULoadOp.Clear;
43241        colorAttachment.storeOp = GPUStoreOp.Store;
43242      }
43243      if (supportsDepth || supportsStencil) {
43244        depthStencilAttachment = descriptor.depthStencilAttachment;
43245      }
43246    } else {
43247      supportsDepth = renderTargetContext.depth;
43248      supportsStencil = renderTargetContext.stencil;
43249      const clearConfig = {
43250        loadOp: color3 ? GPULoadOp.Clear : GPULoadOp.Load,
43251        clearValue: color3 ? _clearValue : void 0
43252      };
43253      if (supportsDepth) {
43254        clearConfig.depthLoadOp = depth3 ? GPULoadOp.Clear : GPULoadOp.Load;
43255        clearConfig.depthClearValue = depth3 ? renderer.getClearDepth() : void 0;
43256        clearConfig.depthStoreOp = GPUStoreOp.Store;
43257      }
43258      if (supportsStencil) {
43259        clearConfig.stencilLoadOp = stencil ? GPULoadOp.Clear : GPULoadOp.Load;
43260        clearConfig.stencilClearValue = stencil ? renderer.getClearStencil() : void 0;
43261        clearConfig.stencilStoreOp = GPUStoreOp.Store;
43262      }
43263      const descriptor = this._getRenderPassDescriptor(renderTargetContext, clearConfig);
43264      colorAttachments = descriptor.colorAttachments;
43265      depthStencilAttachment = descriptor.depthStencilAttachment;
43266    }
43267    if (supportsDepth && depthStencilAttachment) {
43268      if (depth3) {
43269        depthStencilAttachment.depthLoadOp = GPULoadOp.Clear;
43270        depthStencilAttachment.depthClearValue = renderer.getClearDepth();
43271        depthStencilAttachment.depthStoreOp = GPUStoreOp.Store;
43272      } else {
43273        depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
43274        depthStencilAttachment.depthStoreOp = GPUStoreOp.Store;
43275      }
43276    }
43277    if (supportsStencil && depthStencilAttachment) {
43278      if (stencil) {
43279        depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear;
43280        depthStencilAttachment.stencilClearValue = renderer.getClearStencil();
43281        depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store;
43282      } else {
43283        depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
43284        depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store;
43285      }
43286    }
43287    const encoder = device.createCommandEncoder({ label: "clear" });
43288    const currentPass = encoder.beginRenderPass({
43289      colorAttachments,
43290      depthStencilAttachment
43291    });
43292    currentPass.end();
43293    device.queue.submit([encoder.finish()]);
43294  }
43295  // compute
43296  /**
43297   * This method is executed at the beginning of a compute call and
43298   * prepares the state for upcoming compute tasks.
43299   *
43300   * @param {Node|Array<Node>} computeGroup - The compute node(s).
43301   */
43302  beginCompute(computeGroup) {
43303    const groupGPU = this.get(computeGroup);
43304    const descriptor = {
43305      label: "computeGroup_" + computeGroup.id
43306    };
43307    this.initTimestampQuery(TimestampQuery.COMPUTE, this.getTimestampUID(computeGroup), descriptor);
43308    groupGPU.cmdEncoderGPU = this.device.createCommandEncoder({ label: "computeGroup_" + computeGroup.id });
43309    groupGPU.passEncoderGPU = groupGPU.cmdEncoderGPU.beginComputePass(descriptor);
43310  }
43311  /**
43312   * Executes a compute command for the given compute node.
43313   *
43314   * @param {Node|Array<Node>} computeGroup - The group of compute nodes of a compute call. Can be a single compute node.
43315   * @param {Node} computeNode - The compute node.
43316   * @param {Array<BindGroup>} bindings - The bindings.
43317   * @param {ComputePipeline} pipeline - The compute pipeline.
43318   * @param {number|Array<number>|IndirectStorageBufferAttribute} [dispatchSize=null]
43319   * - A single number representing count, or
43320   * - An array [x, y, z] representing dispatch size, or
43321   * - A IndirectStorageBufferAttribute for indirect dispatch size.
43322   */
43323  compute(computeGroup, computeNode, bindings, pipeline, dispatchSize = null) {
43324    const computeNodeData = this.get(computeNode);
43325    const { passEncoderGPU } = this.get(computeGroup);
43326    const pipelineGPU = this.get(pipeline).pipeline;
43327    this.pipelineUtils.setPipeline(passEncoderGPU, pipelineGPU);
43328    for (let i = 0, l = bindings.length; i < l; i++) {
43329      const bindGroup = bindings[i];
43330      const bindingsData = this.get(bindGroup);
43331      passEncoderGPU.setBindGroup(i, bindingsData.group);
43332    }
43333    if (dispatchSize === null) {
43334      dispatchSize = computeNode.dispatchSize || computeNode.count;
43335    }
43336    if (dispatchSize && dispatchSize.isIndirectStorageBufferAttribute) {
43337      const dispatchBuffer = this.get(dispatchSize).buffer;
43338      passEncoderGPU.dispatchWorkgroupsIndirect(dispatchBuffer, 0);
43339      return;
43340    }
43341    if (typeof dispatchSize === "number") {
43342      const count = dispatchSize;
43343      if (computeNodeData.dispatchSize === void 0 || computeNodeData.count !== count) {
43344        computeNodeData.dispatchSize = [0, 1, 1];
43345        computeNodeData.count = count;
43346        const workgroupSize = computeNode.workgroupSize;
43347        let size3 = workgroupSize[0];
43348        for (let i = 1; i < workgroupSize.length; i++)
43349          size3 *= workgroupSize[i];
43350        const dispatchCount = Math.ceil(count / size3);
43351        const maxComputeWorkgroupsPerDimension = this.device.limits.maxComputeWorkgroupsPerDimension;
43352        dispatchSize = [dispatchCount, 1, 1];
43353        if (dispatchCount > maxComputeWorkgroupsPerDimension) {
43354          dispatchSize[0] = Math.min(dispatchCount, maxComputeWorkgroupsPerDimension);
43355          dispatchSize[1] = Math.ceil(dispatchCount / maxComputeWorkgroupsPerDimension);
43356        }
43357        computeNodeData.dispatchSize = dispatchSize;
43358      }
43359      dispatchSize = computeNodeData.dispatchSize;
43360    }
43361    passEncoderGPU.dispatchWorkgroups(
43362      dispatchSize[0],
43363      dispatchSize[1] || 1,
43364      dispatchSize[2] || 1
43365    );
43366  }
43367  /**
43368   * This method is executed at the end of a compute call and
43369   * finalizes work after compute tasks.
43370   *
43371   * @param {Node|Array<Node>} computeGroup - The compute node(s).
43372   */
43373  finishCompute(computeGroup) {
43374    const groupData = this.get(computeGroup);
43375    groupData.passEncoderGPU.end();
43376    this.device.queue.submit([groupData.cmdEncoderGPU.finish()]);
43377  }
43378  /**
43379   * Internal draw function that performs the draw with the given pass encoder.
43380   *
43381   * @private
43382   * @param {RenderObject} renderObject - The render object.
43383   * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process.
43384   * @param {Object} renderContextData - The render context data object, holding current pass state and occlusion query tracking.
43385   * @param {GPURenderPipeline} pipelineGPU - The GPU render pipeline.
43386   * @param {Array<BindGroup>} bindings - The bind groups.
43387   * @param {Array<BufferAttribute>} vertexBuffers - The vertex buffers.
43388   * @param {{vertexCount: number, firstVertex: number, instanceCount: number, firstInstance: number}} drawParams - The draw parameters.
43389   * @param {GPURenderPassEncoder|GPURenderBundleEncoder} passEncoderGPU - The GPU pass encoder used for recording draw commands.
43390   * @param {Object} currentSets - Tracking object for currently set pipeline, attributes, bind groups, and index state.
43391   */
43392  _draw(renderObject, info, renderContextData, pipelineGPU, bindings, vertexBuffers, drawParams, passEncoderGPU, currentSets) {
43393    const { object, material, context: context3 } = renderObject;
43394    const index = renderObject.getIndex();
43395    const hasIndex = index !== null;
43396    this.pipelineUtils.setPipeline(passEncoderGPU, pipelineGPU);
43397    currentSets.pipeline = pipelineGPU;
43398    const currentBindingGroups = currentSets.bindingGroups;
43399    for (let i = 0, l = bindings.length; i < l; i++) {
43400      const bindGroup = bindings[i];
43401      const bindingsData = this.get(bindGroup);
43402      if (currentBindingGroups[i] !== bindGroup.id) {
43403        passEncoderGPU.setBindGroup(i, bindingsData.group);
43404        currentBindingGroups[i] = bindGroup.id;
43405      }
43406    }
43407    if (hasIndex === true) {
43408      if (currentSets.index !== index) {
43409        const buffer3 = this.get(index).buffer;
43410        const indexFormat = index.array instanceof Uint16Array ? GPUIndexFormat.Uint16 : GPUIndexFormat.Uint32;
43411        passEncoderGPU.setIndexBuffer(buffer3, indexFormat);
43412        currentSets.index = index;
43413      }
43414    }
43415    for (let i = 0, l = vertexBuffers.length; i < l; i++) {
43416      const vertexBuffer = vertexBuffers[i];
43417      if (currentSets.attributes[i] !== vertexBuffer) {
43418        const buffer3 = this.get(vertexBuffer).buffer;
43419        passEncoderGPU.setVertexBuffer(i, buffer3);
43420        currentSets.attributes[i] = vertexBuffer;
43421      }
43422    }
43423    if (context3.stencil === true && material.stencilWrite === true && renderContextData.currentStencilRef !== material.stencilRef) {
43424      passEncoderGPU.setStencilReference(material.stencilRef);
43425      renderContextData.currentStencilRef = material.stencilRef;
43426    }
43427    if (object.isBatchedMesh === true) {
43428      const starts = object._multiDrawStarts;
43429      const counts = object._multiDrawCounts;
43430      const drawCount = object._multiDrawCount;
43431      let bytesPerElement = hasIndex === true ? index.array.BYTES_PER_ELEMENT : 1;
43432      if (material.wireframe) {
43433        bytesPerElement = object.geometry.attributes.position.count > 65535 ? 4 : 2;
43434      }
43435      for (let i = 0; i < drawCount; i++) {
43436        if (hasIndex === true) {
43437          passEncoderGPU.drawIndexed(counts[i], 1, starts[i] / bytesPerElement, 0, i);
43438        } else {
43439          passEncoderGPU.draw(counts[i], 1, starts[i], i);
43440        }
43441        info.update(object, counts[i], 1);
43442      }
43443    } else if (hasIndex === true) {
43444      const { vertexCount: indexCount, instanceCount, firstVertex: firstIndex } = drawParams;
43445      const indirect = renderObject.getIndirect();
43446      if (indirect !== null) {
43447        const buffer3 = this.get(indirect).buffer;
43448        const indirectOffset = renderObject.getIndirectOffset();
43449        const indirectOffsets = Array.isArray(indirectOffset) ? indirectOffset : [indirectOffset];
43450        for (let i = 0; i < indirectOffsets.length; i++) {
43451          passEncoderGPU.drawIndexedIndirect(buffer3, indirectOffsets[i]);
43452        }
43453      } else {
43454        passEncoderGPU.drawIndexed(indexCount, instanceCount, firstIndex, 0, 0);
43455      }
43456      info.update(object, indexCount, instanceCount);
43457    } else {
43458      const { vertexCount, instanceCount, firstVertex } = drawParams;
43459      const indirect = renderObject.getIndirect();
43460      if (indirect !== null) {
43461        const buffer3 = this.get(indirect).buffer;
43462        const indirectOffset = renderObject.getIndirectOffset();
43463        const indirectOffsets = Array.isArray(indirectOffset) ? indirectOffset : [indirectOffset];
43464        for (let i = 0; i < indirectOffsets.length; i++) {
43465          passEncoderGPU.drawIndirect(buffer3, indirectOffsets[i]);
43466        }
43467      } else {
43468        passEncoderGPU.draw(vertexCount, instanceCount, firstVertex, 0);
43469      }
43470      info.update(object, vertexCount, instanceCount);
43471    }
43472  }
43473  // render object
43474  /**
43475   * Executes a draw command for the given render object.
43476   *
43477   * @param {RenderObject} renderObject - The render object to draw.
43478   * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process.
43479   */
43480  draw(renderObject, info) {
43481    const { object, context: context3, pipeline } = renderObject;
43482    const renderContextData = this.get(context3);
43483    const pipelineData = this.get(pipeline);
43484    const pipelineGPU = pipelineData.pipeline;
43485    if (pipelineData.error === true) return;
43486    const drawParams = renderObject.getDrawParameters();
43487    if (drawParams === null) return;
43488    const bindings = renderObject.getBindings();
43489    const vertexBuffers = renderObject.getVertexBuffers();
43490    if (renderObject.camera.isArrayCamera && renderObject.camera.cameras.length > 0) {
43491      const cameraData = this.get(renderObject.camera);
43492      const cameras = renderObject.camera.cameras;
43493      const cameraIndex3 = renderObject.getBindingGroup("cameraIndex");
43494      if (cameraData.indexesGPU === void 0 || cameraData.indexesGPU.length !== cameras.length) {
43495        const bindingsData = this.get(cameraIndex3);
43496        const indexesGPU = [];
43497        const data = new Uint32Array([0, 0, 0, 0]);
43498        for (let i = 0, len = cameras.length; i < len; i++) {
43499          data[0] = i;
43500          const { layoutGPU } = bindingsData.layout;
43501          const bindGroupIndex = this.bindingUtils.createBindGroupIndex(data, layoutGPU);
43502          indexesGPU.push(bindGroupIndex);
43503        }
43504        cameraData.indexesGPU = indexesGPU;
43505      }
43506      const pixelRatio = this.renderer.getPixelRatio();
43507      for (let i = 0, len = cameras.length; i < len; i++) {
43508        const subCamera = cameras[i];
43509        if (object.layers.test(subCamera.layers)) {
43510          const vp = subCamera.viewport;
43511          let pass3 = renderContextData.currentPass;
43512          let sets = renderContextData.currentSets;
43513          if (renderContextData.bundleEncoders) {
43514            const bundleEncoder = renderContextData.bundleEncoders[i];
43515            const bundleSets = renderContextData.bundleSets[i];
43516            pass3 = bundleEncoder;
43517            sets = bundleSets;
43518          }
43519          if (vp) {
43520            pass3.setViewport(
43521              Math.floor(vp.x * pixelRatio),
43522              Math.floor(vp.y * pixelRatio),
43523              Math.floor(vp.width * pixelRatio),
43524              Math.floor(vp.height * pixelRatio),
43525              context3.viewportValue.minDepth,
43526              context3.viewportValue.maxDepth
43527            );
43528          }
43529          if (cameraIndex3 && cameraData.indexesGPU) {
43530            const indexPos = bindings.indexOf(cameraIndex3);
43531            pass3.setBindGroup(indexPos, cameraData.indexesGPU[i]);
43532            sets.bindingGroups[indexPos] = cameraIndex3.id;
43533          }
43534          this._draw(renderObject, info, renderContextData, pipelineGPU, bindings, vertexBuffers, drawParams, pass3, sets);
43535        }
43536      }
43537    } else {
43538      if (renderContextData.currentPass) {
43539        if (renderContextData.occlusionQuerySet !== void 0) {
43540          const lastObject = renderContextData.lastOcclusionObject;
43541          if (lastObject !== object) {
43542            if (lastObject !== null && lastObject.occlusionTest === true) {
43543              renderContextData.currentPass.endOcclusionQuery();
43544              renderContextData.occlusionQueryIndex++;
43545            }
43546            if (object.occlusionTest === true) {
43547              renderContextData.currentPass.beginOcclusionQuery(renderContextData.occlusionQueryIndex);
43548              renderContextData.occlusionQueryObjects[renderContextData.occlusionQueryIndex] = object;
43549            }
43550            renderContextData.lastOcclusionObject = object;
43551          }
43552        }
43553        this._draw(renderObject, info, renderContextData, pipelineGPU, bindings, vertexBuffers, drawParams, renderContextData.currentPass, renderContextData.currentSets);
43554      }
43555    }
43556  }
43557  // cache key
43558  /**
43559   * Returns `true` if the render pipeline requires an update.
43560   *
43561   * @param {RenderObject} renderObject - The render object.
43562   * @return {boolean} Whether the render pipeline requires an update or not.
43563   */
43564  needsRenderUpdate(renderObject) {
43565    const data = this.get(renderObject);
43566    const { object, material } = renderObject;
43567    const utils = this.utils;
43568    const sampleCount = utils.getSampleCountRenderContext(renderObject.context);
43569    const colorSpace = utils.getCurrentColorSpace(renderObject.context);
43570    const colorFormat = utils.getCurrentColorFormat(renderObject.context);
43571    const depthStencilFormat = utils.getCurrentDepthStencilFormat(renderObject.context);
43572    const primitiveTopology = utils.getPrimitiveTopology(object, material);
43573    let needsUpdate = false;
43574    if (data.material !== material || data.materialVersion !== material.version || data.transparent !== material.transparent || data.blending !== material.blending || data.premultipliedAlpha !== material.premultipliedAlpha || data.blendSrc !== material.blendSrc || data.blendDst !== material.blendDst || data.blendEquation !== material.blendEquation || data.blendSrcAlpha !== material.blendSrcAlpha || data.blendDstAlpha !== material.blendDstAlpha || data.blendEquationAlpha !== material.blendEquationAlpha || data.colorWrite !== material.colorWrite || data.depthWrite !== material.depthWrite || data.depthTest !== material.depthTest || data.depthFunc !== material.depthFunc || data.stencilWrite !== material.stencilWrite || data.stencilFunc !== material.stencilFunc || data.stencilFail !== material.stencilFail || data.stencilZFail !== material.stencilZFail || data.stencilZPass !== material.stencilZPass || data.stencilFuncMask !== material.stencilFuncMask || data.stencilWriteMask !== material.stencilWriteMask || data.side !== material.side || data.alphaToCoverage !== material.alphaToCoverage || data.sampleCount !== sampleCount || data.colorSpace !== colorSpace || data.colorFormat !== colorFormat || data.depthStencilFormat !== depthStencilFormat || data.primitiveTopology !== primitiveTopology || data.clippingContextCacheKey !== renderObject.clippingContextCacheKey) {
43575      data.material = material;
43576      data.materialVersion = material.version;
43577      data.transparent = material.transparent;
43578      data.blending = material.blending;
43579      data.premultipliedAlpha = material.premultipliedAlpha;
43580      data.blendSrc = material.blendSrc;
43581      data.blendDst = material.blendDst;
43582      data.blendEquation = material.blendEquation;
43583      data.blendSrcAlpha = material.blendSrcAlpha;
43584      data.blendDstAlpha = material.blendDstAlpha;
43585      data.blendEquationAlpha = material.blendEquationAlpha;
43586      data.colorWrite = material.colorWrite;
43587      data.depthWrite = material.depthWrite;
43588      data.depthTest = material.depthTest;
43589      data.depthFunc = material.depthFunc;
43590      data.stencilWrite = material.stencilWrite;
43591      data.stencilFunc = material.stencilFunc;
43592      data.stencilFail = material.stencilFail;
43593      data.stencilZFail = material.stencilZFail;
43594      data.stencilZPass = material.stencilZPass;
43595      data.stencilFuncMask = material.stencilFuncMask;
43596      data.stencilWriteMask = material.stencilWriteMask;
43597      data.side = material.side;
43598      data.alphaToCoverage = material.alphaToCoverage;
43599      data.sampleCount = sampleCount;
43600      data.colorSpace = colorSpace;
43601      data.colorFormat = colorFormat;
43602      data.depthStencilFormat = depthStencilFormat;
43603      data.primitiveTopology = primitiveTopology;
43604      data.clippingContextCacheKey = renderObject.clippingContextCacheKey;
43605      needsUpdate = true;
43606    }
43607    return needsUpdate;
43608  }
43609  /**
43610   * Returns a cache key that is used to identify render pipelines.
43611   *
43612   * @param {RenderObject} renderObject - The render object.
43613   * @return {string} The cache key.
43614   */
43615  getRenderCacheKey(renderObject) {
43616    const { object, material } = renderObject;
43617    const utils = this.utils;
43618    const renderContext = renderObject.context;
43619    const frontFaceCW = object.isMesh && object.matrixWorld.determinant() < 0;
43620    return [
43621      material.transparent,
43622      material.blending,
43623      material.premultipliedAlpha,
43624      material.blendSrc,
43625      material.blendDst,
43626      material.blendEquation,
43627      material.blendSrcAlpha,
43628      material.blendDstAlpha,
43629      material.blendEquationAlpha,
43630      material.colorWrite,
43631      material.depthWrite,
43632      material.depthTest,
43633      material.depthFunc,
43634      material.stencilWrite,
43635      material.stencilFunc,
43636      material.stencilFail,
43637      material.stencilZFail,
43638      material.stencilZPass,
43639      material.stencilFuncMask,
43640      material.stencilWriteMask,
43641      material.side,
43642      frontFaceCW,
43643      utils.getSampleCountRenderContext(renderContext),
43644      utils.getCurrentColorSpace(renderContext),
43645      utils.getCurrentColorFormat(renderContext),
43646      utils.getCurrentDepthStencilFormat(renderContext),
43647      utils.getPrimitiveTopology(object, material),
43648      renderObject.getGeometryCacheKey(),
43649      renderObject.clippingContextCacheKey
43650    ].join();
43651  }
43652  // textures
43653  /**
43654   * Updates a GPU sampler for the given texture.
43655   *
43656   * @param {Texture} texture - The texture to update the sampler for.
43657   * @return {string} The current sampler key.
43658   */
43659  updateSampler(texture3) {
43660    return this.textureUtils.updateSampler(texture3);
43661  }
43662  /**
43663   * Creates a default texture for the given texture that can be used
43664   * as a placeholder until the actual texture is ready for usage.
43665   *
43666   * @param {Texture} texture - The texture to create a default texture for.
43667   * @return {boolean} Whether the sampler has been updated or not.
43668   */
43669  createDefaultTexture(texture3) {
43670    return this.textureUtils.createDefaultTexture(texture3);
43671  }
43672  /**
43673   * Defines a texture on the GPU for the given texture object.
43674   *
43675   * @param {Texture} texture - The texture.
43676   * @param {Object} [options={}] - Optional configuration parameter.
43677   */
43678  createTexture(texture3, options) {
43679    this.textureUtils.createTexture(texture3, options);
43680  }
43681  /**
43682   * Uploads the updated texture data to the GPU.
43683   *
43684   * @param {Texture} texture - The texture.
43685   * @param {Object} [options={}] - Optional configuration parameter.
43686   */
43687  updateTexture(texture3, options) {
43688    this.textureUtils.updateTexture(texture3, options);
43689  }
43690  /**
43691   * Generates mipmaps for the given texture.
43692   *
43693   * @param {Texture} texture - The texture.
43694   */
43695  generateMipmaps(texture3) {
43696    this.textureUtils.generateMipmaps(texture3);
43697  }
43698  /**
43699   * Destroys the GPU data for the given texture object.
43700   *
43701   * @param {Texture} texture - The texture.
43702   * @param {boolean} [isDefaultTexture=false] - Whether the texture uses a default GPU texture or not.
43703   */
43704  destroyTexture(texture3, isDefaultTexture = false) {
43705    this.textureUtils.destroyTexture(texture3, isDefaultTexture);
43706  }
43707  /**
43708   * Returns texture data as a typed array.
43709   *
43710   * @async
43711   * @param {Texture} texture - The texture to copy.
43712   * @param {number} x - The x coordinate of the copy origin.
43713   * @param {number} y - The y coordinate of the copy origin.
43714   * @param {number} width - The width of the copy.
43715   * @param {number} height - The height of the copy.
43716   * @param {number} faceIndex - The face index.
43717   * @return {Promise<TypedArray>} A Promise that resolves with a typed array when the copy operation has finished.
43718   */
43719  async copyTextureToBuffer(texture3, x, y, width, height, faceIndex) {
43720    return this.textureUtils.copyTextureToBuffer(texture3, x, y, width, height, faceIndex);
43721  }
43722  /**
43723   * Inits a time stamp query for the given render context.
43724   *
43725   * @param {string} type - The type of the timestamp query (e.g. 'render', 'compute').
43726   * @param {number} uid - Unique id for the context (e.g. render context id).
43727   * @param {Object} descriptor - The query descriptor.
43728   */
43729  initTimestampQuery(type, uid, descriptor) {
43730    if (!this.trackTimestamp) return;
43731    if (!this.timestampQueryPool[type]) {
43732      this.timestampQueryPool[type] = new WebGPUTimestampQueryPool(this.device, type, 2048);
43733    }
43734    const timestampQueryPool = this.timestampQueryPool[type];
43735    const baseOffset = timestampQueryPool.allocateQueriesForContext(uid);
43736    descriptor.timestampWrites = {
43737      querySet: timestampQueryPool.querySet,
43738      beginningOfPassWriteIndex: baseOffset,
43739      endOfPassWriteIndex: baseOffset + 1
43740    };
43741  }
43742  // node builder
43743  /**
43744   * Returns a node builder for the given render object.
43745   *
43746   * @param {RenderObject} object - The render object.
43747   * @param {Renderer} renderer - The renderer.
43748   * @return {WGSLNodeBuilder} The node builder.
43749   */
43750  createNodeBuilder(object, renderer) {
43751    return new WGSLNodeBuilder(object, renderer);
43752  }
43753  // program
43754  /**
43755   * Creates a shader program from the given programmable stage.
43756   *
43757   * @param {ProgrammableStage} program - The programmable stage.
43758   */
43759  createProgram(program) {
43760    const programGPU = this.get(program);
43761    programGPU.module = {
43762      module: this.device.createShaderModule({ code: program.code, label: program.stage + (program.name !== "" ? `_${program.name}` : "") }),
43763      entryPoint: "main"
43764    };
43765  }
43766  /**
43767   * Destroys the shader program of the given programmable stage.
43768   *
43769   * @param {ProgrammableStage} program - The programmable stage.
43770   */
43771  destroyProgram(program) {
43772    this.delete(program);
43773  }
43774  // pipelines
43775  /**
43776   * Creates a render pipeline for the given render object.
43777   *
43778   * @param {RenderObject} renderObject - The render object.
43779   * @param {Array<Promise>} promises - An array of compilation promises which are used in `compileAsync()`.
43780   */
43781  createRenderPipeline(renderObject, promises) {
43782    this.pipelineUtils.createRenderPipeline(renderObject, promises);
43783  }
43784  /**
43785   * Creates a compute pipeline for the given compute node.
43786   *
43787   * @param {ComputePipeline} computePipeline - The compute pipeline.
43788   * @param {Array<BindGroup>} bindings - The bindings.
43789   */
43790  createComputePipeline(computePipeline, bindings) {
43791    this.pipelineUtils.createComputePipeline(computePipeline, bindings);
43792  }
43793  /**
43794   * Prepares the state for encoding render bundles.
43795   *
43796   * @param {RenderContext} renderContext - The render context.
43797   */
43798  beginBundle(renderContext) {
43799    const renderContextData = this.get(renderContext);
43800    renderContextData._currentPass = renderContextData.currentPass;
43801    renderContextData._currentSets = renderContextData.currentSets;
43802    renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null };
43803    renderContextData.currentPass = this.pipelineUtils.createBundleEncoder(renderContext);
43804  }
43805  /**
43806   * After processing render bundles this method finalizes related work.
43807   *
43808   * @param {RenderContext} renderContext - The render context.
43809   * @param {RenderBundle} bundle - The render bundle.
43810   */
43811  finishBundle(renderContext, bundle) {
43812    const renderContextData = this.get(renderContext);
43813    const bundleEncoder = renderContextData.currentPass;
43814    const bundleGPU = bundleEncoder.finish();
43815    this.get(bundle).bundleGPU = bundleGPU;
43816    renderContextData.currentSets = renderContextData._currentSets;
43817    renderContextData.currentPass = renderContextData._currentPass;
43818  }
43819  /**
43820   * Adds a render bundle to the render context data.
43821   *
43822   * @param {RenderContext} renderContext - The render context.
43823   * @param {RenderBundle} bundle - The render bundle to add.
43824   */
43825  addBundle(renderContext, bundle) {
43826    const renderContextData = this.get(renderContext);
43827    renderContextData.renderBundles.push(this.get(bundle).bundleGPU);
43828  }
43829  // bindings
43830  /**
43831   * Creates bindings from the given bind group definition.
43832   *
43833   * @param {BindGroup} bindGroup - The bind group.
43834   * @param {Array<BindGroup>} bindings - Array of bind groups.
43835   * @param {number} cacheIndex - The cache index.
43836   * @param {number} version - The version.
43837   */
43838  createBindings(bindGroup, bindings, cacheIndex, version) {
43839    this.bindingUtils.createBindings(bindGroup, bindings, cacheIndex, version);
43840  }
43841  /**
43842   * Updates the given bind group definition.
43843   *
43844   * @param {BindGroup} bindGroup - The bind group.
43845   * @param {Array<BindGroup>} bindings - Array of bind groups.
43846   * @param {number} cacheIndex - The cache index.
43847   * @param {number} version - The version.
43848   */
43849  updateBindings(bindGroup, bindings, cacheIndex, version) {
43850    this.bindingUtils.createBindings(bindGroup, bindings, cacheIndex, version);
43851  }
43852  /**
43853   * Updates a buffer binding.
43854   *
43855   *  @param {Buffer} binding - The buffer binding to update.
43856   */
43857  updateBinding(binding) {
43858    this.bindingUtils.updateBinding(binding);
43859  }
43860  /**
43861   * Delete data associated with the current bind group.
43862   *
43863   * @param {BindGroup} bindGroup - The bind group.
43864   */
43865  deleteBindGroupData(bindGroup) {
43866    this.bindingUtils.deleteBindGroupData(bindGroup);
43867  }
43868  // attributes
43869  /**
43870   * Creates the buffer of an indexed shader attribute.
43871   *
43872   * @param {BufferAttribute} attribute - The indexed buffer attribute.
43873   */
43874  createIndexAttribute(attribute3) {
43875    let usage = GPUBufferUsage.INDEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST;
43876    if (attribute3.isStorageBufferAttribute || attribute3.isStorageInstancedBufferAttribute) {
43877      usage |= GPUBufferUsage.STORAGE;
43878    }
43879    this.attributeUtils.createAttribute(attribute3, usage);
43880  }
43881  /**
43882   * Creates the GPU buffer of a shader attribute.
43883   *
43884   * @param {BufferAttribute} attribute - The buffer attribute.
43885   */
43886  createAttribute(attribute3) {
43887    this.attributeUtils.createAttribute(attribute3, GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST);
43888  }
43889  /**
43890   * Creates the GPU buffer of a storage attribute.
43891   *
43892   * @param {BufferAttribute} attribute - The buffer attribute.
43893   */
43894  createStorageAttribute(attribute3) {
43895    this.attributeUtils.createAttribute(attribute3, GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST);
43896  }
43897  /**
43898   * Creates the GPU buffer of an indirect storage attribute.
43899   *
43900   * @param {BufferAttribute} attribute - The buffer attribute.
43901   */
43902  createIndirectStorageAttribute(attribute3) {
43903    this.attributeUtils.createAttribute(attribute3, GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST);
43904  }
43905  /**
43906   * Updates the GPU buffer of a shader attribute.
43907   *
43908   * @param {BufferAttribute} attribute - The buffer attribute to update.
43909   */
43910  updateAttribute(attribute3) {
43911    this.attributeUtils.updateAttribute(attribute3);
43912  }
43913  /**
43914   * Destroys the GPU buffer of a shader attribute.
43915   *
43916   * @param {BufferAttribute} attribute - The buffer attribute to destroy.
43917   */
43918  destroyAttribute(attribute3) {
43919    this.attributeUtils.destroyAttribute(attribute3);
43920  }
43921  // canvas
43922  /**
43923   * Triggers an update of the default render pass descriptor.
43924   */
43925  updateSize() {
43926    this.delete(this.renderer.getCanvasTarget());
43927  }
43928  // utils public
43929  /**
43930   * Checks if the given feature is supported by the backend.
43931   *
43932   * @param {string} name - The feature's name.
43933   * @return {boolean} Whether the feature is supported or not.
43934   */
43935  hasFeature(name) {
43936    if (GPUFeatureMap[name] !== void 0) name = GPUFeatureMap[name];
43937    return this.device.features.has(name);
43938  }
43939  /**
43940   * Copies data of the given source texture to the given destination texture.
43941   *
43942   * @param {Texture} srcTexture - The source texture.
43943   * @param {Texture} dstTexture - The destination texture.
43944   * @param {?(Box3|Box2)} [srcRegion=null] - The region of the source texture to copy.
43945   * @param {?(Vector2|Vector3)} [dstPosition=null] - The destination position of the copy.
43946   * @param {number} [srcLevel=0] - The mipmap level to copy.
43947   * @param {number} [dstLevel=0] - The destination mip level to copy to.
43948   */
43949  copyTextureToTexture(srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0) {
43950    let dstX = 0;
43951    let dstY = 0;
43952    let dstZ = 0;
43953    let srcX = 0;
43954    let srcY = 0;
43955    let srcZ = 0;
43956    let srcWidth = srcTexture.image.width;
43957    let srcHeight = srcTexture.image.height;
43958    let srcDepth = 1;
43959    if (srcRegion !== null) {
43960      if (srcRegion.isBox3 === true) {
43961        srcX = srcRegion.min.x;
43962        srcY = srcRegion.min.y;
43963        srcZ = srcRegion.min.z;
43964        srcWidth = srcRegion.max.x - srcRegion.min.x;
43965        srcHeight = srcRegion.max.y - srcRegion.min.y;
43966        srcDepth = srcRegion.max.z - srcRegion.min.z;
43967      } else {
43968        srcX = srcRegion.min.x;
43969        srcY = srcRegion.min.y;
43970        srcWidth = srcRegion.max.x - srcRegion.min.x;
43971        srcHeight = srcRegion.max.y - srcRegion.min.y;
43972        srcDepth = 1;
43973      }
43974    }
43975    if (dstPosition !== null) {
43976      dstX = dstPosition.x;
43977      dstY = dstPosition.y;
43978      dstZ = dstPosition.z || 0;
43979    }
43980    const encoder = this.device.createCommandEncoder({ label: "copyTextureToTexture_" + srcTexture.id + "_" + dstTexture.id });
43981    const sourceGPU = this.get(srcTexture).texture;
43982    const destinationGPU = this.get(dstTexture).texture;
43983    encoder.copyTextureToTexture(
43984      {
43985        texture: sourceGPU,
43986        mipLevel: srcLevel,
43987        origin: { x: srcX, y: srcY, z: srcZ }
43988      },
43989      {
43990        texture: destinationGPU,
43991        mipLevel: dstLevel,
43992        origin: { x: dstX, y: dstY, z: dstZ }
43993      },
43994      [
43995        srcWidth,
43996        srcHeight,
43997        srcDepth
43998      ]
43999    );
44000    this.device.queue.submit([encoder.finish()]);
44001    if (dstLevel === 0 && dstTexture.generateMipmaps) {
44002      this.textureUtils.generateMipmaps(dstTexture);
44003    }
44004  }
44005  /**
44006   * Copies the current bound framebuffer to the given texture.
44007   *
44008   * @param {Texture} texture - The destination texture.
44009   * @param {RenderContext} renderContext - The render context.
44010   * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy.
44011   */
44012  copyFramebufferToTexture(texture3, renderContext, rectangle) {
44013    const renderContextData = this.get(renderContext);
44014    let sourceGPU = null;
44015    if (renderContext.renderTarget) {
44016      if (texture3.isDepthTexture) {
44017        sourceGPU = this.get(renderContext.depthTexture).texture;
44018      } else {
44019        sourceGPU = this.get(renderContext.textures[0]).texture;
44020      }
44021    } else {
44022      if (texture3.isDepthTexture) {
44023        sourceGPU = this.textureUtils.getDepthBuffer(renderContext.depth, renderContext.stencil);
44024      } else {
44025        sourceGPU = this.context.getCurrentTexture();
44026      }
44027    }
44028    const destinationGPU = this.get(texture3).texture;
44029    if (sourceGPU.format !== destinationGPU.format) {
44030      error("WebGPUBackend: copyFramebufferToTexture: Source and destination formats do not match.", sourceGPU.format, destinationGPU.format);
44031      return;
44032    }
44033    let encoder;
44034    if (renderContextData.currentPass) {
44035      renderContextData.currentPass.end();
44036      encoder = renderContextData.encoder;
44037    } else {
44038      encoder = this.device.createCommandEncoder({ label: "copyFramebufferToTexture_" + texture3.id });
44039    }
44040    encoder.copyTextureToTexture(
44041      {
44042        texture: sourceGPU,
44043        origin: [rectangle.x, rectangle.y, 0]
44044      },
44045      {
44046        texture: destinationGPU
44047      },
44048      [
44049        rectangle.z,
44050        rectangle.w
44051      ]
44052    );
44053    if (texture3.generateMipmaps) {
44054      this.textureUtils.generateMipmaps(texture3, encoder);
44055    }
44056    if (renderContextData.currentPass) {
44057      const { descriptor } = renderContextData;
44058      for (let i = 0; i < descriptor.colorAttachments.length; i++) {
44059        descriptor.colorAttachments[i].loadOp = GPULoadOp.Load;
44060      }
44061      if (renderContext.depth) descriptor.depthStencilAttachment.depthLoadOp = GPULoadOp.Load;
44062      if (renderContext.stencil) descriptor.depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
44063      renderContextData.currentPass = encoder.beginRenderPass(descriptor);
44064      renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null };
44065      if (renderContext.viewport) {
44066        this.updateViewport(renderContext);
44067      }
44068      if (renderContext.scissor) {
44069        this.updateScissor(renderContext);
44070      }
44071    } else {
44072      this.device.queue.submit([encoder.finish()]);
44073    }
44074  }
44075  /**
44076   * Checks if the given compatibility is supported by the backend.
44077   *
44078   * @param {string} name - The compatibility name.
44079   * @return {boolean} Whether the compatibility is supported or not.
44080   */
44081  hasCompatibility(name) {
44082    if (this._compatibility[name] !== void 0) {
44083      return this._compatibility[name];
44084    }
44085    return super.hasCompatibility(name);
44086  }
44087  dispose() {
44088    this.bindingUtils.dispose();
44089    this.textureUtils.dispose();
44090    if (this.occludedResolveCache) {
44091      for (const buffer3 of this.occludedResolveCache.values()) {
44092        buffer3.destroy();
44093      }
44094      this.occludedResolveCache.clear();
44095    }
44096    if (this.timestampQueryPool) {
44097      for (const queryPool of Object.values(this.timestampQueryPool)) {
44098        if (queryPool !== null) queryPool.dispose();
44099      }
44100    }
44101    if (this.parameters.device === void 0 && this.device !== null) {
44102      this.device.destroy();
44103    }
44104  }
44105};
44106var IESSpotLight = class extends SpotLight {
44107  /**
44108   * Constructs a new IES spot light.
44109   *
44110   * @param {(number|Color|string)} [color=0xffffff] - The light's color.
44111   * @param {number} [intensity=1] - The light's strength/intensity measured in candela (cd).
44112   * @param {number} [distance=0] - Maximum range of the light. `0` means no limit.
44113   * @param {number} [angle=Math.PI/3] - Maximum angle of light dispersion from its direction whose upper bound is `Math.PI/2`.
44114   * @param {number} [penumbra=0] - Percent of the spotlight cone that is attenuated due to penumbra. Value range is `[0,1]`.
44115   * @param {number} [decay=2] - The amount the light dims along the distance of the light.
44116   */
44117  constructor(color3, intensity, distance3, angle, penumbra, decay) {
44118    super(color3, intensity, distance3, angle, penumbra, decay);
44119    this.iesMap = null;
44120  }
44121  copy(source, recursive) {
44122    super.copy(source, recursive);
44123    this.iesMap = source.iesMap;
44124    return this;
44125  }
44126};
44127var ProjectorLight = class extends SpotLight {
44128  /**
44129   * Constructs a new projector light.
44130   *
44131   * @param {(number|Color|string)} [color=0xffffff] - The light's color.
44132   * @param {number} [intensity=1] - The light's strength/intensity measured in candela (cd).
44133   * @param {number} [distance=0] - Maximum range of the light. `0` means no limit.
44134   * @param {number} [angle=Math.PI/3] - Maximum angle of light dispersion from its direction whose upper bound is `Math.PI/2`.
44135   * @param {number} [penumbra=0] - Percent of the spotlight cone that is attenuated due to penumbra. Value range is `[0,1]`.
44136   * @param {number} [decay=2] - The amount the light dims along the distance of the light.
44137   */
44138  constructor(color3, intensity, distance3, angle, penumbra, decay) {
44139    super(color3, intensity, distance3, angle, penumbra, decay);
44140    this.aspect = null;
44141  }
44142  copy(source, recursive) {
44143    super.copy(source, recursive);
44144    this.aspect = source.aspect;
44145    return this;
44146  }
44147};
44148var StandardNodeLibrary = class extends NodeLibrary {
44149  /**
44150   * Constructs a new standard node library.
44151   */
44152  constructor() {
44153    super();
44154    this.addMaterial(MeshPhongNodeMaterial, "MeshPhongMaterial");
44155    this.addMaterial(MeshStandardNodeMaterial, "MeshStandardMaterial");
44156    this.addMaterial(MeshPhysicalNodeMaterial, "MeshPhysicalMaterial");
44157    this.addMaterial(MeshToonNodeMaterial, "MeshToonMaterial");
44158    this.addMaterial(MeshBasicNodeMaterial, "MeshBasicMaterial");
44159    this.addMaterial(MeshLambertNodeMaterial, "MeshLambertMaterial");
44160    this.addMaterial(MeshNormalNodeMaterial, "MeshNormalMaterial");
44161    this.addMaterial(MeshMatcapNodeMaterial, "MeshMatcapMaterial");
44162    this.addMaterial(LineBasicNodeMaterial, "LineBasicMaterial");
44163    this.addMaterial(LineDashedNodeMaterial, "LineDashedMaterial");
44164    this.addMaterial(PointsNodeMaterial, "PointsMaterial");
44165    this.addMaterial(SpriteNodeMaterial, "SpriteMaterial");
44166    this.addMaterial(ShadowNodeMaterial, "ShadowMaterial");
44167    this.addLight(PointLightNode, PointLight);
44168    this.addLight(DirectionalLightNode, DirectionalLight);
44169    this.addLight(RectAreaLightNode, RectAreaLight);
44170    this.addLight(SpotLightNode, SpotLight);
44171    this.addLight(AmbientLightNode, AmbientLight);
44172    this.addLight(HemisphereLightNode, HemisphereLight);
44173    this.addLight(LightProbeNode, LightProbe);
44174    this.addLight(IESSpotLightNode, IESSpotLight);
44175    this.addLight(ProjectorLightNode, ProjectorLight);
44176    this.addToneMapping(linearToneMapping, LinearToneMapping);
44177    this.addToneMapping(reinhardToneMapping, ReinhardToneMapping);
44178    this.addToneMapping(cineonToneMapping, CineonToneMapping);
44179    this.addToneMapping(acesFilmicToneMapping, ACESFilmicToneMapping);
44180    this.addToneMapping(agxToneMapping, AgXToneMapping);
44181    this.addToneMapping(neutralToneMapping, NeutralToneMapping);
44182  }
44183};
44184var WebGPURenderer = class extends Renderer {
44185  /**
44186   * WebGPURenderer options.
44187   *
44188   * @typedef {Object} WebGPURenderer~Options
44189   * @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
44190   * @property {boolean} [reversedDepthBuffer=false] - Whether reversed depth buffer is enabled or not.
44191   * @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
44192   * @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
44193   * @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
44194   * @property {boolean} [antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
44195   * @property {number} [samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default.
44196   * @property {boolean} [forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not.
44197   * @property {boolean} [multiview=false] - If set to `true`, the renderer will use multiview during WebXR rendering if supported.
44198   * @property {number} [outputType=undefined] - Texture type for output to canvas. By default, device's preferred format is used; other formats may incur overhead.
44199   * @property {number} [outputBufferType=HalfFloatType] - Defines the type of output buffers. The default `HalfFloatType` is recommend for best
44200   * quality. To save memory and bandwidth, `UnsignedByteType` might be used. This will reduce rendering quality though.
44201   */
44202  /**
44203   * Constructs a new WebGPU renderer.
44204   *
44205   * @param {WebGPURenderer~Options} [parameters] - The configuration parameter.
44206   */
44207  constructor(parameters = {}) {
44208    let BackendClass;
44209    if (parameters.forceWebGL) {
44210      BackendClass = WebGLBackend;
44211    } else {
44212      BackendClass = WebGPUBackend;
44213      parameters.getFallback = () => {
44214        warn("WebGPURenderer: WebGPU is not available, running under WebGL2 backend.");
44215        return new WebGLBackend(parameters);
44216      };
44217    }
44218    const backend = new BackendClass(parameters);
44219    super(backend, parameters);
44220    this.library = new StandardNodeLibrary();
44221    this.isWebGPURenderer = true;
44222    if (typeof __THREE_DEVTOOLS__ !== "undefined") {
44223      __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe", { detail: this }));
44224    }
44225  }
44226};
44227
vendor: 179 bytes, lines 44228-44230
44228// node_modules/@solid-primitives/resize-observer/node_modules/@solid-primitives/utils/dist/chunk/APG4HSEJ.js
44229var access = (v) => typeof v === "function" && !v.length ? v() : v;
44230
vendor: 345 bytes, lines 44231-44238
44231// node_modules/@solid-primitives/static-store/node_modules/@solid-primitives/utils/dist/chunk/APG4HSEJ.js
44232function isObject2(value) {
44233  return value !== null && (typeof value === "object" || typeof value === "function");
44234}
44235function accessWith2(valueOrFn, ...args) {
44236  return typeof valueOrFn === "function" ? valueOrFn(...args) : valueOrFn;
44237}
44238
vendor: 1,089 bytes, lines 44239-44279
44239// node_modules/@solid-primitives/static-store/dist/index.js
44240function createStaticStore(init) {
44241  const copy = { ...init }, store = { ...init }, cache4 = {};
44242  const getValue = (key) => {
44243    let signal = cache4[key];
44244    if (!signal) {
44245      if (!getListener())
44246        return copy[key];
44247      cache4[key] = signal = createSignal(copy[key], { internal: true });
44248      delete copy[key];
44249    }
44250    return signal[0]();
44251  };
44252  for (const key in init) {
44253    Object.defineProperty(store, key, { get: () => getValue(key), enumerable: true });
44254  }
44255  const setValue = (key, value) => {
44256    const signal = cache4[key];
44257    if (signal)
44258      return signal[1](value);
44259    if (key in copy)
44260      copy[key] = accessWith2(value, [copy[key]]);
44261  };
44262  return [
44263    store,
44264    (a, b) => {
44265      if (isObject2(a)) {
44266        const entries5 = untrack(
44267          () => Object.entries(accessWith2(a, store))
44268        );
44269        batch(() => {
44270          for (const [key, value] of entries5)
44271            setValue(key, () => value);
44272        });
44273      } else
44274        setValue(a, b);
44275      return store;
44276    }
44277  ];
44278}
44279
vendor: 871 bytes, lines 44280-44310
44280// node_modules/@solid-primitives/resize-observer/dist/index.js
44281var ELEMENT_SIZE_FALLBACK = { width: null, height: null };
44282function getElementSize(target) {
44283  if (isServer || !target) {
44284    return { ...ELEMENT_SIZE_FALLBACK };
44285  }
44286  const { width, height } = target.getBoundingClientRect();
44287  return { width, height };
44288}
44289function createElementSize(target) {
44290  if (isServer) {
44291    return ELEMENT_SIZE_FALLBACK;
44292  }
44293  const [size3, setSize] = createStaticStore(
44294    sharedConfig.context ? ELEMENT_SIZE_FALLBACK : getElementSize(access(target))
44295  );
44296  const ro = new ResizeObserver(([e]) => {
44297    const { width, height } = e.contentRect;
44298    setSize({ width, height });
44299  });
44300  onCleanup(() => ro.disconnect());
44301  createEffect(() => {
44302    const el = access(target);
44303    if (el) {
44304      ro.observe(el);
44305      onCleanup(() => ro.unobserve(el));
44306    }
44307  });
44308  return size3;
44309}
44310
44311// src/viewer/context/webxr.jsx
44312var T2 = createT({
44313  Group
44314});
44315var WebXRSupport = (props) => {
44316  const {
44317    globalScale
44318  } = useCamera();
44319  let originGroup = null;
44320  let trackball = null;
44321  const [originGroupReady, setOriginGroupReady] = createSignal(null);
44322  const captureOriginGroup = (g) => {
44323    originGroup = g;
44324    setOriginGroupReady(g);
44325  };
44326  const setTrackball = (tb) => {
44327    trackball = tb;
44328  };
44329  const StartXRButton = lazy(() => import("./vzome-viewer-xr.js"));
44330  const setRootScene = (scene) => {
44331    originGroup.clear();
44332    originGroup.add(scene);
44333    const children2 = [...scene.children];
44334    for (const child of children2) {
44335      originGroup.add(child);
44336    }
44337  };
44338  return [createComponent(T2.Group, {
44339    ref: captureOriginGroup,
44340    scale: globalScale,
44341    get children() {
44342      return createComponent(WebXRContext.Provider, {
44343        value: {
44344          setRootScene,
44345          setTrackball,
44346          originGroupReady
44347        },
44348        get children() {
44349          return props.children;
44350        }
44351      });
44352    }
44353  }), createComponent(Suspense, {
44354    get children() {
44355      return createComponent(Show, {
44356        get when() {
44357          return memo(() => !!props.xrSupported)() && props.xrSupported();
44358        },
44359        get children() {
44360          return createComponent(StartXRButton, {
44361            getRootGroup: () => originGroup,
44362            trackball
44363          });
44364        }
44365      });
44366    }
44367  })];
44368};
44369var WebXRContext = createContext({});
44370var useWebXRClient = () => {
44371  return useContext(WebXRContext);
44372};
44373
44374// src/viewer/trackballcontrols.jsx
44375var TrackballControls2 = (props) => {
44376  props = mergeProps({
44377    rotateSpeed: 4.5,
44378    zoomSpeed: 3,
44379    panSpeed: 1
44380  }, props);
44381  const {
44382    perspectiveProps,
44383    trackballProps,
44384    name,
44385    cancelTweens
44386  } = useCamera();
44387  const [tool] = useInteractionTool();
44388  const {
44389    canvas,
44390    bounds
44391  } = useThree();
44392  const {
44393    setTrackball
44394  } = useWebXRClient();
44395  createEffect(() => {
44396    if (bounds.height < 0)
44397      console.log("height is", bounds.height);
44398    trackballControls().connect(canvas);
44399  });
44400  const trackballControls = createMemo(() => {
44401    const controls = new TrackballControls(trackballProps.camera);
44402    setTrackball(controls);
44403    return controls;
44404  });
44405  useFrame(() => {
44406    let controls = trackballControls();
44407    if (controls.enabled) {
44408      controls.update();
44409    }
44410  });
44411  createEffect(() => {
44412    trackballControls().enabled = tool === void 0 || tool.allowTrackball();
44413  });
44414  createEffect(() => {
44415    const controls = trackballControls();
44416    controls.staticMoving = true;
44417    if (props.rotationOnly) {
44418      controls.noZoom = true;
44419      controls.noPan = true;
44420    } else {
44421      controls.noZoom = props.zoomSpeed === 0;
44422      controls.zoomSpeed = props.zoomSpeed;
44423      controls.noPan = props.panSpeed === 0;
44424      controls.panSpeed = props.panSpeed;
44425    }
44426    controls.rotateSpeed = props.rotateSpeed;
44427    controls.connect(canvas);
44428    const onStart = () => cancelTweens();
44429    const onChange = () => trackballProps.sync(controls.target, name);
44430    const onEnd = () => tool !== void 0 && tool.onTrackballEnd();
44431    controls.addEventListener("start", onStart);
44432    controls.addEventListener("change", onChange);
44433    controls.addEventListener("end", onEnd);
44434    onCleanup(() => {
44435      controls.removeEventListener("start", onStart);
44436      controls.removeEventListener("change", onChange);
44437      controls.removeEventListener("end", onEnd);
44438      controls.dispose();
44439    });
44440  });
44441  createEffect(() => {
44442    const [x, y, z] = perspectiveProps.target;
44443    trackballControls().target.set(x, y, z);
44444  });
44445  return null;
44446};
44447
44448// src/viewer/perspectivecamera.jsx
44449var T3 = createT({
44450  PerspectiveCamera
44451});
44452var ControlledPerspectiveCamera = (props) => {
44453  const {
44454    perspectiveProps,
44455    state: cameraConfig,
44456    globalScale
44457  } = useCamera();
44458  let cam;
44459  const {
44460    setCamera,
44461    scene
44462  } = useThree();
44463  createEffect(() => {
44464    if (cameraConfig.outlines) cam.layers.enable(4);
44465    else cam.layers.disable(4);
44466  });
44467  createEffect(() => {
44468    const [x, y, z] = perspectiveProps.target;
44469    cam.lookAt(x * globalScale, y * globalScale, z * globalScale);
44470  });
44471  createEffect(() => {
44472    cam.near = perspectiveProps.near * globalScale;
44473    cam.far = perspectiveProps.far * globalScale;
44474    cam.fov = perspectiveProps.fov(props.aspect);
44475    cam.aspect = props.aspect;
44476    cam.updateProjectionMatrix();
44477  });
44478  createEffect(() => {
44479    setCamera(cam);
44480    scene.add(cam);
44481    onCleanup(() => scene.remove(cam));
44482  });
44483  return createComponent(T3.PerspectiveCamera, {
44484    ref(r$) {
44485      const _ref$ = cam;
44486      typeof _ref$ === "function" ? _ref$(r$) : cam = r$;
44487    },
44488    get position() {
44489      return perspectiveProps.position.map((e) => e * globalScale);
44490    },
44491    get up() {
44492      return perspectiveProps.up;
44493    },
44494    get children() {
44495      return props.children;
44496    }
44497  });
44498};
44499
44500// src/viewer/orthographiccamera.jsx
44501var T4 = createT({
44502  OrthographicCamera
44503});
44504var ControlledOrthographicCamera = (props) => {
44505  const {
44506    perspectiveProps,
44507    state,
44508    globalScale
44509  } = useCamera();
44510  const halfWidth = () => perspectiveProps.width / 2;
44511  let cam;
44512  const {
44513    scene,
44514    setCamera
44515  } = useThree();
44516  createEffect(() => {
44517    if (state.outlines) cam.layers.enable(4);
44518    else cam.layers.disable(4);
44519  });
44520  createEffect(() => {
44521    cam.near = perspectiveProps.near * globalScale;
44522    cam.far = perspectiveProps.far * globalScale;
44523    cam.left = -halfWidth() * globalScale;
44524    cam.right = halfWidth() * globalScale;
44525    const halfHeight = halfWidth() / props.aspect;
44526    cam.top = halfHeight * globalScale;
44527    cam.bottom = -halfHeight * globalScale;
44528    cam.updateProjectionMatrix();
44529  });
44530  createEffect(() => {
44531    const [x, y, z] = perspectiveProps.target;
44532    cam.lookAt(x * globalScale, y * globalScale, z * globalScale);
44533  });
44534  createEffect(() => {
44535    setCamera(cam);
44536    scene.add(cam);
44537    onCleanup(() => scene.remove(cam));
44538  });
44539  return createComponent(T4.OrthographicCamera, {
44540    ref(r$) {
44541      const _ref$ = cam;
44542      typeof _ref$ === "function" ? _ref$(r$) : cam = r$;
44543    },
44544    get position() {
44545      return perspectiveProps.position.map((e) => e * globalScale);
44546    },
44547    get up() {
44548      return perspectiveProps.up;
44549    },
44550    get children() {
44551      return props.children;
44552    }
44553  });
44554};
44555
44556// src/viewer/labels.jsx
44557var Labels = (props) => {
44558  const three = useThree();
44559  const {
44560    scene,
44561    canvas
44562  } = three;
44563  let labelRenderer;
44564  onMount(() => {
44565    labelRenderer = new CSS2DRenderer();
44566    const labelsElem = labelRenderer.domElement;
44567    labelsElem.style.isolation = "isolate";
44568    labelsElem.style.position = "absolute";
44569    labelsElem.style.pointerEvents = "none";
44570    labelsElem.style.inset = "0px";
44571    labelsElem.style.width = "100%";
44572    labelsElem.style.height = "100%";
44573    labelsElem.classList.add("labels");
44574    canvas.insertAdjacentElement("beforebegin", labelsElem);
44575  });
44576  createEffect(() => {
44577    props.size && labelRenderer.setSize(props.size.width, props.size.height);
44578  });
44579  useFrame(() => {
44580    labelRenderer.render(scene, three.camera);
44581  });
44582  return null;
44583};
44584var Label = (props) => {
44585  let label3;
44586  onMount(() => {
44587    const elem = document.createElement("div");
44588    elem.className = "vzome-label";
44589    elem.id = `vzome-label-${props.text}`;
44590    elem.textContent = props.text;
44591    label3 = new CSS2DObject(elem);
44592    props.parent.add(label3);
44593  });
44594  onCleanup(() => label3?.parent?.remove(label3));
44595  createEffect(() => {
44596    const {
44597      x,
44598      y,
44599      z
44600    } = props.position;
44601    label3.position.set(x, y, z);
44602  });
44603  return label3;
44604};
44605
44606// src/viewer/ltcanvas.jsx
44607var _tmpl$ = /* @__PURE__ */ template(`<button>START AR`);
44608var _tmpl$2 = /* @__PURE__ */ template(`<div>`);
44609var T5 = createT({
44610  Group,
44611  Mesh,
44612  AmbientLight,
44613  DirectionalLight
44614});
44615var Lighting2 = () => {
44616  const {
44617    state,
44618    perspectiveProps
44619  } = useCamera();
44620  const mapColor = (color3) => new Color().setStyle(color3).multiplyScalar(Math.PI);
44621  useFrame(({
44622    scene
44623  }) => {
44624    scene.background = new Color().setStyle(state.lighting.backgroundColor);
44625  });
44626  let centerObject;
44627  return createComponent(T5.Group, {
44628    get position() {
44629      return perspectiveProps.position;
44630    },
44631    get up() {
44632      return perspectiveProps.up;
44633    },
44634    get target() {
44635      return perspectiveProps.target;
44636    },
44637    get children() {
44638      return [createComponent(T5.Mesh, {
44639        ref(r$) {
44640          const _ref$ = centerObject;
44641          typeof _ref$ === "function" ? _ref$(r$) : centerObject = r$;
44642        },
44643        visible: false
44644      }), createComponent(T5.AmbientLight, {
44645        get color() {
44646          return mapColor(state.lighting.ambientColor);
44647        }
44648      }), createComponent(For, {
44649        get each() {
44650          return state.lighting.directionalLights;
44651        },
44652        children: ({
44653          direction,
44654          color: color3
44655        }) => createComponent(T5.DirectionalLight, {
44656          target: centerObject,
44657          intensity: 1.4,
44658          get color() {
44659            return mapColor(color3);
44660          },
44661          get position() {
44662            return direction.map((x) =>
44662 -x);
44663          }
44664        })
44665      })];
44666    }
44667  });
44668};
44669var ControlledCamera = (props) => {
44670  const {
44671    state
44672  } = useCamera();
44673  return createComponent(Show, {
44674    get when() {
44675      return state.camera.perspective;
44676    },
44677    get fallback() {
44678      return createComponent(ControlledOrthographicCamera, {
44679        get aspect() {
44680          return props.aspect;
44681        },
44682        get children() {
44683          return props.children;
44684        }
44685      });
44686    },
44687    get children() {
44688      return createComponent(ControlledPerspectiveCamera, {
44689        get aspect() {
44690          return props.aspect;
44691        },
44692        get children() {
44693          return props.children;
44694        }
44695      });
44696    }
44697  });
44698};
44699var isLeftMouseButton = (e) => {
44700  e = e || window.event;
44701  if ("which" in e)
44702    return e.which === 1;
44703  else if ("button" in e)
44704    return e.button === 0;
44705  return false;
44706};
44707var LightedTrackballCanvas = (props) => {
44708  let size3;
44709  const aspect = () => size3 && size3.height ? size3.width / size3.height : 1;
44710  const canvasSize = () => size3;
44711  const {
44712    labels
44713  } = useViewer();
44714  const xr = createXR();
44715  const [xrSupported] = createResource(() => xr.isSupported("immersive-ar"));
44716  const [canvasEl, setCanvasEl] = createSignal(null);
44717  size3 = createElementSize(canvasEl);
44718  const connectRef = (ctx) => {
44719    setCanvasEl(ctx.gl.domElement);
44720    return xr.connect(ctx);
44721  };
44722  const [tool] = useInteractionTool();
44723  const handlePointerMove = (e) => {
44724    const handler = tool?.onDrag;
44725    if (isLeftMouseButton(e) && handler) {
44726      e.stopPropagation();
44727      handler(e);
44728    }
44729  };
44730  const handlePointerUp = (e) => {
44731    if (props.symmetryRenderer) return;
44732    const handler = tool?.onDragEnd;
44733    if (isLeftMouseButton(e) && handler) {
44734      handler(e);
44735    }
44736  };
44737  const handleWheel = (e) => {
44738    const handler = tool?.onWheel;
44739    if (handler) {
44740      e.preventDefault();
44741      handler(e.deltaY);
44742    }
44743  };
44744  const handlePointerMissed = (e) => {
44745    if (props.symmetryRenderer) return;
44746    const handler = tool?.bkgdClick;
44747    if (isLeftMouseButton(e.nativeEvent) && handler) {
44748      handler(e);
44749    }
44750  };
44751  const makeCustomRenderer = (canvas) => {
44752    if (props.useWebGL) {
44753      const renderer2 = new WebGLRenderer({
44754        powerPreference: "high-performance",
44755        canvas,
44756        antialias: true,
44757        alpha: true,
44758        preserveDrawingBuffer: true
44759      });
44760      return renderer2;
44761    }
44762    const renderer = new WebGPURenderer({
44763      powerPreference: "high-performance",
44764      canvas,
44765      antialias: true,
44766      alpha: true,
44767      preserveDrawingBuffer: true,
44768      forceWebGL: true
44769    });
44770    return renderer;
44771  };
44772  createRenderEffect(() => {
44773    const el = canvasEl();
44774    if (el) el.style.cursor = tool?.cursor() || "auto";
44775  });
44776  onMount(() => {
44777    const el = canvasEl();
44778    if (el) {
44779      el.addEventListener("pointerup", handlePointerUp);
44780      el.addEventListener("wheel", handleWheel);
44781    }
44782  });
44783  return createComponent(xr.Provider, {
44784    get children() {
44785      const _el$ = _tmpl$2();
44786      _el$.style.setProperty("position", "relative");
44787      insert(_el$, createComponent(Canvas, {
44788        ref: connectRef,
44789        "class": "canvas3d",
44790        get dpr() {
44791          return window.devicePixelRatio;
44792        },
44793        gl: makeCustomRenderer,
44794        style: {
44795          height: "100%",
44796          width: "100%",
44797          display: "flex"
44798        },
44799        frameloop: "always",
44800        onClickMissed: handlePointerMissed,
44801        get children() {
44802          return createComponent(WebXRSupport, {
44803            xrSupported,
44804            get children() {
44805              return [createComponent(ControlledCamera, {
44806                get aspect() {
44807                  return aspect();
44808                },
44809                get children() {
44810                  return createComponent(Lighting2, {});
44811                }
44812              }), createComponent(TrackballControls2, {
44813                get rotationOnly() {
44814                  return props.rotationOnly;
44815                },
44816                get rotateSpeed() {
44817                  return props.rotateSpeed;
44818                },
44819                get zoomSpeed() {
44820                  return props.zoomSpeed;
44821                },
44822                get panSpeed() {
44823                  return props.panSpeed;
44824                }
44825              }), memo(() => props.children), memo(() => memo(() => !!(labels && labels()))() && createComponent(Labels, {
44826                get size() {
44827                  return canvasSize();
44828                }
44829              }))];
44830            }
44831          });
44832        }
44833      }), null);
44834      insert(_el$, createComponent(Suspense, {
44835        get children() {
44836          return createComponent(Show, {
44837            get when() {
44838              return xrSupported();
44839            },
44840            get children() {
44841              const _el$2 = _tmpl$();
44842              _el$2.$$click = () => xr.enter("immersive-ar", {
44843                optionalFeatures: ["local-floor", "hand-tracking"]
44844              });
44845              _el$2.style.setProperty("position", "absolute");
44846              _el$2.style.setProperty("bottom", "20px");
44847              _el$2.style.setProperty("left", "50%");
44848              _el$2.style.setProperty("transform", "translateX(-50%)");
44849              _el$2.style.setProperty("padding", "12px 24px");
44850              _el$2.style.setProperty("border-radius", "4px");
44851              _el$2.style.setProperty("border", "none");
44852              _el$2.style.setProperty("background", "rgba(0,0,0,0.7)");
44853              _el$2.style.setProperty("color", "white");
44854              _el$2.style.setProperty("cursor", "pointer");
44855              _el$2.style.setProperty("font-size", "13px");
44856              _el$2.style.setProperty("font-family", "sans-serif");
44857              return _el$2;
44858            }
44859          });
44860        }
44861      }), null);
44862      createRenderEffect((_p$) => {
44863        const _v$ = props.height ?? "100%", _v$2 = props.width ?? "100%";
44864        _v$ !== _p$._v$ && ((_p$._v$ = _v$) != null ? _el$.style.setProperty("height", _v$) : _el$.style.removeProperty("height"));
44865        _v$2 !== _p$._v$2 && ((_p$._v$2 = _v$2) != null ? _el$.style.setProperty("width", _v$2) : _el$.style.removeProperty("width"));
44866        return _p$;
44867      }, {
44868        _v$: void 0,
44869        _v$2: void 0
44870      });
44871      return _el$;
44872    }
44873  });
44874};
44875delegateEvents(["click"]);
44876
44877// src/viewer/geometry.jsx
44878var T6 = createT({
44879  Group,
44880  Mesh,
44881  MeshLambertMaterial,
44882  LineSegments,
44883  LineBasicMaterial
44884});
44885var Instance = (props) => {
44886  let meshRef, linesRef;
44887  createEffect(() => {
44888    const m = new Matrix4();
44889    m.set(...props.rotation);
44890    meshRef.matrix = m;
44891    if (!!linesRef) linesRef.matrix = m.clone();
44892  });
44893  const [tool] = useInteractionTool();
44894  const handleHover = (value) => (e) => {
44895    const handler = tool?.onHover;
44896    if (handler) {
44897      e.stopPropagation();
44898      handler(props.id, props.position, props.type, value);
44899    }
44900  };
44901  const handleContextMenu = (e) => {
44902    const handler = tool?.onContextMenu;
44903    if (handler) {
44904      e.stopPropagation();
44905      handler(props.id, props.position, props.type, props.selected, props.label);
44906    }
44907  };
44908  const handlePointerDown = (e) => {
44909    if (e.nativeEvent.button !== 0)
44910      return;
44911    const handler = tool?.onDragStart;
44912    if (handler) {
44913      e.stopPropagation();
44914      handler(e.nativeEvent, props.id, props.position, props.type, props.selected);
44915    }
44916  };
44917  const handlePointerMove = (e) => {
44918    const handler = tool?.onDrag;
44919    if (handler) {
44920      e.stopPropagation();
44921      handler(e.nativeEvent, props.id, props.position, props.type, props.selected);
44922    }
44923  };
44924  const handlePointerUp = (e) => {
44925    if (e.nativeEvent.button !== 0)
44926      return;
44927    const handler = tool?.onDragEnd;
44928    if (handler) {
44929      e.stopPropagation();
44930      handler(e.nativeEvent, props.id, props.position, props.type, props.selected, props.label);
44931    }
44932  };
44933  const handleClick = (e) => {
44934    if (e.nativeEvent.button !== 0)
44935      return;
44936    const handler = tool?.onClick;
44937    if (handler) {
44938      e.stopPropagation();
44939      handler(e.nativeEvent, props.id, props.position, props.type, props.selected, props.label);
44940    }
44941  };
44942  onMount(() => linesRef && linesRef.layers.set(4));
44943  const color3 = new Color().setStyle(props.color);
44944  const emissive3 = () => props.selected ? "#c8c8c8" : "black";
44945  return createComponent(T6.Group, {
44946    get position() {
44947      return props.position;
44948    },
44949    get name() {
44950      return props.id;
44951    },
44952    get children() {
44953      return [createComponent(T6.Mesh, {
44954        matrixAutoUpdate: false,
44955        ref(r$) {
44956          const _ref$ = meshRef;
44957          typeof _ref$ === "function" ? _ref$(r$) : meshRef = r$;
44958        },
44959        get geometry() {
44960          return props.geometry;
44961        },
44962        get onPointerEnter() {
44963          return handleHover(true);
44964        },
44965        get onPointerLeave() {
44966          return handleHover(false);
44967        },
44968        onPointerMove: handlePointerMove,
44969        onClick: handleClick,
44970        onPointerDown: handlePointerDown,
44971        onPointerUp: handlePointerUp,
44972        onContextMenu: handleContextMenu,
44973        get children() {
44974          return createComponent(T6.MeshLambertMaterial, {
44975            attach: "material",
44976            color: color3,
44977            get emissive() {
44978              return emissive3();
44979            }
44980          });
44981        }
44982      }), memo(() => memo(() => !!!!props.outlineGeometry)() && createComponent(T6.LineSegments, {
44983        matrixAutoUpdate: false,
44984        ref(r$) {
44985          const _ref$2 = linesRef;
44986          typeof _ref$2 === "function" ? _ref$2(r$) : linesRef = r$;
44987        },
44988        get geometry() {
44989          return props.outlineGeometry;
44990        },
44991        get children() {
44992          return createComponent(T6.LineBasicMaterial, {
44993            attach: "material",
44994            linewidth: 4.4,
44995            color: "black"
44996          });
44997        }
44998      })), memo(() => memo(() => !!!!props.label)() && createComponent(Label, {
44999        parent: meshRef,
45000        get position() {
45001          return props.geometry.shapeCentroid;
45002        },
45003        get text() {
45004          return props.label;
45005        }
45006      }))];
45007    }
45008  });
45009};
45010var centroid = (vertices) => {
45011  let [sx, sy, sz] = [0, 0, 0];
45012  vertices.forEach(({
45013    x,
45014    y,
45015    z
45016  }) => {
45017    sx += x;
45018    sy += y;
45019    sz += z;
45020  });
45021  const num = vertices.length;
45022  return {
45023    x: sx / num,
45024    y: sy / num,
45025    z: sz / num
45026  };
45027};
45028var buildShapeGeometry = (shape, polygons) => {
45029  const {
45030    vertices,
45031    faces
45032  } = shape;
45033  const computeNormal = ([v0, v1, v2]) => {
45034    const e1 = new Vector3().subVectors(v1, v0);
45035    const e2 = new Vector3().subVectors(v2, v0);
45036    return new Vector3().crossVectors(e1, e2).normalize();
45037  };
45038  let positions = [];
45039  let normals = [];
45040  faces.forEach((face) => {
45041    const corners = face.vertices.map((i) => vertices[i]);
45042    const {
45043      x: nx,
45044      y: ny,
45045      z: nz
45046    } = computeNormal(corners);
45047    const addVertex = ({
45048      x,
45049      y,
45050      z
45051    }) => {
45052      positions.push(x, y, z);
45053      normals.push(nx, ny, nz);
45054    };
45055    if (polygons) {
45056      for (let index = 0; index < corners.length - 2; index++) {
45057        addVertex(corners[0]);
45058        addVertex(corners[(index + 1) % corners.length]);
45059        addVertex(corners[(index + 2) % corners.length]);
45060      }
45061    } else {
45062      corners.forEach(addVertex);
45063    }
45064  });
45065  const geometry = new BufferGeometry();
45066  geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
45067  geometry.setAttribute("normal", new Float32BufferAttribute(normals, 3));
45068  geometry.computeBoundingSphere();
45069  geometry.shapeCentroid = centroid(vertices);
45070  return geometry;
45071};
45072var buildOutlineGeometry = (shape) => {
45073  const {
45074    vertices,
45075    faces
45076  } = shape;
45077  let positions = [];
45078  vertices.map(({
45079    x,
45080    y,
45081    z
45082  }) => positions.push(x, y, z));
45083  let indices = [];
45084  faces.forEach((face) => {
45085    for (let i = 0; i < face.vertices.length; i++) {
45086      indices.push(face.vertices[i]);
45087      indices.push(face.vertices[(i + 1) % face.vertices.length]);
45088    }
45089  });
45090  const geometry = new BufferGeometry();
45091  geometry.setIndex(indices);
45092  geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
45093  geometry.computeBoundingSphere();
45094  return geometry;
45095};
45096var InstancedShape = (props) => {
45097  const {
45098    scene
45099  } = useScene();
45100  const showOutlines = () => scene.polygons;
45101  const geometry = createMemo(() => {
45102    const geometry2 = buildShapeGeometry(props.shape, scene.polygons);
45103    onCleanup(() => geometry2.dispose());
45104    return geometry2;
45105  });
45106  const outlineGeometry = createMemo(() => {
45107    const geometry2 = buildOutlineGeometry(props.shape);
45108    onCleanup(() => geometry2.dispose());
45109    return geometry2;
45110  });
45111  return createComponent(For, {
45112    get each() {
45113      return props.shape.instances;
45114    },
45115    children: (instance3) => createComponent(Instance, mergeProps(instance3, {
45116      get geometry() {
45117        return geometry();
45118      },
45119      get outlineGeometry() {
45120        return memo(() => !!showOutlines())() && outlineGeometry();
45121      }
45122    }))
45123  });
45124};
45125var CanvasExportBindings = () => {
45126  const {
45127    setExporter
45128  } = useGltfExporter();
45129  const {
45130    setCapturer
45131  } = useImageCapture();
45132  const three = useThree();
45133  const exportGltf = (callback) => {
45134    const exporter = new GLTFExporter();
45135    const onError = (error2) => {
45136      console.error("An error happened during glTF export:", error2);
45137    };
45138    exporter.parse(three.scene, callback, onError, {
45139      onlyVisible: false,
45140      binary: true
45141    });
45142  };
45143  setExporter({
45144    exportGltf
45145  });
45146  const capture = (mimeType, saveBlob) => {
45147    three.render();
45148    three.canvas.toBlob((blob) => {
45149      console.log(`Captured ${mimeType} image of size ${blob.size} bytes`);
45150      saveBlob(blob);
45151    }, mimeType);
45152  };
45153  setCapturer({
45154    capture
45155  });
45156  return null;
45157};
45158var ShapedGeometry = (props) => {
45159  let groupRef;
45160  createEffect(() => {
45161    if (props.embedding && groupRef && groupRef.matrix) {
45162      const m = new Matrix4();
45163      m.set(...props.embedding);
45164      m.transpose();
45165      groupRef.matrix.identity();
45166      groupRef.applyMatrix4(m);
45167    }
45168  });
45169  return (
45170    // <Show when={ () => props.shapes }>
45171    [createComponent(CanvasExportBindings, {}), createComponent(T6.Group, {
45172      matrixAutoUpdate: false,
45173      ref(r$) {
45174        const _ref$3 = groupRef;
45175        typeof _ref$3 === "function" ? _ref$3(r$) : groupRef = r$;
45176      },
45177      get children() {
45178        return createComponent(For, {
45179          get each() {
45180            return Object.values(props.shapes || {});
45181          },
45182          children: (shape) => createComponent(InstancedShape, {
45183            shape
45184          })
45185        });
45186      }
45187    })]
45188  );
45189};
45190
vendor: 23,899 bytes, lines 45191-45823
45191// node_modules/three/build/three.tsl.js
45192var BRDF_GGX2 = TSL.BRDF_GGX;
45193var BRDF_Lambert2 = TSL.BRDF_Lambert;
45194var BasicPointShadowFilter2 = TSL.BasicPointShadowFilter;
45195var BasicShadowFilter2 = TSL.BasicShadowFilter;
45196var Break2 = TSL.Break;
45197var Const2 = TSL.Const;
45198var Continue2 = TSL.Continue;
45199var DFGLUT2 = TSL.DFGLUT;
45200var D_GGX2 = TSL.D_GGX;
45201var Discard2 = TSL.Discard;
45202var EPSILON2 = TSL.EPSILON;
45203var F_Schlick2 = TSL.F_Schlick;
45204var Fn2 = TSL.Fn;
45205var INFINITY2 = TSL.INFINITY;
45206var If2 = TSL.If;
45207var Loop2 = TSL.Loop;
45208var NodeAccess2 = TSL.NodeAccess;
45209var NodeShaderStage2 = TSL.NodeShaderStage;
45210var NodeType2 = TSL.NodeType;
45211var NodeUpdateType2 = TSL.NodeUpdateType;
45212var PCFShadowFilter2 = TSL.PCFShadowFilter;
45213var PCFSoftShadowFilter2 = TSL.PCFSoftShadowFilter;
45214var PI3 = TSL.PI;
45215var PI22 = TSL.PI2;
45216var TWO_PI2 = TSL.TWO_PI;
45217var HALF_PI2 = TSL.HALF_PI;
45218var PointShadowFilter2 = TSL.PointShadowFilter;
45219var Return2 = TSL.Return;
45220var Schlick_to_F02 = TSL.Schlick_to_F0;
45221var ShaderNode2 = TSL.ShaderNode;
45222var Stack2 = TSL.Stack;
45223var Switch2 = TSL.Switch;
45224var TBNViewMatrix2 = TSL.TBNViewMatrix;
45225var VSMShadowFilter2 = TSL.VSMShadowFilter;
45226var V_GGX_SmithCorrelated2 = TSL.V_GGX_SmithCorrelated;
45227var Var2 = TSL.Var;
45228var VarIntent2 = TSL.VarIntent;
45229var abs2 = TSL.abs;
45230var acesFilmicToneMapping2 = TSL.acesFilmicToneMapping;
45231var acos2 = TSL.acos;
45232var acosh2 = TSL.acosh;
45233var add2 = TSL.add;
45234var addMethodChaining2 = TSL.addMethodChaining;
45235var addNodeElement2 = TSL.addNodeElement;
45236var agxToneMapping2 = TSL.agxToneMapping;
45237var all2 = TSL.all;
45238var alphaT2 = TSL.alphaT;
45239var and2 = TSL.and;
45240var anisotropy2 = TSL.anisotropy;
45241var anisotropyB2 = TSL.anisotropyB;
45242var anisotropyT2 = TSL.anisotropyT;
45243var any2 = TSL.any;
45244var append2 = TSL.append;
45245var array2 = TSL.array;
45246var arrayBuffer2 = TSL.arrayBuffer;
45247var asin2 = TSL.asin;
45248var asinh2 = TSL.asinh;
45249var assign2 = TSL.assign;
45250var atan2 = TSL.atan;
45251var atanh2 = TSL.atanh;
45252var atomicAdd2 = TSL.atomicAdd;
45253var atomicAnd2 = TSL.atomicAnd;
45254var atomicFunc2 = TSL.atomicFunc;
45255var atomicLoad2 = TSL.atomicLoad;
45256var atomicMax2 = TSL.atomicMax;
45257var atomicMin2 = TSL.atomicMin;
45258var atomicOr2 = TSL.atomicOr;
45259var atomicStore2 = TSL.atomicStore;
45260var atomicSub2 = TSL.atomicSub;
45261var atomicXor2 = TSL.atomicXor;
45262var attenuationColor2 = TSL.attenuationColor;
45263var attenuationDistance2 = TSL.attenuationDistance;
45264var attribute2 = TSL.attribute;
45265var attributeArray2 = TSL.attributeArray;
45266var backgroundBlurriness2 = TSL.backgroundBlurriness;
45267var backgroundIntensity2 = TSL.backgroundIntensity;
45268var backgroundRotation2 = TSL.backgroundRotation;
45269var batch3 = TSL.batch;
45270var bentNormalView2 = TSL.bentNormalView;
45271var billboarding2 = TSL.billboarding;
45272var bitAnd2 = TSL.bitAnd;
45273var bitNot2 = TSL.bitNot;
45274var bitOr2 = TSL.bitOr;
45275var bitXor2 = TSL.bitXor;
45276var bitangentGeometry2 = TSL.bitangentGeometry;
45277var bitangentLocal2 = TSL.bitangentLocal;
45278var bitangentView2 = TSL.bitangentView;
45279var bitangentWorld2 = TSL.bitangentWorld;
45280var bitcast2 = TSL.bitcast;
45281var blendBurn2 = TSL.blendBurn;
45282var blendColor2 = TSL.blendColor;
45283var blendDodge2 = TSL.blendDodge;
45284var blendOverlay2 = TSL.blendOverlay;
45285var blendScreen2 = TSL.blendScreen;
45286var blur2 = TSL.blur;
45287var bool2 = TSL.bool;
45288var buffer2 = TSL.buffer;
45289var bufferAttribute2 = TSL.bufferAttribute;
45290var bumpMap2 = TSL.bumpMap;
45291var builtin2 = TSL.builtin;
45292var builtinAOContext2 = TSL.builtinAOContext;
45293var builtinShadowContext2 = TSL.builtinShadowContext;
45294var bvec22 = TSL.bvec2;
45295var bvec32 = TSL.bvec3;
45296var bvec42 = TSL.bvec4;
45297var bypass2 = TSL.bypass;
45298var cache2 = TSL.cache;
45299var call2 = TSL.call;
45300var cameraFar2 = TSL.cameraFar;
45301var cameraIndex2 = TSL.cameraIndex;
45302var cameraNear2 = TSL.cameraNear;
45303var cameraNormalMatrix2 = TSL.cameraNormalMatrix;
45304var cameraPosition2 = TSL.cameraPosition;
45305var cameraProjectionMatrix2 = TSL.cameraProjectionMatrix;
45306var cameraProjectionMatrixInverse2 = TSL.cameraProjectionMatrixInverse;
45307var cameraViewMatrix2 = TSL.cameraViewMatrix;
45308var cameraViewport2 = TSL.cameraViewport;
45309var cameraWorldMatrix2 = TSL.cameraWorldMatrix;
45310var cbrt2 = TSL.cbrt;
45311var cdl2 = TSL.cdl;
45312var ceil2 = TSL.ceil;
45313var checker2 = TSL.checker;
45314var cineonToneMapping2 = TSL.cineonToneMapping;
45315var clamp4 = TSL.clamp;
45316var clearcoat2 = TSL.clearcoat;
45317var clearcoatNormalView2 = TSL.clearcoatNormalView;
45318var clearcoatRoughness2 = TSL.clearcoatRoughness;
45319var clipSpace2 = TSL.clipSpace;
45320var code2 = TSL.code;
45321var color2 = TSL.color;
45322var colorSpaceToWorking2 = TSL.colorSpaceToWorking;
45323var colorToDirection2 = TSL.colorToDirection;
45324var compute2 = TSL.compute;
45325var computeKernel2 = TSL.computeKernel;
45326var computeSkinning2 = TSL.computeSkinning;
45327var context2 = TSL.context;
45328var convert2 = TSL.convert;
45329var convertColorSpace2 = TSL.convertColorSpace;
45330var convertToTexture2 = TSL.convertToTexture;
45331var countLeadingZeros2 = TSL.countLeadingZeros;
45332var countOneBits2 = TSL.countOneBits;
45333var countTrailingZeros2 = TSL.countTrailingZeros;
45334var cos2 = TSL.cos;
45335var cosh2 = TSL.cosh;
45336var cross2 = TSL.cross;
45337var cubeTexture2 = TSL.cubeTexture;
45338var cubeTextureBase2 = TSL.cubeTextureBase;
45339var dFdx2 = TSL.dFdx;
45340var dFdy2 = TSL.dFdy;
45341var dashSize2 = TSL.dashSize;
45342var debug2 = TSL.debug;
45343var decrement2 = TSL.decrement;
45344var decrementBefore2 = TSL.decrementBefore;
45345var defaultBuildStages2 = TSL.defaultBuildStages;
45346var defaultShaderStages2 = TSL.defaultShaderStages;
45347var defined2 = TSL.defined;
45348var degrees2 = TSL.degrees;
45349var deltaTime2 = TSL.deltaTime;
45350var densityFog = TSL.densityFog;
45351var densityFogFactor2 = TSL.densityFogFactor;
45352var depth2 = TSL.depth;
45353var depthPass2 = TSL.depthPass;
45354var determinant2 = TSL.determinant;
45355var difference2 = TSL.difference;
45356var diffuseColor2 = TSL.diffuseColor;
45357var directPointLight2 = TSL.directPointLight;
45358var directionToColor2 = TSL.directionToColor;
45359var directionToFaceDirection2 = TSL.directionToFaceDirection;
45360var dispersion2 = TSL.dispersion;
45361var distance2 = TSL.distance;
45362var div2 = TSL.div;
45363var dot2 = TSL.dot;
45364var drawIndex2 = TSL.drawIndex;
45365var dynamicBufferAttribute2 = TSL.dynamicBufferAttribute;
45366var element2 = TSL.element;
45367var emissive2 = TSL.emissive;
45368var equal2 = TSL.equal;
45369var equirectUV2 = TSL.equirectUV;
45370var exp3 = TSL.exp;
45371var exp22 = TSL.exp2;
45372var exponentialHeightFogFactor2 = TSL.exponentialHeightFogFactor;
45373var expression2 = TSL.expression;
45374var faceDirection2 = TSL.faceDirection;
45375var faceForward2 = TSL.faceForward;
45376var faceforward2 = TSL.faceforward;
45377var float2 = TSL.float;
45378var floatBitsToInt2 = TSL.floatBitsToInt;
45379var floatBitsToUint2 = TSL.floatBitsToUint;
45380var floor2 = TSL.floor;
45381var fog2 = TSL.fog;
45382var fract2 = TSL.fract;
45383var frameGroup2 = TSL.frameGroup;
45384var frameId2 = TSL.frameId;
45385var frontFacing2 = TSL.frontFacing;
45386var fwidth2 = TSL.fwidth;
45387var gain2 = TSL.gain;
45388var gapSize2 = TSL.gapSize;
45389var getConstNodeType2 = TSL.getConstNodeType;
45390var getCurrentStack2 = TSL.getCurrentStack;
45391var getDirection2 = TSL.getDirection;
45392var getDistanceAttenuation2 = TSL.getDistanceAttenuation;
45393var getGeometryRoughness2 = TSL.getGeometryRoughness;
45394var getNormalFromDepth2 = TSL.getNormalFromDepth;
45395var interleavedGradientNoise2 = TSL.interleavedGradientNoise;
45396var vogelDiskSample2 = TSL.vogelDiskSample;
45397var getParallaxCorrectNormal2 = TSL.getParallaxCorrectNormal;
45398var getRoughness2 = TSL.getRoughness;
45399var getScreenPosition2 = TSL.getScreenPosition;
45400var getShIrradianceAt2 = TSL.getShIrradianceAt;
45401var getShadowMaterial2 = TSL.getShadowMaterial;
45402var getShadowRenderObjectFunction2 = TSL.getShadowRenderObjectFunction;
45403var getTextureIndex2 = TSL.getTextureIndex;
45404var getViewPosition2 = TSL.getViewPosition;
45405var globalId2 = TSL.globalId;
45406var glsl2 = TSL.glsl;
45407var glslFn2 = TSL.glslFn;
45408var grayscale2 = TSL.grayscale;
45409var greaterThan2 = TSL.greaterThan;
45410var greaterThanEqual2 = TSL.greaterThanEqual;
45411var hash2 = TSL.hash;
45412var highpModelNormalViewMatrix2 = TSL.highpModelNormalViewMatrix;
45413var highpModelViewMatrix2 = TSL.highpModelViewMatrix;
45414var hue2 = TSL.hue;
45415var increment2 = TSL.increment;
45416var incrementBefore2 = TSL.incrementBefore;
45417var instance2 = TSL.instance;
45418var instanceIndex2 = TSL.instanceIndex;
45419var instancedArray2 = TSL.instancedArray;
45420var instancedBufferAttribute2 = TSL.instancedBufferAttribute;
45421var instancedDynamicBufferAttribute2 = TSL.instancedDynamicBufferAttribute;
45422var instancedMesh2 = TSL.instancedMesh;
45423var int2 = TSL.int;
45424var intBitsToFloat2 = TSL.intBitsToFloat;
45425var inverse2 = TSL.inverse;
45426var inverseSqrt2 = TSL.inverseSqrt;
45427var inversesqrt2 = TSL.inversesqrt;
45428var invocationLocalIndex2 = TSL.invocationLocalIndex;
45429var invocationSubgroupIndex2 = TSL.invocationSubgroupIndex;
45430var ior2 = TSL.ior;
45431var iridescence2 = TSL.iridescence;
45432var iridescenceIOR2 = TSL.iridescenceIOR;
45433var iridescenceThickness2 = TSL.iridescenceThickness;
45434var ivec22 = TSL.ivec2;
45435var ivec32 = TSL.ivec3;
45436var ivec42 = TSL.ivec4;
45437var js2 = TSL.js;
45438var label2 = TSL.label;
45439var length2 = TSL.length;
45440var lengthSq2 = TSL.lengthSq;
45441var lessThan2 = TSL.lessThan;
45442var lessThanEqual2 = TSL.lessThanEqual;
45443var lightPosition2 = TSL.lightPosition;
45444var lightProjectionUV2 = TSL.lightProjectionUV;
45445var lightShadowMatrix2 = TSL.lightShadowMatrix;
45446var lightTargetDirection2 = TSL.lightTargetDirection;
45447var lightTargetPosition2 = TSL.lightTargetPosition;
45448var lightViewPosition2 = TSL.lightViewPosition;
45449var lightingContext2 = TSL.lightingContext;
45450var lights2 = TSL.lights;
45451var linearDepth2 = TSL.linearDepth;
45452var linearToneMapping2 = TSL.linearToneMapping;
45453var localId2 = TSL.localId;
45454var log3 = TSL.log;
45455var log23 = TSL.log2;
45456var logarithmicDepthToViewZ2 = TSL.logarithmicDepthToViewZ;
45457var luminance2 = TSL.luminance;
45458var mat22 = TSL.mat2;
45459var mat32 = TSL.mat3;
45460var mat42 = TSL.mat4;
45461var matcapUV2 = TSL.matcapUV;
45462var materialAO2 = TSL.materialAO;
45463var materialAlphaTest2 = TSL.materialAlphaTest;
45464var materialAnisotropy2 = TSL.materialAnisotropy;
45465var materialAnisotropyVector2 = TSL.materialAnisotropyVector;
45466var materialAttenuationColor2 = TSL.materialAttenuationColor;
45467var materialAttenuationDistance2 = TSL.materialAttenuationDistance;
45468var materialClearcoat2 = TSL.materialClearcoat;
45469var materialClearcoatNormal2 = TSL.materialClearcoatNormal;
45470var materialClearcoatRoughness2 = TSL.materialClearcoatRoughness;
45471var materialColor2 = TSL.materialColor;
45472var materialDispersion2 = TSL.materialDispersion;
45473var materialEmissive2 = TSL.materialEmissive;
45474var materialEnvIntensity2 = TSL.materialEnvIntensity;
45475var materialEnvRotation2 = TSL.materialEnvRotation;
45476var materialIOR2 = TSL.materialIOR;
45477var materialIridescence2 = TSL.materialIridescence;
45478var materialIridescenceIOR2 = TSL.materialIridescenceIOR;
45479var materialIridescenceThickness2 = TSL.materialIridescenceThickness;
45480var materialLightMap2 = TSL.materialLightMap;
45481var materialLineDashOffset2 = TSL.materialLineDashOffset;
45482var materialLineDashSize2 = TSL.materialLineDashSize;
45483var materialLineGapSize2 = TSL.materialLineGapSize;
45484var materialLineScale2 = TSL.materialLineScale;
45485var materialLineWidth2 = TSL.materialLineWidth;
45486var materialMetalness2 = TSL.materialMetalness;
45487var materialNormal2 = TSL.materialNormal;
45488var materialOpacity2 = TSL.materialOpacity;
45489var materialPointSize2 = TSL.materialPointSize;
45490var materialReference2 = TSL.materialReference;
45491var materialReflectivity2 = TSL.materialReflectivity;
45492var materialRefractionRatio2 = TSL.materialRefractionRatio;
45493var materialRotation2 = TSL.materialRotation;
45494var materialRoughness2 = TSL.materialRoughness;
45495var materialSheen2 = TSL.materialSheen;
45496var materialSheenRoughness2 = TSL.materialSheenRoughness;
45497var materialShininess2 = TSL.materialShininess;
45498var materialSpecular2 = TSL.materialSpecular;
45499var materialSpecularColor2 = TSL.materialSpecularColor;
45500var materialSpecularIntensity2 = TSL.materialSpecularIntensity;
45501var materialSpecularStrength2 = TSL.materialSpecularStrength;
45502var materialThickness2 = TSL.materialThickness;
45503var materialTransmission2 = TSL.materialTransmission;
45504var max2 = TSL.max;
45505var maxMipLevel2 = TSL.maxMipLevel;
45506var mediumpModelViewMatrix2 = TSL.mediumpModelViewMatrix;
45507var metalness2 = TSL.metalness;
45508var min2 = TSL.min;
45509var mix2 = TSL.mix;
45510var mixElement2 = TSL.mixElement;
45511var mod2 = TSL.mod;
45512var modInt2 = TSL.modInt;
45513var modelDirection2 = TSL.modelDirection;
45514var modelNormalMatrix2 = TSL.modelNormalMatrix;
45515var modelPosition2 = TSL.modelPosition;
45516var modelRadius2 = TSL.modelRadius;
45517var modelScale2 = TSL.modelScale;
45518var modelViewMatrix2 = TSL.modelViewMatrix;
45519var modelViewPosition2 = TSL.modelViewPosition;
45520var modelViewProjection2 = TSL.modelViewProjection;
45521var modelWorldMatrix2 = TSL.modelWorldMatrix;
45522var modelWorldMatrixInverse2 = TSL.modelWorldMatrixInverse;
45523var morphReference2 = TSL.morphReference;
45524var mrt2 = TSL.mrt;
45525var mul2 = TSL.mul;
45526var mx_aastep2 = TSL.mx_aastep;
45527var mx_add2 = TSL.mx_add;
45528var mx_atan22 = TSL.mx_atan2;
45529var mx_cell_noise_float2 = TSL.mx_cell_noise_float;
45530var mx_contrast2 = TSL.mx_contrast;
45531var mx_divide2 = TSL.mx_divide;
45532var mx_fractal_noise_float2 = TSL.mx_fractal_noise_float;
45533var mx_fractal_noise_vec22 = TSL.mx_fractal_noise_vec2;
45534var mx_fractal_noise_vec32 = TSL.mx_fractal_noise_vec3;
45535var mx_fractal_noise_vec42 = TSL.mx_fractal_noise_vec4;
45536var mx_frame2 = TSL.mx_frame;
45537var mx_heighttonormal2 = TSL.mx_heighttonormal;
45538var mx_hsvtorgb2 = TSL.mx_hsvtorgb;
45539var mx_ifequal2 = TSL.mx_ifequal;
45540var mx_ifgreater2 = TSL.mx_ifgreater;
45541var mx_ifgreatereq2 = TSL.mx_ifgreatereq;
45542var mx_invert2 = TSL.mx_invert;
45543var mx_modulo2 = TSL.mx_modulo;
45544var mx_multiply2 = TSL.mx_multiply;
45545var mx_noise_float2 = TSL.mx_noise_float;
45546var mx_noise_vec32 = TSL.mx_noise_vec3;
45547var mx_noise_vec42 = TSL.mx_noise_vec4;
45548var mx_place2d2 = TSL.mx_place2d;
45549var mx_power2 = TSL.mx_power;
45550var mx_ramp42 = TSL.mx_ramp4;
45551var mx_ramplr2 = TSL.mx_ramplr;
45552var mx_ramptb2 = TSL.mx_ramptb;
45553var mx_rgbtohsv2 = TSL.mx_rgbtohsv;
45554var mx_rotate2d2 = TSL.mx_rotate2d;
45555var mx_rotate3d2 = TSL.mx_rotate3d;
45556var mx_safepower2 = TSL.mx_safepower;
45557var mx_separate2 = TSL.mx_separate;
45558var mx_splitlr2 = TSL.mx_splitlr;
45559var mx_splittb2 = TSL.mx_splittb;
45560var mx_srgb_texture_to_lin_rec7092 = TSL.mx_srgb_texture_to_lin_rec709;
45561var mx_subtract2 = TSL.mx_subtract;
45562var mx_timer2 = TSL.mx_timer;
45563var mx_transform_uv2 = TSL.mx_transform_uv;
45564var mx_unifiednoise2d2 = TSL.mx_unifiednoise2d;
45565var mx_unifiednoise3d2 = TSL.mx_unifiednoise3d;
45566var mx_worley_noise_float2 = TSL.mx_worley_noise_float;
45567var mx_worley_noise_vec22 = TSL.mx_worley_noise_vec2;
45568var mx_worley_noise_vec32 = TSL.mx_worley_noise_vec3;
45569var negate2 = TSL.negate;
45570var neutralToneMapping2 = TSL.neutralToneMapping;
45571var nodeArray2 = TSL.nodeArray;
45572var nodeImmutable2 = TSL.nodeImmutable;
45573var nodeObject2 = TSL.nodeObject;
45574var nodeObjectIntent2 = TSL.nodeObjectIntent;
45575var nodeObjects2 = TSL.nodeObjects;
45576var nodeProxy2 = TSL.nodeProxy;
45577var nodeProxyIntent2 = TSL.nodeProxyIntent;
45578var normalFlat2 = TSL.normalFlat;
45579var normalGeometry2 = TSL.normalGeometry;
45580var normalLocal2 = TSL.normalLocal;
45581var normalMap2 = TSL.normalMap;
45582var normalView2 = TSL.normalView;
45583var normalViewGeometry2 = TSL.normalViewGeometry;
45584var normalWorld2 = TSL.normalWorld;
45585var normalWorldGeometry2 = TSL.normalWorldGeometry;
45586var normalize2 = TSL.normalize;
45587var not2 = TSL.not;
45588var notEqual2 = TSL.notEqual;
45589var numWorkgroups2 = TSL.numWorkgroups;
45590var objectDirection2 = TSL.objectDirection;
45591var objectGroup2 = TSL.objectGroup;
45592var objectPosition2 = TSL.objectPosition;
45593var objectRadius2 = TSL.objectRadius;
45594var objectScale2 = TSL.objectScale;
45595var objectViewPosition2 = TSL.objectViewPosition;
45596var objectWorldMatrix2 = TSL.objectWorldMatrix;
45597var OnBeforeObjectUpdate2 = TSL.OnBeforeObjectUpdate;
45598var OnBeforeMaterialUpdate2 = TSL.OnBeforeMaterialUpdate;
45599var OnObjectUpdate2 = TSL.OnObjectUpdate;
45600var OnMaterialUpdate2 = TSL.OnMaterialUpdate;
45601var oneMinus2 = TSL.oneMinus;
45602var or2 = TSL.or;
45603var orthographicDepthToViewZ2 = TSL.orthographicDepthToViewZ;
45604var oscSawtooth2 = TSL.oscSawtooth;
45605var oscSine2 = TSL.oscSine;
45606var oscSquare2 = TSL.oscSquare;
45607var oscTriangle2 = TSL.oscTriangle;
45608var output2 = TSL.output;
45609var outputStruct2 = TSL.outputStruct;
45610var overloadingFn2 = TSL.overloadingFn;
45611var packHalf2x162 = TSL.packHalf2x16;
45612var packSnorm2x162 = TSL.packSnorm2x16;
45613var packUnorm2x162 = TSL.packUnorm2x16;
45614var parabola2 = TSL.parabola;
45615var parallaxDirection2 = TSL.parallaxDirection;
45616var parallaxUV2 = TSL.parallaxUV;
45617var parameter2 = TSL.parameter;
45618var pass2 = TSL.pass;
45619var passTexture2 = TSL.passTexture;
45620var pcurve2 = TSL.pcurve;
45621var perspectiveDepthToViewZ2 = TSL.perspectiveDepthToViewZ;
45622var pmremTexture2 = TSL.pmremTexture;
45623var pointShadow2 = TSL.pointShadow;
45624var pointUV2 = TSL.pointUV;
45625var pointWidth2 = TSL.pointWidth;
45626var positionGeometry2 = TSL.positionGeometry;
45627var positionLocal2 = TSL.positionLocal;
45628var positionPrevious2 = TSL.positionPrevious;
45629var positionView2 = TSL.positionView;
45630var positionViewDirection2 = TSL.positionViewDirection;
45631var positionWorld2 = TSL.positionWorld;
45632var positionWorldDirection2 = TSL.positionWorldDirection;
45633var posterize2 = TSL.posterize;
45634var pow5 = TSL.pow;
45635var pow22 = TSL.pow2;
45636var pow32 = TSL.pow3;
45637var pow42 = TSL.pow4;
45638var premultiplyAlpha2 = TSL.premultiplyAlpha;
45639var property2 = TSL.property;
45640var radians2 = TSL.radians;
45641var rand2 = TSL.rand;
45642var range2 = TSL.range;
45643var rangeFog = TSL.rangeFog;
45644var rangeFogFactor2 = TSL.rangeFogFactor;
45645var reciprocal2 = TSL.reciprocal;
45646var reference2 = TSL.reference;
45647var referenceBuffer2 = TSL.referenceBuffer;
45648var reflect2 = TSL.reflect;
45649var reflectVector2 = TSL.reflectVector;
45650var reflectView2 = TSL.reflectView;
45651var reflector2 = TSL.reflector;
45652var refract2 = TSL.refract;
45653var refractVector2 = TSL.refractVector;
45654var refractView2 = TSL.refractView;
45655var reinhardToneMapping2 = TSL.reinhardToneMapping;
45656var remap2 = TSL.remap;
45657var remapClamp2 = TSL.remapClamp;
45658var renderGroup2 = TSL.renderGroup;
45659var renderOutput2 = TSL.renderOutput;
45660var rendererReference2 = TSL.rendererReference;
45661var replaceDefaultUV2 = TSL.replaceDefaultUV;
45662var rotate2 = TSL.rotate;
45663var rotateUV2 = TSL.rotateUV;
45664var roughness2 = TSL.roughness;
45665var round2 = TSL.round;
45666var rtt2 = TSL.rtt;
45667var sRGBTransferEOTF2 = TSL.sRGBTransferEOTF;
45668var sRGBTransferOETF2 = TSL.sRGBTransferOETF;
45669var sample2 = TSL.sample;
45670var sampler2 = TSL.sampler;
45671var samplerComparison2 = TSL.samplerComparison;
45672var saturate2 = TSL.saturate;
45673var saturation2 = TSL.saturation;
45674var screen = TSL.screen;
45675var screenCoordinate2 = TSL.screenCoordinate;
45676var screenDPR2 = TSL.screenDPR;
45677var screenSize2 = TSL.screenSize;
45678var screenUV2 = TSL.screenUV;
45679var select2 = TSL.select;
45680var setCurrentStack2 = TSL.setCurrentStack;
45681var setName2 = TSL.setName;
45682var shaderStages2 = TSL.shaderStages;
45683var shadow2 = TSL.shadow;
45684var shadowPositionWorld2 = TSL.shadowPositionWorld;
45685var shapeCircle2 = TSL.shapeCircle;
45686var sharedUniformGroup2 = TSL.sharedUniformGroup;
45687var sheen2 = TSL.sheen;
45688var sheenRoughness2 = TSL.sheenRoughness;
45689var shiftLeft2 = TSL.shiftLeft;
45690var shiftRight2 = TSL.shiftRight;
45691var shininess2 = TSL.shininess;
45692var sign2 = TSL.sign;
45693var sin2 = TSL.sin;
45694var sinh2 = TSL.sinh;
45695var sinc2 = TSL.sinc;
45696var skinning2 = TSL.skinning;
45697var smoothstep2 = TSL.smoothstep;
45698var smoothstepElement2 = TSL.smoothstepElement;
45699var specularColor2 = TSL.specularColor;
45700var specularF902 = TSL.specularF90;
45701var spherizeUV2 = TSL.spherizeUV;
45702var split2 = TSL.split;
45703var spritesheetUV2 = TSL.spritesheetUV;
45704var sqrt2 = TSL.sqrt;
45705var stack2 = TSL.stack;
45706var step2 = TSL.step;
45707var stepElement2 = TSL.stepElement;
45708var storage2 = TSL.storage;
45709var storageBarrier2 = TSL.storageBarrier;
45710var storageTexture2 = TSL.storageTexture;
45711var string2 = TSL.string;
45712var struct2 = TSL.struct;
45713var sub2 = TSL.sub;
45714var subgroupAdd2 = TSL.subgroupAdd;
45715var subgroupAll2 = TSL.subgroupAll;
45716var subgroupAnd2 = TSL.subgroupAnd;
45717var subgroupAny2 = TSL.subgroupAny;
45718var subgroupBallot2 = TSL.subgroupBallot;
45719var subgroupBroadcast2 = TSL.subgroupBroadcast;
45720var subgroupBroadcastFirst2 = TSL.subgroupBroadcastFirst;
45721var subBuild2 = TSL.subBuild;
45722var subgroupElect2 = TSL.subgroupElect;
45723var subgroupExclusiveAdd2 = TSL.subgroupExclusiveAdd;
45724var subgroupExclusiveMul2 = TSL.subgroupExclusiveMul;
45725var subgroupInclusiveAdd2 = TSL.subgroupInclusiveAdd;
45726var subgroupInclusiveMul2 = TSL.subgroupInclusiveMul;
45727var subgroupIndex2 = TSL.subgroupIndex;
45728var subgroupMax2 = TSL.subgroupMax;
45729var subgroupMin2 = TSL.subgroupMin;
45730var subgroupMul2 = TSL.subgroupMul;
45731var subgroupOr2 = TSL.subgroupOr;
45732var subgroupShuffle2 = TSL.subgroupShuffle;
45733var subgroupShuffleDown2 = TSL.subgroupShuffleDown;
45734var subgroupShuffleUp2 = TSL.subgroupShuffleUp;
45735var subgroupShuffleXor2 = TSL.subgroupShuffleXor;
45736var subgroupSize2 = TSL.subgroupSize;
45737var subgroupXor2 = TSL.subgroupXor;
45738var tan2 = TSL.tan;
45739var tanh2 = TSL.tanh;
45740var tangentGeometry2 = TSL.tangentGeometry;
45741var tangentLocal2 = TSL.tangentLocal;
45742var tangentView2 = TSL.tangentView;
45743var tangentWorld2 = TSL.tangentWorld;
45744var texture2 = TSL.texture;
45745var texture3D2 = TSL.texture3D;
45746var textureBarrier2 = TSL.textureBarrier;
45747var textureBicubic2 = TSL.textureBicubic;
45748var textureBicubicLevel2 = TSL.textureBicubicLevel;
45749var textureCubeUV2 = TSL.textureCubeUV;
45750var textureLoad2 = TSL.textureLoad;
45751var textureSize2 = TSL.textureSize;
45752var textureLevel2 = TSL.textureLevel;
45753var textureStore2 = TSL.textureStore;
45754var thickness2 = TSL.thickness;
45755var time2 = TSL.time;
45756var toneMapping2 = TSL.toneMapping;
45757var toneMappingExposure2 = TSL.toneMappingExposure;
45758var toonOutlinePass2 = TSL.toonOutlinePass;
45759var transformDirection2 = TSL.transformDirection;
45760var transformNormal2 = TSL.transformNormal;
45761var transformNormalToView2 = TSL.transformNormalToView;
45762var transformedClearcoatNormalView2 = TSL.transformedClearcoatNormalView;
45763var transformedNormalView2 = TSL.transformedNormalView;
45764var transformedNormalWorld2 = TSL.transformedNormalWorld;
45765var transmission2 = TSL.transmission;
45766var transpose2 = TSL.transpose;
45767var triNoise3D2 = TSL.triNoise3D;
45768var triplanarTexture2 = TSL.triplanarTexture;
45769var triplanarTextures2 = TSL.triplanarTextures;
45770var trunc2 = TSL.trunc;
45771var uint2 = TSL.uint;
45772var uintBitsToFloat2 = TSL.uintBitsToFloat;
45773var uniform2 = TSL.uniform;
45774var uniformArray2 = TSL.uniformArray;
45775var uniformCubeTexture2 = TSL.uniformCubeTexture;
45776var uniformGroup2 = TSL.uniformGroup;
45777var uniformFlow2 = TSL.uniformFlow;
45778var uniformTexture2 = TSL.uniformTexture;
45779var unpackHalf2x162 = TSL.unpackHalf2x16;
45780var unpackSnorm2x162 = TSL.unpackSnorm2x16;
45781var unpackUnorm2x162 = TSL.unpackUnorm2x16;
45782var unpremultiplyAlpha2 = TSL.unpremultiplyAlpha;
45783var userData2 = TSL.userData;
45784var uv2 = TSL.uv;
45785var uvec22 = TSL.uvec2;
45786var uvec32 = TSL.uvec3;
45787var uvec42 = TSL.uvec4;
45788var varying2 = TSL.varying;
45789var varyingProperty2 = TSL.varyingProperty;
45790var vec22 = TSL.vec2;
45791var vec32 = TSL.vec3;
45792var vec42 = TSL.vec4;
45793var vectorComponents2 = TSL.vectorComponents;
45794var velocity2 = TSL.velocity;
45795var vertexColor2 = TSL.vertexColor;
45796var vertexIndex2 = TSL.vertexIndex;
45797var vertexStage2 = TSL.vertexStage;
45798var vibrance2 = TSL.vibrance;
45799var viewZToLogarithmicDepth2 = TSL.viewZToLogarithmicDepth;
45800var viewZToOrthographicDepth2 = TSL.viewZToOrthographicDepth;
45801var viewZToPerspectiveDepth2 = TSL.viewZToPerspectiveDepth;
45802var viewZToReversedOrthographicDepth2 = TSL.viewZToReversedOrthographicDepth;
45803var viewZToReversedPerspectiveDepth2 = TSL.viewZToReversedPerspectiveDepth;
45804var viewport2 = TSL.viewport;
45805var viewportCoordinate2 = TSL.viewportCoordinate;
45806var viewportDepthTexture2 = TSL.viewportDepthTexture;
45807var viewportLinearDepth2 = TSL.viewportLinearDepth;
45808var viewportMipTexture2 = TSL.viewportMipTexture;
45809var viewportOpaqueMipTexture2 = TSL.viewportOpaqueMipTexture;
45810var viewportResolution2 = TSL.viewportResolution;
45811var viewportSafeUV2 = TSL.viewportSafeUV;
45812var viewportSharedTexture2 = TSL.viewportSharedTexture;
45813var viewportSize2 = TSL.viewportSize;
45814var viewportTexture2 = TSL.viewportTexture;
45815var viewportUV2 = TSL.viewportUV;
45816var wgsl2 = TSL.wgsl;
45817var wgslFn2 = TSL.wgslFn;
45818var workgroupArray2 = TSL.workgroupArray;
45819var workgroupBarrier2 = TSL.workgroupBarrier;
45820var workgroupId2 = TSL.workgroupId;
45821var workingToColorSpace2 = TSL.workingToColorSpace;
45822var xor2 = TSL.xor;
45823
45824// src/viewer/context/symmetry-renderer.js
45825var INITIAL_SHAPE_CAPACITY = 64;
45826var COLOR_PALETTE_CAPACITY = 256;
45827function createSymmetryRenderer(parent) {
45828  const originGroup = new Group();
45829  originGroup.matrixAutoUpdate = false;
45830  parent.add(originGroup);
45831  const colorMatrices = Array.from({ length: COLOR_PALETTE_CAPACITY }, () => new Vector3());
45832  let colorCount = 0;
45833  const colorPalette = uniformArray2(colorMatrices);
45834  const symmetryGroups = /* @__PURE__ */ new Map();
45835  let activeGroupId = null;
45836  let discardInactiveShaders = false;
45837  let pickingRendererPromise = null;
45838  async function getPickingRenderer() {
45839    if (!pickingRendererPromise) {
45840      pickingRendererPromise = (async () => {
45841        const canvas = document.createElement("canvas");
45842        const renderer = new WebGPURenderer({
45843          canvas,
45844          antialias: false,
45845          alpha: true,
45846          forceWebGL: true
45847        });
45848        await renderer.init();
45849        return renderer;
45850      })();
45851    }
45852    return pickingRendererPromise;
45853  }
45854  function registerSymmetryGroup(groupId, orientations) {
45855    if (symmetryGroups.has(groupId)) {
45856      throw new Error(`Symmetry group '${groupId}' already exists.`);
45857    }
45858    if (!Array.isArray(orientations) || orientations.length === 0) {
45859      throw new Error("A symmetry group needs at least one orientation.");
45860    }
45861    const orientationMatrices = orientations.map((item) => {
45862      if (item instanceof Matrix4) {
45863        return item.clone();
45864      }
45865      if (item instanceof Euler) {
45866        return new Matrix4().makeRotationFromEuler(item);
45867      }
45868      throw new Error("Orientation must be a Euler or Matrix4.");
45869    });
45870    const group = {
45871      id: groupId,
45872      orientations: orientationMatrices,
45873      styles: /* @__PURE__ */ new Map(),
45874      slots: /* @__PURE__ */ new Set(),
45875      activeStyleId: null,
45876      instancesByShape: /* @__PURE__ */ new Map(),
45877      nextInstanceId: 1,
45878      gpu: null
45879    };
45880    symmetryGroups.set(groupId, group);
45881    return group;
45882  }
45883  function registerStyle(groupId, styleId) {
45884    const group = getSymmetryGroup(groupId);
45885    if (group.styles.has(styleId)) {
45886      throw new Error(`Style '${styleId}' is already registered in group '${groupId}'.`);
45887    }
45888    group.styles.set(styleId, { id: styleId, geometries: /* @__PURE__ */ new Map() });
45889    if (group.activeStyleId === null) {
45890      group.activeStyleId = styleId;
45891    }
45892  }
45893  function registerShape(groupId, styleId, slotId, geometry) {
45894    if (!(geometry instanceof BufferGeometry)) {
45895      throw new Error("Shape geometry must be a BufferGeometry.");
45896    }
45897    const group = getSymmetryGroup(groupId);
45898    const style2 = getStyle(group, styleId);
45899    if (style2.geometries.has(slotId)) {
45900      throw new Error(`Geometry for slot '${slotId}' is already registered in style '${styleId}'.`);
45901    }
45902    style2.geometries.set(slotId, geometry);
45903    group.slots.add(slotId);
45904    if (group.gpu) {
45905      let slotCache = group.gpu.cachedGeometries.get(slotId);
45906      if (!slotCache) {
45907        slotCache = /* @__PURE__ */ new Map();
45908        group.gpu.cachedGeometries.set(slotId, slotCache);
45909      }
45910      slotCache.set(styleId, geometry.clone());
45911      if (!group.gpu.shapeEntries.has(slotId)) {
45912        const activeGeom = (group.activeStyleId && slotCache.get(group.activeStyleId)) ?? slotCache.values().next().value;
45913        const outlineGeom = group.gpu.outlineGeometries.get(slotId) ?? null;
45914        const entry = createShapeEntry(slotId, activeGeom, outlineGeom, group.gpu.material, group.gpu.pickingMaterial, group.gpu.outlineMaterial);
45915        group.gpu.shapeEntries.set(slotId, entry);
45916        if (group.id === activeGroupId) {
45917          originGroup.add(entry.mesh);
45918          group.gpu.pickingOriginGroup.add(entry.pickingMesh);
45919          if (entry.outlineMesh) {
45920            originGroup.add(entry.outlineMesh);
45921          }
45922        }
45923      }
45924    }
45925  }
45926  function registerOutline(groupId, slotId, outlineGeometry) {
45927    if (!(outlineGeometry instanceof BufferGeometry)) {
45928      throw new Error("Outline geometry must be a BufferGeometry.");
45929    }
45930    const group = getSymmetryGroup(groupId);
45931    if (group.gpu && group.gpu.outlineGeometries.has(slotId)) {
45932      throw new Error(`Outline geometry for slot '${slotId}' is already registered in group '${groupId}'.`);
45933    }
45934    if (group.gpu) {
45935      group.gpu.outlineGeometries.set(slotId, outlineGeometry.clone());
45936      const entry = group.gpu.shapeEntries.get(slotId);
45937      if (entry && !entry.outlineMesh) {
45938        attachOutlineMeshToEntry(group, entry, slotId);
45939      }
45940    } else {
45941      group.pendingOutlineGeometries = group.pendingOutlineGeometries ?? /* @__P
45941URE__ */ new Map();
45942      group.pendingOutlineGeometries.set(slotId, outlineGeometry.clone());
45943    }
45944  }
45945  function switchSymmetryGroup(groupId, options = {}) {
45946    const {
45947      discardUnusedShaders = discardInactiveShaders
45948    } = options;
45949    const nextGroup = getSymmetryGroup(groupId);
45950    if (activeGroupId === groupId) {
45951      return;
45952    }
45953    if (activeGroupId !== null) {
45954      const previous = symmetryGroups.get(activeGroupId);
45955      setGroupMeshesCount(previous, 0);
45956    }
45957    ensureGroupGpu(nextGroup);
45958    ensureGroupHasActiveStyle(nextGroup);
45959    addGroupMeshesToScene(nextGroup);
45960    activeGroupId = groupId;
45961    syncAllInstancesForGroup(nextGroup);
45962    if (discardUnusedShaders) {
45963      for (const group of symmetryGroups.values()) {
45964        if (group.id !== activeGroupId) {
45965          disposeGroupGpu(group);
45966        }
45967      }
45968    }
45969  }
45970  function setDiscardInactiveShaders(enabled) {
45971    discardInactiveShaders = Boolean(enabled);
45972  }
45973  function switchStyle(styleId) {
45974    const group = getActiveGroup();
45975    getStyle(group, styleId);
45976    if (group.activeStyleId === styleId) {
45977      return;
45978    }
45979    group.activeStyleId = styleId;
45980    if (group.gpu) {
45981      swapGeometriesForStyle(group, styleId);
45982    }
45983  }
45984  function swapGeometriesForStyle(group, styleId) {
45985    for (const [slotId, entry] of group.gpu.shapeEntries) {
45986      swapBaseGeometry(entry, slotId, styleId, group.gpu.cachedGeometries);
45987    }
45988  }
45989  function setOutlinesVisible(visible) {
45990    const group = getActiveGroup();
45991    if (!group.gpu) return;
45992    for (const entry of group.gpu.shapeEntries.values()) {
45993      if (entry.outlineMesh) {
45994        entry.outlineMesh.visible = visible;
45995      }
45996    }
45997  }
45998  function swapBaseGeometry(entry, slotId, newStyleId, cachedGeometries) {
45999    const slotCache = cachedGeometries.get(slotId);
46000    if (!slotCache) return;
46001    const newGeom = slotCache.get(newStyleId);
46002    if (!newGeom) return;
46003    const oldGeom = entry.mesh.geometry;
46004    if (oldGeom === newGeom) return;
46005    for (const name of ["orientationIndex", "instanceTranslation", "colorIndex", "highlightIntensity", "pickingId"]) {
46006      const attr = oldGeom.getAttribute(name);
46007      if (attr) {
46008        oldGeom.deleteAttribute(name);
46009        newGeom.setAttribute(name, attr);
46010      }
46011    }
46012    entry.mesh.geometry = newGeom;
46013    if (entry.pickingMesh) {
46014      entry.pickingMesh.geometry = newGeom;
46015    }
46016  }
46017  function registerColor(colorInput) {
46018    if (colorCount >= COLOR_PALETTE_CAPACITY) {
46019      throw new Error(`Color palette is full (capacity ${COLOR_PALETTE_CAPACITY}).`);
46020    }
46021    const color3 = normalizeColorInput(colorInput);
46022    colorMatrices[colorCount].copy(color3);
46023    return colorCount++;
46024  }
46025  function addInstance(styleId, shapeId, instanceOptions = {}) {
46026    const group = getActiveGroup();
46027    getStyle(group, styleId);
46028    ensureStyleIsActiveForInstances(group, styleId);
46029    const shapeMap = getOrCreateShapeInstanceMap(group, shapeId);
46030    const position = instanceOptions.position ?? new Vector3();
46031    const orientationIndex = normalizeOrientationIndex(group, instanceOptions.orientationIndex);
46032    const colorIndex = normalizeColorIndex(instanceOptions.colorIndex);
46033    const highlight = instanceOptions.highlight ?? 0;
46034    const id = group.nextInstanceId;
46035    group.nextInstanceId += 1;
46036    shapeMap.set(id, {
46037      position,
46038      orientationIndex,
46039      colorIndex,
46040      highlight
46041    });
46042    syncShapeInstances(group, shapeId);
46043    return id;
46044  }
46045  function removeInstance(styleId, shapeId, instanceId) {
46046    const group = getActiveGroup();
46047    const shapeMap = group.instancesByShape.get(shapeId);
46048    if (!shapeMap) {
46049      return false;
46050    }
46051    const removed = shapeMap.delete(instanceId);
46052    if (removed) {
46053      syncShapeInstances(group, shapeId);
46054    }
46055    return removed;
46056  }
46057  function removeAllInstances(styleId, shapeId) {
46058    const group = getActiveGroup();
46059    group.instancesByShape.delete(shapeId);
46060    syncShapeInstances(group, shapeId);
46061  }
46062  function replaceShapeInstances(styleId, shapeId, instances) {
46063    const group = getActiveGroup();
46064    getStyle(group, styleId);
46065    ensureStyleIsActiveForInstances(group, styleId);
46066    const shapeMap = /* @__PURE__ */ new Map();
46067    const assignedIds = new Array(instances.length);
46068    for (let i = 0; i < instances.length; i += 1) {
46069      const instanceOptions = instances[i];
46070      const id = group.nextInstanceId;
46071      group.nextInstanceId += 1;
46072      shapeMap.set(id, {
46073        position: instanceOptions.position ?? new Vector3(),
46074        orientationIndex: normalizeOrientationIndex(group, instanceOptions.orientationIndex),
46075        colorIndex: normalizeColorIndex(instanceOptions.colorIndex),
46076        highlight: instanceOptions.highlight ?? 0
46077      });
46078      assignedIds[i] = id;
46079    }
46080    group.instancesByShape.set(shapeId, shapeMap);
46081    syncShapeInstances(group, shapeId);
46082    return assignedIds;
46083  }
46084  function clearActiveInstances() {
46085    const group = getActiveGroup();
46086    clearGroupInstances(group);
46087    setGroupMeshesCount(group, 0);
46088  }
46089  function createMaterialForGroup(group) {
46090    const orientationUniform = uniformArray2(group.orientations);
46091    const orientationIndexNode = attribute2("orientationIndex", "float");
46092    const instanceTranslationNode = attribute2("instanceTranslation", "vec3");
46093    const colorIndexNode = attribute2("colorIndex", "float");
46094    const highlightIntensityNode = attribute2("highlightIntensity", "float");
46095    const rotatedPositionNode = Fn2(() => {
46096      const orientationMat = orientationUniform.element(orientationIndexNode.toInt());
46097      return orientationMat.mul(vec42(positionLocal2, 1)).xyz.add(instanceTranslationNode);
46098    })();
46099    const roundedColorIndexNode = floor2(colorIndexNode.add(float2(0.5)));
46100    const indexedColorNode = colorPalette.element(roundedColorIndexNode.toInt());
46101    const material = new MeshLambertNodeMaterial({
46102      flatShading: true
46103    });
46104    material.positionNode = rotatedPositionNode;
46105    material.colorNode = indexedColorNode;
46106    material.emissiveNode = vec42(1, 1, 1, 1).xyz.mul(highlightIntensityNode);
46107    const pickingIdNode = floor2(
46108      attribute2("pickingId", "float").add(float2(0.5))
46109    );
46110    const pickingColorNode = vec32(
46111      mod2(pickingIdNode, float2(256)).div(255),
46112      mod2(floor2(pickingIdNode.div(float2(256))), float2(256)).div(255),
46113      floor2(pickingIdNode.div(float2(65536))).div(255)
46114    );
46115    const pickingMaterial = new MeshBasicNodeMaterial({ toneMapped: false });
46116    pickingMaterial.positionNode = rotatedPositionNode;
46117    pickingMaterial.colorNode = pickingColorNode;
46118    const outlineMaterial = new MeshBasicNodeMaterial({ toneMapped: false });
46119    outlineMaterial.positionNode = rotatedPositionNode;
46120    outlineMaterial.colorNode = vec32(0, 0, 0);
46121    return { material, pickingMaterial, outlineMaterial };
46122  }
46123  function createShapeEntry(slotId, meshGeometry, outlineGeometry, material, pickingMaterial, outlineMaterial) {
46124    const mesh = new InstancedMesh(meshGeometry, material, INITIAL_SHAPE_CAPACITY);
46125    const orientBuffer = new Float32Array(INITIAL_SHAPE_CAPACITY);
46126    const translationBuffer = new Float32Array(INITIAL_SHAPE_CAPACITY * 3);
46127    const colorIndexBuffer = new Float32Array(INITIAL_SHAPE_CAPACITY);
46128    const highlightBuffer = new Float32Array(INITIAL_SHAPE_CAPACITY);
46129    const pickingIdBuffer = new Float32Array(INITIAL_SHAPE_CAPACITY);
46130    attachAttributes(mesh.geometry, orientBuffer, translationBuffer, colorIndexBuffer, highlightBuffer, pickingIdBuffer);
46131    initializeIdentityMatrices(mesh, INITIAL_SHAPE_CAPACITY);
46132    mesh.count = 0;
46133    mesh.frustumCulled = false;
46134    const pickingMesh = new InstancedMesh(meshGeometry, pickingMaterial, INITIAL_SHAPE_CAPACITY);
46135    initializeIdentityMatrices(pickingMesh, INITIAL_SHAPE_CAPACITY);
46136    pickingMesh.count = 0;
46137    pickingMesh.frustumCulled = false;
46138    const outlineMesh = outlineGeometry ? makeOutlineMesh(outlineGeometry, outlineMaterial, INITIAL_SHAPE_CAPACITY, orientBuffer, translationBuffer, highlightBuffer, pickingIdBuffer) : null;
46139    return {
46140      slotId,
46141      capacity: INITIAL_SHAPE_CAPACITY,
46142      mesh,
46143      pickingMesh,
46144      outlineMesh,
46145      orientBuffer,
46146      translationBuffer,
46147      colorIndexBuffer,
46148      highlightBuffer,
46149      pickingIdBuffer
46150    };
46151  }
46152  function makeOutlineMesh(outlineGeometry, outlineMaterial, capacity, orientBuffer, translationBuffer, highlightBuffer, pickingIdBuffer) {
46153    outlineGeometry.setAttribute("orientationIndex", new InstancedBufferAttribute(orientBuffer, 1));
46154    outlineGeometry.setAttribute("instanceTranslation", new InstancedBufferAttribute(translationBuffer, 3));
46155    outlineGeometry.setAttribute("highlightIntensity", new InstancedBufferAttribute(highlightBuffer, 1));
46156    outlineGeometry.setAttribute("pickingId", new InstancedBufferAttribute(pickingIdBuffer, 1));
46157    const outlineMesh = new InstancedMesh(outlineGeometry, outlineMaterial, capacity);
46158    outlineMesh.isLineSegments = true;
46159    initializeIdentityMatrices(outlineMesh, capacity);
46160    outlineMesh.count = 0;
46161    outlineMesh.frustumCulled = false;
46162    outlineMesh.visible = false;
46163    return outlineMesh;
46164  }
46165  function ensureGroupGpu(group) {
46166    if (group.gpu) {
46167      return;
46168    }
46169    const { material, pickingMaterial, outlineMaterial } = createMaterialForGroup(group);
46170    const cachedGeometries = /* @__PURE__ */ new Map();
46171    for (const slotId of group.slots) {
46172      const slotCache = /* @__PURE__ */ new Map();
46173      for (const [styleId, style2] of group.styles) {
46174        if (style2.geometries.has(slotId)) {
46175          slotCache.set(styleId, style2.geometries.get(slotId).clone());
46176        }
46177      }
46178      cachedGeometries.set(slotId, slotCache);
46179    }
46180    const outlineGeometries = group.pendingOutlineGeometries ?? /* @__PURE__ */ new Map();
46181    group.pendingOutlineGeometries = void 0;
46182    const shapeEntries = /* @__PURE__ */ new Map();
46183    for (const slotId of group.slots) {
46184      const slotCache = cachedGeometries.get(slotId);
46185      if (!slotCache) continue;
46186      const geom = (group.activeStyleId && slotCache.get(group.activeStyleId)) ?? slotCache.values().next().value;
46187      if (geom) {
46188        const outlineGeom = outlineGeometries.get(slotId) ?? null;
46189        shapeEntries.set(slotId, createShapeEntry(slotId, geom, outlineGeom, material, pickingMaterial, outlineMaterial));
46190      }
46191    }
46192    const pickingScene = new Scene();
46193    const pickingOriginGroup = new Group();
46194    pickingOriginGroup.matrixAutoUpdate = false;
46195    pickingScene.add(pickingOriginGroup);
46196    const pickingTarget = new RenderTarget(1, 1, {
46197      type: UnsignedByteType,
46198      format: RGBAFormat
46199    });
46200    group.gpu = { material, pickingMaterial, outlineMaterial, shapeEntries, cachedGeometries, outlineGeometries, pickingScene, pickingOriginGroup, pickingTarget };
46201  }
46202  function attachOutlineMeshToEntry(group, entry, slotId) {
46203    const outlineGeom = group.gpu.outlineGeometries.get(slotId);
46204    if (!outlineGeom) return;
46205    const outlineMesh = makeOutlineMesh(
46206      outlineGeom,
46207      group.gpu.outlineMaterial,
46208      entry.capacity,
46209      entry.orientBuffer,
46210      entry.translationBuffer,
46211      entry.highlightBuffer,
46212      entry.pickingIdBuffer
46213    );
46214    outlineMesh.count = entry.mesh.count;
46215    entry.outlineMesh = outlineMesh;
46216    if (entry.mesh.parent === originGroup) {
46217      originGroup.add(outlineMesh);
46218    }
46219  }
46220  function addGroupMeshesToScene(group) {
46221    if (!group.gpu) {
46222      return;
46223    }
46224    for (const entry of group.gpu.shapeEntries.values()) {
46225      if (entry.mesh.parent !== originGroup) {
46226        originGroup.add(entry.mesh);
46227      }
46228      if (entry.outlineMesh && entry.outlineMesh.parent !== originGroup) {
46229        originGroup.add(entry.outlineMesh);
46230      }
46231      if (entry.pickingMesh && entry.pickingMesh.parent !== group.gpu.pickingOriginGroup) {
46232        group.gpu.pickingOriginGroup.add(entry.pickingMesh);
46233      }
46234    }
46235  }
46236  function setGroupMeshesCount(group, count) {
46237    if (!group || !group.gpu) {
46238      return;
46239    }
46240    for (const entry of group.gpu.shapeEntries.values()) {
46241      entry.mesh.count = count;
46242      if (entry.pickingMesh) {
46243        entry.pickingMesh.count = count;
46244      }
46245      if (entry.outlineMesh) {
46246        entry.outlineMesh.count = count;
46247      }
46248    }
46249  }
46250  function clearGroupInstances(group) {
46251    if (!group) {
46252      return;
46253    }
46254    group.instancesByShape.clear();
46255  }
46256  function syncShapeInstances(group, slotId) {
46257    if (!group.gpu) {
46258      return;
46259    }
46260    const entry = group.gpu.shapeEntries.get(slotId);
46261    if (!entry) {
46262      throw new Error(`Shape slot '${slotId}' is not registered for active group '${group.id}'.`);
46263    }
46264    const shapeMap = group.instancesByShape.get(slotId);
46265    const instances = shapeMap ? Array.from(shapeMap.entries()) : [];
46266    ensureShapeCapacity(group, slotId, instances.length);
46267    const currentEntry = group.gpu.shapeEntries.get(slotId);
46268    currentEntry.mesh.count = instances.length;
46269    if (currentEntry.pickingMesh) {
46270      currentEntry.pickingMesh.count = instances.length;
46271    }
46272    if (currentEntry.outlineMesh) {
46273      currentEntry.outlineMesh.count = instances.length;
46274    }
46275    for (let i = 0; i < instances.length; i += 1) {
46276      const [instanceId, { position, orientationIndex, colorIndex, highlight = 0 }] = instances[i];
46277      currentEntry.orientBuffer[i] = orientationIndex;
46278      const base = i * 3;
46279      currentEntry.translationBuffer[base] = position.x;
46280      currentEntry.translationBuffer[base + 1] = position.y;
46281      currentEntry.translationBuffer[base + 2] = position.z;
46282      currentEntry.colorIndexBuffer[i] = colorIndex;
46283      currentEntry.highlightBuffer[i] = highlight;
46284      currentEntry.pickingIdBuffer[i] = instanceId;
46285    }
46286    const geom = currentEntry.mesh.geometry;
46287    geom.getAttribute("orientationIndex").needsUpdate = true;
46288    geom.getAttribute("instanceTranslation").needsUpdate = true;
46289    geom.getAttribute("colorIndex").needsUpdate = true;
46290    geom.getAttribute("highlightIntensity").needsUpdate = true;
46291    geom.getAttribute("pickingId").needsUpdate = true;
46292    if (currentEntry.outlineMesh) {
46293      const outlineGeom = currentEntry.outlineMesh.geometry;
46294      outlineGeom.getAttribute("orientationIndex").needsUpdate = true;
46295      outlineGeom.getAttribute("instanceTranslation").needsUpdate = true;
46296      outlineGeom.getAttribute("highlightIntensity").needsUpdate = true;
46297      outlineGeom.getAttribute("pickingId").needsUpdate = true;
46298    }
46299  }
46300  function ensureShapeCapacity(group, key, needed) {
46301    const entry = group.gpu.shapeEntries.get(key);
46302    if (needed <= entry.capacity) {
46303      return;
46304    }
46305    const expandedCapacity = Math.max(needed, entry.capacity * 2);
46306    const nextOrient = new Float32Array(expandedCapacity);
46307    const nextTranslation = new Float32Array(expandedCapacity * 3);
46308    const nextColor = new Float32Array(expandedCapacity);
46309    const nextHighlight = new Float32Array(expandedCapacity);
46310    const nextPickingId = new Float32Array(expandedCapacity);
46311    nextOrient.set(entry.orientBuffer);
46312    nextTranslation.set(entry.translationBuffer);
46313    nextColor.set(entry.colorIndexBuffer);
46314    nextHighlight.set(entry.highlightBuffer);
46315    nextPickingId.set(entry.pickingIdBuffer);
46316    const previousMesh = entry.mesh;
46317    const previousGeometry = previousMesh.geometry;
46318    const activeStyle = group.styles.get(group.activeStyleId);
46319    const sourceGeom = activeStyle ? activeStyle.geometries.get(entry.slotId) : null;
46320    const nextGeometry = sourceGeom ? sourceGeom.clone() : previousGeometry.clone();
46321    attachAttributes(nextGeometry, nextOrient, nextTranslation, nextColor, nextHighlight, nextPickingId);
46322    const slotCache = group.gpu.cachedGeometries.get(entry.slotId);
46323    if (slotCache && group.activeStyleId) {
46324      slotCache.set(group.activeStyleId, nextGeometry);
46325    }
46326    const nextMesh = new InstancedMesh(nextGeometry, group.gpu.material, expandedCapacity);
46327    initializeIdentityMatrices(nextMesh, expandedCapacity);
46328    nextMesh.count = previousMesh.count;
46329    nextMesh.frustumCulled = false;
46330    if (previousMesh.parent === originGroup) {
46331      originGroup.remove(previousMesh);
46332      originGroup.add(nextMesh);
46333    }
46334    const nextPickingMesh = new InstancedMesh(nextGeometry, group.gpu.pickingMaterial, expandedCapacity);
46335    initializeIdentityMatrices(nextPickingMesh, expandedCapacity);
46336    nextPickingMesh.count = previousMesh.count;
46337    nextPickingMesh.frustumCulled = false;
46338    const previousPickingMesh = entry.pickingMesh;
46339    if (previousPickingMesh && previousPickingMesh.parent === group.gpu.pickingOriginGroup) {
46340      group.gpu.pickingOriginGroup.remove(previousPickingMesh);
46341      group.gpu.pickingOriginGroup.add(nextPickingMesh);
46342    }
46343    let nextOutlineMesh = null;
46344    const previousOutlineMesh = entry.outlineMesh;
46345    if (previousOutlineMesh) {
46346      const sourceOutlineGeom = group.gpu.outlineGeometries.get(entry.slotId);
46347      const nextOutlineGeometry = sourceOutlineGeom ? sourceOutlineGeom.clone() : previousOutlineMesh.geometry.clone();
46348      nextOutlineMesh = makeOutlineMesh(
46349        nextOutlineGeometry,
46350        group.gpu.outlineMaterial,
46351        expandedCapacity,
46352        nextOrient,
46353        nextTranslation,
46354        nextHighlight,
46355        nextPickingId
46356      );
46357      nextOutlineMesh.count = previousOutlineMesh.count;
46358      nextOutlineMesh.visible = previousOutlineMesh.visible;
46359      if (previousOutlineMesh.parent === originGroup) {
46360        originGroup.remove(previousOutlineMesh);
46361        originGroup.add(nextOutlineMesh);
46362      }
46363      const previousOutlineGeometry = previousOutlineMesh.geometry;
46364      requestAnimationFrame(() => previousOutlineGeometry.dispose());
46365    }
46366    requestAnimationFrame(() => previousGeometry.dispose());
46367    group.gpu.shapeEntries.set(key, {
46368      ...entry,
46369      capacity: expandedCapacity,
46370      mesh: nextMesh,
46371      pickingMesh: nextPickingMesh,
46372      outlineMesh: nextOutlineMesh,
46373      orientBuffer: nextOrient,
46374      translationBuffer: nextTranslation,
46375      colorIndexBuffer: nextColor,
46376      highlightBuffer: nextHighlight,
46377      pickingIdBuffer: nextPickingId
46378    });
46379  }
46380  function attachAttributes(geometry, orientBuffer, translationBuffer, colorIndexBuffer, highlightBuffer, pickingIdBuffer) {
46381    geometry.setAttribute("orientationIndex", new InstancedBufferAttribute(orientBuffer, 1));
46382    geometry.setAttribute("instanceTranslation", new InstancedBufferAttribute(translationBuffer, 3));
46383    geometry.setAttribute("colorIndex", new InstancedBufferAttribute(colorIndexBuffer, 1));
46384    geometry.setAttribute("highlightIntensity", new InstancedBufferAttribute(highlightBuffer, 1));
46385    geometry.setAttribute("pickingId", new InstancedBufferAttribute(pickingIdBuffer, 1));
46386  }
46387  function initializeIdentityMatrices(mesh, capacity) {
46388    const identity = new Matrix4();
46389    for (let i = 0; i < capacity; i += 1) {
46390      mesh.setMatrixAt(i, identity);
46391    }
46392    mesh.instanceMatrix.needsUpdate = true;
46393  }
46394  function disposeGroupGpu(group) {
46395    if (!group.gpu) {
46396      return;
46397    }
46398    for (const entry of group.gpu.shapeEntries.values()) {
46399      if (entry.mesh.parent === originGroup) {
46400        originGroup.remove(entry.mesh);
46401      }
46402      if (entry.pickingMesh && entry.pickingMesh.parent === group.gpu.pickingOriginGroup) {
46403        group.gpu.pickingOriginGroup.remove(entry.pickingMesh);
46404      }
46405      if (entry.outlineMesh) {
46406        if (entry.outlineMesh.parent === originGroup) {
46407          originGroup.remove(entry.outlineMesh);
46408        }
46409        entry.outlineMesh.geometry.dispose();
46410      }
46411    }
46412    for (const slotCache of group.gpu.cachedGeometries.values()) {
46413      for (const geom of slotCache.values()) {
46414        geom.dispose();
46415      }
46416    }
46417    group.gpu.material.dispose();
46418    group.gpu.pickingMaterial.dispose();
46419    group.gpu.outlineMaterial.dispose();
46420    group.gpu.pickingTarget.dispose();
46421    group.gpu = null;
46422  }
46423  function syncAllInstancesForGroup(group) {
46424    for (const slotId of group.instancesByShape.keys()) {
46425      syncShapeInstances(group, slotId);
46426    }
46427  }
46428  function getSymmetryGroup(groupId) {
46429    const group = symmetryGroups.get(groupId);
46430    if (!group) {
46431      throw new Error(`Unknown symmetry group '${groupId}'.`);
46432    }
46433    return group;
46434  }
46435  function getStyle(group, styleId) {
46436    const style2 = group.styles.get(styleId);
46437    if (!style2) {
46438      throw new Error(`Unknown style '${styleId}' in group '${group.id}'.`);
46439    }
46440    return style2;
46441  }
46442  function getGroupIds() {
46443    return [...symmetryGroups.keys()];
46444  }
46445  function getActiveGroupId() {
46446    return activeGroupId;
46447  }
46448  function getActiveGroup() {
46449    if (activeGroupId === null) {
46450      throw new Error("No active symmetry group. Call switchSymmetryGroup() first.");
46451    }
46452    return getSymmetryGroup(activeGroupId);
46453  }
46454  function getOrCreateShapeInstanceMap(group, key) {
46455    let shapeMap = group.instancesByShape.get(key);
46456    if (!shapeMap) {
46457      shapeMap = /* @__PURE__ */ new Map();
46458      group.instancesByShape.set(key, shapeMap);
46459    }
46460    return shapeMap;
46461  }
46462  function normalizeOrientationIndex(group, orientationIndex) {
46463    if (orientationIndex === void 0 || orientationIndex === null) {
46464      return 0;
46465    }
46466    if (!Number.isInteger(orientationIndex)) {
46467      throw new Error("orientationIndex must be an integer.");
46468    }
46469    if (orientationIndex < 0 || orientationIndex >= group.orientations.length) {
46470      throw new Error(`orientationIndex out of range for group '${group.id}'.`);
46471    }
46472    return orientationIndex;
46473  }
46474  function normalizeColorIndex(colorIndex) {
46475    if (colorIndex === void 0 || colorIndex === null) {
46476      return 0;
46477    }
46478    if (!Number.isInteger(colorIndex)) {
46479      throw new Error("colorIndex must be an integer.");
46480    }
46481    if (colorIndex < 0 || colorIndex >= colorCount) {
46482      throw new Error("colorIndex out of range.");
46483    }
46484    return colorIndex;
46485  }
46486  function normalizeColorInput(colorInput) {
46487    if (colorInput instanceof Vector3) {
46488      return colorInput.clone();
46489    }
46490    if (colorInput instanceof Color) {
46491      return new Vector3(colorInput.r, colorInput.g, colorInput.b);
46492    }
46493    if (Array.isArray(colorInput) && colorInput.length === 3) {
46494      return new Vector3(colorInput[0], colorInput[1], colorInput[2]);
46495    }
46496    if (typeof colorInput === "object" && colorInput !== null && "r" in colorInput && "g" in colorInput && "b" in colorInput) {
46497      return new Vector3(colorInput.r, colorInput.g, colorInput.b);
46498    }
46499    if (typeof colorInput === "number" || typeof colorInput === "string") {
46500      const color3 = new Color(colorInput);
46501      return new Vector3(color3.r, color3.g, color3.b);
46502    }
46503    throw new Error("registerColor expects a Color, Vector3, [r,g,b], {r,g,b}
46503, number, or CSS color string.");
46504  }
46505  function ensureGroupHasActiveStyle(group) {
46506    if (group.activeStyleId !== null) {
46507      return;
46508    }
46509    const firstStyle = group.styles.keys().next();
46510    group.activeStyleId = firstStyle.done ? null : firstStyle.value;
46511  }
46512  function ensureStyleIsActiveForInstances(group, styleId) {
46513    if (group.activeStyleId === null) {
46514      group.activeStyleId = styleId;
46515      return;
46516    }
46517    if (group.activeStyleId === styleId) {
46518      return;
46519    }
46520    group.activeStyleId = styleId;
46521    if (group.gpu) {
46522      swapGeometriesForStyle(group, styleId);
46523    }
46524  }
46525  function setInstanceHighlight(shapeId, instanceId, intensity = 1) {
46526    const group = getActiveGroup();
46527    const shapeMap = group.instancesByShape.get(shapeId);
46528    if (!shapeMap || !shapeMap.has(instanceId)) {
46529      return false;
46530    }
46531    shapeMap.get(instanceId).highlight = intensity;
46532    syncShapeInstances(group, shapeId);
46533    return true;
46534  }
46535  function clearHighlights(shapeId) {
46536    const group = getActiveGroup();
46537    if (shapeId !== void 0) {
46538      const shapeMap = group.instancesByShape.get(shapeId);
46539      if (shapeMap) {
46540        for (const inst of shapeMap.values()) {
46541          inst.highlight = 0;
46542        }
46543        syncShapeInstances(group, shapeId);
46544      }
46545    } else {
46546      for (const [sid, shapeMap] of group.instancesByShape) {
46547        for (const inst of shapeMap.values()) {
46548          inst.highlight = 0;
46549        }
46550        syncShapeInstances(group, sid);
46551      }
46552    }
46553  }
46554  function listShapeKeys(group, styleId) {
46555    const keys5 = [];
46556    for (const slotId of group.slots) {
46557      keys5.push({ styleId, shapeId: slotId });
46558    }
46559    return keys5;
46560  }
46561  const PICK_SIZE = 3;
46562  const pickProjectionMatrix = new Matrix4();
46563  async function pickAt(clientX, clientY, mainRenderer, camera) {
46564    if (activeGroupId === null) return null;
46565    const group = symmetryGroups.get(activeGroupId);
46566    if (!group || !group.gpu) return null;
46567    const { pickingScene, pickingOriginGroup: pickGroup, pickingTarget } = group.gpu;
46568    originGroup.updateMatrixWorld(true);
46569    pickGroup.matrix.copy(originGroup.matrixWorld);
46570    pickGroup.updateMatrixWorld(true);
46571    const pickingRenderer = await getPickingRenderer();
46572    const canvas = mainRenderer.domElement;
46573    const w = canvas.width;
46574    const h = canvas.height;
46575    if (pickingRenderer.domElement.width !== PICK_SIZE || pickingRenderer.domElement.height !== PICK_SIZE) {
46576      pickingRenderer.setSize(PICK_SIZE, PICK_SIZE, false);
46577    }
46578    if (pickingTarget.width !== PICK_SIZE || pickingTarget.height !== PICK_SIZE) {
46579      pickingTarget.setSize(PICK_SIZE, PICK_SIZE);
46580    }
46581    const rect = canvas.getBoundingClientRect();
46582    const scaleX = w / rect.width;
46583    const scaleY = h / rect.height;
46584    const pixelX = Math.floor((clientX - rect.left) * scaleX);
46585    const pixelY = Math.floor((clientY - rect.top) * scaleY);
46586    const ndcCenterX = (pixelX + 0.5) / w * 2 - 1;
46587    const ndcCenterY = 1 - (pixelY + 0.5) / h * 2;
46588    const scaleNdcX = w / PICK_SIZE;
46589    const scaleNdcY = h / PICK_SIZE;
46590    pickProjectionMatrix.set(
46591      scaleNdcX,
46592      0,
46593      0,
46594      -ndcCenterX * scaleNdcX,
46595      0,
46596      scaleNdcY,
46597      0,
46598      -ndcCenterY * scaleNdcY,
46599      0,
46600      0,
46601      1,
46602      0,
46603      0,
46604      0,
46605      0,
46606      1
46607    );
46608    pickProjectionMatrix.multiply(camera.projectionMatrix);
46609    const savedProjectionMatrix = camera.projectionMatrix;
46610    camera.projectionMatrix = pickProjectionMatrix;
46611    pickingRenderer.setRenderTarget(pickingTarget);
46612    pickingRenderer.setClearColor(0, 0);
46613    pickingRenderer.clear(true, true, true);
46614    pickingRenderer.render(pickingScene, camera);
46615    pickingRenderer.setRenderTarget(null);
46616    camera.projectionMatrix = savedProjectionMatrix;
46617    const buffer3 = await pickingRenderer.readRenderTargetPixelsAsync(pickingTarget, 0, 0, PICK_SIZE, PICK_SIZE);
46618    const centerIdx = (Math.floor(PICK_SIZE / 2) * PICK_SIZE + Math.floor(PICK_SIZE / 2)) * 4;
46619    const pixelBuffer = buffer3.subarray(centerIdx, centerIdx + 4);
46620    if (pixelBuffer[3] === 0) return null;
46621    const instanceId = pixelBuffer[0] + pixelBuffer[1] * 256 + pixelBuffer[2] * 65536;
46622    if (instanceId === 0) return null;
46623    for (const [shapeId, shapeMap] of group.instancesByShape) {
46624      if (shapeMap.has(instanceId)) {
46625        return { shapeId, instanceId };
46626      }
46627    }
46628    return null;
46629  }
46630  function setOrigin(vec33) {
46631    originGroup.position.copy(vec33);
46632  }
46633  return {
46634    registerSymmetryGroup,
46635    registerStyle,
46636    registerShape,
46637    registerOutline,
46638    registerColor,
46639    switchSymmetryGroup,
46640    switchStyle,
46641    setOutlinesVisible,
46642    setDiscardInactiveShaders,
46643    addInstance,
46644    removeInstance,
46645    removeAllInstances,
46646    replaceShapeInstances,
46647    clearActiveInstances,
46648    setInstanceHighlight,
46649    clearHighlights,
46650    getGroupIds,
46651    getActiveGroupId,
46652    getActiveGroup,
46653    listShapeKeys,
46654    pickAt,
46655    setOrigin,
46656    originGroup
46657  };
46658}
46659
46660// src/viewer/symmetry-geometry.jsx
46661var STYLE_ID = "default";
46662var hashOrientations = (orientations) => `g${orientations.length}:` + orientations.map((flat) => flat.join(",")).join(";");
46663var groupKeyFor = (symmetryId, orientations) => symmetryId ? `id:${symmetryId}` : hashOrientations(orientations);
46664var SELECTED_HIGHLIGHT = 200 / 255;
46665var toMatrix4 = (flat) => new Matrix4().set(...flat);
46666var toVector3 = ([x, y, z]) => new Vector3(x, y, z);
46667var orientationIndexOf = (instance3) => instance3.orientation === null || !(instance3.orientation >= 0) ? 0 : instance3.orientation;
46668var SymmetryGeometry = (props) => {
46669  const {
46670    originGroupReady
46671  } = useWebXRClient();
46672  return createComponent(Show, {
46673    get when() {
46674      return originGroupReady();
46675    },
46676    children: (parent) => createComponent(SymmetryGeometryImpl, mergeProps(props, {
46677      get parent() {
46678        return parent();
46679      }
46680    }))
46681  });
46682};
46683var SymmetryGeometryImpl = (props) => {
46684  const {
46685    state: cameraState
46686  } = useCamera();
46687  const renderer = createSymmetryRenderer(props.parent);
46688  const [activeGroupKey, setActiveGroupKey] = createSignal(null);
46689  const registeredGroupKeys = /* @__PURE__ */ new Set();
46690  const registeredShapeIdsByGroup = /* @__PURE__ */ new Map();
46691  const colorIndexByCss = /* @__PURE__ */ new Map();
46692  let instanceRefById = /* @__PURE__ */ new Map();
46693  let metadataByInstanceId = /* @__PURE__ */ new Map();
46694  let orientationMatrices = [];
46695  const shapeCentroidById = /* @__PURE__ */ new Map();
46696  let labelById = /* @__PURE__ */ new Map();
46697  const colorIndexFor = (cssColor) => {
46698    let index = colorIndexByCss.get(cssColor);
46699    if (index === void 0) {
46700      index = renderer.registerColor(cssColor);
46701      colorIndexByCss.set(cssColor, index);
46702    }
46703    return index;
46704  };
46705  createEffect(() => {
46706    const m = new Matrix4();
46707    if (props.embedding) {
46708      m.set(...props.embedding);
46709      m.transpose();
46710    }
46711    renderer.originGroup.matrix.copy(m);
46712    renderer.originGroup.matrixWorldNeedsUpdate = true;
46713  });
46714  createEffect(() => {
46715    if (!props.orientations || props.orientations.length === 0) return;
46716    const key = groupKeyFor(props.symmetryId, props.orientations);
46717    if (key === untrack(activeGroupKey)) return;
46718    orientationMatrices = props.orientations.map(toMatrix4);
46719    if (!registeredGroupKeys.has(key)) {
46720      renderer.registerSymmetryGroup(key, orientationMatrices);
46721      renderer.registerStyle(key, STYLE_ID);
46722      registeredGroupKeys.add(key);
46723    }
46724    renderer.switchSymmetryGroup(key);
46725    setActiveGroupKey(key);
46726  });
46727  createEffect(() => {
46728    const groupKey = activeGroupKey();
46729    if (!groupKey) return;
46730    const shapes = props.shapes || {};
46731    let registeredShapeIds = registeredShapeIdsByGroup.get(groupKey);
46732    if (!registeredShapeIds) {
46733      registeredShapeIds = /* @__PURE__ */ new Set();
46734      registeredShapeIdsByGroup.set(groupKey, registeredShapeIds);
46735    }
46736    for (const [shapeId, shape] of Object.entries(shapes)) {
46737      if (!registeredShapeIds.has(shapeId)) {
46738        const geometry = buildShapeGeometry(shape, true);
46739        renderer.registerShape(groupKey, STYLE_ID, shapeId, geometry);
46740        renderer.registerOutline(groupKey, shapeId, buildOutlineGeometry(shape));
46741        shapeCentroidById.set(shapeId, geometry.shapeCentroid);
46742        registeredShapeIds.add(shapeId);
46743      }
46744    }
46745    const nextInstanceRefById = /* @__PURE__ */ new Map();
46746    const nextMetadataByInstanceId = /* @__PURE__ */ new Map();
46747    const nextLabelById = /* @__PURE__ */ new Map();
46748    for (const [shapeId, shape] of Object.entries(shapes)) {
46749      const centroid2 = shapeCentroidById.get(shapeId);
46750      const instanceOptionsList = shape.instances.map((instance3) => {
46751        const selected = untrack(() => !!instance3.selected);
46752        return {
46753          position: toVector3(instance3.position),
46754          // Both spellings of "no orientation" must become identity here; see
46755          // orientationIndexOf above for why a bare `< 0` test is not enough.
46756          orientationIndex: orientationIndexOf(instance3),
46757          colorIndex: colorIndexFor(instance3.color),
46758          // Set the initial highlight directly (rather than relying on a later toggle to catch
46759          // up) so an already-selected instance never flashes unhighlighted for a frame right
46760          // after a structural rebuild. The store's `selected` is the source of truth here.
46761          highlight: selected ? SELECTED_HIGHLIGHT : 0
46762        };
46763      });
46764      const instanceIds = renderer.replaceShapeInstances(STYLE_ID, shapeId, instanceOptionsList);
46765      shape.instances.forEach((instance3, i) => {
46766        const selected = untrack(() => !!instance3.selected);
46767        const instanceId = instanceIds[i];
46768        nextInstanceRefById.set(instance3.id, {
46769          shapeId,
46770          instanceId
46771        });
46772        nextMetadataByInstanceId.set(instanceId, {
46773          id: instance3.id,
46774          position: instance3.position,
46775          type: instance3.type,
46776          selected,
46777          label: instance3.label
46778        });
46779        if (instance3.label) {
46780          const orientationIndex = orientationIndexOf(instance3);
46781          const worldPos = new Vector3(centroid2.x, centroid2.y, centroid2.z).applyMatrix4(orientationMatrices[orientationIndex]).add(toVector3(instance3.position));
46782          let label3 = labelById.get(instance3.id);
46783          if (!label3) {
46784            const elem = document.createElement("div");
46785            elem.className = "vzome-label";
46786            elem.id = `vzome-label-${instance3.label}`;
46787            elem.textContent = instance3.label;
46788            label3 = new CSS2DObject(elem);
46789            renderer.originGroup.add(label3);
46790          }
46791          label3.position.copy(worldPos);
46792          nextLabelById.set(instance3.id, label3);
46793          labelById.delete(instance3.id);
46794        }
46795      });
46796    }
46797    for (const shapeId of registeredShapeIds) {
46798      if (!(shapeId in shapes)) {
46799        renderer.removeAllInstances(STYLE_ID, shapeId);
46800      }
46801    }
46802    for (const staleLabel of labelById.values()) {
46803      renderer.originGroup.remove(staleLabel);
46804    }
46805    instanceRefById = nextInstanceRefById;
46806    labelById = nextLabelById;
46807    metadataByInstanceId = nextMetadataByInstanceId;
46808  });
46809  const {
46810    setSelectionHighlighter
46811  } = useScene();
46812  setSelectionHighlighter((shapeId, id, selected) => {
46813    const ref = instanceRefById.get(id);
46814    if (!ref) return;
46815    renderer.setInstanceHighlight(ref.shapeId, ref.instanceId, selected ? SELECTED_HIGHLIGHT : 0);
46816    const meta = metadataByInstanceId.get(ref.instanceId);
46817    if (meta) meta.selected = !!selected;
46818  });
46819  onCleanup(() => setSelectionHighlighter(null));
46820  createEffect(() => {
46821    if (!activeGroupKey()) return;
46822    renderer.setOutlinesVisible(!!props.polygons && !!cameraState.outlines);
46823  });
46824  const three = useThree();
46825  const [tool] = useInteractionTool();
46826  const pick = (clientX, clientY) => renderer.pickAt(clientX, clientY, three.gl, three.camera);
46827  let draggingHit = null;
46828  let pendingGesture = null;
46829  const isLeftButton = (e) => e.button === 0;
46830  const pickingSuppressed = () => tool?.allowTrackball?.();
46831  const onPointerDown = (e) => {
46832    if (!isLeftButton(e)) return;
46833    if (pickingSuppressed()) return;
46834    pendingGesture = (async () => {
46835      const hit = await pick(e.clientX, e.clientY);
46836      const meta = hit && metadataByInstanceId.get(hit.instanceId);
46837      if (!meta) return null;
46838      draggingHit = meta;
46839      tool?.onDragStart?.(e, meta.id, meta.position, meta.type, meta.selected);
46840      return meta;
46841    })();
46842  };
46843  const onPointerMove = (e) => {
46844    if (!draggingHit) return;
46845    tool?.onDrag?.(e, draggingHit.id, draggingHit.position, draggingHit.type, draggingHit.selected);
46846  };
46847  const onPointerUp = async (e) => {
46848    if (!isLeftButton(e)) return;
46849    if (pickingSuppressed()) return;
46850    if (pendingGesture) await pendingGesture;
46851    pendingGesture = null;
46852    if (draggingHit) {
46853      const {
46854        id,
46855        position,
46856        type,
46857        selected,
46858        label: label3
46859      } = draggingHit;
46860      draggingHit = null;
46861      tool?.onDragEnd?.(e, id, position, type, selected, label3);
46862    } else {
46863      tool?.bkgdClick?.();
46864    }
46865  };
46866  const onContextMenu = async (e) => {
46867    if (pickingSuppressed()) return;
46868    const hit = await pick(e.clientX, e.clientY);
46869    if (!hit) return;
46870    const meta = metadataByInstanceId.get(hit.instanceId);
46871    if (!meta) return;
46872    e.preventDefault();
46873    tool?.onContextMenu?.(meta.id, meta.position, meta.type, meta.selected, meta.label);
46874  };
46875  const canvasEl = three.canvas;
46876  canvasEl.addEventListener("pointerdown", onPointerDown);
46877  canvasEl.addEventListener("pointermove", onPointerMove);
46878  canvasEl.addEventListener("pointerup", onPointerUp);
46879  canvasEl.addEventListener("contextmenu", onContextMenu);
46880  onCleanup(() => {
46881    canvasEl.removeEventListener("pointerdown", onPointerDown);
46882    canvasEl.removeEventListener("pointermove", onPointerMove);
46883    canvasEl.removeEventListener("pointerup", onPointerUp);
46884    canvasEl.removeEventListener("contextmenu", onContextMenu);
46885  });
46886  return createComponent(CanvasExportBindings, {});
46887};
46888
46889// src/viewer/renderer-support.js
46890var STORAGE_KEY = "vzome.forceWebGLFallback";
46891var URL_PARAM = "forceWebGL";
46892var readStorage = () => {
46893  try {
46894    return globalThis.localStorage?.getItem(STORAGE_KEY) === "true";
46895  } catch {
46896    return false;
46897  }
46898};
46899var writeStorage = () => {
46900  try {
46901    globalThis.localStorage?.setItem(STORAGE_KEY, "true");
46902  } catch {
46903  }
46904};
46905var readUrlParam = () => {
46906  try {
46907    const value = new URLSearchParams(globalThis.location?.search).get(URL_PARAM);
46908    return value === "" || value === "1" || value === "true";
46909  } catch {
46910    return false;
46911  }
46912};
46913var isFallbackForced = () => {
46914  if (readUrlParam()) {
46915    writeStorage();
46916    return true;
46917  }
46918  return readStorage();
46919};
46920var probePromise = null;
46921var canUseWebGPURenderer = () => {
46922  if (probePromise)
46923    return probePromise;
46924  probePromise = (async () => {
46925    if (isFallbackForced()) {
46926      console.info("[vZome] WebGL fallback forced (localStorage/URL); using classic WebGLRenderer.");
46927      return false;
46928    }
46929    let renderer;
46930    try {
46931      const canvas = document.createElement("canvas");
46932      renderer = new WebGPURenderer({ canvas, antialias: true, alpha: true, forceWebGL: true });
46933      await renderer.init();
46934      return true;
46935    } catch (e) {
46936      console.warn("[vZome] WebGPURenderer init failed; using classic WebGLRenderer fallback.", e);
46937      return false;
46938    } finally {
46939      try {
46940        renderer?.dispose?.();
46941      } catch {
46942      }
46943    }
46944  })();
46945  return probePromise;
46946};
46947
46948// src/viewer/scenecanvas.jsx
46949var SceneCanvas = (props) => {
46950  props = mergeProps({
46951    rotateSpeed: 4.5,
46952    zoomSpeed: 3,
46953    panSpeed: 1
46954  }, props);
46955  const {
46956    scene
46957  } = useScene();
46958  const [webgpuOk] = createResource(canUseWebGPURenderer);
46959  const useWebGL = () => webgpuOk() === false;
46960  const useSymmetry = () => props.symmetryRenderer && !useWebGL();
46961  return createComponent(Show, {
46962    get when() {
46963      return webgpuOk() !== void 0;
46964    },
46965    get children() {
46966      return createComponent(LightedTrackballCanvas, {
46967        get height() {
46968          return props.height;
46969        },
46970        get width() {
46971          return props.width;
46972        },
46973        get rotationOnly() {
46974          return props.rotationOnly;
46975        },
46976        get rotateSpeed() {
46977          return props.rotateSpeed;
46978        },
46979        get zoomSpeed() {
46980          return props.zoomSpeed;
46981        },
46982        get panSpeed() {
46983          return props.panSpeed;
46984        },
46985        get useWebGL() {
46986          return useWebGL();
46987        },
46988        get symmetryRenderer() {
46989          return useSymmetry();
46990        },
46991        get children() {
46992          return [createComponent(Show, {
46993            when: () => props.scene?.shapes,
46994            get children() {
46995              return memo(() => !!useSymmetry())() ? createComponent(SymmetryGeometry, {
46996                get embedding() {
46997                  return scene?.embedding;
46998                },
46999                get shapes() {
47000                  return scene?.shapes;
47001                },
47002                get orientations() {
47003                  return scene?.orientations;
47004                },
47005                get polygons() {
47006                  return scene?.polygons;
47007                },
47008                get symmetryId() {
47009                  return scene?.symmetryId;
47010                }
47011              }) : createComponent(ShapedGeometry, {
47012                get embedding() {
47013                  return scene?.embedding;
47014                },
47015                get shapes() {
47016                  return scene?.shapes;
47017                }
47018              });
47019            }
47020          }), memo(() => props.children)];
47021        }
47022      });
47023    }
47024  });
47025};
47026
vendor: 489 bytes, lines 47027-47039
47027// node_modules/@solid-primitives/utils/dist/chunk/R5675YMU.js
47028var isClient3 = !isServer;
47029var isDev3 = isClient3 && !!DEV;
47030function chain3(callbacks) {
47031  return (...args) => {
47032    for (const callback of callbacks)
47033      callback && callback(...args);
47034  };
47035}
47036var access3 = (v) => typeof v === "function" && !v.length ? v() : v;
47037var asArray3 = (value) => Array.isArray(value) ? value : value ? [value] : [];
47038var tryOnCleanup3 = isDev3 ? (fn) => getOwner() ? onCleanup(fn) : fn : onCleanup;
47039
vendor: 691 bytes, lines 47040-47059
47040// node_modules/@solid-primitives/event-listener/dist/index.js
47041function makeEventListener(target, type, handler, options) {
47042  target.addEventListener(type, handler, options);
47043  return tryOnCleanup3(target.removeEventListener.bind(target, type, handler, options));
47044}
47045function createEventListener(targets, type, handler, options) {
47046  if (isServer)
47047    return;
47048  const attachListeners = () => {
47049    asArray3(access3(targets)).forEach((el) => {
47050      if (el)
47051        asArray3(access3(type)).forEach((type2) => makeEventListener(el, type2, handler, options));
47052    });
47053  };
47054  if (typeof targets === "function")
47055    createEffect(attachListeners);
47056  else
47057    createRenderEffect(attachListeners);
47058}
47059
vendor: 2,713 bytes, lines 47060-47157
47060// node_modules/@solid-primitives/keyed/dist/index.js
47061var FALLBACK = Symbol("fallback");
47062function dispose(list) {
47063  for (const o of list)
47064    o.dispose();
47065}
47066function keyArray(items, keyFn, mapFn, options = {}) {
47067  if (isServer) {
47068    const itemsRef = items();
47069    let s = [];
47070    if (itemsRef && itemsRef.length) {
47071      for (let i = 0, len = itemsRef.length; i < len; i++)
47072        s.push(
47073          mapFn(
47074            () => itemsRef[i],
47075            () => i
47076          )
47077        );
47078    } else if (options.fallback)
47079      s = [options.fallback()];
47080    return () => s;
47081  }
47082  const prev = /* @__PURE__ */ new Map();
47083  onCleanup(() => dispose(prev.values()));
47084  return () => {
47085    const list = items() || [];
47086    list[$TRACK];
47087    return untrack(() => {
47088      if (!list.length) {
47089        dispose(prev.values());
47090        prev.clear();
47091        if (!options.fallback)
47092          return [];
47093        const fb2 = createRoot((dispose2) => {
47094          prev.set(FALLBACK, { dispose: dispose2 });
47095          return options.fallback();
47096        });
47097        return [fb2];
47098      }
47099      const result = new Array(list.length);
47100      const fb = prev.get(FALLBACK);
47101      if (!prev.size || fb) {
47102        fb?.dispose();
47103        prev.delete(FALLBACK);
47104        for (let i = 0; i < list.length; i++) {
47105          const item = list[i];
47106          const key = keyFn(item, i);
47107          addNewItem(result, item, i, key);
47108        }
47109        return result;
47110      }
47111      const prevKeys = new Set(prev.keys());
47112      for (let i = 0; i < list.length; i++) {
47113        const item = list[i];
47114        const key = keyFn(item, i);
47115        prevKeys.delete(key);
47116        const lookup = prev.get(key);
47117        if (lookup) {
47118          result[i] = lookup.mapped;
47119          lookup.setIndex?.(i);
47120          lookup.setItem(() => item);
47121        } else
47122          addNewItem(result, item, i, key);
47123      }
47124      for (const key of prevKeys) {
47125        prev.get(key)?.dispose();
47126        prev.delete(key);
47127      }
47128      return result;
47129    });
47130  };
47131  function addNewItem(list, item, i, key) {
47132    createRoot((dispose2) => {
47133      const [getItem, setItem] = createSignal(item);
47134      const save = { setItem, dispose: dispose2 };
47135      if (mapFn.length > 1) {
47136        const [index, setIndex] = createSignal(i);
47137        save.setIndex = setIndex;
47138        save.mapped = mapFn(getItem, index);
47139      } else
47140        save.mapped = mapFn(getItem);
47141      prev.set(key, save);
47142      list[i] = save.mapped;
47143    });
47144  }
47145}
47146function Key(props) {
47147  const { by } = props;
47148  return createMemo(
47149    keyArray(
47150      () => props.each,
47151      typeof by === "function" ? by : (v) => v[by],
47152      props.children,
47153      "fallback" in props ? { fallback: () => props.fallback } : void 0
47154    )
47155  );
47156}
47157
vendor: 544 bytes, lines 47158-47178
47158// node_modules/@solid-primitives/props/dist/index.js
47159var extractCSSregex = /((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g;
47160function stringStyleToObject(style2) {
47161  const object = {};
47162  let match;
47163  while (match = extractCSSregex.exec(style2)) {
47164    object[match[1]] = match[2];
47165  }
47166  return object;
47167}
47168function combineStyle(a, b) {
47169  if (typeof a === "string") {
47170    if (typeof b === "string")
47171      return `${a};${b}`;
47172    a = stringStyleToObject(a);
47173  } else if (typeof b === "string") {
47174    b = stringStyleToObject(b);
47175  }
47176  return { ...a, ...b };
47177}
47178
vendor: 109 bytes, lines 47179-47183
47179// node_modules/@solid-primitives/refs/dist/index.js
47180function mergeRefs(...refs) {
47181  return chain3(refs);
47182}
47183
vendor: 281 bytes, lines 47184-47189
47184// node_modules/@kobalte/utils/node_modules/@solid-primitives/utils/dist/chunk/R5675YMU.js
47185var access4 = (v) => typeof v === "function" && !v.length ? v() : v;
47186function accessWith4(valueOrFn, ...args) {
47187  return typeof valueOrFn === "function" ? valueOrFn(...args) : valueOrFn;
47188}
47189
vendor: 15,888 bytes, lines 47190-47705
47190// node_modules/@kobalte/utils/dist/index.js
47191function addItemToArray(array3, item, index = -1) {
47192  if (!(index in array3)) {
47193    return [...array3, item];
47194  }
47195  return [...array3.slice(0, index), item, ...array3.slice(index)];
47196}
47197function removeItemFromArray(array3, item) {
47198  const updatedArray = [...array3];
47199  const index = updatedArray.indexOf(item);
47200  if (index !== -1) {
47201    updatedArray.splice(index, 1);
47202  }
47203  return updatedArray;
47204}
47205function isNumber(value) {
47206  return typeof value === "number";
47207}
47208function isString(value) {
47209  return Object.prototype.toString.call(value) === "[object String]";
47210}
47211function isFunction(value) {
47212  return typeof value === "function";
47213}
47214function createGenerateId(baseId) {
47215  return (suffix) => `${baseId()}-${suffix}`;
47216}
47217function contains(parent, child) {
47218  if (!parent) {
47219    return false;
47220  }
47221  return parent === child || parent.contains(child);
47222}
47223function getActiveElement(node, activeDescendant = false) {
47224  const { activeElement } = getDocument(node);
47225  if (!activeElement?.nodeName) {
47226    return null;
47227  }
47228  if (isFrame(activeElement) && activeElement.contentDocument) {
47229    return getActiveElement(
47230      activeElement.contentDocument.body,
47231      activeDescendant
47232    );
47233  }
47234  if (activeDescendant) {
47235    const id = activeElement.getAttribute("aria-activedescendant");
47236    if (id) {
47237      const element3 = getDocument(activeElement).getElementById(id);
47238      if (element3) {
47239        return element3;
47240      }
47241    }
47242  }
47243  return activeElement;
47244}
47245function getWindow(node) {
47246  return getDocument(node).defaultView || window;
47247}
47248function getDocument(node) {
47249  return node ? node.ownerDocument || node : document;
47250}
47251function isFrame(element3) {
47252  return element3.tagName === "IFRAME";
47253}
47254var EventKey = /* @__PURE__ */ ((EventKey2) => {
47255  EventKey2["Escape"] = "Escape";
47256  EventKey2["Enter"] = "Enter";
47257  EventKey2["Tab"] = "Tab";
47258  EventKey2["Space"] = " ";
47259  EventKey2["ArrowDown"] = "ArrowDown";
47260  EventKey2["ArrowLeft"] = "ArrowLeft";
47261  EventKey2["ArrowRight"] = "ArrowRight";
47262  EventKey2["ArrowUp"] = "ArrowUp";
47263  EventKey2["End"] = "End";
47264  EventKey2["Home"] = "Home";
47265  EventKey2["PageDown"] = "PageDown";
47266  EventKey2["PageUp"] = "PageUp";
47267  return EventKey2;
47268})(EventKey || {});
47269function testUserAgent(re) {
47270  if (typeof window === "undefined" || window.navigator == null) {
47271    return false;
47272  }
47273  return (
47274    // @ts-ignore
47275    window.navigator.userAgentData?.brands.some(
47276      (brand) => re.test(brand.brand)
47277    ) || re.test(window.navigator.userAgent)
47278  );
47279}
47280function testPlatform(re) {
47281  return typeof window !== "undefined" && window.navigator != null ? re.test(
47282    // @ts-ignore
47283    window.navigator.userAgentData?.platform || window.navigator.platform
47284  ) : false;
47285}
47286function isMac() {
47287  return testPlatform(/^Mac/i);
47288}
47289function isIPhone() {
47290  return testPlatform(/^iPhone/i);
47291}
47292function isIPad() {
47293  return testPlatform(/^iPad/i) || // iPadOS 13 lies and says it's a Mac, but we can distinguish by detecting touch support.
47294  isMac() && navigator.maxTouchPoints > 1;
47295}
47296function isIOS() {
47297  return isIPhone() || isIPad();
47298}
47299function isAppleDevice() {
47300  return isMac() || isIOS();
47301}
47302function isWebKit() {
47303  return testUserAgent(/AppleWebKit/i) && !isChrome();
47304}
47305function isChrome() {
47306  return testUserAgent(/Chrome/i);
47307}
47308function callHandler(event, handler) {
47309  if (handler) {
47310    if (isFunction(handler)) {
47311      handler(event);
47312    } else {
47313      handler[0](handler[1], event);
47314    }
47315  }
47316  return event?.defaultPrevented;
47317}
47318function composeEventHandlers(handlers) {
47319  return (event) => {
47320    for (const handler of handlers) {
47321      callHandler(event, handler);
47322    }
47323  };
47324}
47325function isCtrlKey(e) {
47326  if (isMac()) {
47327    return e.metaKey && !e.ctrlKey;
47328  }
47329  return e.ctrlKey && !e.metaKey;
47330}
47331function focusWithoutScrolling(element3) {
47332  if (!element3) {
47333    return;
47334  }
47335  if (supportsPreventScroll()) {
47336    element3.focus({ preventScroll: true });
47337  } else {
47338    const scrollableElements = getScrollableElements(element3);
47339    element3.focus();
47340    restoreScrollPosition(scrollableElements);
47341  }
47342}
47343var supportsPreventScrollCached = null;
47344function supportsPreventScroll() {
47345  if (supportsPreventScrollCached == null) {
47346    supportsPreventScrollCached = false;
47347    try {
47348      const focusElem = document.createElement("div");
47349      focusElem.focus({
47350        get preventScroll() {
47351          supportsPreventScrollCached = true;
47352          return true;
47353        }
47354      });
47355    } catch (e) {
47356    }
47357  }
47358  return supportsPreventScrollCached;
47359}
47360function getScrollableElements(element3) {
47361  let parent = element3.parentNode;
47362  const scrollableElements = [];
47363  const rootScrollingElement = document.scrollingElement || document.documentElement;
47364  while (parent instanceof HTMLElement && parent !== rootScrollingElement) {
47365    if (parent.offsetHeight < parent.scrollHeight || parent.offsetWidth < parent.scrollWidth) {
47366      scrollableElements.push({
47367        element: parent,
47368        scrollTop: parent.scrollTop,
47369        scrollLeft: parent.scrollLeft
47370      });
47371    }
47372    parent = parent.parentNode;
47373  }
47374  if (rootScrollingElement instanceof HTMLElement) {
47375    scrollableElements.push({
47376      element: rootScrollingElement,
47377      scrollTop: rootScrollingElement.scrollTop,
47378      scrollLeft: rootScrollingElement.scrollLeft
47379    });
47380  }
47381  return scrollableElements;
47382}
47383function restoreScrollPosition(scrollableElements) {
47384  for (const { element: element3, scrollTop, scrollLeft } of scrollableElements) {
47385    element3.scrollTop = scrollTop;
47386    element3.scrollLeft = scrollLeft;
47387  }
47388}
47389var focusableElements = [
47390  "input:not([type='hidden']):not([disabled])",
47391  "select:not([disabled])",
47392  "textarea:not([disabled])",
47393  "button:not([disabled])",
47394  "a[href]",
47395  "area[href]",
47396  "[tabindex]",
47397  "iframe",
47398  "object",
47399  "embed",
47400  "audio[controls]",
47401  "video[controls]",
47402  "[contenteditable]:not([contenteditable='false'])"
47403];
47404var tabbableElements = [
47405  ...focusableElements,
47406  '[tabindex]:not([tabindex="-1"]):not([disabled])'
47407];
47408var FOCUSABLE_ELEMENT_SELECTOR = `${focusableElements.join(
47409  ":not([hidden]),"
47410)},[tabindex]:not([disabled]):not([hidden])`;
47411var TABBABLE_ELEMENT_SELECTOR = tabbableElements.join(
47412  ':not([hidden]):not([tabindex="-1"]),'
47413);
47414function getAllTabbableIn(container, includeContainer) {
47415  const elements = Array.from(
47416    container.querySelectorAll(FOCUSABLE_ELEMENT_SELECTOR)
47417  );
47418  const tabbableElements2 = elements.filter(isTabbable);
47419  if (includeContainer && isTabbable(container)) {
47420    tabbableElements2.unshift(container);
47421  }
47422  tabbableElements2.forEach((element3, i) => {
47423    if (isFrame(element3) && element3.contentDocument) {
47424      const frameBody = element3.contentDocument.body;
47425      const allFrameTabbable = getAllTabbableIn(frameBody, false);
47426      tabbableElements2.splice(i, 1, ...allFrameTabbable);
47427    }
47428  });
47429  return tabbableElements2;
47430}
47431function isTabbable(element3) {
47432  return isFocusable(element3) && !hasNegativeTabIndex(element3);
47433}
47434function isFocusable(element3) {
47435  return element3.matches(FOCUSABLE_ELEMENT_SELECTOR) && isElementVisible(element3);
47436}
47437function hasNegativeTabIndex(element3) {
47438  const tabIndex = Number.parseInt(element3.getAttribute("tabindex") || "0", 10);
47439  return tabIndex < 0;
47440}
47441function isElementVisible(element3, childElement) {
47442  return element3.nodeName !== "#comment" && isStyleVisible(element3) && isAttributeVisible(element3, childElement) && (!element3.parentElement || isElementVisible(element3.parentElement, element3));
47443}
47444function isStyleVisible(element3) {
47445  if (!(element3 instanceof HTMLElement) && !(element3 instanceof SVGElement)) {
47446    return false;
47447  }
47448  const { display, visibility } = element3.style;
47449  let isVisible = display !== "none" && visibility !== "hidden" && visibility !== "collapse";
47450  if (isVisible) {
47451    if (!element3.ownerDocument.defaultView) {
47452      return isVisible;
47453    }
47454    const { getComputedStyle: getComputedStyle3 } = element3.ownerDocument.defaultView;
47455    const { display: computedDisplay, visibility: computedVisibility } = getComputedStyle3(element3);
47456    isVisible = computedDisplay !== "none" && computedVisibility !== "hidden" && computedVisibility !== "collapse";
47457  }
47458  return isVisible;
47459}
47460function isAttributeVisible(element3, childElement) {
47461  return !element3.hasAttribute("hidden") && (element3.nodeName === "DETAILS" && childElement && childElement.nodeName !== "SUMMARY" ? element3.hasAttribute("open") : true);
47462}
47463function isElementInScope(element3, scope) {
47464  return scope.some((node) => node.contains(element3));
47465}
47466function getFocusableTreeWalker(root, opts, scope) {
47467  const selector = opts?.tabbable ? TABBABLE_ELEMENT_SELECTOR : FOCUSABLE_ELEMENT_SELECTOR;
47468  const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
47469    acceptNode(node) {
47470      if (opts?.from?.contains(node)) {
47471        return NodeFilter.FILTER_REJECT;
47472      }
47473      if (node.matches(selector) && isElementVisible(node) && (!scope || isElementInScope(node, scope)) && (!opts?.accept || opts.accept(node))) {
47474        return NodeFilter.FILTER_ACCEPT;
47475      }
47476      return NodeFilter.FILTER_SKIP;
47477    }
47478  });
47479  if (opts?.from) {
47480    walker.currentNode = opts.from;
47481  }
47482  return walker;
47483}
47484function getScrollParent(node) {
47485  let parentNode = node;
47486  while (parentNode && !isScrollable(parentNode)) {
47487    parentNode = parentNode.parentElement;
47488  }
47489  return parentNode || document.scrollingElement || document.documentElement;
47490}
47491function isScrollable(node) {
47492  const style2 = window.getComputedStyle(node);
47493  return /(auto|scroll)/.test(
47494    style2.overflow + style2.overflowX + style2.overflowY
47495  );
47496}
47497function noop5() {
47498  return;
47499}
47500function clamp7(value, min5 = Number.NEGATIVE_INFINITY, max5 = Number.POSITIVE_INFINITY) {
47501  return Math.min(Math.max(value, min5), max5);
47502}
47503function snapValueToStep(value, min5, max5, step3) {
47504  const remainder = (value - (Number.isNaN(min5) ? 0 : min5)) % step3;
47505  let snappedValue = Math.abs(remainder) * 2 >= step3 ? value + Math.sign(remainder) * (step3 - Math.abs(remainder)) : value - remainder;
47506  if (!Number.isNaN(min5)) {
47507    if (snappedValue < min5) {
47508      snappedValue = min5;
47509    } else if (!Number.isNaN(max5) && snappedValue > max5) {
47510      snappedValue = min5 + Math.floor((max5 - min5) / step3) * step3;
47511    }
47512  } else if (!Number.isNaN(max5) && snappedValue > max5) {
47513    snappedValue = Math.floor(max5 / step3) * step3;
47514  }
47515  const string3 = step3.toString();
47516  const index = string3.indexOf(".");
47517  const precision = index >= 0 ? string3.length - index : 0;
47518  if (precision > 0) {
47519    const pow6 = 10 ** precision;
47520    snappedValue = Math.round(snappedValue * pow6) / pow6;
47521  }
47522  return snappedValue;
47523}
47524function getEventPoint(event) {
47525  return [event.clientX, event.clientY];
47526}
47527function isPointInPolygon(point, polygon) {
47528  const [x, y] = point;
47529  let inside = false;
47530  const length3 = polygon.length;
47531  for (let l = length3, i = 0, j = l - 1; i < l; j = i++) {
47532    const [xi, yi] = polygon[i];
47533    const [xj, yj] = polygon[j];
47534    const [, vy] = polygon[j === 0 ? l - 1 : j - 1] || [0, 0];
47535    const where = (yi - yj) * (x - xi) - (xi - xj) * (y - yi);
47536    if (yj < yi) {
47537      if (y >= yj && y < yi) {
47538        if (where === 0)
47539          return true;
47540        if (where > 0) {
47541          if (y === yj) {
47542            if (y > vy) {
47543              inside = !inside;
47544            }
47545          } else {
47546            inside = !inside;
47547          }
47548        }
47549      }
47550    } else if (yi < yj) {
47551      if (y > yi && y <= yj) {
47552        if (where === 0)
47553          return true;
47554        if (where < 0) {
47555          if (y === yj) {
47556            if (y < vy) {
47557              inside = !inside;
47558            }
47559          } else {
47560            inside = !inside;
47561          }
47562        }
47563      }
47564    } else if (y === yi && (x >= xj && x <= xi || x >= xi && x <= xj)) {
47565      return true;
47566    }
47567  }
47568  return inside;
47569}
47570function mergeDefaultProps(defaultProps, props) {
47571  return mergeProps(defaultProps, props);
47572}
47573var transitionsByElement = /* @__PURE__ */ new Map();
47574var transitionCallbacks = /* @__PURE__ */ new Set();
47575function setupGlobalEvents() {
47576  if (typeof window === "undefined" || document.body === null) {
47577    return;
47578  }
47579  const onTransitionStart = (e) => {
47580    if (!e.target) {
47581      return;
47582    }
47583    let transitions = transitionsByElement.get(e.target);
47584    if (!transitions) {
47585      transitions = /* @__PURE__ */ new Set();
47586      transitionsByElement.set(e.target, transitions);
47587      e.target.addEventListener(
47588        "transitioncancel",
47589        onTransitionEnd
47590      );
47591    }
47592    transitions.add(e.propertyName);
47593  };
47594  const onTransitionEnd = (e) => {
47595    if (!e.target) {
47596      return;
47597    }
47598    const properties = transitionsByElement.get(e.target);
47599    if (!properties) {
47600      return;
47601    }
47602    properties.delete(e.propertyName);
47603    if (properties.size === 0) {
47604      e.target.removeEventListener(
47605        "transitioncancel",
47606        onTransitionEnd
47607      );
47608      transitionsByElement.delete(e.target);
47609    }
47610    if (transitionsByElement.size === 0) {
47611      for (const cb of transitionCallbacks) {
47612        cb();
47613      }
47614      transitionCallbacks.clear();
47615    }
47616  };
47617  document.body.addEventListener("transitionrun", onTransitionStart);
47618  document.body.addEventListener("transitionend", onTransitionEnd);
47619}
47620if (typeof document !== "undefined") {
47621  if (document.readyState !== "loading") {
47622    setupGlobalEvents();
47623  } else {
47624    document.addEventListener("DOMContentLoaded", setupGlobalEvents);
47625  }
47626}
47627function scrollIntoView(scrollView, element3) {
47628  const offsetX = relativeOffset(scrollView, element3, "left");
47629  const offsetY = relativeOffset(scrollView, element3, "top");
47630  const width = element3.offsetWidth;
47631  const height = element3.offsetHeight;
47632  let x = scrollView.scrollLeft;
47633  let y = scrollView.scrollTop;
47634  const maxX = x + scrollView.offsetWidth;
47635  const maxY = y + scrollView.offsetHeight;
47636  if (offsetX <= x) {
47637    x = offsetX;
47638  } else if (offsetX + width > maxX) {
47639    x += offsetX + width - maxX;
47640  }
47641  if (offsetY <= y) {
47642    y = offsetY;
47643  } else if (offsetY + height > maxY) {
47644    y += offsetY + height - maxY;
47645  }
47646  scrollView.scrollLeft = x;
47647  scrollView.scrollTop = y;
47648}
47649function relativeOffset(ancestor, child, axis) {
47650  const prop = axis === "left" ? "offsetLeft" : "offsetTop";
47651  let sum = 0;
47652  while (child.offsetParent) {
47653    sum += child[prop];
47654    if (child.offsetParent === ancestor) {
47655      break;
47656    }
47657    if (child.offsetParent.contains(ancestor)) {
47658      sum -= ancestor[prop];
47659      break;
47660    }
47661    child = child.offsetParent;
47662  }
47663  return sum;
47664}
47665function scrollIntoViewport(targetElement, opts) {
47666  if (document.contains(targetElement)) {
47667    const root = document.scrollingElement || document.documentElement;
47668    const isScrollPrevented = window.getComputedStyle(root).overflow === "hidden";
47669    if (!isScrollPrevented) {
47670      const { left: originalLeft, top: originalTop } = targetElement.getBoundingClientRect();
47671      targetElement?.scrollIntoView?.({ block: "nearest" });
47672      const { left: newLeft, top: newTop } = targetElement.getBoundingClientRect();
47673      if (Math.abs(originalLeft - newLeft) > 1 || Math.abs(originalTop - newTop) > 1) {
47674        opts?.containingElement?.scrollIntoView?.({
47675          block: "center",
47676          inline: "center"
47677        });
47678        targetElement.scrollIntoView?.({ block: "nearest" });
47679      }
47680    } else {
47681      let scrollParent = getScrollParent(targetElement);
47682      while (targetElement && scrollParent && targetElement !== root && scrollParent !== root) {
47683        scrollIntoView(
47684          scrollParent,
47685          targetElement
47686        );
47687        targetElement = scrollParent;
47688        scrollParent = getScrollParent(targetElement);
47689      }
47690    }
47691  }
47692}
47693var visuallyHiddenStyles = {
47694  border: "0",
47695  clip: "rect(0 0 0 0)",
47696  "clip-path": "inset(50%)",
47697  height: "1px",
47698  margin: "0 -1px -1px 0",
47699  overflow: "hidden",
47700  padding: "0",
47701  position: "absolute",
47702  width: "1px",
47703  "white-space": "nowrap"
47704};
47705
vendor: 2,155 bytes, lines 47706-47782
47706// node_modules/@kobalte/core/dist/chunk/2YCOH52P.js
47707var DATA_TOP_LAYER_ATTR = "data-kb-top-layer";
47708var originalBodyPointerEvents;
47709var hasDisabledBodyPointerEvents = false;
47710var layers = [];
47711function indexOf(node) {
47712  return layers.findIndex((layer) => layer.node === node);
47713}
47714function find(node) {
47715  return layers[indexOf(node)];
47716}
47717function isTopMostLayer(node) {
47718  return layers.length > 0 && layers[layers.length - 1].node === node;
47719}
47720function getPointerBlockingLayers() {
47721  return layers.filter((layer) => layer.isPointerBlocking);
47722}
47723function getTopMostPointerBlockingLayer() {
47724  return [...getPointerBlockingLayers()].slice(-1)[0];
47725}
47726function hasPointerBlockingLayer() {
47727  return getPointerBlockingLayers().length > 0;
47728}
47729function isBelowPointerBlockingLayer(node) {
47730  const highestBlockingIndex = indexOf(getTopMostPointerBlockingLayer()?.node);
47731  return indexOf(node) < highestBlockingIndex;
47732}
47733function addLayer(layer) {
47734  layers.push(layer);
47735}
47736function removeLayer(node) {
47737  const index = indexOf(node);
47738  if (index < 0) {
47739    return;
47740  }
47741  layers.splice(index, 1);
47742}
47743function assignPointerEventToLayers() {
47744  for (const {
47745    node
47746  } of layers) {
47747    node.style.pointerEvents = isBelowPointerBlockingLayer(node) ? "none" : "auto";
47748  }
47749}
47750function disableBodyPointerEvents(node) {
47751  if (hasPointerBlockingLayer() && !hasDisabledBodyPointerEvents) {
47752    const ownerDocument = getDocument(node);
47753    originalBodyPointerEvents = document.body.style.pointerEvents;
47754    ownerDocument.body.style.pointerEvents = "none";
47755    hasDisabledBodyPointerEvents = true;
47756  }
47757}
47758function restoreBodyPointerEvents(node) {
47759  if (hasPointerBlockingLayer()) {
47760    return;
47761  }
47762  const ownerDocument = getDocument(node);
47763  ownerDocument.body.style.pointerEvents = originalBodyPointerEvents;
47764  if (ownerDocument.body.style.length === 0) {
47765    ownerDocument.body.removeAttribute("style");
47766  }
47767  hasDisabledBodyPointerEvents = false;
47768}
47769var layerStack = {
47770  layers,
47771  isTopMostLayer,
47772  hasPointerBlockingLayer,
47773  isBelowPointerBlockingLayer,
47774  addLayer,
47775  removeLayer,
47776  indexOf,
47777  find,
47778  assignPointerEventToLayers,
47779  disableBodyPointerEvents,
47780  restoreBodyPointerEvents
47781};
47782
vendor: 6,388 bytes, lines 47783-47983
47783// node_modules/@kobalte/core/dist/chunk/G3KI2B4X.js
47784var AUTOFOCUS_ON_MOUNT_EVENT = "focusScope.autoFocusOnMount";
47785var AUTOFOCUS_ON_UNMOUNT_EVENT = "focusScope.autoFocusOnUnmount";
47786var EVENT_OPTIONS = {
47787  bubbles: false,
47788  cancelable: true
47789};
47790var focusScopeStack = {
47791  /** A stack of focus scopes, with the active one at the top */
47792  stack: [],
47793  active() {
47794    return this.stack[0];
47795  },
47796  add(scope) {
47797    if (scope !== this.active()) {
47798      this.active()?.pause();
47799    }
47800    this.stack = removeItemFromArray(this.stack, scope);
47801    this.stack.unshift(scope);
47802  },
47803  remove(scope) {
47804    this.stack = removeItemFromArray(this.stack, scope);
47805    this.active()?.resume();
47806  }
47807};
47808function createFocusScope(props, ref) {
47809  const [isPaused, setIsPaused] = createSignal(false);
47810  const focusScope = {
47811    pause() {
47812      setIsPaused(true);
47813    },
47814    resume() {
47815      setIsPaused(false);
47816    }
47817  };
47818  let lastFocusedElement = null;
47819  const onMountAutoFocus = (e) => props.onMountAutoFocus?.(e);
47820  const onUnmountAutoFocus = (e) => props.onUnmountAutoFocus?.(e);
47821  const ownerDocument = () => getDocument(ref());
47822  const createSentinel = () => {
47823    const element3 = ownerDocument().createElement("span");
47824    element3.setAttribute("data-focus-trap", "");
47825    element3.tabIndex = 0;
47826    Object.assign(element3.style, visuallyHiddenStyles);
47827    return element3;
47828  };
47829  const tabbables = () => {
47830    const container = ref();
47831    if (!container) {
47832      return [];
47833    }
47834    return getAllTabbableIn(container, true).filter((el) => !el.hasAttribute("data-focus-trap"));
47835  };
47836  const firstTabbable = () => {
47837    const items = tabbables();
47838    return items.length > 0 ? items[0] : null;
47839  };
47840  const lastTabbable = () => {
47841    const items = tabbables();
47842    return items.length > 0 ? items[items.length - 1] : null;
47843  };
47844  const shouldPreventUnmountAutoFocus = () => {
47845    const container = ref();
47846    if (!container) {
47847      return false;
47848    }
47849    const activeElement = getActiveElement(container);
47850    if (!activeElement) {
47851      return false;
47852    }
47853    if (contains(container, activeElement)) {
47854      return false;
47855    }
47856    return isFocusable(activeElement);
47857  };
47858  createEffect(() => {
47859    if (isServer) {
47860      return;
47861    }
47862    const container = ref();
47863    if (!container) {
47864      return;
47865    }
47866    focusScopeStack.add(focusScope);
47867    const previouslyFocusedElement = getActiveElement(container);
47868    const hasFocusedCandidate = contains(container, previouslyFocusedElement);
47869    if (!hasFocusedCandidate) {
47870      const mountEvent = new CustomEvent(AUTOFOCUS_ON_MOUNT_EVENT, EVENT_OPTIONS);
47871      container.addEventListener(AUTOFOCUS_ON_MOUNT_EVENT, onMountAutoFocus);
47872      container.dispatchEvent(mountEvent);
47873      if (!mountEvent.defaultPrevented) {
47874        setTimeout(() => {
47875          focusWithoutScrolling(firstTabbable());
47876          if (getActiveElement(container) === previouslyFocusedElement) {
47877            focusWithoutScrolling(container);
47878          }
47879        }, 0);
47880      }
47881    }
47882    onCleanup(() => {
47883      container.removeEventListener(AUTOFOCUS_ON_MOUNT_EVENT, onMountAutoFocus);
47884      setTimeout(() => {
47885        const unmountEvent = new CustomEvent(AUTOFOCUS_ON_UNMOUNT_EVENT, EVENT_OPTIONS);
47886        if (shouldPreventUnmountAutoFocus()) {
47887          unmountEvent.preventDefault();
47888        }
47889        container.addEventListener(AUTOFOCUS_ON_UNMOUNT_EVENT, onUnmountAutoFocus);
47890        container.dispatchEvent(unmountEvent);
47891        if (!unmountEvent.defaultPrevented) {
47892          focusWithoutScrolling(previouslyFocusedElement ?? ownerDocument().body);
47893        }
47894        container.removeEventListener(AUTOFOCUS_ON_UNMOUNT_EVENT, onUnmountAutoFocus);
47895        focusScopeStack.remove(focusScope);
47896      }, 0);
47897    });
47898  });
47899  createEffect(() => {
47900    if (isServer) {
47901      return;
47902    }
47903    const container = ref();
47904    if (!container || !access4(props.trapFocus) || isPaused()) {
47905      return;
47906    }
47907    const onFocusIn = (event) => {
47908      const target = event.target;
47909      if (target?.closest(`[${DATA_TOP_LAYER_ATTR}]`)) {
47910        return;
47911      }
47912      if (contains(container, target)) {
47913        lastFocusedElement = target;
47914      } else {
47915        focusWithoutScrolling(lastFocusedElement);
47916      }
47917    };
47918    const onFocusOut = (event) => {
47919      const relatedTarget = event.relatedTarget;
47920      const target = relatedTarget ?? getActiveElement(container);
47921      if (target?.closest(`[${DATA_TOP_LAYER_ATTR}]`)) {
47922        return;
47923      }
47924      if (!contains(container, target)) {
47925        focusWithoutScrolling(lastFocusedElement);
47926      }
47927    };
47928    ownerDocument().addEventListener("focusin", onFocusIn);
47929    ownerDocument().addEventListener("focusout", onFocusOut);
47930    onCleanup(() => {
47931      ownerDocument().removeEventListener("focusin", onFocusIn);
47932      ownerDocument().removeEventListener("focusout", onFocusOut);
47933    });
47934  });
47935  createEffect(() => {
47936    if (isServer) {
47937      return;
47938    }
47939    const container = ref();
47940    if (!container || !access4(props.trapFocus) || isPaused()) {
47941      return;
47942    }
47943    const startSentinel = createSentinel();
47944    container.insertAdjacentElement("afterbegin", startSentinel);
47945    const endSentinel = createSentinel();
47946    container.insertAdjacentElement("beforeend", endSentinel);
47947    function onFocus(event) {
47948      const first = firstTabbable();
47949      const last = lastTabbable();
47950      if (event.relatedTarget === first) {
47951        focusWithoutScrolling(last);
47952      } else {
47953        focusWithoutScrolling(first);
47954      }
47955    }
47956    startSentinel.addEventListener("focusin", onFocus);
47957    endSentinel.addEventListener("focusin", onFocus);
47958    const observer = new MutationObserver((mutations) => {
47959      for (const mutation of mutations) {
47960        if (mutation.previousSibling === endSentinel) {
47961          endSentinel.remove();
47962          container.insertAdjacentElement("beforeend", endSentinel);
47963        }
47964        if (mutation.nextSibling === startSentinel) {
47965          startSentinel.remove();
47966          container.insertAdjacentElement("afterbegin", startSentinel);
47967        }
47968      }
47969    });
47970    observer.observe(container, {
47971      childList: true,
47972      subtree: false
47973    });
47974    onCleanup(() => {
47975      startSentinel.removeEventListener("focusin", onFocus);
47976      endSentinel.removeEventListener("focusin", onFocus);
47977      startSentinel.remove();
47978      endSentinel.remove();
47979      observer.disconnect();
47980    });
47981  });
47982}
47983
vendor: 108 bytes, lines 47984-47986
47984// node_modules/@kobalte/core/dist/chunk/YA7DCYMB.js
47985var DATA_LIVE_ANNOUNCER_ATTR = "data-live-announcer";
47986
vendor: 3,837 bytes, lines 47987-48110
47987// node_modules/@kobalte/core/dist/chunk/R4V3527Z.js
47988function createHideOutside(props) {
47989  createEffect(() => {
47990    if (access4(props.isDisabled)) {
47991      return;
47992    }
47993    onCleanup(ariaHideOutside(access4(props.targets), access4(props.root)));
47994  });
47995}
47996var refCountMap = /* @__PURE__ */ new WeakMap();
47997var observerStack = [];
47998function ariaHideOutside(targets, root = document.body) {
47999  const visibleNodes = new Set(targets);
48000  const hiddenNodes = /* @__PURE__ */ new Set();
48001  const walk = (root2) => {
48002    for (const element3 of root2.querySelectorAll(
48003      `[${DATA_LIVE_ANNOUNCER_ATTR}], [${DATA_TOP_LAYER_ATTR}]`
48004    )) {
48005      visibleNodes.add(element3);
48006    }
48007    const acceptNode = (node) => {
48008      if (visibleNodes.has(node) || node.parentElement && hiddenNodes.has(node.parentElement) && node.parentElement.getAttribute("role") !== "row") {
48009        return NodeFilter.FILTER_REJECT;
48010      }
48011      for (const target of visibleNodes) {
48012        if (node.contains(target)) {
48013          return NodeFilter.FILTER_SKIP;
48014        }
48015      }
48016      return NodeFilter.FILTER_ACCEPT;
48017    };
48018    const walker = document.createTreeWalker(root2, NodeFilter.SHOW_ELEMENT, {
48019      acceptNode
48020    });
48021    const acceptRoot = acceptNode(root2);
48022    if (acceptRoot === NodeFilter.FILTER_ACCEPT) {
48023      hide3(root2);
48024    }
48025    if (acceptRoot !== NodeFilter.FILTER_REJECT) {
48026      let node = walker.nextNode();
48027      while (node != null) {
48028        hide3(node);
48029        node = walker.nextNode();
48030      }
48031    }
48032  };
48033  const hide3 = (node) => {
48034    const refCount = refCountMap.get(node) ?? 0;
48035    if (node.getAttribute("aria-hidden") === "true" && refCount === 0) {
48036      return;
48037    }
48038    if (refCount === 0) {
48039      setTimeout(
48040        () => requestAnimationFrame(() => node.setAttribute("aria-hidden", "true"))
48041      );
48042    }
48043    hiddenNodes.add(node);
48044    refCountMap.set(node, refCount + 1);
48045  };
48046  if (observerStack.length) {
48047    observerStack[observerStack.length - 1].disconnect();
48048  }
48049  walk(root);
48050  const observer = new MutationObserver((changes) => {
48051    for (const change of changes) {
48052      if (change.type !== "childList" || change.addedNodes.length === 0) {
48053        continue;
48054      }
48055      if (![...visibleNodes, ...hiddenNodes].some(
48056        (node) => node.contains(change.target)
48057      )) {
48058        for (const node of change.removedNodes) {
48059          if (node instanceof Element) {
48060            visibleNodes.delete(node);
48061            hiddenNodes.delete(node);
48062          }
48063        }
48064        for (const node of change.addedNodes) {
48065          if ((node instanceof HTMLElement || node instanceof SVGElement) && (node.dataset.liveAnnouncer === "true" || node.dataset.reactAriaTopLayer === "true")) {
48066            visibleNodes.add(node);
48067          } else if (node instanceof Element) {
48068            walk(node);
48069          }
48070        }
48071      }
48072    }
48073  });
48074  observer.observe(root, { childList: true, subtree: true });
48075  const observerWrapper = {
48076    observe() {
48077      observer.observe(root, { childList: true, subtree: true });
48078    },
48079    disconnect() {
48080      observer.disconnect();
48081    }
48082  };
48083  observerStack.push(observerWrapper);
48084  return () => {
48085    observer.disconnect();
48086    for (const node of hiddenNodes) {
48087      const count = refCountMap.get(node);
48088      if (count == null) {
48089        return;
48090      }
48091      if (count === 1) {
48092        setTimeout(
48093          () => requestAnimationFrame(() => node.removeAttribute("aria-hidden"))
48094        );
48095        refCountMap.delete(node);
48096      } else {
48097        refCountMap.set(node, count - 1);
48098      }
48099    }
48100    if (observerWrapper === observerStack[observerStack.length - 1]) {
48101      observerStack.pop();
48102      if (observerStack.length) {
48103        observerStack[observerStack.length - 1].observe();
48104      }
48105    } else {
48106      observerStack.splice(observerStack.indexOf(observerWrapper), 1);
48107    }
48108  };
48109}
48110
vendor: 562 bytes, lines 48111-48132
48111// node_modules/@kobalte/core/dist/chunk/QEMPLYZX.js
48112function createEscapeKeyDown(props) {
48113  const handleKeyDown = (event) => {
48114    if (event.key === EventKey.Escape) {
48115      props.onEscapeKeyDown?.(event);
48116    }
48117  };
48118  createEffect(() => {
48119    if (isServer) {
48120      return;
48121    }
48122    if (access4(props.isDisabled)) {
48123      return;
48124    }
48125    const document2 = props.ownerDocument?.() ?? getDocument();
48126    document2.addEventListener("keydown", handleKeyDown);
48127    onCleanup(() => {
48128      document2.removeEventListener("keydown", handleKeyDown);
48129    });
48130  });
48131}
48132
vendor: 3,167 bytes, lines 48133-48234
48133// node_modules/@kobalte/core/dist/chunk/XLBXJFYN.js
48134var POINTER_DOWN_OUTSIDE_EVENT = "interactOutside.pointerDownOutside";
48135var FOCUS_OUTSIDE_EVENT = "interactOutside.focusOutside";
48136function createInteractOutside(props, ref) {
48137  let pointerDownTimeoutId;
48138  let clickHandler = noop5;
48139  const ownerDocument = () => getDocument(ref());
48140  const onPointerDownOutside = (e) => props.onPointerDownOutside?.(e);
48141  const onFocusOutside = (e) => props.onFocusOutside?.(e);
48142  const onInteractOutside = (e) => props.onInteractOutside?.(e);
48143  const isEventOutside = (e) => {
48144    const target = e.target;
48145    if (!(target instanceof Element)) {
48146      return false;
48147    }
48148    if (target.closest(`[${DATA_TOP_LAYER_ATTR}]`)) {
48149      return false;
48150    }
48151    if (!contains(ownerDocument(), target)) {
48152      return false;
48153    }
48154    if (contains(ref(), target)) {
48155      return false;
48156    }
48157    return !props.shouldExcludeElement?.(target);
48158  };
48159  const onPointerDown = (e) => {
48160    function handler() {
48161      const container = ref();
48162      const target = e.target;
48163      if (!container || !target || !isEventOutside(e)) {
48164        return;
48165      }
48166      const handler2 = composeEventHandlers([
48167        onPointerDownOutside,
48168        onInteractOutside
48169      ]);
48170      target.addEventListener(POINTER_DOWN_OUTSIDE_EVENT, handler2, {
48171        once: true
48172      });
48173      const pointerDownOutsideEvent = new CustomEvent(
48174        POINTER_DOWN_OUTSIDE_EVENT,
48175        {
48176          bubbles: false,
48177          cancelable: true,
48178          detail: {
48179            originalEvent: e,
48180            isContextMenu: e.button === 2 || isCtrlKey(e) && e.button === 0
48181          }
48182        }
48183      );
48184      target.dispatchEvent(pointerDownOutsideEvent);
48185    }
48186    if (e.pointerType === "touch") {
48187      ownerDocument().removeEventListener("click", handler);
48188      clickHandler = handler;
48189      ownerDocument().addEventListener("click", handler, { once: true });
48190    } else {
48191      handler();
48192    }
48193  };
48194  const onFocusIn = (e) => {
48195    const container = ref();
48196    const target = e.target;
48197    if (!container || !target || !isEventOutside(e)) {
48198      return;
48199    }
48200    const handler = composeEventHandlers([
48201      onFocusOutside,
48202      onInteractOutside
48203    ]);
48204    target.addEventListener(FOCUS_OUTSIDE_EVENT, handler, { once: true });
48205    const focusOutsideEvent = new CustomEvent(FOCUS_OUTSIDE_EVENT, {
48206      bubbles: false,
48207      cancelable: true,
48208      detail: {
48209        originalEvent: e,
48210        isContextMenu: false
48211      }
48212    });
48213    target.dispatchEvent(focusOutsideEvent);
48214  };
48215  createEffect(() => {
48216    if (isServer) {
48217      return;
48218    }
48219    if (access4(props.isDisabled)) {
48220      return;
48221    }
48222    pointerDownTimeoutId = window.setTimeout(() => {
48223      ownerDocument().addEventListener("pointerdown", onPointerDown, true);
48224    }, 0);
48225    ownerDocument().addEventListener("focusin", onFocusIn, true);
48226    onCleanup(() => {
48227      window.clearTimeout(pointerDownTimeoutId);
48228      ownerDocument().removeEventListener("click", clickHandler);
48229      ownerDocument().removeEventListener("pointerdown", onPointerDown, true);
48230      ownerDocument().removeEventListener("focusin", onFocusIn, true);
48231    });
48232  });
48233}
48234
vendor: 436 bytes, lines 48235-48250
48235// node_modules/@kobalte/core/dist/chunk/6Y7B2NEO.js
48236function Polymorphic(props) {
48237  const [local, others] = splitProps(props, ["as"]);
48238  if (!local.as) {
48239    throw new Error("[kobalte]: Polymorphic is missing the required `as` prop.");
48240  }
48241  return (
48242    // @ts-ignore: Props are valid but not worth calculating
48243    createComponent(Dynamic, mergeProps(others, {
48244      get component() {
48245        return local.as;
48246      }
48247    }))
48248  );
48249}
48250
vendor: 3,648 bytes, lines 48251-48369
48251// node_modules/@kobalte/core/dist/chunk/WHII6HHI.js
48252var DismissableLayerContext = createContext();
48253function useOptionalDismissableLayerContext() {
48254  return useContext(DismissableLayerContext);
48255}
48256function DismissableLayer(props) {
48257  let ref;
48258  const parentContext = useOptionalDismissableLayerContext();
48259  const [local, others] = splitProps(props, ["ref", "disableOutsidePointerEvents", "excludedElements", "onEscapeKeyDown", "onPointerDownOutside", "onFocusOutside", "onInteractOutside", "onDismiss", "bypassTopMostLayerCheck"]);
48260  const nestedLayers = /* @__PURE__ */ new Set([]);
48261  const registerNestedLayer = (element3) => {
48262    nestedLayers.add(element3);
48263    const parentUnregister = parentContext?.registerNestedLayer(element3);
48264    return () => {
48265      nestedLayers.delete(element3);
48266      parentUnregister?.();
48267    };
48268  };
48269  const shouldExcludeElement = (element3) => {
48270    if (!ref) {
48271      return false;
48272    }
48273    return local.excludedElements?.some((node) => contains(node(), element3)) || [...nestedLayers].some((layer) => contains(layer, element3));
48274  };
48275  const onPointerDownOutside = (e) => {
48276    if (!ref || layerStack.isBelowPointerBlockingLayer(ref)) {
48277      return;
48278    }
48279    if (!local.bypassTopMostLayerCheck && !layerStack.isTopMostLayer(ref)) {
48280      return;
48281    }
48282    local.onPointerDownOutside?.(e);
48283    local.onInteractOutside?.(e);
48284    if (!e.defaultPrevented) {
48285      local.onDismiss?.();
48286    }
48287  };
48288  const onFocusOutside = (e) => {
48289    local.onFocusOutside?.(e);
48290    local.onInteractOutside?.(e);
48291    if (!e.defaultPrevented) {
48292      local.onDismiss?.();
48293    }
48294  };
48295  createInteractOutside({
48296    shouldExcludeElement,
48297    onPointerDownOutside,
48298    onFocusOutside
48299  }, () => ref);
48300  createEscapeKeyDown({
48301    ownerDocument: () => getDocument(ref),
48302    onEscapeKeyDown: (e) => {
48303      if (!ref || !layerStack.isTopMostLayer(ref)) {
48304        return;
48305      }
48306      local.onEscapeKeyDown?.(e);
48307      if (!e.defaultPrevented && local.onDismiss) {
48308        e.preventDefault();
48309        local.onDismiss();
48310      }
48311    }
48312  });
48313  onMount(() => {
48314    if (!ref) {
48315      return;
48316    }
48317    layerStack.addLayer({
48318      node: ref,
48319      isPointerBlocking: local.disableOutsidePointerEvents,
48320      dismiss: local.onDismiss
48321    });
48322    const unregisterFromParentLayer = parentContext?.registerNestedLayer(ref);
48323    layerStack.assignPointerEventToLayers();
48324    layerStack.disableBodyPointerEvents(ref);
48325    onCleanup(() => {
48326      if (!ref) {
48327        return;
48328      }
48329      layerStack.removeLayer(ref);
48330      unregisterFromParentLayer?.();
48331      layerStack.assignPointerEventToLayers();
48332      layerStack.restoreBodyPointerEvents(ref);
48333    });
48334  });
48335  createEffect(on([() => ref, () => local.disableOutsidePointerEvents], ([ref2, disableOutsidePointerEvents]) => {
48336    if (!ref2) {
48337      return;
48338    }
48339    const layer = layerStack.find(ref2);
48340    if (layer && layer.isPointerBlocking !== disableOutsidePointerEvents) {
48341      layer.isPointerBlocking = disableOutsidePointerEvents;
48342      layerStack.assignPointerEventToLayers();
48343    }
48344    if (disableOutsidePointerEvents) {
48345      layerStack.disableBodyPointerEvents(ref2);
48346    }
48347    onCleanup(() => {
48348      layerStack.restoreBodyPointerEvents(ref2);
48349    });
48350  }, {
48351    defer: true
48352  }));
48353  const context3 = {
48354    registerNestedLayer
48355  };
48356  return createComponent(DismissableLayerContext.Provider, {
48357    value: context3,
48358    get children() {
48359      return createComponent(Polymorphic, mergeProps({
48360        as: "div",
48361        ref(r$) {
48362          const _ref$ = mergeRefs((el) => ref = el, local.ref);
48363          typeof _ref$ === "function" && _ref$(r$);
48364        }
48365      }, others));
48366    }
48367  });
48368}
48369
vendor: 1,006 bytes, lines 48370-48399
48370// node_modules/@kobalte/core/dist/chunk/BLN63FDC.js
48371function createControllableSignal(props) {
48372  const [_value, _setValue] = createSignal(props.defaultValue?.());
48373  const isControlled = createMemo(() => props.value?.() !== void 0);
48374  const value = createMemo(() => isControlled() ? props.value?.() : _value());
48375  const setValue = (next) => {
48376    untrack(() => {
48377      const nextValue = accessWith4(next, value());
48378      if (!Object.is(nextValue, value())) {
48379        if (!isControlled()) {
48380          _setValue(nextValue);
48381        }
48382        props.onChange?.(nextValue);
48383      }
48384      return nextValue;
48385    });
48386  };
48387  return [value, setValue];
48388}
48389function createControllableBooleanSignal(props) {
48390  const [_value, setValue] = createControllableSignal(props);
48391  const value = () => _value() ?? false;
48392  return [value, setValue];
48393}
48394function createControllableArraySignal(props) {
48395  const [_value, setValue] = createControllableSignal(props);
48396  const value = () => _value() ?? [];
48397  return [value, setValue];
48398}
48399
vendor: 554 bytes, lines 48400-48424
48400// node_modules/@kobalte/core/dist/chunk/7LCANGHD.js
48401function createDisclosureState(props = {}) {
48402  const [isOpen, setIsOpen] = createControllableBooleanSignal({
48403    value: () => access4(props.open),
48404    defaultValue: () => !!access4(props.defaultOpen),
48405    onChange: (value) => props.onOpenChange?.(value)
48406  });
48407  const open = () => {
48408    setIsOpen(true);
48409  };
48410  const close = () => {
48411    setIsOpen(false);
48412  };
48413  const toggle = () => {
48414    isOpen() ? close() : open();
48415  };
48416  return {
48417    isOpen,
48418    setIsOpen,
48419    open,
48420    close,
48421    toggle
48422  };
48423}
48424
vendor: 384 bytes, lines 48425-48436
48425// node_modules/@kobalte/core/dist/chunk/ET5T45DO.js
48426function createTagName(ref, fallback) {
48427  const [tagName, setTagName] = createSignal(stringOrUndefined(fallback?.()));
48428  createEffect(() => {
48429    setTagName(ref()?.tagName.toLowerCase() || stringOrUndefined(fallback?.()));
48430  });
48431  return tagName;
48432}
48433function stringOrUndefined(value) {
48434  return isString(value) ? value : void 0;
48435}
48436
vendor: 224 bytes, lines 48437-48443
48437// node_modules/@kobalte/core/dist/chunk/5ZKAE4VZ.js
48438var __defProp = Object.defineProperty;
48439var __export = (target, all3) => {
48440  for (var name in all3)
48441    __defProp(target, name, { get: all3[name], enumerable: true });
48442};
48443
vendor: 2,047 bytes, lines 48444-48518
48444// node_modules/@kobalte/core/dist/chunk/7OVKXYPU.js
48445var button_exports = {};
48446__export(button_exports, {
48447  Button: () => Button,
48448  Root: () => ButtonRoot
48449});
48450var BUTTON_INPUT_TYPES = [
48451  "button",
48452  "color",
48453  "file",
48454  "image",
48455  "reset",
48456  "submit"
48457];
48458function isButton(element3) {
48459  const tagName = element3.tagName.toLowerCase();
48460  if (tagName === "button") {
48461    return true;
48462  }
48463  if (tagName === "input" && element3.type) {
48464    return BUTTON_INPUT_TYPES.indexOf(element3.type) !== -1;
48465  }
48466  return false;
48467}
48468function ButtonRoot(props) {
48469  let ref;
48470  const mergedProps = mergeDefaultProps({
48471    type: "button"
48472  }, props);
48473  const [local, others] = splitProps(mergedProps, ["ref", "type", "disabled"]);
48474  const tagName = createTagName(() => ref, () => "button");
48475  const isNativeButton = createMemo(() => {
48476    const elementTagName = tagName();
48477    if (elementTagName == null) {
48478      return false;
48479    }
48480    return isButton({
48481      tagName: elementTagName,
48482      type: local.type
48483    });
48484  });
48485  const isNativeInput = createMemo(() => {
48486    return tagName() === "input";
48487  });
48488  const isNativeLink = createMemo(() => {
48489    return tagName() === "a" && ref?.getAttribute("href") != null;
48490  });
48491  return createComponent(Polymorphic, mergeProps({
48492    as: "button",
48493    ref(r$) {
48494      const _ref$ = mergeRefs((el) => ref = el, local.ref);
48495      typeof _ref$ === "function" && _ref$(r$);
48496    },
48497    get type() {
48498      return isNativeButton() || isNativeInput() ? local.type : void 0;
48499    },
48500    get role() {
48501      return !isNativeButton() && !isNativeLink() ? "button" : void 0;
48502    },
48503    get tabIndex() {
48504      return !isNativeButton() && !isNativeLink() && !local.disabled ? 0 : void 0;
48505    },
48506    get disabled() {
48507      return isNativeButton() || isNativeInput() ? local.disabled : void 0;
48508    },
48509    get ["aria-disabled"]() {
48510      return !isNativeButton() && !isNativeInput() && local.disabled ? true : void 0;
48511    },
48512    get ["data-disabled"]() {
48513      return local.disabled ? "" : void 0;
48514    }
48515  }, others));
48516}
48517var Button = ButtonRoot;
48518
vendor: 165 bytes, lines 48519-48526
48519// node_modules/@kobalte/core/dist/chunk/E4R2EMM4.js
48520function createRegisterId(setter) {
48521  return (id) => {
48522    setter(id);
48523    return () => setter(void 0);
48524  };
48525}
48526
vendor: 109 bytes, lines 48527-48529
48527// node_modules/@corvu/utils/dist/chunk/ZV6G25TT.js
48528var access5 = (v) => typeof v === "function" ? v() : v;
48529
vendor: 343 bytes, lines 48530-48540
48530// node_modules/@corvu/utils/dist/chunk/SEUPK2SH.js
48531var contains2 = (wrapper, target) => {
48532  if (wrapper.contains(target)) return true;
48533  let currentElement = target;
48534  while (currentElement) {
48535    if (currentElement === wrapper) return true;
48536    currentElement = currentElement._$host ?? currentElement.parentElement;
48537  }
48538  return false;
48539};
48540
vendor: 1,516 bytes, lines 48541-48587
48541// node_modules/@corvu/utils/dist/create/style.js
48542var activeStyles = /* @__PURE__ */ new Map();
48543var createStyle = (props) => {
48544  createEffect(() => {
48545    const style2 = access5(props.style) ?? {};
48546    const properties = access5(props.properties) ?? [];
48547    const originalStyles = {};
48548    for (const key in style2) {
48549      originalStyles[key] = props.element.style[key];
48550    }
48551    const activeStyle = activeStyles.get(props.key);
48552    if (activeStyle) {
48553      activeStyle.activeCount++;
48554    } else {
48555      activeStyles.set(props.key, {
48556        activeCount: 1,
48557        originalStyles,
48558        properties: properties.map((property3) => property3.key)
48559      });
48560    }
48561    Object.assign(props.element.style, props.style);
48562    for (const property3 of properties) {
48563      props.element.style.setProperty(property3.key, property3.value);
48564    }
48565    onCleanup(() => {
48566      const activeStyle2 = activeStyles.get(props.key);
48567      if (!activeStyle2) return;
48568      if (activeStyle2.activeCount !== 1) {
48569        activeStyle2.activeCount--;
48570        return;
48571      }
48572      activeStyles.delete(props.key);
48573      for (const [key, value] of Object.entries(activeStyle2.originalStyles)) {
48574        props.element.style[key] = value;
48575      }
48576      for (const property3 of activeStyle2.properties) {
48577        props.element.style.removeProperty(property3);
48578      }
48579      if (props.element.style.length === 0) {
48580        props.element.removeAttribute("style");
48581      }
48582      props.cleanup?.();
48583    });
48584  });
48585};
48586var style_default = createStyle;
48587
vendor: 1,608 bytes, lines 48588-48627
48588// node_modules/@corvu/utils/dist/scroll/index.js
48589var getScrollDimensions = (element3, axis) => {
48590  switch (axis) {
48591    case "x":
48592      return [element3.clientWidth, element3.scrollLeft, element3.scrollWidth];
48593    case "y":
48594      return [element3.clientHeight, element3.scrollTop, element3.scrollHeight];
48595  }
48596};
48597var isScrollContainer = (element3, axis) => {
48598  const styles = getComputedStyle(element3);
48599  const overflow = axis === "x" ? styles.overflowX : styles.overflowY;
48600  return overflow === "auto" || overflow === "scroll" || // The HTML element is a scroll container if it has overflow visible
48601  element3.tagName === "HTML" && overflow === "visible";
48602};
48603var getScrollAtLocation = (location, axis, stopAt) => {
48604  const directionFactor = axis === "x" && window.getComputedStyle(location).direction === "rtl" ? -1 : 1;
48605  let currentElement = location;
48606  let availableScroll = 0;
48607  let availableScrollTop = 0;
48608  let wrapperReached = false;
48609  do {
48610    const [clientSize, scrollOffset, scrollSize] = getScrollDimensions(
48611      currentElement,
48612      axis
48613    );
48614    const scrolled = scrollSize - clientSize - directionFactor * scrollOffset;
48615    if ((scrollOffset !== 0 || scrolled !== 0) && isScrollContainer(currentElement, axis)) {
48616      availableScroll += scrolled;
48617      availableScrollTop += scrollOffset;
48618    }
48619    if (currentElement === (stopAt ?? document.documentElement)) {
48620      wrapperReached = true;
48621    } else {
48622      currentElement = currentElement._$host ?? currentElement.parentElement;
48623    }
48624  } while (currentElement && !wrapperReached);
48625  return [availableScroll, availableScrollTop];
48626};
48627
vendor: 5,644 bytes, lines 48628-48796
48628// node_modules/solid-prevent-scroll/dist/index.js
48629var [preventScrollStack, setPreventScrollStack] = createSignal([]);
48630var isActive = (id) => preventScrollStack().indexOf(id) === preventScrollStack().length - 1;
48631var createPreventScroll = (props) => {
48632  const defaultedProps = mergeProps(
48633    {
48634      element: null,
48635      enabled: true,
48636      hideScrollbar: true,
48637      preventScrollbarShift: true,
48638      preventScrollbarShiftMode: "padding",
48639      restoreScrollPosition: true,
48640      allowPinchZoom: false
48641    },
48642    props
48643  );
48644  const preventScrollId = createUniqueId();
48645  let currentTouchStart = [0, 0];
48646  let currentTouchStartAxis = null;
48647  let currentTouchStartDelta = null;
48648  createEffect(() => {
48649    if (!access5(defaultedProps.enabled)) return;
48650    setPreventScrollStack((stack3) => [...stack3, preventScrollId]);
48651    onCleanup(() => {
48652      setPreventScrollStack(
48653        (stack3) => stack3.filter((id) => id !== preventScrollId)
48654      );
48655    });
48656  });
48657  createEffect(() => {
48658    if (!access5(defaultedProps.enabled) || !access5(defaultedProps.hideScrollbar))
48659      return;
48660    const { documentElement } = document;
48661    const scrollbarWidth = window.innerWidth - documentElement.clientWidth;
48662    if (access5(defaultedProps.preventScrollbarShift)) {
48663      const style2 = { overflow: "hidden" };
48664      const properties = [];
48665      if (scrollbarWidth > 0) {
48666        if (access5(defaultedProps.preventScrollbarShiftMode) === "padding") {
48667          style2.paddingRight = `calc(${window.getComputedStyle(documentElement).paddingRight} + ${scrollbarWidth}px)`;
48668        } else {
48669          style2.marginRight = `calc(${window.getComputedStyle(documentElement).marginRight} + ${scrollbarWidth}px)`;
48670        }
48671        properties.push({
48672          key: "--scrollbar-width",
48673          value: `${scrollbarWidth}px`
48674        });
48675      }
48676      const offsetTop = window.scrollY;
48677      const offsetLeft = window.scrollX;
48678      style_default({
48679        key: "prevent-scroll",
48680        element: documentElement,
48681        style: style2,
48682        properties,
48683        cleanup: () => {
48684          if (access5(defaultedProps.restoreScrollPosition) && scrollbarWidth > 0) {
48685            window.scrollTo(offsetLeft, offsetTop);
48686          }
48687        }
48688      });
48689    } else {
48690      style_default({
48691        key: "prevent-scroll",
48692        element: documentElement,
48693        style: {
48694          overflow: "hidden"
48695        }
48696      });
48697    }
48698  });
48699  createEffect(() => {
48700    if (!isActive(preventScrollId) || !access5(defaultedProps.enabled)) return;
48701    document.addEventListener("wheel", maybePreventWheel, {
48702      passive: false
48703    });
48704    document.addEventListener("touchstart", logTouchStart, {
48705      passive: false
48706    });
48707    document.addEventListener("touchmove", maybePreventTouch, {
48708      passive: false
48709    });
48710    onCleanup(() => {
48711      document.removeEventListener("wheel", maybePreventWheel);
48712      document.removeEventListener("touchstart", logTouchStart);
48713      document.removeEventListener("touchmove", maybePreventTouch);
48714    });
48715  });
48716  const logTouchStart = (event) => {
48717    currentTouchStart = getTouchXY(event);
48718    currentTouchStartAxis = null;
48719    currentTouchStartDelta = null;
48720  };
48721  const maybePreventWheel = (event) => {
48722    const target = event.target;
48723    const wrapper = access5(defaultedProps.element);
48724    const delta = getDeltaXY(event);
48725    const axis = Math.abs(delta[0]) > Math.abs(delta[1]) ? "x" : "y";
48726    const axisDelta = axis === "x" ? delta[0] : delta[1];
48727    const resultsInScroll = wouldScroll(target, axis, axisDelta, wrapper);
48728    let shouldCancel;
48729    if (wrapper && contains2(wrapper, target)) {
48730      shouldCancel = !resultsInScroll;
48731    } else {
48732      shouldCancel = true;
48733    }
48734    if (shouldCancel && event.cancelable) {
48735      event.preventDefault();
48736    }
48737  };
48738  const maybePreventTouch = (event) => {
48739    const wrapper = access5(defaultedProps.element);
48740    const target = event.target;
48741    let shouldCancel;
48742    if (event.touches.length === 2) {
48743      shouldCancel = !access5(defaultedProps.allowPinchZoom);
48744    } else {
48745      if (currentTouchStartAxis == null || currentTouchStartDelta === null) {
48746        const delta = getTouchXY(event).map(
48747          (touch, i) => currentTouchStart[i] - touch
48748        );
48749        const axis = Math.abs(delta[0]) > Math.abs(delta[1]) ? "x" : "y";
48750        currentTouchStartAxis = axis;
48751        currentTouchStartDelta = axis === "x" ? delta[0] : delta[1];
48752      }
48753      if (target.type === "range") {
48754        shouldCancel = false;
48755      } else {
48756        const wouldResultInScroll = wouldScroll(
48757          target,
48758          currentTouchStartAxis,
48759          currentTouchStartDelta,
48760          wrapper
48761        );
48762        if (wrapper && contains2(wrapper, target)) {
48763          shouldCancel = !wouldResultInScroll;
48764        } else {
48765          shouldCancel = true;
48766        }
48767      }
48768    }
48769    if (shouldCancel && event.cancelable) {
48770      event.preventDefault();
48771    }
48772  };
48773};
48774var getDeltaXY = (event) => [
48775  event.deltaX,
48776  event.deltaY
48777];
48778var getTouchXY = (event) => event.changedTouches[0] ? [event.changedTouches[0].clientX, event.changedTouches[0].clientY] : [0, 0];
48779var wouldScroll = (target, axis, delta, wrapper) => {
48780  const targetInWrapper = wrapper !== null && contains2(wrapper, target);
48781  const [availableScroll, availableScrollTop] = getScrollAtLocation(
48782    target,
48783    axis,
48784    targetInWrapper ? wrapper : void 0
48785  );
48786  if (delta > 0 && Math.abs(availableScroll) <= 1) {
48787    return false;
48788  }
48789  if (delta < 0 && Math.abs(availableScrollTop) < 1) {
48790    return false;
48791  }
48792  return true;
48793};
48794var preventScroll_default = createPreventScroll;
48795var index_default = preventScroll_default;
48796
vendor: 2,531 bytes, lines 48797-48867
48797// node_modules/solid-presence/dist/index.js
48798var createPresence = (props) => {
48799  const refStyles = createMemo(() => {
48800    const element3 = access5(props.element);
48801    if (!element3) return;
48802    return getComputedStyle(element3);
48803  });
48804  const getAnimationName = () => {
48805    return refStyles()?.animationName ?? "none";
48806  };
48807  const [presentState, setPresentStateInternal] = createSignal(access5(props.show) ? "present" : "hidden");
48808  const setPresentState = (state) => {
48809    setPresentStateInternal(state);
48810    props.onStateChange?.(state);
48811  };
48812  let animationName = "none";
48813  createEffect((prevShow) => {
48814    const show = access5(props.show);
48815    untrack(() => {
48816      if (prevShow === show) return show;
48817      const prevAnimationName = animationName;
48818      const currentAnimationName = getAnimationName();
48819      if (show) {
48820        setPresentState("present");
48821      } else if (currentAnimationName === "none" || refStyles()?.display === "none") {
48822        setPresentState("hidden");
48823      } else {
48824        const isAnimating = prevAnimationName !== currentAnimationName;
48825        if (prevShow === true && isAnimating) {
48826          setPresentState("hiding");
48827        } else {
48828          setPresentState("hidden");
48829        }
48830      }
48831    });
48832    return show;
48833  }, access5(props.show));
48834  createEffect(() => {
48835    const element3 = access5(props.element);
48836    if (!element3) return;
48837    const handleAnimationStart = (event) => {
48838      if (event.target === element3) {
48839        animationName = getAnimationName();
48840      }
48841    };
48842    const handleAnimationEnd = (event) => {
48843      const currentAnimationName = getAnimationName();
48844      const isCurrentAnimation = currentAnimationName.includes(
48845        event.animationName
48846      );
48847      if (event.target === element3 && isCurrentAnimation && presentState() === "hiding") {
48848        setPresentState("hidden");
48849      }
48850    };
48851    element3.addEventListener("animationstart", handleAnimationStart);
48852    element3.addEventListener("animationcancel", handleAnimationEnd);
48853    element3.addEventListener("animationend", handleAnimationEnd);
48854    onCleanup(() => {
48855      element3.removeEventListener("animationstart", handleAnimationStart);
48856      element3.removeEventListener("animationcancel", handleAnimationEnd);
48857      element3.removeEventListener("animationend", handleAnimationEnd);
48858    });
48859  });
48860  return {
48861    present: () => presentState() === "present" || presentState() === "hiding",
48862    state: presentState
48863  };
48864};
48865var presence_default = createPresence;
48866var index_default2 = presence_default;
48867
vendor: 9,732 bytes, lines 48868-49193
48868// node_modules/@kobalte/core/dist/chunk/27MLNS66.js
48869var dialog_exports = {};
48870__export(dialog_exports, {
48871  CloseButton: () => DialogCloseButton,
48872  Content: () => DialogContent,
48873  Description: () => DialogDescription,
48874  Dialog: () => Dialog,
48875  Overlay: () => DialogOverlay,
48876  Portal: () => DialogPortal,
48877  Root: () => DialogRoot,
48878  Title: () => DialogTitle,
48879  Trigger: () => DialogTrigger,
48880  useDialogContext: () => useDialogContext
48881});
48882var DialogContext = createContext();
48883function useDialogContext() {
48884  const context3 = useContext(DialogContext);
48885  if (context3 === void 0) {
48886    throw new Error("[kobalte]: `useDialogContext` must be used within a `Dialog` component");
48887  }
48888  return context3;
48889}
48890function DialogCloseButton(props) {
48891  const context3 = useDialogContext();
48892  const [local, others] = splitProps(props, ["aria-label", "onClick"]);
48893  const onClick = (e) => {
48894    callHandler(e, local.onClick);
48895    context3.close();
48896  };
48897  return createComponent(ButtonRoot, mergeProps({
48898    get ["aria-label"]() {
48899      return local["aria-label"] || context3.translations().dismiss;
48900    },
48901    onClick
48902  }, others));
48903}
48904function DialogContent(props) {
48905  let ref;
48906  const context3 = useDialogContext();
48907  const mergedProps = mergeDefaultProps({
48908    id: context3.generateId("content")
48909  }, props);
48910  const [local, others] = splitProps(mergedProps, ["ref", "onOpenAutoFocus", "onCloseAutoFocus", "onPointerDownOutside", "onFocusOutside", "onInteractOutside"]);
48911  let hasInteractedOutside = false;
48912  let hasPointerDownOutside = false;
48913  const onPointerDownOutside = (e) => {
48914    local.onPointerDownOutside?.(e);
48915    if (context3.modal() && e.detail.isContextMenu) {
48916      e.preventDefault();
48917    }
48918  };
48919  const onFocusOutside = (e) => {
48920    local.onFocusOutside?.(e);
48921    if (context3.modal()) {
48922      e.preventDefault();
48923    }
48924  };
48925  const onInteractOutside = (e) => {
48926    local.onInteractOutside?.(e);
48927    if (context3.modal()) {
48928      return;
48929    }
48930    if (!e.defaultPrevented) {
48931      hasInteractedOutside = true;
48932      if (e.detail.originalEvent.type === "pointerdown") {
48933        hasPointerDownOutside = true;
48934      }
48935    }
48936    if (contains(context3.triggerRef(), e.target)) {
48937      e.preventDefault();
48938    }
48939    if (e.detail.originalEvent.type === "focusin" && hasPointerDownOutside) {
48940      e.preventDefault();
48941    }
48942  };
48943  const onCloseAutoFocus = (e) => {
48944    local.onCloseAutoFocus?.(e);
48945    if (context3.modal()) {
48946      e.preventDefault();
48947      focusWithoutScrolling(context3.triggerRef());
48948    } else {
48949      if (!e.defaultPrevented) {
48950        if (!hasInteractedOutside) {
48951          focusWithoutScrolling(context3.triggerRef());
48952        }
48953        e.preventDefault();
48954      }
48955      hasInteractedOutside = false;
48956      hasPointerDownOutside = false;
48957    }
48958  };
48959  createHideOutside({
48960    isDisabled: () => !(context3.isOpen() && context3.modal()),
48961    targets: () => ref ? [ref] : []
48962  });
48963  index_default({
48964    element: () => ref ?? null,
48965    enabled: () => context3.contentPresent() && context3.preventScroll()
48966  });
48967  createFocusScope({
48968    trapFocus: () => context3.isOpen() && context3.modal(),
48969    onMountAutoFocus: local.onOpenAutoFocus,
48970    onUnmountAutoFocus: onCloseAutoFocus
48971  }, () => ref);
48972  createEffect(() => onCleanup(context3.registerContentId(others.id)));
48973  return createComponent(Show, {
48974    get when() {
48975      return context3.contentPresent();
48976    },
48977    get children() {
48978      return createComponent(DismissableLayer, mergeProps({
48979        ref(r$) {
48980          const _ref$ = mergeRefs((el) => {
48981            context3.setContentRef(el);
48982            ref = el;
48983          }, local.ref);
48984          typeof _ref$ === "function" && _ref$(r$);
48985        },
48986        role: "dialog",
48987        tabIndex: -1,
48988        get disableOutsidePointerEvents() {
48989          return memo(() => !!context3.modal())() && context3.isOpen();
48990        },
48991        get excludedElements() {
48992          return [context3.triggerRef];
48993        },
48994        get ["aria-labelledby"]() {
48995          return context3.titleId();
48996        },
48997        get ["aria-describedby"]() {
48998          return context3.descriptionId();
48999        },
49000        get ["data-expanded"]() {
49001          return context3.isOpen() ? "" : void 0;
49002        },
49003        get ["data-closed"]() {
49004          return !context3.isOpen() ? "" : void 0;
49005        },
49006        onPointerDownOutside,
49007        onFocusOutside,
49008        onInteractOutside,
49009        get onDismiss() {
49010          return context3.close;
49011        }
49012      }, others));
49013    }
49014  });
49015}
49016function DialogDescription(props) {
49017  const context3 = useDialogContext();
49018  const mergedProps = mergeDefaultProps({
49019    id: context3.generateId("description")
49020  }, props);
49021  const [local, others] = splitProps(mergedProps, ["id"]);
49022  createEffect(() => onCleanup(context3.registerDescriptionId(local.id)));
49023  return createComponent(Polymorphic, mergeProps({
49024    as: "p",
49025    get id() {
49026      return local.id;
49027    }
49028  }, others));
49029}
49030function DialogOverlay(props) {
49031  const context3 = useDialogContext();
49032  const [local, others] = splitProps(props, ["ref", "style", "onPointerDown"]);
49033  const onPointerDown = (e) => {
49034    callHandler(e, local.onPointerDown);
49035    if (e.target === e.currentTarget) {
49036      e.preventDefault();
49037    }
49038  };
49039  return createComponent(Show, {
49040    get when() {
49041      return context3.overlayPresent();
49042    },
49043    get children() {
49044      return createComponent(Polymorphic, mergeProps({
49045        as: "div",
49046        ref(r$) {
49047          const _ref$ = mergeRefs(context3.setOverlayRef, local.ref);
49048          typeof _ref$ === "function" && _ref$(r$);
49049        },
49050        get style() {
49051          return combineStyle({
49052            "pointer-events": "auto"
49053          }, local.style);
49054        },
49055        get ["data-expanded"]() {
49056          return context3.isOpen() ? "" : void 0;
49057        },
49058        get ["data-closed"]() {
49059          return !context3.isOpen() ? "" : void 0;
49060        },
49061        onPointerDown
49062      }, others));
49063    }
49064  });
49065}
49066function DialogPortal(props) {
49067  const context3 = useDialogContext();
49068  return createComponent(Show, {
49069    get when() {
49070      return context3.contentPresent() || context3.overlayPresent();
49071    },
49072    get children() {
49073      return createComponent(Portal, props);
49074    }
49075  });
49076}
49077var DIALOG_INTL_TRANSLATIONS = {
49078  // `aria-label` of Dialog.CloseButton.
49079  dismiss: "Dismiss"
49080};
49081function DialogRoot(props) {
49082  const defaultId = `dialog-${createUniqueId()}`;
49083  const mergedProps = mergeDefaultProps({
49084    id: defaultId,
49085    modal: true,
49086    translations: DIALOG_INTL_TRANSLATIONS
49087  }, props);
49088  const [contentId, setContentId] = createSignal();
49089  const [titleId, setTitleId] = createSignal();
49090  const [descriptionId, setDescriptionId] = createSignal();
49091  const [overlayRef, setOverlayRef] = createSignal();
49092  const [contentRef, setContentRef] = createSignal();
49093  const [triggerRef, setTriggerRef] = createSignal();
49094  const disclosureState = createDisclosureState({
49095    open: () => mergedProps.open,
49096    defaultOpen: () => mergedProps.defaultOpen,
49097    onOpenChange: (isOpen) => mergedProps.onOpenChange?.(isOpen)
49098  });
49099  const shouldMount = () => mergedProps.forceMount || disclosureState.isOpen();
49100  const {
49101    present: overlayPresent
49102  } = index_default2({
49103    show: shouldMount,
49104    element: () => overlayRef() ?? null
49105  });
49106  const {
49107    present: contentPresent
49108  } = index_default2({
49109    show: shouldMount,
49110    element: () => contentRef() ?? null
49111  });
49112  const context3 = {
49113    translations: () => mergedProps.translations ?? DIALOG_INTL_TRANSLATIONS,
49114    isOpen: disclosureState.isOpen,
49115    modal: () => mergedProps.modal ?? true,
49116    preventScroll: () => mergedProps.preventScroll ?? context3.modal(),
49117    contentId,
49118    titleId,
49119    descriptionId,
49120    triggerRef,
49121    overlayRef,
49122    setOverlayRef,
49123    contentRef,
49124    setContentRef,
49125    overlayPresent,
49126    contentPresent,
49127    close: disclosureState.close,
49128    toggle: disclosureState.toggle,
49129    setTriggerRef,
49130    generateId: createGenerateId(() => mergedProps.id),
49131    registerContentId: createRegisterId(setContentId),
49132    registerTitleId: createRegisterId(setTitleId),
49133    registerDescriptionId: createRegisterId(setDescriptionId)
49134  };
49135  return createComponent(DialogContext.Provider, {
49136    value: context3,
49137    get children() {
49138      return mergedProps.children;
49139    }
49140  });
49141}
49142function DialogTitle(props) {
49143  const context3 = useDialogContext();
49144  const mergedProps = mergeDefaultProps({
49145    id: context3.generateId("title")
49146  }, props);
49147  const [local, others] = splitProps(mergedProps, ["id"]);
49148  createEffect(() => onCleanup(context3.registerTitleId(local.id)));
49149  return createComponent(Polymorphic, mergeProps({
49150    as: "h2",
49151    get id() {
49152      return local.id;
49153    }
49154  }, others));
49155}
49156function DialogTrigger(props) {
49157  const context3 = useDialogContext();
49158  const [local, others] = splitProps(props, ["ref", "onClick"]);
49159  const onClick = (e) => {
49160    callHandler(e, local.onClick);
49161    context3.toggle();
49162  };
49163  return createComponent(ButtonRoot, mergeProps({
49164    ref(r$) {
49165      const _ref$ = mergeRefs(context3.setTriggerRef, local.ref);
49166      typeof _ref$ === "function" && _ref$(r$);
49167    },
49168    "aria-haspopup": "dialog",
49169    get ["aria-expanded"]() {
49170      return context3.isOpen();
49171    },
49172    get ["aria-controls"]() {
49173      return memo(() => !!context3.isOpen())() ? context3.contentId() : void 0;
49174    },
49175    get ["data-expanded"]() {
49176      return context3.isOpen() ? "" : void 0;
49177    },
49178    get ["data-closed"]() {
49179      return !context3.isOpen() ? "" : void 0;
49180    },
49181    onClick
49182  }, others));
49183}
49184var Dialog = Object.assign(DialogRoot, {
49185  CloseButton: DialogCloseButton,
49186  Content: DialogContent,
49187  Description: DialogDescription,
49188  Overlay: DialogOverlay,
49189  Portal: DialogPortal,
49190  Title: DialogTitle,
49191  Trigger: DialogTrigger
49192});
49193
vendor: 5,810 bytes, lines 49194-49334
49194// node_modules/@internationalized/number/dist/NumberFormatter.mjs
49195var $488c6ddbf4ef74c2$var$formatterCache = /* @__PURE__ */ new Map();
49196var $488c6ddbf4ef74c2$var$supportsSignDisplay = false;
49197try {
49198  $488c6ddbf4ef74c2$var$supportsSignDisplay = new Intl.NumberFormat("de-DE", {
49199    signDisplay: "exceptZero"
49200  }).resolvedOptions().signDisplay === "exceptZero";
49201} catch (e) {
49202}
49203var $488c6ddbf4ef74c2$var$supportsUnit = false;
49204try {
49205  $488c6ddbf4ef74c2$var$supportsUnit = new Intl.NumberFormat("de-DE", {
49206    style: "unit",
49207    unit: "degree"
49208  }).resolvedOptions().style === "unit";
49209} catch (e) {
49210}
49211var $488c6ddbf4ef74c2$var$UNITS = {
49212  degree: {
49213    narrow: {
49214      default: "\xB0",
49215      "ja-JP": " \u5EA6",
49216      "zh-TW": "\u5EA6",
49217      "sl-SI": " \xB0"
49218    }
49219  }
49220};
49221var $488c6ddbf4ef74c2$export$cc77c4ff7e8673c5 = class {
49222  /** Formats a number value as a string, according to the locale and options provided to the constructor. */
49223  format(value) {
49224    let res = "";
49225    if (!$488c6ddbf4ef74c2$var$supportsSignDisplay && this.options.signDisplay != null) res = $488c6ddbf4ef74c2$export$711b50b3c525e0f2(this.numberFormatter, this.options.signDisplay, value);
49226    else res = this.numberFormatter.format(value);
49227    if (this.options.style === "unit" && !$488c6ddbf4ef74c2$var$supportsUnit) {
49228      var _UNITS_unit;
49229      let { unit, unitDisplay = "short", locale } = this.resolvedOptions();
49230      if (!unit) return res;
49231      let values = (_UNITS_unit = $488c6ddbf4ef74c2$var$UNITS[unit]) === null || _UNITS_unit === void 0 ? void 0 : _UNITS_unit[unitDisplay];
49232      res += values[locale] || values.default;
49233    }
49234    return res;
49235  }
49236  /** Formats a number to an array of parts such as separators, digits, punctuation, and more. */
49237  formatToParts(value) {
49238    return this.numberFormatter.formatToParts(value);
49239  }
49240  /** Formats a number range as a string. */
49241  formatRange(start, end) {
49242    if (typeof this.numberFormatter.formatRange === "function")
49243      return this.numberFormatter.formatRange(start, end);
49244    if (end < start) throw new RangeError("End date must be >= start date");
49245    return `${this.format(start)} \u2013 ${this.format(end)}`;
49246  }
49247  /** Formats a number range as an array of parts. */
49248  formatRangeToParts(start, end) {
49249    if (typeof this.numberFormatter.formatRangeToParts === "function")
49250      return this.numberFormatter.formatRangeToParts(start, end);
49251    if (end < start) throw new RangeError("End date must be >= start date");
49252    let startParts = this.numberFormatter.formatToParts(start);
49253    let endParts = this.numberFormatter.formatToParts(end);
49254    return [
49255      ...startParts.map((p) => ({
49256        ...p,
49257        source: "startRange"
49258      })),
49259      {
49260        type: "literal",
49261        value: " \u2013 ",
49262        source: "shared"
49263      },
49264      ...endParts.map((p) => ({
49265        ...p,
49266        source: "endRange"
49267      }))
49268    ];
49269  }
49270  /** Returns the resolved formatting options based on the values passed to the constructor. */
49271  resolvedOptions() {
49272    let options = this.numberFormatter.resolvedOptions();
49273    if (!$488c6ddbf4ef74c2$var$supportsSignDisplay && this.options.signDisplay != null) options = {
49274      ...options,
49275      signDisplay: this.options.signDisplay
49276    };
49277    if (!$488c6ddbf4ef74c2$var$supportsUnit && this.options.style === "unit") options = {
49278      ...options,
49279      style: "unit",
49280      unit: this.options.unit,
49281      unitDisplay: this.options.unitDisplay
49282    };
49283    return options;
49284  }
49285  constructor(locale, options = {}) {
49286    this.numberFormatter = $488c6ddbf4ef74c2$var$getCachedNumberFormatter(locale, options);
49287    this.options = options;
49288  }
49289};
49290function $488c6ddbf4ef74c2$var$getCachedNumberFormatter(locale, options = {}) {
49291  let { numberingSystem } = options;
49292  if (numberingSystem && locale.includes("-nu-")) {
49293    if (!locale.includes("-u-")) locale += "-u-";
49294    locale += `-nu-${numberingSystem}`;
49295  }
49296  if (options.style === "unit" && !$488c6ddbf4ef74c2$var$supportsUnit) {
49297    var _UNITS_unit;
49298    let { unit, unitDisplay = "short" } = options;
49299    if (!unit) throw new Error('unit option must be provided with style: "unit"');
49300    if (!((_UNITS_unit = $488c6ddbf4ef74c2$var$UNITS[unit]) === null || _UNITS_unit === void 0 ? void 0 : _UNITS_unit[unitDisplay])) throw new Error(`Unsupported unit ${unit} with unitDisplay = ${unitDisplay}`);
49301    options = {
49302      ...options,
49303      style: "decimal"
49304    };
49305  }
49306  let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : "");
49307  if ($488c6ddbf4ef74c2$var$formatterCache.has(cacheKey)) return $488c6ddbf4ef74c2$var$formatterCache.get(cacheKey);
49308  let numberFormatter = new Intl.NumberFormat(locale, options);
49309  $488c6ddbf4ef74c2$var$formatterCache.set(cacheKey, numberFormatter);
49310  return numberFormatter;
49311}
49312function $488c6ddbf4ef74c2$export$711b50b3c525e0f2(numberFormat, signDisplay, num) {
49313  if (signDisplay === "auto") return numberFormat.format(num);
49314  else if (signDisplay === "never") return numberFormat.format(Math.abs(num));
49315  else {
49316    let needsPositiveSign = false;
49317    if (signDisplay === "always") needsPositiveSign = num > 0 || Object.is(num, 0);
49318    else if (signDisplay === "exceptZero") {
49319      if (Object.is(num, -0) || Object.is(num, 0)) num = Math.abs(num);
49320      else needsPositiveSign = num > 0;
49321    }
49322    if (needsPositiveSign) {
49323      let negative = numberFormat.format(-num);
49324      let noSign = numberFormat.format(num);
49325      let minus = negative.replace(noSign, "").replace(/\u200e|\u061C/, "");
49326      if ([
49327        ...minus
49328      ].length !== 1) console.warn("@react-aria/i18n polyfill for NumberFormat signDisplay: Unsupported case");
49329      let positive = negative.replace(noSign, "!!!").replace(minus, "+").replace("!!!", noSign);
49330      return positive;
49331    } else return numberFormat.format(num);
49332  }
49333}
49334
vendor: 2,852 bytes, lines 49335-49453
49335// node_modules/@kobalte/core/dist/chunk/7TPOQ36Z.js
49336var RTL_SCRIPTS = /* @__PURE__ */ new Set([
49337  "Avst",
49338  "Arab",
49339  "Armi",
49340  "Syrc",
49341  "Samr",
49342  "Mand",
49343  "Thaa",
49344  "Mend",
49345  "Nkoo",
49346  "Adlm",
49347  "Rohg",
49348  "Hebr"
49349]);
49350var RTL_LANGS = /* @__PURE__ */ new Set([
49351  "ae",
49352  "ar",
49353  "arc",
49354  "bcc",
49355  "bqi",
49356  "ckb",
49357  "dv",
49358  "fa",
49359  "glk",
49360  "he",
49361  "ku",
49362  "mzn",
49363  "nqo",
49364  "pnb",
49365  "ps",
49366  "sd",
49367  "ug",
49368  "ur",
49369  "yi"
49370]);
49371function isRTL(locale) {
49372  if (Intl.Locale) {
49373    const script = new Intl.Locale(locale).maximize().script ?? "";
49374    return RTL_SCRIPTS.has(script);
49375  }
49376  const lang = locale.split("-")[0];
49377  return RTL_LANGS.has(lang);
49378}
49379function getReadingDirection(locale) {
49380  return isRTL(locale) ? "rtl" : "ltr";
49381}
49382function getDefaultLocale() {
49383  let locale = typeof navigator !== "undefined" && // @ts-ignore
49384  (navigator.language || navigator.userLanguage) || "en-US";
49385  return {
49386    locale,
49387    direction: getReadingDirection(locale)
49388  };
49389}
49390var currentLocale = getDefaultLocale();
49391var listeners = /* @__PURE__ */ new Set();
49392function updateLocale() {
49393  currentLocale = getDefaultLocale();
49394  for (const listener of listeners) {
49395    listener(currentLocale);
49396  }
49397}
49398function createDefaultLocale() {
49399  const defaultSSRLocale = {
49400    locale: "en-US",
49401    direction: "ltr"
49402  };
49403  const [defaultClientLocale, setDefaultClientLocale] = createSignal(currentLocale);
49404  const defaultLocale = createMemo(
49405    () => isServer ? defaultSSRLocale : defaultClientLocale()
49406  );
49407  onMount(() => {
49408    if (listeners.size === 0) {
49409      window.addEventListener("languagechange", updateLocale);
49410    }
49411    listeners.add(setDefaultClientLocale);
49412    onCleanup(() => {
49413      listeners.delete(setDefaultClientLocale);
49414      if (listeners.size === 0) {
49415        window.removeEventListener("languagechange", updateLocale);
49416      }
49417    });
49418  });
49419  return {
49420    locale: () => defaultLocale().locale,
49421    direction: () => defaultLocale().direction
49422  };
49423}
49424var I18nContext = createContext();
49425function useLocale() {
49426  const defaultLocale = createDefaultLocale();
49427  const context3 = useContext(I18nContext);
49428  return context3 || defaultLocale;
49429}
49430var cache3 = /* @__PURE__ */ new Map();
49431function createCollator(options) {
49432  const { locale } = useLocale();
49433  const cacheKey = createMemo(() => {
49434    return locale() + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : "");
49435  });
49436  return createMemo(() => {
49437    const key = cacheKey();
49438    let collator;
49439    if (cache3.has(key)) {
49440      collator = cache3.get(key);
49441    }
49442    if (!collator) {
49443      collator = new Intl.Collator(locale(), options);
49444      cache3.set(key, collator);
49445    }
49446    return collator;
49447  });
49448}
49449function createNumberFormatter(options) {
49450  const { locale } = useLocale();
49451  return createMemo(() => new $488c6ddbf4ef74c2$export$cc77c4ff7e8673c5(locale(), access4(options)));
49452}
49453
vendor: 3,845 bytes, lines 49454-49588
49454// node_modules/@kobalte/core/dist/chunk/PTVG6YKC.js
49455var MeterContext = createContext();
49456function useMeterContext() {
49457  const context3 = useContext(MeterContext);
49458  if (context3 === void 0) {
49459    throw new Error("[kobalte]: `useMeterContext` must be used within a `Meter.Root` component");
49460  }
49461  return context3;
49462}
49463function MeterFill(props) {
49464  const context3 = useMeterContext();
49465  const [local, others] = splitProps(props, ["style"]);
49466  return createComponent(Polymorphic, mergeProps({
49467    as: "div",
49468    get style() {
49469      return combineStyle({
49470        "--kb-meter-fill-width": context3.meterFillWidth()
49471      }, local.style);
49472    }
49473  }, () => context3.dataset(), others));
49474}
49475function MeterLabel(props) {
49476  const context3 = useMeterContext();
49477  const mergedProps = mergeDefaultProps({
49478    id: context3.generateId("label")
49479  }, props);
49480  const [local, others] = splitProps(mergedProps, ["id"]);
49481  createEffect(() => onCleanup(context3.registerLabelId(local.id)));
49482  return createComponent(Polymorphic, mergeProps({
49483    as: "span",
49484    get id() {
49485      return local.id;
49486    }
49487  }, () => context3.dataset(), others));
49488}
49489function MeterRoot(props) {
49490  const defaultId = `meter-${createUniqueId()}`;
49491  const mergedProps = mergeDefaultProps({
49492    id: defaultId,
49493    value: 0,
49494    minValue: 0,
49495    maxValue: 100,
49496    role: "meter",
49497    indeterminate: false
49498  }, props);
49499  const [local, others] = splitProps(mergedProps, ["value", "minValue", "maxValue", "getValueLabel", "role", "aria-valuetext", "aria-labelledby", "aria-valuemax", "aria-valuemin", "aria-valuenow", "indeterminate"]);
49500  const [labelId, setLabelId] = createSignal();
49501  const defaultFormatter = createNumberFormatter(() => ({
49502    style: "percent"
49503  }));
49504  const value = () => {
49505    return clamp7(local.value, local.minValue, local.maxValue);
49506  };
49507  const valuePercent = () => {
49508    return (value() - local.minValue) / (local.maxValue - local.minValue);
49509  };
49510  const valueLabel = () => {
49511    if (local.indeterminate) {
49512      return void 0;
49513    }
49514    if (local.getValueLabel) {
49515      return local.getValueLabel({
49516        value: value(),
49517        min: local.minValue,
49518        max: local.maxValue
49519      });
49520    }
49521    return defaultFormatter().format(valuePercent());
49522  };
49523  const meterFillWidth = () => {
49524    return `${valuePercent() * 100}%`;
49525  };
49526  const dataset = createMemo(() => {
49527    return {};
49528  });
49529  const context3 = {
49530    dataset,
49531    value,
49532    valuePercent,
49533    valueLabel,
49534    labelId,
49535    meterFillWidth,
49536    generateId: createGenerateId(() => others.id),
49537    registerLabelId: createRegisterId(setLabelId)
49538  };
49539  return createComponent(MeterContext.Provider, {
49540    value: context3,
49541    get children() {
49542      return createComponent(Polymorphic, mergeProps({
49543        as: "div",
49544        get role() {
49545          return local.role || "meter";
49546        },
49547        get ["aria-valuenow"]() {
49548          return memo(() => !!local.indeterminate)() ? void 0 : value();
49549        },
49550        get ["aria-valuemin"]() {
49551          return local.minValue;
49552        },
49553        get ["aria-valuemax"]() {
49554          return local.maxValue;
49555        },
49556        get ["aria-valuetext"]() {
49557          return valueLabel();
49558        },
49559        get ["aria-labelledby"]() {
49560          return labelId();
49561        }
49562      }, dataset, others));
49563    }
49564  });
49565}
49566function MeterTrack(props) {
49567  const context3 = useMeterContext();
49568  return createComponent(Polymorphic, mergeProps({
49569    as: "div"
49570  }, () => context3.dataset(), props));
49571}
49572function MeterValueLabel(props) {
49573  const context3 = useMeterContext();
49574  return createComponent(Polymorphic, mergeProps({
49575    as: "div"
49576  }, () => context3.dataset(), props, {
49577    get children() {
49578      return context3.valueLabel();
49579    }
49580  }));
49581}
49582var Meter = Object.assign(MeterRoot, {
49583  Fill: MeterFill,
49584  Label: MeterLabel,
49585  Track: MeterTrack,
49586  ValueLabel: MeterValueLabel
49587});
49588
vendor: 3,805 bytes, lines 49589-49713
49589// node_modules/@kobalte/core/dist/chunk/JGNXQB3J.js
49590var progress_exports = {};
49591__export(progress_exports, {
49592  Fill: () => ProgressFill,
49593  Label: () => ProgressLabel,
49594  Progress: () => Progress,
49595  Root: () => ProgressRoot,
49596  Track: () => ProgressTrack,
49597  ValueLabel: () => ProgressValueLabel,
49598  useProgressContext: () => useProgressContext
49599});
49600var ProgressContext = createContext();
49601function useProgressContext() {
49602  const context3 = useContext(ProgressContext);
49603  if (context3 === void 0) {
49604    throw new Error("[kobalte]: `useProgressContext` must be used within a `Progress.Root` component");
49605  }
49606  return context3;
49607}
49608function ProgressFill(props) {
49609  const context3 = useProgressContext();
49610  const [local, others] = splitProps(props, ["style"]);
49611  return createComponent(Meter.Fill, mergeProps({
49612    get style() {
49613      return combineStyle({
49614        "--kb-progress-fill-width": context3.progressFillWidth()
49615      }, local.style);
49616    }
49617  }, () => context3.dataset(), others));
49618}
49619function ProgressLabel(props) {
49620  const context3 = useProgressContext();
49621  const mergedProps = mergeDefaultProps({
49622    id: context3.generateId("label")
49623  }, props);
49624  const [local, others] = splitProps(mergedProps, ["id"]);
49625  createEffect(() => onCleanup(context3.registerLabelId(local.id)));
49626  return createComponent(Meter.Label, mergeProps({
49627    get id() {
49628      return local.id;
49629    }
49630  }, () => context3.dataset(), others));
49631}
49632function ProgressRoot(props) {
49633  const defaultId = `progress-${createUniqueId()}`;
49634  const mergedProps = mergeDefaultProps({
49635    id: defaultId,
49636    value: 0,
49637    minValue: 0,
49638    maxValue: 100
49639  }, props);
49640  const [local, others] = splitProps(mergedProps, ["value", "minValue", "maxValue", "indeterminate", "getValueLabel"]);
49641  const [labelId, setLabelId] = createSignal();
49642  const defaultFormatter = createNumberFormatter(() => ({
49643    style: "percent"
49644  }));
49645  const value = () => {
49646    return clamp7(local.value, local.minValue, local.maxValue);
49647  };
49648  const valuePercent = () => {
49649    return (value() - local.minValue) / (local.maxValue - local.minValue);
49650  };
49651  const valueLabel = () => {
49652    if (local.indeterminate) {
49653      return void 0;
49654    }
49655    if (local.getValueLabel) {
49656      return local.getValueLabel({
49657        value: value(),
49658        min: local.minValue,
49659        max: local.maxValue
49660      });
49661    }
49662    return defaultFormatter().format(valuePercent());
49663  };
49664  const progressFillWidth = () => {
49665    return local.indeterminate ? void 0 : `${valuePercent() * 100}%`;
49666  };
49667  const dataset = createMemo(() => {
49668    let dataProgress = void 0;
49669    if (!local.indeterminate) {
49670      dataProgress = valuePercent() === 1 ? "complete" : "loading";
49671    }
49672    return {
49673      "data-progress": dataProgress,
49674      "data-indeterminate": local.indeterminate ? "" : void 0
49675    };
49676  });
49677  const context3 = {
49678    dataset,
49679    value,
49680    valuePercent,
49681    valueLabel,
49682    labelId,
49683    progressFillWidth,
49684    generateId: createGenerateId(() => others.id),
49685    registerLabelId: createRegisterId(setLabelId)
49686  };
49687  return createComponent(ProgressContext.Provider, {
49688    value: context3,
49689    get children() {
49690      return createComponent(Meter, mergeProps({
49691        role: "progressbar",
49692        get indeterminate() {
49693          return local.indeterminate || false;
49694        }
49695      }, dataset, mergedProps));
49696    }
49697  });
49698}
49699function ProgressTrack(props) {
49700  const context3 = useProgressContext();
49701  return createComponent(Meter.Track, mergeProps(() => context3.dataset(), props));
49702}
49703function ProgressValueLabel(props) {
49704  const context3 = useProgressContext();
49705  return createComponent(Meter.ValueLabel, mergeProps(() => context3.dataset(), props));
49706}
49707var Progress = Object.assign(ProgressRoot, {
49708  Fill: ProgressFill,
49709  Label: ProgressLabel,
49710  Track: ProgressTrack,
49711  ValueLabel: ProgressValueLabel
49712});
49713
49714// src/viewer/spinner.jsx
49715var _tmpl$3 = /* @__PURE__ */ template(`<div class="progress__label-container">`);
49716var _tmpl$22 = /* @__PURE__ */ template(`<div class="progress__positioner">`);
49717var Spinner = (props) => {
49718  return createComponent(Dialog, {
49719    open: true,
49720    get children() {
49721      return createComponent(Dialog.Portal, {
49722        get mount() {
49723          return props.root;
49724        },
49725        get children() {
49726          return [createComponent(Dialog.Overlay, {
49727            "class": "progress__overlay"
49728          }), (() => {
49729            const _el$ = _tmpl$22();
49730            insert(_el$, createComponent(Dialog.Content, {
49731              "class": "progress__content",
49732              get children() {
49733                return createComponent(Progress, {
49734                  indeterminate: true,
49735                  "class": "progress",
49736                  get children() {
49737                    return [(() => {
49738                      const _el$2 = _tmpl$3();
49739                      insert(_el$2, createComponent(Progress.Label, {
49740                        "class": "progress__label",
49741                        children: "Loading..."
49742                      }));
49743                      return _el$2;
49744                    })(), createComponent(Progress.Track, {
49745                      "class": "progress__track",
49746                      get children() {
49747                        return createComponent(Progress.Fill, {
49748                          "class": "progress__fill"
49749                        });
49750                      }
49751                    })];
49752                  }
49753                });
49754              }
49755            }));
49756            return _el$;
49757          })()];
49758        }
49759      });
49760    }
49761  });
49762};
49763
49764// src/viewer/alert.jsx
49765var _tmpl$4 = /* @__PURE__ */ template(`<div><div class="alert-dialog__overlay" data-expanded></div><div class="alert-dialog__positioner"><div class="alert-dialog__content" role="alertdialog" id="dialog-cl-3-content" tabindex="-1" data-expanded aria-labelledby="dialog-cl-3-title" aria-describedby="dialog-cl-3-description"><div class="alert-dialog__header"><h2 class="alert-dialog__title" id="dialog-cl-3-title">There's a problem</h2><button class="alert-dialog__close-button" aria-label="Dismiss" type="button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M18.3 5.71a.996.996 0 0 0-1.41 0L12 10.59L7.11 5.7A.996.996 0 1 0 5.7 7.11L10.59 12L5.7 16.89a.996.996 0 1 0 1.41 1.41L12 13.41l4.89 4.89a.996.996 0 1 0 1.41-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z"></path></svg></button></div><p class="alert-dialog__description" id="dialog-cl-3-description">`);
49766var ErrorAlert = (props) => {
49767  const {
49768    problem,
49769    clearProblem
49770  } = useViewer();
49771  return createComponent(Show, {
49772    get when() {
49773      return !!problem();
49774    },
49775    get children() {
49776      const _el$ = _tmpl$4(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling, _el$4 = _el$3.firstChild, _el$5 = _el$4.firstChild, _el$6 = _el$5.firstChild, _el$7 = _el$6.nextSibling, _el$8 = _el$5.nextSibling;
49777      addEventListener(_el$7, "click", clearProblem, true);
49778      insert(_el$8, problem);
49779      return _el$;
49780    }
49781  });
49782};
49783delegateEvents(["click"]);
49784
49785// src/viewer/scenes.jsx
49786var _tmpl$5 = /* @__PURE__ */ template(`<div><select class="scene__select" aria-label="Scene">`);
49787var _tmpl$23 = /* @__PURE__ */ template(`<option>`);
49788var SceneMenu = (props) => {
49789  const {
49790    showTitledScene,
49791    sceneTitle,
49792    setSceneTitle,
49793    sceneTitles
49794  } = useSceneTitles();
49795  const handleChange = (e) => {
49796    const title = e.target.value;
49797    setSceneTitle(title);
49798    showTitledScene(title);
49799  };
49800  return createComponent(Show, {
49801    get when() {
49802      return sceneTitles().length > 1;
49803    },
49804    get children() {
49805      const _el$ = _tmpl$5(), _el$2 = _el$.firstChild;
49806      _el$.style.setProperty("position", "absolute");
49807      _el$.style.setProperty("top", "1em");
49808      _el$.style.setProperty("left", "1em");
49809      _el$2.addEventListener("change", handleChange);
49810      insert(_el$2, createComponent(For, {
49811        get each() {
49812          return sceneTitles();
49813        },
49814        children: (title) => (() => {
49815          const _el$3 = _tmpl$23();
49816          _el$3.value = title;
49817          insert(_el$3, title);
49818          createRenderEffect(() => _el$3.selected = title === sceneTitle());
49819          return _el$3;
49820        })()
49821      }));
49822      return _el$;
49823    }
49824  });
49825};
49826
vendor: 3,426 bytes, lines 49827-49951
49827// node_modules/@floating-ui/core/node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs
49828var sides = ["top", "right", "bottom", "left"];
49829var min3 = Math.min;
49830var max3 = Math.max;
49831var oppositeSideMap = {
49832  left: "right",
49833  right: "left",
49834  bottom: "top",
49835  top: "bottom"
49836};
49837var oppositeAlignmentMap = {
49838  start: "end",
49839  end: "start"
49840};
49841function clamp8(start, value, end) {
49842  return max3(start, min3(value, end));
49843}
49844function evaluate(value, param) {
49845  return typeof value === "function" ? value(param) : value;
49846}
49847function getSide(placement) {
49848  return placement.split("-")[0];
49849}
49850function getAlignment(placement) {
49851  return placement.split("-")[1];
49852}
49853function getOppositeAxis(axis) {
49854  return axis === "x" ? "y" : "x";
49855}
49856function getAxisLength(axis) {
49857  return axis === "y" ? "height" : "width";
49858}
49859function getSideAxis(placement) {
49860  return ["top", "bottom"].includes(getSide(placement)) ? "y" : "x";
49861}
49862function getAlignmentAxis(placement) {
49863  return getOppositeAxis(getSideAxis(placement));
49864}
49865function getAlignmentSides(placement, rects, rtl) {
49866  if (rtl === void 0) {
49867    rtl = false;
49868  }
49869  const alignment = getAlignment(placement);
49870  const alignmentAxis = getAlignmentAxis(placement);
49871  const length3 = getAxisLength(alignmentAxis);
49872  let mainAlignmentSide = alignmentAxis === "x" ? alignment === (rtl ? "end" : "start") ? "right" : "left" : alignment === "start" ? "bottom" : "top";
49873  if (rects.reference[length3] > rects.floating[length3]) {
49874    mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
49875  }
49876  return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];
49877}
49878function getExpandedPlacements(placement) {
49879  const oppositePlacement = getOppositePlacement(placement);
49880  return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
49881}
49882function getOppositeAlignmentPlacement(placement) {
49883  return placement.replace(/start|end/g, (alignment) => oppositeAlignmentMap[alignment]);
49884}
49885function getSideList(side, isStart, rtl) {
49886  const lr = ["left", "right"];
49887  const rl = ["right", "left"];
49888  const tb = ["top", "bottom"];
49889  const bt = ["bottom", "top"];
49890  switch (side) {
49891    case "top":
49892    case "bottom":
49893      if (rtl) return isStart ? rl : lr;
49894      return isStart ? lr : rl;
49895    case "left":
49896    case "right":
49897      return isStart ? tb : bt;
49898    default:
49899      return [];
49900  }
49901}
49902function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {
49903  const alignment = getAlignment(placement);
49904  let list = getSideList(getSide(placement), direction === "start", rtl);
49905  if (alignment) {
49906    list = list.map((side) => side + "-" + alignment);
49907    if (flipAlignment) {
49908      list = list.concat(list.map(getOppositeAlignmentPlacement));
49909    }
49910  }
49911  return list;
49912}
49913function getOppositePlacement(placement) {
49914  return placement.replace(/left|right|bottom|top/g, (side) => oppositeSideMap[side]);
49915}
49916function expandPaddingObject(padding) {
49917  return {
49918    top: 0,
49919    right: 0,
49920    bottom: 0,
49921    left: 0,
49922    ...padding
49923  };
49924}
49925function getPaddingObject(padding) {
49926  return typeof padding !== "number" ? expandPaddingObject(padding) : {
49927    top: padding,
49928    right: padding,
49929    bottom: padding,
49930    left: padding
49931  };
49932}
49933function rectToClientRect(rect) {
49934  const {
49935    x,
49936    y,
49937    width,
49938    height
49939  } = rect;
49940  return {
49941    width,
49942    height,
49943    top: y,
49944    left: x,
49945    right: x + width,
49946    bottom: y + height,
49947    x,
49948    y
49949  };
49950}
49951
vendor: 19,891 bytes, lines 49952-50575
49952// node_modules/@floating-ui/core/dist/floating-ui.core.mjs
49953function computeCoordsFromPlacement(_ref, placement, rtl) {
49954  let {
49955    reference: reference3,
49956    floating
49957  } = _ref;
49958  const sideAxis = getSideAxis(placement);
49959  const alignmentAxis = getAlignmentAxis(placement);
49960  const alignLength = getAxisLength(alignmentAxis);
49961  const side = getSide(placement);
49962  const isVertical = sideAxis === "y";
49963  const commonX = reference3.x + reference3.width / 2 - floating.width / 2;
49964  const commonY = reference3.y + reference3.height / 2 - floating.height / 2;
49965  const commonAlign = reference3[alignLength] / 2 - floating[alignLength] / 2;
49966  let coords;
49967  switch (side) {
49968    case "top":
49969      coords = {
49970        x: commonX,
49971        y: reference3.y - floating.height
49972      };
49973      break;
49974    case "bottom":
49975      coords = {
49976        x: commonX,
49977        y: reference3.y + reference3.height
49978      };
49979      break;
49980    case "right":
49981      coords = {
49982        x: reference3.x + reference3.width,
49983        y: commonY
49984      };
49985      break;
49986    case "left":
49987      coords = {
49988        x: reference3.x - floating.width,
49989        y: commonY
49990      };
49991      break;
49992    default:
49993      coords = {
49994        x: reference3.x,
49995        y: reference3.y
49996      };
49997  }
49998  switch (getAlignment(placement)) {
49999    case "start":
50000      coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
50001      break;
50002    case "end":
50003      coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
50004      break;
50005  }
50006  return coords;
50007}
50008var computePosition = async (reference3, floating, config) => {
50009  const {
50010    placement = "bottom",
50011    strategy = "absolute",
50012    middleware = [],
50013    platform: platform2
50014  } = config;
50015  const validMiddleware = middleware.filter(Boolean);
50016  const rtl = await (platform2.isRTL == null ? void 0 : platform2.isRTL(floating));
50017  let rects = await platform2.getElementRects({
50018    reference: reference3,
50019    floating,
50020    strategy
50021  });
50022  let {
50023    x,
50024    y
50025  } = computeCoordsFromPlacement(rects, placement, rtl);
50026  let statefulPlacement = placement;
50027  let middlewareData = {};
50028  let resetCount = 0;
50029  for (let i = 0; i < validMiddleware.length; i++) {
50030    const {
50031      name,
50032      fn
50033    } = validMiddleware[i];
50034    const {
50035      x: nextX,
50036      y: nextY,
50037      data,
50038      reset
50039    } = await fn({
50040      x,
50041      y,
50042      initialPlacement: placement,
50043      placement: statefulPlacement,
50044      strategy,
50045      middlewareData,
50046      rects,
50047      platform: platform2,
50048      elements: {
50049        reference: reference3,
50050        floating
50051      }
50052    });
50053    x = nextX != null ? nextX : x;
50054    y = nextY != null ? nextY : y;
50055    middlewareData = {
50056      ...middlewareData,
50057      [name]: {
50058        ...middlewareData[name],
50059        ...data
50060      }
50061    };
50062    if (reset && resetCount <= 50) {
50063      resetCount++;
50064      if (typeof reset === "object") {
50065        if (reset.placement) {
50066          statefulPlacement = reset.placement;
50067        }
50068        if (reset.rects) {
50069          rects = reset.rects === true ? await platform2.getElementRects({
50070            reference: reference3,
50071            floating,
50072            strategy
50073          }) : reset.rects;
50074        }
50075        ({
50076          x,
50077          y
50078        } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
50079      }
50080      i = -1;
50081    }
50082  }
50083  return {
50084    x,
50085    y,
50086    placement: statefulPlacement,
50087    strategy,
50088    middlewareData
50089  };
50090};
50091async function detectOverflow(state, options) {
50092  var _await$platform$isEle;
50093  if (options === void 0) {
50094    options = {};
50095  }
50096  const {
50097    x,
50098    y,
50099    platform: platform2,
50100    rects,
50101    elements,
50102    strategy
50103  } = state;
50104  const {
50105    boundary = "clippingAncestors",
50106    rootBoundary = "viewport",
50107    elementContext = "floating",
50108    altBoundary = false,
50109    padding = 0
50110  } = evaluate(options, state);
50111  const paddingObject = getPaddingObject(padding);
50112  const altContext = elementContext === "floating" ? "reference" : "floating";
50113  const element3 = elements[altBoundary ? altContext : elementContext];
50114  const clippingClientRect = rectToClientRect(await platform2.getClippingRect({
50115    element: ((_await$platform$isEle = await (platform2.isElement == null ? void 0 : platform2.isElement(element3))) != null ? _await$platform$isEle : true) ? element3 : element3.contextElement || await (platform2.getDocumentElement == null ? void 0 : platform2.getDocumentElement(elements.floating)),
50116    boundary,
50117    rootBoundary,
50118    strategy
50119  }));
50120  const rect = elementContext === "floating" ? {
50121    x,
50122    y,
50123    width: rects.floating.width,
50124    height: rects.floating.height
50125  } : rects.reference;
50126  const offsetParent = await (platform2.getOffsetParent == null ? void 0 : platform2.getOffsetParent(elements.floating));
50127  const offsetScale = await (platform2.isElement == null ? void 0 : platform2.isElement(offsetParent)) ? await (platform2.getScale == null ? void 0 : platform2.getScale(offsetParent)) || {
50128    x: 1,
50129    y: 1
50130  } : {
50131    x: 1,
50132    y: 1
50133  };
50134  const elementClientRect = rectToClientRect(platform2.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform2.convertOffsetParentRelativeRectToViewportRelativeRect({
50135    elements,
50136    rect,
50137    offsetParent,
50138    strategy
50139  }) : rect);
50140  return {
50141    top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
50142    bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
50143    left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
50144    right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
50145  };
50146}
50147var arrow = (options) => ({
50148  name: "arrow",
50149  options,
50150  async fn(state) {
50151    const {
50152      x,
50153      y,
50154      placement,
50155      rects,
50156      platform: platform2,
50157      elements,
50158      middlewareData
50159    } = state;
50160    const {
50161      element: element3,
50162      padding = 0
50163    } = evaluate(options, state) || {};
50164    if (element3 == null) {
50165      return {};
50166    }
50167    const paddingObject = getPaddingObject(padding);
50168    const coords = {
50169      x,
50170      y
50171    };
50172    const axis = getAlignmentAxis(placement);
50173    const length3 = getAxisLength(axis);
50174    const arrowDimensions = await platform2.getDimensions(element3);
50175    const isYAxis = axis === "y";
50176    const minProp = isYAxis ? "top" : "left";
50177    const maxProp = isYAxis ? "bottom" : "right";
50178    const clientProp = isYAxis ? "clientHeight" : "clientWidth";
50179    const endDiff = rects.reference[length3] + rects.reference[axis] - coords[axis] - rects.floating[length3];
50180    const startDiff = coords[axis] - rects.reference[axis];
50181    const arrowOffsetParent = await (platform2.getOffsetParent == null ? void 0 : platform2.getOffsetParent(element3));
50182    let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;
50183    if (!clientSize || !await (platform2.isElement == null ? void 0 : platform2.isElement(arrowOffsetParent))) {
50184      clientSize = elements.floating[clientProp] || rects.floating[length3];
50185    }
50186    const centerToReference = endDiff / 2 - startDiff / 2;
50187    const largestPossiblePadding = clientSize / 2 - arrowDimensions[length3] / 2 - 1;
50188    const minPadding = min3(paddingObject[minProp], largestPossiblePadding);
50189    const maxPadding = min3(paddingObject[maxProp], largestPossiblePadding);
50190    const min$12 = minPadding;
50191    const max5 = clientSize - arrowDimensions[length3] - maxPadding;
50192    const center = clientSize / 2 - arrowDimensions[length3] / 2 + centerToReference;
50193    const offset3 = clamp8(min$12, center, max5);
50194    const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset3 && rects.reference[length3] / 2 - (center < min$12 ? minPadding : maxPadding) - arrowDimensions[length3] / 2 < 0;
50195    const alignmentOffset = shouldAddOffset ? center < min$12 ? center - min$12 : center - max5 : 0;
50196    return {
50197      [axis]: coords[axis] + alignmentOffset,
50198      data: {
50199        [axis]: offset3,
50200        centerOffset: center - offset3 - alignmentOffset,
50201        ...shouldAddOffset && {
50202          alignmentOffset
50203        }
50204      },
50205      reset: shouldAddOffset
50206    };
50207  }
50208});
50209var flip = function(options) {
50210  if (options === void 0) {
50211    options = {};
50212  }
50213  return {
50214    name: "flip",
50215    options,
50216    async fn(state) {
50217      var _middlewareData$arrow, _middlewareData$flip;
50218      const {
50219        placement,
50220        middlewareData,
50221        rects,
50222        initialPlacement,
50223        platform: platform2,
50224        elements
50225      } = state;
50226      const {
50227        mainAxis: checkMainAxis = true,
50228        crossAxis: checkCrossAxis = true,
50229        fallbackPlacements: specifiedFallbackPlacements,
50230        fallbackStrategy = "bestFit",
50231        fallbackAxisSideDirection = "none",
50232        flipAlignment = true,
50233        ...detectOverflowOptions
50234      } = evaluate(options, state);
50235      if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
50236        return {};
50237      }
50238      const side = getSide(placement);
50239      const isBasePlacement = getSide(initialPlacement) === initialPlacement;
50240      const rtl = await (platform2.isRTL == null ? void 0 : platform2.isRTL(elements.floating));
50241      const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
50242      if (!specifiedFallbackPlacements && fallbackAxisSideDirection !== "none") {
50243        fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
50244      }
50245      const placements2 = [initialPlacement, ...fallbackPlacements];
50246      const overflow = await detectOverflow(state, detectOverflowOptions);
50247      const overflows = [];
50248      let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
50249      if (checkMainAxis) {
50250        overflows.push(overflow[side]);
50251      }
50252      if (checkCrossAxis) {
50253        const sides2 = getAlignmentSides(placement, rects, rtl);
50254        overflows.push(overflow[sides2[0]], overflow[sides2[1]]);
50255      }
50256      overflowsData = [...overflowsData, {
50257        placement,
50258        overflows
50259      }];
50260      if (!overflows.every((side2) => side2 <= 0)) {
50261        var _middlewareData$flip2, _overflowsData$filter;
50262        const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
50263        const nextPlacement = placements2[nextIndex];
50264        if (nextPlacement) {
50265          return {
50266            data: {
50267              index: nextIndex,
50268              overflows: overflowsData
50269            },
50270            reset: {
50271              placement: nextPlacement
50272            }
50273          };
50274        }
50275        let resetPlacement = (_overflowsData$filter = overflowsData.filter((d) => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;
50276        if (!resetPlacement) {
50277          switch (fallbackStrategy) {
50278            case "bestFit": {
50279              var _overflowsData$map$so;
50280              const placement2 = (_overflowsData$map$so = overflowsData.map((d) => [d.placement, d.overflows.filter((overflow2) => overflow2 > 0).reduce((acc, overflow2) => acc + overflow2, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$map$so[0];
50281              if (placement2) {
50282                resetPlacement = placement2;
50283              }
50284              break;
50285            }
50286            case "initialPlacement":
50287              resetPlacement = initialPlacement;
50288              break;
50289          }
50290        }
50291        if (placement !== resetPlacement) {
50292          return {
50293            reset: {
50294              placement: resetPlacement
50295            }
50296          };
50297        }
50298      }
50299      return {};
50300    }
50301  };
50302};
50303function getSideOffsets(overflow, rect) {
50304  return {
50305    top: overflow.top - rect.height,
50306    right: overflow.right - rect.width,
50307    bottom: overflow.bottom - rect.height,
50308    left: overflow.left - rect.width
50309  };
50310}
50311function isAnySideFullyClipped(overflow) {
50312  return sides.some((side) => overflow[side] >= 0);
50313}
50314var hide = function(options) {
50315  if (options === void 0) {
50316    options = {};
50317  }
50318  return {
50319    name: "hide",
50320    options,
50321    async fn(state) {
50322      const {
50323        rects
50324      } = state;
50325      const {
50326        strategy = "referenceHidden",
50327        ...detectOverflowOptions
50328      } = evaluate(options, state);
50329      switch (strategy) {
50330        case "referenceHidden": {
50331          const overflow = await detectOverflow(state, {
50332            ...detectOverflowOptions,
50333            elementContext: "reference"
50334          });
50335          const offsets = getSideOffsets(overflow, rects.reference);
50336          return {
50337            data: {
50338              referenceHiddenOffsets: offsets,
50339              referenceHidden: isAnySideFullyClipped(offsets)
50340            }
50341          };
50342        }
50343        case "escaped": {
50344          const overflow = await detectOverflow(state, {
50345            ...detectOverflowOptions,
50346            altBoundary: true
50347          });
50348          const offsets = getSideOffsets(overflow, rects.floating);
50349          return {
50350            data: {
50351              escapedOffsets: offsets,
50352              escaped: isAnySideFullyClipped(offsets)
50353            }
50354          };
50355        }
50356        default: {
50357          return {};
50358        }
50359      }
50360    }
50361  };
50362};
50363async function convertValueToCoords(state, options) {
50364  const {
50365    placement,
50366    platform: platform2,
50367    elements
50368  } = state;
50369  const rtl = await (platform2.isRTL == null ? void 0 : platform2.isRTL(elements.floating));
50370  const side = getSide(placement);
50371  const alignment = getAlignment(placement);
50372  const isVertical = getSideAxis(placement) === "y";
50373  const mainAxisMulti = ["left", "top"].includes(side) ? -1 : 1;
50374  const crossAxisMulti = rtl && isVertical ? -1 : 1;
50375  const rawValue = evaluate(options, state);
50376  let {
50377    mainAxis,
50378    crossAxis,
50379    alignmentAxis
50380  } = typeof rawValue === "number" ? {
50381    mainAxis: rawValue,
50382    crossAxis: 0,
50383    alignmentAxis: null
50384  } : {
50385    mainAxis: 0,
50386    crossAxis: 0,
50387    alignmentAxis: null,
50388    ...rawValue
50389  };
50390  if (alignment && typeof alignmentAxis === "number") {
50391    crossAxis = alignment === "end" ? alignmentAxis * -1 : alignmentAxis;
50392  }
50393  return isVertical ? {
50394    x: crossAxis * crossAxisMulti,
50395    y: mainAxis * mainAxisMulti
50396  } : {
50397    x: mainAxis * mainAxisMulti,
50398    y: crossAxis * crossAxisMulti
50399  };
50400}
50401var offset = function(options) {
50402  if (options === void 0) {
50403    options = 0;
50404  }
50405  return {
50406    name: "offset",
50407    options,
50408    async fn(state) {
50409      var _middlewareData$offse, _middlewareData$arrow;
50410      const {
50411        x,
50412        y,
50413        placement,
50414        middlewareData
50415      } = state;
50416      const diffCoords = await convertValueToCoords(state, options);
50417      if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
50418        return {};
50419      }
50420      return {
50421        x: x + diffCoords.x,
50422        y: y + diffCoords.y,
50423        data: {
50424          ...diffCoords,
50425          placement
50426        }
50427      };
50428    }
50429  };
50430};
50431var shift = function(options) {
50432  if (options === void 0) {
50433    options = {};
50434  }
50435  return {
50436    name: "shift",
50437    options,
50438    async fn(state) {
50439      const {
50440        x,
50441        y,
50442        placement
50443      } = state;
50444      const {
50445        mainAxis: checkMainAxis = true,
50446        crossAxis: checkCrossAxis = false,
50447        limiter = {
50448          fn: (_ref) => {
50449            let {
50450              x: x2,
50451              y: y2
50452            } = _ref;
50453            return {
50454              x: x2,
50455              y: y2
50456            };
50457          }
50458        },
50459        ...detectOverflowOptions
50460      } = evaluate(options, state);
50461      const coords = {
50462        x,
50463        y
50464      };
50465      const overflow = await detectOverflow(state, detectOverflowOptions);
50466      const crossAxis = getSideAxis(getSide(placement));
50467      const mainAxis = getOppositeAxis(crossAxis);
50468      let mainAxisCoord = coords[mainAxis];
50469      let crossAxisCoord = coords[crossAxis];
50470      if (checkMainAxis) {
50471        const minSide = mainAxis === "y" ? "top" : "left";
50472        const maxSide = mainAxis === "y" ? "bottom" : "right";
50473        const min5 = mainAxisCoord + overflow[minSide];
50474        const max5 = mainAxisCoord - overflow[maxSide];
50475        mainAxisCoord = clamp8(min5, mainAxisCoord, max5);
50476      }
50477      if (checkCrossAxis) {
50478        const minSide = crossAxis === "y" ? "top" : "left";
50479        const maxSide = crossAxis === "y" ? "bottom" : "right";
50480        const min5 = crossAxisCoord + overflow[minSide];
50481        const max5 = crossAxisCoord - overflow[maxSide];
50482        crossAxisCoord = clamp8(min5, crossAxisCoord, max5);
50483      }
50484      const limitedCoords = limiter.fn({
50485        ...state,
50486        [mainAxis]: mainAxisCoord,
50487        [crossAxis]: crossAxisCoord
50488      });
50489      return {
50490        ...limitedCoords,
50491        data: {
50492          x: limitedCoords.x - x,
50493          y: limitedCoords.y - y
50494        }
50495      };
50496    }
50497  };
50498};
50499var size = function(options) {
50500  if (options === void 0) {
50501    options = {};
50502  }
50503  return {
50504    name: "size",
50505    options,
50506    async fn(state) {
50507      const {
50508        placement,
50509        rects,
50510        platform: platform2,
50511        elements
50512      } = state;
50513      const {
50514        apply = () => {
50515        },
50516        ...detectOverflowOptions
50517      } = evaluate(options, state);
50518      const overflow = await detectOverflow(state, detectOverflowOptions);
50519      const side = getSide(placement);
50520      const alignment = getAlignment(placement);
50521      const isYAxis = getSideAxis(placement) === "y";
50522      const {
50523        width,
50524        height
50525      } = rects.floating;
50526      let heightSide;
50527      let widthSide;
50528      if (side === "top" || side === "bottom") {
50529        heightSide = side;
50530        widthSide = alignment === (await (platform2.isRTL == null ? void 0 : platform2.isRTL(elements.floating)) ? "start" : "end") ? "left" : "right";
50531      } else {
50532        widthSide = side;
50533        heightSide = alignment === "end" ? "top" : "bottom";
50534      }
50535      const maximumClippingHeight = height - overflow.top - overflow.bottom;
50536      const maximumClippingWidth = width - overflow.left - overflow.right;
50537      const overflowAvailableHeight = min3(height - overflow[heightSide], maximumClippingHeight);
50538      const overflowAvailableWidth = min3(width - overflow[widthSide], maximumClippingWidth);
50539      const noShift = !state.middlewareData.shift;
50540      let availableHeight = overflowAvailableHeight;
50541      let availableWidth = overflowAvailableWidth;
50542      if (isYAxis) {
50543        availableWidth = alignment || noShift ? min3(overflowAvailableWidth, maximumClippingWidth) : maximumClippingWidth;
50544      } else {
50545        availableHeight = alignment || noShift ? min3(overflowAvailableHeight, maximumClippingHeight) : maximumClippingHeight;
50546      }
50547      if (noShift && !alignment) {
50548        const xMin = max3(overflow.left, 0);
50549        const xMax = max3(overflow.right, 0);
50550        const yMin = max3(overflow.top, 0);
50551        const yMax = max3(overflow.bottom, 0);
50552        if (isYAxis) {
50553          availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max3(overflow.left, overflow.right));
50554        } else {
50555          availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max3(overflow.top, overflow.bottom));
50556        }
50557      }
50558      await apply({
50559        ...state,
50560        availableWidth,
50561        availableHeight
50562      });
50563      const nextDimensions = await platform2.getDimensions(elements.floating);
50564      if (width !== nextDimensions.width || height !== nextDimensions.height) {
50565        return {
50566          reset: {
50567            rects: true
50568          }
50569        };
50570      }
50571      return {};
50572    }
50573  };
50574};
50575
vendor: 233 bytes, lines 50576-50585
50576// node_modules/@floating-ui/dom/node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs
50577var min4 = Math.min;
50578var max4 = Math.max;
50579var round3 = Math.round;
50580var floor3 = Math.floor;
50581var createCoords = (v) => ({
50582  x: v,
50583  y: v
50584});
50585
vendor: 4,506 bytes, lines 50586-50704
50586// node_modules/@floating-ui/dom/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs
50587function getNodeName(node) {
50588  if (isNode(node)) {
50589    return (node.nodeName || "").toLowerCase();
50590  }
50591  return "#document";
50592}
50593function getWindow2(node) {
50594  var _node$ownerDocument;
50595  return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
50596}
50597function getDocumentElement(node) {
50598  var _ref;
50599  return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
50600}
50601function isNode(value) {
50602  return value instanceof Node || value instanceof getWindow2(value).Node;
50603}
50604function isElement(value) {
50605  return value instanceof Element || value instanceof getWindow2(value).Element;
50606}
50607function isHTMLElement(value) {
50608  return value instanceof HTMLElement || value instanceof getWindow2(value).HTMLElement;
50609}
50610function isShadowRoot(value) {
50611  if (typeof ShadowRoot === "undefined") {
50612    return false;
50613  }
50614  return value instanceof ShadowRoot || value instanceof getWindow2(value).ShadowRoot;
50615}
50616function isOverflowElement(element3) {
50617  const {
50618    overflow,
50619    overflowX,
50620    overflowY,
50621    display
50622  } = getComputedStyle2(element3);
50623  return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !["inline", "contents"].includes(display);
50624}
50625function isTableElement(element3) {
50626  return ["table", "td", "th"].includes(getNodeName(element3));
50627}
50628function isContainingBlock(element3) {
50629  const webkit = isWebKit2();
50630  const css = getComputedStyle2(element3);
50631  return css.transform !== "none" || css.perspective !== "none" || (css.containerType ? css.containerType !== "normal" : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== "none" : false) || !webkit && (css.filter ? css.filter !== "none" : false) || ["transform", "perspective", "filter"].some((value) => (css.willChange || "").includes(value)) || ["paint", "layout", "strict", "content"].some((value) => (css.contain || "").includes(value));
50632}
50633function getContainingBlock(element3) {
50634  let currentNode = getParentNode(element3);
50635  while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
50636    if (isContainingBlock(currentNode)) {
50637      return currentNode;
50638    }
50639    currentNode = getParentNode(currentNode);
50640  }
50641  return null;
50642}
50643function isWebKit2() {
50644  if (typeof CSS === "undefined" || !CSS.supports) return false;
50645  return CSS.supports("-webkit-backdrop-filter", "none");
50646}
50647function isLastTraversableNode(node) {
50648  return ["html", "body", "#document"].includes(getNodeName(node));
50649}
50650function getComputedStyle2(element3) {
50651  return getWindow2(element3).getComputedStyle(element3);
50652}
50653function getNodeScroll(element3) {
50654  if (isElement(element3)) {
50655    return {
50656      scrollLeft: element3.scrollLeft,
50657      scrollTop: element3.scrollTop
50658    };
50659  }
50660  return {
50661    scrollLeft: element3.pageXOffset,
50662    scrollTop: element3.pageYOffset
50663  };
50664}
50665function getParentNode(node) {
50666  if (getNodeName(node) === "html") {
50667    return node;
50668  }
50669  const result = (
50670    // Step into the shadow DOM of the parent of a slotted node.
50671    node.assignedSlot || // DOM Element detected.
50672    node.parentNode || // ShadowRoot detected.
50673    isShadowRoot(node) && node.host || // Fallback.
50674    getDocumentElement(node)
50675  );
50676  return isShadowRoot(result) ? result.host : result;
50677}
50678function getNearestOverflowAncestor(node) {
50679  const parentNode = getParentNode(node);
50680  if (isLastTraversableNode(parentNode)) {
50681    return node.ownerDocument ? node.ownerDocument.body : node.body;
50682  }
50683  if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
50684    return parentNode;
50685  }
50686  return getNearestOverflowAncestor(parentNode);
50687}
50688function getOverflowAncestors(node, list, traverseIframes) {
50689  var _node$ownerDocument2;
50690  if (list === void 0) {
50691    list = [];
50692  }
50693  if (traverseIframes === void 0) {
50694    traverseIframes = true;
50695  }
50696  const scrollableAncestor = getNearestOverflowAncestor(node);
50697  const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
50698  const win = getWindow2(scrollableAncestor);
50699  if (isBody) {
50700    return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], win.frameElement && traverseIframes ? getOverflowAncestors(win.frameElement) : []);
50701  }
50702  return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
50703}
50704
vendor: 18,898 bytes, lines 50705-51276
50705// node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs
50706function getCssDimensions(element3) {
50707  const css = getComputedStyle2(element3);
50708  let width = parseFloat(css.width) || 0;
50709  let height = parseFloat(css.height) || 0;
50710  const hasOffset = isHTMLElement(element3);
50711  const offsetWidth = hasOffset ? element3.offsetWidth : width;
50712  const offsetHeight = hasOffset ? element3.offsetHeight : height;
50713  const shouldFallback = round3(width) !== offsetWidth || round3(height) !== offsetHeight;
50714  if (shouldFallback) {
50715    width = offsetWidth;
50716    height = offsetHeight;
50717  }
50718  return {
50719    width,
50720    height,
50721    $: shouldFallback
50722  };
50723}
50724function unwrapElement(element3) {
50725  return !isElement(element3) ? element3.contextElement : element3;
50726}
50727function getScale(element3) {
50728  const domElement = unwrapElement(element3);
50729  if (!isHTMLElement(domElement)) {
50730    return createCoords(1);
50731  }
50732  const rect = domElement.getBoundingClientRect();
50733  const {
50734    width,
50735    height,
50736    $
50737  } = getCssDimensions(domElement);
50738  let x = ($ ? round3(rect.width) : rect.width) / width;
50739  let y = ($ ? round3(rect.height) : rect.height) / height;
50740  if (!x || !Number.isFinite(x)) {
50741    x = 1;
50742  }
50743  if (!y || !Number.isFinite(y)) {
50744    y = 1;
50745  }
50746  return {
50747    x,
50748    y
50749  };
50750}
50751var noOffsets = /* @__PURE__ */ createCoords(0);
50752function getVisualOffsets(element3) {
50753  const win = getWindow2(element3);
50754  if (!isWebKit2() || !win.visualViewport) {
50755    return noOffsets;
50756  }
50757  return {
50758    x: win.visualViewport.offsetLeft,
50759    y: win.visualViewport.offsetTop
50760  };
50761}
50762function shouldAddVisualOffsets(element3, isFixed, floatingOffsetParent) {
50763  if (isFixed === void 0) {
50764    isFixed = false;
50765  }
50766  if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow2(element3)) {
50767    return false;
50768  }
50769  return isFixed;
50770}
50771function getBoundingClientRect(element3, includeScale, isFixedStrategy, offsetParent) {
50772  if (includeScale === void 0) {
50773    includeScale = false;
50774  }
50775  if (isFixedStrategy === void 0) {
50776    isFixedStrategy = false;
50777  }
50778  const clientRect = element3.getBoundingClientRect();
50779  const domElement = unwrapElement(element3);
50780  let scale2 = createCoords(1);
50781  if (includeScale) {
50782    if (offsetParent) {
50783      if (isElement(offsetParent)) {
50784        scale2 = getScale(offsetParent);
50785      }
50786    } else {
50787      scale2 = getScale(element3);
50788    }
50789  }
50790  const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
50791  let x = (clientRect.left + visualOffsets.x) / scale2.x;
50792  let y = (clientRect.top + visualOffsets.y) / scale2.y;
50793  let width = clientRect.width / scale2.x;
50794  let height = clientRect.height / scale2.y;
50795  if (domElement) {
50796    const win = getWindow2(domElement);
50797    const offsetWin = offsetParent && isElement(offsetParent) ? getWindow2(offsetParent) : offsetParent;
50798    let currentWin = win;
50799    let currentIFrame = currentWin.frameElement;
50800    while (currentIFrame && offsetParent && offsetWin !== currentWin) {
50801      const iframeScale = getScale(currentIFrame);
50802      const iframeRect = currentIFrame.getBoundingClientRect();
50803      const css = getComputedStyle2(currentIFrame);
50804      const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
50805      const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
50806      x *= iframeScale.x;
50807      y *= iframeScale.y;
50808      width *= iframeScale.x;
50809      height *= iframeScale.y;
50810      x += left;
50811      y += top;
50812      currentWin = getWindow2(currentIFrame);
50813      currentIFrame = currentWin.frameElement;
50814    }
50815  }
50816  return rectToClientRect({
50817    width,
50818    height,
50819    x,
50820    y
50821  });
50822}
50823var topLayerSelectors = [":popover-open", ":modal"];
50824function isTopLayer(element3) {
50825  return topLayerSelectors.some((selector) => {
50826    try {
50827      return element3.matches(selector);
50828    } catch (e) {
50829      return false;
50830    }
50831  });
50832}
50833function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
50834  let {
50835    elements,
50836    rect,
50837    offsetParent,
50838    strategy
50839  } = _ref;
50840  const isFixed = strategy === "fixed";
50841  const documentElement = getDocumentElement(offsetParent);
50842  const topLayer = elements ? isTopLayer(elements.floating) : false;
50843  if (offsetParent === documentElement || topLayer && isFixed) {
50844    return rect;
50845  }
50846  let scroll = {
50847    scrollLeft: 0,
50848    scrollTop: 0
50849  };
50850  let scale2 = createCoords(1);
50851  const offsets = createCoords(0);
50852  const isOffsetParentAnElement = isHTMLElement(offsetParent);
50853  if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
50854    if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) {
50855      scroll = getNodeScroll(offsetParent);
50856    }
50857    if (isHTMLElement(offsetParent)) {
50858      const offsetRect = getBoundingClientRect(offsetParent);
50859      scale2 = getScale(offsetParent);
50860      offsets.x = offsetRect.x + offsetParent.clientLeft;
50861      offsets.y = offsetRect.y + offsetParent.clientTop;
50862    }
50863  }
50864  return {
50865    width: rect.width * scale2.x,
50866    height: rect.height * scale2.y,
50867    x: rect.x * scale2.x - scroll.scrollLeft * scale2.x + offsets.x,
50868    y: rect.y * scale2.y - scroll.scrollTop * scale2.y + offsets.y
50869  };
50870}
50871function getClientRects(element3) {
50872  return Array.from(element3.getClientRects());
50873}
50874function getWindowScrollBarX(element3) {
50875  return getBoundingClientRect(getDocumentElement(element3)).left + getNodeScroll(element3).scrollLeft;
50876}
50877function getDocumentRect(element3) {
50878  const html = getDocumentElement(element3);
50879  const scroll = getNodeScroll(element3);
50880  const body = element3.ownerDocument.body;
50881  const width = max4(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
50882  const height = max4(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
50883  let x = -scroll.scrollLeft + getWindowScrollBarX(element3);
50884  const y = -scroll.scrollTop;
50885  if (getComputedStyle2(body).direction === "rtl") {
50886    x += max4(html.clientWidth, body.clientWidth) - width;
50887  }
50888  return {
50889    width,
50890    height,
50891    x,
50892    y
50893  };
50894}
50895function getViewportRect(element3, strategy) {
50896  const win = getWindow2(element3);
50897  const html = getDocumentElement(element3);
50898  const visualViewport = win.visualViewport;
50899  let width = html.clientWidth;
50900  let height = html.clientHeight;
50901  let x = 0;
50902  let y = 0;
50903  if (visualViewport) {
50904    width = visualViewport.width;
50905    height = visualViewport.height;
50906    const visualViewportBased = isWebKit2();
50907    if (!visualViewportBased || visualViewportBased && strategy === "fixed") {
50908      x = visualViewport.offsetLeft;
50909      y = visualViewport.offsetTop;
50910    }
50911  }
50912  return {
50913    width,
50914    height,
50915    x,
50916    y
50917  };
50918}
50919function getInnerBoundingClientRect(element3, strategy) {
50920  const clientRect = getBoundingClientRect(element3, true, strategy === "fixed");
50921  const top = clientRect.top + element3.clientTop;
50922  const left = clientRect.left + element3.clientLeft;
50923  const scale2 = isHTMLElement(element3) ? getScale(element3) : createCoords(1);
50924  const width = element3.clientWidth * scale2.x;
50925  const height = element3.clientHeight * scale2.y;
50926  const x = left * scale2.x;
50927  const y = top * scale2.y;
50928  return {
50929    width,
50930    height,
50931    x,
50932    y
50933  };
50934}
50935function getClientRectFromClippingAncestor(element3, clippingAncestor, strategy) {
50936  let rect;
50937  if (clippingAncestor === "viewport") {
50938    rect = getViewportRect(element3, strategy);
50939  } else if (clippingAncestor === "document") {
50940    rect = getDocumentRect(getDocumentElement(element3));
50941  } else if (isElement(clippingAncestor)) {
50942    rect = getInnerBoundingClientRect(clippingAncestor, strategy);
50943  } else {
50944    const visualOffsets = getVisualOffsets(element3);
50945    rect = {
50946      ...clippingAncestor,
50947      x: clippingAncestor.x - visualOffsets.x,
50948      y: clippingAncestor.y - visualOffsets.y
50949    };
50950  }
50951  return rectToClientRect(rect);
50952}
50953function hasFixedPositionAncestor(element3, stopNode) {
50954  const parentNode = getParentNode(element3);
50955  if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
50956    return false;
50957  }
50958  return getComputedStyle2(parentNode).position === "fixed" || hasFixedPositionAncestor(parentNode, stopNode);
50959}
50960function getClippingElementAncestors(element3, cache4) {
50961  const cachedResult = cache4.get(element3);
50962  if (cachedResult) {
50963    return cachedResult;
50964  }
50965  let result = getOverflowAncestors(element3, [], false).filter((el) => isElement(el) && getNodeName(el) !== "body");
50966  let currentContainingBlockComputedStyle = null;
50967  const elementIsFixed = getComputedStyle2(element3).position === "fixed";
50968  let currentNode = elementIsFixed ? getParentNode(element3) : element3;
50969  while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
50970    const computedStyle = getComputedStyle2(currentNode);
50971    const currentNodeIsContaining = isContainingBlock(currentNode);
50972    if (!currentNodeIsContaining && computedStyle.position === "fixed") {
50973      currentContainingBlockComputedStyle = null;
50974    }
50975    const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === "static" && !!currentContainingBlockComputedStyle && ["absolute", "fixed"].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element3, currentNode);
50976    if (shouldDropCurrentNode) {
50977      result = result.filter((ancestor) => ancestor !== currentNode);
50978    } else {
50979      currentContainingBlockComputedStyle = computedStyle;
50980    }
50981    currentNode = getParentNode(currentNode);
50982  }
50983  cache4.set(element3, result);
50984  return result;
50985}
50986function getClippingRect(_ref) {
50987  let {
50988    element: element3,
50989    boundary,
50990    rootBoundary,
50991    strategy
50992  } = _ref;
50993  const elementClippingAncestors = boundary === "clippingAncestors" ? isTopLayer(element3) ? [] : getClippingElementAncestors(element3, this._c) : [].concat(boundary);
50994  const clippingAncestors = [...elementClippingAncestors, rootBoundary];
50995  const firstClippingAncestor = clippingAncestors[0];
50996  const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
50997    const rect = getClientRectFromClippingAncestor(element3, clippingAncestor, strategy);
50998    accRect.top = max4(rect.top, accRect.top);
50999    accRect.right = min4(rect.right, accRect.right);
51000    accRect.bottom = min4(rect.bottom, accRect.bottom);
51001    accRect.left = max4(rect.left, accRect.left);
51002    return accRect;
51003  }, getClientRectFromClippingAncestor(element3, firstClippingAncestor, strategy));
51004  return {
51005    width: clippingRect.right - clippingRect.left,
51006    height: clippingRect.bottom - clippingRect.top,
51007    x: clippingRect.left,
51008    y: clippingRect.top
51009  };
51010}
51011function getDimensions(element3) {
51012  const {
51013    width,
51014    height
51015  } = getCssDimensions(element3);
51016  return {
51017    width,
51018    height
51019  };
51020}
51021function getRectRelativeToOffsetParent(element3, offsetParent, strategy) {
51022  const isOffsetParentAnElement = isHTMLElement(offsetParent);
51023  const documentElement = getDocumentElement(offsetParent);
51024  const isFixed = strategy === "fixed";
51025  const rect = getBoundingClientRect(element3, true, isFixed, offsetParent);
51026  let scroll = {
51027    scrollLeft: 0,
51028    scrollTop: 0
51029  };
51030  const offsets = createCoords(0);
51031  if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
51032    if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) {
51033      scroll = getNodeScroll(offsetParent);
51034    }
51035    if (isOffsetParentAnElement) {
51036      const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
51037      offsets.x = offsetRect.x + offsetParent.clientLeft;
51038      offsets.y = offsetRect.y + offsetParent.clientTop;
51039    } else if (documentElement) {
51040      offsets.x = getWindowScrollBarX(documentElement);
51041    }
51042  }
51043  const x = rect.left + scroll.scrollLeft - offsets.x;
51044  const y = rect.top + scroll.scrollTop - offsets.y;
51045  return {
51046    x,
51047    y,
51048    width: rect.width,
51049    height: rect.height
51050  };
51051}
51052function isStaticPositioned(element3) {
51053  return getComputedStyle2(element3).position === "static";
51054}
51055function getTrueOffsetParent(element3, polyfill) {
51056  if (!isHTMLElement(element3) || getComputedStyle2(element3).position === "fixed") {
51057    return null;
51058  }
51059  if (polyfill) {
51060    return polyfill(element3);
51061  }
51062  return element3.offsetParent;
51063}
51064function getOffsetParent(element3, polyfill) {
51065  const win = getWindow2(element3);
51066  if (isTopLayer(element3)) {
51067    return win;
51068  }
51069  if (!isHTMLElement(element3)) {
51070    let svgOffsetParent = getParentNode(element3);
51071    while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {
51072      if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {
51073        return svgOffsetParent;
51074      }
51075      svgOffsetParent = getParentNode(svgOffsetParent);
51076    }
51077    return win;
51078  }
51079  let offsetParent = getTrueOffsetParent(element3, polyfill);
51080  while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {
51081    offsetParent = getTrueOffsetParent(offsetParent, polyfill);
51082  }
51083  if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {
51084    return win;
51085  }
51086  return offsetParent || getContainingBlock(element3) || win;
51087}
51088var getElementRects = async function(data) {
51089  const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
51090  const getDimensionsFn = this.getDimensions;
51091  const floatingDimensions = await getDimensionsFn(data.floating);
51092  return {
51093    reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
51094    floating: {
51095      x: 0,
51096      y: 0,
51097      width: floatingDimensions.width,
51098      height: floatingDimensions.height
51099    }
51100  };
51101};
51102function isRTL2(element3) {
51103  return getComputedStyle2(element3).direction === "rtl";
51104}
51105var platform = {
51106  convertOffsetParentRelativeRectToViewportRelativeRect,
51107  getDocumentElement,
51108  getClippingRect,
51109  getOffsetParent,
51110  getElementRects,
51111  getClientRects,
51112  getDimensions,
51113  getScale,
51114  isElement,
51115  isRTL: isRTL2
51116};
51117function observeMove(element3, onMove) {
51118  let io = null;
51119  let timeoutId;
51120  const root = getDocumentElement(element3);
51121  function cleanup() {
51122    var _io;
51123    clearTimeout(timeoutId);
51124    (_io = io) == null || _io.disconnect();
51125    io = null;
51126  }
51127  function refresh(skip, threshold) {
51128    if (skip === void 0) {
51129      skip = false;
51130    }
51131    if (threshold === void 0) {
51132      threshold = 1;
51133    }
51134    cleanup();
51135    const {
51136      left,
51137      top,
51138      width,
51139      height
51140    } = element3.getBoundingClientRect();
51141    if (!skip) {
51142      onMove();
51143    }
51144    if (!width || !height) {
51145      return;
51146    }
51147    const insetTop = floor3(top);
51148    const insetRight = floor3(root.clientWidth - (left + width));
51149    const insetBottom = floor3(root.clientHeight - (top + height));
51150    const insetLeft = floor3(left);
51151    const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
51152    const options = {
51153      rootMargin,
51154      threshold: max4(0, min4(1, threshold)) || 1
51155    };
51156    let isFirstUpdate = true;
51157    function handleObserve(entries5) {
51158      const ratio = entries5[0].intersectionRatio;
51159      if (ratio !== threshold) {
51160        if (!isFirstUpdate) {
51161          return refresh();
51162        }
51163        if (!ratio) {
51164          timeoutId = setTimeout(() => {
51165            refresh(false, 1e-7);
51166          }, 1e3);
51167        } else {
51168          refresh(false, ratio);
51169        }
51170      }
51171      isFirstUpdate = false;
51172    }
51173    try {
51174      io = new IntersectionObserver(handleObserve, {
51175        ...options,
51176        // Handle <iframe>s
51177        root: root.ownerDocument
51178      });
51179    } catch (e) {
51180      io = new IntersectionObserver(handleObserve, options);
51181    }
51182    io.observe(element3);
51183  }
51184  refresh(true);
51185  return cleanup;
51186}
51187function autoUpdate(reference3, floating, update, options) {
51188  if (options === void 0) {
51189    options = {};
51190  }
51191  const {
51192    ancestorScroll = true,
51193    ancestorResize = true,
51194    elementResize = typeof ResizeObserver === "function",
51195    layoutShift = typeof IntersectionObserver === "function",
51196    animationFrame = false
51197  } = options;
51198  const referenceEl = unwrapElement(reference3);
51199  const ancestors = ancestorScroll || ancestorResize ? [...referenceEl ? getOverflowAncestors(referenceEl) : [], ...getOverflowAncestors(floating)] : [];
51200  ancestors.forEach((ancestor) => {
51201    ancestorScroll && ancestor.addEventListener("scroll", update, {
51202      passive: true
51203    });
51204    ancestorResize && ancestor.addEventListener("resize", update);
51205  });
51206  const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
51207  let reobserveFrame = -1;
51208  let resizeObserver = null;
51209  if (elementResize) {
51210    resizeObserver = new ResizeObserver((_ref) => {
51211      let [firstEntry] = _ref;
51212      if (firstEntry && firstEntry.target === referenceEl && resizeObserver) {
51213        resizeObserver.unobserve(floating);
51214        cancelAnimationFrame(reobserveFrame);
51215        reobserveFrame = requestAnimationFrame(() => {
51216          var _resizeObserver;
51217          (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
51218        });
51219      }
51220      update();
51221    });
51222    if (referenceEl && !animationFrame) {
51223      resizeObserver.observe(referenceEl);
51224    }
51225    resizeObserver.observe(floating);
51226  }
51227  let frameId3;
51228  let prevRefRect = animationFrame ? getBoundingClientRect(reference3) : null;
51229  if (animationFrame) {
51230    frameLoop();
51231  }
51232  function frameLoop() {
51233    const nextRefRect = getBoundingClientRect(reference3);
51234    if (prevRefRect && (nextRefRect.x !== prevRefRect.x || nextRefRect.y !== prevRefRect.y || nextRefRect.width !== prevRefRect.width || nextRefRect.height !== prevRefRect.height)) {
51235      update();
51236    }
51237    prevRefRect = nextRefRect;
51238    frameId3 = requestAnimationFrame(frameLoop);
51239  }
51240  update();
51241  return () => {
51242    var _resizeObserver2;
51243    ancestors.forEach((ancestor) => {
51244      ancestorScroll && ancestor.removeEventListener("scroll", update);
51245      ancestorResize && ancestor.removeEventListener("resize", update);
51246    });
51247    cleanupIo == null || cleanupIo();
51248    (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
51249    resizeObserver = null;
51250    if (animationFrame) {
51251      cancelAnimationFrame(frameId3);
51252    }
51253  };
51254}
51255var offset2 = offset;
51256var shift2 = shift;
51257var flip2 = flip;
51258var size2 = size;
51259var hide2 = hide;
51260var arrow2 = arrow;
51261var computePosition2 = (reference3, floating, options) => {
51262  const cache4 = /* @__PURE__ */ new Map();
51263  const mergedOptions = {
51264    platform,
51265    ...options
51266  };
51267  const platformWithCache = {
51268    ...mergedOptions.platform,
51269    _c: cache4
51270  };
51271  return computePosition(reference3, floating, {
51272    ...mergedOptions,
51273    platform: platformWithCache
51274  });
51275};
51276
vendor: 10,639 bytes, lines 51277-51602
51277// node_modules/@kobalte/core/dist/chunk/BK63AFY4.js
51278var PopperContext = createContext();
51279function usePopperContext() {
51280  const context3 = useContext(PopperContext);
51281  if (context3 === void 0) {
51282    throw new Error("[kobalte]: `usePopperContext` must be used within a `Popper` component");
51283  }
51284  return context3;
51285}
51286var _tmpl$6 = /* @__PURE__ */ template(`<svg display="block" viewBox="0 0 30 30" style="transform:scale(1.02)"><g><path fill="none" d="M23,27.8c1.1,1.2,3.4,2.2,5,2.2h2H0h2c1.7,0,3.9-1,5-2.2l6.6-7.2c0.7-0.8,2-0.8,2.7,0L23,27.8L23,27.8z"></path><path stroke="none" d="M23,27.8c1.1,1.2,3.4,2.2,5,2.2h2H0h2c1.7,0,3.9-1,5-2.2l6.6-7.2c0.7-0.8,2-0.8,2.7,0L23,27.8L23,27.8z">`);
51287var DEFAULT_SIZE = 30;
51288var HALF_DEFAULT_SIZE = DEFAULT_SIZE / 2;
51289var ROTATION_DEG = {
51290  top: 180,
51291  right: -90,
51292  bottom: 0,
51293  left: 90
51294};
51295function PopperArrow(props) {
51296  const context3 = usePopperContext();
51297  const mergedProps = mergeDefaultProps({
51298    size: DEFAULT_SIZE
51299  }, props);
51300  const [local, others] = splitProps(mergedProps, ["ref", "style", "size"]);
51301  const dir = () => context3.currentPlacement().split("-")[0];
51302  const contentStyle = createComputedStyle(context3.contentRef);
51303  const fill = () => contentStyle()?.getPropertyValue("background-color") || "none";
51304  const stroke = () => contentStyle()?.getPropertyValue(`border-${dir()}-color`) || "none";
51305  const borderWidth = () => contentStyle()?.getPropertyValue(`border-${dir()}-width`) || "0px";
51306  const strokeWidth = () => {
51307    return Number.parseInt(borderWidth()) * 2 * (DEFAULT_SIZE / local.size);
51308  };
51309  const rotate3 = () => {
51310    return `rotate(${ROTATION_DEG[dir()]} ${HALF_DEFAULT_SIZE} ${HALF_DEFAULT_SIZE}) translate(0 2)`;
51311  };
51312  return createComponent(Polymorphic, mergeProps({
51313    as: "div",
51314    ref(r$) {
51315      const _ref$ = mergeRefs(context3.setArrowRef, local.ref);
51316      typeof _ref$ === "function" && _ref$(r$);
51317    },
51318    "aria-hidden": "true",
51319    get style() {
51320      return combineStyle({
51321        // server side rendering
51322        position: "absolute",
51323        "font-size": `${local.size}px`,
51324        width: "1em",
51325        height: "1em",
51326        "pointer-events": "none",
51327        fill: fill(),
51328        stroke: stroke(),
51329        "stroke-width": strokeWidth()
51330      }, local.style);
51331    }
51332  }, others, {
51333    get children() {
51334      const _el$ = _tmpl$6(), _el$2 = _el$.firstChild;
51335      createRenderEffect(() => setAttribute(_el$2, "transform", rotate3()));
51336      return _el$;
51337    }
51338  }));
51339}
51340function createComputedStyle(element3) {
51341  const [style2, setStyle] = createSignal();
51342  createEffect(() => {
51343    const el = element3();
51344    el && setStyle(getWindow(el).getComputedStyle(el));
51345  });
51346  return style2;
51347}
51348function PopperPositioner(props) {
51349  const context3 = usePopperContext();
51350  const [local, others] = splitProps(props, ["ref", "style"]);
51351  return createComponent(Polymorphic, mergeProps({
51352    as: "div",
51353    ref(r$) {
51354      const _ref$ = mergeRefs(context3.setPositionerRef, local.ref);
51355      typeof _ref$ === "function" && _ref$(r$);
51356    },
51357    "data-popper-positioner": "",
51358    get style() {
51359      return combineStyle({
51360        position: "absolute",
51361        top: 0,
51362        left: 0,
51363        "min-width": "max-content"
51364      }, local.style);
51365    }
51366  }, others));
51367}
51368function createDOMRect(anchorRect) {
51369  const { x = 0, y = 0, width = 0, height = 0 } = anchorRect ?? {};
51370  if (typeof DOMRect === "function") {
51371    return new DOMRect(x, y, width, height);
51372  }
51373  const rect = {
51374    x,
51375    y,
51376    width,
51377    height,
51378    top: y,
51379    right: x + width,
51380    bottom: y + height,
51381    left: x
51382  };
51383  return { ...rect, toJSON: () => rect };
51384}
51385function getAnchorElement(anchor, getAnchorRect) {
51386  const contextElement = anchor;
51387  return {
51388    contextElement,
51389    getBoundingClientRect: () => {
51390      const anchorRect = getAnchorRect(anchor);
51391      if (anchorRect) {
51392        return createDOMRect(anchorRect);
51393      }
51394      if (anchor) {
51395        return anchor.getBoundingClientRect();
51396      }
51397      return createDOMRect();
51398    }
51399  };
51400}
51401function isValidPlacement(flip22) {
51402  return /^(?:top|bottom|left|right)(?:-(?:start|end))?$/.test(flip22);
51403}
51404var REVERSE_BASE_PLACEMENT = {
51405  top: "bottom",
51406  right: "left",
51407  bottom: "top",
51408  left: "right"
51409};
51410function getTransformOrigin(placement, readingDirection) {
51411  const [basePlacement, alignment] = placement.split("-");
51412  const reversePlacement = REVERSE_BASE_PLACEMENT[basePlacement];
51413  if (!alignment) {
51414    return `${reversePlacement} center`;
51415  }
51416  if (basePlacement === "left" || basePlacement === "right") {
51417    return `${reversePlacement} ${alignment === "start" ? "top" : "bottom"}`;
51418  }
51419  if (alignment === "start") {
51420    return `${reversePlacement} ${readingDirection === "rtl" ? "right" : "left"}`;
51421  }
51422  return `${reversePlacement} ${readingDirection === "rtl" ? "left" : "right"}`;
51423}
51424function PopperRoot(props) {
51425  const mergedProps = mergeDefaultProps({
51426    getAnchorRect: (anchor) => anchor?.getBoundingClientRect(),
51427    placement: "bottom",
51428    gutter: 0,
51429    shift: 0,
51430    flip: true,
51431    slide: true,
51432    overlap: false,
51433    sameWidth: false,
51434    fitViewport: false,
51435    hideWhenDetached: false,
51436    detachedPadding: 0,
51437    arrowPadding: 4,
51438    overflowPadding: 8
51439  }, props);
51440  const [positionerRef, setPositionerRef] = createSignal();
51441  const [arrowRef, setArrowRef] = createSignal();
51442  const [currentPlacement, setCurrentPlacement] = createSignal(mergedProps.placement);
51443  const anchorRef = () => getAnchorElement(mergedProps.anchorRef?.(), mergedProps.getAnchorRect);
51444  const {
51445    direction
51446  } = useLocale();
51447  async function updatePosition() {
51448    const referenceEl = anchorRef();
51449    const floatingEl = positionerRef();
51450    const arrowEl = arrowRef();
51451    if (!referenceEl || !floatingEl) {
51452      return;
51453    }
51454    const arrowOffset = (arrowEl?.clientHeight || 0) / 2;
51455    const finalGutter = typeof mergedProps.gutter === "number" ? mergedProps.gutter + arrowOffset : mergedProps.gutter ?? arrowOffset;
51456    floatingEl.style.setProperty("--kb-popper-content-overflow-padding", `${mergedProps.overflowPadding}px`);
51457    referenceEl.getBoundingClientRect();
51458    const middleware = [
51459      // https://floating-ui.com/docs/offset
51460      offset2(({
51461        placement
51462      }) => {
51463        const hasAlignment = !!placement.split("-")[1];
51464        return {
51465          mainAxis: finalGutter,
51466          crossAxis: !hasAlignment ? mergedProps.shift : void 0,
51467          alignmentAxis: mergedProps.shift
51468        };
51469      })
51470    ];
51471    if (mergedProps.flip !== false) {
51472      const fallbackPlacements = typeof mergedProps.flip === "string" ? mergedProps.flip.split(" ") : void 0;
51473      if (fallbackPlacements !== void 0 && !fallbackPlacements.every(isValidPlacement)) {
51474        throw new Error("`flip` expects a spaced-delimited list of placements");
51475      }
51476      middleware.push(flip2({
51477        padding: mergedProps.overflowPadding,
51478        fallbackPlacements
51479      }));
51480    }
51481    if (mergedProps.slide || mergedProps.overlap) {
51482      middleware.push(shift2({
51483        mainAxis: mergedProps.slide,
51484        crossAxis: mergedProps.overlap,
51485        padding: mergedProps.overflowPadding
51486      }));
51487    }
51488    middleware.push(size2({
51489      padding: mergedProps.overflowPadding,
51490      apply({
51491        availableWidth,
51492        availableHeight,
51493        rects
51494      }) {
51495        const referenceWidth = Math.round(rects.reference.width);
51496        availableWidth = Math.floor(availableWidth);
51497        availableHeight = Math.floor(availableHeight);
51498        floatingEl.style.setProperty("--kb-popper-anchor-width", `${referenceWidth}px`);
51499        floatingEl.style.setProperty("--kb-popper-content-available-width", `${availableWidth}px`);
51500        floatingEl.style.setProperty("--kb-popper-content-available-height", `${availableHeight}px`);
51501        if (mergedProps.sameWidth) {
51502          floatingEl.style.width = `${referenceWidth}px`;
51503        }
51504        if (mergedProps.fitViewport) {
51505          floatingEl.style.maxWidth = `${availableWidth}px`;
51506          floatingEl.style.maxHeight = `${availableHeight}px`;
51507        }
51508      }
51509    }));
51510    if (mergedProps.hideWhenDetached) {
51511      middleware.push(hide2({
51512        padding: mergedProps.detachedPadding
51513      }));
51514    }
51515    if (arrowEl) {
51516      middleware.push(arrow2({
51517        element: arrowEl,
51518        padding: mergedProps.arrowPadding
51519      }));
51520    }
51521    const pos = await computePosition2(referenceEl, floatingEl, {
51522      placement: mergedProps.placement,
51523      strategy: "absolute",
51524      middleware,
51525      platform: {
51526        ...platform,
51527        isRTL: () => direction() === "rtl"
51528      }
51529    });
51530    setCurrentPlacement(pos.placement);
51531    mergedProps.onCurrentPlacementChange?.(pos.placement);
51532    if (!floatingEl) {
51533      return;
51534    }
51535    floatingEl.style.setProperty("--kb-popper-content-transform-origin", getTransformOrigin(pos.placement, direction()));
51536    const x = Math.round(pos.x);
51537    const y = Math.round(pos.y);
51538    let visibility;
51539    if (mergedProps.hideWhenDetached) {
51540      visibility = pos.middlewareData.hide?.referenceHidden ? "hidden" : "visible";
51541    }
51542    Object.assign(floatingEl.style, {
51543      top: "0",
51544      left: "0",
51545      transform: `translate3d(${x}px, ${y}px, 0)`,
51546      visibility
51547    });
51548    if (arrowEl && pos.middlewareData.arrow) {
51549      const {
51550        x: arrowX,
51551        y: arrowY
51552      } = pos.middlewareData.arrow;
51553      const dir = pos.placement.split("-")[0];
51554      Object.assign(arrowEl.style, {
51555        left: arrowX != null ? `${arrowX}px` : "",
51556        top: arrowY != null ? `${arrowY}px` : "",
51557        [dir]: "100%"
51558      });
51559    }
51560  }
51561  createEffect(() => {
51562    const referenceEl = anchorRef();
51563    const floatingEl = positionerRef();
51564    if (!referenceEl || !floatingEl) {
51565      return;
51566    }
51567    const cleanupAutoUpdate = autoUpdate(referenceEl, floatingEl, updatePosition, {
51568      // JSDOM doesn't support ResizeObserver
51569      elementResize: typeof ResizeObserver === "function"
51570    });
51571    onCleanup(cleanupAutoUpdate);
51572  });
51573  createEffect(() => {
51574    const positioner = positionerRef();
51575    const content = mergedProps.contentRef?.();
51576    if (!positioner || !content) {
51577      return;
51578    }
51579    queueMicrotask(() => {
51580      positioner.style.zIndex = getComputedStyle(content).zIndex;
51581    });
51582  });
51583  const context3 = {
51584    currentPlacement,
51585    contentRef: () => mergedProps.contentRef?.(),
51586    setPositionerRef,
51587    setArrowRef
51588  };
51589  return createComponent(PopperContext.Provider, {
51590    value: context3,
51591    get children() {
51592      return mergedProps.children;
51593    }
51594  });
51595}
51596var Popper = Object.assign(PopperRoot, {
51597  Arrow: PopperArrow,
51598  Context: PopperContext,
51599  usePopperContext,
51600  Positioner: PopperPositioner
51601});
51602
vendor: 13,865 bytes, lines 51603-52054
51603// node_modules/@kobalte/core/dist/chunk/PKWJSNR5.js
51604var tooltip_exports = {};
51605__export(tooltip_exports, {
51606  Arrow: () => PopperArrow,
51607  Content: () => TooltipContent,
51608  Portal: () => TooltipPortal,
51609  Root: () => TooltipRoot,
51610  Tooltip: () => Tooltip,
51611  Trigger: () => TooltipTrigger,
51612  useTooltipContext: () => useTooltipContext
51613});
51614var TooltipContext = createContext();
51615function useTooltipContext() {
51616  const context3 = useContext(TooltipContext);
51617  if (context3 === void 0) {
51618    throw new Error("[kobalte]: `useTooltipContext` must be used within a `Tooltip` component");
51619  }
51620  return context3;
51621}
51622function TooltipContent(props) {
51623  const context3 = useTooltipContext();
51624  const mergedProps = mergeDefaultProps({
51625    id: context3.generateId("content")
51626  }, props);
51627  const [local, others] = splitProps(mergedProps, ["ref", "style"]);
51628  createEffect(() => onCleanup(context3.registerContentId(others.id)));
51629  return createComponent(Show, {
51630    get when() {
51631      return context3.contentPresent();
51632    },
51633    get children() {
51634      return createComponent(Popper.Positioner, {
51635        get children() {
51636          return createComponent(DismissableLayer, mergeProps({
51637            ref(r$) {
51638              const _ref$ = mergeRefs((el) => {
51639                context3.setContentRef(el);
51640              }, local.ref);
51641              typeof _ref$ === "function" && _ref$(r$);
51642            },
51643            role: "tooltip",
51644            disableOutsidePointerEvents: false,
51645            get style() {
51646              return combineStyle({
51647                "--kb-tooltip-content-transform-origin": "var(--kb-popper-content-transform-origin)",
51648                position: "relative"
51649              }, local.style);
51650            },
51651            onFocusOutside: (e) => e.preventDefault(),
51652            onDismiss: () => context3.hideTooltip(true)
51653          }, () => context3.dataset(), others));
51654        }
51655      });
51656    }
51657  });
51658}
51659function TooltipPortal(props) {
51660  const context3 = useTooltipContext();
51661  return createComponent(Show, {
51662    get when() {
51663      return context3.contentPresent();
51664    },
51665    get children() {
51666      return createComponent(Portal, props);
51667    }
51668  });
51669}
51670function getTooltipSafeArea(placement, anchorEl, floatingEl) {
51671  const basePlacement = placement.split("-")[0];
51672  const anchorRect = anchorEl.getBoundingClientRect();
51673  const floatingRect = floatingEl.getBoundingClientRect();
51674  const polygon = [];
51675  const anchorCenterX = anchorRect.left + anchorRect.width / 2;
51676  const anchorCenterY = anchorRect.top + anchorRect.height / 2;
51677  switch (basePlacement) {
51678    case "top":
51679      polygon.push([anchorRect.left, anchorCenterY]);
51680      polygon.push([floatingRect.left, floatingRect.bottom]);
51681      polygon.push([floatingRect.left, floatingRect.top]);
51682      polygon.push([floatingRect.right, floatingRect.top]);
51683      polygon.push([floatingRect.right, floatingRect.bottom]);
51684      polygon.push([anchorRect.right, anchorCenterY]);
51685      break;
51686    case "right":
51687      polygon.push([anchorCenterX, anchorRect.top]);
51688      polygon.push([floatingRect.left, floatingRect.top]);
51689      polygon.push([floatingRect.right, floatingRect.top]);
51690      polygon.push([floatingRect.right, floatingRect.bottom]);
51691      polygon.push([floatingRect.left, floatingRect.bottom]);
51692      polygon.push([anchorCenterX, anchorRect.bottom]);
51693      break;
51694    case "bottom":
51695      polygon.push([anchorRect.left, anchorCenterY]);
51696      polygon.push([floatingRect.left, floatingRect.top]);
51697      polygon.push([floatingRect.left, floatingRect.bottom]);
51698      polygon.push([floatingRect.right, floatingRect.bottom]);
51699      polygon.push([floatingRect.right, floatingRect.top]);
51700      polygon.push([anchorRect.right, anchorCenterY]);
51701      break;
51702    case "left":
51703      polygon.push([anchorCenterX, anchorRect.top]);
51704      polygon.push([floatingRect.right, floatingRect.top]);
51705      polygon.push([floatingRect.left, floatingRect.top]);
51706      polygon.push([floatingRect.left, floatingRect.bottom]);
51707      polygon.push([floatingRect.right, floatingRect.bottom]);
51708      polygon.push([anchorCenterX, anchorRect.bottom]);
51709      break;
51710  }
51711  return polygon;
51712}
51713var tooltips = {};
51714var tooltipsCounter = 0;
51715var globalWarmedUp = false;
51716var globalWarmUpTimeout;
51717var globalCoolDownTimeout;
51718var globalSkipDelayTimeout;
51719function TooltipRoot(props) {
51720  const defaultId = `tooltip-${createUniqueId()}`;
51721  const tooltipId = `${++tooltipsCounter}`;
51722  const mergedProps = mergeDefaultProps({
51723    id: defaultId,
51724    openDelay: 700,
51725    closeDelay: 300,
51726    skipDelayDuration: 300
51727  }, props);
51728  const [local, others] = splitProps(mergedProps, ["id", "open", "defaultOpen", "onOpenChange", "disabled", "triggerOnFocusOnly", "openDelay", "closeDelay", "skipDelayDuration", "ignoreSafeArea", "forceMount", "onCurrentPlacementChange"]);
51729  let closeTimeoutId;
51730  const [contentId, setContentId] = createSignal();
51731  const [triggerRef, setTriggerRef] = createSignal();
51732  const [contentRef, setContentRef] = createSignal();
51733  const [currentPlacement, setCurrentPlacement] = createSignal(others.placement);
51734  const disclosureState = createDisclosureState({
51735    open: () => local.open,
51736    defaultOpen: () => local.defaultOpen,
51737    onOpenChange: (isOpen) => local.onOpenChange?.(isOpen)
51738  });
51739  const {
51740    present: contentPresent
51741  } = index_default2({
51742    show: () => local.forceMount || disclosureState.isOpen(),
51743    element: () => contentRef() ?? null
51744  });
51745  const ensureTooltipEntry = () => {
51746    tooltips[tooltipId] = hideTooltip;
51747  };
51748  const closeOpenTooltips = () => {
51749    for (const hideTooltipId in tooltips) {
51750      if (hideTooltipId !== tooltipId) {
51751        tooltips[hideTooltipId](true);
51752        delete tooltips[hideTooltipId];
51753      }
51754    }
51755  };
51756  const hideTooltip = (immediate = false) => {
51757    if (isServer) {
51758      return;
51759    }
51760    if (immediate || local.closeDelay && local.closeDelay <= 0) {
51761      window.clearTimeout(closeTimeoutId);
51762      closeTimeoutId = void 0;
51763      disclosureState.close();
51764    } else if (!closeTimeoutId) {
51765      closeTimeoutId = window.setTimeout(() => {
51766        closeTimeoutId = void 0;
51767        disclosureState.close();
51768      }, local.closeDelay);
51769    }
51770    window.clearTimeout(globalWarmUpTimeout);
51771    globalWarmUpTimeout = void 0;
51772    if (local.skipDelayDuration && local.skipDelayDuration >= 0) {
51773      globalSkipDelayTimeout = window.setTimeout(() => {
51774        window.clearTimeout(globalSkipDelayTimeout);
51775        globalSkipDelayTimeout = void 0;
51776      }, local.skipDelayDuration);
51777    }
51778    if (globalWarmedUp) {
51779      window.clearTimeout(globalCoolDownTimeout);
51780      globalCoolDownTimeout = window.setTimeout(() => {
51781        delete tooltips[tooltipId];
51782        globalCoolDownTimeout = void 0;
51783        globalWarmedUp = false;
51784      }, local.closeDelay);
51785    }
51786  };
51787  const showTooltip = () => {
51788    if (isServer) {
51789      return;
51790    }
51791    clearTimeout(closeTimeoutId);
51792    closeTimeoutId = void 0;
51793    closeOpenTooltips();
51794    ensureTooltipEntry();
51795    globalWarmedUp = true;
51796    disclosureState.open();
51797    window.clearTimeout(globalWarmUpTimeout);
51798    globalWarmUpTimeout = void 0;
51799    window.clearTimeout(globalCoolDownTimeout);
51800    globalCoolDownTimeout = void 0;
51801    window.clearTimeout(globalSkipDelayTimeout);
51802    globalSkipDelayTimeout = void 0;
51803  };
51804  const warmupTooltip = () => {
51805    if (isServer) {
51806      return;
51807    }
51808    closeOpenTooltips();
51809    ensureTooltipEntry();
51810    if (!disclosureState.isOpen() && !globalWarmUpTimeout && !globalWarmedUp) {
51811      globalWarmUpTimeout = window.setTimeout(() => {
51812        globalWarmUpTimeout = void 0;
51813        globalWarmedUp = true;
51814        showTooltip();
51815      }, local.openDelay);
51816    } else if (!disclosureState.isOpen()) {
51817      showTooltip();
51818    }
51819  };
51820  const openTooltip = (immediate = false) => {
51821    if (isServer) {
51822      return;
51823    }
51824    if (!immediate && local.openDelay && local.openDelay > 0 && !closeTimeoutId && !globalSkipDelayTimeout) {
51825      warmupTooltip();
51826    } else {
51827      showTooltip();
51828    }
51829  };
51830  const cancelOpening = () => {
51831    if (isServer) {
51832      return;
51833    }
51834    window.clearTimeout(globalWarmUpTimeout);
51835    globalWarmUpTimeout = void 0;
51836    globalWarmedUp = false;
51837  };
51838  const cancelClosing = () => {
51839    if (isServer) {
51840      return;
51841    }
51842    window.clearTimeout(closeTimeoutId);
51843    closeTimeoutId = void 0;
51844  };
51845  const isTargetOnTooltip = (target) => {
51846    return contains(triggerRef(), target) || contains(contentRef(), target);
51847  };
51848  const getPolygonSafeArea = (placement) => {
51849    const triggerEl = triggerRef();
51850    const contentEl = contentRef();
51851    if (!triggerEl || !contentEl) {
51852      return;
51853    }
51854    return getTooltipSafeArea(placement, triggerEl, contentEl);
51855  };
51856  const onHoverOutside = (event) => {
51857    const target = event.target;
51858    if (isTargetOnTooltip(target)) {
51859      cancelClosing();
51860      return;
51861    }
51862    if (!local.ignoreSafeArea) {
51863      const polygon = getPolygonSafeArea(currentPlacement());
51864      if (polygon && isPointInPolygon(getEventPoint(event), polygon)) {
51865        cancelClosing();
51866        return;
51867      }
51868    }
51869    if (closeTimeoutId) {
51870      return;
51871    }
51872    hideTooltip();
51873  };
51874  createEffect(() => {
51875    if (isServer) {
51876      return;
51877    }
51878    if (!disclosureState.isOpen()) {
51879      return;
51880    }
51881    const doc = getDocument();
51882    doc.addEventListener("pointermove", onHoverOutside, true);
51883    onCleanup(() => {
51884      doc.removeEventListener("pointermove", onHoverOutside, true);
51885    });
51886  });
51887  createEffect(() => {
51888    const trigger = triggerRef();
51889    if (!trigger || !disclosureState.isOpen()) {
51890      return;
51891    }
51892    const handleScroll = (event) => {
51893      const target = event.target;
51894      if (contains(target, trigger)) {
51895        hideTooltip(true);
51896      }
51897    };
51898    const win = getWindow();
51899    win.addEventListener("scroll", handleScroll, {
51900      capture: true
51901    });
51902    onCleanup(() => {
51903      win.removeEventListener("scroll", handleScroll, {
51904        capture: true
51905      });
51906    });
51907  });
51908  onCleanup(() => {
51909    clearTimeout(closeTimeoutId);
51910    const tooltip = tooltips[tooltipId];
51911    if (tooltip) {
51912      delete tooltips[tooltipId];
51913    }
51914  });
51915  const dataset = createMemo(() => ({
51916    "data-expanded": disclosureState.isOpen() ? "" : void 0,
51917    "data-closed": !disclosureState.isOpen() ? "" : void 0
51918  }));
51919  const context3 = {
51920    dataset,
51921    isOpen: disclosureState.isOpen,
51922    isDisabled: () => local.disabled ?? false,
51923    triggerOnFocusOnly: () => local.triggerOnFocusOnly ?? false,
51924    contentId,
51925    contentPresent,
51926    openTooltip,
51927    hideTooltip,
51928    cancelOpening,
51929    generateId: createGenerateId(() => mergedProps.id),
51930    registerContentId: createRegisterId(setContentId),
51931    isTargetOnTooltip,
51932    setTriggerRef,
51933    setContentRef
51934  };
51935  return createComponent(TooltipContext.Provider, {
51936    value: context3,
51937    get children() {
51938      return createComponent(Popper, mergeProps({
51939        anchorRef: triggerRef,
51940        contentRef,
51941        onCurrentPlacementChange: (value) => {
51942          setCurrentPlacement(value);
51943          local.onCurrentPlacementChange?.(value);
51944        }
51945      }, others));
51946    }
51947  });
51948}
51949function TooltipTrigger(props) {
51950  let ref;
51951  const context3 = useTooltipContext();
51952  const [local, others] = splitProps(props, ["ref", "onPointerEnter", "onPointerLeave", "onPointerDown", "onClick", "onFocus", "onBlur"]);
51953  let isPointerDown = false;
51954  let isHovered = false;
51955  let isFocused = false;
51956  const handlePointerUp = () => {
51957    isPointerDown = false;
51958  };
51959  const handleShow = () => {
51960    if (!context3.isOpen() && (isHovered || isFocused)) {
51961      context3.openTooltip(isFocused);
51962    }
51963  };
51964  const handleHide = (immediate) => {
51965    if (context3.isOpen() && !isHovered && !isFocused) {
51966      context3.hideTooltip(immediate);
51967    }
51968  };
51969  const onPointerEnter = (e) => {
51970    callHandler(e, local.onPointerEnter);
51971    if (e.pointerType === "touch" || context3.triggerOnFocusOnly() || context3.isDisabled() || e.defaultPrevented) {
51972      return;
51973    }
51974    isHovered = true;
51975    handleShow();
51976  };
51977  const onPointerLeave = (e) => {
51978    callHandler(e, local.onPointerLeave);
51979    if (e.pointerType === "touch") {
51980      return;
51981    }
51982    isHovered = false;
51983    isFocused = false;
51984    if (context3.isOpen()) {
51985      handleHide();
51986    } else {
51987      context3.cancelOpening();
51988    }
51989  };
51990  const onPointerDown = (e) => {
51991    callHandler(e, local.onPointerDown);
51992    isPointerDown = true;
51993    getDocument(ref).addEventListener("pointerup", handlePointerUp, {
51994      once: true
51995    });
51996  };
51997  const onClick = (e) => {
51998    callHandler(e, local.onClick);
51999    isHovered = false;
52000    isFocused = false;
52001    handleHide(true);
52002  };
52003  const onFocus = (e) => {
52004    callHandler(e, local.onFocus);
52005    if (context3.isDisabled() || e.defaultPrevented || isPointerDown) {
52006      return;
52007    }
52008    isFocused = true;
52009    handleShow();
52010  };
52011  const onBlur = (e) => {
52012    callHandler(e, local.onBlur);
52013    const relatedTarget = e.relatedTarget;
52014    if (context3.isTargetOnTooltip(relatedTarget)) {
52015      return;
52016    }
52017    isHovered = false;
52018    isFocused = false;
52019    handleHide(true);
52020  };
52021  onCleanup(() => {
52022    if (isServer) {
52023      return;
52024    }
52025    getDocument(ref).removeEventListener("pointerup", handlePointerUp);
52026  });
52027  return createComponent(Polymorphic, mergeProps({
52028    as: "button",
52029    ref(r$) {
52030      const _ref$ = mergeRefs((el) => {
52031        context3.setTriggerRef(el);
52032        ref = el;
52033      }, local.ref);
52034      typeof _ref$ === "function" && _ref$(r$);
52035    },
52036    get ["aria-describedby"]() {
52037      return memo(() => !!context3.isOpen())() ? context3.contentId() : void 0;
52038    },
52039    onPointerEnter,
52040    onPointerLeave,
52041    onPointerDown,
52042    onClick,
52043    onFocus,
52044    onBlur,
52045    type: "button"
52046  }, () => context3.dataset(), others));
52047}
52048var Tooltip = Object.assign(TooltipRoot, {
52049  Arrow: PopperArrow,
52050  Content: TooltipContent,
52051  Portal: TooltipPortal,
52052  Trigger: TooltipTrigger
52053});
52054
52055// src/viewer/iconbutton.jsx
52056var _tmpl$7 = /* @__PURE__ */ template(`<p>`);
52057var IconButton = (props) => {
52058  return createComponent(Tooltip, {
52059    get children() {
52060      return [createComponent(Tooltip.Trigger, {
52061        get ["class"]() {
52062          return `${props.class} corner__icon__button`;
52063        },
52064        get onclick() {
52065          return props.onClick;
52066        },
52067        get children() {
52068          return props.children;
52069        }
52070      }), createComponent(Tooltip.Portal, {
52071        get mount() {
52072          return props.root;
52073        },
52074        get children() {
52075          return createComponent(Tooltip.Content, {
52076            "class": "iconbutton__content",
52077            get children() {
52078              return [createComponent(Tooltip.Arrow, {}), (() => {
52079                const _el$ = _tmpl$7();
52080                insert(_el$, () => props.tooltip);
52081                return _el$;
52082              })()];
52083            }
52084          });
52085        }
52086      })];
52087    }
52088  });
52089};
52090
52091// src/viewer/fullscreen.jsx
52092var _tmpl$8 = /* @__PURE__ */ template(`<svg aria-hidden="true" viewBox="0 0 24 24" focusable="false" data-testid="FullscreenExitIcon"><path d="M0 0h24v24H0z" fill="none"></path><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z">`);
52093var _tmpl$24 = /* @__PURE__ */ template(`<svg aria-hidden="true" viewBox="0 0 24 24" focusable="false" data-testid="FullscreenIcon"><path d="M0 0h24v24H0z" fill="none"></path><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z">`);
52094var FullscreenButton = (props) => {
52095  return createComponent(Show, {
52096    get when() {
52097      return props.fullScreen;
52098    },
52099    get fallback() {
52100      return createComponent(IconButton, {
52101        "class": "fullscreen",
52102        tooltip: "Expand view",
52103        get onClick() {
52104          return props.toggle;
52105        },
52106        get root() {
52107          return props.root;
52108        },
52109        get children() {
52110          return _tmpl$24();
52111        }
52112      });
52113    },
52114    get children() {
52115      return createComponent(IconButton, {
52116        "class": "fullscreen",
52117        tooltip: "Collapse view",
52118        get onClick() {
52119          return props.toggle;
52120        },
52121        get root() {
52122          return props.root;
52123        },
52124        get children() {
52125          return _tmpl$8();
52126        }
52127      });
52128    }
52129  });
52130};
52131
vendor: 935 bytes, lines 52132-52163
52132// node_modules/@kobalte/core/dist/chunk/STGRFJHZ.js
52133var separator_exports = {};
52134__export(separator_exports, {
52135  Root: () => SeparatorRoot,
52136  Separator: () => Separator
52137});
52138function SeparatorRoot(props) {
52139  let ref;
52140  const mergedProps = mergeDefaultProps({
52141    orientation: "horizontal"
52142  }, props);
52143  const [local, others] = splitProps(mergedProps, ["ref", "orientation"]);
52144  const tagName = createTagName(() => ref, () => "hr");
52145  return createComponent(Polymorphic, mergeProps({
52146    as: "hr",
52147    ref(r$) {
52148      const _ref$ = mergeRefs((el) => ref = el, local.ref);
52149      typeof _ref$ === "function" && _ref$(r$);
52150    },
52151    get role() {
52152      return tagName() !== "hr" ? "separator" : void 0;
52153    },
52154    get ["aria-orientation"]() {
52155      return local.orientation === "vertical" ? "vertical" : void 0;
52156    },
52157    get ["data-orientation"]() {
52158      return local.orientation;
52159    }
52160  }, others));
52161}
52162var Separator = SeparatorRoot;
52163
vendor: 3,087 bytes, lines 52164-52272
52164// node_modules/@kobalte/core/dist/chunk/3NGA46QE.js
52165function buildNodes(params) {
52166  let index = params.startIndex ?? 0;
52167  const level = params.startLevel ?? 0;
52168  const nodes = [];
52169  const getKey = (data) => {
52170    if (data == null) {
52171      return "";
52172    }
52173    const _getKey = params.getKey ?? "key";
52174    const dataKey = isString(_getKey) ? data[_getKey] : _getKey(data);
52175    return dataKey != null ? String(dataKey) : "";
52176  };
52177  const getTextValue = (data) => {
52178    if (data == null) {
52179      return "";
52180    }
52181    const _getTextValue = params.getTextValue ?? "textValue";
52182    const dataTextValue = isString(_getTextValue) ? data[_getTextValue] : _getTextValue(data);
52183    return dataTextValue != null ? String(dataTextValue) : "";
52184  };
52185  const getDisabled = (data) => {
52186    if (data == null) {
52187      return false;
52188    }
52189    const _getDisabled = params.getDisabled ?? "disabled";
52190    return (isString(_getDisabled) ? data[_getDisabled] : _getDisabled(data)) ?? false;
52191  };
52192  const getSectionChildren = (data) => {
52193    if (data == null) {
52194      return void 0;
52195    }
52196    if (isString(params.getSectionChildren)) {
52197      return data[params.getSectionChildren];
52198    }
52199    return params.getSectionChildren?.(data);
52200  };
52201  for (const data of params.dataSource) {
52202    if (isString(data) || isNumber(data)) {
52203      nodes.push({
52204        type: "item",
52205        rawValue: data,
52206        key: String(data),
52207        textValue: String(data),
52208        disabled: getDisabled(data),
52209        level,
52210        index
52211      });
52212      index++;
52213      continue;
52214    }
52215    if (getSectionChildren(data) != null) {
52216      nodes.push({
52217        type: "section",
52218        rawValue: data,
52219        key: "",
52220        // not applicable here
52221        textValue: "",
52222        // not applicable here
52223        disabled: false,
52224        // not applicable here
52225        level,
52226        index
52227      });
52228      index++;
52229      const sectionChildren = getSectionChildren(data) ?? [];
52230      if (sectionChildren.length > 0) {
52231        const childNodes = buildNodes({
52232          dataSource: sectionChildren,
52233          getKey: params.getKey,
52234          getTextValue: params.getTextValue,
52235          getDisabled: params.getDisabled,
52236          getSectionChildren: params.getSectionChildren,
52237          startIndex: index,
52238          startLevel: level + 1
52239        });
52240        nodes.push(...childNodes);
52241        index += childNodes.length;
52242      }
52243    } else {
52244      nodes.push({
52245        type: "item",
52246        rawValue: data,
52247        key: getKey(data),
52248        textValue: getTextValue(data),
52249        disabled: getDisabled(data),
52250        level,
52251        index
52252      });
52253      index++;
52254    }
52255  }
52256  return nodes;
52257}
52258function createCollection(props, deps = []) {
52259  return createMemo(() => {
52260    const nodes = buildNodes({
52261      dataSource: access4(props.dataSource),
52262      getKey: access4(props.getKey),
52263      getTextValue: access4(props.getTextValue),
52264      getDisabled: access4(props.getDisabled),
52265      getSectionChildren: access4(props.getSectionChildren)
52266    });
52267    for (let i = 0; i < deps.length; i++)
52268      deps[i]();
52269    return props.factory(nodes);
52270  });
52271}
52272
vendor: 28,977 bytes, lines 52273-53255
52273// node_modules/@kobalte/core/dist/chunk/3D6FM2PJ.js
52274var Selection = class _Selection extends Set {
52275  anchorKey;
52276  currentKey;
52277  constructor(keys5, anchorKey, currentKey) {
52278    super(keys5);
52279    if (keys5 instanceof _Selection) {
52280      this.anchorKey = anchorKey || keys5.anchorKey;
52281      this.currentKey = currentKey || keys5.currentKey;
52282    } else {
52283      this.anchorKey = anchorKey;
52284      this.currentKey = currentKey;
52285    }
52286  }
52287};
52288function createControllableSelectionSignal(props) {
52289  const [_value, setValue] = createControllableSignal(props);
52290  const value = () => _value() ?? new Selection();
52291  return [value, setValue];
52292}
52293function isNonContiguousSelectionModifier(e) {
52294  return isAppleDevice() ? e.altKey : e.ctrlKey;
52295}
52296function isCtrlKeyPressed(e) {
52297  if (isMac()) {
52298    return e.metaKey;
52299  }
52300  return e.ctrlKey;
52301}
52302function convertSelection(selection) {
52303  return new Selection(selection);
52304}
52305function isSameSelection(setA, setB) {
52306  if (setA.size !== setB.size) {
52307    return false;
52308  }
52309  for (const item of setA) {
52310    if (!setB.has(item)) {
52311      return false;
52312    }
52313  }
52314  return true;
52315}
52316function createMultipleSelectionState(props) {
52317  const mergedProps = mergeDefaultProps(
52318    {
52319      selectionMode: "none",
52320      selectionBehavior: "toggle"
52321    },
52322    props
52323  );
52324  const [isFocused, setFocused] = createSignal(false);
52325  const [focusedKey, setFocusedKey] = createSignal();
52326  const selectedKeysProp = createMemo(() => {
52327    const selection = access4(mergedProps.selectedKeys);
52328    if (selection != null) {
52329      return convertSelection(selection);
52330    }
52331    return selection;
52332  });
52333  const defaultSelectedKeys = createMemo(() => {
52334    const defaultSelection = access4(mergedProps.defaultSelectedKeys);
52335    if (defaultSelection != null) {
52336      return convertSelection(defaultSelection);
52337    }
52338    return new Selection();
52339  });
52340  const [selectedKeys, _setSelectedKeys] = createControllableSelectionSignal({
52341    value: selectedKeysProp,
52342    defaultValue: defaultSelectedKeys,
52343    onChange: (value) => mergedProps.onSelectionChange?.(value)
52344  });
52345  const [selectionBehavior, setSelectionBehavior] = createSignal(access4(mergedProps.selectionBehavior));
52346  const selectionMode = () => access4(mergedProps.selectionMode);
52347  const disallowEmptySelection = () => access4(mergedProps.disallowEmptySelection) ?? false;
52348  const setSelectedKeys = (keys5) => {
52349    if (access4(mergedProps.allowDuplicateSelectionEvents) || !isSameSelection(keys5, selectedKeys())) {
52350      _setSelectedKeys(keys5);
52351    }
52352  };
52353  createEffect(() => {
52354    const selection = selectedKeys();
52355    if (access4(mergedProps.selectionBehavior) === "replace" && selectionBehavior() === "toggle" && typeof selection === "object" && selection.size === 0) {
52356      setSelectionBehavior("replace");
52357    }
52358  });
52359  createEffect(() => {
52360    setSelectionBehavior(access4(mergedProps.selectionBehavior) ?? "toggle");
52361  });
52362  return {
52363    selectionMode,
52364    disallowEmptySelection,
52365    selectionBehavior,
52366    setSelectionBehavior,
52367    isFocused,
52368    setFocused,
52369    focusedKey,
52370    setFocusedKey,
52371    selectedKeys,
52372    setSelectedKeys
52373  };
52374}
52375function createTypeSelect(props) {
52376  const [search, setSearch] = createSignal("");
52377  const [timeoutId, setTimeoutId] = createSignal(-1);
52378  const onKeyDown = (e) => {
52379    if (access4(props.isDisabled)) {
52380      return;
52381    }
52382    const delegate = access4(props.keyboardDelegate);
52383    const manager = access4(props.selectionManager);
52384    if (!delegate.getKeyForSearch) {
52385      return;
52386    }
52387    const character = getStringForKey(e.key);
52388    if (!character || e.ctrlKey || e.metaKey) {
52389      return;
52390    }
52391    if (character === " " && search().trim().length > 0) {
52392      e.preventDefault();
52393      e.stopPropagation();
52394    }
52395    let newSearch = setSearch((prev) => prev + character);
52396    let key = delegate.getKeyForSearch(newSearch, manager.focusedKey()) ?? delegate.getKeyForSearch(newSearch);
52397    if (key == null && isAllSameLetter(newSearch)) {
52398      newSearch = newSearch[0];
52399      key = delegate.getKeyForSearch(newSearch, manager.focusedKey()) ?? delegate.getKeyForSearch(newSearch);
52400    }
52401    if (key != null) {
52402      manager.setFocusedKey(key);
52403      props.onTypeSelect?.(key);
52404    }
52405    clearTimeout(timeoutId());
52406    setTimeoutId(window.setTimeout(() => setSearch(""), 500));
52407  };
52408  return {
52409    typeSelectHandlers: {
52410      onKeyDown
52411    }
52412  };
52413}
52414function getStringForKey(key) {
52415  if (key.length === 1 || !/^[A-Z]/i.test(key)) {
52416    return key;
52417  }
52418  return "";
52419}
52420function isAllSameLetter(search) {
52421  return search.split("").every((letter) => letter === search[0]);
52422}
52423function createSelectableCollection(props, ref, scrollRef) {
52424  const defaultProps = {
52425    selectOnFocus: () => access4(props.selectionManager).selectionBehavior() === "replace"
52426  };
52427  const mergedProps = mergeProps(defaultProps, props);
52428  const finalScrollRef = () => scrollRef?.() ?? ref();
52429  const { direction } = useLocale();
52430  let scrollPos = { top: 0, left: 0 };
52431  createEventListener(
52432    () => !access4(mergedProps.isVirtualized) ? finalScrollRef() : void 0,
52433    "scroll",
52434    () => {
52435      const scrollEl = finalScrollRef();
52436      if (!scrollEl) {
52437        return;
52438      }
52439      scrollPos = {
52440        top: scrollEl.scrollTop,
52441        left: scrollEl.scrollLeft
52442      };
52443    }
52444  );
52445  const { typeSelectHandlers } = createTypeSelect({
52446    isDisabled: () => access4(mergedProps.disallowTypeAhead),
52447    keyboardDelegate: () => access4(mergedProps.keyboardDelegate),
52448    selectionManager: () => access4(mergedProps.selectionManager)
52449  });
52450  const orientation = () => access4(mergedProps.orientation) ?? "vertical";
52451  const onKeyDown = (e) => {
52452    callHandler(e, typeSelectHandlers.onKeyDown);
52453    if (e.altKey && e.key === "Tab") {
52454      e.preventDefault();
52455    }
52456    const refEl = ref();
52457    if (!refEl?.contains(e.target)) {
52458      return;
52459    }
52460    const manager = access4(mergedProps.selectionManager);
52461    const selectOnFocus = access4(mergedProps.selectOnFocus);
52462    const navigateToKey = (key) => {
52463      if (key != null) {
52464        manager.setFocusedKey(key);
52465        if (e.shiftKey && manager.selectionMode() === "multiple") {
52466          manager.extendSelection(key);
52467        } else if (selectOnFocus && !isNonContiguousSelectionModifier(e)) {
52468          manager.replaceSelection(key);
52469        }
52470      }
52471    };
52472    const delegate = access4(mergedProps.keyboardDelegate);
52473    const shouldFocusWrap = access4(mergedProps.shouldFocusWrap);
52474    const focusedKey = manager.focusedKey();
52475    switch (e.key) {
52476      case (orientation() === "vertical" ? "ArrowDown" : "ArrowRight"): {
52477        if (delegate.getKeyBelow) {
52478          e.preventDefault();
52479          let nextKey;
52480          if (focusedKey != null) {
52481            nextKey = delegate.getKeyBelow(focusedKey);
52482          } else {
52483            nextKey = delegate.getFirstKey?.();
52484          }
52485          if (nextKey == null && shouldFocusWrap) {
52486            nextKey = delegate.getFirstKey?.(focusedKey);
52487          }
52488          navigateToKey(nextKey);
52489        }
52490        break;
52491      }
52492      case (orientation() === "vertical" ? "ArrowUp" : "ArrowLeft"): {
52493        if (delegate.getKeyAbove) {
52494          e.preventDefault();
52495          let nextKey;
52496          if (focusedKey != null) {
52497            nextKey = delegate.getKeyAbove(focusedKey);
52498          } else {
52499            nextKey = delegate.getLastKey?.();
52500          }
52501          if (nextKey == null && shouldFocusWrap) {
52502            nextKey = delegate.getLastKey?.(focusedKey);
52503          }
52504          navigateToKey(nextKey);
52505        }
52506        break;
52507      }
52508      case (orientation() === "vertical" ? "ArrowLeft" : "ArrowUp"): {
52509        if (delegate.getKeyLeftOf) {
52510          e.preventDefault();
52511          const isRTL3 = direction() === "rtl";
52512          let nextKey;
52513          if (focusedKey != null) {
52514            nextKey = delegate.getKeyLeftOf(focusedKey);
52515          } else {
52516            nextKey = isRTL3 ? delegate.getFirstKey?.() : delegate.getLastKey?.();
52517          }
52518          navigateToKey(nextKey);
52519        }
52520        break;
52521      }
52522      case (orientation() === "vertical" ? "ArrowRight" : "ArrowDown"): {
52523        if (delegate.getKeyRightOf) {
52524          e.preventDefault();
52525          const isRTL3 = direction() === "rtl";
52526          let nextKey;
52527          if (focusedKey != null) {
52528            nextKey = delegate.getKeyRightOf(focusedKey);
52529          } else {
52530            nextKey = isRTL3 ? delegate.getLastKey?.() : delegate.getFirstKey?.();
52531          }
52532          navigateToKey(nextKey);
52533        }
52534        break;
52535      }
52536      case "Home":
52537        if (delegate.getFirstKey) {
52538          e.preventDefault();
52539          const firstKey = delegate.getFirstKey(
52540            focusedKey,
52541            isCtrlKeyPressed(e)
52542          );
52543          if (firstKey != null) {
52544            manager.setFocusedKey(firstKey);
52545            if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode() === "multiple") {
52546              manager.extendSelection(firstKey);
52547            } else if (selectOnFocus) {
52548              manager.replaceSelection(firstKey);
52549            }
52550          }
52551        }
52552        break;
52553      case "End":
52554        if (delegate.getLastKey) {
52555          e.preventDefault();
52556          const lastKey = delegate.getLastKey(focusedKey, isCtrlKeyPressed(e));
52557          if (lastKey != null) {
52558            manager.setFocusedKey(lastKey);
52559            if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode() === "multiple") {
52560              manager.extendSelection(lastKey);
52561            } else if (selectOnFocus) {
52562              manager.replaceSelection(lastKey);
52563            }
52564          }
52565        }
52566        break;
52567      case "PageDown":
52568        if (delegate.getKeyPageBelow && focusedKey != null) {
52569          e.preventDefault();
52570          const nextKey = delegate.getKeyPageBelow(focusedKey);
52571          navigateToKey(nextKey);
52572        }
52573        break;
52574      case "PageUp":
52575        if (delegate.getKeyPageAbove && focusedKey != null) {
52576          e.preventDefault();
52577          const nextKey = delegate.getKeyPageAbove(focusedKey);
52578          navigateToKey(nextKey);
52579        }
52580        break;
52581      case "a":
52582        if (isCtrlKeyPressed(e) && manager.selectionMode() === "multiple" && access4(mergedProps.disallowSelectAll) !== true) {
52583          e.preventDefault();
52584          manager.selectAll();
52585        }
52586        break;
52587      case "Escape":
52588        if (!e.defaultPrevented && !access4(mergedProps.disallowEmptySelection)) {
52589          e.preventDefault();
52590          manager.clearSelection();
52591        }
52592        break;
52593      case "Tab": {
52594        if (!access4(mergedProps.allowsTabNavigation)) {
52595          if (e.shiftKey) {
52596            refEl.focus();
52597          } else {
52598            const walker = getFocusableTreeWalker(refEl, { tabbable: true });
52599            let next;
52600            let last;
52601            do {
52602              last = walker.lastChild();
52603              if (last) {
52604                next = last;
52605              }
52606            } while (last);
52607            if (next && !next.contains(document.activeElement)) {
52608              focusWithoutScrolling(next);
52609            }
52610          }
52611          break;
52612        }
52613      }
52614    }
52615  };
52616  const onFocusIn = (e) => {
52617    const manager = access4(mergedProps.selectionManager);
52618    const delegate = access4(mergedProps.keyboardDelegate);
52619    const selectOnFocus = access4(mergedProps.selectOnFocus);
52620    if (manager.isFocused()) {
52621      if (!e.currentTarget.contains(e.target)) {
52622        manager.setFocused(false);
52623      }
52624      return;
52625    }
52626    if (!e.currentTarget.contains(e.target)) {
52627      return;
52628    }
52629    manager.setFocused(true);
52630    if (manager.focusedKey() == null) {
52631      const navigateToFirstKey = (key) => {
52632        if (key == null) {
52633          return;
52634        }
52635        manager.setFocusedKey(key);
52636        if (selectOnFocus) {
52637          manager.replaceSelection(key);
52638        }
52639      };
52640      const relatedTarget = e.relatedTarget;
52641      if (relatedTarget && e.currentTarget.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING) {
52642        navigateToFirstKey(
52643          manager.lastSelectedKey() ?? delegate.getLastKey?.()
52644        );
52645      } else {
52646        navigateToFirstKey(
52647          manager.firstSelectedKey() ?? delegate.getFirstKey?.()
52648        );
52649      }
52650    } else if (!access4(mergedProps.isVirtualized)) {
52651      const scrollEl = finalScrollRef();
52652      if (scrollEl) {
52653        scrollEl.scrollTop = scrollPos.top;
52654        scrollEl.scrollLeft = scrollPos.left;
52655        const element3 = scrollEl.querySelector(
52656          `[data-key="${manager.focusedKey()}"]`
52657        );
52658        if (element3) {
52659          focusWithoutScrolling(element3);
52660          scrollIntoView(scrollEl, element3);
52661        }
52662      }
52663    }
52664  };
52665  const onFocusOut = (e) => {
52666    const manager = access4(mergedProps.selectionManager);
52667    if (!e.currentTarget.contains(e.relatedTarget)) {
52668      manager.setFocused(false);
52669    }
52670  };
52671  const onMouseDown = (e) => {
52672    if (finalScrollRef() === e.target) {
52673      e.preventDefault();
52674    }
52675  };
52676  const tryAutoFocus = () => {
52677    const autoFocus = access4(mergedProps.autoFocus);
52678    if (!autoFocus) {
52679      return;
52680    }
52681    const manager = access4(mergedProps.selectionManager);
52682    const delegate = access4(mergedProps.keyboardDelegate);
52683    let focusedKey;
52684    if (autoFocus === "first") {
52685      focusedKey = delegate.getFirstKey?.();
52686    }
52687    if (autoFocus === "last") {
52688      focusedKey = delegate.getLastKey?.();
52689    }
52690    const selectedKeys = manager.selectedKeys();
52691    if (selectedKeys.size) {
52692      focusedKey = selectedKeys.values().next().value;
52693    }
52694    manager.setFocused(true);
52695    manager.setFocusedKey(focusedKey);
52696    const refEl = ref();
52697    if (refEl && focusedKey == null && !access4(mergedProps.shouldUseVirtualFocus)) {
52698      focusWithoutScrolling(refEl);
52699    }
52700  };
52701  onMount(() => {
52702    if (mergedProps.deferAutoFocus) {
52703      setTimeout(tryAutoFocus, 0);
52704    } else {
52705      tryAutoFocus();
52706    }
52707  });
52708  createEffect(
52709    on(
52710      [
52711        finalScrollRef,
52712        () => access4(mergedProps.isVirtualized),
52713        () => access4(mergedProps.selectionManager).focusedKey()
52714      ],
52715      (newValue) => {
52716        const [scrollEl, isVirtualized, focusedKey] = newValue;
52717        if (isVirtualized) {
52718          focusedKey && mergedProps.scrollToKey?.(focusedKey);
52719        } else {
52720          if (focusedKey && scrollEl) {
52721            const element3 = scrollEl.querySelector(
52722              `[data-key="${focusedKey}"]`
52723            );
52724            if (element3) {
52725              scrollIntoView(scrollEl, element3);
52726            }
52727          }
52728        }
52729      }
52730    )
52731  );
52732  const tabIndex = createMemo(() => {
52733    if (access4(mergedProps.shouldUseVirtualFocus)) {
52734      return void 0;
52735    }
52736    return access4(mergedProps.selectionManager).focusedKey() == null ? 0 : -1;
52737  });
52738  return {
52739    tabIndex,
52740    onKeyDown,
52741    onMouseDown,
52742    onFocusIn,
52743    onFocusOut
52744  };
52745}
52746function createSelectableItem(props, ref) {
52747  const manager = () => access4(props.selectionManager);
52748  const key = () => access4(props.key);
52749  const shouldUseVirtualFocus = () => access4(props.shouldUseVirtualFocus);
52750  const onSelect = (e) => {
52751    if (manager().selectionMode() === "none") {
52752      return;
52753    }
52754    if (manager().selectionMode() === "single") {
52755      if (manager().isSelected(key()) && !manager().disallowEmptySelection()) {
52756        manager().toggleSelection(key());
52757      } else {
52758        manager().replaceSelection(key());
52759      }
52760    } else if (e?.shiftKey) {
52761      manager().extendSelection(key());
52762    } else if (manager().selectionBehavior() === "toggle" || isCtrlKeyPressed(e) || "pointerType" in e && e.pointerType === "touch") {
52763      manager().toggleSelection(key());
52764    } else {
52765      manager().replaceSelection(key());
52766    }
52767  };
52768  const isSelected = () => manager().isSelected(key());
52769  const isDisabled = () => access4(props.disabled) || manager().isDisabled(key());
52770  const allowsSelection = () => !isDisabled() && manager().canSelectItem(key());
52771  let pointerDownType = null;
52772  const onPointerDown = (e) => {
52773    if (!allowsSelection()) {
52774      return;
52775    }
52776    pointerDownType = e.pointerType;
52777    if (e.pointerType === "mouse" && e.button === 0 && !access4(props.shouldSelectOnPressUp)) {
52778      onSelect(e);
52779    }
52780  };
52781  const onPointerUp = (e) => {
52782    if (!allowsSelection()) {
52783      return;
52784    }
52785    if (e.pointerType === "mouse" && e.button === 0 && access4(props.shouldSelectOnPressUp) && access4(props.allowsDifferentPressOrigin)) {
52786      onSelect(e);
52787    }
52788  };
52789  const onClick = (e) => {
52790    if (!allowsSelection()) {
52791      return;
52792    }
52793    if (access4(props.shouldSelectOnPressUp) && !access4(props.allowsDifferentPressOrigin) || pointerDownType !== "mouse") {
52794      onSelect(e);
52795    }
52796  };
52797  const onKeyDown = (e) => {
52798    if (!allowsSelection() || !["Enter", " "].includes(e.key)) {
52799      return;
52800    }
52801    if (isNonContiguousSelectionModifier(e)) {
52802      manager().toggleSelection(key());
52803    } else {
52804      onSelect(e);
52805    }
52806  };
52807  const onMouseDown = (e) => {
52808    if (isDisabled()) {
52809      e.preventDefault();
52810    }
52811  };
52812  const onFocus = (e) => {
52813    const refEl = ref();
52814    if (shouldUseVirtualFocus() || isDisabled() || !refEl) {
52815      return;
52816    }
52817    if (e.target === refEl) {
52818      manager().setFocusedKey(key());
52819    }
52820  };
52821  const tabIndex = createMemo(() => {
52822    if (shouldUseVirtualFocus() || isDisabled()) {
52823      return void 0;
52824    }
52825    return key() === manager().focusedKey() ? 0 : -1;
52826  });
52827  const dataKey = createMemo(() => {
52828    return access4(props.virtualized) ? void 0 : key();
52829  });
52830  createEffect(
52831    on(
52832      [
52833        ref,
52834        key,
52835        shouldUseVirtualFocus,
52836        () => manager().focusedKey(),
52837        () => manager().isFocused()
52838      ],
52839      ([refEl, key2, shouldUseVirtualFocus2, focusedKey, isFocused]) => {
52840        if (refEl && key2 === focusedKey && isFocused && !shouldUseVirtualFocus2 && document.activeElement !== refEl) {
52841          if (props.focus) {
52842            props.focus();
52843          } else {
52844            focusWithoutScrolling(refEl);
52845          }
52846        }
52847      }
52848    )
52849  );
52850  return {
52851    isSelected,
52852    isDisabled,
52853    allowsSelection,
52854    tabIndex,
52855    dataKey,
52856    onPointerDown,
52857    onPointerUp,
52858    onClick,
52859    onKeyDown,
52860    onMouseDown,
52861    onFocus
52862  };
52863}
52864var SelectionManager = class {
52865  collection;
52866  state;
52867  constructor(collection, state) {
52868    this.collection = collection;
52869    this.state = state;
52870  }
52871  /** The type of selection that is allowed in the collection. */
52872  selectionMode() {
52873    return this.state.selectionMode();
52874  }
52875  /** Whether the collection allows empty selection. */
52876  disallowEmptySelection() {
52877    return this.state.disallowEmptySelection();
52878  }
52879  /** The selection behavior for the collection. */
52880  selectionBehavior() {
52881    return this.state.selectionBehavior();
52882  }
52883  /** Sets the selection behavior for the collection. */
52884  setSelectionBehavior(selectionBehavior) {
52885    this.state.setSelectionBehavior(selectionBehavior);
52886  }
52887  /** Whether the collection is currently focused. */
52888  isFocused() {
52889    return this.state.isFocused();
52890  }
52891  /** Sets whether the collection is focused. */
52892  setFocused(isFocused) {
52893    this.state.setFocused(isFocused);
52894  }
52895  /** The current focused key in the collection. */
52896  focusedKey() {
52897    return this.state.focusedKey();
52898  }
52899  /** Sets the focused key. */
52900  setFocusedKey(key) {
52901    if (key == null || this.collection().getItem(key)) {
52902      this.state.setFocusedKey(key);
52903    }
52904  }
52905  /** The currently selected keys in the collection. */
52906  selectedKeys() {
52907    return this.state.selectedKeys();
52908  }
52909  /** Returns whether a key is selected. */
52910  isSelected(key) {
52911    if (this.state.selectionMode() === "none") {
52912      return false;
52913    }
52914    const retrievedKey = this.getKey(key);
52915    if (retrievedKey == null) {
52916      return false;
52917    }
52918    return this.state.selectedKeys().has(retrievedKey);
52919  }
52920  /** Whether the selection is empty. */
52921  isEmpty() {
52922    return this.state.selectedKeys().size === 0;
52923  }
52924  /** Whether all items in the collection are selected. */
52925  isSelectAll() {
52926    if (this.isEmpty()) {
52927      return false;
52928    }
52929    const selectedKeys = this.state.selectedKeys();
52930    return this.getAllSelectableKeys().every((k) => selectedKeys.has(k));
52931  }
52932  firstSelectedKey() {
52933    let first;
52934    for (const key of this.state.selectedKeys()) {
52935      const item = this.collection().getItem(key);
52936      const isItemBeforeFirst = item?.index != null && first?.index != null && item.index < first.index;
52937      if (!first || isItemBeforeFirst) {
52938        first = item;
52939      }
52940    }
52941    return first?.key;
52942  }
52943  lastSelectedKey() {
52944    let last;
52945    for (const key of this.state.selectedKeys()) {
52946      const item = this.collection().getItem(key);
52947      const isItemAfterLast = item?.index != null && last?.index != null && item.index > last.index;
52948      if (!last || isItemAfterLast) {
52949        last = item;
52950      }
52951    }
52952    return last?.key;
52953  }
52954  /** Extends the selection to the given key. */
52955  extendSelection(toKey) {
52956    if (this.selectionMode() === "none") {
52957      return;
52958    }
52959    if (this.selectionMode() === "single") {
52960      this.replaceSelection(toKey);
52961      return;
52962    }
52963    const retrievedToKey = this.getKey(toKey);
52964    if (retrievedToKey == null) {
52965      return;
52966    }
52967    const selectedKeys = this.state.selectedKeys();
52968    const anchorKey = selectedKeys.anchorKey || retrievedToKey;
52969    const selection = new Selection(selectedKeys, anchorKey, retrievedToKey);
52970    for (const key of this.getKeyRange(
52971      anchorKey,
52972      selectedKeys.currentKey || retrievedToKey
52973    )) {
52974      selection.delete(key);
52975    }
52976    for (const key of this.getKeyRange(retrievedToKey, anchorKey)) {
52977      if (this.canSelectItem(key)) {
52978        selection.add(key);
52979      }
52980    }
52981    this.state.setSelectedKeys(selection);
52982  }
52983  getKeyRange(from, to) {
52984    const fromItem = this.collection().getItem(from);
52985    const toItem = this.collection().getItem(to);
52986    if (fromItem && toItem) {
52987      if (fromItem.index != null && toItem.index != null && fromItem.index <= toItem.index) {
52988        return this.getKeyRangeInternal(from, to);
52989      }
52990      return this.getKeyRangeInternal(to, from);
52991    }
52992    return [];
52993  }
52994  getKeyRangeInternal(from, to) {
52995    const keys5 = [];
52996    let key = from;
52997    while (key != null) {
52998      const item = this.collection().getItem(key);
52999      if (item && item.type === "item") {
53000        keys5.push(key);
53001      }
53002      if (key === to) {
53003        return keys5;
53004      }
53005      key = this.collection().getKeyAfter(key);
53006    }
53007    return [];
53008  }
53009  getKey(key) {
53010    const item = this.collection().getItem(key);
53011    if (!item) {
53012      return key;
53013    }
53014    if (!item || item.type !== "item") {
53015      return null;
53016    }
53017    return item.key;
53018  }
53019  /** Toggles whether the given key is selected. */
53020  toggleSelection(key) {
53021    if (this.selectionMode() === "none") {
53022      return;
53023    }
53024    if (this.selectionMode() === "single" && !this.isSelected(key)) {
53025      this.replaceSelection(key);
53026      return;
53027    }
53028    const retrievedKey = this.getKey(key);
53029    if (retrievedKey == null) {
53030      return;
53031    }
53032    const keys5 = new Selection(this.state.selectedKeys());
53033    if (keys5.has(retrievedKey)) {
53034      keys5.delete(retrievedKey);
53035    } else if (this.canSelectItem(retrievedKey)) {
53036      keys5.add(retrievedKey);
53037      keys5.anchorKey = retrievedKey;
53038      keys5.currentKey = retrievedKey;
53039    }
53040    if (this.disallowEmptySelection() && keys5.size === 0) {
53041      return;
53042    }
53043    this.state.setSelectedKeys(keys5);
53044  }
53045  /** Replaces the selection with only the given key. */
53046  replaceSelection(key) {
53047    if (this.selectionMode() === "none") {
53048      return;
53049    }
53050    const retrievedKey = this.getKey(key);
53051    if (retrievedKey == null) {
53052      return;
53053    }
53054    const selection = this.canSelectItem(retrievedKey) ? new Selection([retrievedKey], retrievedKey, retrievedKey) : new Selection();
53055    this.state.setSelectedKeys(selection);
53056  }
53057  /** Replaces the selection with the given keys. */
53058  setSelectedKeys(keys5) {
53059    if (this.selectionMode() === "none") {
53060      return;
53061    }
53062    const selection = new Selection();
53063    for (const key of keys5) {
53064      const retrievedKey = this.getKey(key);
53065      if (retrievedKey != null) {
53066        selection.add(retrievedKey);
53067        if (this.selectionMode() === "single") {
53068          break;
53069        }
53070      }
53071    }
53072    this.state.setSelectedKeys(selection);
53073  }
53074  /** Selects all items in the collection. */
53075  selectAll() {
53076    if (this.selectionMode() === "multiple") {
53077      this.state.setSelectedKeys(new Set(this.getAllSelectableKeys()));
53078    }
53079  }
53080  /**
53081   * Removes all keys from the selection.
53082   */
53083  clearSelection() {
53084    const selectedKeys = this.state.selectedKeys();
53085    if (!this.disallowEmptySelection() && selectedKeys.size > 0) {
53086      this.state.setSelectedKeys(new Selection());
53087    }
53088  }
53089  /**
53090   * Toggles between select all and an empty selection.
53091   */
53092  toggleSelectAll() {
53093    if (this.isSelectAll()) {
53094      this.clearSelection();
53095    } else {
53096      this.selectAll();
53097    }
53098  }
53099  select(key, e) {
53100    if (this.selectionMode() === "none") {
53101      return;
53102    }
53103    if (this.selectionMode() === "single") {
53104      if (this.isSelected(key) && !this.disallowEmptySelection()) {
53105        this.toggleSelection(key);
53106      } else {
53107        this.replaceSelection(key);
53108      }
53109    } else if (this.selectionBehavior() === "toggle" || e && e.pointerType === "touch") {
53110      this.toggleSelection(key);
53111    } else {
53112      this.replaceSelection(key);
53113    }
53114  }
53115  /** Returns whether the current selection is equal to the given selection. */
53116  isSelectionEqual(selection) {
53117    if (selection === this.state.selectedKeys()) {
53118      return true;
53119    }
53120    const selectedKeys = this.selectedKeys();
53121    if (selection.size !== selectedKeys.size) {
53122      return false;
53123    }
53124    for (const key of selection) {
53125      if (!selectedKeys.has(key)) {
53126        return false;
53127      }
53128    }
53129    for (const key of selectedKeys) {
53130      if (!selection.has(key)) {
53131        return false;
53132      }
53133    }
53134    return true;
53135  }
53136  canSelectItem(key) {
53137    if (this.state.selectionMode() === "none") {
53138      return false;
53139    }
53140    const item = this.collection().getItem(key);
53141    return item != null && !item.disabled;
53142  }
53143  isDisabled(key) {
53144    const item = this.collection().getItem(key);
53145    return !item || item.disabled;
53146  }
53147  getAllSelectableKeys() {
53148    const keys5 = [];
53149    const addKeys = (key) => {
53150      while (key != null) {
53151        if (this.canSelectItem(key)) {
53152          const item = this.collection().getItem(key);
53153          if (!item) {
53154            continue;
53155          }
53156          if (item.type === "item") {
53157            keys5.push(key);
53158          }
53159        }
53160        key = this.collection().getKeyAfter(key);
53161      }
53162    };
53163    addKeys(this.collection().getFirstKey());
53164    return keys5;
53165  }
53166};
53167var ListCollection = class {
53168  keyMap = /* @__PURE__ */ new Map();
53169  iterable;
53170  firstKey;
53171  lastKey;
53172  constructor(nodes) {
53173    this.iterable = nodes;
53174    for (const node of nodes) {
53175      this.keyMap.set(node.key, node);
53176    }
53177    if (this.keyMap.size === 0) {
53178      return;
53179    }
53180    let last;
53181    let index = 0;
53182    for (const [key, node] of this.keyMap) {
53183      if (last) {
53184        last.nextKey = key;
53185        node.prevKey = last.key;
53186      } else {
53187        this.firstKey = key;
53188        node.prevKey = void 0;
53189      }
53190      if (node.type === "item") {
53191        node.index = index++;
53192      }
53193      last = node;
53194      last.nextKey = void 0;
53195    }
53196    this.lastKey = last.key;
53197  }
53198  *[Symbol.iterator]() {
53199    yield* this.iterable;
53200  }
53201  getSize() {
53202    return this.keyMap.size;
53203  }
53204  getKeys() {
53205    return this.keyMap.keys();
53206  }
53207  getKeyBefore(key) {
53208    return this.keyMap.get(key)?.prevKey;
53209  }
53210  getKeyAfter(key) {
53211    return this.keyMap.get(key)?.nextKey;
53212  }
53213  getFirstKey() {
53214    return this.firstKey;
53215  }
53216  getLastKey() {
53217    return this.lastKey;
53218  }
53219  getItem(key) {
53220    return this.keyMap.get(key);
53221  }
53222  at(idx) {
53223    const keys5 = [...this.getKeys()];
53224    return this.getItem(keys5[idx]);
53225  }
53226};
53227function createListState(props) {
53228  const selectionState = createMultipleSelectionState(props);
53229  const factory = (nodes) => {
53230    return props.filter ? new ListCollection(props.filter(nodes)) : new ListCollection(nodes);
53231  };
53232  const collection = createCollection(
53233    {
53234      dataSource: () => access4(props.dataSource),
53235      getKey: () => access4(props.getKey),
53236      getTextValue: () => access4(props.getTextValue),
53237      getDisabled: () => access4(props.getDisabled),
53238      getSectionChildren: () => access4(props.getSectionChildren),
53239      factory
53240    },
53241    [() => props.filter]
53242  );
53243  const selectionManager = new SelectionManager(collection, selectionState);
53244  createComputed(() => {
53245    const focusedKey = selectionState.focusedKey();
53246    if (focusedKey != null && !collection().getItem(focusedKey)) {
53247      selectionState.setFocusedKey(void 0);
53248    }
53249  });
53250  return {
53251    collection,
53252    selectionManager: () => selectionManager
53253  };
53254}
53255
vendor: 4,332 bytes, lines 53256-53392
53256// node_modules/@kobalte/core/dist/chunk/I2LBZHJH.js
53257var ListKeyboardDelegate = class {
53258  collection;
53259  ref;
53260  collator;
53261  constructor(collection, ref, collator) {
53262    this.collection = collection;
53263    this.ref = ref;
53264    this.collator = collator;
53265  }
53266  getKeyBelow(key) {
53267    let keyAfter = this.collection().getKeyAfter(key);
53268    while (keyAfter != null) {
53269      const item = this.collection().getItem(keyAfter);
53270      if (item && item.type === "item" && !item.disabled) {
53271        return keyAfter;
53272      }
53273      keyAfter = this.collection().getKeyAfter(keyAfter);
53274    }
53275  }
53276  getKeyAbove(key) {
53277    let keyBefore = this.collection().getKeyBefore(key);
53278    while (keyBefore != null) {
53279      const item = this.collection().getItem(keyBefore);
53280      if (item && item.type === "item" && !item.disabled) {
53281        return keyBefore;
53282      }
53283      keyBefore = this.collection().getKeyBefore(keyBefore);
53284    }
53285  }
53286  getFirstKey() {
53287    let key = this.collection().getFirstKey();
53288    while (key != null) {
53289      const item = this.collection().getItem(key);
53290      if (item && item.type === "item" && !item.disabled) {
53291        return key;
53292      }
53293      key = this.collection().getKeyAfter(key);
53294    }
53295  }
53296  getLastKey() {
53297    let key = this.collection().getLastKey();
53298    while (key != null) {
53299      const item = this.collection().getItem(key);
53300      if (item && item.type === "item" && !item.disabled) {
53301        return key;
53302      }
53303      key = this.collection().getKeyBefore(key);
53304    }
53305  }
53306  getItem(key) {
53307    return this.ref?.()?.querySelector(`[data-key="${key}"]`) ?? null;
53308  }
53309  // TODO: not working correctly
53310  getKeyPageAbove(key) {
53311    const menu = this.ref?.();
53312    let item = this.getItem(key);
53313    if (!menu || !item) {
53314      return;
53315    }
53316    const pageY = Math.max(
53317      0,
53318      item.offsetTop + item.offsetHeight - menu.offsetHeight
53319    );
53320    let keyAbove = key;
53321    while (keyAbove && item && item.offsetTop > pageY) {
53322      keyAbove = this.getKeyAbove(keyAbove);
53323      item = keyAbove != null ? this.getItem(keyAbove) : null;
53324    }
53325    return keyAbove;
53326  }
53327  // TODO: not working correctly
53328  getKeyPageBelow(key) {
53329    const menu = this.ref?.();
53330    let item = this.getItem(key);
53331    if (!menu || !item) {
53332      return;
53333    }
53334    const pageY = Math.min(
53335      menu.scrollHeight,
53336      item.offsetTop - item.offsetHeight + menu.offsetHeight
53337    );
53338    let keyBelow = key;
53339    while (keyBelow && item && item.offsetTop < pageY) {
53340      keyBelow = this.getKeyBelow(keyBelow);
53341      item = keyBelow != null ? this.getItem(keyBelow) : null;
53342    }
53343    return keyBelow;
53344  }
53345  getKeyForSearch(search, fromKey) {
53346    const collator = this.collator?.();
53347    if (!collator) {
53348      return;
53349    }
53350    let key = fromKey != null ? this.getKeyBelow(fromKey) : this.getFirstKey();
53351    while (key != null) {
53352      const item = this.collection().getItem(key);
53353      if (item) {
53354        const substring = item.textValue.slice(0, search.length);
53355        if (item.textValue && collator.compare(substring, search) === 0) {
53356          return key;
53357        }
53358      }
53359      key = this.getKeyBelow(key);
53360    }
53361  }
53362};
53363function createSelectableList(props, ref, scrollRef) {
53364  const collator = createCollator({ usage: "search", sensitivity: "base" });
53365  const delegate = createMemo(() => {
53366    const keyboardDelegate = access4(props.keyboardDelegate);
53367    if (keyboardDelegate) {
53368      return keyboardDelegate;
53369    }
53370    return new ListKeyboardDelegate(props.collection, ref, collator);
53371  });
53372  return createSelectableCollection(
53373    {
53374      selectionManager: () => access4(props.selectionManager),
53375      keyboardDelegate: delegate,
53376      autoFocus: () => access4(props.autoFocus),
53377      deferAutoFocus: () => access4(props.deferAutoFocus),
53378      shouldFocusWrap: () => access4(props.shouldFocusWrap),
53379      disallowEmptySelection: () => access4(props.disallowEmptySelection),
53380      selectOnFocus: () => access4(props.selectOnFocus),
53381      disallowTypeAhead: () => access4(props.disallowTypeAhead),
53382      shouldUseVirtualFocus: () => access4(props.shouldUseVirtualFocus),
53383      allowsTabNavigation: () => access4(props.allowsTabNavigation),
53384      isVirtualized: () => access4(props.isVirtualized),
53385      scrollToKey: (key) => access4(props.scrollToKey)?.(key),
53386      orientation: () => access4(props.orientation)
53387    },
53388    ref,
53389    scrollRef
53390  );
53391}
53392
vendor: 4,478 bytes, lines 53393-53556
53393// node_modules/@kobalte/core/dist/chunk/7CVNMTYF.js
53394var DomCollectionContext = createContext();
53395function useOptionalDomCollectionContext() {
53396  return useContext(DomCollectionContext);
53397}
53398function useDomCollectionContext() {
53399  const context3 = useOptionalDomCollectionContext();
53400  if (context3 === void 0) {
53401    throw new Error(
53402      "[kobalte]: `useDomCollectionContext` must be used within a `DomCollectionProvider` component"
53403    );
53404  }
53405  return context3;
53406}
53407function isElementPreceding(a, b) {
53408  return Boolean(
53409    b.compareDocumentPosition(a) & Node.DOCUMENT_POSITION_PRECEDING
53410  );
53411}
53412function findDOMIndex(items, item) {
53413  const itemEl = item.ref();
53414  if (!itemEl) {
53415    return -1;
53416  }
53417  let length3 = items.length;
53418  if (!length3) {
53419    return -1;
53420  }
53421  while (length3--) {
53422    const currentItemEl = items[length3]?.ref();
53423    if (!currentItemEl) {
53424      continue;
53425    }
53426    if (isElementPreceding(currentItemEl, itemEl)) {
53427      return length3 + 1;
53428    }
53429  }
53430  return 0;
53431}
53432function sortBasedOnDOMPosition(items) {
53433  const pairs = items.map((item, index) => [index, item]);
53434  let isOrderDifferent = false;
53435  pairs.sort(([indexA, a], [indexB, b]) => {
53436    const elementA = a.ref();
53437    const elementB = b.ref();
53438    if (elementA === elementB) {
53439      return 0;
53440    }
53441    if (!elementA || !elementB) {
53442      return 0;
53443    }
53444    if (isElementPreceding(elementA, elementB)) {
53445      if (indexA > indexB) {
53446        isOrderDifferent = true;
53447      }
53448      return -1;
53449    }
53450    if (indexA < indexB) {
53451      isOrderDifferent = true;
53452    }
53453    return 1;
53454  });
53455  if (isOrderDifferent) {
53456    return pairs.map(([_, item]) => item);
53457  }
53458  return items;
53459}
53460function setItemsBasedOnDOMPosition(items, setItems) {
53461  const sortedItems = sortBasedOnDOMPosition(items);
53462  if (items !== sortedItems) {
53463    setItems(sortedItems);
53464  }
53465}
53466function getCommonParent(items) {
53467  const firstItem = items[0];
53468  const lastItemEl = items[items.length - 1]?.ref();
53469  let parentEl = firstItem?.ref()?.parentElement;
53470  while (parentEl) {
53471    if (lastItemEl && parentEl.contains(lastItemEl)) {
53472      return parentEl;
53473    }
53474    parentEl = parentEl.parentElement;
53475  }
53476  return getDocument(parentEl).body;
53477}
53478function createTimeoutObserver(items, setItems) {
53479  createEffect(() => {
53480    const timeout = setTimeout(() => {
53481      setItemsBasedOnDOMPosition(items(), setItems);
53482    });
53483    onCleanup(() => clearTimeout(timeout));
53484  });
53485}
53486function createSortBasedOnDOMPosition(items, setItems) {
53487  if (typeof IntersectionObserver !== "function") {
53488    createTimeoutObserver(items, setItems);
53489    return;
53490  }
53491  let previousItems = [];
53492  createEffect(() => {
53493    const callback = () => {
53494      const hasPreviousItems = !!previousItems.length;
53495      previousItems = items();
53496      if (!hasPreviousItems) {
53497        return;
53498      }
53499      setItemsBasedOnDOMPosition(items(), setItems);
53500    };
53501    const root = getCommonParent(items());
53502    const observer = new IntersectionObserver(callback, { root });
53503    for (const item of items()) {
53504      const itemEl = item.ref();
53505      if (itemEl) {
53506        observer.observe(itemEl);
53507      }
53508    }
53509    onCleanup(() => observer.disconnect());
53510  });
53511}
53512function createDomCollection(props = {}) {
53513  const [items, setItems] = createControllableArraySignal({
53514    value: () => access4(props.items),
53515    onChange: (value) => props.onItemsChange?.(value)
53516  });
53517  createSortBasedOnDOMPosition(items, setItems);
53518  const registerItem = (item) => {
53519    setItems((prevItems) => {
53520      const index = findDOMIndex(prevItems, item);
53521      return addItemToArray(prevItems, item, index);
53522    });
53523    return () => {
53524      setItems((prevItems) => {
53525        const nextItems = prevItems.filter(
53526          (prevItem) => prevItem.ref() !== item.ref()
53527        );
53528        if (prevItems.length === nextItems.length) {
53529          return prevItems;
53530        }
53531        return nextItems;
53532      });
53533    };
53534  };
53535  const DomCollectionProvider = (props2) => {
53536    return createComponent(DomCollectionContext.Provider, {
53537      value: { registerItem },
53538      get children() {
53539        return props2.children;
53540      }
53541    });
53542  };
53543  return { DomCollectionProvider };
53544}
53545function createDomCollectionItem(props) {
53546  const context3 = useDomCollectionContext();
53547  const mergedProps = mergeDefaultProps({ shouldRegisterItem: true }, props);
53548  createEffect(() => {
53549    if (!mergedProps.shouldRegisterItem) {
53550      return;
53551    }
53552    const unregister = context3.registerItem(mergedProps.getItem());
53553    onCleanup(unregister);
53554  });
53555}
53556
vendor: 685 bytes, lines 53557-53580
53557// node_modules/@kobalte/core/dist/chunk/YGDQXQ2B.js
53558function createToggleState(props = {}) {
53559  const [isSelected, _setIsSelected] = createControllableBooleanSignal({
53560    value: () => access4(props.isSelected),
53561    defaultValue: () => !!access4(props.defaultIsSelected),
53562    onChange: (value) => props.onSelectedChange?.(value)
53563  });
53564  const setIsSelected = (value) => {
53565    if (!access4(props.isReadOnly) && !access4(props.isDisabled)) {
53566      _setIsSelected(value);
53567    }
53568  };
53569  const toggle = () => {
53570    if (!access4(props.isReadOnly) && !access4(props.isDisabled)) {
53571      _setIsSelected(!isSelected());
53572    }
53573  };
53574  return {
53575    isSelected,
53576    setIsSelected,
53577    toggle
53578  };
53579}
53580
vendor: 42,399 bytes, lines 53581-54867
53581// node_modules/@kobalte/core/dist/chunk/HGKTPMYY.js
53582var MenubarContext = createContext();
53583function useOptionalMenubarContext() {
53584  return useContext(MenubarContext);
53585}
53586function useMenubarContext() {
53587  const context3 = useOptionalMenubarContext();
53588  if (context3 === void 0) {
53589    throw new Error("[kobalte]: `useMenubarContext` must be used within a `Menubar` component");
53590  }
53591  return context3;
53592}
53593var NavigationMenuContext = createContext();
53594function useOptionalNavigationMenuContext() {
53595  return useContext(NavigationMenuContext);
53596}
53597var MenuContext = createContext();
53598function useOptionalMenuContext() {
53599  return useContext(MenuContext);
53600}
53601function useMenuContext() {
53602  const context3 = useOptionalMenuContext();
53603  if (context3 === void 0) {
53604    throw new Error("[kobalte]: `useMenuContext` must be used within a `Menu` component");
53605  }
53606  return context3;
53607}
53608var MenuRootContext = createContext();
53609function useMenuRootContext() {
53610  const context3 = useContext(MenuRootContext);
53611  if (context3 === void 0) {
53612    throw new Error("[kobalte]: `useMenuRootContext` must be used within a `MenuRoot` component");
53613  }
53614  return context3;
53615}
53616function getPointerGraceArea(placement, event, contentEl) {
53617  const basePlacement = placement.split("-")[0];
53618  const contentRect = contentEl.getBoundingClientRect();
53619  const polygon = [];
53620  const pointerX = event.clientX;
53621  const pointerY = event.clientY;
53622  switch (basePlacement) {
53623    case "top":
53624      polygon.push([pointerX, pointerY + 5]);
53625      polygon.push([contentRect.left, contentRect.bottom]);
53626      polygon.push([contentRect.left, contentRect.top]);
53627      polygon.push([contentRect.right, contentRect.top]);
53628      polygon.push([contentRect.right, contentRect.bottom]);
53629      break;
53630    case "right":
53631      polygon.push([pointerX - 5, pointerY]);
53632      polygon.push([contentRect.left, contentRect.top]);
53633      polygon.push([contentRect.right, contentRect.top]);
53634      polygon.push([contentRect.right, contentRect.bottom]);
53635      polygon.push([contentRect.left, contentRect.bottom]);
53636      break;
53637    case "bottom":
53638      polygon.push([pointerX, pointerY - 5]);
53639      polygon.push([contentRect.right, contentRect.top]);
53640      polygon.push([contentRect.right, contentRect.bottom]);
53641      polygon.push([contentRect.left, contentRect.bottom]);
53642      polygon.push([contentRect.left, contentRect.top]);
53643      break;
53644    case "left":
53645      polygon.push([pointerX + 5, pointerY]);
53646      polygon.push([contentRect.right, contentRect.bottom]);
53647      polygon.push([contentRect.left, contentRect.bottom]);
53648      polygon.push([contentRect.left, contentRect.top]);
53649      polygon.push([contentRect.right, contentRect.top]);
53650      break;
53651  }
53652  return polygon;
53653}
53654function isPointerInGraceArea(event, area) {
53655  if (!area) {
53656    return false;
53657  }
53658  return isPointInPolygon([event.clientX, event.clientY], area);
53659}
53660function Menu(props) {
53661  const rootContext = useMenuRootContext();
53662  const parentDomCollectionContext = useOptionalDomCollectionContext();
53663  const parentMenuContext = useOptionalMenuContext();
53664  const optionalMenubarContext = useOptionalMenubarContext();
53665  const optionalNavigationMenuContext = useOptionalNavigationMenuContext();
53666  const mergedProps = mergeDefaultProps({
53667    placement: rootContext.orientation() === "horizontal" ? "bottom-start" : "right-start"
53668  }, props);
53669  const [local, others] = splitProps(mergedProps, ["open", "defaultOpen", "onOpenChange"]);
53670  let pointerGraceTimeoutId = 0;
53671  let pointerGraceIntent = null;
53672  let pointerDir = "right";
53673  const [triggerId, setTriggerId] = createSignal();
53674  const [contentId, setContentId] = createSignal();
53675  const [triggerRef, setTriggerRef] = createSignal();
53676  const [contentRef, setContentRef] = createSignal();
53677  const [focusStrategy, setFocusStrategy] = createSignal(true);
53678  const [currentPlacement, setCurrentPlacement] = createSignal(others.placement);
53679  const [nestedMenus, setNestedMenus] = createSignal([]);
53680  const [items, setItems] = createSignal([]);
53681  const {
53682    DomCollectionProvider
53683  } = createDomCollection({
53684    items,
53685    onItemsChange: setItems
53686  });
53687  const disclosureState = createDisclosureState({
53688    open: () => local.open,
53689    defaultOpen: () => local.defaultOpen,
53690    onOpenChange: (isOpen) => local.onOpenChange?.(isOpen)
53691  });
53692  const {
53693    present: contentPresent
53694  } = index_default2({
53695    show: () => rootContext.forceMount() || disclosureState.isOpen(),
53696    element: () => contentRef() ?? null
53697  });
53698  const listState = createListState({
53699    selectionMode: "none",
53700    dataSource: items
53701  });
53702  const open = (focusStrategy2) => {
53703    setFocusStrategy(focusStrategy2);
53704    disclosureState.open();
53705  };
53706  const close = (recursively = false) => {
53707    disclosureState.close();
53708    if (recursively && parentMenuContext) {
53709      parentMenuContext.close(true);
53710    }
53711  };
53712  const toggle = (focusStrategy2) => {
53713    setFocusStrategy(focusStrategy2);
53714    disclosureState.toggle();
53715  };
53716  const _focusContent = () => {
53717    const content = contentRef();
53718    if (content) {
53719      focusWithoutScrolling(content);
53720      listState.selectionManager().setFocused(true);
53721      listState.selectionManager().setFocusedKey(void 0);
53722    }
53723  };
53724  const focusContent = () => {
53725    if (optionalNavigationMenuContext != null)
53726      setTimeout(() => _focusContent());
53727    else
53728      _focusContent();
53729  };
53730  const registerNestedMenu = (element3) => {
53731    setNestedMenus((prev) => [...prev, element3]);
53732    const parentUnregister = parentMenuContext?.registerNestedMenu(element3);
53733    return () => {
53734      setNestedMenus((prev) => removeItemFromArray(prev, element3));
53735      parentUnregister?.();
53736    };
53737  };
53738  const isPointerMovingToSubmenu = (e) => {
53739    const isMovingTowards = pointerDir === pointerGraceIntent?.side;
53740    return isMovingTowards && isPointerInGraceArea(e, pointerGraceIntent?.area);
53741  };
53742  const onItemEnter = (e) => {
53743    if (isPointerMovingToSubmenu(e)) {
53744      e.preventDefault();
53745    }
53746  };
53747  const onItemLeave = (e) => {
53748    if (isPointerMovingToSubmenu(e)) {
53749      return;
53750    }
53751    focusContent();
53752  };
53753  const onTriggerLeave = (e) => {
53754    if (isPointerMovingToSubmenu(e)) {
53755      e.preventDefault();
53756    }
53757  };
53758  createHideOutside({
53759    isDisabled: () => {
53760      return !(parentMenuContext == null && disclosureState.isOpen() && rootContext.isModal());
53761    },
53762    targets: () => [contentRef(), ...nestedMenus()].filter(Boolean)
53763  });
53764  createEffect(() => {
53765    const contentEl = contentRef();
53766    if (!contentEl || !parentMenuContext) {
53767      return;
53768    }
53769    const parentUnregister = parentMenuContext.registerNestedMenu(contentEl);
53770    onCleanup(() => {
53771      parentUnregister();
53772    });
53773  });
53774  createEffect(() => {
53775    if (parentMenuContext !== void 0)
53776      return;
53777    optionalMenubarContext?.registerMenu(rootContext.value(), [contentRef(), ...nestedMenus()]);
53778  });
53779  createEffect(() => {
53780    if (parentMenuContext !== void 0 || optionalMenubarContext === void 0)
53781      return;
53782    if (optionalMenubarContext.value() === rootContext.value()) {
53783      triggerRef()?.focus();
53784      if (optionalMenubarContext.autoFocusMenu())
53785        open(true);
53786    } else
53787      close();
53788  });
53789  createEffect(() => {
53790    if (parentMenuContext !== void 0 || optionalMenubarContext === void 0)
53791      return;
53792    if (disclosureState.isOpen())
53793      optionalMenubarContext.setValue(rootContext.value());
53794  });
53795  onCleanup(() => {
53796    if (parentMenuContext !== void 0)
53797      return;
53798    optionalMenubarContext?.unregisterMenu(rootContext.value());
53799  });
53800  const dataset = createMemo(() => ({
53801    "data-expanded": disclosureState.isOpen() ? "" : void 0,
53802    "data-closed": !disclosureState.isOpen() ? "" : void 0
53803  }));
53804  const context3 = {
53805    dataset,
53806    isOpen: disclosureState.isOpen,
53807    contentPresent,
53808    nestedMenus,
53809    currentPlacement,
53810    pointerGraceTimeoutId: () => pointerGraceTimeoutId,
53811    autoFocus: focusStrategy,
53812    listState: () => listState,
53813    parentMenuContext: () => parentMenuContext,
53814    triggerRef,
53815    contentRef,
53816    triggerId,
53817    contentId,
53818    setTriggerRef,
53819    setContentRef,
53820    open,
53821    close,
53822    toggle,
53823    focusContent,
53824    onItemEnter,
53825    onItemLeave,
53826    onTriggerLeave,
53827    setPointerDir: (dir) => pointerDir = dir,
53828    setPointerGraceTimeoutId: (id) => pointerGraceTimeoutId = id,
53829    setPointerGraceIntent: (intent) => pointerGraceIntent = intent,
53830    registerNestedMenu,
53831    registerItemToParentDomCollection: parentDomCollectionContext?.registerItem,
53832    registerTriggerId: createRegisterId(setTriggerId),
53833    registerContentId: createRegisterId(setContentId)
53834  };
53835  return createComponent(DomCollectionProvider, {
53836    get children() {
53837      return createComponent(MenuContext.Provider, {
53838        value: context3,
53839        get children() {
53840          return createComponent(Show, {
53841            when: optionalNavigationMenuContext === void 0,
53842            get fallback() {
53843              return others.children;
53844            },
53845            get children() {
53846              return createComponent(Popper, mergeProps({
53847                anchorRef: triggerRef,
53848                contentRef,
53849                onCurrentPlacementChange: setCurrentPlacement
53850              }, others));
53851            }
53852          });
53853        }
53854      });
53855    }
53856  });
53857}
53858var MenuItemContext = createContext();
53859function useMenuItemContext() {
53860  const context3 = useContext(MenuItemContext);
53861  if (context3 === void 0) {
53862    throw new Error("[kobalte]: `useMenuItemContext` must be used within a `Menu.Item` component");
53863  }
53864  return context3;
53865}
53866function MenuItemBase(props) {
53867  let ref;
53868  const rootContext = useMenuRootContext();
53869  const menuContext = useMenuContext();
53870  const mergedProps = mergeDefaultProps({
53871    id: rootContext.generateId(`item-${createUniqueId()}`)
53872  }, props);
53873  const [local, others] = splitProps(mergedProps, ["ref", "textValue", "disabled", "closeOnSelect", "checked", "indeterminate", "onSelect", "onPointerMove", "onPointerLeave", "onPointerDown", "onPointerUp", "onClick", "onKeyDown", "onMouseDown", "onFocus"]);
53874  const [labelId, setLabelId] = createSignal();
53875  const [descriptionId, setDescriptionId] = createSignal();
53876  const [labelRef, setLabelRef] = createSignal();
53877  const selectionManager = () => menuContext.listState().selectionManager();
53878  const key = () => others.id;
53879  const isHighlighted = () => selectionManager().focusedKey() === key();
53880  const onSelect = () => {
53881    local.onSelect?.();
53882    if (local.closeOnSelect) {
53883      setTimeout(
53884        () => {
53885          menuContext.close(true);
53886        },
53887        // Fix #446
53888        // Requires a delay for NavigationMenu to work on mobile.
53889        1
53890      );
53891    }
53892  };
53893  createDomCollectionItem({
53894    getItem: () => ({
53895      ref: () => ref,
53896      type: "item",
53897      key: key(),
53898      textValue: local.textValue ?? labelRef()?.textContent ?? ref?.textContent ?? "",
53899      disabled: local.disabled ?? false
53900    })
53901  });
53902  const selectableItem = createSelectableItem({
53903    key,
53904    selectionManager,
53905    shouldSelectOnPressUp: true,
53906    allowsDifferentPressOrigin: true,
53907    disabled: () => local.disabled
53908  }, () => ref);
53909  const onPointerMove = (e) => {
53910    callHandler(e, local.onPointerMove);
53911    if (e.pointerType !== "mouse") {
53912      return;
53913    }
53914    if (local.disabled) {
53915      menuContext.onItemLeave(e);
53916    } else {
53917      menuContext.onItemEnter(e);
53918      if (!e.defaultPrevented) {
53919        focusWithoutScrolling(e.currentTarget);
53920        menuContext.listState().selectionManager().setFocused(true);
53921        menuContext.listState().selectionManager().setFocusedKey(key());
53922      }
53923    }
53924  };
53925  const onPointerLeave = (e) => {
53926    callHandler(e, local.onPointerLeave);
53927    if (e.pointerType !== "mouse") {
53928      return;
53929    }
53930    menuContext.onItemLeave(e);
53931  };
53932  const onPointerUp = (e) => {
53933    callHandler(e, local.onPointerUp);
53934    if (!local.disabled && e.button === 0) {
53935      onSelect();
53936    }
53937  };
53938  const onKeyDown = (e) => {
53939    callHandler(e, local.onKeyDown);
53940    if (e.repeat) {
53941      return;
53942    }
53943    if (local.disabled) {
53944      return;
53945    }
53946    switch (e.key) {
53947      case "Enter":
53948      case " ":
53949        onSelect();
53950        break;
53951    }
53952  };
53953  const ariaChecked = createMemo(() => {
53954    if (local.indeterminate) {
53955      return "mixed";
53956    }
53957    if (local.checked == null) {
53958      return void 0;
53959    }
53960    return local.checked;
53961  });
53962  const dataset = createMemo(() => ({
53963    "data-indeterminate": local.indeterminate ? "" : void 0,
53964    "data-checked": local.checked && !local.indeterminate ? "" : void 0,
53965    "data-disabled": local.disabled ? "" : void 0,
53966    "data-highlighted": isHighlighted() ? "" : void 0
53967  }));
53968  const context3 = {
53969    isChecked: () => local.checked,
53970    dataset,
53971    setLabelRef,
53972    generateId: createGenerateId(() => others.id),
53973    registerLabel: createRegisterId(setLabelId),
53974    registerDescription: createRegisterId(setDescriptionId)
53975  };
53976  return createComponent(MenuItemContext.Provider, {
53977    value: context3,
53978    get children() {
53979      return createComponent(Polymorphic, mergeProps({
53980        as: "div",
53981        ref(r$) {
53982          const _ref$ = mergeRefs((el) => ref = el, local.ref);
53983          typeof _ref$ === "function" && _ref$(r$);
53984        },
53985        get tabIndex() {
53986          return selectableItem.tabIndex();
53987        },
53988        get ["aria-checked"]() {
53989          return ariaChecked();
53990        },
53991        get ["aria-disabled"]() {
53992          return local.disabled;
53993        },
53994        get ["aria-labelledby"]() {
53995          return labelId();
53996        },
53997        get ["aria-describedby"]() {
53998          return descriptionId();
53999        },
54000        get ["data-key"]() {
54001          return selectableItem.dataKey();
54002        },
54003        get onPointerDown() {
54004          return composeEventHandlers([local.onPointerDown, selectableItem.onPointerDown]);
54005        },
54006        get onPointerUp() {
54007          return composeEventHandlers([onPointerUp, selectableItem.onPointerUp]);
54008        },
54009        get onClick() {
54010          return composeEventHandlers([local.onClick, selectableItem.onClick]);
54011        },
54012        get onKeyDown() {
54013          return composeEventHandlers([onKeyDown, selectableItem.onKeyDown]);
54014        },
54015        get onMouseDown() {
54016          return composeEventHandlers([local.onMouseDown, selectableItem.onMouseDown]);
54017        },
54018        get onFocus() {
54019          return composeEventHandlers([local.onFocus, selectableItem.onFocus]);
54020        },
54021        onPointerMove,
54022        onPointerLeave
54023      }, dataset, others));
54024    }
54025  });
54026}
54027function MenuCheckboxItem(props) {
54028  const mergedProps = mergeDefaultProps({
54029    closeOnSelect: false
54030  }, props);
54031  const [local, others] = splitProps(mergedProps, ["checked", "defaultChecked", "onChange", "onSelect"]);
54032  const state = createToggleState({
54033    isSelected: () => local.checked,
54034    defaultIsSelected: () => local.defaultChecked,
54035    onSelectedChange: (checked) => local.onChange?.(checked),
54036    isDisabled: () => others.disabled
54037  });
54038  const onSelect = () => {
54039    local.onSelect?.();
54040    state.toggle();
54041  };
54042  return createComponent(MenuItemBase, mergeProps({
54043    role: "menuitemcheckbox",
54044    get checked() {
54045      return state.isSelected();
54046    },
54047    onSelect
54048  }, others));
54049}
54050var MENUBAR_KEYS = {
54051  next: (dir, orientation) => dir === "ltr" ? orientation === "horizontal" ? "ArrowRight" : "ArrowDown" : orientation === "horizontal" ? "ArrowLeft" : "ArrowUp",
54052  previous: (dir, orientation) => MENUBAR_KEYS.next(dir === "ltr" ? "rtl" : "ltr", orientation)
54053};
54054var MENU_KEYS = {
54055  first: (orientation) => orientation === "horizontal" ? "ArrowDown" : "ArrowRight",
54056  last: (orientation) => orientation === "horizontal" ? "ArrowUp" : "ArrowLeft"
54057};
54058function MenuTrigger(props) {
54059  const rootContext = useMenuRootContext();
54060  const context3 = useMenuContext();
54061  const optionalMenubarContext = useOptionalMenubarContext();
54062  const {
54063    direction
54064  } = useLocale();
54065  const mergedProps = mergeDefaultProps({
54066    id: rootContext.generateId("trigger")
54067  }, props);
54068  const [local, others] = splitProps(mergedProps, ["ref", "id", "disabled", "onPointerDown", "onClick", "onKeyDown", "onMouseOver", "onFocus"]);
54069  let key = () => rootContext.value();
54070  if (optionalMenubarContext !== void 0) {
54071    key = () => rootContext.value() ?? local.id;
54072    if (optionalMenubarContext.lastValue() === void 0)
54073      optionalMenubarContext.setLastValue(key);
54074  }
54075  const tagName = createTagName(() => context3.triggerRef(), () => "button");
54076  const isNativeLink = createMemo(() => {
54077    return tagName() === "a" && context3.triggerRef()?.getAttribute("href") != null;
54078  });
54079  createEffect(on(() => optionalMenubarContext?.value(), (value) => {
54080    if (!isNativeLink())
54081      return;
54082    if (value === key())
54083      context3.triggerRef()?.focus();
54084  }));
54085  const handleClick = () => {
54086    if (optionalMenubarContext !== void 0) {
54087      if (!context3.isOpen()) {
54088        if (!optionalMenubarContext.autoFocusMenu()) {
54089          optionalMenubarContext.setAutoFocusMenu(true);
54090        }
54091        context3.open(false);
54092      } else {
54093        if (optionalMenubarContext.value() === key())
54094          optionalMenubarContext.closeMenu();
54095      }
54096    } else
54097      context3.toggle(true);
54098  };
54099  const onPointerDown = (e) => {
54100    callHandler(e, local.onPointerDown);
54101    e.currentTarget.dataset.pointerType = e.pointerType;
54102    if (!local.disabled && e.pointerType !== "touch" && e.button === 0) {
54103      handleClick();
54104    }
54105  };
54106  const onClick = (e) => {
54107    callHandler(e, local.onClick);
54108    if (!local.disabled) {
54109      if (e.currentTarget.dataset.pointerType === "touch")
54110        handleClick();
54111    }
54112  };
54113  const onKeyDown = (e) => {
54114    callHandler(e, local.onKeyDown);
54115    if (local.disabled) {
54116      return;
54117    }
54118    if (isNativeLink()) {
54119      switch (e.key) {
54120        case "Enter":
54121        case " ":
54122          return;
54123      }
54124    }
54125    switch (e.key) {
54126      case "Enter":
54127      case " ":
54128      case MENU_KEYS.first(rootContext.orientation()):
54129        e.stopPropagation();
54130        e.preventDefault();
54131        scrollIntoViewport(e.currentTarget);
54132        context3.open("first");
54133        optionalMenubarContext?.setAutoFocusMenu(true);
54134        optionalMenubarContext?.setValue(key);
54135        break;
54136      case MENU_KEYS.last(rootContext.orientation()):
54137        e.stopPropagation();
54138        e.preventDefault();
54139        context3.open("last");
54140        break;
54141      case MENUBAR_KEYS.next(direction(), rootContext.orientation()):
54142        if (optionalMenubarContext === void 0)
54143          break;
54144        e.stopPropagation();
54145        e.preventDefault();
54146        optionalMenubarContext.nextMenu();
54147        break;
54148      case MENUBAR_KEYS.previous(direction(), rootContext.orientation()):
54149        if (optionalMenubarContext === void 0)
54150          break;
54151        e.stopPropagation();
54152        e.preventDefault();
54153        optionalMenubarContext.previousMenu();
54154        break;
54155    }
54156  };
54157  const onMouseOver = (e) => {
54158    callHandler(e, local.onMouseOver);
54159    if (context3.triggerRef()?.dataset.pointerType === "touch")
54160      return;
54161    if (!local.disabled && optionalMenubarContext !== void 0 && optionalMenubarContext.value() !== void 0) {
54162      optionalMenubarContext.setValue(key);
54163    }
54164  };
54165  const onFocus = (e) => {
54166    callHandler(e, local.onFocus);
54167    if (optionalMenubarContext !== void 0 && e.currentTarget.dataset.pointerType !== "touch")
54168      optionalMenubarContext.setValue(key);
54169  };
54170  createEffect(() => onCleanup(context3.registerTriggerId(local.id)));
54171  return createComponent(ButtonRoot, mergeProps({
54172    ref(r$) {
54173      const _ref$ = mergeRefs(context3.setTriggerRef, local.ref);
54174      typeof _ref$ === "function" && _ref$(r$);
54175    },
54176    get ["data-kb-menu-value-trigger"]() {
54177      return rootContext.value();
54178    },
54179    get id() {
54180      return local.id;
54181    },
54182    get disabled() {
54183      return local.disabled;
54184    },
54185    "aria-haspopup": "true",
54186    get ["aria-expanded"]() {
54187      return context3.isOpen();
54188    },
54189    get ["aria-controls"]() {
54190      return memo(() => !!context3.isOpen())() ? context3.contentId() : void 0;
54191    },
54192    get ["data-highlighted"]() {
54193      return key() !== void 0 && optionalMenubarContext?.value() === key() ? true : void 0;
54194    },
54195    get tabIndex() {
54196      return optionalMenubarContext !== void 0 ? optionalMenubarContext.value() === key() || optionalMenubarContext.lastValue() === key() ? 0 : -1 : void 0;
54197    },
54198    onPointerDown,
54199    onMouseOver,
54200    onClick,
54201    onKeyDown,
54202    onFocus,
54203    role: optionalMenubarContext !== void 0 ? "menuitem" : void 0
54204  }, () => context3.dataset(), others));
54205}
54206function MenuContentBase(props) {
54207  let ref;
54208  const rootContext = useMenuRootContext();
54209  const context3 = useMenuContext();
54210  const optionalMenubarContext = useOptionalMenubarContext();
54211  const optionalNavigationMenuContext = useOptionalNavigationMenuContext();
54212  const {
54213    direction
54214  } = useLocale();
54215  const mergedProps = mergeDefaultProps({
54216    id: rootContext.generateId(`content-${createUniqueId()}`)
54217  }, props);
54218  const [local, others] = splitProps(mergedProps, ["ref", "id", "style", "onOpenAutoFocus", "onCloseAutoFocus", "onEscapeKeyDown", "onFocusOutside", "onPointerEnter", "onPointerMove", "onKeyDown", "onMouseDown", "onFocusIn", "onFocusOut"]);
54219  let lastPointerX = 0;
54220  const isRootModalContent = () => {
54221    return context3.parentMenuContext() == null && optionalMenubarContext === void 0 && rootContext.isModal();
54222  };
54223  const selectableList = createSelectableList({
54224    selectionManager: context3.listState().selectionManager,
54225    collection: context3.listState().collection,
54226    autoFocus: context3.autoFocus,
54227    deferAutoFocus: true,
54228    // ensure all menu items are mounted and collection is not empty before trying to autofocus.
54229    shouldFocusWrap: true,
54230    disallowTypeAhead: () => !context3.listState().selectionManager().isFocused(),
54231    orientation: () => rootContext.orientation() === "horizontal" ? "vertical" : "horizontal"
54232  }, () => ref);
54233  createFocusScope({
54234    trapFocus: () => isRootModalContent() && context3.isOpen(),
54235    onMountAutoFocus: (event) => {
54236      if (optionalMenubarContext === void 0)
54237        local.onOpenAutoFocus?.(event);
54238    },
54239    onUnmountAutoFocus: local.onCloseAutoFocus
54240  }, () => ref);
54241  const onKeyDown = (e) => {
54242    if (!contains(e.currentTarget, e.target)) {
54243      return;
54244    }
54245    if (e.key === "Tab" && context3.isOpen()) {
54246      e.preventDefault();
54247    }
54248    if (optionalMenubarContext !== void 0) {
54249      if (e.currentTarget.getAttribute("aria-haspopup") !== "true")
54250        switch (e.key) {
54251          case MENUBAR_KEYS.next(direction(), rootContext.orientation()):
54252            e.stopPropagation();
54253            e.preventDefault();
54254            context3.close(true);
54255            optionalMenubarContext.setAutoFocusMenu(true);
54256            optionalMenubarContext.nextMenu();
54257            break;
54258          case MENUBAR_KEYS.previous(direction(), rootContext.orientation()):
54259            if (e.currentTarget.hasAttribute("data-closed"))
54260              break;
54261            e.stopPropagation();
54262            e.preventDefault();
54263            context3.close(true);
54264            optionalMenubarContext.setAutoFocusMenu(true);
54265            optionalMenubarContext.previousMenu();
54266            break;
54267        }
54268    }
54269  };
54270  const onEscapeKeyDown = (e) => {
54271    local.onEscapeKeyDown?.(e);
54272    optionalMenubarContext?.setAutoFocusMenu(false);
54273    context3.close(true);
54274  };
54275  const onFocusOutside = (e) => {
54276    local.onFocusOutside?.(e);
54277    if (rootContext.isModal()) {
54278      e.preventDefault();
54279    }
54280  };
54281  const onPointerEnter = (e) => {
54282    callHandler(e, local.onPointerEnter);
54283    if (!context3.isOpen()) {
54284      return;
54285    }
54286    context3.parentMenuContext()?.listState().selectionManager().setFocused(false);
54287    context3.parentMenuContext()?.listState().selectionManager().setFocusedKey(void 0);
54288  };
54289  const onPointerMove = (e) => {
54290    callHandler(e, local.onPointerMove);
54291    if (e.pointerType !== "mouse") {
54292      return;
54293    }
54294    const target = e.target;
54295    const pointerXHasChanged = lastPointerX !== e.clientX;
54296    if (contains(e.currentTarget, target) && pointerXHasChanged) {
54297      context3.setPointerDir(e.clientX > lastPointerX ? "right" : "left");
54298      lastPointerX = e.clientX;
54299    }
54300  };
54301  createEffect(() => onCleanup(context3.registerContentId(local.id)));
54302  onCleanup(() => context3.setContentRef(void 0));
54303  const commonAttributes = {
54304    ref: mergeRefs((el) => {
54305      context3.setContentRef(el);
54306      ref = el;
54307    }, local.ref),
54308    role: "menu",
54309    get id() {
54310      return local.id;
54311    },
54312    get tabIndex() {
54313      return selectableList.tabIndex();
54314    },
54315    get "aria-labelledby"() {
54316      return context3.triggerId();
54317    },
54318    onKeyDown: composeEventHandlers([local.onKeyDown, selectableList.onKeyDown, onKeyDown]),
54319    onMouseDown: composeEventHandlers([local.onMouseDown, selectableList.onMouseDown]),
54320    onFocusIn: composeEventHandlers([local.onFocusIn, selectableList.onFocusIn]),
54321    onFocusOut: composeEventHandlers([local.onFocusOut, selectableList.onFocusOut]),
54322    onPointerEnter,
54323    onPointerMove,
54324    get "data-orientation"() {
54325      return rootContext.orientation();
54326    }
54327  };
54328  return createComponent(Show, {
54329    get when() {
54330      return context3.contentPresent();
54331    },
54332    get children() {
54333      return createComponent(Show, {
54334        get when() {
54335          return optionalNavigationMenuContext === void 0 || context3.parentMenuContext() != null;
54336        },
54337        get fallback() {
54338          return createComponent(Polymorphic, mergeProps({
54339            as: "div"
54340          }, () => context3.dataset(), commonAttributes, others));
54341        },
54342        get children() {
54343          return createComponent(Popper.Positioner, {
54344            get children() {
54345              return createComponent(DismissableLayer, mergeProps({
54346                get disableOutsidePointerEvents() {
54347                  return memo(() => !!isRootModalContent())() && context3.isOpen();
54348                },
54349                get excludedElements() {
54350                  return [context3.triggerRef];
54351                },
54352                bypassTopMostLayerCheck: true,
54353                get style() {
54354                  return combineStyle({
54355                    "--kb-menu-content-transform-origin": "var(--kb-popper-content-transform-origin)",
54356                    position: "relative"
54357                  }, local.style);
54358                },
54359                onEscapeKeyDown,
54360                onFocusOutside,
54361                get onDismiss() {
54362                  return context3.close;
54363                }
54364              }, () => context3.dataset(), commonAttributes, others));
54365            }
54366          });
54367        }
54368      });
54369    }
54370  });
54371}
54372function MenuContent(props) {
54373  let ref;
54374  const rootContext = useMenuRootContext();
54375  const context3 = useMenuContext();
54376  const [local, others] = splitProps(props, ["ref"]);
54377  index_default({
54378    element: () => ref ?? null,
54379    enabled: () => context3.contentPresent() && rootContext.preventScroll()
54380  });
54381  return createComponent(MenuContentBase, mergeProps({
54382    ref(r$) {
54383      const _ref$ = mergeRefs((el) => {
54384        ref = el;
54385      }, local.ref);
54386      typeof _ref$ === "function" && _ref$(r$);
54387    }
54388  }, others));
54389}
54390var MenuGroupContext = createContext();
54391function useMenuGroupContext() {
54392  const context3 = useContext(MenuGroupContext);
54393  if (context3 === void 0) {
54394    throw new Error("[kobalte]: `useMenuGroupContext` must be used within a `Menu.Group` component");
54395  }
54396  return context3;
54397}
54398function MenuGroup(props) {
54399  const rootContext = useMenuRootContext();
54400  const mergedProps = mergeDefaultProps({
54401    id: rootContext.generateId(`group-${createUniqueId()}`)
54402  }, props);
54403  const [labelId, setLabelId] = createSignal();
54404  const context3 = {
54405    generateId: createGenerateId(() => mergedProps.id),
54406    registerLabelId: createRegisterId(setLabelId)
54407  };
54408  return createComponent(MenuGroupContext.Provider, {
54409    value: context3,
54410    get children() {
54411      return createComponent(Polymorphic, mergeProps({
54412        as: "div",
54413        role: "group",
54414        get ["aria-labelledby"]() {
54415          return labelId();
54416        }
54417      }, mergedProps));
54418    }
54419  });
54420}
54421function MenuGroupLabel(props) {
54422  const context3 = useMenuGroupContext();
54423  const mergedProps = mergeDefaultProps({
54424    id: context3.generateId("label")
54425  }, props);
54426  const [local, others] = splitProps(mergedProps, ["id"]);
54427  createEffect(() => onCleanup(context3.registerLabelId(local.id)));
54428  return createComponent(Polymorphic, mergeProps({
54429    as: "span",
54430    get id() {
54431      return local.id;
54432    },
54433    "aria-hidden": "true"
54434  }, others));
54435}
54436function MenuIcon(props) {
54437  const context3 = useMenuContext();
54438  const mergedProps = mergeDefaultProps({
54439    children: "\u25BC"
54440  }, props);
54441  return createComponent(Polymorphic, mergeProps({
54442    as: "span",
54443    "aria-hidden": "true"
54444  }, () => context3.dataset(), mergedProps));
54445}
54446function MenuItem(props) {
54447  return createComponent(MenuItemBase, mergeProps({
54448    role: "menuitem",
54449    closeOnSelect: true
54450  }, props));
54451}
54452function MenuItemDescription(props) {
54453  const context3 = useMenuItemContext();
54454  const mergedProps = mergeDefaultProps({
54455    id: context3.generateId("description")
54456  }, props);
54457  const [local, others] = splitProps(mergedProps, ["id"]);
54458  createEffect(() => onCleanup(context3.registerDescription(local.id)));
54459  return createComponent(Polymorphic, mergeProps({
54460    as: "div",
54461    get id() {
54462      return local.id;
54463    }
54464  }, () => context3.dataset(), others));
54465}
54466function MenuItemIndicator(props) {
54467  const context3 = useMenuItemContext();
54468  const mergedProps = mergeDefaultProps({
54469    id: context3.generateId("indicator")
54470  }, props);
54471  const [local, others] = splitProps(mergedProps, ["forceMount"]);
54472  return createComponent(Show, {
54473    get when() {
54474      return local.forceMount || context3.isChecked();
54475    },
54476    get children() {
54477      return createComponent(Polymorphic, mergeProps({
54478        as: "div"
54479      }, () => context3.dataset(), others));
54480    }
54481  });
54482}
54483function MenuItemLabel(props) {
54484  const context3 = useMenuItemContext();
54485  const mergedProps = mergeDefaultProps({
54486    id: context3.generateId("label")
54487  }, props);
54488  const [local, others] = splitProps(mergedProps, ["ref", "id"]);
54489  createEffect(() => onCleanup(context3.registerLabel(local.id)));
54490  return createComponent(Polymorphic, mergeProps({
54491    as: "div",
54492    ref(r$) {
54493      const _ref$ = mergeRefs(context3.setLabelRef, local.ref);
54494      typeof _ref$ === "function" && _ref$(r$);
54495    },
54496    get id() {
54497      return local.id;
54498    }
54499  }, () => context3.dataset(), others));
54500}
54501function MenuPortal(props) {
54502  const context3 = useMenuContext();
54503  return createComponent(Show, {
54504    get when() {
54505      return context3.contentPresent();
54506    },
54507    get children() {
54508      return createComponent(Portal, props);
54509    }
54510  });
54511}
54512var MenuRadioGroupContext = createContext();
54513function useMenuRadioGroupContext() {
54514  const context3 = useContext(MenuRadioGroupContext);
54515  if (context3 === void 0) {
54516    throw new Error("[kobalte]: `useMenuRadioGroupContext` must be used within a `Menu.RadioGroup` component");
54517  }
54518  return context3;
54519}
54520function MenuRadioGroup(props) {
54521  const rootContext = useMenuRootContext();
54522  const defaultId = rootContext.generateId(`radiogroup-${createUniqueId()}`);
54523  const mergedProps = mergeDefaultProps({
54524    id: defaultId
54525  }, props);
54526  const [local, others] = splitProps(mergedProps, ["value", "defaultValue", "onChange", "disabled"]);
54527  const [selected, setSelected] = createControllableSignal({
54528    value: () => local.value,
54529    defaultValue: () => local.defaultValue,
54530    onChange: (value) => local.onChange?.(value)
54531  });
54532  const context3 = {
54533    isDisabled: () => local.disabled,
54534    isSelectedValue: (value) => value === selected(),
54535    setSelectedValue: (value) => setSelected(value)
54536  };
54537  return createComponent(MenuRadioGroupContext.Provider, {
54538    value: context3,
54539    get children() {
54540      return createComponent(MenuGroup, others);
54541    }
54542  });
54543}
54544function MenuRadioItem(props) {
54545  const context3 = useMenuRadioGroupContext();
54546  const mergedProps = mergeDefaultProps({
54547    closeOnSelect: false
54548  }, props);
54549  const [local, others] = splitProps(mergedProps, ["value", "onSelect"]);
54550  const onSelect = () => {
54551    local.onSelect?.();
54552    context3.setSelectedValue(local.value);
54553  };
54554  return createComponent(MenuItemBase, mergeProps({
54555    role: "menuitemradio",
54556    get checked() {
54557      return context3.isSelectedValue(local.value);
54558    },
54559    onSelect
54560  }, others));
54561}
54562function MenuRoot(props) {
54563  const optionalMenubarContext = useOptionalMenubarContext();
54564  const defaultId = `menu-${createUniqueId()}`;
54565  const mergedProps = mergeDefaultProps({
54566    id: defaultId,
54567    modal: true
54568  }, props);
54569  const [local, others] = splitProps(mergedProps, ["id", "modal", "preventScroll", "forceMount", "open", "defaultOpen", "onOpenChange", "value", "orientation"]);
54570  const disclosureState = createDisclosureState({
54571    open: () => local.open,
54572    defaultOpen: () => local.defaultOpen,
54573    onOpenChange: (isOpen) => local.onOpenChange?.(isOpen)
54574  });
54575  const context3 = {
54576    isModal: () => local.modal ?? true,
54577    preventScroll: () => local.preventScroll ?? context3.isModal(),
54578    forceMount: () => local.forceMount ?? false,
54579    generateId: createGenerateId(() => local.id),
54580    value: () => local.value,
54581    orientation: () => local.orientation ?? optionalMenubarContext?.orientation() ?? "horizontal"
54582  };
54583  return createComponent(MenuRootContext.Provider, {
54584    value: context3,
54585    get children() {
54586      return createComponent(Menu, mergeProps({
54587        get open() {
54588          return disclosureState.isOpen();
54589        },
54590        get onOpenChange() {
54591          return disclosureState.setIsOpen;
54592        }
54593      }, others));
54594    }
54595  });
54596}
54597function MenuSub(props) {
54598  const {
54599    direction
54600  } = useLocale();
54601  return createComponent(Menu, mergeProps({
54602    get placement() {
54603      return direction() === "rtl" ? "left-start" : "right-start";
54604    },
54605    flip: true
54606  }, props));
54607}
54608var SUB_CLOSE_KEYS = {
54609  close: (dir, orientation) => {
54610    if (dir === "ltr") {
54611      return [orientation === "horizontal" ? "ArrowLeft" : "ArrowUp"];
54612    }
54613    return [orientation === "horizontal" ? "ArrowRight" : "ArrowDown"];
54614  }
54615};
54616function MenuSubContent(props) {
54617  const context3 = useMenuContext();
54618  const rootContext = useMenuRootContext();
54619  const [local, others] = splitProps(props, ["onFocusOutside", "onKeyDown"]);
54620  const {
54621    direction
54622  } = useLocale();
54623  const onOpenAutoFocus = (e) => {
54624    e.preventDefault();
54625  };
54626  const onCloseAutoFocus = (e) => {
54627    e.preventDefault();
54628  };
54629  const onFocusOutside = (e) => {
54630    local.onFocusOutside?.(e);
54631    const target = e.target;
54632    if (!contains(context3.triggerRef(), target)) {
54633      context3.close();
54634    }
54635  };
54636  const onKeyDown = (e) => {
54637    callHandler(e, local.onKeyDown);
54638    const isKeyDownInside = contains(e.currentTarget, e.target);
54639    const isCloseKey = SUB_CLOSE_KEYS.close(direction(), rootContext.orientation()).includes(e.key);
54640    const isSubMenu = context3.parentMenuContext() != null;
54641    if (isKeyDownInside && isCloseKey && isSubMenu) {
54642      context3.close();
54643      focusWithoutScrolling(context3.triggerRef());
54644    }
54645  };
54646  return createComponent(MenuContentBase, mergeProps({
54647    onOpenAutoFocus,
54648    onCloseAutoFocus,
54649    onFocusOutside,
54650    onKeyDown
54651  }, others));
54652}
54653var SELECTION_KEYS = ["Enter", " "];
54654var SUB_OPEN_KEYS = {
54655  open: (dir, orientation) => {
54656    if (dir === "ltr") {
54657      return [...SELECTION_KEYS, orientation === "horizontal" ? "ArrowRight" : "ArrowDown"];
54658    }
54659    return [...SELECTION_KEYS, orientation === "horizontal" ? "ArrowLeft" : "ArrowUp"];
54660  }
54661};
54662function MenuSubTrigger(props) {
54663  let ref;
54664  const rootContext = useMenuRootContext();
54665  const context3 = useMenuContext();
54666  const mergedProps = mergeDefaultProps({
54667    id: rootContext.generateId(`sub-trigger-${createUniqueId()}`)
54668  }, props);
54669  const [local, others] = splitProps(mergedProps, ["ref", "id", "textValue", "disabled", "onPointerMove", "onPointerLeave", "onPointerDown", "onPointerUp", "onClick", "onKeyDown", "onMouseDown", "onFocus"]);
54670  let openTimeoutId = null;
54671  const clearOpenTimeout = () => {
54672    if (isServer) {
54673      return;
54674    }
54675    if (openTimeoutId) {
54676      window.clearTimeout(openTimeoutId);
54677    }
54678    openTimeoutId = null;
54679  };
54680  const {
54681    direction
54682  } = useLocale();
54683  const key = () => local.id;
54684  const parentSelectionManager = () => {
54685    const parentMenuContext = context3.parentMenuContext();
54686    if (parentMenuContext == null) {
54687      throw new Error("[kobalte]: `Menu.SubTrigger` must be used within a `Menu.Sub` component");
54688    }
54689    return parentMenuContext.listState().selectionManager();
54690  };
54691  const collection = () => context3.listState().collection();
54692  const isHighlighted = () => parentSelectionManager().focusedKey() === key();
54693  const selectableItem = createSelectableItem({
54694    key,
54695    selectionManager: parentSelectionManager,
54696    shouldSelectOnPressUp: true,
54697    allowsDifferentPressOrigin: true,
54698    disabled: () => local.disabled
54699  }, () => ref);
54700  const onClick = (e) => {
54701    callHandler(e, local.onClick);
54702    if (!context3.isOpen() && !local.disabled) {
54703      context3.open(true);
54704    }
54705  };
54706  const onPointerMove = (e) => {
54707    callHandler(e, local.onPointerMove);
54708    if (e.pointerType !== "mouse") {
54709      return;
54710    }
54711    const parentMenuContext = context3.parentMenuContext();
54712    parentMenuContext?.onItemEnter(e);
54713    if (e.defaultPrevented) {
54714      return;
54715    }
54716    if (local.disabled) {
54717      parentMenuContext?.onItemLeave(e);
54718      return;
54719    }
54720    if (!context3.isOpen() && !openTimeoutId) {
54721      context3.parentMenuContext()?.setPointerGraceIntent(null);
54722      openTimeoutId = window.setTimeout(() => {
54723        context3.open(false);
54724        clearOpenTimeout();
54725      }, 100);
54726    }
54727    parentMenuContext?.onItemEnter(e);
54728    if (!e.defaultPrevented) {
54729      if (context3.listState().selectionManager().isFocused()) {
54730        context3.listState().selectionManager().setFocused(false);
54731        context3.listState().selectionManager().setFocusedKey(void 0);
54732      }
54733      focusWithoutScrolling(e.currentTarget);
54734      parentMenuContext?.listState().selectionManager().setFocused(true);
54735      parentMenuContext?.listState().selectionManager().setFocusedKey(key());
54736    }
54737  };
54738  const onPointerLeave = (e) => {
54739    callHandler(e, local.onPointerLeave);
54740    if (e.pointerType !== "mouse") {
54741      return;
54742    }
54743    clearOpenTimeout();
54744    const parentMenuContext = context3.parentMenuContext();
54745    const contentEl = context3.contentRef();
54746    if (contentEl) {
54747      parentMenuContext?.setPointerGraceIntent({
54748        area: getPointerGraceArea(context3.currentPlacement(), e, contentEl),
54749        // Safe because sub menu always open "left" or "right".
54750        side: context3.currentPlacement().split("-")[0]
54751      });
54752      window.clearTimeout(parentMenuContext?.pointerGraceTimeoutId());
54753      const pointerGraceTimeoutId = window.setTimeout(() => {
54754        parentMenuContext?.setPointerGraceIntent(null);
54755      }, 300);
54756      parentMenuContext?.setPointerGraceTimeoutId(pointerGraceTimeoutId);
54757    } else {
54758      parentMenuContext?.onTriggerLeave(e);
54759      if (e.defaultPrevented) {
54760        return;
54761      }
54762      parentMenuContext?.setPointerGraceIntent(null);
54763    }
54764    parentMenuContext?.onItemLeave(e);
54765  };
54766  const onKeyDown = (e) => {
54767    callHandler(e, local.onKeyDown);
54768    if (e.repeat) {
54769      return;
54770    }
54771    if (local.disabled) {
54772      return;
54773    }
54774    if (SUB_OPEN_KEYS.open(direction(), rootContext.orientation()).includes(e.key)) {
54775      e.stopPropagation();
54776      e.preventDefault();
54777      parentSelectionManager().setFocused(false);
54778      parentSelectionManager().setFocusedKey(void 0);
54779      if (!context3.isOpen()) {
54780        context3.open("first");
54781      }
54782      context3.focusContent();
54783      context3.listState().selectionManager().setFocused(true);
54784      context3.listState().selectionManager().setFocusedKey(collection().getFirstKey());
54785    }
54786  };
54787  createEffect(() => {
54788    if (context3.registerItemToParentDomCollection == null) {
54789      throw new Error("[kobalte]: `Menu.SubTrigger` must be used within a `Menu.Sub` component");
54790    }
54791    const unregister = context3.registerItemToParentDomCollection({
54792      ref: () => ref,
54793      type: "item",
54794      key: key(),
54795      textValue: local.textValue ?? ref?.textContent ?? "",
54796      disabled: local.disabled ?? false
54797    });
54798    onCleanup(unregister);
54799  });
54800  createEffect(on(() => context3.parentMenuContext()?.pointerGraceTimeoutId(), (pointerGraceTimer) => {
54801    onCleanup(() => {
54802      window.clearTimeout(pointerGraceTimer);
54803      context3.parentMenuContext()?.setPointerGraceIntent(null);
54804    });
54805  }));
54806  createEffect(() => onCleanup(context3.registerTriggerId(local.id)));
54807  onCleanup(() => {
54808    clearOpenTimeout();
54809  });
54810  return createComponent(Polymorphic, mergeProps({
54811    as: "div",
54812    ref(r$) {
54813      const _ref$ = mergeRefs((el) => {
54814        context3.setTriggerRef(el);
54815        ref = el;
54816      }, local.ref);
54817      typeof _ref$ === "function" && _ref$(r$);
54818    },
54819    get id() {
54820      return local.id;
54821    },
54822    role: "menuitem",
54823    get tabIndex() {
54824      return selectableItem.tabIndex();
54825    },
54826    "aria-haspopup": "true",
54827    get ["aria-expanded"]() {
54828      return context3.isOpen();
54829    },
54830    get ["aria-controls"]() {
54831      return memo(() => !!context3.isOpen())() ? context3.contentId() : void 0;
54832    },
54833    get ["aria-disabled"]() {
54834      return local.disabled;
54835    },
54836    get ["data-key"]() {
54837      return selectableItem.dataKey();
54838    },
54839    get ["data-highlighted"]() {
54840      return isHighlighted() ? "" : void 0;
54841    },
54842    get ["data-disabled"]() {
54843      return local.disabled ? "" : void 0;
54844    },
54845    get onPointerDown() {
54846      return composeEventHandlers([local.onPointerDown, selectableItem.onPointerDown]);
54847    },
54848    get onPointerUp() {
54849      return composeEventHandlers([local.onPointerUp, selectableItem.onPointerUp]);
54850    },
54851    get onClick() {
54852      return composeEventHandlers([onClick, selectableItem.onClick]);
54853    },
54854    get onKeyDown() {
54855      return composeEventHandlers([onKeyDown, selectableItem.onKeyDown]);
54856    },
54857    get onMouseDown() {
54858      return composeEventHandlers([local.onMouseDown, selectableItem.onMouseDown]);
54859    },
54860    get onFocus() {
54861      return composeEventHandlers([local.onFocus, selectableItem.onFocus]);
54862    },
54863    onPointerMove,
54864    onPointerLeave
54865  }, () => context3.dataset(), others));
54866}
54867
vendor: 2,297 bytes, lines 54868-54943
54868// node_modules/@kobalte/core/dist/chunk/JEP7F7FN.js
54869var dropdown_menu_exports = {};
54870__export(dropdown_menu_exports, {
54871  Arrow: () => PopperArrow,
54872  CheckboxItem: () => MenuCheckboxItem,
54873  Content: () => DropdownMenuContent,
54874  DropdownMenu: () => DropdownMenu,
54875  Group: () => MenuGroup,
54876  GroupLabel: () => MenuGroupLabel,
54877  Icon: () => MenuIcon,
54878  Item: () => MenuItem,
54879  ItemDescription: () => MenuItemDescription,
54880  ItemIndicator: () => MenuItemIndicator,
54881  ItemLabel: () => MenuItemLabel,
54882  Portal: () => MenuPortal,
54883  RadioGroup: () => MenuRadioGroup,
54884  RadioItem: () => MenuRadioItem,
54885  Root: () => DropdownMenuRoot,
54886  Separator: () => SeparatorRoot,
54887  Sub: () => MenuSub,
54888  SubContent: () => MenuSubContent,
54889  SubTrigger: () => MenuSubTrigger,
54890  Trigger: () => MenuTrigger
54891});
54892function DropdownMenuContent(props) {
54893  const rootContext = useMenuRootContext();
54894  const context3 = useMenuContext();
54895  const [local, others] = splitProps(props, ["onCloseAutoFocus", "onInteractOutside"]);
54896  let hasInteractedOutside = false;
54897  const onCloseAutoFocus = (e) => {
54898    local.onCloseAutoFocus?.(e);
54899    if (!hasInteractedOutside) {
54900      focusWithoutScrolling(context3.triggerRef());
54901    }
54902    hasInteractedOutside = false;
54903    e.preventDefault();
54904  };
54905  const onInteractOutside = (e) => {
54906    local.onInteractOutside?.(e);
54907    if (!rootContext.isModal() || e.detail.isContextMenu) {
54908      hasInteractedOutside = true;
54909    }
54910  };
54911  return createComponent(MenuContent, mergeProps({
54912    onCloseAutoFocus,
54913    onInteractOutside
54914  }, others));
54915}
54916function DropdownMenuRoot(props) {
54917  const defaultId = `dropdownmenu-${createUniqueId()}`;
54918  const mergedProps = mergeDefaultProps({
54919    id: defaultId
54920  }, props);
54921  return createComponent(MenuRoot, mergedProps);
54922}
54923var DropdownMenu = Object.assign(DropdownMenuRoot, {
54924  Arrow: PopperArrow,
54925  CheckboxItem: MenuCheckboxItem,
54926  Content: DropdownMenuContent,
54927  Group: MenuGroup,
54928  GroupLabel: MenuGroupLabel,
54929  Icon: MenuIcon,
54930  Item: MenuItem,
54931  ItemDescription: MenuItemDescription,
54932  ItemIndicator: MenuItemIndicator,
54933  ItemLabel: MenuItemLabel,
54934  Portal: MenuPortal,
54935  RadioGroup: MenuRadioGroup,
54936  RadioItem: MenuRadioItem,
54937  Separator: SeparatorRoot,
54938  Sub: MenuSub,
54939  SubContent: MenuSubContent,
54940  SubTrigger: MenuSubTrigger,
54941  Trigger: MenuTrigger
54942});
54943
vendor: 968 bytes, lines 54944-54978
54944// node_modules/@kobalte/core/dist/chunk/3QQCO6IA.js
54945var link_exports = {};
54946__export(link_exports, {
54947  Link: () => Link,
54948  Root: () => LinkRoot
54949});
54950function LinkRoot(props) {
54951  let ref;
54952  const [local, others] = splitProps(props, ["ref", "href", "disabled"]);
54953  const tagName = createTagName(() => ref, () => "a");
54954  return createComponent(Polymorphic, mergeProps({
54955    as: "a",
54956    ref(r$) {
54957      const _ref$ = mergeRefs((el) => ref = el, local.ref);
54958      typeof _ref$ === "function" && _ref$(r$);
54959    },
54960    get role() {
54961      return tagName() !== "a" || local.disabled ? "link" : void 0;
54962    },
54963    get tabIndex() {
54964      return tagName() !== "a" && !local.disabled ? 0 : void 0;
54965    },
54966    get href() {
54967      return !local.disabled ? local.href : void 0;
54968    },
54969    get ["aria-disabled"]() {
54970      return local.disabled ? true : void 0;
54971    },
54972    get ["data-disabled"]() {
54973      return local.disabled ? "" : void 0;
54974    }
54975  }, others));
54976}
54977var Link = LinkRoot;
54978
54979// src/viewer/export.jsx
54980var _tmpl$9 = /* @__PURE__ */ template(`<svg focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M16.59 9H15V4c0-.55-.45-1-1-1h-4c-.55 0-1 .45-1 1v5H7.41c-.89 0-1.34 1.08-.71 1.71l4.59 4.59c.39.39 1.02.39 1.41 0l4.59-4.59c.63-.63.19-1.71-.7-1.71zM5 19c0 .55.45 1 1 1h12c.55 0 1-.45 1-1s-.45-1-1-1H6c-.55 0-1 .45-1 1z">`);
54981var editUrlBase = "https://vzome.com/app/classic/index.html?design=";
54982var ExportMenu = (props) => {
54983  const {
54984    source
54985  } = useViewer();
54986  const {
54987    exporter
54988  } = useGltfExporter();
54989  const downloadGltf = () => {
54990    const {
54991      name
54992    } = source;
54993    const vName = name || "untitled.vZome";
54994    const fileName = vName.substring(0, vName.length - 6).concat(".glb");
54995    const {
54996      exportGltf
54997    } = exporter();
54998    exportGltf((glb) => saveFileAs(fileName, glb, "model/gltf+binary"));
54999  };
55000  const downloadVZome = () => {
55001    const {
55002      name,
55003      text,
55004      changedText
55005    } = source;
55006    const fileName = name || "untitled.vZome";
55007    saveTextFileAs(fileName, text, "application/xml");
55008  };
55009  return createComponent(Show, {
55010    get when() {
55011      return source?.text || source?.changedText;
55012    },
55013    get children() {
55014      return createComponent(DropdownMenu, {
55015        modal: true,
55016        get children() {
55017          return [createComponent(DropdownMenu.Trigger, {
55018            "class": "exports__trigger corner__icon__button",
55019            get children() {
55020              return _tmpl$9();
55021            }
55022          }), createComponent(DropdownMenu.Portal, {
55023            get mount() {
55024              return props.root;
55025            },
55026            get children() {
55027              return createComponent(DropdownMenu.Content, {
55028                "class": "exports__content",
55029                get children() {
55030                  return [createComponent(DropdownMenu.Item, {
55031                    closeOnSelect: true,
55032                    "class": "exports__item",
55033                    get disabled() {
55034                      return !source?.url;
55035                    },
55036                    get children() {
55037                      return createComponent(Link, {
55038                        "class": "link",
55039                        get href() {
55040                          return editUrlBase + source.url;
55041                        },
55042                        target: "_blank",
55043                        rel: "noopener",
55044                        children: "Open in Online vZome"
55045                      });
55046                    }
55047                  }), createComponent(DropdownMenu.Item, {
55048                    onSelect: downloadVZome,
55049                    closeOnSelect: true,
55050                    "class": "exports__item",
55051                    children: "Download .vZome design"
55052                  }), createComponent(DropdownMenu.Item, {
55053                    closeOnSelect: true,
55054                    "class": "exports__item",
55055                    onSelect: downloadGltf,
55056                    children: "Download glTF scene"
55057                  }), createComponent(DropdownMenu.Arrow, {})];
55058                }
55059              });
55060            }
55061          })];
55062        }
55063      });
55064    }
55065  });
55066};
55067
vendor: 3,243 bytes, lines 55068-55145
55068// node_modules/@kobalte/core/dist/chunk/YKGT7A57.js
55069var FORM_CONTROL_PROP_NAMES = ["id", "name", "validationState", "required", "disabled", "readOnly"];
55070function createFormControl(props) {
55071  const defaultId = `form-control-${createUniqueId()}`;
55072  const mergedProps = mergeDefaultProps({
55073    id: defaultId
55074  }, props);
55075  const [labelId, setLabelId] = createSignal();
55076  const [fieldId, setFieldId] = createSignal();
55077  const [descriptionId, setDescriptionId] = createSignal();
55078  const [errorMessageId, setErrorMessageId] = createSignal();
55079  const getAriaLabelledBy = (fieldId2, fieldAriaLabel, fieldAriaLabelledBy) => {
55080    const hasAriaLabelledBy = fieldAriaLabelledBy != null || labelId() != null;
55081    return [
55082      fieldAriaLabelledBy,
55083      labelId(),
55084      // If there is both an aria-label and aria-labelledby, add the field itself has an aria-labelledby
55085      hasAriaLabelledBy && fieldAriaLabel != null ? fieldId2 : void 0
55086    ].filter(Boolean).join(" ") || void 0;
55087  };
55088  const getAriaDescribedBy = (fieldAriaDescribedBy) => {
55089    return [
55090      descriptionId(),
55091      // Use aria-describedby for error message because aria-errormessage is unsupported using VoiceOver or NVDA.
55092      // See https://github.com/adobe/react-spectrum/issues/1346#issuecomment-740136268
55093      errorMessageId(),
55094      fieldAriaDescribedBy
55095    ].filter(Boolean).join(" ") || void 0;
55096  };
55097  const dataset = createMemo(() => ({
55098    "data-valid": access4(mergedProps.validationState) === "valid" ? "" : void 0,
55099    "data-invalid": access4(mergedProps.validationState) === "invalid" ? "" : void 0,
55100    "data-required": access4(mergedProps.required) ? "" : void 0,
55101    "data-disabled": access4(mergedProps.disabled) ? "" : void 0,
55102    "data-readonly": access4(mergedProps.readOnly) ? "" : void 0
55103  }));
55104  const formControlContext = {
55105    name: () => access4(mergedProps.name) ?? access4(mergedProps.id),
55106    dataset,
55107    validationState: () => access4(mergedProps.validationState),
55108    isRequired: () => access4(mergedProps.required),
55109    isDisabled: () => access4(mergedProps.disabled),
55110    isReadOnly: () => access4(mergedProps.readOnly),
55111    labelId,
55112    fieldId,
55113    descriptionId,
55114    errorMessageId,
55115    getAriaLabelledBy,
55116    getAriaDescribedBy,
55117    generateId: createGenerateId(() => access4(mergedProps.id)),
55118    registerLabel: createRegisterId(setLabelId),
55119    registerField: createRegisterId(setFieldId),
55120    registerDescription: createRegisterId(setDescriptionId),
55121    registerErrorMessage: createRegisterId(setErrorMessageId)
55122  };
55123  return {
55124    formControlContext
55125  };
55126}
55127var FormControlContext = createContext();
55128function useFormControlContext() {
55129  const context3 = useContext(FormControlContext);
55130  if (context3 === void 0) {
55131    throw new Error("[kobalte]: `useFormControlContext` must be used within a `FormControlContext.Provider` component");
55132  }
55133  return context3;
55134}
55135function FormControlDescription(props) {
55136  const context3 = useFormControlContext();
55137  const mergedProps = mergeDefaultProps({
55138    id: context3.generateId("description")
55139  }, props);
55140  createEffect(() => onCleanup(context3.registerDescription(mergedProps.id)));
55141  return createComponent(Polymorphic, mergeProps({
55142    as: "div"
55143  }, () => context3.dataset(), mergedProps));
55144}
55145
vendor: 815 bytes, lines 55146-55163
55146// node_modules/@kobalte/core/dist/chunk/K6P57S75.js
55147var FORM_CONTROL_FIELD_PROP_NAMES = ["id", "aria-label", "aria-labelledby", "aria-describedby"];
55148function createFormControlField(props) {
55149  const context3 = useFormControlContext();
55150  const mergedProps = mergeDefaultProps({
55151    id: context3.generateId("field")
55152  }, props);
55153  createRenderEffect(() => onCleanup(context3.registerField(access4(mergedProps.id))));
55154  return {
55155    fieldProps: {
55156      id: () => access4(mergedProps.id),
55157      ariaLabel: () => access4(mergedProps["aria-label"]),
55158      ariaLabelledBy: () => context3.getAriaLabelledBy(access4(mergedProps.id), access4(mergedProps["aria-label"]), access4(mergedProps["aria-labelledby"])),
55159      ariaDescribedBy: () => context3.getAriaDescribedBy(access4(mergedProps["aria-describedby"]))
55160    }
55161  };
55162}
55163
vendor: 769 bytes, lines 55164-55185
55164// node_modules/@kobalte/core/dist/chunk/7ZHN3PYD.js
55165function FormControlLabel(props) {
55166  let ref;
55167  const context3 = useFormControlContext();
55168  const mergedProps = mergeDefaultProps({
55169    id: context3.generateId("label")
55170  }, props);
55171  const [local, others] = splitProps(mergedProps, ["ref"]);
55172  const tagName = createTagName(() => ref, () => "label");
55173  createEffect(() => onCleanup(context3.registerLabel(others.id)));
55174  return createComponent(Polymorphic, mergeProps({
55175    as: "label",
55176    ref(r$) {
55177      const _ref$ = mergeRefs((el) => ref = el, local.ref);
55178      typeof _ref$ === "function" && _ref$(r$);
55179    },
55180    get ["for"]() {
55181      return memo(() => tagName() === "label")() ? context3.fieldId() : void 0;
55182    }
55183  }, () => context3.dataset(), others));
55184}
55185
vendor: 689 bytes, lines 55186-55210
55186// node_modules/@kobalte/core/dist/chunk/ANN3A2QM.js
55187function createFormResetListener(element3, handler) {
55188  createEffect(
55189    on(element3, (element22) => {
55190      if (element22 == null) {
55191        return;
55192      }
55193      const form = getClosestForm(element22);
55194      if (form == null) {
55195        return;
55196      }
55197      form.addEventListener("reset", handler, { passive: true });
55198      onCleanup(() => {
55199        form.removeEventListener("reset", handler);
55200      });
55201    })
55202  );
55203}
55204function getClosestForm(element3) {
55205  return isFormElement(element3) ? element3.form : element3.closest("form");
55206}
55207function isFormElement(element3) {
55208  return element3.matches("textarea, input, select, button");
55209}
55210
vendor: 761 bytes, lines 55211-55236
55211// node_modules/@kobalte/core/dist/chunk/ICNSTULC.js
55212function FormControlErrorMessage(props) {
55213  const context3 = useFormControlContext();
55214  const mergedProps = mergeDefaultProps({
55215    id: context3.generateId("error-message")
55216  }, props);
55217  const [local, others] = splitProps(mergedProps, ["forceMount"]);
55218  const isInvalid = () => context3.validationState() === "invalid";
55219  createEffect(() => {
55220    if (!isInvalid()) {
55221      return;
55222    }
55223    onCleanup(context3.registerErrorMessage(others.id));
55224  });
55225  return createComponent(Show, {
55226    get when() {
55227      return local.forceMount || isInvalid();
55228    },
55229    get children() {
55230      return createComponent(Polymorphic, mergeProps({
55231        as: "div"
55232      }, () => context3.dataset(), others));
55233    }
55234  });
55235}
55236
vendor: 7,714 bytes, lines 55237-55485
55237// node_modules/@kobalte/core/dist/chunk/YPUNLYJC.js
55238var switch_exports = {};
55239__export(switch_exports, {
55240  Control: () => SwitchControl,
55241  Description: () => SwitchDescription,
55242  ErrorMessage: () => SwitchErrorMessage,
55243  Input: () => SwitchInput,
55244  Label: () => SwitchLabel,
55245  Root: () => SwitchRoot,
55246  Switch: () => Switch3,
55247  Thumb: () => SwitchThumb,
55248  useSwitchContext: () => useSwitchContext
55249});
55250var SwitchContext = createContext();
55251function useSwitchContext() {
55252  const context3 = useContext(SwitchContext);
55253  if (context3 === void 0) {
55254    throw new Error("[kobalte]: `useSwitchContext` must be used within a `Switch` component");
55255  }
55256  return context3;
55257}
55258function SwitchControl(props) {
55259  const formControlContext = useFormControlContext();
55260  const context3 = useSwitchContext();
55261  const mergedProps = mergeDefaultProps({
55262    id: context3.generateId("control")
55263  }, props);
55264  const [local, others] = splitProps(mergedProps, ["onClick", "onKeyDown"]);
55265  const onClick = (e) => {
55266    callHandler(e, local.onClick);
55267    context3.toggle();
55268    context3.inputRef()?.focus({
55269      preventScroll: true
55270    });
55271  };
55272  const onKeyDown = (e) => {
55273    callHandler(e, local.onKeyDown);
55274    if (e.key === EventKey.Space) {
55275      context3.toggle();
55276      context3.inputRef()?.focus({
55277        preventScroll: true
55278      });
55279    }
55280  };
55281  return createComponent(Polymorphic, mergeProps({
55282    as: "div",
55283    onClick,
55284    onKeyDown
55285  }, () => formControlContext.dataset(), () => context3.dataset(), others));
55286}
55287function SwitchDescription(props) {
55288  const context3 = useSwitchContext();
55289  return createComponent(FormControlDescription, mergeProps(() => context3.dataset(), props));
55290}
55291function SwitchErrorMessage(props) {
55292  const context3 = useSwitchContext();
55293  return createComponent(FormControlErrorMessage, mergeProps(() => context3.dataset(), props));
55294}
55295function SwitchInput(props) {
55296  const formControlContext = useFormControlContext();
55297  const context3 = useSwitchContext();
55298  const mergedProps = mergeDefaultProps({
55299    id: context3.generateId("input")
55300  }, props);
55301  const [local, formControlFieldProps, others] = splitProps(mergedProps, ["ref", "style", "onChange", "onFocus", "onBlur"], FORM_CONTROL_FIELD_PROP_NAMES);
55302  const {
55303    fieldProps
55304  } = createFormControlField(formControlFieldProps);
55305  const onChange = (e) => {
55306    callHandler(e, local.onChange);
55307    e.stopPropagation();
55308    const target = e.target;
55309    context3.setIsChecked(target.checked);
55310    target.checked = context3.checked();
55311  };
55312  const onFocus = (e) => {
55313    callHandler(e, local.onFocus);
55314    context3.setIsFocused(true);
55315  };
55316  const onBlur = (e) => {
55317    callHandler(e, local.onBlur);
55318    context3.setIsFocused(false);
55319  };
55320  return createComponent(Polymorphic, mergeProps({
55321    as: "input",
55322    ref(r$) {
55323      const _ref$ = mergeRefs(context3.setInputRef, local.ref);
55324      typeof _ref$ === "function" && _ref$(r$);
55325    },
55326    type: "checkbox",
55327    role: "switch",
55328    get id() {
55329      return fieldProps.id();
55330    },
55331    get name() {
55332      return formControlContext.name();
55333    },
55334    get value() {
55335      return context3.value();
55336    },
55337    get checked() {
55338      return context3.checked();
55339    },
55340    get required() {
55341      return formControlContext.isRequired();
55342    },
55343    get disabled() {
55344      return formControlContext.isDisabled();
55345    },
55346    get readonly() {
55347      return formControlContext.isReadOnly();
55348    },
55349    get style() {
55350      return combineStyle({
55351        ...visuallyHiddenStyles
55352      }, local.style);
55353    },
55354    get ["aria-checked"]() {
55355      return context3.checked();
55356    },
55357    get ["aria-label"]() {
55358      return fieldProps.ariaLabel();
55359    },
55360    get ["aria-labelledby"]() {
55361      return fieldProps.ariaLabelledBy();
55362    },
55363    get ["aria-describedby"]() {
55364      return fieldProps.ariaDescribedBy();
55365    },
55366    get ["aria-invalid"]() {
55367      return formControlContext.validationState() === "invalid" || void 0;
55368    },
55369    get ["aria-required"]() {
55370      return formControlContext.isRequired() || void 0;
55371    },
55372    get ["aria-disabled"]() {
55373      return formControlContext.isDisabled() || void 0;
55374    },
55375    get ["aria-readonly"]() {
55376      return formControlContext.isReadOnly() || void 0;
55377    },
55378    onChange,
55379    onFocus,
55380    onBlur
55381  }, () => formControlContext.dataset(), () => context3.dataset(), others));
55382}
55383function SwitchLabel(props) {
55384  const context3 = useSwitchContext();
55385  return createComponent(FormControlLabel, mergeProps(() => context3.dataset(), props));
55386}
55387function SwitchRoot(props) {
55388  let ref;
55389  const defaultId = `switch-${createUniqueId()}`;
55390  const mergedProps = mergeDefaultProps({
55391    value: "on",
55392    id: defaultId
55393  }, props);
55394  const [local, formControlProps, others] = splitProps(mergedProps, ["ref", "children", "value", "checked", "defaultChecked", "onChange", "onPointerDown"], FORM_CONTROL_PROP_NAMES);
55395  const [inputRef, setInputRef] = createSignal();
55396  const [isFocused, setIsFocused] = createSignal(false);
55397  const {
55398    formControlContext
55399  } = createFormControl(formControlProps);
55400  const state = createToggleState({
55401    isSelected: () => local.checked,
55402    defaultIsSelected: () => local.defaultChecked,
55403    onSelectedChange: (selected) => local.onChange?.(selected),
55404    isDisabled: () => formControlContext.isDisabled(),
55405    isReadOnly: () => formControlContext.isReadOnly()
55406  });
55407  createFormResetListener(() => ref, () => state.setIsSelected(local.defaultChecked ?? false));
55408  const onPointerDown = (e) => {
55409    callHandler(e, local.onPointerDown);
55410    if (isFocused()) {
55411      e.preventDefault();
55412    }
55413  };
55414  const dataset = createMemo(() => ({
55415    "data-checked": state.isSelected() ? "" : void 0
55416  }));
55417  const context3 = {
55418    value: () => local.value,
55419    dataset,
55420    checked: () => state.isSelected(),
55421    inputRef,
55422    generateId: createGenerateId(() => access4(formControlProps.id)),
55423    toggle: () => state.toggle(),
55424    setIsChecked: (isChecked) => state.setIsSelected(isChecked),
55425    setIsFocused,
55426    setInputRef
55427  };
55428  return createComponent(FormControlContext.Provider, {
55429    value: formControlContext,
55430    get children() {
55431      return createComponent(SwitchContext.Provider, {
55432        value: context3,
55433        get children() {
55434          return createComponent(Polymorphic, mergeProps({
55435            as: "div",
55436            ref(r$) {
55437              const _ref$ = mergeRefs((el) => ref = el, local.ref);
55438              typeof _ref$ === "function" && _ref$(r$);
55439            },
55440            role: "group",
55441            get id() {
55442              return access4(formControlProps.id);
55443            },
55444            onPointerDown
55445          }, () => formControlContext.dataset(), dataset, others, {
55446            get children() {
55447              return createComponent(SwitchRootChild, {
55448                state: context3,
55449                get children() {
55450                  return local.children;
55451                }
55452              });
55453            }
55454          }));
55455        }
55456      });
55457    }
55458  });
55459}
55460function SwitchRootChild(props) {
55461  const resolvedChildren = children(() => {
55462    const body = props.children;
55463    return isFunction(body) ? body(props.state) : body;
55464  });
55465  return memo(resolvedChildren);
55466}
55467function SwitchThumb(props) {
55468  const formControlContext = useFormControlContext();
55469  const context3 = useSwitchContext();
55470  const mergedProps = mergeDefaultProps({
55471    id: context3.generateId("thumb")
55472  }, props);
55473  return createComponent(Polymorphic, mergeProps({
55474    as: "div"
55475  }, () => formControlContext.dataset(), () => context3.dataset(), mergedProps));
55476}
55477var Switch3 = Object.assign(SwitchRoot, {
55478  Control: SwitchControl,
55479  Description: SwitchDescription,
55480  ErrorMessage: SwitchErrorMessage,
55481  Input: SwitchInput,
55482  Label: SwitchLabel,
55483  Thumb: SwitchThumb
55484});
55485
55486// src/viewer/settings.jsx
55487var _tmpl$10 = /* @__PURE__ */ template(`<div class="settingsdialog__header">`);
55488var _tmpl$25 = /* @__PURE__ */ template(`<div class="settingsdialog__body">`);
55489var _tmpl$32 = /* @__PURE__ */ template(`<div class="settingsdialog__positioner">`);
55490var Settings = (props) => {
55491  const {
55492    togglePerspective,
55493    toggleOutlines,
55494    state
55495  } = useCamera();
55496  return createComponent(Dialog, {
55497    open: true,
55498    get children() {
55499      return createComponent(Dialog.Portal, {
55500        get mount() {
55501          return props.root;
55502        },
55503        get children() {
55504          return [createComponent(Dialog.Overlay, {
55505            "class": "settingsdialog__overlay"
55506          }), (() => {
55507            const _el$ = _tmpl$32();
55508            insert(_el$, createComponent(Dialog.Content, {
55509              "class": "settingsdialog__content",
55510              get children() {
55511                return [(() => {
55512                  const _el$2 = _tmpl$10();
55513                  insert(_el$2, createComponent(Dialog.Title, {
55514                    "class": "settingsdialog__title",
55515                    children: "View Settings"
55516                  }), null);
55517                  insert(_el$2, createComponent(Dialog.CloseButton, {
55518                    "class": "dialog__close-button",
55519                    get onClick() {
55520                      return props.close;
55521                    },
55522                    children: "x"
55523                  }), null);
55524                  return _el$2;
55525                })(), (() => {
55526                  const _el$3 = _tmpl$25();
55527                  insert(_el$3, createComponent(Switch3, {
55528                    "class": "switch",
55529                    get checked() {
55530                      return state.camera.perspective;
55531                    },
55532                    onChange: togglePerspective,
55533                    get children() {
55534                      return [createComponent(Switch3.Label, {
55535                        "class": "switch__label",
55536                        children: "Perspective"
55537                      }), createComponent(Switch3.Input, {
55538                        "class": "switch__input"
55539                      }), createComponent(Switch3.Control, {
55540                        "class": "switch__control",
55541                        get children() {
55542                          return createComponent(Switch3.Thumb, {
55543                            "class": "switch__thumb"
55544                          });
55545                        }
55546                      })];
55547                    }
55548                  }), null);
55549                  insert(_el$3, createComponent(Show, {
55550                    get when() {
55551                      return props.showOutlines;
55552                    },
55553                    get children() {
55554                      return createComponent(Switch3, {
55555                        "class": "switch",
55556                        get checked() {
55557                          return state.outlines;
55558                        },
55559                        onChange: toggleOutlines,
55560                        get children() {
55561                          return [createComponent(Switch3.Label, {
55562                            "class": "switch__label",
55563                            children: "Outlines"
55564                          }), createComponent(Switch3.Input, {
55565                            "class": "switch__input"
55566                          }), createComponent(Switch3.Control, {
55567                            "class": "switch__control",
55568                            get children() {
55569                              return createComponent(Switch3.Thumb, {
55570                                "class": "switch__thumb"
55571                              });
55572                            }
55573                          })];
55574                        }
55575                      });
55576                    }
55577                  }), null);
55578                  return _el$3;
55579                })()];
55580              }
55581            }));
55582            return _el$;
55583          })()];
55584        }
55585      });
55586    }
55587  });
55588};
55589
55590// src/viewer/index.jsx
55591var _tmpl$11 = /* @__PURE__ */ template(`<svg aria-hidden="true" viewBox="-1 -1 25 25" focusable="false" data-testid="SettingsIcon"><g><path d="M0,0h24v24H0V0z" fill="none"></path><path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z">`);
55592var _tmpl$26 = /* @__PURE__ */ template(`<div id="scene-viewer">`);
55593var _tmpl$33 = /* @__PURE__ */ template(`<div>`);
55594console.log(`vzome-viewer revision ${REVISION2}`);
55595var stylesAdded = false;
55596var normalStyle = {
55597  display: "flex",
55598  // flex is for the light dom content, usually an image
55599  height: "100%",
55600  width: "100%",
55601  position: "relative",
55602  overflow: "hidden"
55603  // curiously, this forces Canvas to recompute its size when changing back
55604};
55605var SceneViewer = (props) => {
55606  const dynConfig = () => mergeProps({
55607    allowFullViewport: false,
55608    showSettings: true,
55609    showOutlines: true
55610  }, props.config);
55611  const {
55612    scene
55613  } = useScene();
55614  const [showSettings, setShowSettings] = createSignal(false);
55615  let rootRef;
55616  const [fullScreen, setFullScreen] = createSignal(false);
55617  const toggleFullScreen = () => {
55618    if (document.fullscreenElement) {
55619      document.exitFullscreen();
55620    } else if (document.fullscreenEnabled && rootRef.requestFullscreen) {
55621      rootRef.requestFullscreen();
55622    }
55623  };
55624  const fullscreenListener = () => setFullScreen(!!document.fullscreenElement);
55625  document.addEventListener("fullscreenchange", fullscreenListener);
55626  getOwner() && onCleanup(() => {
55627    document.removeEventListener("fullscreenchange", fullscreenListener);
55628    if (document.fullscreenElement) {
55629      document.exitFullscreen();
55630    }
55631  });
55632  return (() => {
55633    const _el$ = _tmpl$26();
55634    const _ref$ = rootRef;
55635    typeof _ref$ === "function" ? use(_ref$, _el$) : rootRef = _el$;
55636    style(_el$, normalStyle);
55637    insert(_el$, createComponent(InteractionToolProvider, {
55638      get children() {
55639        return createComponent(GltfExportProvider, {
55640          get children() {
55641            return [createComponent(Show, {
55642              when: scene,
55643              get fallback() {
55644                return props.children;
55645              },
55646              get children() {
55647                return createComponent(SceneCanvas, {
55648                  get symmetryRenderer() {
55649                    return dynConfig().symmetryRenderer !== false;
55650                  },
55651                  id: "scene-canvas",
55652                  get height() {
55653                    return props.height;
55654                  },
55655                  get width() {
55656                    return props.width;
55657                  },
55658                  get children() {
55659                    return props.children3d;
55660                  }
55661                });
55662              }
55663            }), createComponent(Show, {
55664              get when() {
55665                return dynConfig().showSettings;
55666              },
55667              get children() {
55668                return createComponent(IconButton, {
55669                  "class": "settings-button",
55670                  tooltip: "Show settings",
55671                  onClick: () => setShowSettings(true),
55672                  root: rootRef,
55673                  get children() {
55674                    return _tmpl$11();
55675                  }
55676                });
55677              }
55678            }), createComponent(Show, {
55679              get when() {
55680                return showSettings();
55681              },
55682              get children() {
55683                return createComponent(Settings, {
55684                  root: rootRef,
55685                  get showOutlines() {
55686                    return memo(() => !!scene?.polygons)() && dynConfig().showOutlines;
55687                  },
55688                  close: () => setShowSettings(false)
55689                });
55690              }
55691            }), createComponent(Show, {
55692              get when() {
55693                return dynConfig().allowFullViewport;
55694              },
55695              get children() {
55696                return createComponent(FullscreenButton, {
55697                  get fullScreen() {
55698                    return fullScreen();
55699                  },
55700                  root: rootRef,
55701                  toggle: toggleFullScreen
55702                });
55703              }
55704            }), memo(() => props.children)];
55705          }
55706        });
55707      }
55708    }));
55709    return _el$;
55710  })();
55711};
55712var InitializeScene = (props) => {
55713  const {
55714    showIndexedScene
55715  }
55715 = useSceneIndexing();
55716  const {
55717    showTitledScene,
55718    sceneTitle
55719  } = useSceneTitles();
55720  createEffect(() => {
55721    if (props.showScenes === "indexed") {
55722      showIndexedScene(1);
55723    } else if (props.showScenes === "none") {
55724      showIndexedScene(0);
55725    } else if (props.showScenes !== "managed") {
55726      showTitledScene(sceneTitle());
55727    }
55728  });
55729  return null;
55730};
55731var DesignViewer = (props) => {
55732  const dynConfig = () => mergeProps({
55733    showScenes: "none",
55734    useSpinner: false,
55735    download: true
55736  }, props.config);
55737  const {
55738    waiting
55739  } = useViewer();
55740  const showSpinner = () => {
55741    return props.config?.useSpinner && waiting();
55742  };
55743  onMount(() => {
55744    if (!props.componentRoot && !stylesAdded) {
55745      document.body.appendChild(document.createElement("style")).textContent = urlViewerCSS;
55746      stylesAdded = true;
55747    }
55748  });
55749  let rootRef;
55750  return createComponent(SceneTitlesProvider, {
55751    get show() {
55752      return dynConfig().showScenes;
55753    },
55754    get title() {
55755      return dynConfig().sceneTitle;
55756    },
55757    get children() {
55758      return createComponent(SceneViewer, {
55759        get children3d() {
55760          return props.children3d;
55761        },
55762        get height() {
55763          return props.height;
55764        },
55765        get width() {
55766          return props.width;
55767        },
55768        get config() {
55769          return dynConfig();
55770        },
55771        get children() {
55772          return [createComponent(InitializeScene, {
55773            get showScenes() {
55774              return dynConfig().showScenes;
55775            }
55776          }), (() => {
55777            const _el$3 = _tmpl$33();
55778            const _ref$2 = rootRef;
55779            typeof _ref$2 === "function" ? use(_ref$2, _el$3) : rootRef = _el$3;
55780            insert(_el$3, createComponent(Show, {
55781              get when() {
55782                return dynConfig().download;
55783              },
55784              get children() {
55785                return createComponent(ExportMenu, {
55786                  root: rootRef
55787                });
55788              }
55789            }), null);
55790            insert(_el$3, createComponent(Show, {
55791              get when() {
55792                return showSpinner();
55793              },
55794              get children() {
55795                return createComponent(Spinner, {
55796                  root: rootRef
55797                });
55798              }
55799            }), null);
55800            insert(_el$3, createComponent(ErrorAlert, {
55801              root: rootRef
55802            }), null);
55803            insert(_el$3, () => props.children, null);
55804            insert(_el$3, createComponent(Show, {
55805              get when() {
55806                return dynConfig().showScenes === "all" || dynConfig().showScenes === "titled";
55807              },
55808              get children() {
55809                return createComponent(SceneMenu, {
55810                  root: rootRef
55811                });
55812              }
55813            }), null);
55814            return _el$3;
55815          })()];
55816        }
55817      });
55818    }
55819  });
55820};
55821var UrlViewer = (props) => {
55822  return createComponent(ImageCaptureProvider, {
55823    get children() {
55824      return createComponent(CameraProvider, {
55825        get tweening() {
55826          return props.config?.tweening;
55827        },
55828        get children() {
55829          return createComponent(WorkerProvider, {
55830            get children() {
55831              return createComponent(ViewerProvider, {
55832                get config() {
55833                  return {
55834                    url: props.url,
55835                    preview: true,
55836                    debug: false,
55837                    labels: props.config?.labels,
55838                    source: props.config?.download
55839                  };
55840                },
55841                get children() {
55842                  return createComponent(SceneProvider, {
55843                    get index() {
55844                      return props.config.snapshot;
55845                    },
55846                    get config() {
55847                      return props.config;
55848                    },
55849                    get children() {
55850                      return createComponent(SceneIndexingProvider, {
55851                        get children() {
55852                          return createComponent(DesignViewer, {
55853                            get config() {
55854                              return {
55855                                ...props.config,
55856                                allowFullViewport: true
55857                              };
55858                            },
55859                            get componentRoot() {
55860                              return props.componentRoot;
55861                            },
55862                            height: "100%",
55863                            width: "100%",
55864                            get children() {
55865                              return props.children;
55866                            }
55867                          });
55868                        }
55869                      });
55870                    }
55871                  });
55872                }
55873              });
55874            }
55875          });
55876        }
55877      });
55878    }
55879  });
55880};
55881var WebComponentBindings = (props) => {
55882  const {
55883    showIndexedScene,
55884    lastSceneIndex,
55885    setLastSceneIndex
55886  } = useSceneIndexing();
55887  const {
55888    setTweenDuration
55889  } = useCamera();
55890  const {
55891    requestDesign,
55892    resetScenes,
55893    openText,
55894    exportAs,
55895    indexResources
55896  } = useViewer();
55897  const {
55898    captureImage
55899  } = useImageCapture();
55900  const {
55901    showTitledScene
55902  } = useSceneTitles();
55903  const apiObject = {
55904    showIndexedScene,
55905    showTitledScene,
55906    requestDesign,
55907    setTweenDuration,
55908    resetScenes,
55909    openText,
55910    exportAs,
55911    captureImage
55912  };
55913  const {
55914    subscribeFor
55915  } = useWorkerClient();
55916  const {
55917    setApi,
55918    onAlert,
55919    onSceneRendered,
55920    onScenesDiscovered
55921  } = props.callbacks;
55922  indexResources();
55923  setApi(apiObject);
55924  subscribeFor("ALERT_RAISED", onAlert);
55925  subscribeFor("SCENES_DISCOVERED", ({
55926    scenes
55927  }) => {
55928    setLastSceneIndex(null);
55929    onScenesDiscovered(scenes);
55930  });
55931  createEffect(() => {
55932    if (lastSceneIndex() !== null) {
55933      onSceneRendered(lastSceneIndex());
55934    }
55935  });
55936  return null;
55937};
55938var renderViewer = (container, config, callbacks) => {
55939  const bindComponent = () => {
55940    return createComponent(UrlViewer, {
55941      config,
55942      componentRoot: container,
55943      get children() {
55944        return createComponent(WebComponentBindings, {
55945          callbacks
55946        });
55947      }
55948    });
55949  };
55950  container.appendChild(document.createElement("style")).textContent = urlViewerCSS;
55951  const linkElem = document.createElement("link");
55952  linkElem.setAttribute("rel", "stylesheet");
55953  linkElem.setAttribute("href", "./vzome-viewer-styles.css");
55954  container.appendChild(linkElem);
55955  render(bindComponent, container);
55956};
55957
55958export {
55959  urlViewerCSS,
55960  SceneProvider,
55961  useScene,
55962  useSceneIndexing,
55963  SceneIndexingProvider,
55964  useSceneTitles,
55965  getSceneTitleIndex,
55966  SceneTitlesProvider,
55967  SceneChangeListener,
55968  grabTool,
55969  InteractionToolProvider,
55970  useInteractionTool,
55971  GltfExportProvider,
55972  useGltfExporter,
55973  ImageCaptureProvider,
55974  useImageCapture,
55975  useWebXRClient,
55976  LightedTrackballCanvas,
55977  ShapedGeometry,
55978  SceneCanvas,
55979  Key,
55980  combineStyle,
55981  mergeRefs,
55982  access4 as access,
55983  isFunction,
55984  createGenerateId,
55985  contains,
55986  isMac,
55987  isWebKit,
55988  callHandler,
55989  composeEventHandlers,
55990  focusWithoutScrolling,
55991  getFocusableTreeWalker,
55992  clamp7 as clamp,
55993  snapValueToStep,
55994  mergeDefaultProps,
55995  visuallyHiddenStyles,
55996  createFocusScope,
55997  createHideOutside,
55998  createInteractOutside,
55999  Polymorphic,
56000  DismissableLayer,
56001  createControllableSignal,
56002  createControllableArraySignal,
56003  createDisclosureState,
56004  __export,
56005  ButtonRoot,
56006  Button,
56007  createRegisterId,
56008  index_default,
56009  index_default2,
56010  Dialog,
56011  useLocale,
56012  createCollator,
56013  createNumberFormatter,
56014  PopperArrow,
56015  Popper,
56016  IconButton,
56017  SeparatorRoot,
56018  Selection,
56019  isSameSelection,
56020  createTypeSelect,
56021  createSelectableCollection,
56022  createSelectableItem,
56023  createListState,
56024  ListKeyboardDelegate,
56025  createSelectableList,
56026  createDomCollection,
56027  createDomCollectionItem,
56028  MenubarContext,
56029  useMenubarContext,
56030  useOptionalMenuContext,
56031  useMenuContext,
56032  useMenuRootContext,
56033  MenuCheckboxItem,
56034  MenuTrigger,
56035  MenuContent,
56036  MenuGroup,
56037  MenuGroupLabel,
56038  MenuIcon,
56039  MenuItem,
56040  MenuItemDescription,
56041  MenuItemIndicator,
56042  MenuItemLabel,
56043  MenuPortal,
56044  MenuRadioGroup,
56045  MenuRadioItem,
56046  MenuRoot,
56047  MenuSub,
56048  MenuSubContent,
56049  MenuSubTrigger,
56050  Link,
56051  FORM_CONTROL_PROP_NAMES,
56052  createFormControl,
56053  FormControlContext,
56054  useFormControlContext,
56055  FormControlDescription,
56056  FORM_CONTROL_FIELD_PROP_NAMES,
56057  createFormControlField,
56058  FormControlLabel,
56059  createFormResetListener,
56060  FormControlErrorMessage,
56061  Switch3 as Switch,
56062  SceneViewer,
56063  InitializeScene,
56064  DesignViewer,
56065  UrlViewer,
56066  renderViewer
56067};
56068/*! Bundled license information:
56069
56070three/build/three.webgpu.js:
56071three/build/three.tsl.js:
56072  (**
56073   * @license
56074   * Copyright 2010-2026 Three.js Authors
56075   * SPDX-License-Identifier: MIT
56076   *)
56077*/

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.