@babylonjs/core 8.38.0 → 8.39.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 (235) hide show
  1. package/Animations/animation.d.ts +2 -1
  2. package/Animations/animation.js +3 -2
  3. package/Animations/animation.js.map +1 -1
  4. package/Audio/Interfaces/ISoundOptions.d.ts +1 -1
  5. package/Audio/Interfaces/ISoundOptions.js.map +1 -1
  6. package/Audio/audioEngine.d.ts +3 -4
  7. package/Audio/audioEngine.js +9 -6
  8. package/Audio/audioEngine.js.map +1 -1
  9. package/Audio/sound.d.ts +33 -54
  10. package/Audio/sound.js +450 -718
  11. package/Audio/sound.js.map +1 -1
  12. package/AudioV2/abstractAudio/abstractAudioOutNode.d.ts +1 -1
  13. package/AudioV2/abstractAudio/abstractAudioOutNode.js +1 -1
  14. package/AudioV2/abstractAudio/abstractAudioOutNode.js.map +1 -1
  15. package/AudioV2/abstractAudio/abstractSound.d.ts +1 -1
  16. package/AudioV2/abstractAudio/abstractSound.js +2 -2
  17. package/AudioV2/abstractAudio/abstractSound.js.map +1 -1
  18. package/AudioV2/abstractAudio/abstractSoundSource.d.ts +11 -3
  19. package/AudioV2/abstractAudio/abstractSoundSource.js +37 -1
  20. package/AudioV2/abstractAudio/abstractSoundSource.js.map +1 -1
  21. package/AudioV2/abstractAudio/audioBus.d.ts +8 -3
  22. package/AudioV2/abstractAudio/audioBus.js +24 -1
  23. package/AudioV2/abstractAudio/audioBus.js.map +1 -1
  24. package/AudioV2/abstractAudio/staticSound.d.ts +1 -1
  25. package/AudioV2/abstractAudio/staticSound.js +2 -2
  26. package/AudioV2/abstractAudio/staticSound.js.map +1 -1
  27. package/AudioV2/abstractAudio/streamingSound.d.ts +1 -1
  28. package/AudioV2/abstractAudio/streamingSound.js +2 -2
  29. package/AudioV2/abstractAudio/streamingSound.js.map +1 -1
  30. package/AudioV2/abstractAudio/subNodes/abstractAudioSubGraph.d.ts +1 -1
  31. package/AudioV2/abstractAudio/subNodes/abstractAudioSubGraph.js +3 -0
  32. package/AudioV2/abstractAudio/subNodes/abstractAudioSubGraph.js.map +1 -1
  33. package/AudioV2/abstractAudio/subNodes/spatialAudioSubNode.d.ts +1 -0
  34. package/AudioV2/abstractAudio/subNodes/spatialAudioSubNode.js +1 -0
  35. package/AudioV2/abstractAudio/subNodes/spatialAudioSubNode.js.map +1 -1
  36. package/AudioV2/abstractAudio/subProperties/abstractSpatialAudio.d.ts +12 -2
  37. package/AudioV2/abstractAudio/subProperties/abstractSpatialAudio.js +2 -0
  38. package/AudioV2/abstractAudio/subProperties/abstractSpatialAudio.js.map +1 -1
  39. package/AudioV2/abstractAudio/subProperties/spatialAudio.d.ts +6 -0
  40. package/AudioV2/abstractAudio/subProperties/spatialAudio.js +25 -0
  41. package/AudioV2/abstractAudio/subProperties/spatialAudio.js.map +1 -1
  42. package/AudioV2/webAudio/components/webAudioParameterComponent.js +2 -2
  43. package/AudioV2/webAudio/components/webAudioParameterComponent.js.map +1 -1
  44. package/AudioV2/webAudio/subNodes/spatialWebAudioSubNode.d.ts +3 -0
  45. package/AudioV2/webAudio/subNodes/spatialWebAudioSubNode.js +14 -17
  46. package/AudioV2/webAudio/subNodes/spatialWebAudioSubNode.js.map +1 -1
  47. package/AudioV2/webAudio/subNodes/webAudioBusAndSoundSubGraph.js +1 -0
  48. package/AudioV2/webAudio/subNodes/webAudioBusAndSoundSubGraph.js.map +1 -1
  49. package/AudioV2/webAudio/subProperties/spatialWebAudio.js +1 -0
  50. package/AudioV2/webAudio/subProperties/spatialWebAudio.js.map +1 -1
  51. package/AudioV2/webAudio/webAudioBus.d.ts +2 -7
  52. package/AudioV2/webAudio/webAudioBus.js +4 -24
  53. package/AudioV2/webAudio/webAudioBus.js.map +1 -1
  54. package/AudioV2/webAudio/webAudioEngine.js +1 -0
  55. package/AudioV2/webAudio/webAudioEngine.js.map +1 -1
  56. package/AudioV2/webAudio/webAudioSoundSource.d.ts +2 -7
  57. package/AudioV2/webAudio/webAudioSoundSource.js +3 -24
  58. package/AudioV2/webAudio/webAudioSoundSource.js.map +1 -1
  59. package/AudioV2/webAudio/webAudioStaticSound.d.ts +3 -7
  60. package/AudioV2/webAudio/webAudioStaticSound.js +13 -26
  61. package/AudioV2/webAudio/webAudioStaticSound.js.map +1 -1
  62. package/AudioV2/webAudio/webAudioStreamingSound.d.ts +3 -7
  63. package/AudioV2/webAudio/webAudioStreamingSound.js +6 -23
  64. package/AudioV2/webAudio/webAudioStreamingSound.js.map +1 -1
  65. package/Behaviors/Cameras/autoRotationBehavior.d.ts +4 -0
  66. package/Behaviors/Cameras/autoRotationBehavior.js +7 -0
  67. package/Behaviors/Cameras/autoRotationBehavior.js.map +1 -1
  68. package/Behaviors/Cameras/bouncingBehavior.d.ts +5 -0
  69. package/Behaviors/Cameras/bouncingBehavior.js +8 -0
  70. package/Behaviors/Cameras/bouncingBehavior.js.map +1 -1
  71. package/Behaviors/Cameras/framingBehavior.d.ts +4 -0
  72. package/Behaviors/Cameras/framingBehavior.js +7 -0
  73. package/Behaviors/Cameras/framingBehavior.js.map +1 -1
  74. package/Behaviors/Cameras/interpolatingBehavior.d.ts +7 -1
  75. package/Behaviors/Cameras/interpolatingBehavior.js +11 -3
  76. package/Behaviors/Cameras/interpolatingBehavior.js.map +1 -1
  77. package/Behaviors/Meshes/attachToBoxBehavior.d.ts +5 -0
  78. package/Behaviors/Meshes/attachToBoxBehavior.js +8 -1
  79. package/Behaviors/Meshes/attachToBoxBehavior.js.map +1 -1
  80. package/Behaviors/Meshes/baseSixDofDragBehavior.d.ts +5 -2
  81. package/Behaviors/Meshes/baseSixDofDragBehavior.js +8 -0
  82. package/Behaviors/Meshes/baseSixDofDragBehavior.js.map +1 -1
  83. package/Behaviors/Meshes/fadeInOutBehavior.d.ts +5 -0
  84. package/Behaviors/Meshes/fadeInOutBehavior.js +6 -0
  85. package/Behaviors/Meshes/fadeInOutBehavior.js.map +1 -1
  86. package/Behaviors/Meshes/handConstraintBehavior.d.ts +5 -0
  87. package/Behaviors/Meshes/handConstraintBehavior.js +8 -0
  88. package/Behaviors/Meshes/handConstraintBehavior.js.map +1 -1
  89. package/Behaviors/Meshes/multiPointerScaleBehavior.d.ts +5 -0
  90. package/Behaviors/Meshes/multiPointerScaleBehavior.js +8 -0
  91. package/Behaviors/Meshes/multiPointerScaleBehavior.js.map +1 -1
  92. package/Behaviors/Meshes/sixDofDragBehavior.js +1 -1
  93. package/Behaviors/Meshes/sixDofDragBehavior.js.map +1 -1
  94. package/Behaviors/Meshes/surfaceMagnetismBehavior.d.ts +5 -0
  95. package/Behaviors/Meshes/surfaceMagnetismBehavior.js +7 -0
  96. package/Behaviors/Meshes/surfaceMagnetismBehavior.js.map +1 -1
  97. package/Behaviors/behavior.d.ts +4 -0
  98. package/Behaviors/behavior.js.map +1 -1
  99. package/Cameras/geospatialCamera.d.ts +13 -5
  100. package/Cameras/geospatialCamera.js +116 -48
  101. package/Cameras/geospatialCamera.js.map +1 -1
  102. package/Cameras/geospatialCameraMovement.d.ts +6 -2
  103. package/Cameras/geospatialCameraMovement.js +11 -11
  104. package/Cameras/geospatialCameraMovement.js.map +1 -1
  105. package/Engines/WebGPU/Extensions/engine.multiRender.d.ts +2 -1
  106. package/Engines/WebGPU/Extensions/engine.multiRender.js +5 -2
  107. package/Engines/WebGPU/Extensions/engine.multiRender.js.map +1 -1
  108. package/Engines/WebGPU/webgpuTextureHelper.d.ts +1 -0
  109. package/Engines/WebGPU/webgpuTextureHelper.js +11 -0
  110. package/Engines/WebGPU/webgpuTextureHelper.js.map +1 -1
  111. package/Engines/WebGPU/webgpuTextureManager.d.ts +1 -0
  112. package/Engines/WebGPU/webgpuTextureManager.js +100 -9
  113. package/Engines/WebGPU/webgpuTextureManager.js.map +1 -1
  114. package/Engines/abstractEngine.d.ts +2 -2
  115. package/Engines/abstractEngine.js +2 -2
  116. package/Engines/abstractEngine.js.map +1 -1
  117. package/Engines/renderTargetWrapper.js +6 -1
  118. package/Engines/renderTargetWrapper.js.map +1 -1
  119. package/Engines/thinEngine.js +1 -1
  120. package/Engines/thinEngine.js.map +1 -1
  121. package/Engines/webgpuEngine.d.ts +7 -4
  122. package/Engines/webgpuEngine.js +53 -25
  123. package/Engines/webgpuEngine.js.map +1 -1
  124. package/FrameGraph/Node/Blocks/PostProcesses/volumetricLightingBlock.d.ts +74 -0
  125. package/FrameGraph/Node/Blocks/PostProcesses/volumetricLightingBlock.js +179 -0
  126. package/FrameGraph/Node/Blocks/PostProcesses/volumetricLightingBlock.js.map +1 -0
  127. package/FrameGraph/Node/Blocks/index.d.ts +2 -0
  128. package/FrameGraph/Node/Blocks/index.js +2 -0
  129. package/FrameGraph/Node/Blocks/index.js.map +1 -1
  130. package/FrameGraph/Node/Blocks/lightingVolumeBlock.d.ts +46 -0
  131. package/FrameGraph/Node/Blocks/lightingVolumeBlock.js +106 -0
  132. package/FrameGraph/Node/Blocks/lightingVolumeBlock.js.map +1 -0
  133. package/FrameGraph/Node/nodeRenderGraph.d.ts +22 -5
  134. package/FrameGraph/Node/nodeRenderGraph.js +39 -18
  135. package/FrameGraph/Node/nodeRenderGraph.js.map +1 -1
  136. package/FrameGraph/Passes/pass.d.ts +2 -0
  137. package/FrameGraph/Passes/pass.js +2 -0
  138. package/FrameGraph/Passes/pass.js.map +1 -1
  139. package/FrameGraph/Passes/renderPass.d.ts +2 -0
  140. package/FrameGraph/Passes/renderPass.js +4 -0
  141. package/FrameGraph/Passes/renderPass.js.map +1 -1
  142. package/FrameGraph/Tasks/Misc/lightingVolumeTask.d.ts +31 -0
  143. package/FrameGraph/Tasks/Misc/lightingVolumeTask.js +56 -0
  144. package/FrameGraph/Tasks/Misc/lightingVolumeTask.js.map +1 -0
  145. package/FrameGraph/Tasks/PostProcesses/postProcessTask.d.ts +2 -2
  146. package/FrameGraph/Tasks/PostProcesses/postProcessTask.js.map +1 -1
  147. package/FrameGraph/Tasks/PostProcesses/volumetricLightingBlendVolumeTask.d.ts +30 -0
  148. package/FrameGraph/Tasks/PostProcesses/volumetricLightingBlendVolumeTask.js +57 -0
  149. package/FrameGraph/Tasks/PostProcesses/volumetricLightingBlendVolumeTask.js.map +1 -0
  150. package/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.d.ts +91 -0
  151. package/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.js +210 -0
  152. package/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.js.map +1 -0
  153. package/FrameGraph/Tasks/Rendering/objectRendererTask.js +1 -1
  154. package/FrameGraph/Tasks/Rendering/objectRendererTask.js.map +1 -1
  155. package/FrameGraph/Tasks/Texture/clearTextureTask.js +1 -1
  156. package/FrameGraph/Tasks/Texture/clearTextureTask.js.map +1 -1
  157. package/FrameGraph/frameGraph.d.ts +13 -4
  158. package/FrameGraph/frameGraph.js +45 -5
  159. package/FrameGraph/frameGraph.js.map +1 -1
  160. package/FrameGraph/frameGraphRenderContext.d.ts +2 -2
  161. package/FrameGraph/frameGraphRenderContext.js.map +1 -1
  162. package/FrameGraph/frameGraphRenderTarget.d.ts +1 -0
  163. package/FrameGraph/frameGraphRenderTarget.js +3 -0
  164. package/FrameGraph/frameGraphRenderTarget.js.map +1 -1
  165. package/FrameGraph/frameGraphTask.d.ts +6 -0
  166. package/FrameGraph/frameGraphTask.js +17 -2
  167. package/FrameGraph/frameGraphTask.js.map +1 -1
  168. package/FrameGraph/frameGraphTypes.d.ts +2 -0
  169. package/FrameGraph/frameGraphTypes.js.map +1 -1
  170. package/FrameGraph/index.d.ts +2 -0
  171. package/FrameGraph/index.js +2 -0
  172. package/FrameGraph/index.js.map +1 -1
  173. package/Helpers/sceneHelpers.js +1 -1
  174. package/Helpers/sceneHelpers.js.map +1 -1
  175. package/Lights/index.d.ts +1 -0
  176. package/Lights/index.js +1 -0
  177. package/Lights/index.js.map +1 -1
  178. package/Lights/lightingVolume.d.ts +89 -0
  179. package/Lights/lightingVolume.js +435 -0
  180. package/Lights/lightingVolume.js.map +1 -0
  181. package/Materials/GaussianSplatting/gaussianSplattingMaterial.d.ts +7 -0
  182. package/Materials/GaussianSplatting/gaussianSplattingMaterial.js +19 -5
  183. package/Materials/GaussianSplatting/gaussianSplattingMaterial.js.map +1 -1
  184. package/Materials/Node/nodeMaterial.js +8 -2
  185. package/Materials/Node/nodeMaterial.js.map +1 -1
  186. package/Materials/floatingOriginMatrixOverrides.js +6 -5
  187. package/Materials/floatingOriginMatrixOverrides.js.map +1 -1
  188. package/Materials/uniformBuffer.d.ts +1 -0
  189. package/Materials/uniformBuffer.js +8 -1
  190. package/Materials/uniformBuffer.js.map +1 -1
  191. package/Meshes/GaussianSplatting/gaussianSplattingMesh.d.ts +5 -2
  192. package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +138 -45
  193. package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
  194. package/Meshes/mesh.js +1 -1
  195. package/Meshes/mesh.js.map +1 -1
  196. package/Misc/screenshotTools.js +2 -8
  197. package/Misc/screenshotTools.js.map +1 -1
  198. package/Particles/solidParticle.d.ts +9 -0
  199. package/Particles/solidParticle.js +11 -0
  200. package/Particles/solidParticle.js.map +1 -1
  201. package/Particles/solidParticleSystem.d.ts +28 -0
  202. package/Particles/solidParticleSystem.js +75 -0
  203. package/Particles/solidParticleSystem.js.map +1 -1
  204. package/Physics/v2/characterController.d.ts +42 -2
  205. package/Physics/v2/characterController.js +140 -46
  206. package/Physics/v2/characterController.js.map +1 -1
  207. package/Shaders/volumetricLightingBlendVolume.fragment.d.ts +5 -0
  208. package/Shaders/volumetricLightingBlendVolume.fragment.js +21 -0
  209. package/Shaders/volumetricLightingBlendVolume.fragment.js.map +1 -0
  210. package/Shaders/volumetricLightingRenderVolume.fragment.d.ts +7 -0
  211. package/Shaders/volumetricLightingRenderVolume.fragment.js +25 -0
  212. package/Shaders/volumetricLightingRenderVolume.fragment.js.map +1 -0
  213. package/Shaders/volumetricLightingRenderVolume.vertex.d.ts +9 -0
  214. package/Shaders/volumetricLightingRenderVolume.vertex.js +18 -0
  215. package/Shaders/volumetricLightingRenderVolume.vertex.js.map +1 -0
  216. package/ShadersWGSL/gaussianSplattingDepth.fragment.d.ts +0 -1
  217. package/ShadersWGSL/gaussianSplattingDepth.fragment.js +0 -2
  218. package/ShadersWGSL/gaussianSplattingDepth.fragment.js.map +1 -1
  219. package/ShadersWGSL/lightingVolume.compute.d.ts +5 -0
  220. package/ShadersWGSL/lightingVolume.compute.js +27 -0
  221. package/ShadersWGSL/lightingVolume.compute.js.map +1 -0
  222. package/ShadersWGSL/volumetricLightingBlendVolume.fragment.d.ts +5 -0
  223. package/ShadersWGSL/volumetricLightingBlendVolume.fragment.js +22 -0
  224. package/ShadersWGSL/volumetricLightingBlendVolume.fragment.js.map +1 -0
  225. package/ShadersWGSL/volumetricLightingRenderVolume.fragment.d.ts +7 -0
  226. package/ShadersWGSL/volumetricLightingRenderVolume.fragment.js +27 -0
  227. package/ShadersWGSL/volumetricLightingRenderVolume.fragment.js.map +1 -0
  228. package/ShadersWGSL/volumetricLightingRenderVolume.vertex.d.ts +7 -0
  229. package/ShadersWGSL/volumetricLightingRenderVolume.vertex.js +17 -0
  230. package/ShadersWGSL/volumetricLightingRenderVolume.vertex.js.map +1 -0
  231. package/States/IStencilState.d.ts +48 -2
  232. package/States/IStencilState.js.map +1 -1
  233. package/package.json +1 -1
  234. package/scene.js +6 -4
  235. package/scene.js.map +1 -1
@@ -0,0 +1,435 @@
1
+ import { AbortError } from "../Misc/error.js";
2
+
3
+ import { Matrix, Vector3 } from "../Maths/math.vector.js";
4
+ import { DirectionalLight } from "./directionalLight.js";
5
+ import { Mesh } from "../Meshes/mesh.js";
6
+ import { ComputeShader } from "../Compute/computeShader.js";
7
+ import { CopyTextureToTexture } from "../Misc/copyTextureToTexture.js";
8
+ import { UniformBuffer } from "../Materials/uniformBuffer.js";
9
+ import { StorageBuffer } from "../Buffers/storageBuffer.js";
10
+ import { BaseTexture } from "../Materials/Textures/baseTexture.js";
11
+ import { VertexBuffer } from "../Buffers/buffer.js";
12
+ import "../ShadersWGSL/lightingVolume.compute.js";
13
+ const InvViewProjMatrix = new Matrix();
14
+ const TmpVec3 = new Vector3();
15
+ /**
16
+ * Class used to create a lighting volume from a directional light's shadow generator.
17
+ */
18
+ export class LightingVolume {
19
+ /**
20
+ * The shadow generator used to create the lighting volume.
21
+ */
22
+ get shadowGenerator() {
23
+ return this._shadowGenerator;
24
+ }
25
+ set shadowGenerator(sg) {
26
+ const light = sg.getLight();
27
+ if (!(light instanceof DirectionalLight)) {
28
+ throw new Error(`LightingVolumeMesh ${this._name}: light must be a directional light`);
29
+ }
30
+ this._shadowGenerator = sg;
31
+ this._light = light;
32
+ this._createGeometry();
33
+ if (!this._engine.isWebGPU) {
34
+ this._createFallbackTextures();
35
+ }
36
+ const depthTexture = this._shadowGenerator.getShadowMap()?.depthStencilTexture;
37
+ if (this._cs && depthTexture) {
38
+ this._cs.setInternalTexture("shadowMap", depthTexture);
39
+ }
40
+ }
41
+ /**
42
+ * The tesselation level of the lighting volume.
43
+ */
44
+ get tesselation() {
45
+ return this._tesselation;
46
+ }
47
+ set tesselation(n) {
48
+ this._tesselation = n;
49
+ this._createGeometry();
50
+ }
51
+ /**
52
+ * Indicates whether to build the full volume (true) or only the near plane (false). Default is false.
53
+ */
54
+ get buildFullVolume() {
55
+ return this._buildFullVolume;
56
+ }
57
+ set buildFullVolume(value) {
58
+ if (this._buildFullVolume === value) {
59
+ return;
60
+ }
61
+ this._buildFullVolume = value;
62
+ this._createGeometry();
63
+ if (this._engine.isWebGPU) {
64
+ this._createComputeShader();
65
+ }
66
+ this._firstUpdate = true;
67
+ }
68
+ /**
69
+ * The mesh used as a support for the lighting volume.
70
+ * Note that this mesh is not automatically added to the scene's mesh array.
71
+ * If you want to render it, you need to add it manually.
72
+ */
73
+ get mesh() {
74
+ return this._mesh;
75
+ }
76
+ /**
77
+ * The frequency (in number of times you call updateMesh) at which the lighting volume is updated.
78
+ */
79
+ get frequency() {
80
+ return this._frequency;
81
+ }
82
+ set frequency(value) {
83
+ this._frequency = value;
84
+ this._firstUpdate = true;
85
+ }
86
+ /**
87
+ * The name of the lighting volume.
88
+ */
89
+ get name() {
90
+ return this._name;
91
+ }
92
+ set name(name) {
93
+ this._name = name;
94
+ if (this._mesh) {
95
+ this._mesh.name = name;
96
+ }
97
+ }
98
+ /**
99
+ * Indicates whether this is the first update of the lighting volume.
100
+ * If true, the volume has not yet been updated for the first time.
101
+ */
102
+ get firstUpdate() {
103
+ return this._firstUpdate;
104
+ }
105
+ /**
106
+ * Creates a new LightingVolume.
107
+ * @param name The name of the lighting volume.
108
+ * @param scene The scene the lighting volume belongs to.
109
+ * @param shadowGenerator The shadow generator used to create the lighting volume. This is optional in the constructor, but must be set before calling updateMesh.
110
+ * @param tesselation The tesselation level of the lighting volume (default: 64).
111
+ */
112
+ constructor(name, scene, shadowGenerator, tesselation = 64) {
113
+ this._readPixelPromise = null;
114
+ this._readPixelAbortController = null;
115
+ this._numFrames = 0;
116
+ this._firstUpdate = true;
117
+ this._tesselation = 0;
118
+ this._buildFullVolume = false;
119
+ this._frequency = 1;
120
+ const light = shadowGenerator ? shadowGenerator.getLight() : undefined;
121
+ if (light && !(light instanceof DirectionalLight)) {
122
+ throw new Error(`LightingVolumeMesh ${name}: light must be a directional light`);
123
+ }
124
+ this._name = name;
125
+ this._shadowGenerator = shadowGenerator;
126
+ this._light = light;
127
+ this._engine = scene.getEngine();
128
+ this._scene = scene;
129
+ this._mesh = new Mesh(name, this._scene);
130
+ scene.meshes.splice(scene.meshes.indexOf(this._mesh), 1);
131
+ if (this._engine.isWebGPU) {
132
+ this._uBuffer = new UniformBuffer(this._engine);
133
+ this._uBuffer.addUniform("invViewProjMatrix", 16);
134
+ this._uBuffer.addUniform("startVertexIndex", 1);
135
+ this._uBuffer.addUniform("step", 1);
136
+ this._uBuffer.addUniform("tesselation", 1);
137
+ this._uBuffer.update();
138
+ this._createComputeShader();
139
+ }
140
+ else {
141
+ this._copyTexture = new CopyTextureToTexture(this._engine, false, true);
142
+ this._createFallbackTextures();
143
+ }
144
+ this._tesselation = tesselation;
145
+ this._createGeometry();
146
+ }
147
+ /**
148
+ * Checks if the lighting volume is ready to be updated.
149
+ * @returns True if the volume is ready to be updated.
150
+ */
151
+ isReady() {
152
+ let isReady = this._mesh.isReady(true);
153
+ if (this._cs) {
154
+ isReady = this._cs.isReady() && isReady;
155
+ }
156
+ return isReady;
157
+ }
158
+ /**
159
+ * Updates the lighting volume mesh.
160
+ * @param forceUpdate If true, forces the update even if the frequency condition is not met.
161
+ */
162
+ update(forceUpdate = false) {
163
+ if (this._tesselation === 0 || !this._shadowGenerator) {
164
+ return;
165
+ }
166
+ if (!forceUpdate && !this._firstUpdate && (this.frequency === 0 || ++this._numFrames < this.frequency)) {
167
+ return;
168
+ }
169
+ this._numFrames = 0;
170
+ if (this._cs && this._uBuffer) {
171
+ const dispatchSize = Math.ceil((this._tesselation + 1) / 8);
172
+ const viewProjMatrix = this._shadowGenerator.getTransformMatrix();
173
+ viewProjMatrix.invertToRef(InvViewProjMatrix);
174
+ this._uBuffer.updateMatrix("invViewProjMatrix", InvViewProjMatrix);
175
+ this._uBuffer.update();
176
+ this._engine._debugPushGroup?.(`Update lighting volume (${this._name})`, 1);
177
+ this._cs.dispatch(dispatchSize, dispatchSize, 1);
178
+ this._engine._debugPopGroup?.(1);
179
+ this._firstUpdate = false;
180
+ }
181
+ else {
182
+ try {
183
+ void this._fallbackReadPixelAsync();
184
+ }
185
+ catch {
186
+ this._readPixelPromise = null;
187
+ }
188
+ }
189
+ }
190
+ /**
191
+ * Disposes the lighting volume and associated resources.
192
+ */
193
+ dispose() {
194
+ this._readPixelAbortController?.abort(new AbortError("LightingVolume is disposed"));
195
+ this._readPixelAbortController = null;
196
+ this._mesh.dispose();
197
+ if (this._fallbackTexture) {
198
+ this._fallbackTexture._texture = null;
199
+ }
200
+ this._fallbackTexture?.dispose();
201
+ this._copyTexture?.dispose();
202
+ this._storageBuffer?.dispose();
203
+ this._uBuffer?.dispose();
204
+ this._depthCopy?.dispose();
205
+ }
206
+ _createComputeShader() {
207
+ this._cs = new ComputeShader("createLightVolume", this._engine, "lightingVolume", {
208
+ bindingsMapping: {
209
+ shadowMap: { group: 0, binding: 0 },
210
+ params: { group: 0, binding: 1 },
211
+ positions: { group: 0, binding: 2 },
212
+ },
213
+ defines: !this._buildFullVolume ? ["#define KEEP_EDGES", "#define MOVE_FAR_DEPTH_TO_NEAR"] : undefined,
214
+ });
215
+ if (this._shadowGenerator) {
216
+ const depthTexture = this._shadowGenerator.getShadowMap()?.depthStencilTexture;
217
+ if (depthTexture) {
218
+ this._cs.setInternalTexture("shadowMap", depthTexture);
219
+ }
220
+ }
221
+ if (this._uBuffer) {
222
+ this._cs.setUniformBuffer("params", this._uBuffer);
223
+ }
224
+ if (this._storageBuffer) {
225
+ this._cs.setStorageBuffer("positions", this._storageBuffer);
226
+ }
227
+ }
228
+ _createFallbackTextures() {
229
+ if (!this._shadowGenerator) {
230
+ return;
231
+ }
232
+ this._readPixelAbortController?.abort(new AbortError("Fallback textures are being (re)created"));
233
+ this._readPixelAbortController = new AbortController();
234
+ const mapSize = this._shadowGenerator.mapSize;
235
+ this._depthCopy?.dispose();
236
+ this._depthCopy = this._engine.createRenderTargetTexture({ width: mapSize, height: mapSize }, {
237
+ type: 1,
238
+ format: 6,
239
+ samples: 1,
240
+ label: `${this._name} - fallback internal texture`,
241
+ generateDepthBuffer: false,
242
+ });
243
+ this._fallbackTexture?.dispose();
244
+ this._fallbackTexture = new BaseTexture(this._scene, this._depthCopy.texture);
245
+ this._fallbackTexture.name = `${this._name} - fallback texture`;
246
+ }
247
+ async _fallbackReadPixelAsync() {
248
+ if (this._readPixelPromise || !this._fallbackTexture || !this._copyTexture) {
249
+ return;
250
+ }
251
+ const abortController = this._readPixelAbortController;
252
+ abortController?.signal.throwIfAborted();
253
+ const engine = this._engine;
254
+ const shadowGenerator = this._shadowGenerator;
255
+ const shadowMapDepthTexture = shadowGenerator?.getShadowMap()?.depthStencilTexture;
256
+ if (!shadowMapDepthTexture) {
257
+ return;
258
+ }
259
+ // Copies the shadow map of the shadow generator into _depthCopy
260
+ // That's because we can't read from a depth attachment texture in WebGL. We must first copy it to a regular texture.
261
+ engine.updateTextureSamplingMode(1, shadowMapDepthTexture);
262
+ engine.updateTextureComparisonFunction(shadowMapDepthTexture, 0);
263
+ this._copyTexture.copy(shadowMapDepthTexture, this._depthCopy);
264
+ engine.updateTextureComparisonFunction(shadowMapDepthTexture, 513);
265
+ // Gets the texture from GPU to CPU
266
+ this._readPixelPromise = this._fallbackTexture.readPixels(0, 0, undefined, true, false);
267
+ if (!this._readPixelPromise) {
268
+ return;
269
+ }
270
+ const buffer = await this._readPixelPromise;
271
+ abortController?.signal.throwIfAborted();
272
+ const depthValues = buffer;
273
+ const positions = this._mesh.getVerticesData("position");
274
+ const numTesselation = this._tesselation;
275
+ const startPos = this._buildFullVolume ? (numTesselation + 1) * 4 * 3 : 4 * 3;
276
+ const mapSize = shadowGenerator.mapSize;
277
+ const step = (mapSize - 1) / numTesselation;
278
+ if (!positions) {
279
+ this._readPixelPromise = null;
280
+ return;
281
+ }
282
+ const halfTesselation = numTesselation / 2;
283
+ const invViewProjMatrix = shadowGenerator.getTransformMatrix().clone();
284
+ invViewProjMatrix.invertToRef(invViewProjMatrix);
285
+ const factor = 4;
286
+ let posIndex = startPos;
287
+ let stepY = 0;
288
+ for (let y = 0; y < numTesselation + 1; ++y) {
289
+ for (let x = 0; x < numTesselation + 1; ++x) {
290
+ let depth = depthValues[Math.floor(mapSize * Math.floor(stepY) + x * step) * factor];
291
+ if (!this._buildFullVolume) {
292
+ if (y === 0 || x === 0 || y === numTesselation || x === numTesselation) {
293
+ posIndex += 3;
294
+ continue;
295
+ }
296
+ if (depth === 1) {
297
+ depth = 0;
298
+ }
299
+ }
300
+ TmpVec3.set((x - halfTesselation) / halfTesselation, (y - halfTesselation) / halfTesselation, -1 + 2 * depth);
301
+ Vector3.TransformCoordinatesToRef(TmpVec3, invViewProjMatrix, TmpVec3);
302
+ positions[posIndex] = TmpVec3.x;
303
+ positions[posIndex + 1] = TmpVec3.y;
304
+ positions[posIndex + 2] = TmpVec3.z;
305
+ posIndex += 3;
306
+ }
307
+ stepY += step;
308
+ }
309
+ this._mesh.setVerticesData("position", positions);
310
+ this._readPixelPromise = null;
311
+ this._firstUpdate = false;
312
+ }
313
+ _createGeometry() {
314
+ if (!this._light) {
315
+ return;
316
+ }
317
+ this._tesselation = Math.max(Math.ceil(this._tesselation) & ~1, 2);
318
+ const light = this._light;
319
+ const min = new Vector3(light.orthoLeft, light.orthoBottom, light.shadowMinZ ?? 0);
320
+ const max = new Vector3(light.orthoRight, light.orthoTop, light.shadowMaxZ ?? 10000);
321
+ const invViewMatrix = Matrix.LookAtLH(light.position, light.position.add(light.direction), Vector3.UpReadOnly);
322
+ invViewMatrix.invertToRef(invViewMatrix);
323
+ const positions = [];
324
+ const indices = [];
325
+ const numTesselation = this._tesselation;
326
+ const stepX = (max.x - min.x) / numTesselation;
327
+ const stepY = (max.y - min.y) / numTesselation;
328
+ const v = new Vector3();
329
+ const startFarIndices = this._buildFullVolume ? (numTesselation + 1) * 4 : 4;
330
+ if (this._buildFullVolume) {
331
+ let startIndices = 0;
332
+ // Right faces of the frustum
333
+ for (let i = 0; i <= numTesselation; ++i) {
334
+ v.set(max.x, min.y + i * stepY, min.z);
335
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
336
+ positions.push(p.x, p.y, p.z);
337
+ if (i < numTesselation) {
338
+ indices.push(startIndices + i, startFarIndices + numTesselation + (i + 1) * (numTesselation + 1), startFarIndices + numTesselation + i * (numTesselation + 1));
339
+ indices.push(startIndices + i, startIndices + i + 1, startFarIndices + numTesselation + (i + 1) * (numTesselation + 1));
340
+ }
341
+ }
342
+ const n0 = 0;
343
+ const n1 = positions.length / 3 - 1;
344
+ const n2 = n1 + 1;
345
+ startIndices = positions.length / 3;
346
+ // Left faces of the frustum
347
+ for (let i = 0; i <= numTesselation; ++i) {
348
+ v.set(min.x, min.y + i * stepY, min.z);
349
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
350
+ positions.push(p.x, p.y, p.z);
351
+ if (i < numTesselation) {
352
+ indices.push(startIndices + i, startFarIndices + 0 + i * (numTesselation + 1), startFarIndices + 0 + (i + 1) * (numTesselation + 1));
353
+ indices.push(startIndices + i, startFarIndices + 0 + (i + 1) * (numTesselation + 1), startIndices + i + 1);
354
+ }
355
+ }
356
+ const n3 = positions.length / 3 - 1;
357
+ startIndices = positions.length / 3;
358
+ // Bottom faces of the frustum
359
+ for (let i = 0; i <= numTesselation; ++i) {
360
+ v.set(min.x + i * stepX, min.y, min.z);
361
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
362
+ positions.push(p.x, p.y, p.z);
363
+ if (i < numTesselation) {
364
+ indices.push(startIndices + i, startIndices + i + 1, startFarIndices + i + 0 * (numTesselation + 1));
365
+ indices.push(startIndices + i + 1, startFarIndices + i + 1 + 0 * (numTesselation + 1), startFarIndices + i + 0 * (numTesselation + 1));
366
+ }
367
+ }
368
+ startIndices = positions.length / 3;
369
+ // Top faces of the frustum
370
+ for (let i = 0; i <= numTesselation; ++i) {
371
+ v.set(min.x + i * stepX, max.y, min.z);
372
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
373
+ positions.push(p.x, p.y, p.z);
374
+ if (i < numTesselation) {
375
+ indices.push(startIndices + i, startFarIndices + i + numTesselation * (numTesselation + 1), startIndices + i + 1);
376
+ indices.push(startIndices + i + 1, startFarIndices + i + numTesselation * (numTesselation + 1), startFarIndices + i + 1 + numTesselation * (numTesselation + 1));
377
+ }
378
+ }
379
+ startIndices = positions.length / 3;
380
+ // Near faces of the frustum
381
+ indices.push(n0, n2, n1);
382
+ indices.push(n2, n3, n1);
383
+ }
384
+ else {
385
+ let p;
386
+ v.set(max.x, min.y, min.z);
387
+ p = Vector3.TransformCoordinates(v, invViewMatrix);
388
+ positions.push(p.x, p.y, p.z);
389
+ v.set(max.x, max.y, min.z);
390
+ p = Vector3.TransformCoordinates(v, invViewMatrix);
391
+ positions.push(p.x, p.y, p.z);
392
+ v.set(min.x, min.y, min.z);
393
+ p = Vector3.TransformCoordinates(v, invViewMatrix);
394
+ positions.push(p.x, p.y, p.z);
395
+ v.set(min.x, max.y, min.z);
396
+ p = Vector3.TransformCoordinates(v, invViewMatrix);
397
+ positions.push(p.x, p.y, p.z);
398
+ indices.push(0, 2, 1);
399
+ indices.push(2, 3, 1);
400
+ }
401
+ // Tesselate the near plane
402
+ let y = min.y;
403
+ for (let iy = 0; iy <= numTesselation; ++iy) {
404
+ let x = min.x;
405
+ for (let ix = 0; ix <= numTesselation; ++ix) {
406
+ v.set(x, y, min.z);
407
+ const p = Vector3.TransformCoordinates(v, invViewMatrix);
408
+ positions.push(p.x, p.y, p.z);
409
+ if (ix < numTesselation && iy < numTesselation) {
410
+ indices.push(startFarIndices + ix + iy * (numTesselation + 1), startFarIndices + ix + 1 + iy * (numTesselation + 1), startFarIndices + ix + 1 + (iy + 1) * (numTesselation + 1));
411
+ indices.push(startFarIndices + ix + iy * (numTesselation + 1), startFarIndices + ix + 1 + (iy + 1) * (numTesselation + 1), startFarIndices + ix + (iy + 1) * (numTesselation + 1));
412
+ }
413
+ x += stepX;
414
+ }
415
+ y += stepY;
416
+ }
417
+ if (this._uBuffer && this._cs) {
418
+ const webGPUEngine = this._engine;
419
+ this._storageBuffer?.dispose();
420
+ this._storageBuffer = new StorageBuffer(webGPUEngine, positions.length * 4, 8 | 3);
421
+ this._storageBuffer.update(positions);
422
+ const vertexBuffer = new VertexBuffer(webGPUEngine, this._storageBuffer.getBuffer(), "position");
423
+ this._mesh.setVerticesBuffer(vertexBuffer);
424
+ this._cs.setStorageBuffer("positions", this._storageBuffer);
425
+ this._uBuffer.updateUInt("startVertexIndex", this._buildFullVolume ? (numTesselation + 1) * 4 * 3 : 4 * 3);
426
+ this._uBuffer.updateFloat("step", ((this._shadowGenerator?.mapSize ?? 128) - 1) / numTesselation);
427
+ this._uBuffer.updateUInt("tesselation", numTesselation);
428
+ }
429
+ else {
430
+ this._mesh.setVerticesData("position", positions);
431
+ }
432
+ this._mesh.setIndices(indices, positions.length / 3);
433
+ }
434
+ }
435
+ //# sourceMappingURL=lightingVolume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lightingVolume.js","sourceRoot":"","sources":["../../../../dev/core/src/Lights/lightingVolume.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,yBAAwB;AAC7C,OAAO,EAAE,SAAS,EAAE,gCAA+B;AACnD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,gCAA+B;AACzD,OAAO,EAAE,gBAAgB,EAAE,8BAAqC;AAChE,OAAO,EAAE,IAAI,EAAE,0BAAyB;AACxC,OAAO,EAAE,aAAa,EAAE,oCAAmC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,wCAAuC;AACtE,OAAO,EAAE,aAAa,EAAE,sCAAqC;AAC7D,OAAO,EAAE,aAAa,EAAE,oCAAmC;AAC3D,OAAO,EAAE,WAAW,EAAE,6CAA4C;AAClE,OAAO,EAAE,YAAY,EAAE,6BAA4B;AAEnD,kDAAiD;AAEjD,MAAM,iBAAiB,GAAG,IAAI,MAAM,EAAE,CAAC;AACvC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B;;GAEG;AACH,MAAM,OAAO,cAAc;IAkBvB;;OAEG;IACH,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,gBAAiB,CAAC;IAClC,CAAC;IAED,IAAW,eAAe,CAAC,EAAmB;QAC1C,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QAE5B,IAAI,CAAC,CAAC,KAAK,YAAY,gBAAgB,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,KAAK,qCAAqC,CAAC,CAAC;QAC3F,CAAC;QAED,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QAEpB,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACnC,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,EAAE,mBAAmB,CAAC;QAC/E,IAAI,IAAI,CAAC,GAAG,IAAI,YAAY,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC3D,CAAC;IACL,CAAC;IAGD;;OAEG;IACH,IAAW,WAAW;QAClB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC7B,CAAC;IAED,IAAW,WAAW,CAAC,CAAS;QAC5B,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,eAAe,EAAE,CAAC;IAC3B,CAAC;IAGD;;OAEG;IACH,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IACjC,CAAC;IAED,IAAW,eAAe,CAAC,KAAc;QACrC,IAAI,IAAI,CAAC,gBAAgB,KAAK,KAAK,EAAE,CAAC;YAClC,OAAO;QACX,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACxB,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAID;;OAEG;IACH,IAAW,SAAS;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;IAED,IAAW,SAAS,CAAC,KAAa;QAC9B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,IAAW,IAAI,CAAC,IAAY;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAC3B,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,IAAW,WAAW;QAClB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC7B,CAAC;IAED;;;;;;OAMG;IACH,YAAY,IAAY,EAAE,KAAY,EAAE,eAAiC,EAAE,WAAW,GAAG,EAAE;QAxHnF,sBAAiB,GAAuC,IAAI,CAAC;QAC7D,8BAAyB,GAA8B,IAAI,CAAC;QAC5D,eAAU,GAAG,CAAC,CAAC;QACf,iBAAY,GAAG,IAAI,CAAC;QAgCpB,iBAAY,GAAG,CAAC,CAAC;QAajB,qBAAgB,GAAG,KAAK,CAAC;QA6BzB,eAAU,GAAG,CAAC,CAAC;QA4CnB,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAEvE,IAAI,KAAK,IAAI,CAAC,CAAC,KAAK,YAAY,gBAAgB,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,qCAAqC,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,KAAyB,CAAC;QAExC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QAEpB,IAAI,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAEzD,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAEhD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;YAClD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;YAChD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACpC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;YAC3C,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAEvB,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAChC,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,YAAY,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACxE,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,eAAe,EAAE,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACI,OAAO;QACV,IAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACX,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,OAAO,CAAC;QAC5C,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,WAAW,GAAG,KAAK;QAC7B,IAAI,IAAI,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACpD,OAAO;QACX,CAAC;QAED,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACrG,OAAO;QACX,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QAEpB,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAE5D,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,CAAC;YAClE,cAAc,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;YAE9C,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;YACnE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAEvB,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,2BAA2B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;YAC5E,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;YACjD,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC;YAEjC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC9B,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC;gBACD,KAAK,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACL,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;YAClC,CAAC;QACL,CAAC;IACL,CAAC;IAED;;OAEG;IACI,OAAO;QACV,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACpF,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,CAAC,gBAAgB,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,gBAAgB,EAAE,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;IAC/B,CAAC;IAEO,oBAAoB;QACxB,IAAI,CAAC,GAAG,GAAG,IAAI,aAAa,CAAC,mBAAmB,EAAE,IAAI,CAAC,OAAO,EAAE,gBAAgB,EAAE;YAC9E,eAAe,EAAE;gBACb,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;gBACnC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;gBAChC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;aACtC;YACD,OAAO,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,oBAAoB,EAAE,gCAAgC,CAAC,CAAC,CAAC,CAAC,SAAS;SACzG,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,EAAE,mBAAmB,CAAC;YAC/E,IAAI,YAAY,EAAE,CAAC;gBACf,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAC3D,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAChE,CAAC;IACL,CAAC;IAEO,uBAAuB;QAC3B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACzB,OAAO;QACX,CAAC;QAED,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,yCAAyC,CAAC,CAAC,CAAC;QACjG,IAAI,CAAC,yBAAyB,GAAG,IAAI,eAAe,EAAE,CAAC;QAEvD,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;QAE9C,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,yBAAyB,CACpD,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EACnC;YACI,IAAI,EAAE,SAAS,CAAC,iBAAiB;YACjC,MAAM,EAAE,SAAS,CAAC,iBAAiB;YACnC,OAAO,EAAE,CAAC;YACV,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,8BAA8B;YAClD,mBAAmB,EAAE,KAAK;SAC7B,CACJ,CAAC;QAEF,IAAI,CAAC,gBAAgB,EAAE,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC,gBAAgB,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC9E,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,qBAAqB,CAAC;IACpE,CAAC;IAEO,KAAK,CAAC,uBAAuB;QACjC,IAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACzE,OAAO;QACX,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,CAAC,yBAAyB,CAAC;QAEvD,eAAe,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC;QAEzC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAiB,CAAC;QAEtC,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAC9C,MAAM,qBAAqB,GAAG,eAAe,EAAE,YAAY,EAAE,EAAE,mBAAmB,CAAC;QAEnF,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACzB,OAAO;QACX,CAAC;QAED,gEAAgE;QAChE,qHAAqH;QACrH,MAAM,CAAC,yBAAyB,CAAC,SAAS,CAAC,4BAA4B,EAAE,qBAAqB,CAAC,CAAC;QAChG,MAAM,CAAC,+BAA+B,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC;QAEjE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAE/D,MAAM,CAAC,+BAA+B,CAAC,qBAAqB,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAE9E,mCAAmC;QACnC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACxF,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC1B,OAAO;QACX,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;QAE5C,eAAe,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC;QAEzC,MAAM,WAAW,GAAG,MAAsB,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC9E,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC;QACxC,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC;QAE5C,IAAI,CAAC,SAAS,EAAE,CAAC;YACb,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;YAC9B,OAAO;QACX,CAAC;QAED,MAAM,eAAe,GAAG,cAAc,GAAG,CAAC,CAAC;QAE3C,MAAM,iBAAiB,GAAG,eAAe,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,CAAC;QACvE,iBAAiB,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAEjD,MAAM,MAAM,GAAG,CAAC,CAAC;QAEjB,IAAI,QAAQ,GAAG,QAAQ,CAAC;QACxB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC1C,IAAI,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;gBACrF,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBACzB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,cAAc,IAAI,CAAC,KAAK,cAAc,EAAE,CAAC;wBACrE,QAAQ,IAAI,CAAC,CAAC;wBACd,SAAS;oBACb,CAAC;oBACD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;wBACd,KAAK,GAAG,CAAC,CAAC;oBACd,CAAC;gBACL,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,GAAG,eAAe,EAAE,CAAC,CAAC,GAAG,eAAe,CAAC,GAAG,eAAe,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;gBAE9G,OAAO,CAAC,yBAAyB,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;gBAEvE,SAAS,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;gBAChC,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;gBACpC,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;gBACpC,QAAQ,IAAI,CAAC,CAAC;YAClB,CAAC;YACD,KAAK,IAAI,IAAI,CAAC;QAClB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAElD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC9B,CAAC;IAEO,eAAe;QACnB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,OAAO;QACX,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEnE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAE1B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;QACtG,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;QAEpG,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QAC/G,aAAa,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAEzC,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC;QACzC,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;QAC/C,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;QAC/C,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;QAExB,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7E,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,YAAY,GAAG,CAAC,CAAC;YAErB,6BAA6B;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC;gBACvC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAEvC,MAAM,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;gBACzD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAE9B,IAAI,CAAC,GAAG,cAAc,EAAE,CAAC;oBACrB,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,eAAe,GAAG,cAAc,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,eAAe,GAAG,cAAc,GAAG,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;oBAC/J,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,YAAY,GAAG,CAAC,GAAG,CAAC,EAAE,eAAe,GAAG,cAAc,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC5H,CAAC;YACL,CAAC;YAED,MAAM,EAAE,GAAG,CAAC,CAAC;YACb,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAElB,YAAY,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YAEpC,4BAA4B;YAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC;gBACvC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAEvC,MAAM,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;gBACzD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAE9B,IAAI,CAAC,GAAG,cAAc,EAAE,CAAC;oBACrB,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,eAAe,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;oBACrI,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,eAAe,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC/G,CAAC;YACL,CAAC;YAED,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;YAEpC,YAAY,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YAEpC,8BAA8B;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC;gBACvC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAEvC,MAAM,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;gBACzD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAE9B,IAAI,CAAC,GAAG,cAAc,EAAE,CAAC;oBACrB,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,YAAY,GAAG,CAAC,GAAG,CAAC,EAAE,eAAe,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;oBACrG,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,GAAG,CAAC,EAAE,eAAe,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC3I,CAAC;YACL,CAAC;YAED,YAAY,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YAEpC,2BAA2B;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC;gBACvC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAEvC,MAAM,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;gBACzD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAE9B,IAAI,CAAC,GAAG,cAAc,EAAE,CAAC;oBACrB,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,eAAe,GAAG,CAAC,GAAG,cAAc,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;oBAClH,OAAO,CAAC,IAAI,CACR,YAAY,GAAG,CAAC,GAAG,CAAC,EACpB,eAAe,GAAG,CAAC,GAAG,cAAc,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAC3D,eAAe,GAAG,CAAC,GAAG,CAAC,GAAG,cAAc,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAClE,CAAC;gBACN,CAAC;YACL,CAAC;YAED,YAAY,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YAEpC,4BAA4B;YAC5B,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACJ,IAAI,CAAU,CAAC;YAEf,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9B,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9B,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9B,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9B,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC;QAED,2BAA2B;QAC3B,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QACd,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,cAAc,EAAE,EAAE,EAAE,EAAE,CAAC;YAC1C,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACd,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,cAAc,EAAE,EAAE,EAAE,EAAE,CAAC;gBAC1C,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAEnB,MAAM,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;gBACzD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAE9B,IAAI,EAAE,GAAG,cAAc,IAAI,EAAE,GAAG,cAAc,EAAE,CAAC;oBAC7C,OAAO,CAAC,IAAI,CACR,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAChD,eAAe,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EACpD,eAAe,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAC7D,CAAC;oBACF,OAAO,CAAC,IAAI,CACR,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAChD,eAAe,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,EAC1D,eAAe,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CACzD,CAAC;gBACN,CAAC;gBACD,CAAC,IAAI,KAAK,CAAC;YACf,CAAC;YACD,CAAC,IAAI,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAuB,CAAC;YAElD,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,CAAC;YAC/B,IAAI,CAAC,cAAc,GAAG,IAAI,aAAa,CAAC,YAAY,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,SAAS,CAAC,0BAA0B,GAAG,SAAS,CAAC,6BAA6B,CAAC,CAAC;YAE5J,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAEtC,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,EAAE,UAAU,CAAC,CAAC;YAEjG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;YAE3C,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;YAE5D,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,kBAAkB,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3G,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC;YAClG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;CACJ","sourcesContent":["import type { AbstractEngine, Engine, Nullable, RenderTargetWrapper, Scene, ShadowGenerator, WebGPUEngine } from \"core/index\";\r\nimport { AbortError } from \"core/Misc/error\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Matrix, Vector3 } from \"core/Maths/math.vector\";\r\nimport { DirectionalLight } from \"core/Lights/directionalLight\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport { ComputeShader } from \"core/Compute/computeShader\";\r\nimport { CopyTextureToTexture } from \"core/Misc/copyTextureToTexture\";\r\nimport { UniformBuffer } from \"core/Materials/uniformBuffer\";\r\nimport { StorageBuffer } from \"core/Buffers/storageBuffer\";\r\nimport { BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { VertexBuffer } from \"core/Buffers/buffer\";\r\n\r\nimport \"core/ShadersWGSL/lightingVolume.compute\";\r\n\r\nconst InvViewProjMatrix = new Matrix();\r\nconst TmpVec3 = new Vector3();\r\n\r\n/**\r\n * Class used to create a lighting volume from a directional light's shadow generator.\r\n */\r\nexport class LightingVolume {\r\n private readonly _engine: AbstractEngine;\r\n private readonly _scene: Scene;\r\n private readonly _mesh: Mesh;\r\n private readonly _copyTexture?: CopyTextureToTexture;\r\n private readonly _uBuffer?: UniformBuffer;\r\n private _name: string;\r\n private _cs?: ComputeShader;\r\n private _light?: DirectionalLight;\r\n private _fallbackTexture?: BaseTexture;\r\n private _storageBuffer?: StorageBuffer;\r\n private _depthCopy?: RenderTargetWrapper;\r\n private _readPixelPromise: Nullable<Promise<ArrayBufferView>> = null;\r\n private _readPixelAbortController: Nullable<AbortController> = null;\r\n private _numFrames = 0;\r\n private _firstUpdate = true;\r\n\r\n private _shadowGenerator?: ShadowGenerator;\r\n /**\r\n * The shadow generator used to create the lighting volume.\r\n */\r\n public get shadowGenerator() {\r\n return this._shadowGenerator!;\r\n }\r\n\r\n public set shadowGenerator(sg: ShadowGenerator) {\r\n const light = sg.getLight();\r\n\r\n if (!(light instanceof DirectionalLight)) {\r\n throw new Error(`LightingVolumeMesh ${this._name}: light must be a directional light`);\r\n }\r\n\r\n this._shadowGenerator = sg;\r\n this._light = light;\r\n\r\n this._createGeometry();\r\n\r\n if (!this._engine.isWebGPU) {\r\n this._createFallbackTextures();\r\n }\r\n\r\n const depthTexture = this._shadowGenerator.getShadowMap()?.depthStencilTexture;\r\n if (this._cs && depthTexture) {\r\n this._cs.setInternalTexture(\"shadowMap\", depthTexture);\r\n }\r\n }\r\n\r\n private _tesselation = 0;\r\n /**\r\n * The tesselation level of the lighting volume.\r\n */\r\n public get tesselation() {\r\n return this._tesselation;\r\n }\r\n\r\n public set tesselation(n: number) {\r\n this._tesselation = n;\r\n this._createGeometry();\r\n }\r\n\r\n private _buildFullVolume = false;\r\n /**\r\n * Indicates whether to build the full volume (true) or only the near plane (false). Default is false.\r\n */\r\n public get buildFullVolume() {\r\n return this._buildFullVolume;\r\n }\r\n\r\n public set buildFullVolume(value: boolean) {\r\n if (this._buildFullVolume === value) {\r\n return;\r\n }\r\n this._buildFullVolume = value;\r\n this._createGeometry();\r\n if (this._engine.isWebGPU) {\r\n this._createComputeShader();\r\n }\r\n this._firstUpdate = true;\r\n }\r\n\r\n /**\r\n * The mesh used as a support for the lighting volume.\r\n * Note that this mesh is not automatically added to the scene's mesh array.\r\n * If you want to render it, you need to add it manually.\r\n */\r\n public get mesh() {\r\n return this._mesh;\r\n }\r\n\r\n private _frequency = 1;\r\n\r\n /**\r\n * The frequency (in number of times you call updateMesh) at which the lighting volume is updated.\r\n */\r\n public get frequency() {\r\n return this._frequency;\r\n }\r\n\r\n public set frequency(value: number) {\r\n this._frequency = value;\r\n this._firstUpdate = true;\r\n }\r\n\r\n /**\r\n * The name of the lighting volume.\r\n */\r\n public get name() {\r\n return this._name;\r\n }\r\n\r\n public set name(name: string) {\r\n this._name = name;\r\n if (this._mesh) {\r\n this._mesh.name = name;\r\n }\r\n }\r\n\r\n /**\r\n * Indicates whether this is the first update of the lighting volume.\r\n * If true, the volume has not yet been updated for the first time.\r\n */\r\n public get firstUpdate() {\r\n return this._firstUpdate;\r\n }\r\n\r\n /**\r\n * Creates a new LightingVolume.\r\n * @param name The name of the lighting volume.\r\n * @param scene The scene the lighting volume belongs to.\r\n * @param shadowGenerator The shadow generator used to create the lighting volume. This is optional in the constructor, but must be set before calling updateMesh.\r\n * @param tesselation The tesselation level of the lighting volume (default: 64).\r\n */\r\n constructor(name: string, scene: Scene, shadowGenerator?: ShadowGenerator, tesselation = 64) {\r\n const light = shadowGenerator ? shadowGenerator.getLight() : undefined;\r\n\r\n if (light && !(light instanceof DirectionalLight)) {\r\n throw new Error(`LightingVolumeMesh ${name}: light must be a directional light`);\r\n }\r\n\r\n this._name = name;\r\n this._shadowGenerator = shadowGenerator;\r\n this._light = light as DirectionalLight;\r\n\r\n this._engine = scene.getEngine();\r\n this._scene = scene;\r\n\r\n this._mesh = new Mesh(name, this._scene);\r\n scene.meshes.splice(scene.meshes.indexOf(this._mesh), 1);\r\n\r\n if (this._engine.isWebGPU) {\r\n this._uBuffer = new UniformBuffer(this._engine);\r\n\r\n this._uBuffer.addUniform(\"invViewProjMatrix\", 16);\r\n this._uBuffer.addUniform(\"startVertexIndex\", 1);\r\n this._uBuffer.addUniform(\"step\", 1);\r\n this._uBuffer.addUniform(\"tesselation\", 1);\r\n this._uBuffer.update();\r\n\r\n this._createComputeShader();\r\n } else {\r\n this._copyTexture = new CopyTextureToTexture(this._engine, false, true);\r\n this._createFallbackTextures();\r\n }\r\n\r\n this._tesselation = tesselation;\r\n this._createGeometry();\r\n }\r\n\r\n /**\r\n * Checks if the lighting volume is ready to be updated.\r\n * @returns True if the volume is ready to be updated.\r\n */\r\n public isReady() {\r\n let isReady = this._mesh.isReady(true);\r\n if (this._cs) {\r\n isReady = this._cs.isReady() && isReady;\r\n }\r\n return isReady;\r\n }\r\n\r\n /**\r\n * Updates the lighting volume mesh.\r\n * @param forceUpdate If true, forces the update even if the frequency condition is not met.\r\n */\r\n public update(forceUpdate = false) {\r\n if (this._tesselation === 0 || !this._shadowGenerator) {\r\n return;\r\n }\r\n\r\n if (!forceUpdate && !this._firstUpdate && (this.frequency === 0 || ++this._numFrames < this.frequency)) {\r\n return;\r\n }\r\n\r\n this._numFrames = 0;\r\n\r\n if (this._cs && this._uBuffer) {\r\n const dispatchSize = Math.ceil((this._tesselation + 1) / 8);\r\n\r\n const viewProjMatrix = this._shadowGenerator.getTransformMatrix();\r\n viewProjMatrix.invertToRef(InvViewProjMatrix);\r\n\r\n this._uBuffer.updateMatrix(\"invViewProjMatrix\", InvViewProjMatrix);\r\n this._uBuffer.update();\r\n\r\n this._engine._debugPushGroup?.(`Update lighting volume (${this._name})`, 1);\r\n this._cs.dispatch(dispatchSize, dispatchSize, 1);\r\n this._engine._debugPopGroup?.(1);\r\n\r\n this._firstUpdate = false;\r\n } else {\r\n try {\r\n void this._fallbackReadPixelAsync();\r\n } catch {\r\n this._readPixelPromise = null;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Disposes the lighting volume and associated resources.\r\n */\r\n public dispose() {\r\n this._readPixelAbortController?.abort(new AbortError(\"LightingVolume is disposed\"));\r\n this._readPixelAbortController = null;\r\n this._mesh.dispose();\r\n if (this._fallbackTexture) {\r\n this._fallbackTexture._texture = null;\r\n }\r\n this._fallbackTexture?.dispose();\r\n this._copyTexture?.dispose();\r\n this._storageBuffer?.dispose();\r\n this._uBuffer?.dispose();\r\n this._depthCopy?.dispose();\r\n }\r\n\r\n private _createComputeShader() {\r\n this._cs = new ComputeShader(\"createLightVolume\", this._engine, \"lightingVolume\", {\r\n bindingsMapping: {\r\n shadowMap: { group: 0, binding: 0 },\r\n params: { group: 0, binding: 1 },\r\n positions: { group: 0, binding: 2 },\r\n },\r\n defines: !this._buildFullVolume ? [\"#define KEEP_EDGES\", \"#define MOVE_FAR_DEPTH_TO_NEAR\"] : undefined,\r\n });\r\n\r\n if (this._shadowGenerator) {\r\n const depthTexture = this._shadowGenerator.getShadowMap()?.depthStencilTexture;\r\n if (depthTexture) {\r\n this._cs.setInternalTexture(\"shadowMap\", depthTexture);\r\n }\r\n }\r\n\r\n if (this._uBuffer) {\r\n this._cs.setUniformBuffer(\"params\", this._uBuffer);\r\n }\r\n if (this._storageBuffer) {\r\n this._cs.setStorageBuffer(\"positions\", this._storageBuffer);\r\n }\r\n }\r\n\r\n private _createFallbackTextures() {\r\n if (!this._shadowGenerator) {\r\n return;\r\n }\r\n\r\n this._readPixelAbortController?.abort(new AbortError(\"Fallback textures are being (re)created\"));\r\n this._readPixelAbortController = new AbortController();\r\n\r\n const mapSize = this._shadowGenerator.mapSize;\r\n\r\n this._depthCopy?.dispose();\r\n this._depthCopy = this._engine.createRenderTargetTexture(\r\n { width: mapSize, height: mapSize },\r\n {\r\n type: Constants.TEXTURETYPE_FLOAT,\r\n format: Constants.TEXTUREFORMAT_RED,\r\n samples: 1,\r\n label: `${this._name} - fallback internal texture`,\r\n generateDepthBuffer: false,\r\n }\r\n );\r\n\r\n this._fallbackTexture?.dispose();\r\n this._fallbackTexture = new BaseTexture(this._scene, this._depthCopy.texture);\r\n this._fallbackTexture.name = `${this._name} - fallback texture`;\r\n }\r\n\r\n private async _fallbackReadPixelAsync() {\r\n if (this._readPixelPromise || !this._fallbackTexture || !this._copyTexture) {\r\n return;\r\n }\r\n\r\n const abortController = this._readPixelAbortController;\r\n\r\n abortController?.signal.throwIfAborted();\r\n\r\n const engine = this._engine as Engine;\r\n\r\n const shadowGenerator = this._shadowGenerator;\r\n const shadowMapDepthTexture = shadowGenerator?.getShadowMap()?.depthStencilTexture;\r\n\r\n if (!shadowMapDepthTexture) {\r\n return;\r\n }\r\n\r\n // Copies the shadow map of the shadow generator into _depthCopy\r\n // That's because we can't read from a depth attachment texture in WebGL. We must first copy it to a regular texture.\r\n engine.updateTextureSamplingMode(Constants.TEXTURE_NEAREST_SAMPLINGMODE, shadowMapDepthTexture);\r\n engine.updateTextureComparisonFunction(shadowMapDepthTexture, 0);\r\n\r\n this._copyTexture.copy(shadowMapDepthTexture, this._depthCopy);\r\n\r\n engine.updateTextureComparisonFunction(shadowMapDepthTexture, Constants.LESS);\r\n\r\n // Gets the texture from GPU to CPU\r\n this._readPixelPromise = this._fallbackTexture.readPixels(0, 0, undefined, true, false);\r\n if (!this._readPixelPromise) {\r\n return;\r\n }\r\n\r\n const buffer = await this._readPixelPromise;\r\n\r\n abortController?.signal.throwIfAborted();\r\n\r\n const depthValues = buffer as Float32Array;\r\n const positions = this._mesh.getVerticesData(\"position\");\r\n const numTesselation = this._tesselation;\r\n const startPos = this._buildFullVolume ? (numTesselation + 1) * 4 * 3 : 4 * 3;\r\n const mapSize = shadowGenerator.mapSize;\r\n const step = (mapSize - 1) / numTesselation;\r\n\r\n if (!positions) {\r\n this._readPixelPromise = null;\r\n return;\r\n }\r\n\r\n const halfTesselation = numTesselation / 2;\r\n\r\n const invViewProjMatrix = shadowGenerator.getTransformMatrix().clone();\r\n invViewProjMatrix.invertToRef(invViewProjMatrix);\r\n\r\n const factor = 4;\r\n\r\n let posIndex = startPos;\r\n let stepY = 0;\r\n for (let y = 0; y < numTesselation + 1; ++y) {\r\n for (let x = 0; x < numTesselation + 1; ++x) {\r\n let depth = depthValues[Math.floor(mapSize * Math.floor(stepY) + x * step) * factor];\r\n if (!this._buildFullVolume) {\r\n if (y === 0 || x === 0 || y === numTesselation || x === numTesselation) {\r\n posIndex += 3;\r\n continue;\r\n }\r\n if (depth === 1) {\r\n depth = 0;\r\n }\r\n }\r\n\r\n TmpVec3.set((x - halfTesselation) / halfTesselation, (y - halfTesselation) / halfTesselation, -1 + 2 * depth);\r\n\r\n Vector3.TransformCoordinatesToRef(TmpVec3, invViewProjMatrix, TmpVec3);\r\n\r\n positions[posIndex] = TmpVec3.x;\r\n positions[posIndex + 1] = TmpVec3.y;\r\n positions[posIndex + 2] = TmpVec3.z;\r\n posIndex += 3;\r\n }\r\n stepY += step;\r\n }\r\n\r\n this._mesh.setVerticesData(\"position\", positions);\r\n\r\n this._readPixelPromise = null;\r\n this._firstUpdate = false;\r\n }\r\n\r\n private _createGeometry() {\r\n if (!this._light) {\r\n return;\r\n }\r\n\r\n this._tesselation = Math.max(Math.ceil(this._tesselation) & ~1, 2);\r\n\r\n const light = this._light;\r\n\r\n const min = new Vector3(light.orthoLeft, light.orthoBottom, light.shadowMinZ ?? Constants.ShadowMinZ);\r\n const max = new Vector3(light.orthoRight, light.orthoTop, light.shadowMaxZ ?? Constants.ShadowMaxZ);\r\n\r\n const invViewMatrix = Matrix.LookAtLH(light.position, light.position.add(light.direction), Vector3.UpReadOnly);\r\n invViewMatrix.invertToRef(invViewMatrix);\r\n\r\n const positions: number[] = [];\r\n const indices: number[] = [];\r\n\r\n const numTesselation = this._tesselation;\r\n const stepX = (max.x - min.x) / numTesselation;\r\n const stepY = (max.y - min.y) / numTesselation;\r\n const v = new Vector3();\r\n\r\n const startFarIndices = this._buildFullVolume ? (numTesselation + 1) * 4 : 4;\r\n\r\n if (this._buildFullVolume) {\r\n let startIndices = 0;\r\n\r\n // Right faces of the frustum\r\n for (let i = 0; i <= numTesselation; ++i) {\r\n v.set(max.x, min.y + i * stepY, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (i < numTesselation) {\r\n indices.push(startIndices + i, startFarIndices + numTesselation + (i + 1) * (numTesselation + 1), startFarIndices + numTesselation + i * (numTesselation + 1));\r\n indices.push(startIndices + i, startIndices + i + 1, startFarIndices + numTesselation + (i + 1) * (numTesselation + 1));\r\n }\r\n }\r\n\r\n const n0 = 0;\r\n const n1 = positions.length / 3 - 1;\r\n const n2 = n1 + 1;\r\n\r\n startIndices = positions.length / 3;\r\n\r\n // Left faces of the frustum\r\n for (let i = 0; i <= numTesselation; ++i) {\r\n v.set(min.x, min.y + i * stepY, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (i < numTesselation) {\r\n indices.push(startIndices + i, startFarIndices + 0 + i * (numTesselation + 1), startFarIndices + 0 + (i + 1) * (numTesselation + 1));\r\n indices.push(startIndices + i, startFarIndices + 0 + (i + 1) * (numTesselation + 1), startIndices + i + 1);\r\n }\r\n }\r\n\r\n const n3 = positions.length / 3 - 1;\r\n\r\n startIndices = positions.length / 3;\r\n\r\n // Bottom faces of the frustum\r\n for (let i = 0; i <= numTesselation; ++i) {\r\n v.set(min.x + i * stepX, min.y, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (i < numTesselation) {\r\n indices.push(startIndices + i, startIndices + i + 1, startFarIndices + i + 0 * (numTesselation + 1));\r\n indices.push(startIndices + i + 1, startFarIndices + i + 1 + 0 * (numTesselation + 1), startFarIndices + i + 0 * (numTesselation + 1));\r\n }\r\n }\r\n\r\n startIndices = positions.length / 3;\r\n\r\n // Top faces of the frustum\r\n for (let i = 0; i <= numTesselation; ++i) {\r\n v.set(min.x + i * stepX, max.y, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (i < numTesselation) {\r\n indices.push(startIndices + i, startFarIndices + i + numTesselation * (numTesselation + 1), startIndices + i + 1);\r\n indices.push(\r\n startIndices + i + 1,\r\n startFarIndices + i + numTesselation * (numTesselation + 1),\r\n startFarIndices + i + 1 + numTesselation * (numTesselation + 1)\r\n );\r\n }\r\n }\r\n\r\n startIndices = positions.length / 3;\r\n\r\n // Near faces of the frustum\r\n indices.push(n0, n2, n1);\r\n indices.push(n2, n3, n1);\r\n } else {\r\n let p: Vector3;\r\n\r\n v.set(max.x, min.y, min.z);\r\n p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n v.set(max.x, max.y, min.z);\r\n p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n v.set(min.x, min.y, min.z);\r\n p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n v.set(min.x, max.y, min.z);\r\n p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n indices.push(0, 2, 1);\r\n indices.push(2, 3, 1);\r\n }\r\n\r\n // Tesselate the near plane\r\n let y = min.y;\r\n for (let iy = 0; iy <= numTesselation; ++iy) {\r\n let x = min.x;\r\n for (let ix = 0; ix <= numTesselation; ++ix) {\r\n v.set(x, y, min.z);\r\n\r\n const p = Vector3.TransformCoordinates(v, invViewMatrix);\r\n positions.push(p.x, p.y, p.z);\r\n\r\n if (ix < numTesselation && iy < numTesselation) {\r\n indices.push(\r\n startFarIndices + ix + iy * (numTesselation + 1),\r\n startFarIndices + ix + 1 + iy * (numTesselation + 1),\r\n startFarIndices + ix + 1 + (iy + 1) * (numTesselation + 1)\r\n );\r\n indices.push(\r\n startFarIndices + ix + iy * (numTesselation + 1),\r\n startFarIndices + ix + 1 + (iy + 1) * (numTesselation + 1),\r\n startFarIndices + ix + (iy + 1) * (numTesselation + 1)\r\n );\r\n }\r\n x += stepX;\r\n }\r\n y += stepY;\r\n }\r\n\r\n if (this._uBuffer && this._cs) {\r\n const webGPUEngine = this._engine as WebGPUEngine;\r\n\r\n this._storageBuffer?.dispose();\r\n this._storageBuffer = new StorageBuffer(webGPUEngine, positions.length * 4, Constants.BUFFER_CREATIONFLAG_VERTEX | Constants.BUFFER_CREATIONFLAG_READWRITE);\r\n\r\n this._storageBuffer.update(positions);\r\n\r\n const vertexBuffer = new VertexBuffer(webGPUEngine, this._storageBuffer.getBuffer(), \"position\");\r\n\r\n this._mesh.setVerticesBuffer(vertexBuffer);\r\n\r\n this._cs.setStorageBuffer(\"positions\", this._storageBuffer);\r\n\r\n this._uBuffer.updateUInt(\"startVertexIndex\", this._buildFullVolume ? (numTesselation + 1) * 4 * 3 : 4 * 3);\r\n this._uBuffer.updateFloat(\"step\", ((this._shadowGenerator?.mapSize ?? 128) - 1) / numTesselation);\r\n this._uBuffer.updateUInt(\"tesselation\", numTesselation);\r\n } else {\r\n this._mesh.setVerticesData(\"position\", positions);\r\n }\r\n\r\n this._mesh.setIndices(indices, positions.length / 3);\r\n }\r\n}\r\n"]}
@@ -4,6 +4,7 @@ import type { Mesh } from "../../Meshes/mesh.js";
4
4
  import type { Effect } from "../../Materials/effect.js";
5
5
  import type { Scene } from "../../scene.js";
6
6
  import type { Matrix } from "../../Maths/math.vector.js";
7
+ import type { GaussianSplattingMesh } from "../../Meshes/GaussianSplatting/gaussianSplattingMesh.js";
7
8
  import { PushMaterial } from "../../Materials/pushMaterial.js";
8
9
  import { ShadowDepthWrapper } from "../../Materials/shadowDepthWrapper.js";
9
10
  import "../../Shaders/gaussianSplatting.fragment.js";
@@ -66,6 +67,7 @@ export declare class GaussianSplattingMaterial extends PushMaterial {
66
67
  protected static _Samplers: string[];
67
68
  protected static _UniformBuffers: string[];
68
69
  protected static _Uniforms: string[];
70
+ private _sourceMesh;
69
71
  /**
70
72
  * Checks whether the material is ready to be rendered for a given mesh.
71
73
  * @param mesh The mesh to render
@@ -73,6 +75,11 @@ export declare class GaussianSplattingMaterial extends PushMaterial {
73
75
  * @returns true if all the dependencies are ready (Textures, Effects...)
74
76
  */
75
77
  isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh): boolean;
78
+ /**
79
+ * GaussianSplattingMaterial belongs to a single mesh
80
+ * @param mesh mesh this material belongs to
81
+ */
82
+ setSourceMesh(mesh: GaussianSplattingMesh): void;
76
83
  /**
77
84
  * Bind material effect for a specific Gaussian Splatting mesh
78
85
  * @param mesh Gaussian splatting mesh
@@ -58,6 +58,7 @@ export class GaussianSplattingMaterial extends PushMaterial {
58
58
  this._compensation = GaussianSplattingMaterial.Compensation;
59
59
  // set to true when material defines are dirty
60
60
  this._isDirty = false;
61
+ this._sourceMesh = null;
61
62
  this.backFaceCulling = false;
62
63
  this.shadowDepthWrapper = GaussianSplattingMaterial._MakeGaussianSplattingShadowDepthWrapper(scene, this.shaderLanguage);
63
64
  }
@@ -119,8 +120,11 @@ export class GaussianSplattingMaterial extends PushMaterial {
119
120
  if (this._isReadyForSubMesh(subMesh)) {
120
121
  return true;
121
122
  }
123
+ if (!this._sourceMesh) {
124
+ return false;
125
+ }
122
126
  const engine = scene.getEngine();
123
- const gsMesh = mesh;
127
+ const gsMesh = this._sourceMesh;
124
128
  // Misc.
125
129
  PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, false, defines, undefined, undefined, undefined, this._isVertexOutputInvariant);
126
130
  // Values that need to be evaluated on every frame
@@ -178,6 +182,13 @@ export class GaussianSplattingMaterial extends PushMaterial {
178
182
  this._isDirty = false;
179
183
  return true;
180
184
  }
185
+ /**
186
+ * GaussianSplattingMaterial belongs to a single mesh
187
+ * @param mesh mesh this material belongs to
188
+ */
189
+ setSourceMesh(mesh) {
190
+ this._sourceMesh = mesh;
191
+ }
181
192
  /**
182
193
  * Bind material effect for a specific Gaussian Splatting mesh
183
194
  * @param mesh Gaussian splatting mesh
@@ -187,10 +198,13 @@ export class GaussianSplattingMaterial extends PushMaterial {
187
198
  static BindEffect(mesh, effect, scene) {
188
199
  const engine = scene.getEngine();
189
200
  const camera = scene.activeCamera;
190
- const renderWidth = engine.getRenderWidth();
191
- const renderHeight = engine.getRenderHeight();
192
- const gsMesh = mesh;
193
- const gsMaterial = gsMesh.material;
201
+ const renderWidth = engine.getRenderWidth() * camera.viewport.width;
202
+ const renderHeight = engine.getRenderHeight() * camera.viewport.height;
203
+ const gsMaterial = mesh.material;
204
+ if (!gsMaterial._sourceMesh) {
205
+ return;
206
+ }
207
+ const gsMesh = gsMaterial._sourceMesh;
194
208
  // check if rigcamera, get number of rigs
195
209
  const numberOfRigs = camera?.rigParent?.rigCameras.length || 1;
196
210
  effect.setFloat2("invViewport", 1 / (renderWidth / numberOfRigs), 1 / renderHeight);