@zephyr3d/scene 0.9.19 → 0.9.20

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 (95) hide show
  1. package/dist/animation/joint_dynamics/convex_collider.js +320 -0
  2. package/dist/animation/joint_dynamics/convex_collider.js.map +1 -0
  3. package/dist/asset/assetmanager.js +1 -0
  4. package/dist/asset/assetmanager.js.map +1 -1
  5. package/dist/camera/camera.js +240 -201
  6. package/dist/camera/camera.js.map +1 -1
  7. package/dist/index.d.ts +190 -4
  8. package/dist/index.js +2 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/material/meshmaterial.js +2 -2
  11. package/dist/material/meshmaterial.js.map +1 -1
  12. package/dist/material/mixins/lit.js +10 -0
  13. package/dist/material/mixins/lit.js.map +1 -1
  14. package/dist/material/shader/helper.js +117 -2
  15. package/dist/material/shader/helper.js.map +1 -1
  16. package/dist/posteffect/skinsss.js +10 -10
  17. package/dist/posteffect/skinsss.js.map +1 -1
  18. package/dist/posteffect/ssr.js +13 -13
  19. package/dist/posteffect/ssr.js.map +1 -1
  20. package/dist/posteffect/sss.js +16 -15
  21. package/dist/posteffect/sss.js.map +1 -1
  22. package/dist/posteffect/tonemap.js +5 -5
  23. package/dist/posteffect/tonemap.js.map +1 -1
  24. package/dist/render/abuffer_oit.js +5 -0
  25. package/dist/render/abuffer_oit.js.map +1 -1
  26. package/dist/render/cluster_light.js +52 -8
  27. package/dist/render/cluster_light.js.map +1 -1
  28. package/dist/render/dualdepthpeeling_oit.js +331 -0
  29. package/dist/render/dualdepthpeeling_oit.js.map +1 -0
  30. package/dist/render/lightpass.js +24 -7
  31. package/dist/render/lightpass.js.map +1 -1
  32. package/dist/render/renderer.js +3 -0
  33. package/dist/render/renderer.js.map +1 -1
  34. package/dist/render/rendergraph/blackboard.js +40 -39
  35. package/dist/render/rendergraph/blackboard.js.map +1 -1
  36. package/dist/render/rendergraph/device_pool_allocator.js +10 -1
  37. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -1
  38. package/dist/render/rendergraph/forward_plus_builder.js +56 -0
  39. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  40. package/dist/render/rendergraph/types.js.map +1 -1
  41. package/dist/render/renderpass.js +12 -2
  42. package/dist/render/renderpass.js.map +1 -1
  43. package/dist/render/shadow_mask_pass.js +297 -0
  44. package/dist/render/shadow_mask_pass.js.map +1 -0
  45. package/dist/render/weightedblended_oit.js +5 -0
  46. package/dist/render/weightedblended_oit.js.map +1 -1
  47. package/dist/scene/basesprite.js +1 -0
  48. package/dist/scene/basesprite.js.map +1 -1
  49. package/dist/scene/batchgroup.js +1 -0
  50. package/dist/scene/batchgroup.js.map +1 -1
  51. package/dist/scene/environment.js +1 -0
  52. package/dist/scene/environment.js.map +1 -1
  53. package/dist/scene/msdftext.js +1 -0
  54. package/dist/scene/msdftext.js.map +1 -1
  55. package/dist/scene/msdftextsprite.js +1 -0
  56. package/dist/scene/msdftextsprite.js.map +1 -1
  57. package/dist/scene/particlesys.js +1 -0
  58. package/dist/scene/particlesys.js.map +1 -1
  59. package/dist/scene/scene.js +1 -0
  60. package/dist/scene/scene.js.map +1 -1
  61. package/dist/scene/terrain-cm/grass.js +1 -0
  62. package/dist/scene/terrain-cm/grass.js.map +1 -1
  63. package/dist/scene/terrain-cm/terrain-cm.js +1 -0
  64. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  65. package/dist/scene/water.js +1 -0
  66. package/dist/scene/water.js.map +1 -1
  67. package/dist/utility/serialization/manager.js +1 -0
  68. package/dist/utility/serialization/manager.js.map +1 -1
  69. package/dist/utility/serialization/scene/animation.js +1 -0
  70. package/dist/utility/serialization/scene/animation.js.map +1 -1
  71. package/dist/utility/serialization/scene/batch.js +1 -0
  72. package/dist/utility/serialization/scene/batch.js.map +1 -1
  73. package/dist/utility/serialization/scene/camera.js +35 -2
  74. package/dist/utility/serialization/scene/camera.js.map +1 -1
  75. package/dist/utility/serialization/scene/light.js +1 -0
  76. package/dist/utility/serialization/scene/light.js.map +1 -1
  77. package/dist/utility/serialization/scene/mesh.js +1 -0
  78. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  79. package/dist/utility/serialization/scene/node.js +1 -0
  80. package/dist/utility/serialization/scene/node.js.map +1 -1
  81. package/dist/utility/serialization/scene/particle.js +1 -0
  82. package/dist/utility/serialization/scene/particle.js.map +1 -1
  83. package/dist/utility/serialization/scene/primitive.js +1 -0
  84. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  85. package/dist/utility/serialization/scene/sprite.js +1 -0
  86. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  87. package/dist/utility/serialization/scene/terrain.js +1 -0
  88. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  89. package/dist/utility/serialization/scene/text.js +1 -0
  90. package/dist/utility/serialization/scene/text.js.map +1 -1
  91. package/dist/utility/serialization/scene/water.js +1 -0
  92. package/dist/utility/serialization/scene/water.js.map +1 -1
  93. package/dist/values.js +11 -1
  94. package/dist/values.js.map +1 -1
  95. package/package.json +2 -2
@@ -15,6 +15,7 @@ import { getDevice } from '../app/api.js';
15
15
  import { ScreenAdapter } from '../app/screen.js';
16
16
  import { ABufferOIT } from '../render/abuffer_oit.js';
17
17
  import { WeightedBlendedOIT } from '../render/weightedblended_oit.js';
18
+ import { DualDepthPeelingOIT } from '../render/dualdepthpeeling_oit.js';
18
19
 
19
20
  const SSS_DEFAULT_SETTINGS = {
20
21
  blurScale: 11,
@@ -46,24 +47,24 @@ const SSS_QUALITY_PRESET_SETTINGS = {
46
47
  normalCutoff: 0.72
47
48
  }
48
49
  };
49
- /**
50
- * A renderable camera node that manages view/projection math, frusta,
51
- * input control, picking, and a post-processing chain via a compositor.
52
- *
53
- * Key features:
54
- * - Maintains projection, view, VP, and inverse VP matrices and lazily recomputes them when invalidated.
55
- * - Provides world- and view-space frusta for culling and clipping.
56
- * - Supports perspective and orthographic projections.
57
- * - Integrates with post effects (Tonemap, FXAA, TAA, Bloom, SSR, SSS, SSAO, Motion Blur) through an internal `Compositor`.
58
- * - Handles temporal jitter and history state when TAA or motion blur are enabled.
59
- * - Emits picking rays from screen coordinates and supports async GPU picking.
60
- * - Optional controller integration for user input handling.
61
- *
62
- * Performance notes:
63
- * - Matrices/frusta are computed on demand and cached until invalidation.
64
- * - Temporal jitter and history are set up only when required by enabled features and device support.
65
- *
66
- * @public
50
+ /**
51
+ * A renderable camera node that manages view/projection math, frusta,
52
+ * input control, picking, and a post-processing chain via a compositor.
53
+ *
54
+ * Key features:
55
+ * - Maintains projection, view, VP, and inverse VP matrices and lazily recomputes them when invalidated.
56
+ * - Provides world- and view-space frusta for culling and clipping.
57
+ * - Supports perspective and orthographic projections.
58
+ * - Integrates with post effects (Tonemap, FXAA, TAA, Bloom, SSR, SSS, SSAO, Motion Blur) through an internal `Compositor`.
59
+ * - Handles temporal jitter and history state when TAA or motion blur are enabled.
60
+ * - Emits picking rays from screen coordinates and supports async GPU picking.
61
+ * - Optional controller integration for user input handling.
62
+ *
63
+ * Performance notes:
64
+ * - Matrices/frusta are computed on demand and cached until invalidation.
65
+ * - Temporal jitter and history are set up only when required by enabled features and device support.
66
+ *
67
+ * @public
67
68
  */ class Camera extends SceneNode {
68
69
  /** @internal Halton 2-3 sequence used for TAA jittering. */ static _halton23 = halton23(16);
69
70
  /** @internal Per-camera history resources. */ static _historyData = new WeakMap();
@@ -92,10 +93,12 @@ const SSS_QUALITY_PRESET_SETTINGS = {
92
93
  /** @internal Order-Independent Transparency reference. */ _oit;
93
94
  /** @internal OIT algorithm selection mode. */ _oitMode;
94
95
  /** @internal ABuffer OIT layer budget. */ _oitABufferLayers;
96
+ /** @internal Dual depth peeling OIT peel iteration count. */ _oitDualDepthPeels;
95
97
  /** @internal Whether to perform a depth pre-pass. */ _depthPrePass;
96
98
  /** @internal Render path selection for scene renderer. */ _renderPath;
97
99
  /** @internal Whether command buffers may be reused for optimization. */ _commandBufferReuse;
98
100
  /** @internal Hi-Z acceleration enable (primarily for SSR). */ _HiZ;
101
+ /** @internal Screen-space shadow mask enable (Forward+ deferred shadows). */ _screenSpaceShadowMask;
99
102
  /** @internal If true, a float point backbuffer will be used. The default value is true */ _HDR;
100
103
  /** @internal Tonemap enable flag (via post effect). */ _toneMap;
101
104
  /** @internal Tonemap post effect reference. */ _postEffectTonemap;
@@ -174,14 +177,14 @@ const SSS_QUALITY_PRESET_SETTINGS = {
174
177
  /** @internal Post-processing compositor attached to this camera. */ _compositor;
175
178
  /** @internal Pointer interaction rectangle in css pixels (relative to canvas) */ _interactionRect;
176
179
  /** @internal captured by which mouse button (-1 if not captured) */ _capturedButton;
177
- /**
178
- * Creates a new camera node.
179
- *
180
- * Initializes projection/view matrices, temporal fields, controller linkage, and
181
- * builds the default post-processing pipeline on the internal compositor.
182
- *
183
- * @param scene - The scene that owns this camera.
184
- * @param projectionMatrix - Optional projection matrix to initialize with.
180
+ /**
181
+ * Creates a new camera node.
182
+ *
183
+ * Initializes projection/view matrices, temporal fields, controller linkage, and
184
+ * builds the default post-processing pipeline on the internal compositor.
185
+ *
186
+ * @param scene - The scene that owns this camera.
187
+ * @param projectionMatrix - Optional projection matrix to initialize with.
185
188
  */ constructor(scene, projectionMatrix){
186
189
  super(scene);
187
190
  this._projMatrix = projectionMatrix || Matrix4x4.identity();
@@ -206,11 +209,13 @@ const SSS_QUALITY_PRESET_SETTINGS = {
206
209
  this._oit = new DRef();
207
210
  this._oitMode = 'none';
208
211
  this._oitABufferLayers = 20;
212
+ this._oitDualDepthPeels = 8;
209
213
  this._depthPrePass = false;
210
214
  this._renderPath = 'forward';
211
215
  this._screenAdapter = new ScreenAdapter();
212
216
  this._adapted = false;
213
217
  this._HiZ = false;
218
+ this._screenSpaceShadowMask = true;
214
219
  this._HDR = true;
215
220
  this._toneMap = true;
216
221
  this._postEffectTonemap = new DRef();
@@ -303,81 +308,94 @@ const SSS_QUALITY_PRESET_SETTINGS = {
303
308
  scene.mainCamera = this;
304
309
  }
305
310
  }
306
- /**
307
- * The compositor that owns and runs the camera's post-processing chain.
311
+ /**
312
+ * The compositor that owns and runs the camera's post-processing chain.
308
313
  */ get compositor() {
309
314
  return this._compositor;
310
315
  }
311
- /**
312
- * Pointer interaction rectangle in css pixels (relative to canvas)
316
+ /**
317
+ * Pointer interaction rectangle in css pixels (relative to canvas)
313
318
  */ get interactionRect() {
314
319
  return this._interactionRect;
315
320
  }
316
321
  set interactionRect(rect) {
317
322
  this._interactionRect = rect;
318
323
  }
319
- /**
320
- * Framebuffer clear color, or `null` to disable.
324
+ /**
325
+ * Framebuffer clear color, or `null` to disable.
321
326
  */ get clearColor() {
322
327
  return this._clearColor;
323
328
  }
324
329
  set clearColor(v) {
325
330
  this._clearColor = v?.clone() ?? null;
326
331
  }
327
- /**
328
- * Framebuffer stencil clear value, disabled when null. Default is 0.
332
+ /**
333
+ * Framebuffer stencil clear value, disabled when null. Default is 0.
329
334
  */ get clearDepth() {
330
335
  return this._clearDepth;
331
336
  }
332
337
  set clearDepth(v) {
333
338
  this._clearDepth = v;
334
339
  }
335
- /**
336
- * Framebuffer stencil clear value, disabled when null. Default is 0.
340
+ /**
341
+ * Framebuffer stencil clear value, disabled when null. Default is 0.
337
342
  */ get clearStencil() {
338
343
  return this._clearStencil;
339
344
  }
340
345
  set clearStencil(v) {
341
346
  this._clearStencil = v;
342
347
  }
343
- /**
344
- * Whether Hi-Z acceleration is enabled.
345
- *
346
- * Often improves SSR performance with little quality impact when supported.
348
+ /**
349
+ * Whether Hi-Z acceleration is enabled.
350
+ *
351
+ * Often improves SSR performance with little quality impact when supported.
347
352
  */ get HiZ() {
348
353
  return this._HiZ;
349
354
  }
350
355
  set HiZ(val) {
351
356
  this._HiZ = !!val;
352
357
  }
353
- /**
354
- * Render path used by the scene renderer.
358
+ /**
359
+ * Whether the screen-space shadow mask is enabled.
360
+ *
361
+ * When enabled, shadow-casting lights are lit through the clustered pass and
362
+ * sample a pre-rendered screen-space shadow mask instead of each casting an
363
+ * additional full-scene additive light pass. Requires the depth prepass
364
+ * (always on in Forward+).
365
+ */ get screenSpaceShadowMask() {
366
+ return this._screenSpaceShadowMask;
367
+ }
368
+ set screenSpaceShadowMask(val) {
369
+ this._screenSpaceShadowMask = !!val;
370
+ }
371
+ /**
372
+ * Render path used by the scene renderer.
355
373
  */ get renderPath() {
356
374
  return this._renderPath;
357
375
  }
358
376
  set renderPath(_val) {
359
377
  this._renderPath = 'forward';
360
378
  }
361
- /**
362
- * Whether HDR backbuffer is enabled.
363
- *
364
- * Tonemap should be disabled when not using HDR backbuffer.
379
+ /**
380
+ * Whether HDR backbuffer is enabled.
381
+ *
382
+ * Tonemap should be disabled when not using HDR backbuffer.
365
383
  */ get HDR() {
366
384
  return this._HDR;
367
385
  }
368
386
  set HDR(val) {
369
387
  this._HDR = !!val;
370
388
  }
371
- /**
372
- * Whether tonemapping is enabled via the post effect.
389
+ /**
390
+ * Whether tonemapping is enabled via the post effect.
373
391
  */ get toneMap() {
374
392
  return this._postEffectTonemap.get().enabled;
375
393
  }
376
394
  set toneMap(val) {
377
395
  this._postEffectTonemap.get().enabled = !!val;
378
396
  }
379
- /**
380
- * Whether motion blur is enabled via the post effect.
397
+ /**
398
+ * Whether motion blur is enabled via the post effect.
381
399
  */ get motionBlur() {
382
400
  return this._postEffectMotionBlur.get().enabled;
383
401
  }
@@ -393,16 +411,16 @@ const SSS_QUALITY_PRESET_SETTINGS = {
393
411
  this._postEffectMotionBlur.get().strength = this._motionBlurStrength;
394
412
  }
395
413
  }
396
- /**
397
- * Gets whether Bloom is enabled.
414
+ /**
415
+ * Gets whether Bloom is enabled.
398
416
  */ get bloom() {
399
417
  return this._postEffectBloom.get().enabled;
400
418
  }
401
419
  set bloom(val) {
402
420
  this._postEffectBloom.get().enabled = !!val;
403
421
  }
404
- /**
405
- * Maximum bloom downsample levels
422
+ /**
423
+ * Maximum bloom downsample levels
406
424
  */ get bloomMaxDownsampleLevels() {
407
425
  return this._bloomMaxDownsampleLevels;
408
426
  }
@@ -412,8 +430,8 @@ const SSS_QUALITY_PRESET_SETTINGS = {
412
430
  this._postEffectBloom.get().maxDownsampleLevel = val;
413
431
  }
414
432
  }
415
- /**
416
- * Bloom downsample limit
433
+ /**
434
+ * Bloom downsample limit
417
435
  */ get bloomDownsampleLimit() {
418
436
  return this._bloomDownsampleLimit;
419
437
  }
@@ -423,8 +441,8 @@ const SSS_QUALITY_PRESET_SETTINGS = {
423
441
  this._postEffectBloom.get().downsampleLimit = val;
424
442
  }
425
443
  }
426
- /**
427
- * Bloom threshold
444
+ /**
445
+ * Bloom threshold
428
446
  */ get bloomThreshold() {
429
447
  return this._bloomThreshold;
430
448
  }
@@ -434,8 +452,8 @@ const SSS_QUALITY_PRESET_SETTINGS = {
434
452
  this._postEffectBloom.get().threshold = val;
435
453
  }
436
454
  }
437
- /**
438
- * Bloom threshold knee
455
+ /**
456
+ * Bloom threshold knee
439
457
  */ get bloomThresholdKnee() {
440
458
  return this._bloomThresholdKnee;
441
459
  }
@@ -445,8 +463,8 @@ const SSS_QUALITY_PRESET_SETTINGS = {
445
463
  this._postEffectBloom.get().thresholdKnee = val;
446
464
  }
447
465
  }
448
- /**
449
- * Bloom intensity
466
+ /**
467
+ * Bloom intensity
450
468
  */ get bloomIntensity() {
451
469
  return this._bloomIntensity;
452
470
  }
@@ -498,16 +516,16 @@ const SSS_QUALITY_PRESET_SETTINGS = {
498
516
  this._postEffectColorAdjust.get().sharpen = val;
499
517
  }
500
518
  }
501
- /**
502
- * Gets whether FXAA is enabled.
519
+ /**
520
+ * Gets whether FXAA is enabled.
503
521
  */ get FXAA() {
504
522
  return this._postEffectFXAA.get().enabled;
505
523
  }
506
524
  set FXAA(val) {
507
525
  this._postEffectFXAA.get().enabled = !!val;
508
526
  }
509
- /**
510
- * Tonemap exposure
527
+ /**
528
+ * Tonemap exposure
511
529
  */ get toneMapExposure() {
512
530
  return this._tonemapExposure;
513
531
  }
@@ -517,156 +535,156 @@ const SSS_QUALITY_PRESET_SETTINGS = {
517
535
  this._postEffectTonemap.get().exposure = val;
518
536
  }
519
537
  }
520
- /**
521
- * Gets whether TAA is enabled.
538
+ /**
539
+ * Gets whether TAA is enabled.
522
540
  */ get TAA() {
523
541
  return this._postEffectTAA.get().enabled;
524
542
  }
525
543
  set TAA(val) {
526
544
  this._postEffectTAA.get().enabled = !!val;
527
545
  }
528
- /**
529
- * Gets the debug flag for TAA
546
+ /**
547
+ * Gets the debug flag for TAA
530
548
  */ get TAADebug() {
531
549
  return this._TAADebug;
532
550
  }
533
551
  set TAADebug(val) {
534
552
  this._TAADebug = val;
535
553
  }
536
- /**
537
- * Enables cascade debug visualization for directional shadows.
554
+ /**
555
+ * Enables cascade debug visualization for directional shadows.
538
556
  */ get shadowDebugCascades() {
539
557
  return this._shadowDebugCascades;
540
558
  }
541
559
  set shadowDebugCascades(val) {
542
560
  this._shadowDebugCascades = !!val;
543
561
  }
544
- /**
545
- * Gets whether Screen Space Reflections (SSR) is enabled.
562
+ /**
563
+ * Gets whether Screen Space Reflections (SSR) is enabled.
546
564
  */ get SSR() {
547
565
  return this._postEffectSSR.get().enabled;
548
566
  }
549
567
  set SSR(val) {
550
568
  this._postEffectSSR.get().enabled = !!val;
551
569
  }
552
- /**
553
- * Gets the maximum roughness value for screen space reflections.
554
- * Controls the cutoff point where surfaces are considered too rough for SSR.
570
+ /**
571
+ * Gets the maximum roughness value for screen space reflections.
572
+ * Controls the cutoff point where surfaces are considered too rough for SSR.
555
573
  */ get ssrMaxRoughness() {
556
574
  return this._ssrMaxRoughness;
557
575
  }
558
576
  set ssrMaxRoughness(val) {
559
577
  this._ssrMaxRoughness = val;
560
578
  }
561
- /**
562
- * Gets the roughness factor for SSR calculations.
563
- * Affects how surface roughness influences reflection clarity.
579
+ /**
580
+ * Gets the roughness factor for SSR calculations.
581
+ * Affects how surface roughness influences reflection clarity.
564
582
  */ get ssrRoughnessFactor() {
565
583
  return this._ssrRoughnessFactor;
566
584
  }
567
585
  set ssrRoughnessFactor(val) {
568
586
  this._ssrRoughnessFactor = val;
569
587
  }
570
- /**
571
- * Gets the stride value for SSR ray marching.
572
- * Controls the step size during ray marching. Larger values improve performance but may miss details.
588
+ /**
589
+ * Gets the stride value for SSR ray marching.
590
+ * Controls the step size during ray marching. Larger values improve performance but may miss details.
573
591
  */ get ssrStride() {
574
592
  return this._ssrStride;
575
593
  }
576
594
  set ssrStride(val) {
577
595
  this._ssrStride = val;
578
596
  }
579
- /**
580
- * Gets the maximum distance for SSR ray marching.
581
- * Defines how far rays will travel when searching for reflection intersections.
597
+ /**
598
+ * Gets the maximum distance for SSR ray marching.
599
+ * Defines how far rays will travel when searching for reflection intersections.
582
600
  */ get ssrMaxDistance() {
583
601
  return this._ssrParams.x;
584
602
  }
585
603
  set ssrMaxDistance(val) {
586
604
  this._ssrParams.x = val;
587
605
  }
588
- /**
589
- * Gets the number of iterations for SSR ray marching.
590
- * Higher values provide more accurate reflections but impact performance.
606
+ /**
607
+ * Gets the number of iterations for SSR ray marching.
608
+ * Higher values provide more accurate reflections but impact performance.
591
609
  */ get ssrIterations() {
592
610
  return this._ssrParams.y;
593
611
  }
594
612
  set ssrIterations(val) {
595
613
  this._ssrParams.y = val;
596
614
  }
597
- /**
598
- * Gets the thickness value for SSR calculations.
599
- * Determines the thickness threshold for surfaces when calculating reflections.
615
+ /**
616
+ * Gets the thickness value for SSR calculations.
617
+ * Determines the thickness threshold for surfaces when calculating reflections.
600
618
  */ get ssrThickness() {
601
619
  return this._ssrParams.z;
602
620
  }
603
621
  set ssrThickness(val) {
604
622
  this._ssrParams.z = val;
605
623
  }
606
- /**
607
- * Gets whether SSR should calculate thickness automatically.
608
- * When enabled, the system will dynamically compute surface thickness for reflections.
624
+ /**
625
+ * Gets whether SSR should calculate thickness automatically.
626
+ * When enabled, the system will dynamically compute surface thickness for reflections.
609
627
  */ get ssrCalcThickness() {
610
628
  return this._ssrCalcThickness;
611
629
  }
612
630
  set ssrCalcThickness(val) {
613
631
  this._ssrCalcThickness = !!val;
614
632
  }
615
- /**
616
- * Gets the blur scale factor for SSR.
617
- * Controls the overall intensity of the blur effect applied to reflections.
633
+ /**
634
+ * Gets the blur scale factor for SSR.
635
+ * Controls the overall intensity of the blur effect applied to reflections.
618
636
  */ get ssrBlurScale() {
619
637
  return this._ssrBlurriness;
620
638
  }
621
639
  set ssrBlurScale(val) {
622
640
  this._ssrBlurriness = val;
623
641
  }
624
- /**
625
- * Gets the depth cutoff value for SSR blur.
626
- * Determines at what depth difference the blur effect should be reduced or eliminated.
642
+ /**
643
+ * Gets the depth cutoff value for SSR blur.
644
+ * Determines at what depth difference the blur effect should be reduced or eliminated.
627
645
  */ get ssrBlurDepthCutoff() {
628
646
  return this._ssrBlurDepthCutoff;
629
647
  }
630
648
  set ssrBlurDepthCutoff(val) {
631
649
  this._ssrBlurDepthCutoff = val;
632
650
  }
633
- /**
634
- * Gets the kernel size for the SSR blur effect.
635
- * Defines the size of the blur kernel. Larger values create softer, more spread-out blur.
651
+ /**
652
+ * Gets the kernel size for the SSR blur effect.
653
+ * Defines the size of the blur kernel. Larger values create softer, more spread-out blur.
636
654
  */ get ssrBlurKernelSize() {
637
655
  return this._ssrBlurKernelSize;
638
656
  }
639
657
  set ssrBlurKernelSize(val) {
640
658
  this._ssrBlurKernelSize = val;
641
659
  }
642
- /**
643
- * Gets the standard deviation for the SSR Gaussian blur.
644
- * Controls the distribution of the blur effect. Higher values create more pronounced blur.
660
+ /**
661
+ * Gets the standard deviation for the SSR Gaussian blur.
662
+ * Controls the distribution of the blur effect. Higher values create more pronounced blur.
645
663
  */ get ssrBlurStdDev() {
646
664
  return this._ssrBlurStdDev;
647
665
  }
648
666
  set ssrBlurStdDev(val) {
649
667
  this._ssrBlurStdDev = val;
650
668
  }
651
- /**
652
- * Gets whether SSR temporal accumulation is enabled.
669
+ /**
670
+ * Gets whether SSR temporal accumulation is enabled.
653
671
  */ get ssrTemporal() {
654
672
  return this._ssrTemporal;
655
673
  }
656
674
  set ssrTemporal(val) {
657
675
  this._ssrTemporal = !!val;
658
676
  }
659
- /**
660
- * Gets SSR temporal blending weight in [0, 1].
661
- * Higher values rely more on reprojected history.
677
+ /**
678
+ * Gets SSR temporal blending weight in [0, 1].
679
+ * Higher values rely more on reprojected history.
662
680
  */ get ssrTemporalWeight() {
663
681
  return this._ssrTemporalWeight;
664
682
  }
665
683
  set ssrTemporalWeight(val) {
666
684
  this._ssrTemporalWeight = Math.max(0, Math.min(1, val ?? 0));
667
685
  }
668
- /**
669
- * Gets whether Screen Space Subsurface Scattering (SSS) is enabled.
686
+ /**
687
+ * Gets whether Screen Space Subsurface Scattering (SSS) is enabled.
670
688
  */ get SSS() {
671
689
  return this._postEffectSSS.get().enabled;
672
690
  }
@@ -679,11 +697,11 @@ const SSS_QUALITY_PRESET_SETTINGS = {
679
697
  set sssBlurScale(val) {
680
698
  this._sssBlurScale = Math.max(0, val ?? 0);
681
699
  }
682
- /**
683
- * High-level quality preset for SSS blur controls.
684
- *
685
- * This is the primary user-facing SSS quality control and only affects
686
- * the blur sampling quality/performance tradeoff, not the authored look.
700
+ /**
701
+ * High-level quality preset for SSS blur controls.
702
+ *
703
+ * This is the primary user-facing SSS quality control and only affects
704
+ * the blur sampling quality/performance tradeoff, not the authored look.
687
705
  */ get sssQualityPreset() {
688
706
  return this._sssQualityPreset;
689
707
  }
@@ -781,8 +799,8 @@ const SSS_QUALITY_PRESET_SETTINGS = {
781
799
  /** @internal */ get ssrParams() {
782
800
  return this._ssrParams;
783
801
  }
784
- /**
785
- * Gets whether SSAO is enabled.
802
+ /**
803
+ * Gets whether SSAO is enabled.
786
804
  */ get SSAO() {
787
805
  return this._postEffectSSAO.get().enabled;
788
806
  }
@@ -889,6 +907,21 @@ const SSS_QUALITY_PRESET_SETTINGS = {
889
907
  }
890
908
  }
891
909
  }
910
+ /** Dual depth peeling OIT peel iteration count. */ get oitDualDepthPeels() {
911
+ return this._oitDualDepthPeels;
912
+ }
913
+ set oitDualDepthPeels(val) {
914
+ const peels = Math.max(1, Math.floor(val || 0));
915
+ if (peels !== this._oitDualDepthPeels) {
916
+ this._oitDualDepthPeels = peels;
917
+ // Peel count only drives the per-frame pass loop, so update the live
918
+ // instance in place instead of rebuilding it.
919
+ const oit = this._oit.get();
920
+ if (oit instanceof DualDepthPeelingOIT) {
921
+ oit.numPeels = peels;
922
+ }
923
+ }
924
+ }
892
925
  /** Clip plane mask */ get clipMask() {
893
926
  return this._clipMask;
894
927
  }
@@ -922,27 +955,27 @@ const SSS_QUALITY_PRESET_SETTINGS = {
922
955
  }
923
956
  return this._viewport;
924
957
  }
925
- /**
926
- * Screen configuration used for adapting the camera viewport
958
+ /**
959
+ * Screen configuration used for adapting the camera viewport
927
960
  */ get screenConfig() {
928
961
  return this._screenAdapter.config;
929
962
  }
930
963
  set screenConfig(config) {
931
964
  this._screenAdapter.config = config;
932
965
  }
933
- /**
934
- * Screen viewport used for adapting the camera viewport
966
+ /**
967
+ * Screen viewport used for adapting the camera viewport
935
968
  */ get screenViewport() {
936
969
  return this._screenAdapter.viewport;
937
970
  }
938
971
  set screenViewport(viewport) {
939
972
  this._screenAdapter.viewport = viewport;
940
973
  }
941
- /**
942
- * Handle input events
943
- * @param ev - input event object
944
- * @param type - event type, default to ev.type
945
- * @returns Boolean value indicates whether the event was handled.
974
+ /**
975
+ * Handle input events
976
+ * @param ev - input event object
977
+ * @param type - event type, default to ev.type
978
+ * @returns Boolean value indicates whether the event was handled.
946
979
  */ handleEvent(ev, type) {
947
980
  let handled = false;
948
981
  if (this._controller) {
@@ -975,12 +1008,12 @@ const SSS_QUALITY_PRESET_SETTINGS = {
975
1008
  }
976
1009
  return handled;
977
1010
  }
978
- /**
979
- * Constructs a ray based on the given screen coordinates.
980
- *
981
- * @param x - The x-component of the screen coordinates, relative to the top-left corner of the viewport.
982
- * @param y - The y-component of the screen coordinates, relative to the top-left corner of the viewport.
983
- * @returns The ray originating from the camera position and passing through the given screen coordinates.
1011
+ /**
1012
+ * Constructs a ray based on the given screen coordinates.
1013
+ *
1014
+ * @param x - The x-component of the screen coordinates, relative to the top-left corner of the viewport.
1015
+ * @param y - The y-component of the screen coordinates, relative to the top-left corner of the viewport.
1016
+ * @returns The ray originating from the camera position and passing through the given screen coordinates.
984
1017
  */ constructRay(x, y) {
985
1018
  const width = this.viewport ? this.viewport[2] : getDevice().getViewport().width;
986
1019
  const height = this.viewport ? this.viewport[3] : getDevice().getViewport().height;
@@ -998,54 +1031,54 @@ const SSS_QUALITY_PRESET_SETTINGS = {
998
1031
  const vDir = Vector3.sub(farWorld.xyz(), vEye).inplaceNormalize();
999
1032
  return new Ray(vEye, vDir);
1000
1033
  }
1001
- /**
1002
- * Place the camera by specifying the camera position and the target point
1003
- * @param eye - The camera position
1004
- * @param target - The target point to look at
1005
- * @param up - The up vector
1006
- * @returns self
1034
+ /**
1035
+ * Place the camera by specifying the camera position and the target point
1036
+ * @param eye - The camera position
1037
+ * @param target - The target point to look at
1038
+ * @param up - The up vector
1039
+ * @returns self
1007
1040
  */ lookAt(eye, target, up) {
1008
1041
  return this.setLocalTransform(Matrix4x4.lookAt(eye, target, up));
1009
1042
  }
1010
- /**
1011
- * Place the camera to look at a given cube face at a given camera position
1012
- * @param face - The cube face to look at
1013
- * @param position - The camera position
1014
- * @returns self
1043
+ /**
1044
+ * Place the camera to look at a given cube face at a given camera position
1045
+ * @param face - The cube face to look at
1046
+ * @param position - The camera position
1047
+ * @returns self
1015
1048
  */ lookAtCubeFace(face, position) {
1016
1049
  return this.setLocalTransform(Matrix4x4.lookAtCubeFace(face, position ?? this.position));
1017
1050
  }
1018
- /**
1019
- * Setup a perspective projection matrix for the camera
1020
- * @param fovY - The vertical field of view in radians.
1021
- * @param aspect - The aspect ratio
1022
- * @param zNear - The near clip plane
1023
- * @param zFar - The far clip plane
1024
- * @returns self
1051
+ /**
1052
+ * Setup a perspective projection matrix for the camera
1053
+ * @param fovY - The vertical field of view in radians.
1054
+ * @param aspect - The aspect ratio
1055
+ * @param zNear - The near clip plane
1056
+ * @param zFar - The far clip plane
1057
+ * @returns self
1025
1058
  */ setPerspective(fovY, aspect, zNear, zFar) {
1026
1059
  this._projMatrix.perspective(fovY, aspect, zNear, zFar);
1027
1060
  Matrix4x4.invert(this._projMatrix, this._invProjMatrix);
1028
1061
  this._invalidate(true);
1029
1062
  return this;
1030
1063
  }
1031
- /**
1032
- * Setup a orthogonal projection matrix for the camera
1033
- * @param left - Left bound of the frustum
1034
- * @param right - Right bound of the frustum
1035
- * @param bottom - Bottom bound of the frustum
1036
- * @param top - Top bound of the frustum
1037
- * @param near - Near bound of the frustum.
1038
- * @param far - Far bound of the frustum.
1039
- * @returns self
1064
+ /**
1065
+ * Setup a orthogonal projection matrix for the camera
1066
+ * @param left - Left bound of the frustum
1067
+ * @param right - Right bound of the frustum
1068
+ * @param bottom - Bottom bound of the frustum
1069
+ * @param top - Top bound of the frustum
1070
+ * @param near - Near bound of the frustum.
1071
+ * @param far - Far bound of the frustum.
1072
+ * @returns self
1040
1073
  */ setOrtho(left, right, bottom, top, near, far) {
1041
1074
  this._projMatrix.ortho(left, right, bottom, top, near, far);
1042
1075
  Matrix4x4.invert(this._projMatrix, this._invProjMatrix);
1043
1076
  this._invalidate(true);
1044
1077
  return this;
1045
1078
  }
1046
- /**
1047
- * Setup a projection matrix for the camera
1048
- * @param matrix - The projection matrix
1079
+ /**
1080
+ * Setup a projection matrix for the camera
1081
+ * @param matrix - The projection matrix
1049
1082
  */ setProjectionMatrix(matrix) {
1050
1083
  if (matrix && matrix !== this._projMatrix) {
1051
1084
  this._projMatrix = matrix;
@@ -1053,18 +1086,18 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1053
1086
  this._invalidate(true);
1054
1087
  }
1055
1088
  }
1056
- /**
1057
- * Gets the projection matrix of the camera
1058
- * @returns The projection matrix
1089
+ /**
1090
+ * Gets the projection matrix of the camera
1091
+ * @returns The projection matrix
1059
1092
  */ getProjectionMatrix() {
1060
1093
  if (this.dirtyCheck()) {
1061
1094
  this._compute();
1062
1095
  }
1063
1096
  return this._projMatrix;
1064
1097
  }
1065
- /**
1066
- * Gets the inverse projection matrix of the camera
1067
- * @returns The projection matrix
1098
+ /**
1099
+ * Gets the inverse projection matrix of the camera
1100
+ * @returns The projection matrix
1068
1101
  */ getInvProjectionMatrix() {
1069
1102
  if (this.dirtyCheck()) {
1070
1103
  this._compute();
@@ -1082,11 +1115,11 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1082
1115
  rotationMatrix.setRow(2, new Vector4(zAxis.x, zAxis.y, zAxis.z, 0));
1083
1116
  return rotationMatrix;
1084
1117
  }
1085
- /**
1086
- * View matrix of the camera
1087
- *
1088
- * @remarks
1089
- * Camera's view matrix will transform a point from the world space to the camera space
1118
+ /**
1119
+ * View matrix of the camera
1120
+ *
1121
+ * @remarks
1122
+ * Camera's view matrix will transform a point from the world space to the camera space
1090
1123
  */ get viewMatrix() {
1091
1124
  if (this.dirtyCheck()) {
1092
1125
  this._compute();
@@ -1099,11 +1132,11 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1099
1132
  }
1100
1133
  return this._viewProjMatrix;
1101
1134
  }
1102
- /**
1103
- * The inverse-view-projection matrix of the camera
1104
- *
1105
- * @remarks
1106
- * The inverse-view-projection matrix transforms a point from the clip space to the camera space
1135
+ /**
1136
+ * The inverse-view-projection matrix of the camera
1137
+ *
1138
+ * @remarks
1139
+ * The inverse-view-projection matrix transforms a point from the clip space to the camera space
1107
1140
  */ get invViewProjectionMatrix() {
1108
1141
  if (this.dirtyCheck()) {
1109
1142
  this._compute();
@@ -1155,9 +1188,9 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1155
1188
  /** Returns true if the camera is orthographic */ isOrtho() {
1156
1189
  return this.getProjectionMatrix().isOrtho();
1157
1190
  }
1158
- /**
1159
- * Gets the camera history data which is used in temporal reprojection
1160
- * @returns Camera history data
1191
+ /**
1192
+ * Gets the camera history data which is used in temporal reprojection
1193
+ * @returns Camera history data
1161
1194
  */ getHistoryData() {
1162
1195
  let data = Camera._historyData.get(this);
1163
1196
  if (!data) {
@@ -1171,8 +1204,8 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1171
1204
  }
1172
1205
  return data;
1173
1206
  }
1174
- /**
1175
- * Clears the camera history data which is used in temporal reprojection
1207
+ /**
1208
+ * Clears the camera history data which is used in temporal reprojection
1176
1209
  */ clearHistoryData() {
1177
1210
  const data = Camera._historyData.get(this);
1178
1211
  if (data) {
@@ -1302,10 +1335,10 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1302
1335
  this._sssResolvedSettings.blurDepthCutoff = source.blurDepthCutoff;
1303
1336
  this._sssResolvedSettings.normalCutoff = source.normalCutoff;
1304
1337
  }
1305
- /**
1306
- * Renders a scene
1307
- * @param scene - The scene to be rendered
1308
- * @param compositor - Compositor instance that will be used to apply postprocess effects
1338
+ /**
1339
+ * Renders a scene
1340
+ * @param scene - The scene to be rendered
1341
+ * @param compositor - Compositor instance that will be used to apply postprocess effects
1309
1342
  */ render(scene) {
1310
1343
  const device = getDevice();
1311
1344
  //this.updatePostProcessing(device);
@@ -1379,13 +1412,13 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1379
1412
  /** @internal */ getPickPosY() {
1380
1413
  return this._pickPosY;
1381
1414
  }
1382
- /**
1383
- * Updates the controller state
1415
+ /**
1416
+ * Updates the controller state
1384
1417
  */ updateController() {
1385
1418
  this._controller?.update();
1386
1419
  }
1387
- /**
1388
- * Reset the controller
1420
+ /**
1421
+ * Reset the controller
1389
1422
  */ resetController() {
1390
1423
  this._controller?.reset();
1391
1424
  }
@@ -1410,15 +1443,15 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1410
1443
  /** @internal */ get prevPosition() {
1411
1444
  return this._prevPosition;
1412
1445
  }
1413
- /**
1414
- * Gets the camera history resource manager for temporal effects.
1446
+ /**
1447
+ * Gets the camera history resource manager for temporal effects.
1415
1448
  */ getHistoryResourceManager() {
1416
1449
  return Camera._historyResourceManager.get(this) ?? null;
1417
1450
  }
1418
- /**
1419
- * Sets the camera history resource manager for temporal effects.
1420
- *
1421
- * @internal
1451
+ /**
1452
+ * Sets the camera history resource manager for temporal effects.
1453
+ *
1454
+ * @internal
1422
1455
  */ setHistoryResourceManager(manager) {
1423
1456
  const current = Camera._historyResourceManager.get(this);
1424
1457
  if (current && current !== manager) {
@@ -1482,6 +1515,9 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1482
1515
  if (mode === 'weighted') {
1483
1516
  return new WeightedBlendedOIT();
1484
1517
  }
1518
+ if (mode === 'dual-depth') {
1519
+ return new DualDepthPeelingOIT(this._oitDualDepthPeels);
1520
+ }
1485
1521
  return null;
1486
1522
  }
1487
1523
  /** @internal */ inferOITMode(oit) {
@@ -1495,6 +1531,9 @@ const SSS_QUALITY_PRESET_SETTINGS = {
1495
1531
  if (type === WeightedBlendedOIT.type) {
1496
1532
  return 'weighted';
1497
1533
  }
1534
+ if (type === DualDepthPeelingOIT.type) {
1535
+ return 'dual-depth';
1536
+ }
1498
1537
  return null;
1499
1538
  }
1500
1539
  /** @internal */ posInViewport(x, y) {