@zephyr3d/editor 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +143 -0
  2. package/dist/assets/{index-BaUzUcND.js → index-IISR7uQv.js} +1 -1
  3. package/dist/assistant/zephyr-types-index.json +1 -1
  4. package/dist/index.html +2 -2
  5. package/dist/modules/zephyr3d_backend-webgpu.js.map +1 -1
  6. package/dist/modules/zephyr3d_imgui.js +3 -3
  7. package/dist/modules/zephyr3d_imgui.js.map +1 -1
  8. package/dist/modules/zephyr3d_scene.js +1439 -1439
  9. package/dist/modules/zephyr3d_scene.js.map +1 -1
  10. package/dist/vendor/zephyr3d/backend-webgpu/dist/bindgroup_webgpu.js.map +1 -1
  11. package/dist/vendor/zephyr3d/backend-webgpu/dist/buffer_webgpu.js.map +1 -1
  12. package/dist/vendor/zephyr3d/backend-webgpu/dist/commandqueue.js.map +1 -1
  13. package/dist/vendor/zephyr3d/backend-webgpu/dist/uploadringbuffer.js.map +1 -1
  14. package/dist/vendor/zephyr3d/imgui/dist/imgui_impl.js.map +1 -1
  15. package/dist/vendor/zephyr3d/imgui/dist/renderer.js +3 -3
  16. package/dist/vendor/zephyr3d/imgui/dist/renderer.js.map +1 -1
  17. package/dist/vendor/zephyr3d/scene/dist/animation/animationset.js +135 -135
  18. package/dist/vendor/zephyr3d/scene/dist/animation/animationset.js.map +1 -1
  19. package/dist/vendor/zephyr3d/scene/dist/animation/joint_dynamics/controller.js +146 -146
  20. package/dist/vendor/zephyr3d/scene/dist/animation/joint_dynamics/controller.js.map +1 -1
  21. package/dist/vendor/zephyr3d/scene/dist/animation/spring/spring_system.js +75 -75
  22. package/dist/vendor/zephyr3d/scene/dist/animation/spring/spring_system.js.map +1 -1
  23. package/dist/vendor/zephyr3d/scene/dist/camera/camera.js +184 -184
  24. package/dist/vendor/zephyr3d/scene/dist/camera/camera.js.map +1 -1
  25. package/dist/vendor/zephyr3d/scene/dist/material/material.js +288 -288
  26. package/dist/vendor/zephyr3d/scene/dist/material/material.js.map +1 -1
  27. package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/history_resource_manager.js +93 -93
  28. package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/history_resource_manager.js.map +1 -1
  29. package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/history_resources.js +3 -3
  30. package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/history_resources.js.map +1 -1
  31. package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/types.js +22 -22
  32. package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/types.js.map +1 -1
  33. package/dist/vendor/zephyr3d/scene/dist/utility/blueprint/material/ir.js +489 -489
  34. package/dist/vendor/zephyr3d/scene/dist/utility/blueprint/material/ir.js.map +1 -1
  35. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/animation.js.map +1 -1
  36. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/camera.js.map +1 -1
  37. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/common.js.map +1 -1
  38. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/light.js.map +1 -1
  39. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/material.js.map +1 -1
  40. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/mesh.js.map +1 -1
  41. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/node.js.map +1 -1
  42. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/particle.js.map +1 -1
  43. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/primitive.js.map +1 -1
  44. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/scene.js.map +1 -1
  45. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/terrain.js.map +1 -1
  46. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/types.js +4 -4
  47. package/dist/vendor/zephyr3d/scene/dist/utility/serialization/types.js.map +1 -1
  48. package/package.json +1 -1
@@ -5616,25 +5616,25 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5616
5616
  dstClip.addTrack(remap.dstNode, track);
5617
5617
  }
5618
5618
  }
5619
- /**
5620
- * Animation set
5621
- *
5622
- * Manages a collection of named animation clips for a model and orchestrates:
5623
- * - Playback state (time, loops, speed, weights, fade-in/out).
5624
- * - Blending across multiple tracks targeting the same property via weighted averages.
5625
- * - Skeleton usage and application for clips that drive skeletal animation.
5626
- * - Active track registration and cleanup as clips start/stop.
5627
- *
5628
- * Usage:
5629
- * - Create or retrieve `AnimationClip`s by name.
5630
- * - Start playback with `playAnimation(name, options)`.
5631
- * - Advance animation with `update(deltaSeconds)`.
5632
- * - Optionally adjust weight while playing with `setAnimationWeight(name, weight)`.
5633
- *
5634
- * Lifetime:
5635
- * - Disposing the set releases references to the model, clips, and clears active state.
5636
- *
5637
- * @public
5619
+ /**
5620
+ * Animation set
5621
+ *
5622
+ * Manages a collection of named animation clips for a model and orchestrates:
5623
+ * - Playback state (time, loops, speed, weights, fade-in/out).
5624
+ * - Blending across multiple tracks targeting the same property via weighted averages.
5625
+ * - Skeleton usage and application for clips that drive skeletal animation.
5626
+ * - Active track registration and cleanup as clips start/stop.
5627
+ *
5628
+ * Usage:
5629
+ * - Create or retrieve `AnimationClip`s by name.
5630
+ * - Start playback with `playAnimation(name, options)`.
5631
+ * - Advance animation with `update(deltaSeconds)`.
5632
+ * - Optionally adjust weight while playing with `setAnimationWeight(name, weight)`.
5633
+ *
5634
+ * Lifetime:
5635
+ * - Disposing the set releases references to the model, clips, and clears active state.
5636
+ *
5637
+ * @public
5638
5638
  */ class AnimationSet extends Disposable {
5639
5639
  /** @internal */ _model;
5640
5640
  /** @internal */ _animations;
@@ -5642,10 +5642,10 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5642
5642
  /** @internal */ _activeTracks;
5643
5643
  /** @internal */ _activeSkeletons;
5644
5644
  /** @internal */ _activeAnimations;
5645
- /**
5646
- * Create an AnimationSet controlling the provided model.
5647
- *
5648
- * @param model - The SceneNode (model root) controlled by this animation set.
5645
+ /**
5646
+ * Create an AnimationSet controlling the provided model.
5647
+ *
5648
+ * @param model - The SceneNode (model root) controlled by this animation set.
5649
5649
  */ constructor(model){
5650
5650
  super();
5651
5651
  this._model = model;
@@ -5655,35 +5655,35 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5655
5655
  this._activeAnimations = new Map();
5656
5656
  this._skeletons = [];
5657
5657
  }
5658
- /**
5659
- * The model (SceneNode) controlled by this animation set.
5658
+ /**
5659
+ * The model (SceneNode) controlled by this animation set.
5660
5660
  */ get model() {
5661
5661
  return this._model;
5662
5662
  }
5663
- /**
5664
- * Number of animation clips registered in this set.
5663
+ /**
5664
+ * Number of animation clips registered in this set.
5665
5665
  */ get numAnimations() {
5666
5666
  return Object.getOwnPropertyNames(this._animations).length;
5667
5667
  }
5668
- /**
5669
- * The skeletons used by animations in this set.
5668
+ /**
5669
+ * The skeletons used by animations in this set.
5670
5670
  */ get skeletons() {
5671
5671
  return this._skeletons;
5672
5672
  }
5673
- /**
5674
- * Retrieve an animation clip by name.
5675
- *
5676
- * @param name - Name of the animation.
5677
- * @returns The clip if present; otherwise null.
5673
+ /**
5674
+ * Retrieve an animation clip by name.
5675
+ *
5676
+ * @param name - Name of the animation.
5677
+ * @returns The clip if present; otherwise null.
5678
5678
  */ get(name) {
5679
5679
  return this._animations[name] ?? null;
5680
5680
  }
5681
- /**
5682
- * Create and register a new animation clip.
5683
- *
5684
- * @param name - Unique name for the animation clip.
5685
- * @param embedded - Whether the clip is embedded/owned (implementation-specific). Default false.
5686
- * @returns The created clip, or null if the name is empty or not unique.
5681
+ /**
5682
+ * Create and register a new animation clip.
5683
+ *
5684
+ * @param name - Unique name for the animation clip.
5685
+ * @param embedded - Whether the clip is embedded/owned (implementation-specific). Default false.
5686
+ * @returns The created clip, or null if the name is empty or not unique.
5687
5687
  */ createAnimation(name, embedded = false) {
5688
5688
  if (!name || this._animations[name]) {
5689
5689
  console.error('Animation must have unique name');
@@ -5695,12 +5695,12 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5695
5695
  return animation;
5696
5696
  }
5697
5697
  }
5698
- /**
5699
- * Delete and dispose an animation clip by name.
5700
- *
5701
- * - If the animation is currently playing, it is first stopped (immediately).
5702
- *
5703
- * @param name - Name of the animation to remove.
5698
+ /**
5699
+ * Delete and dispose an animation clip by name.
5700
+ *
5701
+ * - If the animation is currently playing, it is first stopped (immediately).
5702
+ *
5703
+ * @param name - Name of the animation to remove.
5704
5704
  */ deleteAnimation(name) {
5705
5705
  const animation = this._animations[name];
5706
5706
  if (animation) {
@@ -5709,24 +5709,24 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5709
5709
  animation.dispose();
5710
5710
  }
5711
5711
  }
5712
- /**
5713
- * Get the list of all registered animation names.
5714
- *
5715
- * @returns An array of clip names.
5712
+ /**
5713
+ * Get the list of all registered animation names.
5714
+ *
5715
+ * @returns An array of clip names.
5716
5716
  */ getAnimationNames() {
5717
5717
  return Object.keys(this._animations);
5718
5718
  }
5719
- /**
5720
- * Advance and apply active animations.
5721
- *
5722
- * Responsibilities per call:
5723
- * - Update time cursor for each active clip (respecting speedRatio and looping).
5724
- * - Enforce repeat limits and apply fade-out termination if configured.
5725
- * - For each animated target, blend active tracks (weighted by clip weight × fade-in × fade-out)
5726
- * and apply the resulting state to the target.
5727
- * - Apply all active skeletons to update skinning transforms.
5728
- *
5729
- * @param deltaInSeconds - Time step in seconds since last update.
5719
+ /**
5720
+ * Advance and apply active animations.
5721
+ *
5722
+ * Responsibilities per call:
5723
+ * - Update time cursor for each active clip (respecting speedRatio and looping).
5724
+ * - Enforce repeat limits and apply fade-out termination if configured.
5725
+ * - For each animated target, blend active tracks (weighted by clip weight × fade-in × fade-out)
5726
+ * and apply the resulting state to the target.
5727
+ * - Apply all active skeletons to update skinning transforms.
5728
+ *
5729
+ * @param deltaInSeconds - Time step in seconds since last update.
5730
5730
  */ update(deltaInSeconds) {
5731
5731
  this._activeAnimations.forEach((v, k)=>{
5732
5732
  if (v.fadeOut > 0 && v.fadeOutStart < 0) {
@@ -5788,11 +5788,11 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5788
5788
  v.get()?.apply(deltaInSeconds);
5789
5789
  });
5790
5790
  }
5791
- /**
5792
- * Check whether an animation is currently playing.
5793
- *
5794
- * @param name - Optional animation name. If omitted, returns true if any animation is playing.
5795
- * @returns True if playing; otherwise false.
5791
+ /**
5792
+ * Check whether an animation is currently playing.
5793
+ *
5794
+ * @param name - Optional animation name. If omitted, returns true if any animation is playing.
5795
+ * @returns True if playing; otherwise false.
5796
5796
  */ isPlayingAnimation(name) {
5797
5797
  if (name) {
5798
5798
  const animation = this._animations[name];
@@ -5800,23 +5800,23 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5800
5800
  }
5801
5801
  return this._activeAnimations.size > 0;
5802
5802
  }
5803
- /**
5804
- * Get an animation clip by name.
5805
- *
5806
- * Alias of `get(name)` returning a nullable type.
5807
- *
5808
- * @param name - Name of the animation.
5809
- * @returns The clip if present; otherwise null.
5803
+ /**
5804
+ * Get an animation clip by name.
5805
+ *
5806
+ * Alias of `get(name)` returning a nullable type.
5807
+ *
5808
+ * @param name - Name of the animation.
5809
+ * @returns The clip if present; otherwise null.
5810
5810
  */ getAnimationClip(name) {
5811
5811
  return this._animations[name] ?? null;
5812
5812
  }
5813
- /**
5814
- * Set the runtime blend weight for a currently playing animation.
5815
- *
5816
- * Has no effect if the clip is not active.
5817
- *
5818
- * @param name - Name of the playing animation.
5819
- * @param weight - New weight value used during blending.
5813
+ /**
5814
+ * Set the runtime blend weight for a currently playing animation.
5815
+ *
5816
+ * Has no effect if the clip is not active.
5817
+ *
5818
+ * @param name - Name of the playing animation.
5819
+ * @param weight - New weight value used during blending.
5820
5820
  */ setAnimationWeight(name, weight) {
5821
5821
  const ani = this._animations[name];
5822
5822
  if (!ani) {
@@ -5828,16 +5828,16 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5828
5828
  info.weight = weight;
5829
5829
  }
5830
5830
  }
5831
- /**
5832
- * Start (or update) playback of an animation clip.
5833
- *
5834
- * Behavior:
5835
- * - If the clip is already playing, updates its fade-in (resets fade-out).
5836
- * - Otherwise initializes playback state (repeat counter, speed, weight, initial time).
5837
- * - Registers clip tracks and skeletons into the active sets for blending and application.
5838
- *
5839
- * @param name - Name of the animation to play.
5840
- * @param options - Playback options (repeat, speedRatio, fadeIn).
5831
+ /**
5832
+ * Start (or update) playback of an animation clip.
5833
+ *
5834
+ * Behavior:
5835
+ * - If the clip is already playing, updates its fade-in (resets fade-out).
5836
+ * - Otherwise initializes playback state (repeat counter, speed, weight, initial time).
5837
+ * - Registers clip tracks and skeletons into the active sets for blending and application.
5838
+ *
5839
+ * @param name - Name of the animation to play.
5840
+ * @param options - Playback options (repeat, speedRatio, fadeIn).
5841
5841
  */ playAnimation(name, options) {
5842
5842
  const ani = this._animations[name];
5843
5843
  if (!ani) {
@@ -5895,18 +5895,18 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5895
5895
  });
5896
5896
  }
5897
5897
  }
5898
- /**
5899
- * Stop playback of an animation clip.
5900
- *
5901
- * Behavior:
5902
- * - If `options.fadeOut > 0`, marks the clip for fade-out; actual removal occurs after fade completes.
5903
- * - If `fadeOut` is 0 or omitted, immediately:
5904
- * - Removes the clip from active animations.
5905
- * - Unregisters its tracks from active track maps.
5906
- * - Decrements skeleton reference counts; resets and removes skeletons when refcount reaches 0.
5907
- *
5908
- * @param name - Name of the animation to stop.
5909
- * @param options - Optional fade-out configuration.
5898
+ /**
5899
+ * Stop playback of an animation clip.
5900
+ *
5901
+ * Behavior:
5902
+ * - If `options.fadeOut > 0`, marks the clip for fade-out; actual removal occurs after fade completes.
5903
+ * - If `fadeOut` is 0 or omitted, immediately:
5904
+ * - Removes the clip from active animations.
5905
+ * - Unregisters its tracks from active track maps.
5906
+ * - Decrements skeleton reference counts; resets and removes skeletons when refcount reaches 0.
5907
+ *
5908
+ * @param name - Name of the animation to stop.
5909
+ * @param options - Optional fade-out configuration.
5910
5910
  */ stopAnimation(name, options) {
5911
5911
  const ani = this._animations[name];
5912
5912
  if (!ani) {
@@ -5941,18 +5941,18 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
5941
5941
  }
5942
5942
  }
5943
5943
  }
5944
- /**
5945
- * Copy a humanoid animation clip from another AnimationSet into this one via humanoid rig mapping.
5946
- *
5947
- * Prerequisites:
5948
- * - Both source and destination skeletons must have a non-null `humanoidJointMapping`.
5949
- * - Joints are matched by shared `HumanoidBodyRig` / `HumanoidHandRig` keys instead of joint names.
5950
- * - The source clip must exist in `sourceSet` and must be driven by exactly one skeleton.
5951
- *
5952
- * @param sourceSet - The AnimationSet to copy from.
5953
- * @param animationName - Name of the clip to copy.
5954
- * @param targetName - Name for the new clip in this set. Defaults to `animationName`.
5955
- * @returns The newly created AnimationClip, or null on failure.
5944
+ /**
5945
+ * Copy a humanoid animation clip from another AnimationSet into this one via humanoid rig mapping.
5946
+ *
5947
+ * Prerequisites:
5948
+ * - Both source and destination skeletons must have a non-null `humanoidJointMapping`.
5949
+ * - Joints are matched by shared `HumanoidBodyRig` / `HumanoidHandRig` keys instead of joint names.
5950
+ * - The source clip must exist in `sourceSet` and must be driven by exactly one skeleton.
5951
+ *
5952
+ * @param sourceSet - The AnimationSet to copy from.
5953
+ * @param animationName - Name of the clip to copy.
5954
+ * @param targetName - Name for the new clip in this set. Defaults to `animationName`.
5955
+ * @returns The newly created AnimationClip, or null on failure.
5956
5956
  */ copyHumanoidAnimationFrom(sourceSet, animationName, targetName) {
5957
5957
  const destName = targetName ?? animationName;
5958
5958
  const sourceClip = sourceSet.get(animationName);
@@ -6120,21 +6120,21 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
6120
6120
  }
6121
6121
  return dstClip;
6122
6122
  }
6123
- /**
6124
- * Copy an animation clip from another AnimationSet into this one.
6125
- *
6126
- * Prerequisites:
6127
- * - Both sets must reference skeletons with identical joint names and counts.
6128
- * - The source clip must exist in `sourceSet`.
6129
- *
6130
- * @param sourceSet - The AnimationSet to copy from.
6131
- * @param animationName - Name of the clip to copy.
6132
- * @param targetName - Name for the new clip in this set. Defaults to `animationName`.
6133
- * @param excludeJoint - Optional predicate; joints whose name returns true are excluded from
6134
- * skeleton structure matching.
6135
- * @returns The newly created AnimationClip, or null on failure.
6136
- *
6137
- * @deprecated Use the new {@link AnimationSet.copyHumanoidAnimationFrom} method instead.
6123
+ /**
6124
+ * Copy an animation clip from another AnimationSet into this one.
6125
+ *
6126
+ * Prerequisites:
6127
+ * - Both sets must reference skeletons with identical joint names and counts.
6128
+ * - The source clip must exist in `sourceSet`.
6129
+ *
6130
+ * @param sourceSet - The AnimationSet to copy from.
6131
+ * @param animationName - Name of the clip to copy.
6132
+ * @param targetName - Name for the new clip in this set. Defaults to `animationName`.
6133
+ * @param excludeJoint - Optional predicate; joints whose name returns true are excluded from
6134
+ * skeleton structure matching.
6135
+ * @returns The newly created AnimationClip, or null on failure.
6136
+ *
6137
+ * @deprecated Use the new {@link AnimationSet.copyHumanoidAnimationFrom} method instead.
6138
6138
  */ copyAnimationFrom(sourceSet, animationName, targetName, excludeJoint) {
6139
6139
  const destName = targetName ?? animationName;
6140
6140
  const sourceClip = sourceSet.get(animationName);
@@ -6284,12 +6284,12 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
6284
6284
  return ordered;
6285
6285
  }
6286
6286
  }
6287
- /**
6288
- * Dispose the animation set and release owned resources.
6289
- *
6290
- * - Disposes the weak reference to the model.
6291
- * - Disposes all registered animation clips.
6292
- * - Clears active animations, tracks, and skeleton references.
6287
+ /**
6288
+ * Dispose the animation set and release owned resources.
6289
+ *
6290
+ * - Disposes the weak reference to the model.
6291
+ * - Disposes all registered animation clips.
6292
+ * - Clears active animations, tracks, and skeleton references.
6293
6293
  */ onDispose() {
6294
6294
  super.onDispose();
6295
6295
  for(const k in this._animations){
@@ -10670,99 +10670,99 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
10670
10670
  }
10671
10671
  }
10672
10672
 
10673
- /**
10674
- * Base class for all materials.
10675
- *
10676
- * Responsibilities:
10677
- * - Defines a multi-pass rendering interface (`numPasses`, `apply`, `bind`, `draw`, `drawPrimitive`).
10678
- * - Builds and caches GPU shader programs per pass and per-render-context hash.
10679
- * - Manages a per-material bind group (typically at index 2) for uniforms and resources.
10680
- * - Updates render states per pass (`updateRenderStates`) and uploads uniforms (`_applyUniforms`).
10681
- * - Tracks "option" changes that affect shader variant hashing and render bundles.
10682
- *
10683
- * Caching and hashing:
10684
- * - `createHash(pass)` produces a stable hash representing shader variant options for a pass.
10685
- * Override `_createHash()` in subclasses to encode feature toggles (defines, keywords, macros).
10686
- * - The global hash used to key `MaterialState` also includes `ctx.materialFlags` and
10687
- * `ctx.renderPassHash`, allowing context-sensitive variants (e.g., MSAA, MRT layout).
10688
- * - GPU programs are additionally memoized in a global static `_programCache` across materials
10689
- * by `constructor.name` + hash, to avoid recompilation of identical variants.
10690
- *
10691
- * Bind groups and uniforms:
10692
- * - If a program declares a bind group layout at index 2 (i.e., `bindGroupLayouts.length > 2`),
10693
- * `apply()` will allocate the group and keep it in the state. Subclasses should fill it in
10694
- * `_applyUniforms()`.
10695
- * - `applyUniforms()` only calls `_applyUniforms()` when `needUpdate` is true, based on
10696
- * `_optionTag` changes (see `optionChanged()`).
10697
- *
10698
- * Lifecycle:
10699
- * - Constructed materials register a persistent ID into a global registry for serialization.
10700
- * - `apply(ctx)` prepares all passes: creates/gets state, programs, bind groups, render states,
10701
- * and uploads uniforms as needed.
10702
- * - `bind(device, pass)` binds the program, bind group (index 2), and render states.
10703
- * - `draw(primitive, ctx, numInstances)` runs all passes, calling `bind()` and `drawPrimitive()`.
10704
- * - `onDispose()` releases bind groups and registry entries.
10705
- *
10706
- * Extending:
10707
- * - Override `_createProgram(pb, ctx, pass)` to build a shader.
10708
- * - Override `_applyUniforms(bindGroup, ctx, pass)` to upload uniforms and resources.
10709
- * - Override `updateRenderStates(pass, renderStates, ctx)` to set depth, blend, cull, etc.
10710
- * - Override `_createHash()` to encode options that affect program compilation.
10711
- * - Override `supportLighting`, `supportInstancing`, `isTransparentPass`, `getQueueType`, etc.
10712
- *
10713
- * Thread-safety:
10714
- * - Intended for main-thread use in a renderer driving WebGPU/WebGL-like devices.
10715
- *
10716
- * @public
10673
+ /**
10674
+ * Base class for all materials.
10675
+ *
10676
+ * Responsibilities:
10677
+ * - Defines a multi-pass rendering interface (`numPasses`, `apply`, `bind`, `draw`, `drawPrimitive`).
10678
+ * - Builds and caches GPU shader programs per pass and per-render-context hash.
10679
+ * - Manages a per-material bind group (typically at index 2) for uniforms and resources.
10680
+ * - Updates render states per pass (`updateRenderStates`) and uploads uniforms (`_applyUniforms`).
10681
+ * - Tracks "option" changes that affect shader variant hashing and render bundles.
10682
+ *
10683
+ * Caching and hashing:
10684
+ * - `createHash(pass)` produces a stable hash representing shader variant options for a pass.
10685
+ * Override `_createHash()` in subclasses to encode feature toggles (defines, keywords, macros).
10686
+ * - The global hash used to key `MaterialState` also includes `ctx.materialFlags` and
10687
+ * `ctx.renderPassHash`, allowing context-sensitive variants (e.g., MSAA, MRT layout).
10688
+ * - GPU programs are additionally memoized in a global static `_programCache` across materials
10689
+ * by `constructor.name` + hash, to avoid recompilation of identical variants.
10690
+ *
10691
+ * Bind groups and uniforms:
10692
+ * - If a program declares a bind group layout at index 2 (i.e., `bindGroupLayouts.length > 2`),
10693
+ * `apply()` will allocate the group and keep it in the state. Subclasses should fill it in
10694
+ * `_applyUniforms()`.
10695
+ * - `applyUniforms()` only calls `_applyUniforms()` when `needUpdate` is true, based on
10696
+ * `_optionTag` changes (see `optionChanged()`).
10697
+ *
10698
+ * Lifecycle:
10699
+ * - Constructed materials register a persistent ID into a global registry for serialization.
10700
+ * - `apply(ctx)` prepares all passes: creates/gets state, programs, bind groups, render states,
10701
+ * and uploads uniforms as needed.
10702
+ * - `bind(device, pass)` binds the program, bind group (index 2), and render states.
10703
+ * - `draw(primitive, ctx, numInstances)` runs all passes, calling `bind()` and `drawPrimitive()`.
10704
+ * - `onDispose()` releases bind groups and registry entries.
10705
+ *
10706
+ * Extending:
10707
+ * - Override `_createProgram(pb, ctx, pass)` to build a shader.
10708
+ * - Override `_applyUniforms(bindGroup, ctx, pass)` to upload uniforms and resources.
10709
+ * - Override `updateRenderStates(pass, renderStates, ctx)` to set depth, blend, cull, etc.
10710
+ * - Override `_createHash()` to encode options that affect program compilation.
10711
+ * - Override `supportLighting`, `supportInstancing`, `isTransparentPass`, `getQueueType`, etc.
10712
+ *
10713
+ * Thread-safety:
10714
+ * - Intended for main-thread use in a renderer driving WebGPU/WebGL-like devices.
10715
+ *
10716
+ * @public
10717
10717
  */ class Material extends Disposable {
10718
- /**
10719
- * Monotonic instance ID counter.
10720
- * @internal
10718
+ /**
10719
+ * Monotonic instance ID counter.
10720
+ * @internal
10721
10721
  */ static _nextId = 0;
10722
- /**
10723
- * Global program cache keyed by global hash
10722
+ /**
10723
+ * Global program cache keyed by global hash
10724
10724
  */ static _programCache = {};
10725
- /**
10726
- * Per-material state cache keyed by global hash (material + context + pass).
10727
- * @internal
10725
+ /**
10726
+ * Per-material state cache keyed by global hash (material + context + pass).
10727
+ * @internal
10728
10728
  */ _states;
10729
- /**
10730
- * Number of rendering passes.
10731
- * Subclasses can increase this to implement multi-pass rendering.
10732
- * @internal
10729
+ /**
10730
+ * Number of rendering passes.
10731
+ * Subclasses can increase this to implement multi-pass rendering.
10732
+ * @internal
10733
10733
  */ _numPasses;
10734
- /**
10735
- * Per-pass hash cached results. Length scales with `numPasses`.
10736
- * @internal
10734
+ /**
10735
+ * Per-pass hash cached results. Length scales with `numPasses`.
10736
+ * @internal
10737
10737
  */ _hash;
10738
- /**
10739
- * Incremented each time options change (via `optionChanged`), used to decide whether
10740
- * uniforms need update on next `apply()`.
10741
- * @internal
10738
+ /**
10739
+ * Incremented each time options change (via `optionChanged`), used to decide whether
10740
+ * uniforms need update on next `apply()`.
10741
+ * @internal
10742
10742
  */ _optionTag;
10743
- /**
10744
- * Unique runtime instance ID.
10745
- * @internal
10743
+ /**
10744
+ * Unique runtime instance ID.
10745
+ * @internal
10746
10746
  */ _id;
10747
- /**
10748
- * Latest computed global hash per pass, set during `apply()`, read in `bind()`.
10749
- * @internal
10747
+ /**
10748
+ * Latest computed global hash per pass, set during `apply()`, read in `bind()`.
10749
+ * @internal
10750
10750
  */ _currentHash;
10751
- /**
10752
- * Incremented when material states affecting render bundles change (e.g., bind group id changes
10753
- * or `optionChanged(true)`), used to trigger re-recording of render bundles.
10754
- * @internal
10751
+ /**
10752
+ * Incremented when material states affecting render bundles change (e.g., bind group id changes
10753
+ * or `optionChanged(true)`), used to trigger re-recording of render bundles.
10754
+ * @internal
10755
10755
  */ _changeTag;
10756
- /**
10757
- * Unique program id counter for naming compiled programs.
10758
- * @internal
10756
+ /**
10757
+ * Unique program id counter for naming compiled programs.
10758
+ * @internal
10759
10759
  */ _nextProgramId = 0;
10760
- /**
10761
- * Create a new material instance.
10762
- *
10763
- * - Initializes one pass by default.
10764
- * - Prepares per-pass hash storage and change tracking.
10765
- * - Registers a persistent ID in the global registry.
10760
+ /**
10761
+ * Create a new material instance.
10762
+ *
10763
+ * - Initializes one pass by default.
10764
+ * - Prepares per-pass hash storage and change tracking.
10765
+ * - Registers a persistent ID in the global registry.
10766
10766
  */ constructor(){
10767
10767
  super();
10768
10768
  this._id = ++Material._nextId;
@@ -10776,46 +10776,46 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
10776
10776
  this._changeTag = 0;
10777
10777
  this._currentHash = [];
10778
10778
  }
10779
- /**
10780
- * Create a shallow clone of this material.
10781
- *
10782
- * Note: The base implementation returns a base `Material`. Subclasses should
10783
- * override to return their own type and copy custom fields.
10779
+ /**
10780
+ * Create a shallow clone of this material.
10781
+ *
10782
+ * Note: The base implementation returns a base `Material`. Subclasses should
10783
+ * override to return their own type and copy custom fields.
10784
10784
  */ clone() {
10785
10785
  const other = new Material();
10786
10786
  other.copyFrom(this);
10787
10787
  return other;
10788
10788
  }
10789
- /**
10790
- * Copy basic properties from another material.
10791
- *
10792
- * Disposes existing bind groups/states, copies `numPasses`. Subclasses should
10793
- * extend this to copy their own fields and call `optionChanged(true)` if
10794
- * shader-affecting options differ.
10795
- *
10796
- * @param other - Source material.
10789
+ /**
10790
+ * Copy basic properties from another material.
10791
+ *
10792
+ * Disposes existing bind groups/states, copies `numPasses`. Subclasses should
10793
+ * extend this to copy their own fields and call `optionChanged(true)` if
10794
+ * shader-affecting options differ.
10795
+ *
10796
+ * @param other - Source material.
10797
10797
  */ copyFrom(other) {
10798
10798
  this.clearCache();
10799
10799
  this._numPasses = other._numPasses;
10800
10800
  getEngine().resourceManager.setAssetId(this, getEngine().resourceManager.getAssetId(other.coreMaterial));
10801
10801
  }
10802
- /**
10803
- * Incremented when the material’s GPU-relevant state changes and render bundles
10804
- * may need to be rebuilt.
10802
+ /**
10803
+ * Incremented when the material’s GPU-relevant state changes and render bundles
10804
+ * may need to be rebuilt.
10805
10805
  */ get changeTag() {
10806
10806
  return this._changeTag;
10807
10807
  }
10808
- /**
10809
- * Runtime-unique numeric identifier for the material instance.
10808
+ /**
10809
+ * Runtime-unique numeric identifier for the material instance.
10810
10810
  */ get instanceId() {
10811
10811
  return this._id;
10812
10812
  }
10813
- /**
10814
- * Number of rendering passes this material uses.
10815
- *
10816
- * Increasing this will expand the per-pass hash cache; make sure to implement
10817
- * `createHash(pass)`, `_createProgram(pb, ctx, pass)`, and `updateRenderStates(pass, ...)`
10818
- * accordingly for each pass.
10813
+ /**
10814
+ * Number of rendering passes this material uses.
10815
+ *
10816
+ * Increasing this will expand the per-pass hash cache; make sure to implement
10817
+ * `createHash(pass)`, `_createProgram(pb, ctx, pass)`, and `updateRenderStates(pass, ...)`
10818
+ * accordingly for each pass.
10819
10819
  */ get numPasses() {
10820
10820
  return this._numPasses;
10821
10821
  }
@@ -10825,86 +10825,86 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
10825
10825
  }
10826
10826
  this._numPasses = val;
10827
10827
  }
10828
- /**
10829
- * Get or compute the per-pass shader hash used for program caching.
10830
- *
10831
- * Calls `createHash(pass)` lazily and caches the result.
10832
- * @internal
10828
+ /**
10829
+ * Get or compute the per-pass shader hash used for program caching.
10830
+ *
10831
+ * Calls `createHash(pass)` lazily and caches the result.
10832
+ * @internal
10833
10833
  */ getHash(pass) {
10834
10834
  if (this._hash[pass] === null) {
10835
10835
  this._hash[pass] = this.createHash(pass);
10836
10836
  }
10837
10837
  return this._hash[pass];
10838
10838
  }
10839
- /**
10840
- * Return the queue type to which this material belongs.
10841
- *
10842
- * Override this in transparent or special materials (e.g., post-process).
10839
+ /**
10840
+ * Return the queue type to which this material belongs.
10841
+ *
10842
+ * Override this in transparent or special materials (e.g., post-process).
10843
10843
  */ getQueueType() {
10844
10844
  return QUEUE_OPAQUE;
10845
10845
  }
10846
- /**
10847
- * Whether the given pass is transparent.
10848
- *
10849
- * Used to place draw calls into appropriate render queues and set blending states.
10846
+ /**
10847
+ * Whether the given pass is transparent.
10848
+ *
10849
+ * Used to place draw calls into appropriate render queues and set blending states.
10850
10850
  */ isTransparentPass(_pass) {
10851
10851
  return false;
10852
10852
  }
10853
- /**
10854
- * Whether this material's shading is affected by scene lights.
10855
- *
10856
- * Override and return `false` for unlit materials.
10853
+ /**
10854
+ * Whether this material's shading is affected by scene lights.
10855
+ *
10856
+ * Override and return `false` for unlit materials.
10857
10857
  */ supportLighting() {
10858
10858
  return true;
10859
10859
  }
10860
- /**
10861
- * Whether this material supports hardware instancing.
10862
- *
10863
- * Override and return `false` if per-instance data is not supported in the shader.
10860
+ /**
10861
+ * Whether this material supports hardware instancing.
10862
+ *
10863
+ * Override and return `false` if per-instance data is not supported in the shader.
10864
10864
  */ supportInstancing() {
10865
10865
  return true;
10866
10866
  }
10867
10867
  /** Returns true if this is a instance of material */ isBatchable() {
10868
10868
  return false;
10869
10869
  }
10870
- /**
10871
- * Whether this material requires the scene color texture (e.g., for refraction).
10870
+ /**
10871
+ * Whether this material requires the scene color texture (e.g., for refraction).
10872
10872
  */ needSceneColor() {
10873
10873
  return false;
10874
10874
  }
10875
- /**
10876
- * Whether this material requires the linear scene depth texture (e.g., for depth-aware effects).
10875
+ /**
10876
+ * Whether this material requires the linear scene depth texture (e.g., for depth-aware effects).
10877
10877
  */ needSceneDepth() {
10878
10878
  return false;
10879
10879
  }
10880
- /**
10881
- * Create a material instance (instance-uniform-driven variant).
10882
- *
10883
- * Base returns `null`. Subclasses that support instancing can return a lightweight instance.
10880
+ /**
10881
+ * Create a material instance (instance-uniform-driven variant).
10882
+ *
10883
+ * Base returns `null`. Subclasses that support instancing can return a lightweight instance.
10884
10884
  */ createInstance() {
10885
10885
  throw new Error('Abstract function call');
10886
10886
  }
10887
- /**
10888
- * Returns the core material that owns GPU state.
10889
- *
10890
- * Instances may delegate to a shared core to reuse compiled programs and caches.
10891
- * @public
10887
+ /**
10888
+ * Returns the core material that owns GPU state.
10889
+ *
10890
+ * Instances may delegate to a shared core to reuse compiled programs and caches.
10891
+ * @public
10892
10892
  */ get coreMaterial() {
10893
10893
  return this;
10894
10894
  }
10895
- /**
10896
- * Prepare the material for drawing across all passes for the given draw context.
10897
- *
10898
- * Steps per pass:
10899
- * - Compute global hash (material variant + context).
10900
- * - Retrieve or build the GPU program, cache in `_programCache`.
10901
- * - Create per-material bind group (index 2) if the program exposes it.
10902
- * - Update uniforms if `_optionTag` indicates changes since last apply.
10903
- * - Update and cache render states for the pass.
10904
- * - Detect bind group GPU ID changes to bump `changeTag` and notify `RenderBundleWrapper`.
10905
- *
10906
- * @param ctx - Draw context (device, flags, pass hash, instance data, etc.).
10907
- * @returns `true` if successful; `false` if any pass lacks a valid program.
10895
+ /**
10896
+ * Prepare the material for drawing across all passes for the given draw context.
10897
+ *
10898
+ * Steps per pass:
10899
+ * - Compute global hash (material variant + context).
10900
+ * - Retrieve or build the GPU program, cache in `_programCache`.
10901
+ * - Create per-material bind group (index 2) if the program exposes it.
10902
+ * - Update uniforms if `_optionTag` indicates changes since last apply.
10903
+ * - Update and cache render states for the pass.
10904
+ * - Detect bind group GPU ID changes to bump `changeTag` and notify `RenderBundleWrapper`.
10905
+ *
10906
+ * @param ctx - Draw context (device, flags, pass hash, instance data, etc.).
10907
+ * @returns `true` if successful; `false` if any pass lacks a valid program.
10908
10908
  */ apply(ctx) {
10909
10909
  for(let pass = 0; pass < this._numPasses; pass++){
10910
10910
  const hash = this.calcGlobalHash(ctx, pass);
@@ -10946,15 +10946,15 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
10946
10946
  }
10947
10947
  return true;
10948
10948
  }
10949
- /**
10950
- * Bind the program, bind group, and render states for the specified pass.
10951
- *
10952
- * Must be called after `apply(ctx)` for the same pass.
10953
- *
10954
- * @param device - Rendering device.
10955
- * @param pass - Pass index to bind.
10956
- * @returns `true` on success; `false` if state or program missing.
10957
- * @internal
10949
+ /**
10950
+ * Bind the program, bind group, and render states for the specified pass.
10951
+ *
10952
+ * Must be called after `apply(ctx)` for the same pass.
10953
+ *
10954
+ * @param device - Rendering device.
10955
+ * @param pass - Pass index to bind.
10956
+ * @returns `true` on success; `false` if state or program missing.
10957
+ * @internal
10958
10958
  */ bind(device, pass) {
10959
10959
  const hash = this._currentHash[pass];
10960
10960
  const state = this._states[hash];
@@ -10972,56 +10972,56 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
10972
10972
  device.setRenderStates(state.renderStateSet);
10973
10973
  return true;
10974
10974
  }
10975
- /**
10976
- * Compute the global hash for the given pass and draw context.
10977
- *
10978
- * Includes:
10979
- * - Per-pass material hash from `getHash(pass)`.
10980
- * - `ctx.materialFlags` for context-dependent toggles.
10981
- * - `ctx.renderPassHash` for framebuffer/attachment layout variants.
10982
- * @internal
10975
+ /**
10976
+ * Compute the global hash for the given pass and draw context.
10977
+ *
10978
+ * Includes:
10979
+ * - Per-pass material hash from `getHash(pass)`.
10980
+ * - `ctx.materialFlags` for context-dependent toggles.
10981
+ * - `ctx.renderPassHash` for framebuffer/attachment layout variants.
10982
+ * @internal
10983
10983
  */ calcGlobalHash(ctx, pass) {
10984
10984
  return `${this.getHash(pass)}:${ctx.materialFlags}:${ctx.renderPassHash}`;
10985
10985
  }
10986
- /**
10987
- * Draw a primitive for all passes using this material.
10988
- *
10989
- * Calls `bind()` then `drawPrimitive()` per pass. If `numInstances` is zero,
10990
- * and `ctx.instanceData` exists, uses `ctx.instanceData.numInstances`.
10991
- *
10992
- * @param primitive - Geometry to draw.
10993
- * @param ctx - Draw context.
10994
- * @param numInstances - Instance count; 0 means auto-detect from context.
10995
- * @internal
10986
+ /**
10987
+ * Draw a primitive for all passes using this material.
10988
+ *
10989
+ * Calls `bind()` then `drawPrimitive()` per pass. If `numInstances` is zero,
10990
+ * and `ctx.instanceData` exists, uses `ctx.instanceData.numInstances`.
10991
+ *
10992
+ * @param primitive - Geometry to draw.
10993
+ * @param ctx - Draw context.
10994
+ * @param numInstances - Instance count; 0 means auto-detect from context.
10995
+ * @internal
10996
10996
  */ draw(primitive, ctx, numInstances = 0) {
10997
10997
  for(let pass = 0; pass < this._numPasses; pass++){
10998
10998
  this.bind(ctx.device, pass);
10999
10999
  this.drawPrimitive(pass, primitive, ctx, numInstances);
11000
11000
  }
11001
11001
  }
11002
- /**
11003
- * Conditionally update uniforms/resources into the material bind group.
11004
- *
11005
- * Delegates to `_applyUniforms()` when `needUpdate` is true (based on `_optionTag` check).
11006
- *
11007
- * @param bindGroup - Material bind group at index 2 (may be `null` if program has no layout).
11008
- * @param ctx - Draw context.
11009
- * @param needUpdate - Whether uniforms need to be refreshed.
11010
- * @param pass - Pass index.
11002
+ /**
11003
+ * Conditionally update uniforms/resources into the material bind group.
11004
+ *
11005
+ * Delegates to `_applyUniforms()` when `needUpdate` is true (based on `_optionTag` check).
11006
+ *
11007
+ * @param bindGroup - Material bind group at index 2 (may be `null` if program has no layout).
11008
+ * @param ctx - Draw context.
11009
+ * @param needUpdate - Whether uniforms need to be refreshed.
11010
+ * @param pass - Pass index.
11011
11011
  */ applyUniforms(bindGroup, ctx, needUpdate, pass) {
11012
11012
  if (needUpdate) {
11013
11013
  this._applyUniforms(bindGroup, ctx, pass);
11014
11014
  }
11015
11015
  }
11016
- /**
11017
- * Notify the material that some option changed.
11018
- *
11019
- * - Always increments `_optionTag`. This will trigger uniforms update on next `apply()`.
11020
- * - If `changeHash` is true, clears per-pass hashes so programs/states will be rebuilt,
11021
- * increments `_changeTag`, and notifies `RenderBundleWrapper` to regenerate recorded bundles.
11022
- *
11023
- * @param changeHash - Set true if the change affects shader compilation or render states.
11024
- * @internal
11016
+ /**
11017
+ * Notify the material that some option changed.
11018
+ *
11019
+ * - Always increments `_optionTag`. This will trigger uniforms update on next `apply()`.
11020
+ * - If `changeHash` is true, clears per-pass hashes so programs/states will be rebuilt,
11021
+ * increments `_changeTag`, and notifies `RenderBundleWrapper` to regenerate recorded bundles.
11022
+ *
11023
+ * @param changeHash - Set true if the change affects shader compilation or render states.
11024
+ * @internal
11025
11025
  */ optionChanged(changeHash) {
11026
11026
  this._optionTag++;
11027
11027
  if (changeHash) {
@@ -11040,39 +11040,39 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
11040
11040
  }
11041
11041
  this._states = {};
11042
11042
  }
11043
- /**
11044
- * Convert a pass index to a hash seed string.
11045
- *
11046
- * Subclasses may override to encode per-pass role (e.g., "depth", "forward", "shadow").
11047
- *
11048
- * @param pass - Pass number.
11049
- * @returns String used when building full hash.
11043
+ /**
11044
+ * Convert a pass index to a hash seed string.
11045
+ *
11046
+ * Subclasses may override to encode per-pass role (e.g., "depth", "forward", "shadow").
11047
+ *
11048
+ * @param pass - Pass number.
11049
+ * @returns String used when building full hash.
11050
11050
  */ passToHash(pass) {
11051
11051
  return String(pass);
11052
11052
  }
11053
- /**
11054
- * Build the material hash for a pass (excluding context-dependent parts).
11055
- *
11056
- * Default formula: `${constructor.name}|${pass}|${_createHash()}`
11057
- *
11058
- * @param pass - Pass number.
11059
- * @returns Hash string used in program caching.
11060
- * @internal
11053
+ /**
11054
+ * Build the material hash for a pass (excluding context-dependent parts).
11055
+ *
11056
+ * Default formula: `${constructor.name}|${pass}|${_createHash()}`
11057
+ *
11058
+ * @param pass - Pass number.
11059
+ * @returns Hash string used in program caching.
11060
+ * @internal
11061
11061
  */ createHash(pass) {
11062
11062
  return `${this.constructor.name}|${pass}|${this._createHash()}`;
11063
11063
  }
11064
- /**
11065
- * Issue the actual draw call for a pass.
11066
- *
11067
- * Override for custom per-pass draw behavior if necessary. The default implementation:
11068
- * - Draws instanced if `numInstances > 0`.
11069
- * - Else uses `ctx.instanceData.numInstances` if available.
11070
- * - Else issues a non-instanced draw.
11071
- *
11072
- * @param pass - Pass number.
11073
- * @param primitive - Primitive to draw.
11074
- * @param ctx - Draw context.
11075
- * @param numInstances - Explicit instance count (0 = auto).
11064
+ /**
11065
+ * Issue the actual draw call for a pass.
11066
+ *
11067
+ * Override for custom per-pass draw behavior if necessary. The default implementation:
11068
+ * - Draws instanced if `numInstances > 0`.
11069
+ * - Else uses `ctx.instanceData.numInstances` if available.
11070
+ * - Else issues a non-instanced draw.
11071
+ *
11072
+ * @param pass - Pass number.
11073
+ * @param primitive - Primitive to draw.
11074
+ * @param ctx - Draw context.
11075
+ * @param numInstances - Explicit instance count (0 = auto).
11076
11076
  */ drawPrimitive(pass, primitive, ctx, numInstances) {
11077
11077
  if (numInstances > 0) {
11078
11078
  primitive.drawInstanced(numInstances);
@@ -11082,88 +11082,88 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
11082
11082
  primitive.draw();
11083
11083
  }
11084
11084
  }
11085
- /**
11086
- * Dispose the material and release GPU-side resource references.
11087
- *
11088
- * - Unregisters from the global registry.
11089
- * - Disposes the per-material bind groups kept in `_states`.
11085
+ /**
11086
+ * Dispose the material and release GPU-side resource references.
11087
+ *
11088
+ * - Unregisters from the global registry.
11089
+ * - Disposes the per-material bind groups kept in `_states`.
11090
11090
  */ onDispose() {
11091
11091
  super.onDispose();
11092
11092
  this.clearCache();
11093
11093
  }
11094
- /**
11095
- * Build the GPU program for a pass.
11096
- *
11097
- * Default creates a `ProgramBuilder` and calls `_createProgram(pb, ctx, pass)`.
11098
- * Subclasses should override `_createProgram` instead of this method unless
11099
- * they need to replace builder instantiation.
11100
- *
11101
- * @param ctx - Draw context.
11102
- * @param pass - Pass number.
11103
- * @returns The compiled `GPUProgram`, or `null` on failure.
11104
- * @internal
11094
+ /**
11095
+ * Build the GPU program for a pass.
11096
+ *
11097
+ * Default creates a `ProgramBuilder` and calls `_createProgram(pb, ctx, pass)`.
11098
+ * Subclasses should override `_createProgram` instead of this method unless
11099
+ * they need to replace builder instantiation.
11100
+ *
11101
+ * @param ctx - Draw context.
11102
+ * @param pass - Pass number.
11103
+ * @returns The compiled `GPUProgram`, or `null` on failure.
11104
+ * @internal
11105
11105
  */ createProgram(ctx, pass) {
11106
11106
  const pb = new ProgramBuilder(ctx.device);
11107
11107
  return this._createProgram(pb, ctx, pass);
11108
11108
  }
11109
- /**
11110
- * Create and compile the shader program for this material/pass.
11111
- *
11112
- * Implement in subclasses:
11113
- * - Define shader stages, entry points, macros/defines, and resource layouts.
11114
- * - Return a compiled `GPUProgram`.
11115
- *
11116
- * @param pb - Program builder.
11117
- * @param ctx - Draw context.
11118
- * @param _pass - Pass number.
11119
- * @returns The created program, or `null` on failure.
11109
+ /**
11110
+ * Create and compile the shader program for this material/pass.
11111
+ *
11112
+ * Implement in subclasses:
11113
+ * - Define shader stages, entry points, macros/defines, and resource layouts.
11114
+ * - Return a compiled `GPUProgram`.
11115
+ *
11116
+ * @param pb - Program builder.
11117
+ * @param ctx - Draw context.
11118
+ * @param _pass - Pass number.
11119
+ * @returns The created program, or `null` on failure.
11120
11120
  */ _createProgram(_pb, _ctx, _pass) {
11121
11121
  throw new Error('Abstract function call');
11122
11122
  }
11123
- /**
11124
- * Upload uniforms and bind resources to the per-material bind group (index 2).
11125
- *
11126
- * Implement in subclasses to:
11127
- * - Write uniform buffers/textures/samplers to the `bindGroup`.
11128
- * - Respect the current `pass` and `ctx`.
11129
- *
11130
- * @param _bindGroup - The bind group to populate.
11131
- * @param _ctx - Draw context.
11132
- * @param _pass - Pass number.
11123
+ /**
11124
+ * Upload uniforms and bind resources to the per-material bind group (index 2).
11125
+ *
11126
+ * Implement in subclasses to:
11127
+ * - Write uniform buffers/textures/samplers to the `bindGroup`.
11128
+ * - Respect the current `pass` and `ctx`.
11129
+ *
11130
+ * @param _bindGroup - The bind group to populate.
11131
+ * @param _ctx - Draw context.
11132
+ * @param _pass - Pass number.
11133
11133
  */ _applyUniforms(_bindGroup, _ctx, _pass) {}
11134
- /**
11135
- * Update render states (depth/stencil, blending, rasterization) for the pass.
11136
- *
11137
- * Implement in subclasses based on transparency, double-sidedness, depth writes/tests,
11138
- * color mask, stencil ops, etc., and any context flags in `ctx`.
11139
- *
11140
- * @param _pass - Current pass index.
11141
- * @param _renderStates - Render state set to mutate.
11142
- * @param _ctx - Draw context.
11134
+ /**
11135
+ * Update render states (depth/stencil, blending, rasterization) for the pass.
11136
+ *
11137
+ * Implement in subclasses based on transparency, double-sidedness, depth writes/tests,
11138
+ * color mask, stencil ops, etc., and any context flags in `ctx`.
11139
+ *
11140
+ * @param _pass - Current pass index.
11141
+ * @param _renderStates - Render state set to mutate.
11142
+ * @param _ctx - Draw context.
11143
11143
  */ updateRenderStates(_pass, _renderStates, _ctx) {}
11144
- /**
11145
- * Compute the material-specific portion of the shader hash for the current options.
11146
- *
11147
- * Subclasses should override to include macro/define sets that influence program compilation.
11148
- * Example return: `"USE_NORMALMAP=1;ALPHA_MODE=BLEND;RECEIVE_SHADOWS=1"`.
11149
- *
11150
- * @returns Hash fragment string (no context/pass info).
11144
+ /**
11145
+ * Compute the material-specific portion of the shader hash for the current options.
11146
+ *
11147
+ * Subclasses should override to include macro/define sets that influence program compilation.
11148
+ * Example return: `"USE_NORMALMAP=1;ALPHA_MODE=BLEND;RECEIVE_SHADOWS=1"`.
11149
+ *
11150
+ * @returns Hash fragment string (no context/pass info).
11151
11151
  */ _createHash() {
11152
11152
  return '';
11153
11153
  }
11154
- /**
11155
- * Whether this is a lightweight instance of a core material.
11156
- *
11157
- * Instances typically share GPU programs with a core and only override instance uniforms.
11158
- * @internal
11154
+ /**
11155
+ * Whether this is a lightweight instance of a core material.
11156
+ *
11157
+ * Instances typically share GPU programs with a core and only override instance uniforms.
11158
+ * @internal
11159
11159
  */ get $isInstance() {
11160
11160
  return false;
11161
11161
  }
11162
- /**
11163
- * Instance-uniform buffer for material instances, if supported.
11164
- *
11165
- * Returned as a typed Float32 view over a backing ArrayBuffer.
11166
- * @internal
11162
+ /**
11163
+ * Instance-uniform buffer for material instances, if supported.
11164
+ *
11165
+ * Returned as a typed Float32 view over a backing ArrayBuffer.
11166
+ * @internal
11167
11167
  */ get $instanceUniforms() {
11168
11168
  throw new Error('Abstract function call');
11169
11169
  }
@@ -16623,10 +16623,10 @@ const PBR_REFLECTION_MODE$1 = {
16623
16623
  };
16624
16624
  }
16625
16625
 
16626
- /**
16627
- * Returns the property accessor list unchanged while preserving typing.
16628
- *
16629
- * @public
16626
+ /**
16627
+ * Returns the property accessor list unchanged while preserving typing.
16628
+ *
16629
+ * @public
16630
16630
  */ function defineProps(accessors) {
16631
16631
  return accessors;
16632
16632
  }
@@ -25422,26 +25422,26 @@ let paramId = 1;
25422
25422
  }
25423
25423
  }
25424
25424
 
25425
- /**
25426
- * Abstract base class for intermediate representation expressions
25427
- *
25428
- * @remarks
25429
- * Represents a node in the IR tree that can be compiled to shader code.
25430
- * Uses reference counting to determine if intermediate variables are needed.
25431
- * Each expression can be referenced multiple times in the final shader code.
25432
- *
25433
- * The IR expression tree is built during compilation and then translated
25434
- * to actual shader code via the `create()` method.
25435
- *
25436
- * @public
25425
+ /**
25426
+ * Abstract base class for intermediate representation expressions
25427
+ *
25428
+ * @remarks
25429
+ * Represents a node in the IR tree that can be compiled to shader code.
25430
+ * Uses reference counting to determine if intermediate variables are needed.
25431
+ * Each expression can be referenced multiple times in the final shader code.
25432
+ *
25433
+ * The IR expression tree is built during compilation and then translated
25434
+ * to actual shader code via the `create()` method.
25435
+ *
25436
+ * @public
25437
25437
  */ class IRExpression {
25438
25438
  /** Reference count for this expression (number of times it's used) */ _ref;
25439
25439
  /** Cached output expressions for each output slot */ _outputs;
25440
- /**
25441
- * Creates a new IR expression
25442
- *
25443
- * @remarks
25444
- * Initializes reference count to 0 and empty outputs array.
25440
+ /**
25441
+ * Creates a new IR expression
25442
+ *
25443
+ * @remarks
25444
+ * Initializes reference count to 0 and empty outputs array.
25445
25445
  */ constructor(){
25446
25446
  this._ref = 0;
25447
25447
  this._outputs = [];
@@ -25449,26 +25449,26 @@ let paramId = 1;
25449
25449
  /** Gets the array of output expressions */ get outputs() {
25450
25450
  return this._outputs;
25451
25451
  }
25452
- /**
25453
- * Increments the reference count
25454
- *
25455
- * @returns This expression for method chaining
25456
- *
25457
- * @remarks
25458
- * Called when this expression is referenced by another expression.
25459
- * Reference count is used to determine if a temporary variable is needed.
25452
+ /**
25453
+ * Increments the reference count
25454
+ *
25455
+ * @returns This expression for method chaining
25456
+ *
25457
+ * @remarks
25458
+ * Called when this expression is referenced by another expression.
25459
+ * Reference count is used to determine if a temporary variable is needed.
25460
25460
  */ addRef() {
25461
25461
  this._ref++;
25462
25462
  return this;
25463
25463
  }
25464
- /**
25465
- * Generates a unique temporary variable name
25466
- *
25467
- * @param scope - The shader scope to check for name conflicts
25468
- * @returns A unique temporary variable name (e.g., 'tmp0', 'tmp1')
25469
- *
25470
- * @remarks
25471
- * Ensures the generated name doesn't conflict with existing variables in the scope.
25464
+ /**
25465
+ * Generates a unique temporary variable name
25466
+ *
25467
+ * @param scope - The shader scope to check for name conflicts
25468
+ * @returns A unique temporary variable name (e.g., 'tmp0', 'tmp1')
25469
+ *
25470
+ * @remarks
25471
+ * Ensures the generated name doesn't conflict with existing variables in the scope.
25472
25472
  */ getTmpName(scope) {
25473
25473
  let tmp = 0;
25474
25474
  for(;;){
@@ -25478,60 +25478,60 @@ let paramId = 1;
25478
25478
  }
25479
25479
  }
25480
25480
  }
25481
- /**
25482
- * Converts this expression to a uniform value if applicable
25483
- *
25484
- * @param _node - The graph node associated with this expression
25485
- * @returns The uniform value descriptor, or null if not a uniform
25486
- *
25487
- * @remarks
25488
- * Only constant expressions can be converted to uniforms.
25489
- * Returns null by default; overridden by constant expression types.
25481
+ /**
25482
+ * Converts this expression to a uniform value if applicable
25483
+ *
25484
+ * @param _node - The graph node associated with this expression
25485
+ * @returns The uniform value descriptor, or null if not a uniform
25486
+ *
25487
+ * @remarks
25488
+ * Only constant expressions can be converted to uniforms.
25489
+ * Returns null by default; overridden by constant expression types.
25490
25490
  */ asUniformValue(_node) {
25491
25491
  return null;
25492
25492
  }
25493
- /**
25494
- * Converts this expression to a uniform texture if applicable
25495
- *
25496
- * @param _node - The graph node associated with this expression
25497
- * @returns The uniform texture descriptor, or null if not a texture uniform
25498
- *
25499
- * @remarks
25500
- * Only texture constant expressions can be converted to texture uniforms.
25501
- * Returns null by default; overridden by texture constant expression types.
25493
+ /**
25494
+ * Converts this expression to a uniform texture if applicable
25495
+ *
25496
+ * @param _node - The graph node associated with this expression
25497
+ * @returns The uniform texture descriptor, or null if not a texture uniform
25498
+ *
25499
+ * @remarks
25500
+ * Only texture constant expressions can be converted to texture uniforms.
25501
+ * Returns null by default; overridden by texture constant expression types.
25502
25502
  */ asUniformTexture(_node) {
25503
25503
  return null;
25504
25504
  }
25505
- /**
25506
- * Reset state for creation
25505
+ /**
25506
+ * Reset state for creation
25507
25507
  */ reset() {}
25508
25508
  }
25509
- /**
25510
- * IR expression for a constant scalar (float) value
25511
- *
25512
- * @public
25509
+ /**
25510
+ * IR expression for a constant scalar (float) value
25511
+ *
25512
+ * @public
25513
25513
  */ class IRConstantf extends IRExpression {
25514
25514
  /** The constant float value */ value;
25515
25515
  /** The uniform parameter name, or empty string for literals */ name;
25516
- /**
25517
- * Creates a constant float expression
25518
- *
25519
- * @param value - The float value
25520
- * @param paramName - The uniform parameter name, or empty string for literals
25516
+ /**
25517
+ * Creates a constant float expression
25518
+ *
25519
+ * @param value - The float value
25520
+ * @param paramName - The uniform parameter name, or empty string for literals
25521
25521
  */ constructor(value, paramName){
25522
25522
  super();
25523
25523
  this.value = value;
25524
25524
  this.name = paramName;
25525
25525
  }
25526
- /**
25527
- * Generates shader code for this constant
25528
- *
25529
- * @param pb - The program builder
25530
- * @returns A uniform reference or literal number
25531
- *
25532
- * @remarks
25533
- * If a parameter name exists, creates a uniform in the global scope.
25534
- * Otherwise, returns the literal value.
25526
+ /**
25527
+ * Generates shader code for this constant
25528
+ *
25529
+ * @param pb - The program builder
25530
+ * @returns A uniform reference or literal number
25531
+ *
25532
+ * @remarks
25533
+ * If a parameter name exists, creates a uniform in the global scope.
25534
+ * Otherwise, returns the literal value.
25535
25535
  */ create(pb) {
25536
25536
  if (this.name) {
25537
25537
  if (!pb.getGlobalScope()[this.name]) {
@@ -25541,11 +25541,11 @@ let paramId = 1;
25541
25541
  }
25542
25542
  return this.value;
25543
25543
  }
25544
- /**
25545
- * Converts to a uniform value descriptor
25546
- *
25547
- * @param node - The graph node
25548
- * @returns Uniform value descriptor if this is a uniform parameter, null otherwise
25544
+ /**
25545
+ * Converts to a uniform value descriptor
25546
+ *
25547
+ * @param node - The graph node
25548
+ * @returns Uniform value descriptor if this is a uniform parameter, null otherwise
25549
25549
  */ asUniformValue() {
25550
25550
  return this.name ? {
25551
25551
  name: this.name,
@@ -25556,57 +25556,57 @@ let paramId = 1;
25556
25556
  } : null;
25557
25557
  }
25558
25558
  }
25559
- /**
25560
- * IR expression for a constant scalar (boolean) value
25561
- *
25562
- * @public
25559
+ /**
25560
+ * IR expression for a constant scalar (boolean) value
25561
+ *
25562
+ * @public
25563
25563
  */ class IRConstantb extends IRExpression {
25564
25564
  /** The constant boolean value */ value;
25565
- /**
25566
- * Creates a constant boolean expression
25567
- *
25568
- * @param value - The boolean value
25565
+ /**
25566
+ * Creates a constant boolean expression
25567
+ *
25568
+ * @param value - The boolean value
25569
25569
  */ constructor(value){
25570
25570
  super();
25571
25571
  this.value = value;
25572
25572
  }
25573
- /**
25574
- * Generates shader code for this constant
25575
- *
25576
- * @returns The literal boolean value
25577
- *
25573
+ /**
25574
+ * Generates shader code for this constant
25575
+ *
25576
+ * @returns The literal boolean value
25577
+ *
25578
25578
  */ create() {
25579
25579
  return this.value;
25580
25580
  }
25581
25581
  }
25582
- /**
25583
- * IR expression for a constant vector value
25584
- *
25585
- * @public
25582
+ /**
25583
+ * IR expression for a constant vector value
25584
+ *
25585
+ * @public
25586
25586
  */ class IRConstantfv extends IRExpression {
25587
25587
  /** The constant vector value as an array of floats */ value;
25588
25588
  /** The uniform parameter name, or empty string for literals */ name;
25589
25589
  /** vector type */ type;
25590
- /**
25591
- * Creates a constant vector expression
25592
- *
25593
- * @param value - The vector value as an array (length 2-4)
25594
- * @param paramName - The uniform parameter name, or empty string for literals
25590
+ /**
25591
+ * Creates a constant vector expression
25592
+ *
25593
+ * @param value - The vector value as an array (length 2-4)
25594
+ * @param paramName - The uniform parameter name, or empty string for literals
25595
25595
  */ constructor(value, paramName, type){
25596
25596
  super();
25597
25597
  this.value = value;
25598
25598
  this.name = paramName;
25599
25599
  this.type = type;
25600
25600
  }
25601
- /**
25602
- * Generates shader code for this constant vector
25603
- *
25604
- * @param pb - The program builder
25605
- * @returns A uniform reference or vector constructor expression
25606
- *
25607
- * @remarks
25608
- * If a parameter name exists, creates a uniform in the global scope.
25609
- * The vector size is determined by the array length (vec2/vec3/vec4).
25601
+ /**
25602
+ * Generates shader code for this constant vector
25603
+ *
25604
+ * @param pb - The program builder
25605
+ * @returns A uniform reference or vector constructor expression
25606
+ *
25607
+ * @remarks
25608
+ * If a parameter name exists, creates a uniform in the global scope.
25609
+ * The vector size is determined by the array length (vec2/vec3/vec4).
25610
25610
  */ create(pb) {
25611
25611
  if (this.name) {
25612
25612
  if (!pb.getGlobalScope()[this.name]) {
@@ -25618,11 +25618,11 @@ let paramId = 1;
25618
25618
  return(// @ts-ignore
25619
25619
  Array.isArray(this.value) ? pb[`vec${this.value.length}`](...this.value) : this.value);
25620
25620
  }
25621
- /**
25622
- * Converts to a uniform value descriptor
25623
- *
25624
- * @param node - The graph node
25625
- * @returns Uniform value descriptor if this is a uniform parameter, null otherwise
25621
+ /**
25622
+ * Converts to a uniform value descriptor
25623
+ *
25624
+ * @param node - The graph node
25625
+ * @returns Uniform value descriptor if this is a uniform parameter, null otherwise
25626
25626
  */ asUniformValue() {
25627
25627
  return this.name ? {
25628
25628
  name: this.name,
@@ -25631,97 +25631,97 @@ let paramId = 1;
25631
25631
  } : null;
25632
25632
  }
25633
25633
  }
25634
- /**
25635
- * IR expression for a constant boolean vector value
25636
- *
25637
- * @public
25634
+ /**
25635
+ * IR expression for a constant boolean vector value
25636
+ *
25637
+ * @public
25638
25638
  */ class IRConstantbv extends IRExpression {
25639
25639
  /** The constant vector value as an array of booleans */ value;
25640
- /**
25641
- * Creates a constant boolean vector expression
25642
- *
25643
- * @param value - The vector value as an array (length 2-4)
25640
+ /**
25641
+ * Creates a constant boolean vector expression
25642
+ *
25643
+ * @param value - The vector value as an array (length 2-4)
25644
25644
  */ constructor(value){
25645
25645
  super();
25646
25646
  this.value = value;
25647
25647
  }
25648
- /**
25649
- * Generates shader code for this constant vector
25650
- *
25651
- * @param pb - The program builder
25652
- *
25653
- * @returns A boolean vector constructor expression
25648
+ /**
25649
+ * Generates shader code for this constant vector
25650
+ *
25651
+ * @param pb - The program builder
25652
+ *
25653
+ * @returns A boolean vector constructor expression
25654
25654
  */ create(pb) {
25655
25655
  // @ts-ignore
25656
25656
  return pb[`bvec${this.value.length}`](...this.value);
25657
25657
  }
25658
25658
  }
25659
- /**
25660
- * IR expression for shader input variables
25661
- *
25662
- * @remarks
25663
- * Represents variables that are passed into the shader from the vertex stage
25664
- * or defined in the current scope. Examples include vertex attributes,
25665
- * varyings, and built-in variables.
25666
- *
25667
- * @example
25668
- * ```typescript
25669
- * // Reference to vertex color
25670
- * const vertexColor = new IRInput('zVertexColor');
25671
- *
25672
- * // Reference via function
25673
- * const worldPos = new IRInput((scope) => scope.zWorldPos);
25674
- * ```
25675
- *
25676
- * @public
25659
+ /**
25660
+ * IR expression for shader input variables
25661
+ *
25662
+ * @remarks
25663
+ * Represents variables that are passed into the shader from the vertex stage
25664
+ * or defined in the current scope. Examples include vertex attributes,
25665
+ * varyings, and built-in variables.
25666
+ *
25667
+ * @example
25668
+ * ```typescript
25669
+ * // Reference to vertex color
25670
+ * const vertexColor = new IRInput('zVertexColor');
25671
+ *
25672
+ * // Reference via function
25673
+ * const worldPos = new IRInput((scope) => scope.zWorldPos);
25674
+ * ```
25675
+ *
25676
+ * @public
25677
25677
  */ class IRInput extends IRExpression {
25678
25678
  /** The variable name or a function that retrieves the variable from scope */ func;
25679
- /**
25680
- * Creates an input variable expression
25681
- *
25682
- * @param func - Variable name string or function to retrieve the variable
25679
+ /**
25680
+ * Creates an input variable expression
25681
+ *
25682
+ * @param func - Variable name string or function to retrieve the variable
25683
25683
  */ constructor(func){
25684
25684
  super();
25685
25685
  this.func = func;
25686
25686
  }
25687
- /**
25688
- * Generates shader code for this input variable
25689
- *
25690
- * @param pb - The program builder
25691
- * @returns The shader expression referencing the input variable
25687
+ /**
25688
+ * Generates shader code for this input variable
25689
+ *
25690
+ * @param pb - The program builder
25691
+ * @returns The shader expression referencing the input variable
25692
25692
  */ create(pb) {
25693
25693
  return typeof this.func === 'string' ? pb.getCurrentScope()[this.func] : this.func(pb.getCurrentScope());
25694
25694
  }
25695
25695
  }
25696
- /**
25697
- * IR expression for function calls and operations
25698
- *
25699
- * @remarks
25700
- * Represents built-in shader functions (add, mul, sin, etc.) or vector constructors.
25701
- * Uses reference counting to determine if result should be stored in a temporary variable.
25702
- *
25703
- * @example
25704
- * ```typescript
25705
- * // Addition: a + b
25706
- * const add = new IRFunc([exprA, exprB], 'add');
25707
- *
25708
- * // Vector constructor: vec3(x, y, z)
25709
- * const vec = new IRFunc([x, y, z], 'vec3');
25710
- * ```
25711
- *
25712
- * @public
25696
+ /**
25697
+ * IR expression for function calls and operations
25698
+ *
25699
+ * @remarks
25700
+ * Represents built-in shader functions (add, mul, sin, etc.) or vector constructors.
25701
+ * Uses reference counting to determine if result should be stored in a temporary variable.
25702
+ *
25703
+ * @example
25704
+ * ```typescript
25705
+ * // Addition: a + b
25706
+ * const add = new IRFunc([exprA, exprB], 'add');
25707
+ *
25708
+ * // Vector constructor: vec3(x, y, z)
25709
+ * const vec = new IRFunc([x, y, z], 'vec3');
25710
+ * ```
25711
+ *
25712
+ * @public
25713
25713
  */ class IRFunc extends IRExpression {
25714
25714
  /** Array of parameters (can be expressions or literal numbers) */ params;
25715
25715
  /** The function name (e.g., 'add', 'mul', 'sin', 'vec3') */ func;
25716
25716
  /** Cached temporary variable name if expression is referenced multiple times */ tmpName;
25717
- /**
25718
- * Creates a function call expression
25719
- *
25720
- * @param params - Array of parameters for the function
25721
- * @param func - The function name or function implementation
25722
- *
25723
- * @remarks
25724
- * Increments reference count for all expression parameters.
25717
+ /**
25718
+ * Creates a function call expression
25719
+ *
25720
+ * @param params - Array of parameters for the function
25721
+ * @param func - The function name or function implementation
25722
+ *
25723
+ * @remarks
25724
+ * Increments reference count for all expression parameters.
25725
25725
  */ constructor(params, func){
25726
25726
  super();
25727
25727
  this.params = params.map((param)=>param instanceof IRExpression ? param.addRef() : param);
@@ -25731,15 +25731,15 @@ let paramId = 1;
25731
25731
  /** Reset for next creation */ reset() {
25732
25732
  this.tmpName = '';
25733
25733
  }
25734
- /**
25735
- * Generates shader code for this function call
25736
- *
25737
- * @param pb - The program builder
25738
- * @returns The shader expression for the function result
25739
- *
25740
- * @remarks
25741
- * If referenced multiple times (_ref > 1), stores result in a temporary variable.
25742
- * Otherwise, generates the function call inline.
25734
+ /**
25735
+ * Generates shader code for this function call
25736
+ *
25737
+ * @param pb - The program builder
25738
+ * @returns The shader expression for the function result
25739
+ *
25740
+ * @remarks
25741
+ * If referenced multiple times (_ref > 1), stores result in a temporary variable.
25742
+ * Otherwise, generates the function call inline.
25743
25743
  */ create(pb) {
25744
25744
  if (this.tmpName) {
25745
25745
  const exp = pb.getCurrentScope()[this.tmpName];
@@ -25761,27 +25761,27 @@ let paramId = 1;
25761
25761
  }
25762
25762
  }
25763
25763
  }
25764
- /**
25765
- * IR expression for function output values
25766
- *
25767
- * @remarks
25768
- * Represents the output of a material function (subgraph).
25769
- * Handles caching of output values when referenced multiple times.
25770
- *
25771
- * @example
25772
- * ```typescript
25773
- * // Function returns a processed color value
25774
- * const output = new IRFunctionOutput(colorExpression);
25775
- * ```
25776
- *
25777
- * @public
25764
+ /**
25765
+ * IR expression for function output values
25766
+ *
25767
+ * @remarks
25768
+ * Represents the output of a material function (subgraph).
25769
+ * Handles caching of output values when referenced multiple times.
25770
+ *
25771
+ * @example
25772
+ * ```typescript
25773
+ * // Function returns a processed color value
25774
+ * const output = new IRFunctionOutput(colorExpression);
25775
+ * ```
25776
+ *
25777
+ * @public
25778
25778
  */ class IRFunctionOutput extends IRExpression {
25779
25779
  /** Cached temporary variable name for the output */ tmpName;
25780
25780
  /** The input expression to output */ input;
25781
- /**
25782
- * Creates a function output expression
25783
- *
25784
- * @param input - The expression or value to output
25781
+ /**
25782
+ * Creates a function output expression
25783
+ *
25784
+ * @param input - The expression or value to output
25785
25785
  */ constructor(input){
25786
25786
  super();
25787
25787
  this.input = input;
@@ -25790,14 +25790,14 @@ let paramId = 1;
25790
25790
  /** Reset for next creation */ reset() {
25791
25791
  this.tmpName = '';
25792
25792
  }
25793
- /**
25794
- * Generates shader code for this function output
25795
- *
25796
- * @param pb - The program builder
25797
- * @returns The shader expression or value
25798
- *
25799
- * @remarks
25800
- * If referenced multiple times, stores result in a temporary variable.
25793
+ /**
25794
+ * Generates shader code for this function output
25795
+ *
25796
+ * @param pb - The program builder
25797
+ * @returns The shader expression or value
25798
+ *
25799
+ * @remarks
25800
+ * If referenced multiple times, stores result in a temporary variable.
25801
25801
  */ create(pb) {
25802
25802
  if (this.tmpName) {
25803
25803
  return pb.getCurrentScope()[this.tmpName];
@@ -25812,30 +25812,30 @@ let paramId = 1;
25812
25812
  }
25813
25813
  }
25814
25814
  }
25815
- /**
25816
- * IR expression for calling user-defined material functions
25817
- *
25818
- * @remarks
25819
- * Represents a call to a material function (subgraph) with parameters.
25820
- * Generates both the function definition and the call site.
25821
- * Uses a struct return type to return multiple outputs from the function.
25822
- *
25823
- * @example
25824
- * ```typescript
25825
- * // Call to a custom "calculateLighting" function
25826
- * const call = new IRCallFunc(functionNode, [normalExpr, lightDirExpr]);
25827
- * ```
25828
- *
25829
- * @public
25815
+ /**
25816
+ * IR expression for calling user-defined material functions
25817
+ *
25818
+ * @remarks
25819
+ * Represents a call to a material function (subgraph) with parameters.
25820
+ * Generates both the function definition and the call site.
25821
+ * Uses a struct return type to return multiple outputs from the function.
25822
+ *
25823
+ * @example
25824
+ * ```typescript
25825
+ * // Call to a custom "calculateLighting" function
25826
+ * const call = new IRCallFunc(functionNode, [normalExpr, lightDirExpr]);
25827
+ * ```
25828
+ *
25829
+ * @public
25830
25830
  */ class IRCallFunc extends IRExpression {
25831
25831
  /** The function call node from the graph */ node;
25832
25832
  /** Array of argument expressions */ args;
25833
25833
  /** Cached temporary variable name if result is referenced multiple times */ tmpName;
25834
- /**
25835
- * Creates a function call expression
25836
- *
25837
- * @param node - The function call node
25838
- * @param args - Array of argument expressions
25834
+ /**
25835
+ * Creates a function call expression
25836
+ *
25837
+ * @param node - The function call node
25838
+ * @param args - Array of argument expressions
25839
25839
  */ constructor(node, args){
25840
25840
  super();
25841
25841
  this.node = node;
@@ -25845,16 +25845,16 @@ let paramId = 1;
25845
25845
  /** Reset for next creation */ reset() {
25846
25846
  this.tmpName = '';
25847
25847
  }
25848
- /**
25849
- * Generates shader code for the function definition and call
25850
- *
25851
- * @param pb - The program builder
25852
- * @returns The shader expression for the function result
25853
- *
25854
- * @remarks
25855
- * First generates the function definition (if not already defined),
25856
- * then generates the function call with the provided arguments.
25857
- * The function returns a struct containing all output values.
25848
+ /**
25849
+ * Generates shader code for the function definition and call
25850
+ *
25851
+ * @param pb - The program builder
25852
+ * @returns The shader expression for the function result
25853
+ *
25854
+ * @remarks
25855
+ * First generates the function definition (if not already defined),
25856
+ * then generates the function call with the provided arguments.
25857
+ * The function returns a struct containing all output values.
25858
25858
  */ create(pb) {
25859
25859
  if (this.tmpName) {
25860
25860
  return pb.getCurrentScope()[this.tmpName];
@@ -26021,82 +26021,82 @@ class IRComparison extends IRExpression {
26021
26021
  }
26022
26022
  }
26023
26023
  }
26024
- /**
26025
- * IR expression for vector component swizzling
26026
- *
26027
- * @remarks
26028
- * Extracts specific components from a vector using swizzle notation.
26029
- * For scalar sources, constructs a vector with replicated values.
26030
- *
26031
- * @example
26032
- * ```typescript
26033
- * // Extract xyz from vec4
26034
- * const xyz = new IRSwizzle(vec4Expr, 'xyz');
26035
- *
26036
- * // Extract single component
26037
- * const x = new IRSwizzle(vec3Expr, 'x');
26038
- *
26039
- * // Swizzle and reorder
26040
- * const bgr = new IRSwizzle(rgbExpr, 'bgr');
26041
- * ```
26042
- *
26043
- * @public
26024
+ /**
26025
+ * IR expression for vector component swizzling
26026
+ *
26027
+ * @remarks
26028
+ * Extracts specific components from a vector using swizzle notation.
26029
+ * For scalar sources, constructs a vector with replicated values.
26030
+ *
26031
+ * @example
26032
+ * ```typescript
26033
+ * // Extract xyz from vec4
26034
+ * const xyz = new IRSwizzle(vec4Expr, 'xyz');
26035
+ *
26036
+ * // Extract single component
26037
+ * const x = new IRSwizzle(vec3Expr, 'x');
26038
+ *
26039
+ * // Swizzle and reorder
26040
+ * const bgr = new IRSwizzle(rgbExpr, 'bgr');
26041
+ * ```
26042
+ *
26043
+ * @public
26044
26044
  */ class IRSwizzle extends IRExpression {
26045
26045
  /** The source expression to swizzle */ src;
26046
26046
  /** The swizzle pattern (e.g., 'xyz', 'rgb', 'x', 'yzw') */ hash;
26047
- /**
26048
- * Creates a swizzle expression
26049
- *
26050
- * @param src - The source vector expression
26051
- * @param hash - The swizzle pattern using xyzw or rgba notation
26047
+ /**
26048
+ * Creates a swizzle expression
26049
+ *
26050
+ * @param src - The source vector expression
26051
+ * @param hash - The swizzle pattern using xyzw or rgba notation
26052
26052
  */ constructor(src, hash){
26053
26053
  super();
26054
26054
  this.src = src.addRef();
26055
26055
  this.hash = hash;
26056
26056
  }
26057
- /**
26058
- * Generates shader code for the swizzle operation
26059
- *
26060
- * @param pb - The program builder
26061
- * @returns The swizzled shader expression
26062
- *
26063
- * @remarks
26064
- * If source is a scalar number, creates a vector with that value repeated.
26065
- * Otherwise, applies the swizzle notation to the source expression.
26057
+ /**
26058
+ * Generates shader code for the swizzle operation
26059
+ *
26060
+ * @param pb - The program builder
26061
+ * @returns The swizzled shader expression
26062
+ *
26063
+ * @remarks
26064
+ * If source is a scalar number, creates a vector with that value repeated.
26065
+ * Otherwise, applies the swizzle notation to the source expression.
26066
26066
  */ create(pb) {
26067
26067
  const src = this.src.create(pb);
26068
26068
  // @ts-ignore
26069
26069
  return typeof src === 'number' ? pb[`vec${this.hash.length}`](src) : src[this.hash];
26070
26070
  }
26071
26071
  }
26072
- /**
26073
- * IR expression for type casting with padding
26074
- *
26075
- * @remarks
26076
- * Converts a value to a different vector type by padding with zeros.
26077
- * Used when a smaller vector needs to be converted to a larger one.
26078
- *
26079
- * @example
26080
- * ```typescript
26081
- * // Cast float to vec3: vec3(value, 0, 0)
26082
- * const vec3 = new IRCast(floatExpr, 'vec3', 2);
26083
- *
26084
- * // Cast vec2 to vec4: vec4(value.xy, 0, 0)
26085
- * const vec4 = new IRCast(vec2Expr, 'vec4', 2);
26086
- * ```
26087
- *
26088
- * @public
26072
+ /**
26073
+ * IR expression for type casting with padding
26074
+ *
26075
+ * @remarks
26076
+ * Converts a value to a different vector type by padding with zeros.
26077
+ * Used when a smaller vector needs to be converted to a larger one.
26078
+ *
26079
+ * @example
26080
+ * ```typescript
26081
+ * // Cast float to vec3: vec3(value, 0, 0)
26082
+ * const vec3 = new IRCast(floatExpr, 'vec3', 2);
26083
+ *
26084
+ * // Cast vec2 to vec4: vec4(value.xy, 0, 0)
26085
+ * const vec4 = new IRCast(vec2Expr, 'vec4', 2);
26086
+ * ```
26087
+ *
26088
+ * @public
26089
26089
  */ class IRCast extends IRExpression {
26090
26090
  /** The source expression to cast */ src;
26091
26091
  /** The values to be filled */ fill;
26092
26092
  /** The target type name (e.g., 'vec2', 'vec3', 'vec4') */ type;
26093
26093
  /** Number of zero components to append */ cast;
26094
- /**
26095
- * Creates a type cast expression
26096
- *
26097
- * @param src - The source expression
26098
- * @param type - The target type name
26099
- * @param cast - Number of zero components to append
26094
+ /**
26095
+ * Creates a type cast expression
26096
+ *
26097
+ * @param src - The source expression
26098
+ * @param type - The target type name
26099
+ * @param cast - Number of zero components to append
26100
26100
  */ constructor(src, type, cast, fill){
26101
26101
  super();
26102
26102
  this.src = src.addRef();
@@ -26104,15 +26104,15 @@ class IRComparison extends IRExpression {
26104
26104
  this.fill = fill?.slice() ?? null;
26105
26105
  this.type = type;
26106
26106
  }
26107
- /**
26108
- * Generates shader code for the type cast
26109
- *
26110
- * @param pb - The program builder
26111
- * @returns The casted shader expression
26112
- *
26113
- * @remarks
26114
- * Creates a vector constructor with the source value followed by zeros.
26115
- * Example: vec4(src, 0, 0) for casting vec2 to vec4.
26107
+ /**
26108
+ * Generates shader code for the type cast
26109
+ *
26110
+ * @param pb - The program builder
26111
+ * @returns The casted shader expression
26112
+ *
26113
+ * @remarks
26114
+ * Creates a vector constructor with the source value followed by zeros.
26115
+ * Example: vec4(src, 0, 0) for casting vec2 to vec4.
26116
26116
  */ create(pb) {
26117
26117
  // @ts-ignore
26118
26118
  return pb[this.type](this.src.create(pb), ...this.fill ?? Array.from({
@@ -26120,35 +26120,35 @@ class IRComparison extends IRExpression {
26120
26120
  }).fill(0));
26121
26121
  }
26122
26122
  }
26123
- /**
26124
- * IR expression for texture sampling
26125
- *
26126
- * @remarks
26127
- * Represents a texture lookup operation with optional normal map decoding.
26128
- * Handles both color and normal map sampling with appropriate transformations.
26129
- * Uses reference counting to cache the sampled result if used multiple times.
26130
- *
26131
- * @example
26132
- * ```typescript
26133
- * // Sample color texture
26134
- * const color = new IRSampleTexture(texExpr, uvExpr, 'Color');
26135
- *
26136
- * // Sample normal map (automatically decodes from [0,1] to [-1,1])
26137
- * const normal = new IRSampleTexture(texExpr, uvExpr, 'Normal');
26138
- * ```
26139
- *
26140
- * @public
26123
+ /**
26124
+ * IR expression for texture sampling
26125
+ *
26126
+ * @remarks
26127
+ * Represents a texture lookup operation with optional normal map decoding.
26128
+ * Handles both color and normal map sampling with appropriate transformations.
26129
+ * Uses reference counting to cache the sampled result if used multiple times.
26130
+ *
26131
+ * @example
26132
+ * ```typescript
26133
+ * // Sample color texture
26134
+ * const color = new IRSampleTexture(texExpr, uvExpr, 'Color');
26135
+ *
26136
+ * // Sample normal map (automatically decodes from [0,1] to [-1,1])
26137
+ * const normal = new IRSampleTexture(texExpr, uvExpr, 'Normal');
26138
+ * ```
26139
+ *
26140
+ * @public
26141
26141
  */ class IRSampleTexture extends IRExpression {
26142
26142
  /** The texture expression */ tex;
26143
26143
  /** The texture coordinate expression */ coord;
26144
26144
  /** The sampler type determining how to interpret the sampled value */ samplerType;
26145
26145
  /** Cached temporary variable name if result is referenced multiple times */ tmpName;
26146
- /**
26147
- * Creates a texture sample expression
26148
- *
26149
- * @param tex - The texture to sample from
26150
- * @param coord - The texture coordinates
26151
- * @param samplerType - How to interpret the sampled value ('Color' or 'Normal')
26146
+ /**
26147
+ * Creates a texture sample expression
26148
+ *
26149
+ * @param tex - The texture to sample from
26150
+ * @param coord - The texture coordinates
26151
+ * @param samplerType - How to interpret the sampled value ('Color' or 'Normal')
26152
26152
  */ constructor(tex, coord, samplerType){
26153
26153
  super();
26154
26154
  this.tex = tex.addRef();
@@ -26159,18 +26159,18 @@ class IRComparison extends IRExpression {
26159
26159
  /** Reset for next creation */ reset() {
26160
26160
  this.tmpName = '';
26161
26161
  }
26162
- /**
26163
- * Generates shader code for the texture sample operation
26164
- *
26165
- * @param pb - The program builder
26166
- * @returns The sampled color value
26167
- *
26168
- * @remarks
26169
- * For normal maps, applies the transformation: normal * 2 - 1 to convert
26170
- * from [0,1] texture space to [-1,1] tangent space.
26171
- * Caches result in a temporary variable if referenced multiple times.
26172
- *
26173
- * @throws Error if texture coordinate is not a valid expression or array
26162
+ /**
26163
+ * Generates shader code for the texture sample operation
26164
+ *
26165
+ * @param pb - The program builder
26166
+ * @returns The sampled color value
26167
+ *
26168
+ * @remarks
26169
+ * For normal maps, applies the transformation: normal * 2 - 1 to convert
26170
+ * from [0,1] texture space to [-1,1] tangent space.
26171
+ * Caches result in a temporary variable if referenced multiple times.
26172
+ *
26173
+ * @throws Error if texture coordinate is not a valid expression or array
26174
26174
  */ create(pb) {
26175
26175
  if (this.tmpName) {
26176
26176
  return pb.getCurrentScope()[this.tmpName];
@@ -26205,27 +26205,27 @@ class IRComparison extends IRExpression {
26205
26205
  }
26206
26206
  }
26207
26207
  }
26208
- /**
26209
- * IR expression for texture uniform constants
26210
- *
26211
- * @remarks
26212
- * Represents a texture parameter that will be bound as a uniform.
26213
- * Includes sampler configuration for texture filtering and addressing modes.
26214
- *
26215
- * @example
26216
- * ```typescript
26217
- * const tex = new IRConstantTexture(
26218
- * 'u_baseColorMap',
26219
- * 'tex2d',
26220
- * 'repeat',
26221
- * 'repeat',
26222
- * 'linear',
26223
- * 'linear',
26224
- * 'linear'
26225
- * );
26226
- * ```
26227
- *
26228
- * @public
26208
+ /**
26209
+ * IR expression for texture uniform constants
26210
+ *
26211
+ * @remarks
26212
+ * Represents a texture parameter that will be bound as a uniform.
26213
+ * Includes sampler configuration for texture filtering and addressing modes.
26214
+ *
26215
+ * @example
26216
+ * ```typescript
26217
+ * const tex = new IRConstantTexture(
26218
+ * 'u_baseColorMap',
26219
+ * 'tex2d',
26220
+ * 'repeat',
26221
+ * 'repeat',
26222
+ * 'linear',
26223
+ * 'linear',
26224
+ * 'linear'
26225
+ * );
26226
+ * ```
26227
+ *
26228
+ * @public
26229
26229
  */ class IRConstantTexture extends IRExpression {
26230
26230
  /** The uniform texture variable name */ name;
26231
26231
  /** The texture id */ id;
@@ -26237,18 +26237,18 @@ class IRComparison extends IRExpression {
26237
26237
  /** Magnification filter mode */ filterMag;
26238
26238
  /** Mipmap filter mode */ filterMip;
26239
26239
  /** Whether texture params is used */ useParams;
26240
- /**
26241
- * Creates a texture constant expression
26242
- *
26243
- * @param name - The uniform variable name
26244
- * @param id - The texture id
26245
- * @param type - The texture type
26246
- * @param sRGB - Whether this texture should be loaded in sRGB color space
26247
- * @param addressU - Horizontal addressing mode
26248
- * @param addressV - Vertical addressing mode
26249
- * @param minFilter - Minification filter
26250
- * @param magFilter - Magnification filter
26251
- * @param mipFilter - Mipmap filter
26240
+ /**
26241
+ * Creates a texture constant expression
26242
+ *
26243
+ * @param name - The uniform variable name
26244
+ * @param id - The texture id
26245
+ * @param type - The texture type
26246
+ * @param sRGB - Whether this texture should be loaded in sRGB color space
26247
+ * @param addressU - Horizontal addressing mode
26248
+ * @param addressV - Vertical addressing mode
26249
+ * @param minFilter - Minification filter
26250
+ * @param magFilter - Magnification filter
26251
+ * @param mipFilter - Mipmap filter
26252
26252
  */ constructor(name, id, type, sRGB, addressU, addressV, minFilter, magFilter, mipFilter){
26253
26253
  super();
26254
26254
  this.name = name;
@@ -26262,14 +26262,14 @@ class IRComparison extends IRExpression {
26262
26262
  this.filterMip = mipFilter;
26263
26263
  this.useParams = false;
26264
26264
  }
26265
- /**
26266
- * Generates shader code for the texture uniform
26267
- *
26268
- * @param pb - The program builder
26269
- * @returns The texture uniform reference
26270
- *
26271
- * @remarks
26272
- * Creates the uniform declaration in the global scope if not already present.
26265
+ /**
26266
+ * Generates shader code for the texture uniform
26267
+ *
26268
+ * @param pb - The program builder
26269
+ * @returns The texture uniform reference
26270
+ *
26271
+ * @remarks
26272
+ * Creates the uniform declaration in the global scope if not already present.
26273
26273
  */ create(pb) {
26274
26274
  if (!pb.getGlobalScope()[this.name]) {
26275
26275
  // @ts-ignore
@@ -26277,11 +26277,11 @@ class IRComparison extends IRExpression {
26277
26277
  }
26278
26278
  return pb.getGlobalScope()[this.name];
26279
26279
  }
26280
- /**
26281
- * Converts to a uniform texture descriptor
26282
- *
26283
- * @param node - The texture node
26284
- * @returns Uniform texture descriptor with texture and sampler references
26280
+ /**
26281
+ * Converts to a uniform texture descriptor
26282
+ *
26283
+ * @param node - The texture node
26284
+ * @returns Uniform texture descriptor with texture and sampler references
26285
26285
  */ asUniformTexture() {
26286
26286
  return {
26287
26287
  name: this.name,
@@ -26296,24 +26296,24 @@ class IRComparison extends IRExpression {
26296
26296
  };
26297
26297
  }
26298
26298
  }
26299
- /**
26300
- * Material Blueprint Intermediate Representation
26301
- *
26302
- * @remarks
26303
- * The IR is a compiled representation of the material node graph that can be
26304
- * efficiently translated to shader code. It performs:
26305
- * - Type checking and validation
26306
- * - Expression optimization (common subexpression elimination via reference counting)
26307
- * - Uniform extraction (constants become shader uniforms)
26308
- * - Dependency analysis (determines required vertex attributes)
26309
- *
26310
- * The compilation process:
26311
- * 1. Traverse the DAG in topological order
26312
- * 2. Build an IR expression tree
26313
- * 3. Track uniforms and behaviors
26314
- * 4. Generate optimized shader code from the IR
26315
- *
26316
- * @public
26299
+ /**
26300
+ * Material Blueprint Intermediate Representation
26301
+ *
26302
+ * @remarks
26303
+ * The IR is a compiled representation of the material node graph that can be
26304
+ * efficiently translated to shader code. It performs:
26305
+ * - Type checking and validation
26306
+ * - Expression optimization (common subexpression elimination via reference counting)
26307
+ * - Uniform extraction (constants become shader uniforms)
26308
+ * - Dependency analysis (determines required vertex attributes)
26309
+ *
26310
+ * The compilation process:
26311
+ * 1. Traverse the DAG in topological order
26312
+ * 2. Build an IR expression tree
26313
+ * 3. Track uniforms and behaviors
26314
+ * 4. Generate optimized shader code from the IR
26315
+ *
26316
+ * @public
26317
26317
  */ class MaterialBlueprintIR {
26318
26318
  /** The directed acyclic graph of material nodes */ _dag;
26319
26319
  /** Unique hash identifying this material configuration */ _hash;
@@ -26325,16 +26325,16 @@ class IRComparison extends IRExpression {
26325
26325
  /** Fallback texture uniforms generated for TextureSample nodes without texture input */ _textureSampleFallbackMap;
26326
26326
  /** Flags indicating which shader features are used */ _behaviors;
26327
26327
  /** Array of named output expressions (e.g., baseColor, normal, metallic) */ _outputs;
26328
- /**
26329
- * Creates and compiles a material blueprint IR
26330
- *
26331
- * @param dag - The material node graph DAG
26332
- * @param hash - Unique identifier for this material
26333
- * @param editorState - Editor state snapshot
26334
- *
26335
- * @remarks
26336
- * Automatically compiles the DAG during construction.
26337
- * Check the `ok` property to verify successful compilation.
26328
+ /**
26329
+ * Creates and compiles a material blueprint IR
26330
+ *
26331
+ * @param dag - The material node graph DAG
26332
+ * @param hash - Unique identifier for this material
26333
+ * @param editorState - Editor state snapshot
26334
+ *
26335
+ * @remarks
26336
+ * Automatically compiles the DAG during construction.
26337
+ * Check the `ok` property to verify successful compilation.
26338
26338
  */ constructor(dag, hash, editorState){
26339
26339
  this._dag = dag ?? {
26340
26340
  nodeMap: {},
@@ -26349,10 +26349,10 @@ class IRComparison extends IRExpression {
26349
26349
  this._editorState = editorState;
26350
26350
  this.compile();
26351
26351
  }
26352
- /**
26353
- * Whether the IR compiled successfully
26354
- *
26355
- * @returns True if compilation produced valid outputs
26352
+ /**
26353
+ * Whether the IR compiled successfully
26354
+ *
26355
+ * @returns True if compilation produced valid outputs
26356
26356
  */ get ok() {
26357
26357
  return this._outputs ? this._outputs.length > 0 : false;
26358
26358
  }
@@ -26377,17 +26377,17 @@ class IRComparison extends IRExpression {
26377
26377
  /** Gets the array of uniform textures to bind at runtime */ get uniformTextures() {
26378
26378
  return this._uniformTextures;
26379
26379
  }
26380
- /**
26381
- * Compiles the material node graph to IR
26382
- *
26383
- * @returns True if compilation succeeded, false otherwise
26384
- *
26385
- * @remarks
26386
- * Processes all root nodes (typically a single material output node)
26387
- * and builds IR expressions for all connected inputs.
26388
- * Collects all required uniforms and sets behavior flags.
26389
- *
26390
- * Compilation fails if any required input is missing.
26380
+ /**
26381
+ * Compiles the material node graph to IR
26382
+ *
26383
+ * @returns True if compilation succeeded, false otherwise
26384
+ *
26385
+ * @remarks
26386
+ * Processes all root nodes (typically a single material output node)
26387
+ * and builds IR expressions for all connected inputs.
26388
+ * Collects all required uniforms and sets behavior flags.
26389
+ *
26390
+ * Compilation fails if any required input is missing.
26391
26391
  */ compile() {
26392
26392
  this.reset();
26393
26393
  this._outputs = [];
@@ -26427,24 +26427,24 @@ class IRComparison extends IRExpression {
26427
26427
  }
26428
26428
  return true;
26429
26429
  }
26430
- /**
26431
- * Generates shader code from the IR
26432
- *
26433
- * @param pb - The program builder to generate code with
26434
- * @returns Array of named shader expressions, or null if IR is invalid
26435
- *
26436
- * @remarks
26437
- * Translates all IR expressions to actual shader code.
26438
- * Should be called within a shader function scope.
26439
- *
26440
- * @example
26441
- * ```typescript
26442
- * pb.fragmentShader(function() {
26443
- * const outputs = ir.create(this);
26444
- * this.baseColor = outputs.find(o => o.name === 'baseColor').exp;
26445
- * this.normal = outputs.find(o => o.name === 'normal').exp;
26446
- * });
26447
- * ```
26430
+ /**
26431
+ * Generates shader code from the IR
26432
+ *
26433
+ * @param pb - The program builder to generate code with
26434
+ * @returns Array of named shader expressions, or null if IR is invalid
26435
+ *
26436
+ * @remarks
26437
+ * Translates all IR expressions to actual shader code.
26438
+ * Should be called within a shader function scope.
26439
+ *
26440
+ * @example
26441
+ * ```typescript
26442
+ * pb.fragmentShader(function() {
26443
+ * const outputs = ir.create(this);
26444
+ * this.baseColor = outputs.find(o => o.name === 'baseColor').exp;
26445
+ * this.normal = outputs.find(o => o.name === 'normal').exp;
26446
+ * });
26447
+ * ```
26448
26448
  */ create(pb) {
26449
26449
  if (!this._outputs) {
26450
26450
  return null;
@@ -26461,12 +26461,12 @@ class IRComparison extends IRExpression {
26461
26461
  }
26462
26462
  return outputs;
26463
26463
  }
26464
- /**
26465
- * Resets the IR state for recompilation
26466
- *
26467
- * @remarks
26468
- * Clears all compiled data including expressions, uniforms, and behaviors.
26469
- * Called at the start of compilation.
26464
+ /**
26465
+ * Resets the IR state for recompilation
26466
+ *
26467
+ * @remarks
26468
+ * Clears all compiled data including expressions, uniforms, and behaviors.
26469
+ * Called at the start of compilation.
26470
26470
  */ reset() {
26471
26471
  this._expressions = [];
26472
26472
  this._expressionMap = new Map();
@@ -26479,19 +26479,19 @@ class IRComparison extends IRExpression {
26479
26479
  useVertexUV: false
26480
26480
  };
26481
26481
  }
26482
- /**
26483
- * Converts a graph node to an IR expression
26484
- *
26485
- * @param node - The graph node to convert
26486
- * @param output - The output slot ID
26487
- * @param originType - Optional type override for type casting
26488
- * @returns The corresponding IR expression
26489
- *
26490
- * @remarks
26491
- * Main dispatch method that routes to specific converters based on node type.
26492
- * Handles automatic type casting when originType differs from node output type.
26493
- *
26494
- * @throws Error if type casting is invalid
26482
+ /**
26483
+ * Converts a graph node to an IR expression
26484
+ *
26485
+ * @param node - The graph node to convert
26486
+ * @param output - The output slot ID
26487
+ * @param originType - Optional type override for type casting
26488
+ * @returns The corresponding IR expression
26489
+ *
26490
+ * @remarks
26491
+ * Main dispatch method that routes to specific converters based on node type.
26492
+ * Handles automatic type casting when originType differs from node output type.
26493
+ *
26494
+ * @throws Error if type casting is invalid
26495
26495
  */ ir(inputNode) {
26496
26496
  const node = inputNode.inputNode;
26497
26497
  const output = inputNode.inputId;
@@ -26619,19 +26619,19 @@ class IRComparison extends IRExpression {
26619
26619
  }
26620
26620
  return expr;
26621
26621
  }
26622
- /**
26623
- * Gets or creates an IR expression for a graph node
26624
- *
26625
- * @param node - The graph node
26626
- * @param outputId - The output slot ID
26627
- * @param ctor - The IR expression constructor
26628
- * @param args - Constructor arguments
26629
- * @returns The cached or newly created IR expression
26630
- *
26631
- * @remarks
26632
- * Implements common subexpression elimination by caching expressions per node.
26633
- * Handles output slot swizzling and type casting.
26634
- * Collects uniform values and textures.
26622
+ /**
26623
+ * Gets or creates an IR expression for a graph node
26624
+ *
26625
+ * @param node - The graph node
26626
+ * @param outputId - The output slot ID
26627
+ * @param ctor - The IR expression constructor
26628
+ * @param args - Constructor arguments
26629
+ * @returns The cached or newly created IR expression
26630
+ *
26631
+ * @remarks
26632
+ * Implements common subexpression elimination by caching expressions per node.
26633
+ * Handles output slot swizzling and type casting.
26634
+ * Collects uniform values and textures.
26635
26635
  */ getOrCreateIRExpression(node, outputId, ctor, ...args) {
26636
26636
  let ir;
26637
26637
  if (!this._expressionMap.has(node)) {
@@ -26886,11 +26886,11 @@ class IRComparison extends IRExpression {
26886
26886
  this.$l.objUp = pb.normalize(pb.div(pb.mul(this.cameraUp, this.rotation), this.objScale));
26887
26887
  this.$l.objRight = pb.normalize(pb.div(pb.mul(this.cameraRight, this.rotation), this.objScale));
26888
26888
  // make ortho
26889
- /*
26890
- this.objRight = pb.normalize(
26891
- pb.sub(this.objRight, pb.mul(this.objUp, pb.dot(this.objRight, this.objUp)))
26892
- );
26893
- this.objForward = pb.cross(this.objUp, this.objRight);
26889
+ /*
26890
+ this.objRight = pb.normalize(
26891
+ pb.sub(this.objRight, pb.mul(this.objUp, pb.dot(this.objRight, this.objUp)))
26892
+ );
26893
+ this.objForward = pb.cross(this.objUp, this.objRight);
26894
26894
  */ // make rotation matrix
26895
26895
  this.$l.billboardMatrix = pb.mat3(this.objRight.x, this.objUp.x, this.objForward.x, this.objRight.y, this.objUp.y, this.objForward.y, this.objRight.z, this.objUp.z, this.objForward.z);
26896
26896
  this.$return(pb.transpose(this.billboardMatrix));
@@ -29734,14 +29734,14 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
29734
29734
  }
29735
29735
 
29736
29736
  // ─── Handles ────────────────────────────────────────────────────────────
29737
- /**
29738
- * Opaque handle referencing a resource within the render graph.
29739
- *
29740
- * Handles are obtained from {@link RGPassBuilder.createTexture}, {@link RGPassBuilder.createFramebuffer},
29741
- * {@link RenderGraph.importTexture}, or {@link RGPassBuilder.write}. They are lightweight identifiers
29742
- * used to declare dependencies between passes.
29743
- *
29744
- * @public
29737
+ /**
29738
+ * Opaque handle referencing a resource within the render graph.
29739
+ *
29740
+ * Handles are obtained from {@link RGPassBuilder.createTexture}, {@link RGPassBuilder.createFramebuffer},
29741
+ * {@link RenderGraph.importTexture}, or {@link RGPassBuilder.write}. They are lightweight identifiers
29742
+ * used to declare dependencies between passes.
29743
+ *
29744
+ * @public
29745
29745
  */ class RGHandle {
29746
29746
  /** @internal */ _id;
29747
29747
  /** @internal */ _name;
@@ -29753,9 +29753,9 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
29753
29753
  return this._name;
29754
29754
  }
29755
29755
  }
29756
- /**
29757
- * Internal bookkeeping for a resource within the render graph.
29758
- * @public
29756
+ /**
29757
+ * Internal bookkeeping for a resource within the render graph.
29758
+ * @public
29759
29759
  */ class RGResource {
29760
29760
  id;
29761
29761
  name;
@@ -29772,14 +29772,14 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
29772
29772
  this.physicalId = physicalId;
29773
29773
  }
29774
29774
  }
29775
- /**
29776
- * Ordered execution step inside a render graph pass.
29777
- *
29778
- * Subpasses share the parent pass's resource declarations, lifetime, culling,
29779
- * and access validation. They are intended to make multi-step pass bodies
29780
- * explicit without splitting graph-level resource dependencies.
29781
- *
29782
- * @public
29775
+ /**
29776
+ * Ordered execution step inside a render graph pass.
29777
+ *
29778
+ * Subpasses share the parent pass's resource declarations, lifetime, culling,
29779
+ * and access validation. They are intended to make multi-step pass bodies
29780
+ * explicit without splitting graph-level resource dependencies.
29781
+ *
29782
+ * @public
29783
29783
  */ class RGSubpass {
29784
29784
  name;
29785
29785
  executeFn;
@@ -29788,9 +29788,9 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
29788
29788
  this.executeFn = executeFn;
29789
29789
  }
29790
29790
  }
29791
- /**
29792
- * Internal bookkeeping for a pass within the render graph.
29793
- * @public
29791
+ /**
29792
+ * Internal bookkeeping for a pass within the render graph.
29793
+ * @public
29794
29794
  */ class RGPass {
29795
29795
  index;
29796
29796
  name;
@@ -30706,50 +30706,50 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
30706
30706
  }
30707
30707
  }
30708
30708
 
30709
- /**
30710
- * Manages cross-frame history resources that can be imported into a render graph.
30711
- *
30712
- * History resources are textures that persist across frames for temporal effects
30713
- * like TAA, motion blur, or temporal upscaling. Previous-frame textures can be
30714
- * imported into a {@link RenderGraph}, and current-frame textures are committed
30715
- * only after graph execution succeeds.
30716
- *
30717
- * Usage:
30718
- * ```ts
30719
- * const historyMgr = new HistoryResourceManager(allocator);
30720
- * historyMgr.beginFrame();
30721
- * const prev = historyMgr.importPrevious(graph, 'taaColor');
30722
- * // declare builder.read(prev) if non-null
30723
- * historyMgr.bindImportedTextures(executor);
30724
- * // after successful execution:
30725
- * historyMgr.commitFrame();
30726
- * ```
30727
- *
30728
- * @typeParam TTexture - The concrete texture type (e.g. `Texture2D`).
30729
- * @public
30709
+ /**
30710
+ * Manages cross-frame history resources that can be imported into a render graph.
30711
+ *
30712
+ * History resources are textures that persist across frames for temporal effects
30713
+ * like TAA, motion blur, or temporal upscaling. Previous-frame textures can be
30714
+ * imported into a {@link RenderGraph}, and current-frame textures are committed
30715
+ * only after graph execution succeeds.
30716
+ *
30717
+ * Usage:
30718
+ * ```ts
30719
+ * const historyMgr = new HistoryResourceManager(allocator);
30720
+ * historyMgr.beginFrame();
30721
+ * const prev = historyMgr.importPrevious(graph, 'taaColor');
30722
+ * // declare builder.read(prev) if non-null
30723
+ * historyMgr.bindImportedTextures(executor);
30724
+ * // after successful execution:
30725
+ * historyMgr.commitFrame();
30726
+ * ```
30727
+ *
30728
+ * @typeParam TTexture - The concrete texture type (e.g. `Texture2D`).
30729
+ * @public
30730
30730
  */ class HistoryResourceManager {
30731
30731
  _resources = new Map();
30732
30732
  _allocator;
30733
30733
  _pendingImports = new Map();
30734
30734
  _pendingCommits = new Map();
30735
30735
  _readScopeStack = [];
30736
- /**
30737
- * Create a new history resource manager.
30738
- *
30739
- * @param allocator - Texture allocator for creating history textures.
30736
+ /**
30737
+ * Create a new history resource manager.
30738
+ *
30739
+ * @param allocator - Texture allocator for creating history textures.
30740
30740
  */ constructor(allocator){
30741
30741
  this._allocator = allocator;
30742
30742
  }
30743
- /**
30744
- * Get the previous-frame texture resolved by the current render graph pass.
30745
- *
30746
- * The resource must have been imported with {@link HistoryResourceManager.importPrevious} or
30747
- * {@link HistoryResourceManager.importPreviousIfCompatible}, declared as a pass read, and bound with
30748
- * {@link HistoryResourceManager.beginReadScope} before this method is called.
30749
- *
30750
- * @param name - Name of the history resource.
30751
- * @returns The graph-resolved previous-frame texture.
30752
- * @throws If no read scope is active for the resource.
30743
+ /**
30744
+ * Get the previous-frame texture resolved by the current render graph pass.
30745
+ *
30746
+ * The resource must have been imported with {@link HistoryResourceManager.importPrevious} or
30747
+ * {@link HistoryResourceManager.importPreviousIfCompatible}, declared as a pass read, and bound with
30748
+ * {@link HistoryResourceManager.beginReadScope} before this method is called.
30749
+ *
30750
+ * @param name - Name of the history resource.
30751
+ * @returns The graph-resolved previous-frame texture.
30752
+ * @throws If no read scope is active for the resource.
30753
30753
  */ getPrevious(name) {
30754
30754
  const scoped = this._getScopedRead(name);
30755
30755
  if (scoped) {
@@ -30757,32 +30757,32 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
30757
30757
  }
30758
30758
  throw new Error(`History resource '${name}' is not available in the current render graph read scope. ` + `Import it and declare a pass read before accessing it.`);
30759
30759
  }
30760
- /**
30761
- * Check whether a valid history resource exists and matches the descriptor.
30762
- *
30763
- * @param name - Name of the history resource.
30764
- * @param desc - Expected texture descriptor.
30765
- * @param size - Expected resolved size.
30766
- * @returns True if the resource exists, is valid, and matches.
30760
+ /**
30761
+ * Check whether a valid history resource exists and matches the descriptor.
30762
+ *
30763
+ * @param name - Name of the history resource.
30764
+ * @param desc - Expected texture descriptor.
30765
+ * @param size - Expected resolved size.
30766
+ * @returns True if the resource exists, is valid, and matches.
30767
30767
  */ isCompatible(name, desc, size) {
30768
30768
  const resource = this._resources.get(name);
30769
30769
  return !!resource?.valid && this._matches(resource, desc, size);
30770
30770
  }
30771
- /**
30772
- * Start collecting graph imports and deferred commits for a new frame.
30771
+ /**
30772
+ * Start collecting graph imports and deferred commits for a new frame.
30773
30773
  */ beginFrame() {
30774
30774
  this.discardFrame();
30775
30775
  this._pendingImports.clear();
30776
30776
  this._readScopeStack.length = 0;
30777
30777
  }
30778
- /**
30779
- * Import the latest committed texture for a history resource into the graph.
30780
- *
30781
- * Returns null when the resource has no valid previous frame.
30782
- *
30783
- * @param graph - Render graph to import into.
30784
- * @param name - History resource name.
30785
- * @returns Imported graph handle, or null when no valid previous texture exists.
30778
+ /**
30779
+ * Import the latest committed texture for a history resource into the graph.
30780
+ *
30781
+ * Returns null when the resource has no valid previous frame.
30782
+ *
30783
+ * @param graph - Render graph to import into.
30784
+ * @param name - History resource name.
30785
+ * @returns Imported graph handle, or null when no valid previous texture exists.
30786
30786
  */ importPrevious(graph, name) {
30787
30787
  const resource = this._resources.get(name);
30788
30788
  const texture = resource?.valid ? resource.textures[resource.currentIndex] : null;
@@ -30793,34 +30793,34 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
30793
30793
  this._pendingImports.set(handle, texture);
30794
30794
  return handle;
30795
30795
  }
30796
- /**
30797
- * Import the latest committed texture only when it matches the expected shape.
30798
- *
30799
- * This is the preferred API for effects that can declare their history reads
30800
- * while building the graph: incompatible history is treated as absent, so the
30801
- * pass does not declare stale reads after resize or format changes.
30802
- *
30803
- * @param graph - Render graph to import into.
30804
- * @param name - History resource name.
30805
- * @param desc - Expected texture descriptor.
30806
- * @param size - Expected resolved size.
30807
- * @returns Imported graph handle, or null when no compatible history exists.
30796
+ /**
30797
+ * Import the latest committed texture only when it matches the expected shape.
30798
+ *
30799
+ * This is the preferred API for effects that can declare their history reads
30800
+ * while building the graph: incompatible history is treated as absent, so the
30801
+ * pass does not declare stale reads after resize or format changes.
30802
+ *
30803
+ * @param graph - Render graph to import into.
30804
+ * @param name - History resource name.
30805
+ * @param desc - Expected texture descriptor.
30806
+ * @param size - Expected resolved size.
30807
+ * @returns Imported graph handle, or null when no compatible history exists.
30808
30808
  */ importPreviousIfCompatible(graph, name, desc, size) {
30809
30809
  return this.isCompatible(name, desc, size) ? this.importPrevious(graph, name) : null;
30810
30810
  }
30811
- /**
30812
- * Bind all history imports created for this frame to the executor.
30813
- *
30814
- * @param executor - Render graph executor for the current frame.
30811
+ /**
30812
+ * Bind all history imports created for this frame to the executor.
30813
+ *
30814
+ * @param executor - Render graph executor for the current frame.
30815
30815
  */ bindImportedTextures(executor) {
30816
30816
  for (const [handle, texture] of this._pendingImports){
30817
30817
  executor.setImportedTexture(handle, texture);
30818
30818
  }
30819
30819
  }
30820
- /**
30821
- * Make resolved history textures available to code executing inside a pass.
30822
- *
30823
- * @param bindings - History name to resolved texture bindings.
30820
+ /**
30821
+ * Make resolved history textures available to code executing inside a pass.
30822
+ *
30823
+ * @param bindings - History name to resolved texture bindings.
30824
30824
  */ beginReadScope(bindings) {
30825
30825
  const scope = new Map();
30826
30826
  for (const binding of bindings){
@@ -30828,22 +30828,22 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
30828
30828
  }
30829
30829
  this._readScopeStack.push(scope);
30830
30830
  }
30831
- /**
30832
- * End the most recent history read scope.
30831
+ /**
30832
+ * End the most recent history read scope.
30833
30833
  */ endReadScope() {
30834
30834
  this._readScopeStack.pop();
30835
30835
  }
30836
- /**
30837
- * Queue a current-frame texture to become the next previous-frame history.
30838
- *
30839
- * The texture is committed only when {@link HistoryResourceManager.commitFrame} is called. If the
30840
- * frame fails, {@link HistoryResourceManager.discardFrame} releases owned pending textures instead.
30841
- *
30842
- * @param name - History resource name.
30843
- * @param desc - Texture descriptor.
30844
- * @param size - Resolved texture size.
30845
- * @param texture - Texture produced by the current frame.
30846
- * @param ownsTexture - Whether this manager should release the texture later.
30836
+ /**
30837
+ * Queue a current-frame texture to become the next previous-frame history.
30838
+ *
30839
+ * The texture is committed only when {@link HistoryResourceManager.commitFrame} is called. If the
30840
+ * frame fails, {@link HistoryResourceManager.discardFrame} releases owned pending textures instead.
30841
+ *
30842
+ * @param name - History resource name.
30843
+ * @param desc - Texture descriptor.
30844
+ * @param size - Resolved texture size.
30845
+ * @param texture - Texture produced by the current frame.
30846
+ * @param ownsTexture - Whether this manager should release the texture later.
30847
30847
  */ queueCommit(name, desc, size, texture, ownsTexture = true) {
30848
30848
  const existing = this._pendingCommits.get(name);
30849
30849
  if (existing?.ownsTexture) {
@@ -30860,8 +30860,8 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
30860
30860
  ownsTexture
30861
30861
  });
30862
30862
  }
30863
- /**
30864
- * Commit all current-frame history writes.
30863
+ /**
30864
+ * Commit all current-frame history writes.
30865
30865
  */ commitFrame() {
30866
30866
  for (const [name, pending] of this._pendingCommits){
30867
30867
  let resource = this._resources.get(name);
@@ -30908,8 +30908,8 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
30908
30908
  this._pendingImports.clear();
30909
30909
  this._readScopeStack.length = 0;
30910
30910
  }
30911
- /**
30912
- * Discard all uncommitted frame history writes.
30911
+ /**
30912
+ * Discard all uncommitted frame history writes.
30913
30913
  */ discardFrame() {
30914
30914
  for (const pending of this._pendingCommits.values()){
30915
30915
  if (pending.ownsTexture) {
@@ -30920,10 +30920,10 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
30920
30920
  this._pendingImports.clear();
30921
30921
  this._readScopeStack.length = 0;
30922
30922
  }
30923
- /**
30924
- * Release all history resources and clear the manager.
30925
- *
30926
- * Call this when disposing the render context or when history is no longer needed.
30923
+ /**
30924
+ * Release all history resources and clear the manager.
30925
+ *
30926
+ * Call this when disposing the render context or when history is no longer needed.
30927
30927
  */ dispose() {
30928
30928
  this.discardFrame();
30929
30929
  for (const resource of this._resources.values()){
@@ -30962,9 +30962,9 @@ function buildHiZ(sourceTex, HiZFrameBuffer) {
30962
30962
  }
30963
30963
  }
30964
30964
 
30965
- /**
30966
- * Resource names for render graph history resources.
30967
- * @public
30965
+ /**
30966
+ * Resource names for render graph history resources.
30967
+ * @public
30968
30968
  */ const RGHistoryResources = {
30969
30969
  TAA_COLOR: 'taaColor',
30970
30970
  TAA_MOTION_VECTOR: 'taaMotionVector'
@@ -36978,24 +36978,24 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
36978
36978
  }
36979
36979
  }
36980
36980
 
36981
- /**
36982
- * A renderable camera node that manages view/projection math, frusta,
36983
- * input control, picking, and a post-processing chain via a compositor.
36984
- *
36985
- * Key features:
36986
- * - Maintains projection, view, VP, and inverse VP matrices and lazily recomputes them when invalidated.
36987
- * - Provides world- and view-space frusta for culling and clipping.
36988
- * - Supports perspective and orthographic projections.
36989
- * - Integrates with post effects (Tonemap, FXAA, TAA, Bloom, SSR, SSAO, Motion Blur) through an internal `Compositor`.
36990
- * - Handles temporal jitter and history state when TAA or motion blur are enabled.
36991
- * - Emits picking rays from screen coordinates and supports async GPU picking.
36992
- * - Optional controller integration for user input handling.
36993
- *
36994
- * Performance notes:
36995
- * - Matrices/frusta are computed on demand and cached until invalidation.
36996
- * - Temporal jitter and history are set up only when required by enabled features and device support.
36997
- *
36998
- * @public
36981
+ /**
36982
+ * A renderable camera node that manages view/projection math, frusta,
36983
+ * input control, picking, and a post-processing chain via a compositor.
36984
+ *
36985
+ * Key features:
36986
+ * - Maintains projection, view, VP, and inverse VP matrices and lazily recomputes them when invalidated.
36987
+ * - Provides world- and view-space frusta for culling and clipping.
36988
+ * - Supports perspective and orthographic projections.
36989
+ * - Integrates with post effects (Tonemap, FXAA, TAA, Bloom, SSR, SSAO, Motion Blur) through an internal `Compositor`.
36990
+ * - Handles temporal jitter and history state when TAA or motion blur are enabled.
36991
+ * - Emits picking rays from screen coordinates and supports async GPU picking.
36992
+ * - Optional controller integration for user input handling.
36993
+ *
36994
+ * Performance notes:
36995
+ * - Matrices/frusta are computed on demand and cached until invalidation.
36996
+ * - Temporal jitter and history are set up only when required by enabled features and device support.
36997
+ *
36998
+ * @public
36999
36999
  */ class Camera extends SceneNode {
37000
37000
  /** @internal Halton 2-3 sequence used for TAA jittering. */ static _halton23 = halton23(16);
37001
37001
  /** @internal Per-camera history resource manager. */ static _historyResourceManager = new WeakMap();
@@ -37084,14 +37084,14 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37084
37084
  /** @internal Post-processing compositor attached to this camera. */ _compositor;
37085
37085
  /** @internal Pointer interaction rectangle in css pixels (relative to canvas) */ _interactionRect;
37086
37086
  /** @internal captured by which mouse button (-1 if not captured) */ _capturedButton;
37087
- /**
37088
- * Creates a new camera node.
37089
- *
37090
- * Initializes projection/view matrices, temporal fields, controller linkage, and
37091
- * builds the default post-processing pipeline on the internal compositor.
37092
- *
37093
- * @param scene - The scene that owns this camera.
37094
- * @param projectionMatrix - Optional projection matrix to initialize with.
37087
+ /**
37088
+ * Creates a new camera node.
37089
+ *
37090
+ * Initializes projection/view matrices, temporal fields, controller linkage, and
37091
+ * builds the default post-processing pipeline on the internal compositor.
37092
+ *
37093
+ * @param scene - The scene that owns this camera.
37094
+ * @param projectionMatrix - Optional projection matrix to initialize with.
37095
37095
  */ constructor(scene, projectionMatrix){
37096
37096
  super(scene);
37097
37097
  this._projMatrix = projectionMatrix || Matrix4x4.identity();
@@ -37184,73 +37184,73 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37184
37184
  scene.mainCamera = this;
37185
37185
  }
37186
37186
  }
37187
- /**
37188
- * The compositor that owns and runs the camera's post-processing chain.
37187
+ /**
37188
+ * The compositor that owns and runs the camera's post-processing chain.
37189
37189
  */ get compositor() {
37190
37190
  return this._compositor;
37191
37191
  }
37192
- /**
37193
- * Pointer interaction rectangle in css pixels (relative to canvas)
37192
+ /**
37193
+ * Pointer interaction rectangle in css pixels (relative to canvas)
37194
37194
  */ get interactionRect() {
37195
37195
  return this._interactionRect;
37196
37196
  }
37197
37197
  set interactionRect(rect) {
37198
37198
  this._interactionRect = rect;
37199
37199
  }
37200
- /**
37201
- * Framebuffer clear color, or `null` to disable.
37200
+ /**
37201
+ * Framebuffer clear color, or `null` to disable.
37202
37202
  */ get clearColor() {
37203
37203
  return this._clearColor;
37204
37204
  }
37205
37205
  set clearColor(v) {
37206
37206
  this._clearColor = v?.clone() ?? null;
37207
37207
  }
37208
- /**
37209
- * Framebuffer stencil clear value, disabled when null. Default is 0.
37208
+ /**
37209
+ * Framebuffer stencil clear value, disabled when null. Default is 0.
37210
37210
  */ get clearDepth() {
37211
37211
  return this._clearDepth;
37212
37212
  }
37213
37213
  set clearDepth(v) {
37214
37214
  this._clearDepth = v;
37215
37215
  }
37216
- /**
37217
- * Framebuffer stencil clear value, disabled when null. Default is 0.
37216
+ /**
37217
+ * Framebuffer stencil clear value, disabled when null. Default is 0.
37218
37218
  */ get clearStencil() {
37219
37219
  return this._clearStencil;
37220
37220
  }
37221
37221
  set clearStencil(v) {
37222
37222
  this._clearStencil = v;
37223
37223
  }
37224
- /**
37225
- * Whether Hi-Z acceleration is enabled.
37226
- *
37227
- * Often improves SSR performance with little quality impact when supported.
37224
+ /**
37225
+ * Whether Hi-Z acceleration is enabled.
37226
+ *
37227
+ * Often improves SSR performance with little quality impact when supported.
37228
37228
  */ get HiZ() {
37229
37229
  return this._HiZ;
37230
37230
  }
37231
37231
  set HiZ(val) {
37232
37232
  this._HiZ = !!val;
37233
37233
  }
37234
- /**
37235
- * Whether HDR backbuffer is enabled.
37236
- *
37237
- * Tonemap should be disabled when not using HDR backbuffer.
37234
+ /**
37235
+ * Whether HDR backbuffer is enabled.
37236
+ *
37237
+ * Tonemap should be disabled when not using HDR backbuffer.
37238
37238
  */ get HDR() {
37239
37239
  return this._HDR;
37240
37240
  }
37241
37241
  set HDR(val) {
37242
37242
  this._HDR = !!val;
37243
37243
  }
37244
- /**
37245
- * Whether tonemapping is enabled via the post effect.
37244
+ /**
37245
+ * Whether tonemapping is enabled via the post effect.
37246
37246
  */ get toneMap() {
37247
37247
  return this._postEffectTonemap.get().enabled;
37248
37248
  }
37249
37249
  set toneMap(val) {
37250
37250
  this._postEffectTonemap.get().enabled = !!val;
37251
37251
  }
37252
- /**
37253
- * Whether motion blur is enabled via the post effect.
37252
+ /**
37253
+ * Whether motion blur is enabled via the post effect.
37254
37254
  */ get motionBlur() {
37255
37255
  return this._postEffectMotionBlur.get().enabled;
37256
37256
  }
@@ -37266,16 +37266,16 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37266
37266
  this._postEffectMotionBlur.get().strength = this._motionBlurStrength;
37267
37267
  }
37268
37268
  }
37269
- /**
37270
- * Gets whether Bloom is enabled.
37269
+ /**
37270
+ * Gets whether Bloom is enabled.
37271
37271
  */ get bloom() {
37272
37272
  return this._postEffectBloom.get().enabled;
37273
37273
  }
37274
37274
  set bloom(val) {
37275
37275
  this._postEffectBloom.get().enabled = !!val;
37276
37276
  }
37277
- /**
37278
- * Maximum bloom downsample levels
37277
+ /**
37278
+ * Maximum bloom downsample levels
37279
37279
  */ get bloomMaxDownsampleLevels() {
37280
37280
  return this._bloomMaxDownsampleLevels;
37281
37281
  }
@@ -37285,8 +37285,8 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37285
37285
  this._postEffectBloom.get().maxDownsampleLevel = val;
37286
37286
  }
37287
37287
  }
37288
- /**
37289
- * Bloom downsample limit
37288
+ /**
37289
+ * Bloom downsample limit
37290
37290
  */ get bloomDownsampleLimit() {
37291
37291
  return this._bloomDownsampleLimit;
37292
37292
  }
@@ -37296,8 +37296,8 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37296
37296
  this._postEffectBloom.get().downsampleLimit = val;
37297
37297
  }
37298
37298
  }
37299
- /**
37300
- * Bloom threshold
37299
+ /**
37300
+ * Bloom threshold
37301
37301
  */ get bloomThreshold() {
37302
37302
  return this._bloomThreshold;
37303
37303
  }
@@ -37307,8 +37307,8 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37307
37307
  this._postEffectBloom.get().threshold = val;
37308
37308
  }
37309
37309
  }
37310
- /**
37311
- * Bloom threshold knee
37310
+ /**
37311
+ * Bloom threshold knee
37312
37312
  */ get bloomThresholdKnee() {
37313
37313
  return this._bloomThresholdKnee;
37314
37314
  }
@@ -37318,8 +37318,8 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37318
37318
  this._postEffectBloom.get().thresholdKnee = val;
37319
37319
  }
37320
37320
  }
37321
- /**
37322
- * Bloom intensity
37321
+ /**
37322
+ * Bloom intensity
37323
37323
  */ get bloomIntensity() {
37324
37324
  return this._bloomIntensity;
37325
37325
  }
@@ -37371,16 +37371,16 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37371
37371
  this._postEffectColorAdjust.get().sharpen = val;
37372
37372
  }
37373
37373
  }
37374
- /**
37375
- * Gets whether FXAA is enabled.
37374
+ /**
37375
+ * Gets whether FXAA is enabled.
37376
37376
  */ get FXAA() {
37377
37377
  return this._postEffectFXAA.get().enabled;
37378
37378
  }
37379
37379
  set FXAA(val) {
37380
37380
  this._postEffectFXAA.get().enabled = !!val;
37381
37381
  }
37382
- /**
37383
- * Tonemap exposure
37382
+ /**
37383
+ * Tonemap exposure
37384
37384
  */ get toneMapExposure() {
37385
37385
  return this._tonemapExposure;
37386
37386
  }
@@ -37390,123 +37390,123 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37390
37390
  this._postEffectTonemap.get().exposure = val;
37391
37391
  }
37392
37392
  }
37393
- /**
37394
- * Gets whether TAA is enabled.
37393
+ /**
37394
+ * Gets whether TAA is enabled.
37395
37395
  */ get TAA() {
37396
37396
  return this._postEffectTAA.get().enabled;
37397
37397
  }
37398
37398
  set TAA(val) {
37399
37399
  this._postEffectTAA.get().enabled = !!val;
37400
37400
  }
37401
- /**
37402
- * Gets the debug flag for TAA
37401
+ /**
37402
+ * Gets the debug flag for TAA
37403
37403
  */ get TAADebug() {
37404
37404
  return this._TAADebug;
37405
37405
  }
37406
37406
  set TAADebug(val) {
37407
37407
  this._TAADebug = val;
37408
37408
  }
37409
- /**
37410
- * Gets whether Screen Space Reflections (SSR) is enabled.
37409
+ /**
37410
+ * Gets whether Screen Space Reflections (SSR) is enabled.
37411
37411
  */ get SSR() {
37412
37412
  return this._postEffectSSR.get().enabled;
37413
37413
  }
37414
37414
  set SSR(val) {
37415
37415
  this._postEffectSSR.get().enabled = !!val;
37416
37416
  }
37417
- /**
37418
- * Gets the maximum roughness value for screen space reflections.
37419
- * Controls the cutoff point where surfaces are considered too rough for SSR.
37417
+ /**
37418
+ * Gets the maximum roughness value for screen space reflections.
37419
+ * Controls the cutoff point where surfaces are considered too rough for SSR.
37420
37420
  */ get ssrMaxRoughness() {
37421
37421
  return this._ssrMaxRoughness;
37422
37422
  }
37423
37423
  set ssrMaxRoughness(val) {
37424
37424
  this._ssrMaxRoughness = val;
37425
37425
  }
37426
- /**
37427
- * Gets the roughness factor for SSR calculations.
37428
- * Affects how surface roughness influences reflection clarity.
37426
+ /**
37427
+ * Gets the roughness factor for SSR calculations.
37428
+ * Affects how surface roughness influences reflection clarity.
37429
37429
  */ get ssrRoughnessFactor() {
37430
37430
  return this._ssrRoughnessFactor;
37431
37431
  }
37432
37432
  set ssrRoughnessFactor(val) {
37433
37433
  this._ssrRoughnessFactor = val;
37434
37434
  }
37435
- /**
37436
- * Gets the stride value for SSR ray marching.
37437
- * Controls the step size during ray marching. Larger values improve performance but may miss details.
37435
+ /**
37436
+ * Gets the stride value for SSR ray marching.
37437
+ * Controls the step size during ray marching. Larger values improve performance but may miss details.
37438
37438
  */ get ssrStride() {
37439
37439
  return this._ssrStride;
37440
37440
  }
37441
37441
  set ssrStride(val) {
37442
37442
  this._ssrStride = val;
37443
37443
  }
37444
- /**
37445
- * Gets the maximum distance for SSR ray marching.
37446
- * Defines how far rays will travel when searching for reflection intersections.
37444
+ /**
37445
+ * Gets the maximum distance for SSR ray marching.
37446
+ * Defines how far rays will travel when searching for reflection intersections.
37447
37447
  */ get ssrMaxDistance() {
37448
37448
  return this._ssrParams.x;
37449
37449
  }
37450
37450
  set ssrMaxDistance(val) {
37451
37451
  this._ssrParams.x = val;
37452
37452
  }
37453
- /**
37454
- * Gets the number of iterations for SSR ray marching.
37455
- * Higher values provide more accurate reflections but impact performance.
37453
+ /**
37454
+ * Gets the number of iterations for SSR ray marching.
37455
+ * Higher values provide more accurate reflections but impact performance.
37456
37456
  */ get ssrIterations() {
37457
37457
  return this._ssrParams.y;
37458
37458
  }
37459
37459
  set ssrIterations(val) {
37460
37460
  this._ssrParams.y = val;
37461
37461
  }
37462
- /**
37463
- * Gets the thickness value for SSR calculations.
37464
- * Determines the thickness threshold for surfaces when calculating reflections.
37462
+ /**
37463
+ * Gets the thickness value for SSR calculations.
37464
+ * Determines the thickness threshold for surfaces when calculating reflections.
37465
37465
  */ get ssrThickness() {
37466
37466
  return this._ssrParams.z;
37467
37467
  }
37468
37468
  set ssrThickness(val) {
37469
37469
  this._ssrParams.z = val;
37470
37470
  }
37471
- /**
37472
- * Gets whether SSR should calculate thickness automatically.
37473
- * When enabled, the system will dynamically compute surface thickness for reflections.
37471
+ /**
37472
+ * Gets whether SSR should calculate thickness automatically.
37473
+ * When enabled, the system will dynamically compute surface thickness for reflections.
37474
37474
  */ get ssrCalcThickness() {
37475
37475
  return this._ssrCalcThickness;
37476
37476
  }
37477
37477
  set ssrCalcThickness(val) {
37478
37478
  this._ssrCalcThickness = !!val;
37479
37479
  }
37480
- /**
37481
- * Gets the blur scale factor for SSR.
37482
- * Controls the overall intensity of the blur effect applied to reflections.
37480
+ /**
37481
+ * Gets the blur scale factor for SSR.
37482
+ * Controls the overall intensity of the blur effect applied to reflections.
37483
37483
  */ get ssrBlurScale() {
37484
37484
  return this._ssrBlurriness;
37485
37485
  }
37486
37486
  set ssrBlurScale(val) {
37487
37487
  this._ssrBlurriness = val;
37488
37488
  }
37489
- /**
37490
- * Gets the depth cutoff value for SSR blur.
37491
- * Determines at what depth difference the blur effect should be reduced or eliminated.
37489
+ /**
37490
+ * Gets the depth cutoff value for SSR blur.
37491
+ * Determines at what depth difference the blur effect should be reduced or eliminated.
37492
37492
  */ get ssrBlurDepthCutoff() {
37493
37493
  return this._ssrBlurDepthCutoff;
37494
37494
  }
37495
37495
  set ssrBlurDepthCutoff(val) {
37496
37496
  this._ssrBlurDepthCutoff = val;
37497
37497
  }
37498
- /**
37499
- * Gets the kernel size for the SSR blur effect.
37500
- * Defines the size of the blur kernel. Larger values create softer, more spread-out blur.
37498
+ /**
37499
+ * Gets the kernel size for the SSR blur effect.
37500
+ * Defines the size of the blur kernel. Larger values create softer, more spread-out blur.
37501
37501
  */ get ssrBlurKernelSize() {
37502
37502
  return this._ssrBlurKernelSize;
37503
37503
  }
37504
37504
  set ssrBlurKernelSize(val) {
37505
37505
  this._ssrBlurKernelSize = val;
37506
37506
  }
37507
- /**
37508
- * Gets the standard deviation for the SSR Gaussian blur.
37509
- * Controls the distribution of the blur effect. Higher values create more pronounced blur.
37507
+ /**
37508
+ * Gets the standard deviation for the SSR Gaussian blur.
37509
+ * Controls the distribution of the blur effect. Higher values create more pronounced blur.
37510
37510
  */ get ssrBlurStdDev() {
37511
37511
  return this._ssrBlurStdDev;
37512
37512
  }
@@ -37516,8 +37516,8 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37516
37516
  /** @internal */ get ssrParams() {
37517
37517
  return this._ssrParams;
37518
37518
  }
37519
- /**
37520
- * Gets whether SSAO is enabled.
37519
+ /**
37520
+ * Gets whether SSAO is enabled.
37521
37521
  */ get SSAO() {
37522
37522
  return this._postEffectSSAO.get().enabled;
37523
37523
  }
@@ -37657,27 +37657,27 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37657
37657
  }
37658
37658
  return this._viewport;
37659
37659
  }
37660
- /**
37661
- * Screen configuration used for adapting the camera viewport
37660
+ /**
37661
+ * Screen configuration used for adapting the camera viewport
37662
37662
  */ get screenConfig() {
37663
37663
  return this._screenAdapter.config;
37664
37664
  }
37665
37665
  set screenConfig(config) {
37666
37666
  this._screenAdapter.config = config;
37667
37667
  }
37668
- /**
37669
- * Screen viewport used for adapting the camera viewport
37668
+ /**
37669
+ * Screen viewport used for adapting the camera viewport
37670
37670
  */ get screenViewport() {
37671
37671
  return this._screenAdapter.viewport;
37672
37672
  }
37673
37673
  set screenViewport(viewport) {
37674
37674
  this._screenAdapter.viewport = viewport;
37675
37675
  }
37676
- /**
37677
- * Handle input events
37678
- * @param ev - input event object
37679
- * @param type - event type, default to ev.type
37680
- * @returns Boolean value indicates whether the event was handled.
37676
+ /**
37677
+ * Handle input events
37678
+ * @param ev - input event object
37679
+ * @param type - event type, default to ev.type
37680
+ * @returns Boolean value indicates whether the event was handled.
37681
37681
  */ handleEvent(ev, type) {
37682
37682
  let handled = false;
37683
37683
  if (this._controller) {
@@ -37710,14 +37710,14 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37710
37710
  }
37711
37711
  return handled;
37712
37712
  }
37713
- /**
37714
- * Constructs a ray based on the given screen coordinates.
37715
- *
37716
- * @param x - The x-component of the screen coordinates, relative to the top-left corner of the viewport.
37717
- * @param y - The y-component of the screen coordinates, relative to the top-left corner of the viewport.
37718
- * @param viewportWidth - Optional width of the viewport for normalizing screen coordinates. If not provided, it will be derived from the camera's viewport or the device's viewport.
37719
- * @param viewportHeight - Optional height of the viewport for normalizing screen coordinates. If not provided, it will be derived from the camera's viewport or the device's viewport.
37720
- * @returns The ray originating from the camera position and passing through the given screen coordinates.
37713
+ /**
37714
+ * Constructs a ray based on the given screen coordinates.
37715
+ *
37716
+ * @param x - The x-component of the screen coordinates, relative to the top-left corner of the viewport.
37717
+ * @param y - The y-component of the screen coordinates, relative to the top-left corner of the viewport.
37718
+ * @param viewportWidth - Optional width of the viewport for normalizing screen coordinates. If not provided, it will be derived from the camera's viewport or the device's viewport.
37719
+ * @param viewportHeight - Optional height of the viewport for normalizing screen coordinates. If not provided, it will be derived from the camera's viewport or the device's viewport.
37720
+ * @returns The ray originating from the camera position and passing through the given screen coordinates.
37721
37721
  */ constructRay(x, y, viewportWidth, viewportHeight) {
37722
37722
  const width = viewportWidth ?? (this.viewport ? this.viewport[2] : getDevice().getViewport().width);
37723
37723
  const height = viewportHeight ?? (this.viewport ? this.viewport[3] : getDevice().getViewport().height);
@@ -37735,54 +37735,54 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37735
37735
  const vDir = Vector3.sub(farWorld.xyz(), vEye).inplaceNormalize();
37736
37736
  return new Ray(vEye, vDir);
37737
37737
  }
37738
- /**
37739
- * Place the camera by specifying the camera position and the target point
37740
- * @param eye - The camera position
37741
- * @param target - The target point to look at
37742
- * @param up - The up vector
37743
- * @returns self
37738
+ /**
37739
+ * Place the camera by specifying the camera position and the target point
37740
+ * @param eye - The camera position
37741
+ * @param target - The target point to look at
37742
+ * @param up - The up vector
37743
+ * @returns self
37744
37744
  */ lookAt(eye, target, up) {
37745
37745
  return this.setLocalTransform(Matrix4x4.lookAt(eye, target, up));
37746
37746
  }
37747
- /**
37748
- * Place the camera to look at a given cube face at a given camera position
37749
- * @param face - The cube face to look at
37750
- * @param position - The camera position
37751
- * @returns self
37747
+ /**
37748
+ * Place the camera to look at a given cube face at a given camera position
37749
+ * @param face - The cube face to look at
37750
+ * @param position - The camera position
37751
+ * @returns self
37752
37752
  */ lookAtCubeFace(face, position) {
37753
37753
  return this.setLocalTransform(Matrix4x4.lookAtCubeFace(face, position ?? this.position));
37754
37754
  }
37755
- /**
37756
- * Setup a perspective projection matrix for the camera
37757
- * @param fovY - The vertical field of view in radians.
37758
- * @param aspect - The aspect ratio
37759
- * @param zNear - The near clip plane
37760
- * @param zFar - The far clip plane
37761
- * @returns self
37755
+ /**
37756
+ * Setup a perspective projection matrix for the camera
37757
+ * @param fovY - The vertical field of view in radians.
37758
+ * @param aspect - The aspect ratio
37759
+ * @param zNear - The near clip plane
37760
+ * @param zFar - The far clip plane
37761
+ * @returns self
37762
37762
  */ setPerspective(fovY, aspect, zNear, zFar) {
37763
37763
  this._projMatrix.perspective(fovY, aspect, zNear, zFar);
37764
37764
  Matrix4x4.invert(this._projMatrix, this._invProjMatrix);
37765
37765
  this._invalidate(true);
37766
37766
  return this;
37767
37767
  }
37768
- /**
37769
- * Setup a orthogonal projection matrix for the camera
37770
- * @param left - Left bound of the frustum
37771
- * @param right - Right bound of the frustum
37772
- * @param bottom - Bottom bound of the frustum
37773
- * @param top - Top bound of the frustum
37774
- * @param near - Near bound of the frustum.
37775
- * @param far - Far bound of the frustum.
37776
- * @returns self
37768
+ /**
37769
+ * Setup a orthogonal projection matrix for the camera
37770
+ * @param left - Left bound of the frustum
37771
+ * @param right - Right bound of the frustum
37772
+ * @param bottom - Bottom bound of the frustum
37773
+ * @param top - Top bound of the frustum
37774
+ * @param near - Near bound of the frustum.
37775
+ * @param far - Far bound of the frustum.
37776
+ * @returns self
37777
37777
  */ setOrtho(left, right, bottom, top, near, far) {
37778
37778
  this._projMatrix.ortho(left, right, bottom, top, near, far);
37779
37779
  Matrix4x4.invert(this._projMatrix, this._invProjMatrix);
37780
37780
  this._invalidate(true);
37781
37781
  return this;
37782
37782
  }
37783
- /**
37784
- * Setup a projection matrix for the camera
37785
- * @param matrix - The projection matrix
37783
+ /**
37784
+ * Setup a projection matrix for the camera
37785
+ * @param matrix - The projection matrix
37786
37786
  */ setProjectionMatrix(matrix) {
37787
37787
  if (matrix && matrix !== this._projMatrix) {
37788
37788
  this._projMatrix = matrix;
@@ -37790,18 +37790,18 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37790
37790
  this._invalidate(true);
37791
37791
  }
37792
37792
  }
37793
- /**
37794
- * Gets the projection matrix of the camera
37795
- * @returns The projection matrix
37793
+ /**
37794
+ * Gets the projection matrix of the camera
37795
+ * @returns The projection matrix
37796
37796
  */ getProjectionMatrix() {
37797
37797
  if (this.dirtyCheck()) {
37798
37798
  this._compute();
37799
37799
  }
37800
37800
  return this._projMatrix;
37801
37801
  }
37802
- /**
37803
- * Gets the inverse projection matrix of the camera
37804
- * @returns The projection matrix
37802
+ /**
37803
+ * Gets the inverse projection matrix of the camera
37804
+ * @returns The projection matrix
37805
37805
  */ getInvProjectionMatrix() {
37806
37806
  if (this.dirtyCheck()) {
37807
37807
  this._compute();
@@ -37819,11 +37819,11 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37819
37819
  rotationMatrix.setRow(2, new Vector4(zAxis.x, zAxis.y, zAxis.z, 0));
37820
37820
  return rotationMatrix;
37821
37821
  }
37822
- /**
37823
- * View matrix of the camera
37824
- *
37825
- * @remarks
37826
- * Camera's view matrix will transform a point from the world space to the camera space
37822
+ /**
37823
+ * View matrix of the camera
37824
+ *
37825
+ * @remarks
37826
+ * Camera's view matrix will transform a point from the world space to the camera space
37827
37827
  */ get viewMatrix() {
37828
37828
  if (this.dirtyCheck()) {
37829
37829
  this._compute();
@@ -37836,11 +37836,11 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37836
37836
  }
37837
37837
  return this._viewProjMatrix;
37838
37838
  }
37839
- /**
37840
- * The inverse-view-projection matrix of the camera
37841
- *
37842
- * @remarks
37843
- * The inverse-view-projection matrix transforms a point from the clip space to the camera space
37839
+ /**
37840
+ * The inverse-view-projection matrix of the camera
37841
+ *
37842
+ * @remarks
37843
+ * The inverse-view-projection matrix transforms a point from the clip space to the camera space
37844
37844
  */ get invViewProjectionMatrix() {
37845
37845
  if (this.dirtyCheck()) {
37846
37846
  this._compute();
@@ -37892,9 +37892,9 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37892
37892
  /** Returns true if the camera is orthographic */ isOrtho() {
37893
37893
  return this.getProjectionMatrix().isOrtho();
37894
37894
  }
37895
- /**
37896
- * Gets the camera history resource manager for temporal effects
37897
- * @returns History resource manager
37895
+ /**
37896
+ * Gets the camera history resource manager for temporal effects
37897
+ * @returns History resource manager
37898
37898
  */ getHistoryResourceManager() {
37899
37899
  let manager = Camera._historyResourceManager.get(this);
37900
37900
  if (!manager) {
@@ -37904,14 +37904,14 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37904
37904
  }
37905
37905
  return manager;
37906
37906
  }
37907
- /**
37908
- * Sets the camera history resource manager for temporal effects
37909
- * @internal
37907
+ /**
37908
+ * Sets the camera history resource manager for temporal effects
37909
+ * @internal
37910
37910
  */ setHistoryResourceManager(manager) {
37911
37911
  Camera._historyResourceManager.set(this, manager);
37912
37912
  }
37913
- /**
37914
- * Clears the camera history data which is used in temporal reprojection
37913
+ /**
37914
+ * Clears the camera history data which is used in temporal reprojection
37915
37915
  */ clearHistoryData() {
37916
37916
  // Clear history resource manager
37917
37917
  const manager = Camera._historyResourceManager.get(this);
@@ -37991,10 +37991,10 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
37991
37991
  this._compositor.appendPostEffect(bloom);
37992
37992
  }
37993
37993
  }
37994
- /**
37995
- * Renders a scene
37996
- * @param scene - The scene to be rendered
37997
- * @param compositor - Compositor instance that will be used to apply postprocess effects
37994
+ /**
37995
+ * Renders a scene
37996
+ * @param scene - The scene to be rendered
37997
+ * @param compositor - Compositor instance that will be used to apply postprocess effects
37998
37998
  */ render(scene) {
37999
37999
  const device = getDevice();
38000
38000
  //this.updatePostProcessing(device);
@@ -38068,13 +38068,13 @@ class DepthLimitAOBlurBlitter extends BilateralBlurBlitter {
38068
38068
  /** @internal */ getPickPosY() {
38069
38069
  return this._pickPosY;
38070
38070
  }
38071
- /**
38072
- * Updates the controller state
38071
+ /**
38072
+ * Updates the controller state
38073
38073
  */ updateController() {
38074
38074
  this._controller?.update();
38075
38075
  }
38076
- /**
38077
- * Reset the controller
38076
+ /**
38077
+ * Reset the controller
38078
38078
  */ resetController() {
38079
38079
  this._controller?.reset();
38080
38080
  }
@@ -54516,16 +54516,16 @@ function isBoneFixed(roots, index) {
54516
54516
  }
54517
54517
 
54518
54518
  // High-level orchestrator - SPCRJointDynamicsController API
54519
- /**
54520
- * High-level controller for joint dynamics simulation.
54521
- *
54522
- * This class manages the physics simulation for a hierarchy of bones, including constraints,
54523
- * colliders, and grabbers. It provides an API for initializing the system with bone data and
54524
- * transforms, stepping the simulation each frame, and modifying colliders and grabbers at runtime.
54525
- * The controller handles the internal state and logic for blending between animation and physics,
54526
- * applying forces, and enforcing constraints.
54527
- *
54528
- * @public
54519
+ /**
54520
+ * High-level controller for joint dynamics simulation.
54521
+ *
54522
+ * This class manages the physics simulation for a hierarchy of bones, including constraints,
54523
+ * colliders, and grabbers. It provides an API for initializing the system with bone data and
54524
+ * transforms, stepping the simulation each frame, and modifying colliders and grabbers at runtime.
54525
+ * The controller handles the internal state and logic for blending between animation and physics,
54526
+ * applying forces, and enforcing constraints.
54527
+ *
54528
+ * @public
54529
54529
  */ class JointDynamicsSystemController {
54530
54530
  _config;
54531
54531
  _pointsR = [];
@@ -54565,14 +54565,14 @@ function isBoneFixed(roots, index) {
54565
54565
  constructor(config){
54566
54566
  this._config = config;
54567
54567
  }
54568
- /**
54569
- * Initializes the physics system.
54570
- * @param rootTransform - Root bone transform used to detect root motion.
54571
- * @param rootPoints - Root nodes of the bone hierarchy. Multiple roots are allowed.
54572
- * @param pointTransforms - Transform array for all physics points. Order must match `BoneNode.index`.
54573
- * @param colliders - Collider array (spheres/capsules).
54574
- * @param grabbers - Grabber array used for interactions such as mouse dragging.
54575
- * @param flatPlanes - Plane limiters such as the floor to prevent penetration.
54568
+ /**
54569
+ * Initializes the physics system.
54570
+ * @param rootTransform - Root bone transform used to detect root motion.
54571
+ * @param rootPoints - Root nodes of the bone hierarchy. Multiple roots are allowed.
54572
+ * @param pointTransforms - Transform array for all physics points. Order must match `BoneNode.index`.
54573
+ * @param colliders - Collider array (spheres/capsules).
54574
+ * @param grabbers - Grabber array used for interactions such as mouse dragging.
54575
+ * @param flatPlanes - Plane limiters such as the floor to prevent penetration.
54576
54576
  */ initialize(rootTransform, rootPoints, pointTransforms, colliders, grabbers, flatPlanes) {
54577
54577
  this._rootTransform = rootTransform;
54578
54578
  this._pointTransforms = pointTransforms;
@@ -54662,11 +54662,11 @@ function isBoneFixed(roots, index) {
54662
54662
  }
54663
54663
  this._initialized = true;
54664
54664
  }
54665
- /**
54666
- * Advances the simulation by one frame.
54667
- * Internal flow: read current transforms, run Verlet integration and constraint solving,
54668
- * then write the result back to the transforms.
54669
- * @param deltaTime - Frame delta time in seconds. Internally subdivided by `subSteps`.
54665
+ /**
54666
+ * Advances the simulation by one frame.
54667
+ * Internal flow: read current transforms, run Verlet integration and constraint solving,
54668
+ * then write the result back to the transforms.
54669
+ * @param deltaTime - Frame delta time in seconds. Internally subdivided by `subSteps`.
54670
54670
  */ step(deltaTime) {
54671
54671
  if (!this._initialized || !this._rootTransform) {
54672
54672
  return;
@@ -54741,10 +54741,10 @@ function isBoneFixed(roots, index) {
54741
54741
  this._previousRootPosition = rootPos;
54742
54742
  this._previousRootRotation = rootRot;
54743
54743
  }
54744
- /**
54745
- * Returns the simulated results for all points as world-space positions and rotations.
54746
- * Usually this does not need to be called manually because `step()` already writes the
54747
- * output back to the transforms.
54744
+ /**
54745
+ * Returns the simulated results for all points as world-space positions and rotations.
54746
+ * Usually this does not need to be called manually because `step()` already writes the
54747
+ * output back to the transforms.
54748
54748
  */ getResults() {
54749
54749
  const transformRots = this._pointTransforms.map((t)=>t.getWorldRotation());
54750
54750
  const transformLocalRots = this._pointTransforms.map((t)=>t.getLocalRotation());
@@ -54754,10 +54754,10 @@ function isBoneFixed(roots, index) {
54754
54754
  rotation: o.rotation
54755
54755
  }));
54756
54756
  }
54757
- /**
54758
- * Compensates for teleportation by resetting the previous root transform to the current one.
54759
- * Call this after a character warp or teleport to avoid a large root-motion impulse on the
54760
- * next simulation step.
54757
+ /**
54758
+ * Compensates for teleportation by resetting the previous root transform to the current one.
54759
+ * Call this after a character warp or teleport to avoid a large root-motion impulse on the
54760
+ * next simulation step.
54761
54761
  */ warp() {
54762
54762
  if (!this._rootTransform) {
54763
54763
  return;
@@ -54765,10 +54765,10 @@ function isBoneFixed(roots, index) {
54765
54765
  this._previousRootPosition = this._rootTransform.getWorldPosition();
54766
54766
  this._previousRootRotation = this._rootTransform.getWorldRotation();
54767
54767
  }
54768
- /**
54769
- * Resets all physics state.
54770
- * Each simulated point is snapped back to the current transform position and grab state
54771
- * is cleared.
54768
+ /**
54769
+ * Resets all physics state.
54770
+ * Each simulated point is snapped back to the current transform position and grab state
54771
+ * is cleared.
54772
54772
  */ reset() {
54773
54773
  for(let i = 0; i < this._pointsRW.length; i++){
54774
54774
  const pos = this._pointTransforms[i].getWorldPosition();
@@ -54778,10 +54778,10 @@ function isBoneFixed(roots, index) {
54778
54778
  }
54779
54779
  this._fakeWaveCounter = 0;
54780
54780
  }
54781
- /**
54782
- * Releases a fixed point so it becomes dynamic, for example when cloth is detached.
54783
- * The point state is reset to avoid a sudden impulse.
54784
- * @param index - Point index.
54781
+ /**
54782
+ * Releases a fixed point so it becomes dynamic, for example when cloth is detached.
54783
+ * The point state is reset to avoid a sudden impulse.
54784
+ * @param index - Point index.
54785
54785
  */ releasePoint(index) {
54786
54786
  if (index < 0 || index >= this._pointsR.length) {
54787
54787
  return;
@@ -54792,10 +54792,10 @@ function isBoneFixed(roots, index) {
54792
54792
  this._pointsRW[index].positionPrevious = pos.clone();
54793
54793
  this._pointsRW[index].grabberIndex = -1;
54794
54794
  }
54795
- /**
54796
- * Fixes a dynamic point back to the animation pose, for example when an item is reattached.
54797
- * The point grab state is cleared.
54798
- * @param index - Point index.
54795
+ /**
54796
+ * Fixes a dynamic point back to the animation pose, for example when an item is reattached.
54797
+ * The point grab state is cleared.
54798
+ * @param index - Point index.
54799
54799
  */ fixPoint(index) {
54800
54800
  if (index < 0 || index >= this._pointsR.length) {
54801
54801
  return;
@@ -54803,9 +54803,9 @@ function isBoneFixed(roots, index) {
54803
54803
  this._pointsR[index].weight = 0;
54804
54804
  this._pointsRW[index].grabberIndex = -1;
54805
54805
  }
54806
- /**
54807
- * Returns whether a point is fixed to animation (`weight = 0`).
54808
- * @param index - Point index.
54806
+ /**
54807
+ * Returns whether a point is fixed to animation (`weight = 0`).
54808
+ * @param index - Point index.
54809
54809
  */ isPointFixed(index) {
54810
54810
  if (index < 0 || index >= this._pointsR.length) {
54811
54811
  return false;
@@ -54815,34 +54815,34 @@ function isBoneFixed(roots, index) {
54815
54815
  /** Gets the total number of physics points. */ get pointCount() {
54816
54816
  return this._pointsR.length;
54817
54817
  }
54818
- /**
54819
- * Fades physics in by blending from animation pose to simulation.
54820
- * `blendRatio` moves from `1` (animation only) to `0` (physics only).
54821
- * @param seconds - Transition duration in seconds.
54818
+ /**
54819
+ * Fades physics in by blending from animation pose to simulation.
54820
+ * `blendRatio` moves from `1` (animation only) to `0` (physics only).
54821
+ * @param seconds - Transition duration in seconds.
54822
54822
  */ fadeIn(seconds) {
54823
54823
  this._fadeState = 'in';
54824
54824
  this._fadeTimer = 0;
54825
54825
  this._fadeDuration = seconds;
54826
54826
  }
54827
- /**
54828
- * Fades physics out by blending from simulation back to animation pose.
54829
- * `blendRatio` moves from `0` (physics only) to `1` (animation only).
54830
- * @param seconds - Transition duration in seconds.
54827
+ /**
54828
+ * Fades physics out by blending from simulation back to animation pose.
54829
+ * `blendRatio` moves from `0` (physics only) to `1` (animation only).
54830
+ * @param seconds - Transition duration in seconds.
54831
54831
  */ fadeOut(seconds) {
54832
54832
  this._fadeState = 'out';
54833
54833
  this._fadeTimer = 0;
54834
54834
  this._fadeDuration = seconds;
54835
54835
  }
54836
- /**
54837
- * Sets the global wind force vector.
54838
- * The final wind contribution is still scaled per point by `windForceScale` and mass.
54839
- * @param wind - Wind vector in world space.
54836
+ /**
54837
+ * Sets the global wind force vector.
54838
+ * The final wind contribution is still scaled per point by `windForceScale` and mass.
54839
+ * @param wind - Wind vector in world space.
54840
54840
  */ setWindForce(wind) {
54841
54841
  this._config.windForce = wind;
54842
54842
  }
54843
- /**
54844
- * Enable/disable broad-phase pruning for runtime performance comparison
54845
- * @param enabled - `true` to enable broad-phase, `false` to disable.
54843
+ /**
54844
+ * Enable/disable broad-phase pruning for runtime performance comparison
54845
+ * @param enabled - `true` to enable broad-phase, `false` to disable.
54846
54846
  */ setBroadPhaseEnabled(enabled) {
54847
54847
  this._config.enableBroadPhase = enabled;
54848
54848
  }
@@ -54852,23 +54852,23 @@ function isBoneFixed(roots, index) {
54852
54852
  set blendRatio(value) {
54853
54853
  this._config.blendRatio = clamp01(value);
54854
54854
  }
54855
- /**
54856
- * Pauses or resumes the physics simulation.
54857
- * While paused, the system still follows root motion but skips force integration and
54858
- * constraint solving.
54859
- * @param paused - `true` to pause, `false` to resume.
54855
+ /**
54856
+ * Pauses or resumes the physics simulation.
54857
+ * While paused, the system still follows root motion but skips force integration and
54858
+ * constraint solving.
54859
+ * @param paused - `true` to pause, `false` to resume.
54860
54860
  */ setPaused(paused) {
54861
54861
  this._isPaused = paused;
54862
54862
  }
54863
- /**
54864
- * Enable or disable a collider by current array index.
54865
- * Transform state is still read from the collider's TransformAccess each frame.
54866
- * Prefer setColliderEnabled(handle, enabled) for runtime-owned colliders.
54867
- *
54868
- * @param index - Collider index in the current array. Note that this may change when colliders are added or removed.
54869
- * @param enabled - `true` to enable the collider, `false` to disable it.
54870
- *
54871
- * @returns `true` if the index is valid and the collider was updated, `false` if the index is out of range.
54863
+ /**
54864
+ * Enable or disable a collider by current array index.
54865
+ * Transform state is still read from the collider's TransformAccess each frame.
54866
+ * Prefer setColliderEnabled(handle, enabled) for runtime-owned colliders.
54867
+ *
54868
+ * @param index - Collider index in the current array. Note that this may change when colliders are added or removed.
54869
+ * @param enabled - `true` to enable the collider, `false` to disable it.
54870
+ *
54871
+ * @returns `true` if the index is valid and the collider was updated, `false` if the index is out of range.
54872
54872
  */ setColliderEnabledAt(index, enabled) {
54873
54873
  if (index >= 0 && index < this._collidersRW.length) {
54874
54874
  this._collidersRW[index].enabled = enabled ? 1 : 0;
@@ -54876,12 +54876,12 @@ function isBoneFixed(roots, index) {
54876
54876
  }
54877
54877
  return false;
54878
54878
  }
54879
- /**
54880
- * Enable or disable a runtime collider by stable handle.
54881
- *
54882
- * @param handle - Stable handle for the collider to enable or disable.
54883
- * @param enabled - `true` to enable the collider, `false` to disable it.
54884
- * @returns true if the handle is still valid.
54879
+ /**
54880
+ * Enable or disable a runtime collider by stable handle.
54881
+ *
54882
+ * @param handle - Stable handle for the collider to enable or disable.
54883
+ * @param enabled - `true` to enable the collider, `false` to disable it.
54884
+ * @returns true if the handle is still valid.
54885
54885
  */ setColliderEnabled(handle, enabled) {
54886
54886
  const index = this._getColliderIndex(handle);
54887
54887
  if (index === -1) {
@@ -54889,11 +54889,11 @@ function isBoneFixed(roots, index) {
54889
54889
  }
54890
54890
  return this.setColliderEnabledAt(index, enabled);
54891
54891
  }
54892
- /**
54893
- * Add a collider at runtime.
54894
- * @param r - Read-only collider data such as shape and size.
54895
- * @param transform - TransformAccess that provides the collider's position and rotation each frame.
54896
- * @returns A stable handle that remains valid until this collider is removed.
54892
+ /**
54893
+ * Add a collider at runtime.
54894
+ * @param r - Read-only collider data such as shape and size.
54895
+ * @param transform - TransformAccess that provides the collider's position and rotation each frame.
54896
+ * @returns A stable handle that remains valid until this collider is removed.
54897
54897
  */ addCollider(r, transform) {
54898
54898
  const id = this._nextColliderHandleId++;
54899
54899
  this._collidersR.push(r);
@@ -54906,10 +54906,10 @@ function isBoneFixed(roots, index) {
54906
54906
  id
54907
54907
  };
54908
54908
  }
54909
- /**
54910
- * Remove a collider by stable handle.
54911
- * @param handle - Stable handle for the collider to remove.
54912
- * @returns true if the collider existed and was removed.
54909
+ /**
54910
+ * Remove a collider by stable handle.
54911
+ * @param handle - Stable handle for the collider to remove.
54912
+ * @returns true if the collider existed and was removed.
54913
54913
  */ removeCollider(handle) {
54914
54914
  const index = this._getColliderIndex(handle);
54915
54915
  if (index === -1) {
@@ -54917,10 +54917,10 @@ function isBoneFixed(roots, index) {
54917
54917
  }
54918
54918
  return this.removeColliderAt(index);
54919
54919
  }
54920
- /**
54921
- * Remove a collider by current array index.
54922
- * @param index - Collider index in the current array. Note that this may change when colliders are added or removed.
54923
- * Prefer removeCollider(handle) for runtime-owned colliders.
54920
+ /**
54921
+ * Remove a collider by current array index.
54922
+ * @param index - Collider index in the current array. Note that this may change when colliders are added or removed.
54923
+ * Prefer removeCollider(handle) for runtime-owned colliders.
54924
54924
  */ removeColliderAt(index) {
54925
54925
  if (index < 0 || index >= this._collidersR.length) {
54926
54926
  return false;
@@ -54932,11 +54932,11 @@ function isBoneFixed(roots, index) {
54932
54932
  this._rebuildColliderHandleMap();
54933
54933
  return true;
54934
54934
  }
54935
- /**
54936
- * Enable or disable a flat plane by current array index.
54937
- * @param index - Flat plane index in the current array. Note that this may change when flat planes are added or removed.
54938
- * @param enabled - `true` to enable the flat plane, `false` to disable it.
54939
- * @returns `true` if the index is valid and the flat plane was updated, `false` if the index is out of range.
54935
+ /**
54936
+ * Enable or disable a flat plane by current array index.
54937
+ * @param index - Flat plane index in the current array. Note that this may change when flat planes are added or removed.
54938
+ * @param enabled - `true` to enable the flat plane, `false` to disable it.
54939
+ * @returns `true` if the index is valid and the flat plane was updated, `false` if the index is out of range.
54940
54940
  */ setFlatPlaneEnabledAt(index, enabled) {
54941
54941
  if (index < 0 || index >= this._flatPlaneAll.length) {
54942
54942
  return false;
@@ -54945,11 +54945,11 @@ function isBoneFixed(roots, index) {
54945
54945
  this._rebuildActiveFlatPlanes();
54946
54946
  return true;
54947
54947
  }
54948
- /**
54949
- * Enable or disable a runtime flat plane by stable handle.
54950
- * @param handle - Stable handle for the flat plane to enable or disable.
54951
- * @param enabled - `true` to enable the flat plane, `false` to disable it.
54952
- * @returns true if the handle is still valid.
54948
+ /**
54949
+ * Enable or disable a runtime flat plane by stable handle.
54950
+ * @param handle - Stable handle for the flat plane to enable or disable.
54951
+ * @param enabled - `true` to enable the flat plane, `false` to disable it.
54952
+ * @returns true if the handle is still valid.
54953
54953
  */ setFlatPlaneEnabled(handle, enabled) {
54954
54954
  const index = this._getFlatPlaneIndex(handle);
54955
54955
  if (index === -1) {
@@ -54957,11 +54957,11 @@ function isBoneFixed(roots, index) {
54957
54957
  }
54958
54958
  return this.setFlatPlaneEnabledAt(index, enabled);
54959
54959
  }
54960
- /**
54961
- * Add a flat plane at runtime.
54962
- * @param up - Up direction of the plane. The normal is computed as `Vector3.normalize(up)`.
54963
- * @param position - A point on the plane. The distance is computed as `-Vector3.dot(normal, position)`.
54964
- * @returns A stable handle that remains valid until this flat plane is removed.
54960
+ /**
54961
+ * Add a flat plane at runtime.
54962
+ * @param up - Up direction of the plane. The normal is computed as `Vector3.normalize(up)`.
54963
+ * @param position - A point on the plane. The distance is computed as `-Vector3.dot(normal, position)`.
54964
+ * @returns A stable handle that remains valid until this flat plane is removed.
54965
54965
  */ addFlatPlane(up, position) {
54966
54966
  const id = this._nextFlatPlaneHandleId++;
54967
54967
  const normal = Vector3.normalize(up);
@@ -54978,10 +54978,10 @@ function isBoneFixed(roots, index) {
54978
54978
  id
54979
54979
  };
54980
54980
  }
54981
- /**
54982
- * Remove a flat plane by stable handle.
54983
- * @param handle - Stable handle for the flat plane to remove.
54984
- * @returns true if the flat plane existed and was removed.
54981
+ /**
54982
+ * Remove a flat plane by stable handle.
54983
+ * @param handle - Stable handle for the flat plane to remove.
54984
+ * @returns true if the flat plane existed and was removed.
54985
54985
  */ removeFlatPlane(handle) {
54986
54986
  const index = this._getFlatPlaneIndex(handle);
54987
54987
  if (index === -1) {
@@ -54989,10 +54989,10 @@ function isBoneFixed(roots, index) {
54989
54989
  }
54990
54990
  return this.removeFlatPlaneAt(index);
54991
54991
  }
54992
- /**
54993
- * Remove a flat plane by current array index.
54994
- * @param index - Flat plane index in the current array. Note that this may change when flat planes are added or removed.
54995
- * @returns true if the index was valid and the flat plane was removed, false if the index was out of range.
54992
+ /**
54993
+ * Remove a flat plane by current array index.
54994
+ * @param index - Flat plane index in the current array. Note that this may change when flat planes are added or removed.
54995
+ * @returns true if the index was valid and the flat plane was removed, false if the index was out of range.
54996
54996
  */ removeFlatPlaneAt(index) {
54997
54997
  if (index < 0 || index >= this._flatPlaneAll.length) {
54998
54998
  return false;
@@ -55004,14 +55004,14 @@ function isBoneFixed(roots, index) {
55004
55004
  this._rebuildActiveFlatPlanes();
55005
55005
  return true;
55006
55006
  }
55007
- /**
55008
- * Enable or disable a grabber by current array index.
55009
- * Transform state is still read from the grabber's TransformAccess each frame.
55010
- * Prefer setGrabberEnabled(handle, enabled) for runtime-owned grabbers.
55011
- *
55012
- * @param index - Grabber index in the current array. Note that this may change when grabbers are added or removed.
55013
- * @param enabled - `true` to enable the grabber, `false` to disable it.
55014
- * @returns `true` if the index is valid and the grabber was updated, `false` if the index is out of range.
55007
+ /**
55008
+ * Enable or disable a grabber by current array index.
55009
+ * Transform state is still read from the grabber's TransformAccess each frame.
55010
+ * Prefer setGrabberEnabled(handle, enabled) for runtime-owned grabbers.
55011
+ *
55012
+ * @param index - Grabber index in the current array. Note that this may change when grabbers are added or removed.
55013
+ * @param enabled - `true` to enable the grabber, `false` to disable it.
55014
+ * @returns `true` if the index is valid and the grabber was updated, `false` if the index is out of range.
55015
55015
  */ setGrabberEnabledAt(index, enabled) {
55016
55016
  if (index >= 0 && index < this._grabbersRW.length) {
55017
55017
  this._grabbersRW[index].enabled = enabled ? 1 : 0;
@@ -55022,11 +55022,11 @@ function isBoneFixed(roots, index) {
55022
55022
  }
55023
55023
  return false;
55024
55024
  }
55025
- /**
55026
- * Enable or disable a runtime grabber by stable handle.
55027
- * @param handle - Stable handle for the grabber to enable or disable.
55028
- * @param enabled - `true` to enable the grabber, `false` to disable it.
55029
- * @returns true if the handle is still valid.
55025
+ /**
55026
+ * Enable or disable a runtime grabber by stable handle.
55027
+ * @param handle - Stable handle for the grabber to enable or disable.
55028
+ * @param enabled - `true` to enable the grabber, `false` to disable it.
55029
+ * @returns true if the handle is still valid.
55030
55030
  */ setGrabberEnabled(handle, enabled) {
55031
55031
  const index = this._getGrabberIndex(handle);
55032
55032
  if (index === -1) {
@@ -55034,12 +55034,12 @@ function isBoneFixed(roots, index) {
55034
55034
  }
55035
55035
  return this.setGrabberEnabledAt(index, enabled);
55036
55036
  }
55037
- /**
55038
- * Add a grabber at runtime.
55039
- * @param r - Read-only grabber data such as interaction radius.
55040
- * @param transform - TransformAccess that provides the grabber's position each frame.
55041
- * @param enabled - Whether the grabber starts enabled. The grabber can still be moved by its transform while disabled, but it won't affect any points until enabled.
55042
- * @returns A stable handle that remains valid until this grabber is removed.
55037
+ /**
55038
+ * Add a grabber at runtime.
55039
+ * @param r - Read-only grabber data such as interaction radius.
55040
+ * @param transform - TransformAccess that provides the grabber's position each frame.
55041
+ * @param enabled - Whether the grabber starts enabled. The grabber can still be moved by its transform while disabled, but it won't affect any points until enabled.
55042
+ * @returns A stable handle that remains valid until this grabber is removed.
55043
55043
  */ addGrabber(r, transform, enabled = false) {
55044
55044
  const id = this._nextGrabberHandleId++;
55045
55045
  this._grabbersR.push(r);
@@ -55055,10 +55055,10 @@ function isBoneFixed(roots, index) {
55055
55055
  id
55056
55056
  };
55057
55057
  }
55058
- /**
55059
- * Remove a grabber by stable handle.
55060
- * @param handle - Stable handle for the grabber to remove.
55061
- * @returns true if the grabber existed and was removed.
55058
+ /**
55059
+ * Remove a grabber by stable handle.
55060
+ * @param handle - Stable handle for the grabber to remove.
55061
+ * @returns true if the grabber existed and was removed.
55062
55062
  */ removeGrabber(handle) {
55063
55063
  const index = this._getGrabberIndex(handle);
55064
55064
  if (index === -1) {
@@ -55066,12 +55066,12 @@ function isBoneFixed(roots, index) {
55066
55066
  }
55067
55067
  return this.removeGrabberAt(index);
55068
55068
  }
55069
- /**
55070
- * Remove a grabber by current array index.
55071
- * Prefer removeGrabber(handle) for runtime-owned grabbers.
55072
- *
55073
- * @param index - Grabber index in the current array. Note that this may change when grabbers are added or removed.
55074
- * @returns true if the index was valid and the grabber was removed, false if the index was out of range.
55069
+ /**
55070
+ * Remove a grabber by current array index.
55071
+ * Prefer removeGrabber(handle) for runtime-owned grabbers.
55072
+ *
55073
+ * @param index - Grabber index in the current array. Note that this may change when grabbers are added or removed.
55074
+ * @returns true if the index was valid and the grabber was removed, false if the index was out of range.
55075
55075
  */ removeGrabberAt(index) {
55076
55076
  if (index < 0 || index >= this._grabbersR.length) {
55077
55077
  return false;
@@ -73762,11 +73762,11 @@ const MAX_ACCUMULATED_SIMULATION_TIME$1 = 1 / 20;
73762
73762
  const MAX_SIMULATION_STEPS_PER_UPDATE$1 = Math.max(1, Math.ceil(MAX_ACCUMULATED_SIMULATION_TIME$1 / FIXED_SIMULATION_TIME_STEP$1));
73763
73763
  const DEFAULT_PARTICLE_TARGET_SMOOTHING_TIME = 1 / 30;
73764
73764
  const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
73765
- /**
73766
- * Physics engine for spring-based particle simulation
73767
- * Uses Verlet integration and iterative constraint solving
73768
- *
73769
- * @public
73765
+ /**
73766
+ * Physics engine for spring-based particle simulation
73767
+ * Uses Verlet integration and iterative constraint solving
73768
+ *
73769
+ * @public
73770
73770
  */ class SpringSystem {
73771
73771
  _chain;
73772
73772
  _iterations;
@@ -73812,9 +73812,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
73812
73812
  this._smoothedCapsuleEndpoints = new WeakMap();
73813
73813
  this._smoothedPlaneData = new WeakMap();
73814
73814
  }
73815
- /**
73816
- * Updates the physics simulation
73817
- * @param deltaTime - Time step in seconds
73815
+ /**
73816
+ * Updates the physics simulation
73817
+ * @param deltaTime - Time step in seconds
73818
73818
  */ update(deltaTime) {
73819
73819
  const frameDt = Math.min(Math.max(Number(deltaTime) || 0, 0), MAX_ACCUMULATED_SIMULATION_TIME$1);
73820
73820
  if (frameDt <= 0) {
@@ -73891,8 +73891,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
73891
73891
  this.solveCollisions(inputDeltaTime);
73892
73892
  }
73893
73893
  }
73894
- /**
73895
- * Updates fixed particles to match their scene node positions
73894
+ /**
73895
+ * Updates fixed particles to match their scene node positions
73896
73896
  */ updateFixedParticles(deltaTime) {
73897
73897
  const blend = this.getTemporalBlendFactor(deltaTime, DEFAULT_PARTICLE_TARGET_SMOOTHING_TIME);
73898
73898
  for (const particle of this._chain.particles){
@@ -73920,9 +73920,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
73920
73920
  }
73921
73921
  }
73922
73922
  }
73923
- /**
73924
- * Solves pose preservation (long-range attachment to animated pose).
73925
- * This keeps strands close to authored shape while preserving dynamic movement.
73923
+ /**
73924
+ * Solves pose preservation (long-range attachment to animated pose).
73925
+ * This keeps strands close to authored shape while preserving dynamic movement.
73926
73926
  */ solvePosePreservation(totalIterations) {
73927
73927
  if (this._poseFollowRoot <= 0 && this._poseFollowTip <= 0) {
73928
73928
  return;
@@ -73955,9 +73955,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
73955
73955
  lerp(a, b, t) {
73956
73956
  return a + (b - a) * t;
73957
73957
  }
73958
- /**
73959
- * Calculates global rotation parameters from fixed particle movements
73960
- * Uses position history to estimate rotation center
73958
+ /**
73959
+ * Calculates global rotation parameters from fixed particle movements
73960
+ * Uses position history to estimate rotation center
73961
73961
  */ calculateGlobalRotation(dt) {
73962
73962
  // Collect fixed particles with movement
73963
73963
  const fixedParticles = [];
@@ -74015,9 +74015,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74015
74015
  omega: sumOmega
74016
74016
  };
74017
74017
  }
74018
- /**
74019
- * Estimates rotation center from a single particle's position history
74020
- * Uses circular motion fitting
74018
+ /**
74019
+ * Estimates rotation center from a single particle's position history
74020
+ * Uses circular motion fitting
74021
74021
  */ estimateRotationCenterFromHistory(particle, currentVelocity) {
74022
74022
  const history = particle.positionHistory;
74023
74023
  if (!history || history.length < 3) {
@@ -74053,9 +74053,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74053
74053
  const center = this.calculateCircleCenter(p1, p2, p3);
74054
74054
  return center;
74055
74055
  }
74056
- /**
74057
- * Calculates the center of a circle passing through 3 points
74058
- * Uses perpendicular bisector method
74056
+ /**
74057
+ * Calculates the center of a circle passing through 3 points
74058
+ * Uses perpendicular bisector method
74059
74059
  */ calculateCircleCenter(p1, p2, p3) {
74060
74060
  // Midpoints
74061
74061
  const mid12 = Vector3.scale(Vector3.add(p1, p2, new Vector3()), 0.5, new Vector3());
@@ -74092,8 +74092,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74092
74092
  // Fallback: use centroid
74093
74093
  return Vector3.scale(Vector3.add(Vector3.add(p1, p2, new Vector3()), p3, new Vector3()), 1.0 / 3.0, new Vector3());
74094
74094
  }
74095
- /**
74096
- * Calculates inertial acceleration for a particle in a rotating reference frame
74095
+ /**
74096
+ * Calculates inertial acceleration for a particle in a rotating reference frame
74097
74097
  */ calculateInertialAcceleration(particle, rotationCenter, angularVelocity, particleVelocity, centrifugalScale, coriolisScale) {
74098
74098
  // Vector from rotation center to particle
74099
74099
  const r = Vector3.sub(particle.position, rotationCenter, new Vector3());
@@ -74110,10 +74110,10 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74110
74110
  const totalAccel = Vector3.add(centrifugalAccel, coriolisAccel, new Vector3());
74111
74111
  return totalAccel;
74112
74112
  }
74113
- /**
74114
- * Solves a single spring constraint using XPBD (Extended Position-Based Dynamics).
74115
- *
74116
- * Reference: Müller et al., "Detailed Rigid Body Simulation with Extended Position Based Dynamics", 2020.
74113
+ /**
74114
+ * Solves a single spring constraint using XPBD (Extended Position-Based Dynamics).
74115
+ *
74116
+ * Reference: Müller et al., "Detailed Rigid Body Simulation with Extended Position Based Dynamics", 2020.
74117
74117
  */ solveConstraintXPBD(constraint, dt) {
74118
74118
  const pA = this._chain.particles[constraint.particleA];
74119
74119
  const pB = this._chain.particles[constraint.particleB];
@@ -74146,8 +74146,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74146
74146
  Vector3.add(pB.position, Vector3.scale(n, wB * deltaLambda, new Vector3()), pB.position);
74147
74147
  }
74148
74148
  }
74149
- /**
74150
- * Solves a single spring constraint (Verlet / PBD)
74149
+ /**
74150
+ * Solves a single spring constraint (Verlet / PBD)
74151
74151
  */ solveConstraint(constraint) {
74152
74152
  const pA = this._chain.particles[constraint.particleA];
74153
74153
  const pB = this._chain.particles[constraint.particleB];
@@ -74168,8 +74168,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74168
74168
  Vector3.sub(pB.position, correction, pB.position);
74169
74169
  }
74170
74170
  }
74171
- /**
74172
- * Solves collisions for all particles
74171
+ /**
74172
+ * Solves collisions for all particles
74173
74173
  */ solveCollisions(deltaTime) {
74174
74174
  // Update dynamic colliders from their nodes
74175
74175
  const blend = this.getTemporalBlendFactor(deltaTime, DEFAULT_COLLIDER_SMOOTHING_TIME$1);
@@ -74242,9 +74242,9 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74242
74242
  }
74243
74243
  }
74244
74244
  }
74245
- /**
74246
- * Applies simulation results to scene nodes
74247
- * @param weight - Blend weight [0-1] (default: 1.0)
74245
+ /**
74246
+ * Applies simulation results to scene nodes
74247
+ * @param weight - Blend weight [0-1] (default: 1.0)
74248
74248
  */ applyToNodes(weight = 1.0) {
74249
74249
  for(let i = 0; i < this._chain.particles.length - 1; i++){
74250
74250
  const particle = this._chain.particles[i];
@@ -74292,8 +74292,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74292
74292
  }
74293
74293
  }
74294
74294
  }
74295
- /**
74296
- * Resets the simulation to initial state
74295
+ /**
74296
+ * Resets the simulation to initial state
74297
74297
  */ reset() {
74298
74298
  this._chain.reset();
74299
74299
  for (const particle of this._chain.particles){
@@ -74309,61 +74309,61 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74309
74309
  this._smoothedCapsuleEndpoints = new WeakMap();
74310
74310
  this._smoothedPlaneData = new WeakMap();
74311
74311
  }
74312
- /**
74313
- * Gets the spring chain
74312
+ /**
74313
+ * Gets the spring chain
74314
74314
  */ get chain() {
74315
74315
  return this._chain;
74316
74316
  }
74317
- /**
74318
- * Gets the current gravity
74317
+ /**
74318
+ * Gets the current gravity
74319
74319
  */ get gravity() {
74320
74320
  return this._gravity;
74321
74321
  }
74322
74322
  set gravity(gravity) {
74323
74323
  this._gravity.set(gravity);
74324
74324
  }
74325
- /**
74326
- * Gets the current wind
74325
+ /**
74326
+ * Gets the current wind
74327
74327
  */ get wind() {
74328
74328
  return this._wind;
74329
74329
  }
74330
74330
  set wind(wind) {
74331
74331
  this._wind.set(wind);
74332
74332
  }
74333
- /**
74334
- * Gets the number of iterations
74333
+ /**
74334
+ * Gets the number of iterations
74335
74335
  */ get iterations() {
74336
74336
  return this._iterations;
74337
74337
  }
74338
74338
  set iterations(count) {
74339
74339
  this._iterations = Math.max(1, count);
74340
74340
  }
74341
- /**
74342
- * Gets whether inertial forces are enabled
74341
+ /**
74342
+ * Gets whether inertial forces are enabled
74343
74343
  */ get enableInertialForces() {
74344
74344
  return this._enableInertialForces;
74345
74345
  }
74346
74346
  set enableInertialForces(enabled) {
74347
74347
  this._enableInertialForces = enabled;
74348
74348
  }
74349
- /**
74350
- * Gets the centrifugal force scale
74349
+ /**
74350
+ * Gets the centrifugal force scale
74351
74351
  */ get centrifugalScale() {
74352
74352
  return this._centrifugalScale;
74353
74353
  }
74354
74354
  set centrifugalScale(scale) {
74355
74355
  this._centrifugalScale = Math.max(0, scale);
74356
74356
  }
74357
- /**
74358
- * Gets the Coriolis force scale
74357
+ /**
74358
+ * Gets the Coriolis force scale
74359
74359
  */ get coriolisScale() {
74360
74360
  return this._coriolisScale;
74361
74361
  }
74362
74362
  set coriolisScale(scale) {
74363
74363
  this._coriolisScale = Math.max(0, scale);
74364
74364
  }
74365
- /**
74366
- * Gets the constraint solver type
74365
+ /**
74366
+ * Gets the constraint solver type
74367
74367
  */ get solver() {
74368
74368
  return this._solver;
74369
74369
  }
@@ -74377,8 +74377,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74377
74377
  }
74378
74378
  }
74379
74379
  }
74380
- /**
74381
- * Gets pose preservation strength [0-1]
74380
+ /**
74381
+ * Gets pose preservation strength [0-1]
74382
74382
  */ get poseFollow() {
74383
74383
  return this._poseFollow;
74384
74384
  }
@@ -74388,8 +74388,8 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74388
74388
  this._poseFollowRoot = v;
74389
74389
  this._poseFollowTip = v;
74390
74390
  }
74391
- /**
74392
- * Gets max allowed deviation from animated pose
74391
+ /**
74392
+ * Gets max allowed deviation from animated pose
74393
74393
  */ get maxPoseOffset() {
74394
74394
  return this._maxPoseOffset;
74395
74395
  }
@@ -74399,56 +74399,56 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74399
74399
  this._maxPoseOffsetRoot = v;
74400
74400
  this._maxPoseOffsetTip = v;
74401
74401
  }
74402
- /**
74403
- * Gets root pose follow strength [0-1]
74402
+ /**
74403
+ * Gets root pose follow strength [0-1]
74404
74404
  */ get poseFollowRoot() {
74405
74405
  return this._poseFollowRoot;
74406
74406
  }
74407
74407
  set poseFollowRoot(value) {
74408
74408
  this._poseFollowRoot = Math.max(0, Math.min(1, value));
74409
74409
  }
74410
- /**
74411
- * Gets tip pose follow strength [0-1]
74410
+ /**
74411
+ * Gets tip pose follow strength [0-1]
74412
74412
  */ get poseFollowTip() {
74413
74413
  return this._poseFollowTip;
74414
74414
  }
74415
74415
  set poseFollowTip(value) {
74416
74416
  this._poseFollowTip = Math.max(0, Math.min(1, value));
74417
74417
  }
74418
- /**
74419
- * Gets exponent for root-to-tip interpolation
74418
+ /**
74419
+ * Gets exponent for root-to-tip interpolation
74420
74420
  */ get poseFollowExponent() {
74421
74421
  return this._poseFollowExponent;
74422
74422
  }
74423
74423
  set poseFollowExponent(value) {
74424
74424
  this._poseFollowExponent = Math.max(0.1, value);
74425
74425
  }
74426
- /**
74427
- * Gets root max allowed deviation from animated pose
74426
+ /**
74427
+ * Gets root max allowed deviation from animated pose
74428
74428
  */ get maxPoseOffsetRoot() {
74429
74429
  return this._maxPoseOffsetRoot;
74430
74430
  }
74431
74431
  set maxPoseOffsetRoot(value) {
74432
74432
  this._maxPoseOffsetRoot = Math.max(0, value);
74433
74433
  }
74434
- /**
74435
- * Gets tip max allowed deviation from animated pose
74434
+ /**
74435
+ * Gets tip max allowed deviation from animated pose
74436
74436
  */ get maxPoseOffsetTip() {
74437
74437
  return this._maxPoseOffsetTip;
74438
74438
  }
74439
74439
  set maxPoseOffsetTip(value) {
74440
74440
  this._maxPoseOffsetTip = Math.max(0, value);
74441
74441
  }
74442
- /**
74443
- * Adds a collider to the system
74442
+ /**
74443
+ * Adds a collider to the system
74444
74444
  */ addCollider(collider) {
74445
74445
  this._colliders.push(collider);
74446
74446
  this._smoothedSphereCenters = new WeakMap();
74447
74447
  this._smoothedCapsuleEndpoints = new WeakMap();
74448
74448
  this._smoothedPlaneData = new WeakMap();
74449
74449
  }
74450
- /**
74451
- * Removes a collider from the system
74450
+ /**
74451
+ * Removes a collider from the system
74452
74452
  */ removeCollider(collider) {
74453
74453
  const index = this._colliders.indexOf(collider);
74454
74454
  if (index >= 0) {
@@ -74460,16 +74460,16 @@ const DEFAULT_COLLIDER_SMOOTHING_TIME$1 = 1 / 30;
74460
74460
  }
74461
74461
  return false;
74462
74462
  }
74463
- /**
74464
- * Clears all colliders
74463
+ /**
74464
+ * Clears all colliders
74465
74465
  */ clearColliders() {
74466
74466
  this._colliders = [];
74467
74467
  this._smoothedSphereCenters = new WeakMap();
74468
74468
  this._smoothedCapsuleEndpoints = new WeakMap();
74469
74469
  this._smoothedPlaneData = new WeakMap();
74470
74470
  }
74471
- /**
74472
- * Gets all colliders
74471
+ /**
74472
+ * Gets all colliders
74473
74473
  */ get colliders() {
74474
74474
  return this._colliders;
74475
74475
  }