@unikia/upe-renderer 0.186.110 → 0.187.11

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 (506) hide show
  1. package/README.md +5 -7
  2. package/UPSTREAM.md +4 -4
  3. package/build/three.core.js +853 -277
  4. package/build/three.module.js +1098 -1280
  5. package/build/three.tsl.js +41938 -686
  6. package/build/three.webgpu.js +10604 -49055
  7. package/build/three.webgpu.nodes.js +9249 -5788
  8. package/examples/jsm/Addons.js +2 -0
  9. package/examples/jsm/animation/CCDIKSolver.js +17 -5
  10. package/examples/jsm/controls/FirstPersonControls.js +1 -1
  11. package/examples/jsm/controls/OrbitControls.js +27 -14
  12. package/examples/jsm/csm/CSMShader.js +74 -3
  13. package/examples/jsm/curves/CurveExtras.js +4 -4
  14. package/examples/jsm/curves/NURBSCurve.js +14 -0
  15. package/examples/jsm/exporters/EXRExporter.js +673 -16
  16. package/examples/jsm/exporters/GLTFExporter.js +4 -4
  17. package/examples/jsm/exporters/KTX2Exporter.js +1 -1
  18. package/examples/jsm/exporters/OBJExporter.js +48 -5
  19. package/examples/jsm/exporters/PLYExporter.js +22 -11
  20. package/examples/jsm/generators/CityGenerator.js +3 -2
  21. package/examples/jsm/generators/city/SkyscraperGenerator.js +63 -21
  22. package/examples/jsm/gpgpu/BitonicSort.js +30 -23
  23. package/examples/jsm/helpers/VertexTangentsHelper.js +1 -1
  24. package/examples/jsm/inspector/Extension.js +1 -1
  25. package/examples/jsm/inspector/Inspector.js +6 -46
  26. package/examples/jsm/inspector/RendererInspector.js +43 -8
  27. package/examples/jsm/inspector/Storage.js +49 -0
  28. package/examples/jsm/inspector/extensions/color-grading/ColorGrading.js +32 -27
  29. package/examples/jsm/inspector/tabs/Parameters.js +5 -1
  30. package/examples/jsm/inspector/tabs/Performance.js +22 -7
  31. package/examples/jsm/inspector/tabs/Settings.js +1 -1
  32. package/examples/jsm/inspector/tabs/Timeline.js +83 -7
  33. package/examples/jsm/inspector/tabs/Viewer.js +25 -10
  34. package/examples/jsm/inspector/ui/Profiler.js +1 -1
  35. package/examples/jsm/inspector/ui/Style.js +21 -53
  36. package/examples/jsm/inspector/ui/Values.js +28 -3
  37. package/examples/jsm/libs/fflate.module.js +83 -56
  38. package/examples/jsm/libs/mikktspace.README.md +27 -0
  39. package/examples/jsm/libs/mikktspace.module.js +721 -109
  40. package/examples/jsm/lighting/ClusteredLighting.js +100 -2
  41. package/examples/jsm/lighting/LightMapper.js +295 -0
  42. package/examples/jsm/lighting/LightProbeGrid.js +242 -139
  43. package/examples/jsm/lighting/LightProbeGridWebGL.js +30 -14
  44. package/examples/jsm/lighting/vxgi/VXGIConeTracer.js +54 -5
  45. package/examples/jsm/lighting/vxgi/VXGIIrradiance.js +43 -0
  46. package/examples/jsm/lighting/vxgi/VXGINode.js +13 -56
  47. package/examples/jsm/lighting/vxgi/VXGISceneCollector.js +316 -1
  48. package/examples/jsm/lighting/vxgi/VXGIVolume.js +69 -59
  49. package/examples/jsm/lights/SunLight.js +9 -4
  50. package/examples/jsm/lights/SunLightNode.js +3 -3
  51. package/examples/jsm/lines/LineMaterial.js +26 -10
  52. package/examples/jsm/loaders/3DMLoader.js +10 -1
  53. package/examples/jsm/loaders/3MFLoader.js +5 -1
  54. package/examples/jsm/loaders/AMFLoader.js +2 -0
  55. package/examples/jsm/loaders/BVHLoader.js +2 -0
  56. package/examples/jsm/loaders/ColladaLoader.js +8 -0
  57. package/examples/jsm/loaders/DDSLoader.js +1 -1
  58. package/examples/jsm/loaders/DRACOLoader.js +5 -1
  59. package/examples/jsm/loaders/EXRLoader.js +120 -104
  60. package/examples/jsm/loaders/FBXLoader.js +4 -0
  61. package/examples/jsm/loaders/FontLoader.js +2 -0
  62. package/examples/jsm/loaders/GCodeLoader.js +5 -9
  63. package/examples/jsm/loaders/GLTFLoader.js +112 -31
  64. package/examples/jsm/loaders/GaussianSplatPLYLoader.js +2 -0
  65. package/examples/jsm/loaders/HDRCubeTextureLoader.js +3 -0
  66. package/examples/jsm/loaders/IESLoader.js +46 -12
  67. package/examples/jsm/loaders/JXLLoader.js +159 -0
  68. package/examples/jsm/loaders/KMZLoader.js +6 -0
  69. package/examples/jsm/loaders/KSPLATLoader.js +2 -0
  70. package/examples/jsm/loaders/KTX2Loader.js +49 -4
  71. package/examples/jsm/loaders/KTXLoader.js +5 -3
  72. package/examples/jsm/loaders/LDrawLoader.js +15 -22
  73. package/examples/jsm/loaders/LUT3dlLoader.js +5 -1
  74. package/examples/jsm/loaders/LUTCubeLoader.js +6 -2
  75. package/examples/jsm/loaders/LUTImageLoader.js +2 -0
  76. package/examples/jsm/loaders/LWOLoader.js +6 -0
  77. package/examples/jsm/loaders/MD2Loader.js +2 -0
  78. package/examples/jsm/loaders/MDDLoader.js +4 -0
  79. package/examples/jsm/loaders/MTLLoader.js +8 -0
  80. package/examples/jsm/loaders/MaterialXLoader.js +57 -5
  81. package/examples/jsm/loaders/NRRDLoader.js +4 -2
  82. package/examples/jsm/loaders/OBJLoader.js +10 -4
  83. package/examples/jsm/loaders/PCDLoader.js +6 -2
  84. package/examples/jsm/loaders/PDBLoader.js +5 -3
  85. package/examples/jsm/loaders/PLYLoader.js +39 -15
  86. package/examples/jsm/loaders/PVRLoader.js +2 -2
  87. package/examples/jsm/loaders/SPLATLoader.js +2 -0
  88. package/examples/jsm/loaders/SPZLoader.js +2 -0
  89. package/examples/jsm/loaders/STLLoader.js +3 -1
  90. package/examples/jsm/loaders/SVGLoader.js +27 -49
  91. package/examples/jsm/loaders/TDSLoader.js +4 -0
  92. package/examples/jsm/loaders/TGALoader.js +6 -5
  93. package/examples/jsm/loaders/TTFLoader.js +2 -0
  94. package/examples/jsm/loaders/USDLoader.js +14 -0
  95. package/examples/jsm/loaders/UltraHDRLoader.js +2 -0
  96. package/examples/jsm/loaders/VOXLoader.js +3 -0
  97. package/examples/jsm/loaders/VRMLLoader.js +4 -0
  98. package/examples/jsm/loaders/VTKLoader.js +2 -0
  99. package/examples/jsm/loaders/XYZLoader.js +2 -0
  100. package/examples/jsm/loaders/collada/ColladaComposer.js +15 -8
  101. package/examples/jsm/loaders/materialx/MaterialXDocument.js +610 -138
  102. package/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js +12 -95
  103. package/examples/jsm/loaders/materialx/MaterialXLog.js +4 -0
  104. package/examples/jsm/loaders/materialx/MaterialXNodeDefs.js +99 -0
  105. package/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js +760 -1
  106. package/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js +222 -372
  107. package/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js +163 -259
  108. package/examples/jsm/loaders/materialx/MaterialXUtils.js +25 -0
  109. package/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js +161 -159
  110. package/examples/jsm/loaders/usd/USDAParser.js +56 -47
  111. package/examples/jsm/loaders/usd/USDComposer.js +25 -30
  112. package/examples/jsm/math/ColorConverter.js +7 -3
  113. package/examples/jsm/math/Lut.js +2 -2
  114. package/examples/jsm/math/OBB.js +3 -3
  115. package/examples/jsm/math/Octree.js +20 -17
  116. package/examples/jsm/objects/GaussianSplat.js +5 -4
  117. package/examples/jsm/objects/Reflector.js +5 -0
  118. package/examples/jsm/objects/SkyMesh.js +14 -7
  119. package/examples/jsm/objects/Water2Mesh.js +2 -2
  120. package/examples/jsm/physics/RapierPhysics.js +2 -2
  121. package/examples/jsm/pipelines/MeshletDrawingPipeline.js +5571 -0
  122. package/examples/jsm/pipelines/VisibilityBufferDrawingPipeline.js +954 -0
  123. package/examples/jsm/postprocessing/BokehPass.js +1 -1
  124. package/examples/jsm/postprocessing/GTAOPass.js +26 -18
  125. package/examples/jsm/renderers/SVGRenderer.js +3 -2
  126. package/examples/jsm/shaders/GTAOShader.js +7 -4
  127. package/examples/jsm/shaders/PoissonDenoiseShader.js +1 -10
  128. package/examples/jsm/tsl/WebGLNodesHandler.js +21 -9
  129. package/examples/jsm/tsl/display/AfterImageNode.js +3 -3
  130. package/examples/jsm/tsl/display/BilateralBlurNode.js +3 -3
  131. package/examples/jsm/tsl/display/BloomNode.js +3 -3
  132. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +8 -19
  133. package/examples/jsm/tsl/display/DenoiseNode.js +5 -5
  134. package/examples/jsm/tsl/display/DepthOfFieldNode.js +3 -3
  135. package/examples/jsm/tsl/display/DotScreenNode.js +3 -3
  136. package/examples/jsm/tsl/display/FSR1Node.js +3 -3
  137. package/examples/jsm/tsl/display/FXAANode.js +3 -10
  138. package/examples/jsm/tsl/display/FilmNode.js +3 -3
  139. package/examples/jsm/tsl/display/GTAONode.js +33 -25
  140. package/examples/jsm/tsl/display/GaussianBlurNode.js +3 -3
  141. package/examples/jsm/tsl/display/GodraysNode.js +5 -19
  142. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +8 -4
  143. package/examples/jsm/tsl/display/LensflareNode.js +3 -3
  144. package/examples/jsm/tsl/display/Lut3DNode.js +3 -3
  145. package/examples/jsm/tsl/display/OITPassNode.js +0 -11
  146. package/examples/jsm/tsl/display/OutlineNode.js +107 -5
  147. package/examples/jsm/tsl/display/PixelationPassNode.js +85 -193
  148. package/examples/jsm/tsl/display/RGBShiftNode.js +3 -3
  149. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +23 -126
  150. package/examples/jsm/tsl/display/SMAANode.js +3 -3
  151. package/examples/jsm/tsl/display/SSAONode.js +6 -20
  152. package/examples/jsm/tsl/display/SSGINode.js +36 -29
  153. package/examples/jsm/tsl/display/SSRNode.js +135 -63
  154. package/examples/jsm/tsl/display/SSSNode.js +6 -20
  155. package/examples/jsm/tsl/display/SharpenNode.js +3 -3
  156. package/examples/jsm/tsl/display/SobelOperatorNode.js +3 -3
  157. package/examples/jsm/tsl/display/TAAUNode.js +10 -42
  158. package/examples/jsm/tsl/display/TRAANode.js +11 -43
  159. package/examples/jsm/tsl/display/TemporalReprojectNode.js +42 -47
  160. package/examples/jsm/tsl/display/TransitionNode.js +3 -3
  161. package/examples/jsm/tsl/display/lensDirt.js +30 -0
  162. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +482 -121
  163. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +41 -140
  164. package/examples/jsm/tsl/lighting/LightProbeGridNode.js +72 -25
  165. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +6 -0
  166. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +6 -0
  167. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +6 -0
  168. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +6 -0
  169. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +6 -0
  170. package/examples/jsm/tsl/shadows/TileShadowNode.js +102 -14
  171. package/examples/jsm/tsl/utils/Raymarching.js +1 -1
  172. package/examples/jsm/tsl/utils/SoftParticles.js +5 -12
  173. package/examples/jsm/tsl/utils/SpecularHelpers.js +47 -70
  174. package/examples/jsm/tsl/utils/TAAUtils.js +6 -17
  175. package/examples/jsm/utils/BufferGeometryUtils.js +110 -88
  176. package/examples/jsm/utils/MeshletGeometryUtils.js +417 -0
  177. package/examples/jsm/utils/SceneOptimizer.js +2 -1
  178. package/examples/jsm/utils/SceneUtils.js +1 -1
  179. package/examples/jsm/utils/unwrapUVs.js +865 -0
  180. package/examples/jsm/webxr/XREstimatedLight.js +11 -4
  181. package/package.json +3 -3
  182. package/src/Three.TSL.js +2 -683
  183. package/src/Three.WebGPU.Nodes.js +2 -1
  184. package/src/Three.WebGPU.js +2 -1
  185. package/src/animation/AnimationAction.js +1 -1
  186. package/src/animation/AnimationUtils.js +1 -3
  187. package/src/animation/KeyframeTrack.js +19 -0
  188. package/src/cameras/ArrayCamera.js +12 -0
  189. package/src/cameras/CubeCamera.js +3 -3
  190. package/src/constants.js +1 -9
  191. package/src/core/BufferAttribute.js +57 -21
  192. package/src/core/BufferGeometry.js +5 -13
  193. package/src/core/Clock.js +1 -1
  194. package/src/core/InterleavedBuffer.js +28 -18
  195. package/src/core/InterleavedBufferAttribute.js +54 -20
  196. package/src/core/Object3D.js +19 -9
  197. package/src/core/Raycaster.js +2 -0
  198. package/src/core/RenderTarget.js +11 -5
  199. package/src/core/UniformsGroup.js +7 -3
  200. package/src/extras/PMREMGenerator.js +392 -685
  201. package/src/extras/core/Curve.js +4 -0
  202. package/src/extras/core/CurvePath.js +13 -0
  203. package/src/extras/core/ShapePath.js +1 -1
  204. package/src/geometries/EdgesGeometry.js +12 -10
  205. package/src/geometries/LatheGeometry.js +2 -0
  206. package/src/helpers/PolarGridHelper.js +1 -1
  207. package/src/lights/Light.js +11 -0
  208. package/src/lights/LightProbe.js +2 -0
  209. package/src/lights/LightShadow.js +2 -0
  210. package/src/loaders/AnimationLoader.js +2 -0
  211. package/src/loaders/AudioLoader.js +2 -0
  212. package/src/loaders/BufferGeometryLoader.js +2 -0
  213. package/src/loaders/CompressedTextureLoader.js +2 -0
  214. package/src/loaders/CubeTextureLoader.js +2 -0
  215. package/src/loaders/DataTextureLoader.js +2 -0
  216. package/src/loaders/FileLoader.js +2 -0
  217. package/src/loaders/ImageBitmapLoader.js +3 -1
  218. package/src/loaders/ImageLoader.js +1 -0
  219. package/src/loaders/Loader.js +47 -0
  220. package/src/loaders/MaterialLoader.js +2 -0
  221. package/src/loaders/ObjectLoader.js +27 -8
  222. package/src/loaders/TextureLoader.js +5 -3
  223. package/src/loaders/nodes/NodeLoader.js +2 -0
  224. package/src/materials/Material.js +21 -2
  225. package/src/materials/MeshDepthMaterial.js +1 -1
  226. package/src/materials/MeshDistanceMaterial.js +1 -1
  227. package/src/materials/MeshLambertMaterial.js +1 -1
  228. package/src/materials/MeshMatcapMaterial.js +1 -1
  229. package/src/materials/MeshNormalMaterial.js +1 -1
  230. package/src/materials/MeshPhongMaterial.js +1 -1
  231. package/src/materials/MeshPhysicalMaterial.js +90 -11
  232. package/src/materials/MeshStandardMaterial.js +1 -1
  233. package/src/materials/MeshToonMaterial.js +1 -1
  234. package/src/materials/nodes/Line2NodeMaterial.js +32 -10
  235. package/src/materials/nodes/MeshLambertNodeMaterial.js +13 -0
  236. package/src/materials/nodes/MeshPhongNodeMaterial.js +13 -0
  237. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +40 -5
  238. package/src/materials/nodes/MeshToonNodeMaterial.js +13 -0
  239. package/src/materials/nodes/NodeMaterial.js +36 -16
  240. package/src/materials/nodes/NodeMaterialInstance.js +193 -0
  241. package/src/materials/nodes/NodeMaterials.js +1 -0
  242. package/src/materials/nodes/PointsNodeMaterial.js +1 -1
  243. package/src/materials/nodes/SpriteNodeMaterial.js +3 -3
  244. package/src/materials/nodes/manager/NodeMaterialObserver.js +191 -22
  245. package/src/math/Box3.js +2 -2
  246. package/src/math/Color.js +8 -8
  247. package/src/math/ColorManagement.js +2 -21
  248. package/src/math/FrustumArray.js +12 -0
  249. package/src/math/Interpolant.js +1 -1
  250. package/src/math/Line3.js +2 -4
  251. package/src/math/MathUtils.js +33 -46
  252. package/src/math/Matrix2.js +1 -1
  253. package/src/math/Matrix3.js +1 -1
  254. package/src/math/Matrix4.js +1 -1
  255. package/src/math/Triangle.js +2 -1
  256. package/src/math/Vector2.js +1 -1
  257. package/src/math/Vector3.js +1 -1
  258. package/src/math/Vector4.js +1 -1
  259. package/src/nodes/Nodes.js +1 -0
  260. package/src/nodes/TSL.js +2 -0
  261. package/src/nodes/accessors/Arrays.js +1 -1
  262. package/src/nodes/accessors/Batch.js +29 -23
  263. package/src/nodes/accessors/BufferAttributeNode.js +21 -1
  264. package/src/nodes/accessors/BuiltinNode.js +6 -0
  265. package/src/nodes/accessors/Camera.js +100 -93
  266. package/src/nodes/accessors/ClippingNode.js +17 -6
  267. package/src/nodes/accessors/CubeTextureNode.js +12 -24
  268. package/src/nodes/accessors/Instance.js +198 -160
  269. package/src/nodes/accessors/Lights.js +19 -6
  270. package/src/nodes/accessors/MaterialNode.js +33 -4
  271. package/src/nodes/accessors/Morph.js +81 -22
  272. package/src/nodes/accessors/Normal.js +0 -42
  273. package/src/nodes/accessors/Object3DNode.js +6 -0
  274. package/src/nodes/accessors/PointUVNode.js +6 -0
  275. package/src/nodes/accessors/ReferenceAttributeNode.js +279 -0
  276. package/src/nodes/accessors/ReferenceBaseNode.js +6 -0
  277. package/src/nodes/accessors/ReferenceNode.js +6 -0
  278. package/src/nodes/accessors/Skinning.js +57 -52
  279. package/src/nodes/accessors/StorageBufferNode.js +3 -12
  280. package/src/nodes/accessors/TextureBicubic.js +30 -27
  281. package/src/nodes/accessors/TextureNode.js +164 -78
  282. package/src/nodes/accessors/TextureSizeNode.js +6 -0
  283. package/src/nodes/accessors/UniformArrayNode.js +8 -15
  284. package/src/nodes/accessors/VelocityNode.js +13 -8
  285. package/src/nodes/code/CodeNode.js +6 -0
  286. package/src/nodes/code/ExpressionNode.js +6 -0
  287. package/src/nodes/code/FunctionCallNode.js +3 -3
  288. package/src/nodes/code/FunctionNode.js +15 -13
  289. package/src/nodes/core/ArrayNode.js +3 -3
  290. package/src/nodes/core/AssignNode.js +10 -9
  291. package/src/nodes/core/AttributeNode.js +39 -0
  292. package/src/nodes/core/BypassNode.js +6 -0
  293. package/src/nodes/core/ConstNode.js +31 -1
  294. package/src/nodes/core/ContextNode.js +11 -6
  295. package/src/nodes/core/IndexNode.js +6 -0
  296. package/src/nodes/core/InputNode.js +6 -0
  297. package/src/nodes/core/InspectorNode.js +17 -31
  298. package/src/nodes/core/IsolateNode.js +8 -0
  299. package/src/nodes/core/Node.js +367 -67
  300. package/src/nodes/core/NodeBuilder.js +664 -222
  301. package/src/nodes/core/NodeUtils.js +25 -0
  302. package/src/nodes/core/NodeVar.js +10 -1
  303. package/src/nodes/core/OutputStructNode.js +6 -0
  304. package/src/nodes/core/OverrideContextNode.js +38 -37
  305. package/src/nodes/core/PropertyNode.js +14 -0
  306. package/src/nodes/core/StackNode.js +33 -21
  307. package/src/nodes/core/StructNode.js +6 -0
  308. package/src/nodes/core/StructTypeNode.js +6 -0
  309. package/src/nodes/core/SubBuildNode.js +8 -0
  310. package/src/nodes/core/TempNode.js +10 -35
  311. package/src/nodes/core/UniformGroupNode.js +6 -0
  312. package/src/nodes/core/VarNode.js +43 -135
  313. package/src/nodes/core/VaryingNode.js +33 -2
  314. package/src/nodes/display/BlendModes.js +5 -40
  315. package/src/nodes/display/BumpMapNode.js +17 -7
  316. package/src/nodes/display/ColorAdjustment.js +22 -10
  317. package/src/nodes/display/ColorSpaceFunctions.js +2 -14
  318. package/src/nodes/display/ColorSpaceNode.js +3 -3
  319. package/src/nodes/display/FrontFacingNode.js +6 -0
  320. package/src/nodes/display/NormalMapNode.js +3 -3
  321. package/src/nodes/display/PassNode.js +75 -16
  322. package/src/nodes/display/RenderOutputNode.js +22 -5
  323. package/src/nodes/display/ScreenNode.js +6 -0
  324. package/src/nodes/display/ToneMappingFunctions.js +9 -51
  325. package/src/nodes/display/ToneMappingNode.js +3 -3
  326. package/src/nodes/display/ToonOutlinePassNode.js +66 -2
  327. package/src/nodes/display/ViewportDepthNode.js +34 -4
  328. package/src/nodes/functions/BSDF/BRDF_EON.js +65 -0
  329. package/src/nodes/functions/BSDF/BRDF_GGX.js +5 -3
  330. package/src/nodes/functions/BSDF/BRDF_Sheen.js +2 -16
  331. package/src/nodes/functions/BSDF/D_GGX.js +1 -8
  332. package/src/nodes/functions/BSDF/D_GGX_Anisotropic.js +7 -10
  333. package/src/nodes/functions/BSDF/LTC.js +20 -47
  334. package/src/nodes/functions/BSDF/Schlick_to_F0.js +1 -9
  335. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +1 -9
  336. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +10 -13
  337. package/src/nodes/functions/PhysicalLightingModel.js +84 -51
  338. package/src/nodes/functions/VolumetricLightingModel.js +1 -1
  339. package/src/nodes/functions/material/getAlphaHashThreshold.js +3 -9
  340. package/src/nodes/functions/material/getParallaxCorrectNormal.js +10 -11
  341. package/src/nodes/functions/material/getRoughness.js +3 -1
  342. package/src/nodes/geometry/RangeNode.js +52 -69
  343. package/src/nodes/gpgpu/AtomicFunctionNode.js +11 -6
  344. package/src/nodes/gpgpu/BarrierNode.js +6 -0
  345. package/src/nodes/gpgpu/ComputeBuiltinNode.js +6 -0
  346. package/src/nodes/gpgpu/ComputeNode.js +6 -0
  347. package/src/nodes/gpgpu/SubgroupFunctionNode.js +38 -29
  348. package/src/nodes/gpgpu/WorkgroupInfoNode.js +6 -0
  349. package/src/nodes/lighting/AnalyticLightNode.js +7 -14
  350. package/src/nodes/lighting/BasicEnvironmentNode.js +5 -1
  351. package/src/nodes/lighting/EnvironmentNode.js +58 -8
  352. package/src/nodes/lighting/IESSpotLightNode.js +19 -4
  353. package/src/nodes/lighting/LightProbeNode.js +2 -1
  354. package/src/nodes/lighting/LightUtils.js +2 -2
  355. package/src/nodes/lighting/LightingNode.js +6 -0
  356. package/src/nodes/lighting/LightsNode.js +26 -32
  357. package/src/nodes/lighting/PointShadowNode.js +92 -48
  358. package/src/nodes/lighting/ProjectorLightNode.js +1 -1
  359. package/src/nodes/lighting/RectAreaLightNode.js +13 -14
  360. package/src/nodes/lighting/ShadowBaseNode.js +9 -17
  361. package/src/nodes/lighting/ShadowFilterNode.js +26 -3
  362. package/src/nodes/lighting/ShadowNode.js +13 -11
  363. package/src/nodes/materialx/MaterialXColor.js +2 -14
  364. package/src/nodes/materialx/MaterialXColorTransform.js +1 -7
  365. package/src/nodes/materialx/MaterialXNodes.js +8 -11
  366. package/src/nodes/materialx/MaterialXNoise.js +195 -454
  367. package/src/nodes/math/BitcastNode.js +5 -5
  368. package/src/nodes/math/BitcountNode.js +18 -46
  369. package/src/nodes/math/ConditionalNode.js +92 -22
  370. package/src/nodes/math/Hash.js +1 -1
  371. package/src/nodes/math/MathNode.js +86 -64
  372. package/src/nodes/math/MathUtils.js +2 -2
  373. package/src/nodes/math/OperatorNode.js +42 -59
  374. package/src/nodes/math/PackFloatNode.js +9 -9
  375. package/src/nodes/math/Packed4x8IntegerNode.js +20 -52
  376. package/src/nodes/math/TriNoise3D.js +3 -23
  377. package/src/nodes/math/UnpackFloatNode.js +9 -9
  378. package/src/nodes/pmrem/PMREMNode.js +38 -75
  379. package/src/nodes/pmrem/PMREMUtils.js +108 -272
  380. package/src/nodes/procedural/Checker.js +1 -1
  381. package/src/nodes/tsl/TSLCore.js +199 -74
  382. package/src/nodes/utils/ArrayElementNode.js +19 -1
  383. package/src/nodes/utils/CubeMapNode.js +3 -3
  384. package/src/nodes/utils/DebugNode.js +2 -2
  385. package/src/nodes/utils/EventNode.js +6 -0
  386. package/src/nodes/utils/FlipNode.js +3 -3
  387. package/src/nodes/utils/FunctionOverloadingNode.js +7 -1
  388. package/src/nodes/utils/JoinNode.js +3 -3
  389. package/src/nodes/utils/LoopNode.js +14 -9
  390. package/src/nodes/utils/MemberNode.js +18 -0
  391. package/src/nodes/utils/PostProcessingUtils.js +20 -25
  392. package/src/nodes/utils/RTTNode.js +2 -0
  393. package/src/nodes/utils/ReflectorNode.js +24 -0
  394. package/src/nodes/utils/RotateNode.js +3 -3
  395. package/src/nodes/utils/SampleNode.js +6 -0
  396. package/src/nodes/utils/SetNode.js +3 -3
  397. package/src/nodes/utils/SplitNode.js +6 -0
  398. package/src/nodes/utils/UVUtils.js +2 -2
  399. package/src/objects/BatchedMesh.js +146 -15
  400. package/src/objects/InstancedMesh.js +12 -4
  401. package/src/objects/Line.js +20 -0
  402. package/src/objects/Mesh.js +8 -0
  403. package/src/objects/Points.js +20 -0
  404. package/src/objects/Skeleton.js +26 -0
  405. package/src/objects/SkinnedMesh.js +3 -3
  406. package/src/objects/Sprite.js +10 -0
  407. package/src/renderers/WebGLRenderer.js +104 -70
  408. package/src/renderers/common/Animation.js +5 -1
  409. package/src/renderers/common/Attributes.js +67 -57
  410. package/src/renderers/common/Backend.js +78 -3
  411. package/src/renderers/common/BindGroup.js +11 -0
  412. package/src/renderers/common/Binding.js +0 -11
  413. package/src/renderers/common/Bindings.js +116 -10
  414. package/src/renderers/common/Buffer.js +1 -1
  415. package/src/renderers/common/ClippingContext.js +12 -1
  416. package/src/renderers/common/ComputePipeline.js +17 -1
  417. package/src/renderers/common/DirectRenderPipeline.js +7 -3
  418. package/src/renderers/common/Geometries.js +170 -132
  419. package/src/renderers/common/Info.js +1 -1
  420. package/src/renderers/common/InspectorBase.js +5 -5
  421. package/src/renderers/common/Lighting.js +59 -0
  422. package/src/renderers/common/Pipelines.js +26 -12
  423. package/src/renderers/common/ProgrammableStage.js +1 -17
  424. package/src/renderers/common/RenderContext.js +21 -0
  425. package/src/renderers/common/RenderContexts.js +13 -4
  426. package/src/renderers/common/RenderObject.js +111 -35
  427. package/src/renderers/common/RenderObjects.js +37 -19
  428. package/src/renderers/common/Renderer.js +537 -295
  429. package/src/renderers/common/RendererUtils.js +15 -0
  430. package/src/renderers/common/StandardDrawingPipeline.js +343 -0
  431. package/src/renderers/common/Storage3DTexture.js +11 -0
  432. package/src/renderers/common/StorageArrayTexture.js +10 -0
  433. package/src/renderers/common/StorageTexture.js +0 -9
  434. package/src/renderers/common/Textures.js +144 -37
  435. package/src/renderers/common/UniformsGroup.js +19 -0
  436. package/src/renderers/common/XRManager.js +10 -91
  437. package/src/renderers/common/extras/PMREMGenerator.js +298 -576
  438. package/src/renderers/common/nodes/NodeBuilderState.js +7 -5
  439. package/src/renderers/common/nodes/NodeLibrary.js +11 -35
  440. package/src/renderers/common/nodes/NodeManager.js +80 -31
  441. package/src/renderers/common/nodes/NodeSampledTexture.js +14 -0
  442. package/src/renderers/common/nodes/NodeSampler.js +14 -0
  443. package/src/renderers/common/nodes/NodeStorageBuffer.js +1 -1
  444. package/src/renderers/common/nodes/NodeUniformBuffer.js +1 -14
  445. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +13 -4
  446. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +8 -8
  447. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +23 -11
  448. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +21 -2
  449. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +1 -1
  450. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +18 -2
  451. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +104 -7
  452. package/src/renderers/shaders/ShaderChunk/morphcolor_vertex.glsl.js +11 -2
  453. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +36 -20
  454. package/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js +5 -0
  455. package/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js +6 -0
  456. package/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js +5 -0
  457. package/src/renderers/shaders/ShaderChunk.js +0 -2
  458. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +4 -18
  459. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -1
  460. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
  461. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +8 -1
  462. package/src/renderers/shaders/ShaderLib.js +3 -0
  463. package/src/renderers/shaders/UniformsLib.js +4 -5
  464. package/src/renderers/webgl/WebGLBackground.js +3 -3
  465. package/src/renderers/webgl/WebGLBindingStates.js +4 -2
  466. package/src/renderers/webgl/WebGLCapabilities.js +7 -1
  467. package/src/renderers/webgl/WebGLEnvironments.js +2 -2
  468. package/src/renderers/webgl/WebGLGeometries.js +42 -14
  469. package/src/renderers/webgl/WebGLMaterials.js +15 -2
  470. package/src/renderers/webgl/WebGLOutput.js +37 -1
  471. package/src/renderers/webgl/WebGLProgram.js +13 -54
  472. package/src/renderers/webgl/WebGLPrograms.js +22 -8
  473. package/src/renderers/webgl/WebGLRenderStates.js +11 -8
  474. package/src/renderers/webgl/WebGLShadowMap.js +6 -4
  475. package/src/renderers/webgl/WebGLState.js +10 -6
  476. package/src/renderers/webgl/WebGLTextures.js +129 -77
  477. package/src/renderers/webgl/WebGLUniforms.js +44 -6
  478. package/src/renderers/webgl/WebGLUniformsGroups.js +75 -69
  479. package/src/renderers/webgl-fallback/WebGLBackend.js +206 -278
  480. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +154 -20
  481. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +45 -42
  482. package/src/renderers/webgl-fallback/utils/WebGLState.js +29 -4
  483. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +129 -49
  484. package/src/renderers/webgl-fallback/utils/WebGLVertexArrayUtils.js +346 -0
  485. package/src/renderers/webgpu/WebGPUBackend.js +140 -82
  486. package/src/renderers/webgpu/WebGPURenderer.js +1 -1
  487. package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +10 -10
  488. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +10 -10
  489. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +135 -60
  490. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +128 -55
  491. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
  492. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +15 -12
  493. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +55 -19
  494. package/src/renderers/webgpu/utils/WebGPUUtils.js +20 -3
  495. package/src/renderers/webxr/WebXRController.js +3 -3
  496. package/src/renderers/webxr/WebXRManager.js +5 -90
  497. package/src/scenes/Scene.js +4 -4
  498. package/src/textures/CompressedTexture.js +2 -2
  499. package/src/textures/DepthTexture.js +2 -2
  500. package/src/textures/FramebufferTexture.js +11 -0
  501. package/src/textures/Texture.js +29 -1
  502. package/src/textures/TextureSource.js +1 -1
  503. package/src/upe.js +1 -1
  504. package/src/utils.js +4 -4
  505. package/examples/jsm/libs/surfaceNet.js +0 -201
  506. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +0 -186
@@ -1,85 +1,65 @@
1
1
  import NodeMaterial from '../../../materials/nodes/NodeMaterial.js';
2
- import { sphericalGaussianBlur, ggxConvolution } from '../../../nodes/pmrem/PMREMUtils.js';
2
+ import { sphericalGaussianBlur, ggxConvolution, ggxIntegration } from '../../../nodes/pmrem/PMREMUtils.js';
3
3
  import { equirectUV } from '../../../nodes/utils/EquirectUV.js';
4
+ import { positionWorldDirection } from '../../../nodes/accessors/Position.js';
4
5
  import { uniform } from '../../../nodes/core/UniformNode.js';
5
6
  import { texture } from '../../../nodes/accessors/TextureNode.js';
6
7
  import { cubeTexture } from '../../../nodes/accessors/CubeTextureNode.js';
7
- import { float, int, uint } from '../../../nodes/tsl/TSLBase.js';
8
- import { attribute } from '../../../nodes/core/AttributeNode.js';
8
+ import { Fn, int, uint, vec4 } from '../../../nodes/tsl/TSLBase.js';
9
9
 
10
- import { OrthographicCamera } from '../../../cameras/OrthographicCamera.js';
11
10
  import { Color } from '../../../math/Color.js';
11
+ import { floorPowerOfTwo } from '../../../math/MathUtils.js';
12
12
  import { Vector3 } from '../../../math/Vector3.js';
13
- import { BufferGeometry } from '../../../core/BufferGeometry.js';
14
- import { BufferAttribute } from '../../../core/BufferAttribute.js';
15
- import { RenderTarget } from '../../../core/RenderTarget.js';
16
13
  import { Mesh } from '../../../objects/Mesh.js';
17
- import { PerspectiveCamera } from '../../../cameras/PerspectiveCamera.js';
18
- import { MeshBasicMaterial } from '../../../materials/MeshBasicMaterial.js';
19
14
  import { BoxGeometry } from '../../../geometries/BoxGeometry.js';
15
+ import { CubeCamera } from '../../../cameras/CubeCamera.js';
16
+ import CubeRenderTarget from '../CubeRenderTarget.js';
20
17
  import {
21
18
  CubeReflectionMapping,
22
19
  CubeRefractionMapping,
23
- CubeUVReflectionMapping,
24
- LinearFilter,
20
+ LinearMipmapLinearFilter,
25
21
  NoBlending,
26
- RGBAFormat,
27
22
  HalfFloatType,
28
23
  BackSide,
29
24
  LinearSRGBColorSpace
30
25
  } from '../../../constants.js';
31
26
  import { warnOnce } from '../../../utils.js';
32
27
 
33
- const LOD_MIN = 4;
28
+ // Smaller inputs are upsampled so that every PMREM has enough mip levels.
29
+ const MIN_SIZE = 256;
34
30
 
35
- // The number of extra mips.
36
- // Used for scene blur in fromScene() method.
37
- const EXTRA_LODS = 6;
31
+ // Log2 of the face size of the roughest mip level. Smaller faces can't
32
+ // represent the diffuse irradiance that is stored in this level.
33
+ const LOD_MIN = 3;
38
34
 
39
- // The number of spiral samples per blur pass.
40
- // Used for scene blur in fromScene() method.
35
+ // Spiral samples per pass of the initial fromScene() blur.
41
36
  const BLUR_SAMPLES = 20;
42
37
 
43
- // GGX VNDF importance sampling configuration
38
+ // GGX VNDF samples for the sharp mip levels.
44
39
  const GGX_SAMPLES = 256;
45
40
 
46
- const _flatCamera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
47
- const _cubeCamera = /*@__PURE__*/ new PerspectiveCamera( 90, 1 );
48
- const _clearColor = /*@__PURE__*/ new Color();
49
- let _oldTarget = null;
50
- let _oldActiveCubeFace = 0;
51
- let _oldActiveMipmapLevel = 0;
41
+ // Integrate a small source mip for the rough levels to avoid sampling noise.
42
+ const INTEGRATION_SIZE = 16;
43
+ const INTEGRATION_LEVELS = 3;
52
44
 
53
45
  const _origin = /*@__PURE__*/ new Vector3();
54
- const _direction = /*@__PURE__*/ new Vector3();
46
+ const _clearColor = /*@__PURE__*/ new Color();
55
47
 
56
- // maps blur materials to their uniforms dictionary
48
+ // maps materials to their uniforms dictionary
57
49
 
58
50
  const _uniformsMap = new WeakMap();
59
51
 
60
- // WebGPU Face indices
61
- const _faceLib = [
62
- 3, 1, 5,
63
- 0, 4, 2
64
- ];
65
-
66
- const _outputDirection = /*@__PURE__*/ attribute( 'outputDirection' ).normalize();
67
-
68
52
  /**
69
- * This class generates a Prefiltered, Mipmapped Radiance Environment Map
70
- * (PMREM) from a cubeMap environment texture. This allows different levels of
71
- * blur to be quickly accessed based on material roughness. It is packed into a
72
- * special CubeUV format that allows us to perform custom interpolation so that
73
- * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
74
- * chain, it only goes down to the LOD_MIN level (above), and then creates extra
75
- * even more filtered 'mips' at the same LOD_MIN resolution, associated with
76
- * higher roughness levels. In this way we maintain resolution to smoothly
77
- * interpolate diffuse lighting while limiting sampling computation.
53
+ * Generates a Prefiltered, Mipmapped Radiance Environment Map (PMREM) for
54
+ * image-based lighting. The result is a cube render target whose mip levels
55
+ * store GGX-filtered radiance at increasing roughness, from a mirror at level 0
56
+ * to roughness 1. See {@link PMREMGenerator.lodToRoughness} for the mapping.
78
57
  *
79
- * The prefiltering uses GGX VNDF (Visible Normal Distribution Function)
80
- * importance sampling based on "Sampling the GGX Distribution of Visible Normals"
81
- * (Heitz, 2018) to generate environment maps that accurately match the GGX BRDF
82
- * used in material rendering for physically-based image-based lighting.
58
+ * Filtering assumes the view direction equals the surface normal. Sharp levels
59
+ * use GGX visible normal sampling (Heitz, 2018), while rough levels integrate a
60
+ * lower-resolution source cubemap.
61
+ *
62
+ * @see {@link https://jcgt.org/published/0007/04/01/ | Sampling the GGX Distribution of Visible Normals}
83
63
  */
84
64
  class PMREMGenerator {
85
65
 
@@ -91,44 +71,35 @@ class PMREMGenerator {
91
71
  constructor( renderer ) {
92
72
 
93
73
  this._renderer = renderer;
94
- this._pingPongRenderTarget = null;
95
74
 
96
- this._lodMax = 0;
97
75
  this._cubeSize = 0;
98
- this._sizeLods = [];
99
- this._lodMeshes = [];
76
+ this._sourceTarget = null;
100
77
 
101
- this._blurMaterial = null;
102
- this._ggxMaterial = null;
78
+ this._cubeCamera = new CubeCamera( 1, 10, null );
79
+ this._boxMesh = new Mesh( new BoxGeometry( 5, 5, 5 ), null );
103
80
 
104
81
  this._cubemapMaterial = null;
105
82
  this._equirectMaterial = null;
106
- this._backgroundBox = null;
107
83
 
108
- }
109
-
110
- get _hasInitialized() {
111
-
112
- return this._renderer.hasInitialized();
84
+ this._blurMaterial = null;
85
+ this._ggxMaterial = null;
86
+ this._integrationMaterial = null;
113
87
 
114
88
  }
115
89
 
116
90
  /**
117
- * Generates a PMREM from a supplied Scene, which can be faster than using an
118
- * image if networking bandwidth is low. Optional sigma specifies a blur radius
119
- * in radians to be applied to the scene before PMREM generation. Optional near
120
- * and far planes ensure the scene is rendered in its entirety.
91
+ * Generates a PMREM from a scene, optionally applying a Gaussian blur before
92
+ * GGX filtering.
121
93
  *
122
94
  * @param {Scene} scene - The scene to be captured.
123
95
  * @param {number} [sigma=0] - The blur radius in radians.
124
96
  * @param {number} [near=0.1] - The near plane distance.
125
97
  * @param {number} [far=100] - The far plane distance.
126
98
  * @param {Object} [options={}] - The configuration options.
127
- * @param {number} [options.size=256] - The texture size of the PMREM.
99
+ * @param {number} [options.size=256] - The texture size of the PMREM, rounded down to a power of two and at least 256.
128
100
  * @param {Vector3} [options.position=origin] - The position of the internal cube camera that renders the scene.
129
- * @param {?RenderTarget} [options.renderTarget=null] - The render target to use.
130
- * @return {RenderTarget} The resulting PMREM.
131
- * @see {@link PMREMGenerator#fromScene}
101
+ * @param {?CubeRenderTarget} [options.renderTarget=null] - The render target to use.
102
+ * @return {CubeRenderTarget} The resulting PMREM.
132
103
  */
133
104
  fromScene( scene, sigma = 0, near = 0.1, far = 100, options = {} ) {
134
105
 
@@ -138,44 +109,66 @@ class PMREMGenerator {
138
109
  renderTarget = null,
139
110
  } = options;
140
111
 
112
+ const renderer = this._renderer;
113
+
141
114
  this._setSize( size );
142
115
 
143
- if ( this._hasInitialized === false ) {
116
+ if ( renderer.hasInitialized() === false ) {
144
117
 
145
118
  throw new Error( 'THREE.PMREMGenerator: .fromScene() called before the backend is initialized. Use "await renderer.init();" before using this method.' );
146
119
 
147
120
  }
148
121
 
149
- _oldTarget = this._renderer.getRenderTarget();
150
- _oldActiveCubeFace = this._renderer.getActiveCubeFace();
151
- _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
122
+ const pmremTarget = renderTarget || this._allocateTarget();
123
+ const sourceTarget = this._getSourceTarget( true );
152
124
 
153
- const cubeUVRenderTarget = renderTarget || this._allocateTarget( true );
125
+ if ( sigma > 0 ) {
126
+
127
+ sourceTarget.texture.mipmapsAutoUpdate = false;
128
+
129
+ }
130
+
131
+ // Clear every captured face, independent of the application's clear settings.
132
+
133
+ const autoClear = renderer.autoClear;
134
+ const autoClearColor = renderer.autoClearColor;
135
+ const autoClearDepth = renderer.autoClearDepth;
136
+ const autoClearStencil = renderer.autoClearStencil;
137
+ const background = scene.background;
138
+
139
+ renderer.autoClear = true;
140
+ renderer.autoClearColor = true;
141
+ renderer.autoClearDepth = true;
142
+ renderer.autoClearStencil = true;
154
143
 
155
- this._init( cubeUVRenderTarget );
144
+ if ( background === null ) scene.background = renderer.getClearColor( _clearColor );
156
145
 
157
- this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget, position );
146
+ const cubeCamera = new CubeCamera( near, far, sourceTarget );
147
+ cubeCamera.position.copy( position );
148
+ cubeCamera.update( renderer, scene );
149
+
150
+ renderer.autoClear = autoClear;
151
+ renderer.autoClearColor = autoClearColor;
152
+ renderer.autoClearDepth = autoClearDepth;
153
+ renderer.autoClearStencil = autoClearStencil;
154
+
155
+ scene.background = background;
158
156
 
159
157
  if ( sigma > 0 ) {
160
158
 
161
- this._blur( cubeUVRenderTarget, 0, 0, sigma );
159
+ sourceTarget.texture.mipmapsAutoUpdate = true;
160
+ this._blur( pmremTarget, sigma );
162
161
 
163
162
  }
164
163
 
165
- this._applyPMREM( cubeUVRenderTarget );
166
-
167
- this._cleanup( cubeUVRenderTarget );
164
+ this._applyPMREM( pmremTarget );
168
165
 
169
- return cubeUVRenderTarget;
166
+ return pmremTarget;
170
167
 
171
168
  }
172
169
 
173
170
  /**
174
- * Generates a PMREM from a supplied Scene, which can be faster than using an
175
- * image if networking bandwidth is low. Optional sigma specifies a blur radius
176
- * in radians to be applied to the scene before PMREM generation. Optional near
177
- * and far planes ensure the scene is rendered in its entirety (the cubeCamera
178
- * is placed at the origin).
171
+ * Asynchronous version of {@link PMREMGenerator#fromScene}.
179
172
  *
180
173
  * @deprecated
181
174
  * @param {Scene} scene - The scene to be captured.
@@ -183,10 +176,10 @@ class PMREMGenerator {
183
176
  * @param {number} [near=0.1] - The near plane distance.
184
177
  * @param {number} [far=100] - The far plane distance.
185
178
  * @param {Object} [options={}] - The configuration options.
186
- * @param {number} [options.size=256] - The texture size of the PMREM.
179
+ * @param {number} [options.size=256] - The texture size of the PMREM, rounded down to a power of two and at least 256.
187
180
  * @param {Vector3} [options.position=origin] - The position of the internal cube camera that renders the scene.
188
- * @param {?RenderTarget} [options.renderTarget=null] - The render target to use.
189
- * @return {Promise<RenderTarget>} A Promise that resolve with the PMREM when the generation has been finished.
181
+ * @param {?CubeRenderTarget} [options.renderTarget=null] - The render target to use.
182
+ * @return {Promise<CubeRenderTarget>} A Promise that resolves with the PMREM.
190
183
  * @see {@link PMREMGenerator#fromScene}
191
184
  */
192
185
  async fromSceneAsync( scene, sigma = 0, near = 0.1, far = 100, options = {} ) {
@@ -200,19 +193,18 @@ class PMREMGenerator {
200
193
  }
201
194
 
202
195
  /**
203
- * Generates a PMREM from an equirectangular texture, which can be either LDR
204
- * or HDR. The ideal input image size is 1k (1024 x 512), as this matches best
205
- * with the 256 x 256 cubemap output. The minimum supported input image size
206
- * is 64 x 32.
196
+ * Generates a PMREM from an LDR or HDR equirectangular texture. The cube face
197
+ * size is one quarter of the image width, rounded down to a power of two and
198
+ * at least 256.
207
199
  *
208
200
  * @param {Texture} equirectangular - The equirectangular texture to be converted.
209
- * @param {?RenderTarget} [renderTarget=null] - The render target to use.
210
- * @return {RenderTarget} The resulting PMREM.
201
+ * @param {?CubeRenderTarget} [renderTarget=null] - The render target to use.
202
+ * @return {CubeRenderTarget} The resulting PMREM.
211
203
  * @see {@link PMREMGenerator#fromEquirectangularAsync}
212
204
  */
213
205
  fromEquirectangular( equirectangular, renderTarget = null ) {
214
206
 
215
- if ( this._hasInitialized === false ) {
207
+ if ( this._renderer.hasInitialized() === false ) {
216
208
 
217
209
  throw new Error( 'THREE.PMREMGenerator: .fromEquirectangular() called before the backend is initialized. Use "await renderer.init();" before using this method.' );
218
210
 
@@ -223,14 +215,12 @@ class PMREMGenerator {
223
215
  }
224
216
 
225
217
  /**
226
- * Generates a PMREM from an equirectangular texture, which can be either LDR
227
- * or HDR. The ideal input image size is 1k (1024 x 512),
228
- * as this matches best with the 256 x 256 cubemap output.
218
+ * Asynchronous version of {@link PMREMGenerator#fromEquirectangular}.
229
219
  *
230
220
  * @deprecated
231
221
  * @param {Texture} equirectangular - The equirectangular texture to be converted.
232
- * @param {?RenderTarget} [renderTarget=null] - The render target to use.
233
- * @return {Promise<RenderTarget>} The resulting PMREM.
222
+ * @param {?CubeRenderTarget} [renderTarget=null] - The render target to use.
223
+ * @return {Promise<CubeRenderTarget>} The resulting PMREM.
234
224
  * @see {@link PMREMGenerator#fromEquirectangular}
235
225
  */
236
226
  async fromEquirectangularAsync( equirectangular, renderTarget = null ) {
@@ -244,19 +234,17 @@ class PMREMGenerator {
244
234
  }
245
235
 
246
236
  /**
247
- * Generates a PMREM from an cubemap texture, which can be either LDR
248
- * or HDR. The ideal input cube size is 256 x 256, as this matches best
249
- * with the 256 x 256 cubemap output. The minimum supported input cube
250
- * size is 16 x 16 per face.
237
+ * Generates a PMREM from an LDR or HDR cubemap. The cube face size matches
238
+ * the input, rounded down to a power of two and at least 256.
251
239
  *
252
240
  * @param {Texture} cubemap - The cubemap texture to be converted.
253
- * @param {?RenderTarget} [renderTarget=null] - The render target to use.
254
- * @return {RenderTarget} The resulting PMREM.
241
+ * @param {?CubeRenderTarget} [renderTarget=null] - The render target to use.
242
+ * @return {CubeRenderTarget} The resulting PMREM.
255
243
  * @see {@link PMREMGenerator#fromCubemapAsync}
256
244
  */
257
245
  fromCubemap( cubemap, renderTarget = null ) {
258
246
 
259
- if ( this._hasInitialized === false ) {
247
+ if ( this._renderer.hasInitialized() === false ) {
260
248
 
261
249
  throw new Error( 'THREE.PMREMGenerator: .fromCubemap() called before the backend is initialized. Use "await renderer.init();" before using this method.' );
262
250
 
@@ -267,14 +255,12 @@ class PMREMGenerator {
267
255
  }
268
256
 
269
257
  /**
270
- * Generates a PMREM from an cubemap texture, which can be either LDR
271
- * or HDR. The ideal input cube size is 256 x 256,
272
- * with the 256 x 256 cubemap output.
258
+ * Asynchronous version of {@link PMREMGenerator#fromCubemap}.
273
259
  *
274
260
  * @deprecated
275
261
  * @param {Texture} cubemap - The cubemap texture to be converted.
276
- * @param {?RenderTarget} [renderTarget=null] - The render target to use.
277
- * @return {Promise<RenderTarget>} The resulting PMREM.
262
+ * @param {?CubeRenderTarget} [renderTarget=null] - The render target to use.
263
+ * @return {Promise<CubeRenderTarget>} The resulting PMREM.
278
264
  * @see {@link PMREMGenerator#fromCubemap}
279
265
  */
280
266
  async fromCubemapAsync( cubemap, renderTarget = null ) {
@@ -322,629 +308,365 @@ class PMREMGenerator {
322
308
  }
323
309
 
324
310
  /**
325
- * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
326
- * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
327
- * one of them will cause any others to also become unusable.
311
+ * Disposes of the PMREMGenerator's internal memory. The PMREMs it returned
312
+ * belong to the caller and are not disposed.
328
313
  */
329
314
  dispose() {
330
315
 
331
- this._dispose();
316
+ if ( this._sourceTarget !== null ) this._sourceTarget.dispose();
332
317
 
333
318
  if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose();
334
319
  if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose();
335
- if ( this._backgroundBox !== null ) {
336
-
337
- this._backgroundBox.geometry.dispose();
338
- this._backgroundBox.material.dispose();
339
-
340
- }
341
-
342
- }
343
-
344
- // private interface
345
-
346
- _setSizeFromTexture( texture ) {
347
-
348
- if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) {
349
-
350
- this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) );
351
-
352
- } else { // Equirectangular
353
-
354
- this._setSize( texture.image.width / 4 );
355
-
356
- }
357
-
358
- }
359
-
360
- _setSize( cubeSize ) {
361
-
362
- this._lodMax = Math.floor( Math.log2( cubeSize ) );
363
- this._cubeSize = Math.pow( 2, this._lodMax );
364
-
365
- }
366
-
367
- _dispose() {
368
-
369
320
  if ( this._blurMaterial !== null ) this._blurMaterial.dispose();
370
321
  if ( this._ggxMaterial !== null ) this._ggxMaterial.dispose();
322
+ if ( this._integrationMaterial !== null ) this._integrationMaterial.dispose();
371
323
 
372
- if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose();
373
-
374
- for ( let i = 0; i < this._lodMeshes.length; i ++ ) {
375
-
376
- this._lodMeshes[ i ].geometry.dispose();
377
-
378
- }
379
-
380
- }
381
-
382
- _cleanup( outputTarget ) {
383
-
384
- this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel );
385
- outputTarget.scissorTest = false;
386
- this._setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
324
+ this._boxMesh.geometry.dispose();
387
325
 
388
326
  }
389
327
 
390
- _fromTexture( texture, renderTarget ) {
391
-
392
- this._setSizeFromTexture( texture );
393
-
394
- _oldTarget = this._renderer.getRenderTarget();
395
- _oldActiveCubeFace = this._renderer.getActiveCubeFace();
396
- _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
397
-
398
- const cubeUVRenderTarget = renderTarget || this._allocateTarget( false );
399
- this._init( cubeUVRenderTarget );
400
- this._textureToCubeUV( texture, cubeUVRenderTarget );
401
- this._applyPMREM( cubeUVRenderTarget );
402
- this._cleanup( cubeUVRenderTarget );
328
+ /**
329
+ * Returns the roughness a mip level of a PMREM has been prefiltered for.
330
+ * The inverse mapping is used by the renderers when sampling a PMREM.
331
+ *
332
+ * @param {number} lod - The mip level.
333
+ * @param {number} maxLod - The last mip level of the PMREM.
334
+ * @return {number} The roughness.
335
+ */
336
+ static lodToRoughness( lod, maxLod ) {
403
337
 
404
- return cubeUVRenderTarget;
338
+ return maxLod > 0 ? 1 - Math.sqrt( 1 - lod / maxLod ) : 0;
405
339
 
406
340
  }
407
341
 
408
- _allocateTarget( depthBuffer ) {
409
-
410
- const width = 3 * Math.max( this._cubeSize, 16 * 7 );
411
- const height = 4 * this._cubeSize;
342
+ // private interface
412
343
 
413
- const cubeUVRenderTarget = _createRenderTarget( width, height, depthBuffer );
344
+ _setSize( cubeSize ) {
414
345
 
415
- return cubeUVRenderTarget;
346
+ this._cubeSize = Math.max( MIN_SIZE, floorPowerOfTwo( cubeSize ) );
416
347
 
417
348
  }
418
349
 
419
- _init( renderTarget ) {
420
-
421
- if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== renderTarget.width || this._pingPongRenderTarget.height !== renderTarget.height ) {
422
-
423
- if ( this._pingPongRenderTarget !== null ) {
424
-
425
- this._dispose();
350
+ _fromTexture( texture, renderTarget ) {
426
351
 
427
- }
352
+ if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) {
428
353
 
429
- this._pingPongRenderTarget = _createRenderTarget( renderTarget.width, renderTarget.height );
354
+ this._setSize( texture.image.length === 0 ? MIN_SIZE : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) );
430
355
 
431
- const { _lodMax } = this;
432
- ( { lodMeshes: this._lodMeshes, sizeLods: this._sizeLods } = _createPlanes( _lodMax ) );
356
+ } else { // Equirectangular
433
357
 
434
- this._blurMaterial = _getBlurShader( _lodMax, renderTarget.width, renderTarget.height );
435
- this._ggxMaterial = _getGGXShader( _lodMax, renderTarget.width, renderTarget.height );
358
+ this._setSize( texture.image.width / 4 );
436
359
 
437
360
  }
438
361
 
439
- }
362
+ const pmremTarget = renderTarget || this._allocateTarget();
440
363
 
441
- async _compileMaterial( material ) {
364
+ this._textureToCubemap( texture );
365
+ this._applyPMREM( pmremTarget );
442
366
 
443
- const mesh = new Mesh( new BufferGeometry(), material );
444
- await this._renderer.compile( mesh, _flatCamera );
367
+ return pmremTarget;
445
368
 
446
369
  }
447
370
 
448
- _sceneToCubeUV( scene, near, far, cubeUVRenderTarget, position ) {
449
-
450
- const cubeCamera = _cubeCamera;
451
- cubeCamera.near = near;
452
- cubeCamera.far = far;
371
+ _allocateTarget() {
453
372
 
454
- // px, py, pz, nx, ny, nz
455
- const upSign = [ 1, 1, 1, 1, - 1, 1 ];
456
- const forwardSign = [ 1, - 1, 1, - 1, 1, - 1 ];
457
-
458
- const renderer = this._renderer;
373
+ const size = this._cubeSize;
459
374
 
460
- const originalAutoClear = renderer.autoClear;
375
+ const pmremTarget = _createRenderTarget( size, false, false );
461
376
 
462
- renderer.getClearColor( _clearColor );
377
+ // Allocate only the prefiltered mip levels without automatic mipmap generation.
463
378
 
464
- renderer.autoClear = false;
379
+ const maxLod = Math.log2( size ) - LOD_MIN;
465
380
 
466
- if ( this._backgroundBox === null ) {
381
+ for ( let lod = 0; lod <= maxLod; lod ++ ) {
467
382
 
468
- this._backgroundBox = new Mesh(
469
- new BoxGeometry(),
470
- new MeshBasicMaterial( {
471
- name: 'PMREM.Background',
472
- side: BackSide,
473
- depthWrite: false,
474
- depthTest: false,
475
- } )
476
- );
383
+ pmremTarget.texture.mipmaps.push( { width: size >> lod, height: size >> lod } );
477
384
 
478
385
  }
479
386
 
480
- const backgroundBox = this._backgroundBox;
481
- const backgroundMaterial = backgroundBox.material;
387
+ pmremTarget.texture.name = 'PMREM';
388
+ pmremTarget.texture.isPMREMTexture = true;
482
389
 
483
- let useSolidColor = false;
390
+ return pmremTarget;
484
391
 
485
- const background = scene.background;
486
-
487
- if ( background ) {
488
-
489
- if ( background.isColor ) {
490
-
491
- backgroundMaterial.color.copy( background );
492
- scene.background = null;
493
- useSolidColor = true;
494
-
495
- }
496
-
497
- } else {
498
-
499
- backgroundMaterial.color.copy( _clearColor );
500
- useSolidColor = true;
392
+ }
501
393
 
502
- }
394
+ _getSourceTarget( depthBuffer = false ) {
503
395
 
504
- renderer.setRenderTarget( cubeUVRenderTarget );
396
+ const size = this._cubeSize;
397
+ const sourceTarget = this._sourceTarget;
505
398
 
506
- renderer.clear();
399
+ if ( sourceTarget === null || sourceTarget.width !== size || ( depthBuffer && sourceTarget.depthBuffer === false ) ) {
507
400
 
508
- if ( useSolidColor ) {
401
+ if ( sourceTarget !== null ) sourceTarget.dispose();
509
402
 
510
- renderer.render( backgroundBox, cubeCamera );
403
+ this._sourceTarget = _createRenderTarget( size, true, depthBuffer );
511
404
 
512
405
  }
513
406
 
514
- for ( let i = 0; i < 6; i ++ ) {
515
-
516
- const col = i % 3;
517
-
518
- if ( col === 0 ) {
519
-
520
- cubeCamera.up.set( 0, upSign[ i ], 0 );
521
- cubeCamera.position.set( position.x, position.y, position.z );
522
- cubeCamera.lookAt( position.x + forwardSign[ i ], position.y, position.z );
407
+ return this._sourceTarget;
523
408
 
524
- } else if ( col === 1 ) {
525
-
526
- cubeCamera.up.set( 0, 0, upSign[ i ] );
527
- cubeCamera.position.set( position.x, position.y, position.z );
528
- cubeCamera.lookAt( position.x, position.y + forwardSign[ i ], position.z );
529
-
530
-
531
- } else {
532
-
533
- cubeCamera.up.set( 0, upSign[ i ], 0 );
534
- cubeCamera.position.set( position.x, position.y, position.z );
535
- cubeCamera.lookAt( position.x, position.y, position.z + forwardSign[ i ] );
409
+ }
536
410
 
411
+ async _compileMaterial( material ) {
537
412
 
538
- }
413
+ this._boxMesh.material = material;
414
+ await this._renderer.compile( this._boxMesh, this._cubeCamera.children[ 0 ] );
539
415
 
540
- const size = this._cubeSize;
416
+ }
541
417
 
542
- this._setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size );
418
+ /**
419
+ * Renders the box mesh with the given material into all six faces of a cube render target.
420
+ *
421
+ * @private
422
+ * @param {CubeRenderTarget} target - The render target.
423
+ * @param {number} lod - The mip level to render into.
424
+ * @param {NodeMaterial} material - The material.
425
+ */
426
+ _renderCube( target, lod, material ) {
543
427
 
544
- renderer.render( scene, cubeCamera );
428
+ const boxMesh = this._boxMesh;
429
+ const cubeCamera = this._cubeCamera;
545
430
 
546
- }
431
+ boxMesh.material = material;
547
432
 
548
- renderer.autoClear = originalAutoClear;
549
- scene.background = background;
433
+ cubeCamera.renderTarget = target;
434
+ cubeCamera.activeMipmapLevel = lod;
435
+ cubeCamera.update( this._renderer, boxMesh );
550
436
 
551
437
  }
552
438
 
553
- _textureToCubeUV( texture, cubeUVRenderTarget ) {
554
-
555
- const renderer = this._renderer;
439
+ _textureToCubemap( texture ) {
556
440
 
557
- const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping );
441
+ let material;
558
442
 
559
- if ( isCubeTexture ) {
443
+ if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) {
560
444
 
561
445
  if ( this._cubemapMaterial === null ) {
562
446
 
563
- this._cubemapMaterial = _getCubemapMaterial( texture );
447
+ this._cubemapMaterial = _getCubemapMaterial();
564
448
 
565
449
  }
566
450
 
451
+ material = this._cubemapMaterial;
452
+
567
453
  } else {
568
454
 
569
455
  if ( this._equirectMaterial === null ) {
570
456
 
571
- this._equirectMaterial = _getEquirectMaterial( texture );
457
+ this._equirectMaterial = _getEquirectMaterial();
572
458
 
573
459
  }
574
460
 
575
- }
576
-
577
- const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial;
578
- material.fragmentNode.value = texture;
579
-
580
- const mesh = this._lodMeshes[ 0 ];
581
- mesh.material = material;
582
-
583
- const size = this._cubeSize;
584
- this._setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size );
585
- renderer.setRenderTarget( cubeUVRenderTarget );
586
- renderer.render( mesh, _flatCamera );
587
-
588
- }
589
-
590
- _applyPMREM( cubeUVRenderTarget ) {
591
-
592
- const renderer = this._renderer;
593
- const autoClear = renderer.autoClear;
594
- renderer.autoClear = false;
595
-
596
- const n = this._lodMeshes.length;
597
-
598
- // Use GGX VNDF importance sampling
599
- for ( let i = 1; i < n; i ++ ) {
600
-
601
- this._applyGGXFilter( cubeUVRenderTarget, i - 1, i );
461
+ material = this._equirectMaterial;
602
462
 
603
463
  }
604
464
 
605
- renderer.autoClear = autoClear;
606
-
607
- }
608
-
609
- /**
610
- * Applies GGX VNDF importance sampling filter to generate a prefiltered environment map.
611
- * Uses Monte Carlo integration with VNDF importance sampling to accurately represent the
612
- * GGX BRDF for physically-based rendering. Reads from the previous LOD level and
613
- * applies incremental roughness filtering to avoid over-blurring.
614
- *
615
- * @private
616
- * @param {RenderTarget} cubeUVRenderTarget
617
- * @param {number} lodIn - Source LOD level to read from
618
- * @param {number} lodOut - Target LOD level to write to
619
- */
620
- _applyGGXFilter( cubeUVRenderTarget, lodIn, lodOut ) {
621
-
622
- const renderer = this._renderer;
623
- const pingPongRenderTarget = this._pingPongRenderTarget;
624
-
625
- const ggxMaterial = this._ggxMaterial;
626
- const ggxMesh = this._lodMeshes[ lodOut ];
627
- ggxMesh.material = ggxMaterial;
628
-
629
- const ggxUniforms = _uniformsMap.get( ggxMaterial );
630
-
631
- // Calculate incremental roughness between LOD levels
632
- const targetRoughness = lodOut / ( this._lodMeshes.length - 1 );
633
- const sourceRoughness = lodIn / ( this._lodMeshes.length - 1 );
634
- const incrementalRoughness = Math.sqrt( targetRoughness * targetRoughness - sourceRoughness * sourceRoughness );
635
-
636
- // Apply blur strength mapping for better quality across the roughness range
637
- const blurStrength = targetRoughness * 1.25;
638
- const adjustedRoughness = incrementalRoughness * blurStrength;
639
-
640
- // Calculate viewport position based on output LOD level
641
- const { _lodMax } = this;
642
- const outputSize = this._sizeLods[ lodOut ];
643
- const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 );
644
- const y = 4 * ( this._cubeSize - outputSize );
645
-
646
- // Read from previous LOD with incremental roughness
647
- cubeUVRenderTarget.texture.frame = ( cubeUVRenderTarget.texture.frame || 0 ) + 1;
648
- ggxUniforms.envMap.value = cubeUVRenderTarget.texture;
649
- ggxUniforms.roughness.value = adjustedRoughness;
650
- ggxUniforms.mipInt.value = _lodMax - lodIn; // Sample from input LOD
651
-
652
- this._setViewport( pingPongRenderTarget, x, y, 3 * outputSize, 2 * outputSize );
653
- renderer.setRenderTarget( pingPongRenderTarget );
654
- renderer.render( ggxMesh, _flatCamera );
655
-
656
- // Copy from pingPong back to cubeUV (simple direct copy)
657
- pingPongRenderTarget.texture.frame = ( pingPongRenderTarget.texture.frame || 0 ) + 1;
658
- ggxUniforms.envMap.value = pingPongRenderTarget.texture;
659
- ggxUniforms.roughness.value = 0.0; // Direct copy
660
- ggxUniforms.mipInt.value = _lodMax - lodOut; // Read from the level we just wrote
465
+ _uniformsMap.get( material ).envMap.value = texture;
661
466
 
662
- this._setViewport( cubeUVRenderTarget, x, y, 3 * outputSize, 2 * outputSize );
663
- renderer.setRenderTarget( cubeUVRenderTarget );
664
- renderer.render( ggxMesh, _flatCamera );
467
+ this._renderCube( this._getSourceTarget(), 0, material );
665
468
 
666
469
  }
667
470
 
668
471
  /**
669
- * This is a two-pass Gaussian blur for a cubemap. Each pass importance-samples
670
- * the Gaussian along a spiral kernel (Golden Angle), which distributes samples
671
- * isotropically on the sphere (no pole artifacts).
672
- *
673
- * Used for initial scene blur in fromScene() method when sigma > 0.
472
+ * Prefilters the source cubemap into the mip levels of the PMREM. The sharp levels
473
+ * integrate the GGX lobe of their roughness with VNDF importance sampling, reading the
474
+ * mip level of the source that matches the solid angle of each sample. The rough
475
+ * levels weight every texel of a small source mip with the GGX lobe instead.
674
476
  *
675
477
  * @private
676
- * @param {RenderTarget} cubeUVRenderTarget - The cubemap render target.
677
- * @param {number} lodIn - The input level-of-detail.
678
- * @param {number} lodOut - The output level-of-detail.
679
- * @param {number} sigma - The blur radius in radians.
478
+ * @param {CubeRenderTarget} pmremTarget - The PMREM.
680
479
  */
681
- _blur( cubeUVRenderTarget, lodIn, lodOut, sigma ) {
480
+ _applyPMREM( pmremTarget ) {
682
481
 
683
- const pingPongRenderTarget = this._pingPongRenderTarget;
482
+ if ( this._ggxMaterial === null ) {
684
483
 
685
- // Two passes of sigma / sqrt( 2 ) compose to a blur of sigma while squaring
686
- // the effective sample count. Sigmas beyond PI are visually indistinguishable
687
- // from a uniform blur, so clamp to keep the shader math finite.
688
- const blurSigma = Math.min( sigma, Math.PI ) / Math.SQRT2;
484
+ this._ggxMaterial = _getGGXMaterial();
485
+ this._integrationMaterial = _getIntegrationMaterial();
689
486
 
690
- this._blurPass( cubeUVRenderTarget, pingPongRenderTarget, lodIn, lodOut, blurSigma );
691
- this._blurPass( pingPongRenderTarget, cubeUVRenderTarget, lodOut, lodOut, blurSigma );
692
-
693
- }
694
-
695
- _blurPass( targetIn, targetOut, lodIn, lodOut, sigmaRadians ) {
487
+ }
696
488
 
697
- const renderer = this._renderer;
698
- const blurMaterial = this._blurMaterial;
489
+ const size = this._cubeSize;
490
+ const maxLod = pmremTarget.texture.mipmaps.length - 1;
699
491
 
700
- const blurMesh = this._lodMeshes[ lodOut ];
701
- blurMesh.material = blurMaterial;
492
+ const ggxUniforms = _uniformsMap.get( this._ggxMaterial );
493
+ ggxUniforms.envMap.value = this._sourceTarget.texture;
702
494
 
703
- const blurUniforms = _uniformsMap.get( blurMaterial );
495
+ const integrationUniforms = _uniformsMap.get( this._integrationMaterial );
496
+ integrationUniforms.envMap.value = this._sourceTarget.texture;
497
+ integrationUniforms.sourceLod.value = Math.log2( size / INTEGRATION_SIZE );
704
498
 
705
- targetIn.texture.frame = ( targetIn.texture.frame || 0 ) + 1;
499
+ for ( let lod = 0; lod <= maxLod; lod ++ ) {
706
500
 
707
- blurUniforms.envMap.value = targetIn.texture;
708
- blurUniforms.sigma.value = sigmaRadians;
709
- blurUniforms.mipInt.value = this._lodMax - lodIn;
501
+ const roughness = PMREMGenerator.lodToRoughness( lod, maxLod );
710
502
 
711
- const outputSize = this._sizeLods[ lodOut ];
712
- const x = 3 * outputSize * ( lodOut > this._lodMax - LOD_MIN ? lodOut - this._lodMax + LOD_MIN : 0 );
713
- const y = 4 * ( this._cubeSize - outputSize );
503
+ if ( lod > maxLod - INTEGRATION_LEVELS ) {
714
504
 
715
- this._setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
716
- renderer.setRenderTarget( targetOut );
717
- renderer.render( blurMesh, _flatCamera );
505
+ integrationUniforms.roughness.value = roughness;
718
506
 
719
- }
507
+ this._renderCube( pmremTarget, lod, this._integrationMaterial );
720
508
 
721
- _setViewport( target, x, y, width, height ) {
509
+ } else {
722
510
 
723
- if ( this._renderer.isWebGLRenderer ) {
511
+ // For V = N, pdf( L ) = D( H ) / 4. Match the source texel solid angle to
512
+ // 1 / ( GGX_SAMPLES * pdf ), with a half-mip bias to reduce sampling noise.
513
+ // The shader supplies log2 of the GGX denominator.
514
+ const lodBias = roughness > 0 ? Math.log2( size ) + 0.5 * Math.log2( 6 / ( GGX_SAMPLES * Math.pow( roughness, 4 ) ) ) + 0.5 : 0;
724
515
 
725
- target.viewport.set( x, target.height - height - y, width, height );
726
- target.scissor.set( x, target.height - height - y, width, height );
516
+ ggxUniforms.roughness.value = roughness;
517
+ ggxUniforms.lodBias.value = lodBias;
727
518
 
728
- } else {
519
+ this._renderCube( pmremTarget, lod, this._ggxMaterial );
729
520
 
730
- target.viewport.set( x, y, width, height );
731
- target.scissor.set( x, y, width, height );
521
+ }
732
522
 
733
523
  }
734
524
 
735
525
  }
736
526
 
527
+ /**
528
+ * Applies the initial fromScene() blur in two passes using a golden-angle
529
+ * spiral kernel. Level 0 of the PMREM serves as the intermediate target.
530
+ *
531
+ * @private
532
+ * @param {CubeRenderTarget} pmremTarget - The PMREM.
533
+ * @param {number} sigma - The blur radius in radians.
534
+ */
535
+ _blur( pmremTarget, sigma ) {
737
536
 
738
- }
739
-
740
- function _createPlanes( lodMax ) {
741
-
742
- const sizeLods = [];
743
- const lodMeshes = [];
744
-
745
- let lod = lodMax;
746
-
747
- const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LODS;
748
-
749
- for ( let i = 0; i < totalLods; i ++ ) {
750
-
751
- const sizeLod = Math.pow( 2, lod );
752
- sizeLods.push( sizeLod );
753
-
754
- // UVs overshoot the face by one texel to bake the CubeUV border into the directions.
755
- const texelSize = 1.0 / ( sizeLod - 2 );
756
- const min = - texelSize;
757
- const max = 1 + texelSize;
758
- const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
759
-
760
- const cubeFaces = 6;
761
- const vertices = 6;
762
- const positionSize = 3;
763
-
764
- const position = new Float32Array( positionSize * vertices * cubeFaces );
765
- const outputDirection = new Float32Array( positionSize * vertices * cubeFaces );
766
-
767
- for ( let face = 0; face < cubeFaces; face ++ ) {
768
-
769
- const x = ( face % 3 ) * 2 / 3 - 1;
770
- const y = face > 2 ? 0 : - 1;
771
- const coordinates = [
772
- x, y, 0,
773
- x + 2 / 3, y, 0,
774
- x + 2 / 3, y + 1, 0,
775
- x, y, 0,
776
- x + 2 / 3, y + 1, 0,
777
- x, y + 1, 0
778
- ];
779
-
780
- const faceIdx = _faceLib[ face ];
781
- position.set( coordinates, positionSize * vertices * faceIdx );
782
-
783
- for ( let vertex = 0; vertex < vertices; vertex ++ ) {
784
-
785
- const u = uv1[ vertex * 2 ] * 2 - 1;
786
- const v = uv1[ vertex * 2 + 1 ] * 2 - 1;
787
-
788
- // RH coordinate system; PMREM face-indexing convention
789
- if ( faceIdx === 0 ) {
790
-
791
- _direction.set( 1, v, u ); // pos x
792
-
793
- } else if ( faceIdx === 1 ) {
794
-
795
- _direction.set( - u, 1, - v ); // pos y
796
-
797
- } else if ( faceIdx === 2 ) {
798
-
799
- _direction.set( - u, v, 1 ); // pos z
800
-
801
- } else if ( faceIdx === 3 ) {
802
-
803
- _direction.set( - 1, v, - u ); // neg x
804
-
805
- } else if ( faceIdx === 4 ) {
806
-
807
- _direction.set( - u, - 1, v ); // neg y
808
-
809
- } else {
810
-
811
- _direction.set( u, v, - 1 ); // neg z
812
-
813
- }
814
-
815
- _direction.toArray( outputDirection, ( faceIdx * vertices + vertex ) * positionSize );
537
+ if ( this._blurMaterial === null ) {
816
538
 
817
- }
539
+ this._blurMaterial = _getBlurMaterial();
818
540
 
819
541
  }
820
542
 
821
- const planes = new BufferGeometry();
822
- planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
823
- planes.setAttribute( 'outputDirection', new BufferAttribute( outputDirection, positionSize ) );
824
- lodMeshes.push( new Mesh( planes, null ) );
543
+ const material = this._blurMaterial;
544
+ const uniforms = _uniformsMap.get( material );
825
545
 
826
- if ( lod > LOD_MIN ) {
546
+ const sourceTarget = this._sourceTarget;
827
547
 
828
- lod --;
548
+ // Split the blur variance between two passes. Clamp sigma to the sphere's
549
+ // maximum angular distance.
550
+ uniforms.sigma.value = Math.min( sigma, Math.PI ) / Math.SQRT2;
829
551
 
830
- }
552
+ uniforms.envMap.value = sourceTarget.texture;
553
+ this._renderCube( pmremTarget, 0, material );
831
554
 
832
- }
555
+ uniforms.envMap.value = pmremTarget.texture;
556
+ this._renderCube( sourceTarget, 0, material );
833
557
 
834
- return { lodMeshes, sizeLods };
558
+ }
835
559
 
836
560
  }
837
561
 
838
- function _createRenderTarget( width, height, depthBuffer ) {
562
+ function _createRenderTarget( size, generateMipmaps, depthBuffer ) {
839
563
 
840
- const params = {
841
- magFilter: LinearFilter,
842
- minFilter: LinearFilter,
843
- generateMipmaps: false,
564
+ return new CubeRenderTarget( size, {
565
+ minFilter: LinearMipmapLinearFilter,
566
+ generateMipmaps: generateMipmaps,
844
567
  type: HalfFloatType,
845
- format: RGBAFormat,
846
568
  colorSpace: LinearSRGBColorSpace,
847
- depthBuffer
848
- };
849
-
850
- const cubeUVRenderTarget = new RenderTarget( width, height, params );
851
- cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
852
- cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
853
- cubeUVRenderTarget.texture.isPMREMTexture = true;
854
- cubeUVRenderTarget.scissorTest = true;
855
- return cubeUVRenderTarget;
569
+ depthBuffer: depthBuffer
570
+ } );
856
571
 
857
572
  }
858
573
 
859
- function _getMaterial( type ) {
574
+ function _getMaterial( type, uniforms, fragmentNode ) {
860
575
 
861
576
  const material = new NodeMaterial();
577
+ material.name = `PMREM_${ type }`;
578
+ material.fragmentNode = fragmentNode;
579
+ material.side = BackSide;
580
+ material.blending = NoBlending;
862
581
  material.depthTest = false;
863
582
  material.depthWrite = false;
864
- material.blending = NoBlending;
865
- material.name = `PMREM_${ type }`;
583
+
584
+ _uniformsMap.set( material, uniforms );
866
585
 
867
586
  return material;
868
587
 
869
588
  }
870
589
 
871
- function _getBlurShader( lodMax, width, height ) {
872
-
873
- const envMap = texture();
874
- const sigma = uniform( 0 );
875
- const mipInt = uniform( 0 ); // int
876
- const CUBEUV_TEXEL_WIDTH = float( 1 / width );
877
- const CUBEUV_TEXEL_HEIGHT = float( 1 / height );
878
- const CUBEUV_MAX_MIP = float( lodMax );
879
-
880
- const materialUniforms = {
881
- envMap,
882
- sigma,
883
- mipInt,
884
- CUBEUV_TEXEL_WIDTH,
885
- CUBEUV_TEXEL_HEIGHT,
886
- CUBEUV_MAX_MIP
590
+ function _getBlurMaterial() {
591
+
592
+ const uniforms = {
593
+ envMap: cubeTexture(),
594
+ sigma: uniform( 0 )
887
595
  };
888
596
 
889
- const material = _getMaterial( 'blur' );
890
- material.fragmentNode = sphericalGaussianBlur( {
891
- ...materialUniforms,
892
- outputDirection: _outputDirection,
597
+ return _getMaterial( 'blur', uniforms, sphericalGaussianBlur( {
598
+ ...uniforms,
599
+ direction: positionWorldDirection,
893
600
  SAMPLES: int( BLUR_SAMPLES )
894
- } );
895
-
896
- _uniformsMap.set( material, materialUniforms );
897
-
898
- return material;
601
+ } ) );
899
602
 
900
603
  }
901
604
 
902
- function _getGGXShader( lodMax, width, height ) {
903
-
904
- const envMap = texture();
905
- const roughness = uniform( 0 );
906
- const mipInt = uniform( 0 );
907
- const CUBEUV_TEXEL_WIDTH = float( 1 / width );
908
- const CUBEUV_TEXEL_HEIGHT = float( 1 / height );
909
- const CUBEUV_MAX_MIP = float( lodMax );
910
-
911
- const materialUniforms = {
912
- envMap,
913
- roughness,
914
- mipInt,
915
- CUBEUV_TEXEL_WIDTH,
916
- CUBEUV_TEXEL_HEIGHT,
917
- CUBEUV_MAX_MIP
605
+ function _getGGXMaterial() {
606
+
607
+ const uniforms = {
608
+ envMap: cubeTexture(),
609
+ roughness: uniform( 0 ),
610
+ lodBias: uniform( 0 )
918
611
  };
919
612
 
920
- const material = _getMaterial( 'ggx' );
921
- material.fragmentNode = ggxConvolution( {
922
- ...materialUniforms,
923
- N_immutable: _outputDirection,
613
+ return _getMaterial( 'ggx', uniforms, ggxConvolution( {
614
+ ...uniforms,
615
+ direction: positionWorldDirection,
924
616
  GGX_SAMPLES: uint( GGX_SAMPLES )
925
- } );
617
+ } ) );
926
618
 
927
- _uniformsMap.set( material, materialUniforms );
619
+ }
928
620
 
929
- return material;
621
+ function _getIntegrationMaterial() {
622
+
623
+ const uniforms = {
624
+ envMap: cubeTexture(),
625
+ roughness: uniform( 0 ),
626
+ sourceLod: uniform( 0 ),
627
+ sourceSize: uniform( INTEGRATION_SIZE, 'int' ) // a uniform so the loops aren't unrolled
628
+ };
629
+
630
+ return _getMaterial( 'integration', uniforms, ggxIntegration( {
631
+ ...uniforms,
632
+ direction: positionWorldDirection
633
+ } ) );
930
634
 
931
635
  }
932
636
 
933
- function _getCubemapMaterial( envTexture ) {
637
+ function _getCubemapMaterial() {
934
638
 
935
- const material = _getMaterial( 'cubemap' );
936
- material.fragmentNode = cubeTexture( envTexture, _outputDirection );
639
+ const uniforms = {
640
+ envMap: cubeTexture()
641
+ };
937
642
 
938
- return material;
643
+ return _getMaterial( 'cubemap', uniforms, uniforms.envMap.sample( positionWorldDirection ) );
939
644
 
940
645
  }
941
646
 
942
- function _getEquirectMaterial( envTexture ) {
647
+ function _getEquirectMaterial() {
943
648
 
944
- const material = _getMaterial( 'equirect' );
945
- material.fragmentNode = texture( envTexture, equirectUV( _outputDirection ), 0 );
649
+ const uniforms = {
650
+ envMap: texture()
651
+ };
946
652
 
947
- return material;
653
+ const fragmentNode = Fn( () => {
654
+
655
+ // Average four subpixel samples to preserve small, bright features.
656
+ const direction = positionWorldDirection;
657
+ const dx = direction.dFdx().mul( 0.25 ).toConst();
658
+ const dy = direction.dFdy().mul( 0.25 ).toConst();
659
+
660
+ const color = uniforms.envMap.sample( equirectUV( direction.sub( dx ).sub( dy ).normalize() ) ).level( 0 ).rgb
661
+ .add( uniforms.envMap.sample( equirectUV( direction.add( dx ).sub( dy ).normalize() ) ).level( 0 ).rgb )
662
+ .add( uniforms.envMap.sample( equirectUV( direction.sub( dx ).add( dy ).normalize() ) ).level( 0 ).rgb )
663
+ .add( uniforms.envMap.sample( equirectUV( direction.add( dx ).add( dy ).normalize() ) ).level( 0 ).rgb );
664
+
665
+ return vec4( color.mul( 0.25 ), 1.0 );
666
+
667
+ } )();
668
+
669
+ return _getMaterial( 'equirect', uniforms, fragmentNode );
948
670
 
949
671
  }
950
672