@plastic-software/three 0.183.4 → 0.184.0

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 (277) hide show
  1. package/build/three.cjs +773 -286
  2. package/build/three.core.js +372 -110
  3. package/build/three.core.min.js +1 -1
  4. package/build/three.module.js +426 -180
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +7 -1
  7. package/build/three.tsl.min.js +1 -1
  8. package/build/three.webgpu.js +2979 -1281
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +2942 -1281
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/jsm/Addons.js +11 -0
  13. package/examples/jsm/animation/CCDIKSolver.js +5 -1
  14. package/examples/jsm/controls/ArcballControls.js +4 -1
  15. package/examples/jsm/controls/DragControls.js +2 -2
  16. package/examples/jsm/controls/FirstPersonControls.js +58 -54
  17. package/examples/jsm/controls/FlyControls.js +4 -0
  18. package/examples/jsm/controls/OrbitControls.js +2 -2
  19. package/examples/jsm/controls/TrackballControls.js +2 -2
  20. package/examples/jsm/controls/TransformControls.js +34 -2
  21. package/examples/jsm/csm/CSMShadowNode.js +6 -2
  22. package/examples/jsm/exporters/GLTFExporter.js +21 -5
  23. package/examples/jsm/geometries/TextGeometry.js +18 -0
  24. package/examples/jsm/helpers/LightProbeGridHelper.js +221 -0
  25. package/examples/jsm/inspector/Extension.js +13 -0
  26. package/examples/jsm/inspector/Inspector.js +169 -114
  27. package/examples/jsm/inspector/RendererInspector.js +2 -2
  28. package/examples/jsm/inspector/extensions/extensions.json +6 -0
  29. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +916 -0
  30. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +281 -0
  31. package/examples/jsm/inspector/tabs/Memory.js +128 -0
  32. package/examples/jsm/inspector/tabs/Parameters.js +34 -2
  33. package/examples/jsm/inspector/tabs/Performance.js +2 -2
  34. package/examples/jsm/inspector/tabs/Settings.js +264 -0
  35. package/examples/jsm/inspector/tabs/Timeline.js +1611 -0
  36. package/examples/jsm/inspector/tabs/Viewer.js +105 -3
  37. package/examples/jsm/inspector/ui/Graph.js +2 -2
  38. package/examples/jsm/inspector/ui/List.js +1 -1
  39. package/examples/jsm/inspector/ui/Profiler.js +273 -176
  40. package/examples/jsm/inspector/ui/Style.js +64 -10
  41. package/examples/jsm/inspector/ui/Tab.js +39 -7
  42. package/examples/jsm/inspector/ui/Values.js +39 -2
  43. package/examples/jsm/inspector/ui/utils.js +13 -0
  44. package/examples/jsm/interaction/InteractionManager.js +226 -0
  45. package/examples/jsm/libs/meshopt_decoder.module.js +8 -8
  46. package/examples/jsm/lighting/DynamicLighting.js +82 -0
  47. package/examples/jsm/lighting/LightProbeGrid.js +651 -0
  48. package/examples/jsm/lines/LineMaterial.js +1 -1
  49. package/examples/jsm/loaders/EXRLoader.js +682 -43
  50. package/examples/jsm/loaders/FBXLoader.js +233 -33
  51. package/examples/jsm/loaders/GLTFLoader.js +24 -7
  52. package/examples/jsm/loaders/HDRLoader.js +1 -1
  53. package/examples/jsm/loaders/KTX2Loader.js +8 -2
  54. package/examples/jsm/loaders/LDrawLoader.js +39 -47
  55. package/examples/jsm/loaders/SVGLoader.js +1 -1
  56. package/examples/jsm/loaders/VTKLoader.js +5 -1
  57. package/examples/jsm/loaders/collada/ColladaComposer.js +101 -7
  58. package/examples/jsm/loaders/collada/ColladaParser.js +19 -4
  59. package/examples/jsm/loaders/usd/USDAParser.js +6 -0
  60. package/examples/jsm/loaders/usd/USDCParser.js +26 -0
  61. package/examples/jsm/loaders/usd/USDComposer.js +656 -103
  62. package/examples/jsm/misc/GPUComputationRenderer.js +2 -0
  63. package/examples/jsm/misc/RollerCoaster.js +42 -4
  64. package/examples/jsm/modifiers/TessellateModifier.js +1 -1
  65. package/examples/jsm/objects/Reflector.js +73 -25
  66. package/examples/jsm/objects/Sky.js +14 -2
  67. package/examples/jsm/objects/SkyMesh.js +23 -6
  68. package/examples/jsm/renderers/Projector.js +18 -38
  69. package/examples/jsm/renderers/SVGRenderer.js +6 -25
  70. package/examples/jsm/transpiler/GLSLDecoder.js +2 -2
  71. package/examples/jsm/tsl/WebGLNodesHandler.js +605 -0
  72. package/examples/jsm/tsl/display/AfterImageNode.js +10 -0
  73. package/examples/jsm/tsl/display/AnamorphicNode.js +11 -0
  74. package/examples/jsm/tsl/display/BilateralBlurNode.js +10 -0
  75. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +3 -36
  76. package/examples/jsm/tsl/display/FSR1Node.js +477 -0
  77. package/examples/jsm/tsl/display/GTAONode.js +2 -1
  78. package/examples/jsm/tsl/display/GaussianBlurNode.js +10 -0
  79. package/examples/jsm/tsl/display/GodraysNode.js +2 -11
  80. package/examples/jsm/tsl/display/OutlineNode.js +66 -16
  81. package/examples/jsm/tsl/display/SSGINode.js +0 -4
  82. package/examples/jsm/tsl/display/SharpenNode.js +283 -0
  83. package/examples/jsm/tsl/display/TAAUNode.js +835 -0
  84. package/examples/jsm/tsl/display/TRAANode.js +48 -7
  85. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +300 -0
  86. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +61 -0
  87. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +111 -0
  88. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +99 -0
  89. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +134 -0
  90. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +161 -0
  91. package/examples/jsm/tsl/math/Bayer.js +13 -2
  92. package/examples/jsm/utils/BufferGeometryUtils.js +2 -3
  93. package/examples/jsm/utils/ColorUtils.js +76 -0
  94. package/examples/jsm/utils/SkeletonUtils.js +14 -8
  95. package/examples/jsm/webxr/XRHandMeshModel.js +36 -10
  96. package/examples/jsm/webxr/XRHandModelFactory.js +2 -1
  97. package/package.json +4 -4
  98. package/src/Three.Core.js +1 -0
  99. package/src/Three.TSL.js +6 -0
  100. package/src/Three.WebGPU.Nodes.js +3 -0
  101. package/src/Three.WebGPU.js +6 -0
  102. package/src/animation/AnimationAction.js +11 -1
  103. package/src/audio/AudioContext.js +2 -2
  104. package/src/constants.js +1 -1
  105. package/src/core/BufferAttribute.js +13 -1
  106. package/src/core/Clock.js +1 -1
  107. package/src/core/Object3D.js +1 -5
  108. package/src/core/RenderTarget.js +1 -0
  109. package/src/extras/curves/CatmullRomCurve3.js +3 -2
  110. package/src/loaders/AudioLoader.js +11 -1
  111. package/src/loaders/DataTextureLoader.js +6 -4
  112. package/src/loaders/FileLoader.js +1 -2
  113. package/src/loaders/ImageBitmapLoader.js +4 -6
  114. package/src/loaders/MaterialLoader.js +1 -1
  115. package/src/loaders/ObjectLoader.js +25 -4
  116. package/src/loaders/nodes/NodeObjectLoader.js +18 -0
  117. package/src/materials/MeshToonMaterial.js +1 -1
  118. package/src/materials/nodes/Line2NodeMaterial.js +27 -0
  119. package/src/materials/nodes/NodeMaterial.js +0 -27
  120. package/src/materials/nodes/manager/NodeMaterialObserver.js +188 -89
  121. package/src/math/Line3.js +3 -0
  122. package/src/math/Matrix2.js +13 -9
  123. package/src/math/Matrix3.js +13 -9
  124. package/src/math/Matrix4.js +13 -9
  125. package/src/math/Plane.js +4 -3
  126. package/src/math/Triangle.js +1 -1
  127. package/src/math/Vector2.js +11 -7
  128. package/src/math/Vector3.js +12 -8
  129. package/src/math/Vector4.js +13 -9
  130. package/src/nodes/Nodes.js +0 -1
  131. package/src/nodes/TSL.js +1 -1
  132. package/src/nodes/accessors/BufferAttributeNode.js +9 -3
  133. package/src/nodes/accessors/CubeTextureNode.js +7 -1
  134. package/src/nodes/accessors/MaterialProperties.js +2 -5
  135. package/src/nodes/accessors/Object3DNode.js +1 -1
  136. package/src/nodes/accessors/ReferenceBaseNode.js +2 -2
  137. package/src/nodes/accessors/ReferenceNode.js +4 -4
  138. package/src/nodes/accessors/SceneProperties.js +2 -8
  139. package/src/nodes/accessors/StorageBufferNode.js +10 -4
  140. package/src/nodes/accessors/StorageTextureNode.js +4 -9
  141. package/src/nodes/accessors/TextureNode.js +10 -2
  142. package/src/nodes/accessors/UniformArrayNode.js +2 -2
  143. package/src/nodes/code/FunctionCallNode.js +1 -1
  144. package/src/nodes/code/FunctionNode.js +1 -1
  145. package/src/nodes/core/ArrayNode.js +1 -1
  146. package/src/nodes/core/AssignNode.js +1 -1
  147. package/src/nodes/core/AttributeNode.js +1 -1
  148. package/src/nodes/core/BypassNode.js +1 -1
  149. package/src/nodes/core/ContextNode.js +1 -1
  150. package/src/nodes/core/IndexNode.js +2 -1
  151. package/src/nodes/core/InputNode.js +1 -1
  152. package/src/nodes/core/InspectorNode.js +1 -1
  153. package/src/nodes/core/IsolateNode.js +1 -1
  154. package/src/nodes/core/Node.js +83 -12
  155. package/src/nodes/core/NodeBuilder.js +117 -16
  156. package/src/nodes/core/NodeUtils.js +1 -1
  157. package/src/nodes/core/OutputStructNode.js +1 -1
  158. package/src/nodes/core/ParameterNode.js +1 -1
  159. package/src/nodes/core/StackNode.js +1 -1
  160. package/src/nodes/core/StructNode.js +1 -1
  161. package/src/nodes/core/StructTypeNode.js +1 -1
  162. package/src/nodes/core/SubBuildNode.js +1 -1
  163. package/src/nodes/core/UniformGroupNode.js +36 -6
  164. package/src/nodes/core/VarNode.js +1 -1
  165. package/src/nodes/core/VaryingNode.js +1 -1
  166. package/src/nodes/display/NormalMapNode.js +2 -2
  167. package/src/nodes/display/PassNode.js +27 -7
  168. package/src/nodes/display/RenderOutputNode.js +4 -4
  169. package/src/nodes/display/ScreenNode.js +1 -1
  170. package/src/nodes/display/ViewportDepthTextureNode.js +11 -15
  171. package/src/nodes/display/ViewportTextureNode.js +18 -7
  172. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +2 -2
  173. package/src/nodes/geometry/RangeNode.js +1 -1
  174. package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
  175. package/src/nodes/gpgpu/BarrierNode.js +9 -0
  176. package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -1
  177. package/src/nodes/gpgpu/ComputeNode.js +69 -44
  178. package/src/nodes/gpgpu/SubgroupFunctionNode.js +1 -1
  179. package/src/nodes/lighting/LightsNode.js +6 -27
  180. package/src/nodes/lighting/ShadowNode.js +24 -2
  181. package/src/nodes/math/BitcastNode.js +1 -1
  182. package/src/nodes/math/ConditionalNode.js +1 -1
  183. package/src/nodes/math/MathNode.js +73 -1
  184. package/src/nodes/math/OperatorNode.js +1 -1
  185. package/src/nodes/math/PackFloatNode.js +1 -1
  186. package/src/nodes/math/UnpackFloatNode.js +1 -1
  187. package/src/nodes/tsl/TSLBase.js +1 -1
  188. package/src/nodes/tsl/TSLCore.js +21 -3
  189. package/src/nodes/utils/ArrayElementNode.js +1 -1
  190. package/src/nodes/utils/ConvertNode.js +1 -1
  191. package/src/nodes/utils/DebugNode.js +1 -1
  192. package/src/nodes/utils/EventNode.js +30 -0
  193. package/src/nodes/utils/FlipNode.js +1 -1
  194. package/src/nodes/utils/FunctionOverloadingNode.js +1 -1
  195. package/src/nodes/utils/JoinNode.js +1 -1
  196. package/src/nodes/utils/MemberNode.js +1 -1
  197. package/src/nodes/utils/Remap.js +48 -0
  198. package/src/nodes/utils/RotateNode.js +1 -1
  199. package/src/nodes/utils/SetNode.js +1 -1
  200. package/src/nodes/utils/SplitNode.js +1 -1
  201. package/src/objects/BatchedMesh.js +17 -2
  202. package/src/objects/InstancedMesh.js +19 -3
  203. package/src/objects/SkinnedMesh.js +26 -9
  204. package/src/renderers/WebGLRenderer.js +147 -48
  205. package/src/renderers/common/Animation.js +3 -3
  206. package/src/renderers/common/Attributes.js +15 -1
  207. package/src/renderers/common/Backend.js +0 -8
  208. package/src/renderers/common/Background.js +2 -2
  209. package/src/renderers/common/BindGroup.js +1 -8
  210. package/src/renderers/common/Bindings.js +2 -2
  211. package/src/renderers/common/ComputePipeline.js +1 -1
  212. package/src/renderers/common/CubeRenderTarget.js +1 -1
  213. package/src/renderers/common/Info.js +333 -4
  214. package/src/renderers/common/InspectorBase.js +6 -1
  215. package/src/renderers/common/Pipelines.js +36 -3
  216. package/src/renderers/common/ReadbackBuffer.js +78 -0
  217. package/src/renderers/common/RenderBundle.js +3 -1
  218. package/src/renderers/common/RenderBundles.js +5 -2
  219. package/src/renderers/common/RenderObject.js +2 -2
  220. package/src/renderers/common/RenderObjects.js +3 -3
  221. package/src/renderers/common/RenderPipeline.js +35 -6
  222. package/src/renderers/common/Renderer.js +232 -53
  223. package/src/renderers/common/Textures.js +72 -3
  224. package/src/renderers/common/UniformsGroup.js +1 -1
  225. package/src/renderers/common/XRManager.js +34 -27
  226. package/src/renderers/common/extras/PMREMGenerator.js +23 -15
  227. package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
  228. package/src/renderers/common/nodes/NodeManager.js +230 -99
  229. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +0 -1
  230. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +1 -1
  231. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +80 -0
  232. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +8 -0
  233. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +2 -0
  234. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +1 -3
  235. package/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +7 -0
  236. package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +0 -1
  237. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +12 -2
  238. package/src/renderers/shaders/ShaderChunk.js +2 -0
  239. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +1 -2
  240. package/src/renderers/shaders/ShaderLib.js +0 -1
  241. package/src/renderers/shaders/UniformsLib.js +7 -2
  242. package/src/renderers/shaders/UniformsUtils.js +27 -5
  243. package/src/renderers/webgl/WebGLAnimation.js +2 -1
  244. package/src/renderers/webgl/WebGLBackground.js +13 -13
  245. package/src/renderers/webgl/WebGLBufferRenderer.js +0 -32
  246. package/src/renderers/webgl/WebGLCapabilities.js +6 -0
  247. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +0 -32
  248. package/src/renderers/webgl/WebGLMaterials.js +12 -13
  249. package/src/renderers/webgl/WebGLOutput.js +4 -1
  250. package/src/renderers/webgl/WebGLProgram.js +4 -0
  251. package/src/renderers/webgl/WebGLPrograms.js +19 -3
  252. package/src/renderers/webgl/WebGLRenderStates.js +13 -2
  253. package/src/renderers/webgl/WebGLState.js +43 -0
  254. package/src/renderers/webgl/WebGLTextures.js +129 -26
  255. package/src/renderers/webgl/WebGLUniformsGroups.js +19 -0
  256. package/src/renderers/webgl-fallback/WebGLBackend.js +106 -65
  257. package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +0 -41
  258. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +29 -51
  259. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +53 -19
  260. package/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +25 -0
  261. package/src/renderers/webgl-fallback/utils/WebGLState.js +42 -1
  262. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +63 -50
  263. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +1 -1
  264. package/src/renderers/webgpu/WebGPUBackend.js +160 -146
  265. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +55 -33
  266. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +103 -17
  267. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
  268. package/src/renderers/webgpu/utils/WebGPUCapabilities.js +48 -0
  269. package/src/renderers/webgpu/utils/WebGPUConstants.js +8 -0
  270. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +91 -17
  271. package/src/renderers/webgpu/utils/WebGPUUtils.js +18 -2
  272. package/src/renderers/webxr/WebXRController.js +12 -0
  273. package/src/textures/HTMLTexture.js +74 -0
  274. package/src/textures/Source.js +1 -1
  275. package/src/textures/Texture.js +13 -2
  276. package/src/utils.js +23 -1
  277. package/src/nodes/utils/RemapNode.js +0 -125
@@ -0,0 +1,651 @@
1
+ import {
2
+ Box3,
3
+ CubeCamera,
4
+ FloatType,
5
+ HalfFloatType,
6
+ LinearFilter,
7
+ Mesh,
8
+ NearestFilter,
9
+ Object3D,
10
+ OrthographicCamera,
11
+ PlaneGeometry,
12
+ RGBAFormat,
13
+ Scene,
14
+ ShaderMaterial,
15
+ Vector3,
16
+ Vector4,
17
+ WebGL3DRenderTarget,
18
+ WebGLCubeRenderTarget,
19
+ WebGLRenderTarget
20
+ } from 'three';
21
+
22
+ // Shared fullscreen-quad scene / camera
23
+ let _scene = null;
24
+ let _camera = null;
25
+ let _mesh = null;
26
+
27
+ // SH projection material (depends on cubemapSize)
28
+ let _shMaterial = null;
29
+ let _lastCubemapSize = 0;
30
+
31
+ // Repack materials (one per output sub-volume / texture index)
32
+ let _repackMaterials = null;
33
+
34
+ // Cached bake resources
35
+ let _cubeRenderTarget = null;
36
+ let _cubeCamera = null;
37
+ let _cachedCubemapSize = 0;
38
+ let _cachedNear = 0;
39
+ let _cachedFar = 0;
40
+
41
+ // Cached batch render target
42
+ let _batchTarget = null;
43
+ let _batchTargetProbes = 0;
44
+
45
+ // Reusable temp objects
46
+ const _position = /*@__PURE__*/ new Vector3();
47
+ const _size = /*@__PURE__*/ new Vector3();
48
+ const _savedViewport = /*@__PURE__*/ new Vector4();
49
+ const _savedScissor = /*@__PURE__*/ new Vector4();
50
+
51
+ // Number of padding texels added at each boundary of every sub-volume in the atlas.
52
+ const ATLAS_PADDING = 1;
53
+
54
+ /**
55
+ * A 3D grid of L2 Spherical Harmonic irradiance probes that provides
56
+ * position-dependent diffuse global illumination.
57
+ *
58
+ * All seven packed SH sub-volumes are stored in a **single** RGBA
59
+ * `WebGL3DRenderTarget` using a texture-atlas layout along the Z axis.
60
+ * Each sub-volume occupies `( nz + 2 )` atlas slices: one padding slice at
61
+ * each end (a copy of the nearest edge data slice) to prevent color bleeding
62
+ * when the hardware trilinear filter reads across a sub-volume boundary.
63
+ *
64
+ * Atlas layout (nz = resolution.z, PADDING = 1):
65
+ * ```
66
+ * slice 0 : padding (copy of sub-volume 0, data slice 0)
67
+ * slices 1 … nz : sub-volume 0 data
68
+ * slice nz + 1 : padding (copy of sub-volume 0, data slice nz-1)
69
+ * slice nz + 2 : padding (copy of sub-volume 1, data slice 0)
70
+ * slices nz+3 … 2*nz+2 : sub-volume 1 data
71
+ * …
72
+ * ```
73
+ * Total atlas depth = `7 * ( nz + 2 )`.
74
+ *
75
+ * Baking is fully GPU-resident: cubemap rendering, SH projection, and
76
+ * texture packing all happen on the GPU with zero CPU readback.
77
+ *
78
+ * @three_import import { LightProbeGrid } from 'three/addons/lighting/LightProbeGrid.js';
79
+ */
80
+ class LightProbeGrid extends Object3D {
81
+
82
+ /**
83
+ * Constructs a new irradiance probe grid.
84
+ *
85
+ * The volume is centered at the object's position.
86
+ *
87
+ * @param {number} [width=1] - Full width of the volume along X.
88
+ * @param {number} [height=1] - Full height of the volume along Y.
89
+ * @param {number} [depth=1] - Full depth of the volume along Z.
90
+ * @param {number} [widthProbes] - Number of probes along X. Defaults to `Math.max( 2, Math.round( width ) + 1 )`.
91
+ * @param {number} [heightProbes] - Number of probes along Y. Defaults to `Math.max( 2, Math.round( height ) + 1 )`.
92
+ * @param {number} [depthProbes] - Number of probes along Z. Defaults to `Math.max( 2, Math.round( depth ) + 1 )`.
93
+ */
94
+ constructor( width = 1, height = 1, depth = 1, widthProbes, heightProbes, depthProbes ) {
95
+
96
+ super();
97
+
98
+ /**
99
+ * This flag can be used for type testing.
100
+ *
101
+ * @type {boolean}
102
+ * @readonly
103
+ * @default true
104
+ */
105
+ this.isLightProbeGrid = true;
106
+
107
+ /**
108
+ * The full width of the volume along X.
109
+ *
110
+ * @type {number}
111
+ */
112
+ this.width = width;
113
+
114
+ /**
115
+ * The full height of the volume along Y.
116
+ *
117
+ * @type {number}
118
+ */
119
+ this.height = height;
120
+
121
+ /**
122
+ * The full depth of the volume along Z.
123
+ *
124
+ * @type {number}
125
+ */
126
+ this.depth = depth;
127
+
128
+ /**
129
+ * The number of probes along each axis.
130
+ *
131
+ * @type {Vector3}
132
+ */
133
+ this.resolution = new Vector3(
134
+ widthProbes !== undefined ? widthProbes : Math.max( 2, Math.round( width ) + 1 ),
135
+ heightProbes !== undefined ? heightProbes : Math.max( 2, Math.round( height ) + 1 ),
136
+ depthProbes !== undefined ? depthProbes : Math.max( 2, Math.round( depth ) + 1 )
137
+ );
138
+
139
+ /**
140
+ * The world-space bounding box for the grid. Updated automatically
141
+ * by {@link LightProbeGrid#bake}.
142
+ *
143
+ * @type {Box3}
144
+ */
145
+ this.boundingBox = new Box3();
146
+
147
+ /**
148
+ * The single RGBA atlas 3D texture storing all seven packed SH sub-volumes.
149
+ *
150
+ * @type {?Data3DTexture}
151
+ * @default null
152
+ */
153
+ this.texture = null;
154
+
155
+ /**
156
+ * Internal render target for GPU-resident baking.
157
+ *
158
+ * @private
159
+ * @type {?WebGL3DRenderTarget}
160
+ * @default null
161
+ */
162
+ this._renderTarget = null;
163
+
164
+ this.updateBoundingBox();
165
+
166
+ }
167
+
168
+ /**
169
+ * Returns the world-space position of the probe at grid indices (ix, iy, iz).
170
+ *
171
+ * @param {number} ix - X index.
172
+ * @param {number} iy - Y index.
173
+ * @param {number} iz - Z index.
174
+ * @param {Vector3} target - The target vector.
175
+ * @return {Vector3} The world-space position.
176
+ */
177
+ getProbePosition( ix, iy, iz, target ) {
178
+
179
+ const pos = this.position;
180
+ const res = this.resolution;
181
+ const w = this.width, h = this.height, d = this.depth;
182
+
183
+ target.set(
184
+ res.x > 1 ? pos.x - w / 2 + ix * w / ( res.x - 1 ) : pos.x,
185
+ res.y > 1 ? pos.y - h / 2 + iy * h / ( res.y - 1 ) : pos.y,
186
+ res.z > 1 ? pos.z - d / 2 + iz * d / ( res.z - 1 ) : pos.z
187
+ );
188
+
189
+ return target;
190
+
191
+ }
192
+
193
+ /**
194
+ * Updates the world-space bounding box from the current position and size.
195
+ */
196
+ updateBoundingBox() {
197
+
198
+ _size.set( this.width, this.height, this.depth );
199
+ this.boundingBox.setFromCenterAndSize( this.position, _size );
200
+
201
+ }
202
+
203
+ /**
204
+ * Bakes all probes by rendering cubemaps at each probe position
205
+ * and projecting to L2 SH. Fully GPU-resident with zero CPU readback.
206
+ *
207
+ * @param {WebGLRenderer} renderer - The renderer.
208
+ * @param {Scene} scene - The scene to render.
209
+ * @param {Object} [options] - Bake options.
210
+ * @param {number} [options.cubemapSize=8] - Resolution of each cubemap face.
211
+ * @param {number} [options.near=0.1] - Near plane for the cube camera.
212
+ * @param {number} [options.far=100] - Far plane for the cube camera.
213
+ */
214
+ bake( renderer, scene, options = {} ) {
215
+
216
+ const { cubeRenderTarget, cubeCamera } = _ensureBakeResources( options );
217
+
218
+ this._ensureTextures();
219
+ this.updateBoundingBox();
220
+
221
+ // Prevent feedback: temporarily hide the volume during baking
222
+ this.visible = false;
223
+
224
+ const res = this.resolution;
225
+ const totalProbes = res.x * res.y * res.z;
226
+
227
+ // Batch render target for SH coefficients: 9 pixels wide, one row per probe
228
+ const batchTarget = _ensureBatchTarget( totalProbes );
229
+
230
+ // Save renderer state
231
+ const savedRenderTarget = renderer.getRenderTarget();
232
+ renderer.getViewport( _savedViewport );
233
+ renderer.getScissor( _savedScissor );
234
+ const savedScissorTest = renderer.getScissorTest();
235
+
236
+ // Clear pooled batch target so skipped probes read as zero
237
+ batchTarget.scissorTest = false;
238
+ batchTarget.viewport.set( 0, 0, 9, totalProbes );
239
+ renderer.setRenderTarget( batchTarget );
240
+ renderer.clear();
241
+
242
+ // const t0 = performance.now();
243
+
244
+ // Phase 1: Render cubemaps and project to SH into batch target
245
+ // Note: set viewport/scissor on the render target directly to avoid pixel ratio scaling
246
+ batchTarget.scissorTest = true;
247
+
248
+ // Disable shadow map auto-update during bake — lights don't move between probes.
249
+ // Force one shadow update on the first render so maps are initialized.
250
+ const savedShadowAutoUpdate = renderer.shadowMap.autoUpdate;
251
+ renderer.shadowMap.autoUpdate = false;
252
+ renderer.shadowMap.needsUpdate = true;
253
+
254
+ for ( let iz = 0; iz < res.z; iz ++ ) {
255
+
256
+ for ( let iy = 0; iy < res.y; iy ++ ) {
257
+
258
+ for ( let ix = 0; ix < res.x; ix ++ ) {
259
+
260
+ const probeIndex = ix + iy * res.x + iz * res.x * res.y;
261
+
262
+ this.getProbePosition( ix, iy, iz, _position );
263
+ cubeCamera.position.copy( _position );
264
+ cubeCamera.update( renderer, scene );
265
+
266
+ // SH projection
267
+ _shMaterial.uniforms.envMap.value = cubeRenderTarget.texture;
268
+ _mesh.material = _shMaterial;
269
+ batchTarget.viewport.set( 0, probeIndex, 9, 1 );
270
+ batchTarget.scissor.set( 0, probeIndex, 9, 1 );
271
+ renderer.setRenderTarget( batchTarget );
272
+ renderer.render( _scene, _camera );
273
+
274
+ }
275
+
276
+ }
277
+
278
+ }
279
+
280
+ renderer.shadowMap.autoUpdate = savedShadowAutoUpdate;
281
+
282
+ // Phase 2: Repack SH data from batch target into the atlas 3D texture (GPU-to-GPU).
283
+ //
284
+ // For each of the 7 packed sub-volumes (texture index t) we write:
285
+ // - A leading padding slice (copy of data slice iz = 0)
286
+ // - All nz data slices (iz = 0 … nz-1)
287
+ // - A trailing padding slice (copy of data slice iz = nz-1)
288
+ //
289
+ // In the atlas the slices for sub-volume t occupy the range:
290
+ // [ t * paddedSlices, t * paddedSlices + paddedSlices - 1 ]
291
+ // where paddedSlices = nz + 2 * ATLAS_PADDING.
292
+
293
+ _ensureRepackResources();
294
+
295
+ const paddedSlices = res.z + 2 * ATLAS_PADDING;
296
+ const rt = this._renderTarget;
297
+ rt.scissorTest = false;
298
+ rt.viewport.set( 0, 0, res.x, res.y );
299
+
300
+ for ( let t = 0; t < 7; t ++ ) {
301
+
302
+ _repackMaterials[ t ].uniforms.batchTexture.value = batchTarget.texture;
303
+ _repackMaterials[ t ].uniforms.resolution.value.copy( res );
304
+
305
+ // Write data slices
306
+ for ( let iz = 0; iz < res.z; iz ++ ) {
307
+
308
+ _repackMaterials[ t ].uniforms.sliceZ.value = iz;
309
+ _mesh.material = _repackMaterials[ t ];
310
+ renderer.setRenderTarget( rt, t * paddedSlices + ATLAS_PADDING + iz );
311
+ renderer.render( _scene, _camera );
312
+
313
+ }
314
+
315
+ // Leading padding: copy of data slice iz = 0
316
+ _repackMaterials[ t ].uniforms.sliceZ.value = 0;
317
+ _mesh.material = _repackMaterials[ t ];
318
+ renderer.setRenderTarget( rt, t * paddedSlices );
319
+ renderer.render( _scene, _camera );
320
+
321
+ // Trailing padding: copy of data slice iz = nz - 1
322
+ _repackMaterials[ t ].uniforms.sliceZ.value = res.z - 1;
323
+ _mesh.material = _repackMaterials[ t ];
324
+ renderer.setRenderTarget( rt, t * paddedSlices + ATLAS_PADDING + res.z );
325
+ renderer.render( _scene, _camera );
326
+
327
+ }
328
+
329
+ // Restore renderer state
330
+ renderer.setRenderTarget( savedRenderTarget );
331
+ renderer.setViewport( _savedViewport );
332
+ renderer.setScissor( _savedScissor );
333
+ renderer.setScissorTest( savedScissorTest );
334
+
335
+ // console.log( `LightProbeGrid: bake complete ${ ( performance.now() - t0 ).toFixed( 1 ) }ms` );
336
+
337
+ this.visible = true;
338
+
339
+ }
340
+
341
+ /**
342
+ * Ensures the atlas 3D render target exists with the correct dimensions.
343
+ *
344
+ * @private
345
+ */
346
+ _ensureTextures() {
347
+
348
+ if ( this._renderTarget !== null ) return;
349
+
350
+ const res = this.resolution;
351
+ const nx = res.x, ny = res.y, nz = res.z;
352
+
353
+ // Atlas depth: 7 sub-volumes, each with ATLAS_PADDING slices at both ends
354
+ const atlasDepth = 7 * ( nz + 2 * ATLAS_PADDING );
355
+
356
+ const rt = new WebGL3DRenderTarget( nx, ny, atlasDepth, {
357
+ format: RGBAFormat,
358
+ type: FloatType,
359
+ minFilter: LinearFilter,
360
+ magFilter: LinearFilter,
361
+ generateMipmaps: false,
362
+ depthBuffer: false
363
+ } );
364
+
365
+ this._renderTarget = rt;
366
+ this.texture = rt.texture;
367
+
368
+ }
369
+
370
+ /**
371
+ * Frees GPU resources.
372
+ */
373
+ dispose() {
374
+
375
+ if ( this._renderTarget !== null ) {
376
+
377
+ this._renderTarget.dispose();
378
+ this._renderTarget = null;
379
+ this.texture = null;
380
+
381
+ }
382
+
383
+ }
384
+
385
+ }
386
+
387
+ // Internal: Ensure the shared fullscreen-quad scene exists
388
+ function _ensureScene() {
389
+
390
+ if ( _scene === null ) {
391
+
392
+ _camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
393
+ _mesh = new Mesh( new PlaneGeometry( 2, 2 ) );
394
+ _scene = new Scene();
395
+ _scene.add( _mesh );
396
+
397
+ }
398
+
399
+ }
400
+
401
+ // Internal: Ensure GPU resources for SH projection are created
402
+ function _ensureGPUResources( cubemapSize ) {
403
+
404
+ _ensureScene();
405
+
406
+ // Recreate material when cubemap size changes
407
+ if ( cubemapSize !== _lastCubemapSize ) {
408
+
409
+ if ( _shMaterial !== null ) _shMaterial.dispose();
410
+
411
+ _shMaterial = new ShaderMaterial( {
412
+ precision: 'highp',
413
+ defines: {
414
+ CUBEMAP_SIZE: cubemapSize
415
+ },
416
+ uniforms: {
417
+ envMap: { value: null }
418
+ },
419
+ vertexShader: /* glsl */`
420
+ void main() {
421
+ gl_Position = vec4( position.xy, 0.0, 1.0 );
422
+ }
423
+ `,
424
+ fragmentShader: /* glsl */`
425
+ #include <common>
426
+
427
+ uniform samplerCube envMap;
428
+
429
+ void main() {
430
+
431
+ int coefIndex = int( gl_FragCoord.x );
432
+
433
+ vec3 accum0 = vec3( 0.0 );
434
+ vec3 accum1 = vec3( 0.0 );
435
+ vec3 accum2 = vec3( 0.0 );
436
+ vec3 accum3 = vec3( 0.0 );
437
+ vec3 accum4 = vec3( 0.0 );
438
+ vec3 accum5 = vec3( 0.0 );
439
+ vec3 accum6 = vec3( 0.0 );
440
+ vec3 accum7 = vec3( 0.0 );
441
+ vec3 accum8 = vec3( 0.0 );
442
+ float totalWeight = 0.0;
443
+ float pixelSize = 2.0 / float( CUBEMAP_SIZE );
444
+
445
+ for ( int face = 0; face < 6; face ++ ) {
446
+
447
+ for ( int iy = 0; iy < CUBEMAP_SIZE; iy ++ ) {
448
+
449
+ for ( int ix = 0; ix < CUBEMAP_SIZE; ix ++ ) {
450
+
451
+ // WebGL cubemaps have a left-handed orientation (flip = -1)
452
+ float col = ( float( ix ) + 0.5 ) * pixelSize - 1.0;
453
+ float row = 1.0 - ( float( iy ) + 0.5 ) * pixelSize;
454
+
455
+ vec3 coord;
456
+
457
+ if ( face == 0 ) coord = vec3( 1.0, row, -col );
458
+ else if ( face == 1 ) coord = vec3( -1.0, row, col );
459
+ else if ( face == 2 ) coord = vec3( col, 1.0, -row );
460
+ else if ( face == 3 ) coord = vec3( col, -1.0, row );
461
+ else if ( face == 4 ) coord = vec3( col, row, 1.0 );
462
+ else coord = vec3( -col, row, -1.0 );
463
+
464
+ float lengthSq = dot( coord, coord );
465
+ float weight = 4.0 / ( sqrt( lengthSq ) * lengthSq );
466
+ totalWeight += weight;
467
+
468
+ vec3 dir = normalize( coord );
469
+ vec3 cw = textureCube( envMap, coord ).rgb * weight;
470
+
471
+ // band 0
472
+ accum0 += cw * 0.282095;
473
+
474
+ // band 1
475
+ accum1 += cw * ( 0.488603 * dir.y );
476
+ accum2 += cw * ( 0.488603 * dir.z );
477
+ accum3 += cw * ( 0.488603 * dir.x );
478
+
479
+ // band 2
480
+ accum4 += cw * ( 1.092548 * ( dir.x * dir.y ) );
481
+ accum5 += cw * ( 1.092548 * ( dir.y * dir.z ) );
482
+ accum6 += cw * ( 0.315392 * ( 3.0 * dir.z * dir.z - 1.0 ) );
483
+ accum7 += cw * ( 1.092548 * ( dir.x * dir.z ) );
484
+ accum8 += cw * ( 0.546274 * ( dir.x * dir.x - dir.y * dir.y ) );
485
+
486
+ }
487
+
488
+ }
489
+
490
+ }
491
+
492
+ float norm = 4.0 * PI / totalWeight;
493
+
494
+ vec3 accum;
495
+ if ( coefIndex == 0 ) accum = accum0;
496
+ else if ( coefIndex == 1 ) accum = accum1;
497
+ else if ( coefIndex == 2 ) accum = accum2;
498
+ else if ( coefIndex == 3 ) accum = accum3;
499
+ else if ( coefIndex == 4 ) accum = accum4;
500
+ else if ( coefIndex == 5 ) accum = accum5;
501
+ else if ( coefIndex == 6 ) accum = accum6;
502
+ else if ( coefIndex == 7 ) accum = accum7;
503
+ else accum = accum8;
504
+
505
+ gl_FragColor = vec4( accum * norm, 1.0 );
506
+
507
+ }
508
+ `
509
+ } );
510
+
511
+ _lastCubemapSize = cubemapSize;
512
+
513
+ }
514
+
515
+ }
516
+
517
+ // Internal: Ensure GPU resources for repacking SH into the atlas 3D texture
518
+ function _ensureRepackResources() {
519
+
520
+ if ( _repackMaterials !== null ) return;
521
+
522
+ _ensureScene();
523
+
524
+ // Create 7 materials, one per output texture packing
525
+ // Texture 0: (c0.r, c0.g, c0.b, c1.r)
526
+ // Texture 1: (c1.g, c1.b, c2.r, c2.g)
527
+ // Texture 2: (c2.b, c3.r, c3.g, c3.b)
528
+ // Texture 3: (c4.r, c4.g, c4.b, c5.r)
529
+ // Texture 4: (c5.g, c5.b, c6.r, c6.g)
530
+ // Texture 5: (c6.b, c7.r, c7.g, c7.b)
531
+ // Texture 6: (c8.r, c8.g, c8.b, 0.0)
532
+
533
+ const repackVertexShader = /* glsl */`
534
+ void main() {
535
+ gl_Position = vec4( position.xy, 0.0, 1.0 );
536
+ }
537
+ `;
538
+
539
+ _repackMaterials = [];
540
+
541
+ for ( let t = 0; t < 7; t ++ ) {
542
+
543
+ _repackMaterials[ t ] = new ShaderMaterial( {
544
+ precision: 'highp',
545
+ defines: {
546
+ TEXTURE_INDEX: t
547
+ },
548
+ uniforms: {
549
+ batchTexture: { value: null },
550
+ resolution: { value: new Vector3() },
551
+ sliceZ: { value: 0 }
552
+ },
553
+ vertexShader: repackVertexShader,
554
+ fragmentShader: /* glsl */`
555
+ uniform sampler2D batchTexture;
556
+ uniform vec3 resolution;
557
+ uniform int sliceZ;
558
+
559
+ void main() {
560
+
561
+ int ix = int( gl_FragCoord.x );
562
+ int iy = int( gl_FragCoord.y );
563
+ int iz = sliceZ;
564
+
565
+ int probeIndex = ix + iy * int( resolution.x ) + iz * int( resolution.x ) * int( resolution.y );
566
+
567
+ // Read 9 SH coefficients from the batch texture row
568
+ vec4 c0 = texelFetch( batchTexture, ivec2( 0, probeIndex ), 0 );
569
+ vec4 c1 = texelFetch( batchTexture, ivec2( 1, probeIndex ), 0 );
570
+ vec4 c2 = texelFetch( batchTexture, ivec2( 2, probeIndex ), 0 );
571
+ vec4 c3 = texelFetch( batchTexture, ivec2( 3, probeIndex ), 0 );
572
+ vec4 c4 = texelFetch( batchTexture, ivec2( 4, probeIndex ), 0 );
573
+ vec4 c5 = texelFetch( batchTexture, ivec2( 5, probeIndex ), 0 );
574
+ vec4 c6 = texelFetch( batchTexture, ivec2( 6, probeIndex ), 0 );
575
+ vec4 c7 = texelFetch( batchTexture, ivec2( 7, probeIndex ), 0 );
576
+ vec4 c8 = texelFetch( batchTexture, ivec2( 8, probeIndex ), 0 );
577
+
578
+ // Pack into the output format for this texture index
579
+ #if TEXTURE_INDEX == 0
580
+ gl_FragColor = vec4( c0.rgb, c1.r );
581
+ #elif TEXTURE_INDEX == 1
582
+ gl_FragColor = vec4( c1.gb, c2.rg );
583
+ #elif TEXTURE_INDEX == 2
584
+ gl_FragColor = vec4( c2.b, c3.rgb );
585
+ #elif TEXTURE_INDEX == 3
586
+ gl_FragColor = vec4( c4.rgb, c5.r );
587
+ #elif TEXTURE_INDEX == 4
588
+ gl_FragColor = vec4( c5.gb, c6.rg );
589
+ #elif TEXTURE_INDEX == 5
590
+ gl_FragColor = vec4( c6.b, c7.rgb );
591
+ #else
592
+ gl_FragColor = vec4( c8.rgb, 0.0 );
593
+ #endif
594
+
595
+ }
596
+ `
597
+ } );
598
+
599
+ }
600
+
601
+ }
602
+
603
+ // Internal: Ensure cube render target and camera exist with the right parameters
604
+ function _ensureBakeResources( options ) {
605
+
606
+ const {
607
+ cubemapSize = 8,
608
+ near = 0.1,
609
+ far = 100
610
+ } = options;
611
+
612
+ if ( _cubeRenderTarget === null || cubemapSize !== _cachedCubemapSize || near !== _cachedNear || far !== _cachedFar ) {
613
+
614
+ if ( _cubeRenderTarget !== null ) _cubeRenderTarget.dispose();
615
+
616
+ _cubeRenderTarget = new WebGLCubeRenderTarget( cubemapSize, { type: HalfFloatType } );
617
+ _cubeCamera = new CubeCamera( near, far, _cubeRenderTarget );
618
+ _cachedCubemapSize = cubemapSize;
619
+ _cachedNear = near;
620
+ _cachedFar = far;
621
+
622
+ }
623
+
624
+ _ensureGPUResources( cubemapSize );
625
+
626
+ return { cubeRenderTarget: _cubeRenderTarget, cubeCamera: _cubeCamera };
627
+
628
+ }
629
+
630
+ function _ensureBatchTarget( totalProbes ) {
631
+
632
+ if ( _batchTarget === null || _batchTargetProbes !== totalProbes ) {
633
+
634
+ if ( _batchTarget !== null ) _batchTarget.dispose();
635
+
636
+ _batchTarget = new WebGLRenderTarget( 9, totalProbes, {
637
+ type: FloatType,
638
+ minFilter: NearestFilter,
639
+ magFilter: NearestFilter,
640
+ depthBuffer: false
641
+ } );
642
+
643
+ _batchTargetProbes = totalProbes;
644
+
645
+ }
646
+
647
+ return _batchTarget;
648
+
649
+ }
650
+
651
+ export { LightProbeGrid };
@@ -647,7 +647,7 @@ class LineMaterial extends ShaderMaterial {
647
647
 
648
648
  /**
649
649
  * The size of the viewport, in screen pixels. This must be kept updated to make
650
- * screen-space rendering accurate.The `LineSegments2.onBeforeRender` callback
650
+ * screen-space rendering accurate. The `LineSegments2.onBeforeRender` callback
651
651
  * performs the update for visible objects.
652
652
  *
653
653
  * @type {Vector2}