@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
@@ -19,14 +19,13 @@ import Lighting from './Lighting.js';
19
19
  import XRManager from './XRManager.js';
20
20
  import InspectorBase from './InspectorBase.js';
21
21
  import CanvasTarget from './CanvasTarget.js';
22
+ import { AttributeType } from './Constants.js';
23
+ import StandardDrawingPipeline from './StandardDrawingPipeline.js';
22
24
 
23
25
  import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
24
26
 
25
27
  import { Scene } from '../../scenes/Scene.js';
26
28
  import { ColorManagement } from '../../math/ColorManagement.js';
27
- import { Frustum } from '../../math/Frustum.js';
28
- import { FrustumArray } from '../../math/FrustumArray.js';
29
- import { Matrix4 } from '../../math/Matrix4.js';
30
29
  import { Vector2 } from '../../math/Vector2.js';
31
30
  import { Vector4 } from '../../math/Vector4.js';
32
31
  import { RenderTarget } from '../../core/RenderTarget.js';
@@ -42,14 +41,89 @@ import { frameTimings } from './GPUTimings.js';
42
41
  const _scene = /*@__PURE__*/ new Scene();
43
42
  const _drawingBufferSize = /*@__PURE__*/ new Vector2();
44
43
  const _screen = /*@__PURE__*/ new Vector4();
45
- const _frustum = /*@__PURE__*/ new Frustum();
46
- const _frustumArray = /*@__PURE__*/ new FrustumArray();
47
-
48
- const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
49
44
  const _vector4 = /*@__PURE__*/ new Vector4();
50
45
 
51
46
  const _shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide };
52
47
 
48
+ // The time in milliseconds an async compilation works before it yields to the main thread.
49
+ const _compileYieldInterval = 8;
50
+
51
+ // The maximum number of pipelines an async compilation creates at the same time.
52
+ // Too many pipelines in flight stall the rendering of new frames.
53
+ const _maxCompilingPipelines = 16;
54
+
55
+ /**
56
+ * Yields to the main thread during an async compilation, but only after a time
57
+ * budget, so the compilation does not wait for a new task or frame after every
58
+ * small piece of work.
59
+ *
60
+ * @private
61
+ */
62
+ class CompileScheduler {
63
+
64
+ constructor() {
65
+
66
+ this.lastYieldTime = performance.now();
67
+
68
+ }
69
+
70
+ /**
71
+ * Whether the compilation worked longer than the time budget since the last yield.
72
+ *
73
+ * @return {boolean} Whether the compilation should yield to the main thread.
74
+ */
75
+ needsYield() {
76
+
77
+ return performance.now() - this.lastYieldTime >= _compileYieldInterval;
78
+
79
+ }
80
+
81
+ /**
82
+ * Yields to the main thread until the next frame was rendered. `scheduler.yield()`
83
+ * alone is not enough, since its continuations run before the browser renders.
84
+ *
85
+ * @return {Promise} A promise that resolves when the compilation can continue.
86
+ */
87
+ async yield() {
88
+
89
+ if ( typeof requestAnimationFrame === 'undefined' || ( typeof document !== 'undefined' && document.hidden === true ) ) {
90
+
91
+ // no frames are rendered
92
+ await yieldToMain();
93
+
94
+ } else {
95
+
96
+ await new Promise( ( resolve ) => {
97
+
98
+ let resolved = false;
99
+
100
+ const done = () => {
101
+
102
+ if ( resolved === false ) {
103
+
104
+ resolved = true;
105
+ resolve();
106
+
107
+ }
108
+
109
+ };
110
+
111
+ // continue in a new task after the next frame was rendered
112
+ requestAnimationFrame( () => setTimeout( done, 0 ) );
113
+
114
+ // requestAnimationFrame() stops if the page is hidden in the meantime
115
+ setTimeout( done, 100 );
116
+
117
+ } );
118
+
119
+ }
120
+
121
+ this.lastYieldTime = performance.now();
122
+
123
+ }
124
+
125
+ }
126
+
53
127
  /**
54
128
  * Base class for renderers.
55
129
  */
@@ -59,7 +133,7 @@ class Renderer {
59
133
  * Renderer options.
60
134
  *
61
135
  * @typedef {Object} Renderer~Options
62
- * @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
136
+ * @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. Ignored when a reversed depth buffer is in use.
63
137
  * @property {boolean} [reversedDepthBuffer=false] - Whether reversed depth buffer is enabled or not.
64
138
  * @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
65
139
  * @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
@@ -159,7 +233,8 @@ class Renderer {
159
233
  this.alpha = alpha;
160
234
 
161
235
  /**
162
- * Whether logarithmic depth buffer is enabled or not.
236
+ * Whether logarithmic depth buffer is enabled or not. It is disabled
237
+ * on initialization when a reversed depth buffer is in use.
163
238
  *
164
239
  * @type {boolean}
165
240
  * @default false
@@ -264,6 +339,16 @@ class Renderer {
264
339
  */
265
340
  this.lighting = new Lighting();
266
341
 
342
+ /**
343
+ * The current drawing pipeline. See {@link Renderer#drawingPipeline}.
344
+ *
345
+ * @private
346
+ * @type {StandardDrawingPipeline}
347
+ */
348
+ this._drawingPipeline = null;
349
+
350
+ this.drawingPipeline = new StandardDrawingPipeline();
351
+
267
352
  // internals
268
353
 
269
354
  /**
@@ -283,6 +368,14 @@ class Renderer {
283
368
  */
284
369
  this._onCanvasTargetResize = this._onCanvasTargetResize.bind( this );
285
370
 
371
+ /**
372
+ * OnCanvasTargetDispose callback function.
373
+ *
374
+ * @private
375
+ * @type {Function}
376
+ */
377
+ this._onCanvasTargetDispose = this._onCanvasTargetDispose.bind( this );
378
+
286
379
  /**
287
380
  * The canvas target for rendering.
288
381
  *
@@ -291,6 +384,7 @@ class Renderer {
291
384
  */
292
385
  this._canvasTarget = new CanvasTarget( backend.getDomElement() );
293
386
  this._canvasTarget.addEventListener( 'resize', this._onCanvasTargetResize );
387
+ this._canvasTarget.addEventListener( 'dispose', this._onCanvasTargetDispose );
294
388
  this._canvasTarget.isDefaultCanvasTarget = true;
295
389
 
296
390
  /**
@@ -654,23 +748,23 @@ class Renderer {
654
748
  this._initPromise = null;
655
749
 
656
750
  /**
657
- * An array of compilation promises which are used in `compileAsync()`.
751
+ * Render and compute work items processed sequentially by `compileAsync()`.
658
752
  *
659
753
  * @private
660
- * @type {?Array<Promise>}
754
+ * @type {?Array<Object>}
661
755
  * @default null
662
756
  */
663
757
  this._compilationPromises = null;
664
758
 
665
759
  /**
666
- * Whether the renderer is currently precompiling a render object in
667
- * `compileAsync()`.
760
+ * The state of the current precompilation in `compileAsync()`.
761
+ * `null` when the renderer is not precompiling.
668
762
  *
669
763
  * @private
670
- * @type {boolean}
671
- * @default false
764
+ * @type {?Object}
765
+ * @default null
672
766
  */
673
- this._isPreCompiling = false;
767
+ this._precompilationState = null;
674
768
 
675
769
  /**
676
770
  * When an override material is in use, this property points to the current
@@ -761,7 +855,7 @@ class Renderer {
761
855
  const renderTarget = useFrameBufferTarget ? this._getFrameBufferTarget() : ( this._renderTarget || this._outputRenderTarget );
762
856
 
763
857
  const renderList = this._renderLists.get( scene, camera, this.lighting );
764
- const renderContext = this._renderContexts.get( renderTarget, this._mrt );
858
+ const renderContext = this._renderContexts.get( renderTarget, this._mrt, 0, camera );
765
859
 
766
860
  const material = scene.overrideMaterial || object.material;
767
861
 
@@ -776,6 +870,27 @@ class Renderer {
776
870
 
777
871
  }
778
872
 
873
+ /**
874
+ * Decides which objects of a scene are rendered and how they are submitted
875
+ * to the render list. Assigning a drawing pipeline binds it to this renderer.
876
+ * The default is a {@link StandardDrawingPipeline}. This property is experimental.
877
+ *
878
+ * @type {StandardDrawingPipeline}
879
+ */
880
+ set drawingPipeline( pipeline ) {
881
+
882
+ pipeline.renderer = this;
883
+
884
+ this._drawingPipeline = pipeline;
885
+
886
+ }
887
+
888
+ get drawingPipeline() {
889
+
890
+ return this._drawingPipeline;
891
+
892
+ }
893
+
779
894
  /**
780
895
  * Initializes the renderer so it is ready for usage.
781
896
  *
@@ -825,11 +940,19 @@ class Renderer {
825
940
 
826
941
  }
827
942
 
943
+ if ( this.logarithmicDepthBuffer === true && this.reversedDepthBuffer === true ) {
944
+
945
+ warn( 'WebGPURenderer: Logarithmic depth buffer is ignored when reversed depth buffer is enabled.' );
946
+
947
+ this.logarithmicDepthBuffer = false;
948
+
949
+ }
950
+
828
951
  this._nodes = new NodeManager( this, backend );
829
952
  this._animation = new Animation( this, this._nodes, this.info );
830
953
  this._attributes = new Attributes( backend, this.info );
831
954
  this._background = new Background( this, this._nodes );
832
- this._geometries = new Geometries( this._attributes, this.info );
955
+ this._geometries = new Geometries( backend, this._attributes, this.info );
833
956
  this._textures = new Textures( this, backend, this.info );
834
957
  this._pipelines = new Pipelines( backend, this._nodes, this.info );
835
958
  this._bindings = new Bindings( backend, this._nodes, this._textures, this._attributes, this._pipelines, this.info );
@@ -840,7 +963,6 @@ class Renderer {
840
963
 
841
964
  //
842
965
 
843
- this._animation.start();
844
966
  this._initialized = true;
845
967
 
846
968
  resolve( this );
@@ -882,6 +1004,7 @@ class Renderer {
882
1004
  * Compiles all materials in the given scene. This can be useful to avoid a
883
1005
  * phenomenon which is called "shader compilation stutter", which occurs when
884
1006
  * rendering an object with a new shader for the first time.
1007
+ * The active drawing pipeline also prepares its geometry resources and compute pipelines.
885
1008
  *
886
1009
  * If you want to add a 3D object to an existing scene, use the third optional
887
1010
  * parameter for applying the target scene. Note that the (target) scene's lighting
@@ -900,6 +1023,12 @@ class Renderer {
900
1023
 
901
1024
  if ( this._initialized === false ) await this.init();
902
1025
 
1026
+ // only awaited when the drawing pipeline prepares something, so the state below is still taken synchronously
1027
+
1028
+ const prepare = this.drawingPipeline.prepareAsync( scene, camera );
1029
+
1030
+ if ( prepare !== undefined ) await prepare;
1031
+
903
1032
  if ( this.shadowMap.type === PCFSoftShadowMap ) {
904
1033
 
905
1034
  warn( 'WebGPURenderer: PCFSoftShadowMap has been removed. Using PCFShadowMap instead.' );
@@ -931,9 +1060,23 @@ class Renderer {
931
1060
  const outputRenderTarget = this._renderTarget || this._outputRenderTarget;
932
1061
  const useXRCamera = this.xr.isPresenting === true && this.isOutputTarget;
933
1062
  const renderTarget = useFrameBufferTarget ? this._getFrameBufferTarget() : outputRenderTarget;
934
- const renderContext = this._renderContexts.get( renderTarget, this._mrt );
1063
+
1064
+ const activeCubeFace = this._activeCubeFace;
935
1065
  const activeMipmapLevel = this._activeMipmapLevel;
936
1066
 
1067
+ // a state snapshot is taken once at the beginning and reapplied every time precompilation continues.
1068
+ // `item` is the work item that is currently processed, see `_beginPreCompile()`
1069
+
1070
+ // the work items always set their render target, without the frame buffer target the current one is restored
1071
+
1072
+ const precompilationState = { useFrameBufferTarget, renderTarget, outputRenderTarget: useFrameBufferTarget ? outputRenderTarget : this._renderTarget, activeCubeFace, activeMipmapLevel, item: null, materialSide: null, mrt: this._mrt, outputMRT: this._mrt };
1073
+
1074
+ this._beginPreCompile( precompilationState );
1075
+
1076
+ const renderContext = this._renderContexts.get( renderTarget, this._mrt, this._callDepth, camera );
1077
+
1078
+ precompilationState.renderContext = renderContext;
1079
+
937
1080
  const compilationPromises = [];
938
1081
 
939
1082
  this._currentRenderContext = renderContext;
@@ -969,23 +1112,13 @@ class Renderer {
969
1112
 
970
1113
  //
971
1114
 
972
- _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
973
-
974
- if ( camera.isArrayCamera ) {
975
-
976
- _frustumArray.setFromArrayCamera( camera );
977
-
978
- } else {
979
-
980
- _frustum.setFromProjectionMatrix( _projScreenMatrix, camera.coordinateSystem, camera.reversedDepth );
981
-
982
- }
1115
+ this.drawingPipeline.begin( camera, renderContext );
983
1116
 
984
1117
  // Use sceneRef for render list to ensure lightsNode matches between compileAsync and render
985
1118
  const renderList = this._renderLists.get( sceneRef, camera, this.lighting );
986
- renderList.begin();
1119
+ this.drawingPipeline.beginRenderList( renderList );
987
1120
 
988
- this._projectObject( scene, camera, 0, renderList, renderContext.clippingContext );
1121
+ this.drawingPipeline.project( scene, camera, 0, renderList, renderContext.clippingContext );
989
1122
 
990
1123
  // include lights from target scene
991
1124
  if ( targetScene !== scene ) {
@@ -1002,7 +1135,7 @@ class Renderer {
1002
1135
 
1003
1136
  }
1004
1137
 
1005
- renderList.finish();
1138
+ this.drawingPipeline.finishRenderList( renderList );
1006
1139
 
1007
1140
  //
1008
1141
 
@@ -1034,7 +1167,7 @@ class Renderer {
1034
1167
 
1035
1168
  }
1036
1169
 
1037
- // process render lists - _createObjectPipeline will push async promises to _compilationPromises
1170
+ // process render lists - _createObjectPipeline queues work in _compilationPromises
1038
1171
 
1039
1172
  const opaqueObjects = renderList.opaque;
1040
1173
  const transparentObjects = renderList.transparent;
@@ -1053,54 +1186,165 @@ class Renderer {
1053
1186
  this._handleObjectFunction = previousHandleObjectFunction;
1054
1187
  this._compilationPromises = previousCompilationPromises;
1055
1188
 
1056
- // Process compilation work items sequentially to avoid freezing
1057
- // Yields between objects to keep animation smooth
1189
+ this._finishPreCompile();
1190
+
1191
+ // Process compilation work items sequentially and yield to the main thread after a
1192
+ // time budget to keep animation smooth. Pipelines are compiled in parallel while
1193
+ // the next items are processed.
1058
1194
 
1059
1195
  const total = compilationPromises.length;
1060
1196
  let loaded = 0;
1061
1197
 
1198
+ const scheduler = new CompileScheduler();
1199
+ const compilingPipelines = new Set();
1200
+
1201
+ const onLoaded = () => {
1202
+
1203
+ loaded ++;
1204
+
1205
+ if ( onProgress !== null ) {
1206
+
1207
+ onProgress( new ProgressEvent( 'progress', { lengthComputable: true, loaded, total } ) );
1208
+
1209
+ }
1210
+
1211
+ };
1212
+
1213
+ const yieldPreCompile = async () => {
1214
+
1215
+ if ( scheduler.needsYield() === false ) return;
1216
+
1217
+ const activePrecompilationState = this._precompilationState;
1218
+
1219
+ this._finishPreCompile();
1220
+
1221
+ await scheduler.yield();
1222
+
1223
+ this._beginPreCompile( activePrecompilationState );
1224
+
1225
+ };
1226
+
1062
1227
  for ( const item of compilationPromises ) {
1063
1228
 
1229
+ if ( item.computeNodes !== undefined ) {
1230
+
1231
+ // compute work queued by the drawing pipeline, e.g. its culling
1232
+
1233
+ await this.compileComputeAsync( item.computeNodes );
1234
+
1235
+ onLoaded();
1236
+
1237
+ continue;
1238
+
1239
+ }
1240
+
1241
+ const pipelinePromises = [];
1242
+
1243
+ // each item is compiled with the state of the render call that queued it, e.g. a nested render into another target
1244
+
1245
+ const itemPrecompilationState = item.precompilationState;
1246
+ itemPrecompilationState.item = item;
1247
+
1248
+ this._beginPreCompile( itemPrecompilationState );
1249
+
1064
1250
  const renderObject = this._objects.get( item.object, item.material, item.scene, item.camera, item.lightsNode, item.renderContext, item.clippingContext, item.passId );
1065
1251
  renderObject.drawRange = item.object.geometry.drawRange;
1066
1252
  renderObject.group = item.group;
1067
1253
 
1068
- // Use async node building to yield to main thread
1069
- await this._nodes.getForRenderAsync( renderObject );
1070
-
1071
- this._isPreCompiling = true; // note: no awaits are allowed when this flag is true otherwise the state leaks outside of this method
1254
+ await this._nodes.getForRenderAsync( renderObject, yieldPreCompile );
1072
1255
  this._nodes.updateBefore( renderObject );
1073
1256
  this._geometries.updateForRender( renderObject );
1074
1257
  this._nodes.updateForRender( renderObject );
1075
1258
  this._bindings.updateForRender( renderObject );
1076
- this._isPreCompiling = false;
1077
-
1078
- // Wait for pipeline creation
1079
- const pipelinePromises = [];
1080
1259
  this._pipelines.getForRender( renderObject, pipelinePromises );
1260
+ this._nodes.updateAfter( renderObject );
1261
+
1262
+ this._finishPreCompile();
1263
+
1081
1264
  if ( pipelinePromises.length > 0 ) {
1082
1265
 
1083
- await Promise.all( pipelinePromises );
1266
+ const promise = Promise.all( pipelinePromises ).then( () => {
1084
1267
 
1085
- }
1268
+ compilingPipelines.delete( promise );
1269
+ onLoaded();
1086
1270
 
1087
- this._isPreCompiling = true;
1088
- this._nodes.updateAfter( renderObject );
1089
- this._isPreCompiling = false;
1271
+ } );
1090
1272
 
1091
- loaded ++;
1273
+ compilingPipelines.add( promise );
1092
1274
 
1093
- if ( onProgress !== null ) {
1275
+ while ( compilingPipelines.size >= _maxCompilingPipelines ) await Promise.race( compilingPipelines );
1094
1276
 
1095
- onProgress( new ProgressEvent( 'progress', { lengthComputable: true, loaded, total } ) );
1277
+ } else {
1278
+
1279
+ onLoaded();
1096
1280
 
1097
1281
  }
1098
1282
 
1099
- // Yield between objects to allow animation frames
1100
- await yieldToMain();
1283
+ if ( scheduler.needsYield() ) await scheduler.yield();
1101
1284
 
1102
1285
  }
1103
1286
 
1287
+ await Promise.all( compilingPipelines );
1288
+
1289
+ }
1290
+
1291
+ /**
1292
+ * Sets up the renderer state for precompiling in `compileAsync()`.
1293
+ * The state must be restored with `_finishPreCompile()` before yielding to the main thread,
1294
+ * otherwise it leaks into renders executed in the meantime.
1295
+ *
1296
+ * @private
1297
+ * @param {Object} precompilationState - The precompilation state.
1298
+ */
1299
+ _beginPreCompile( precompilationState ) {
1300
+
1301
+ const { useFrameBufferTarget, renderTarget, mrt, renderContext, item } = precompilationState;
1302
+
1303
+ if ( useFrameBufferTarget === true ) this.setRenderTarget( renderTarget );
1304
+ this.setMRT( mrt );
1305
+
1306
+ if ( item !== null ) {
1307
+
1308
+ // apply the material side the work item was queued with since the renderer changes the side
1309
+ // temporarily, e.g. for the back and front pass of double-sided transparent materials
1310
+
1311
+ precompilationState.materialSide = item.material.side;
1312
+ item.material.side = item.side;
1313
+
1314
+ }
1315
+
1316
+ this._callDepth ++;
1317
+
1318
+ // node builds take their shared bind groups from the current render context
1319
+
1320
+ precompilationState.previousRenderContext = this._currentRenderContext;
1321
+
1322
+ if ( renderContext !== undefined ) this._currentRenderContext = renderContext;
1323
+
1324
+ this._precompilationState = precompilationState;
1325
+
1326
+ }
1327
+
1328
+ /**
1329
+ * Restores the renderer state after precompiling in `compileAsync()`.
1330
+ *
1331
+ * @private
1332
+ */
1333
+ _finishPreCompile() {
1334
+
1335
+ const { useFrameBufferTarget, outputRenderTarget, activeCubeFace, activeMipmapLevel, outputMRT, previousRenderContext, item, materialSide } = this._precompilationState;
1336
+
1337
+ if ( useFrameBufferTarget === true ) this.setRenderTarget( outputRenderTarget, activeCubeFace, activeMipmapLevel );
1338
+ this.setMRT( outputMRT );
1339
+
1340
+ if ( item !== null ) item.material.side = materialSide;
1341
+
1342
+ this._currentRenderContext = previousRenderContext;
1343
+
1344
+ this._callDepth --;
1345
+
1346
+ this._precompilationState = null;
1347
+
1104
1348
  }
1105
1349
 
1106
1350
  /**
@@ -1130,6 +1374,27 @@ class Renderer {
1130
1374
  const total = computeList.length;
1131
1375
  let loaded = 0;
1132
1376
 
1377
+ const scheduler = new CompileScheduler();
1378
+ const compilingPipelines = new Set();
1379
+
1380
+ const onLoaded = () => {
1381
+
1382
+ loaded ++;
1383
+
1384
+ if ( onProgress !== null ) {
1385
+
1386
+ onProgress( new ProgressEvent( 'progress', { lengthComputable: true, loaded, total } ) );
1387
+
1388
+ }
1389
+
1390
+ };
1391
+
1392
+ const yieldCompile = async () => {
1393
+
1394
+ if ( scheduler.needsYield() ) await scheduler.yield();
1395
+
1396
+ };
1397
+
1133
1398
  //
1134
1399
 
1135
1400
  const pipelines = this._pipelines;
@@ -1162,7 +1427,7 @@ class Renderer {
1162
1427
 
1163
1428
  }
1164
1429
 
1165
- await nodes.getForComputeAsync( computeNode );
1430
+ await nodes.getForComputeAsync( computeNode, yieldCompile );
1166
1431
 
1167
1432
  nodes.updateBeforeForCompute( computeNode );
1168
1433
  nodes.updateForCompute( computeNode );
@@ -1172,22 +1437,36 @@ class Renderer {
1172
1437
  const compilationPromises = [];
1173
1438
 
1174
1439
  pipelines.getForCompute( computeNode, computeBindings, compilationPromises );
1175
- await Promise.all( compilationPromises );
1176
1440
 
1177
1441
  nodes.updateAfterForCompute( computeNode );
1178
1442
 
1179
- loaded ++;
1443
+ // Pipelines are compiled in parallel while the next compute nodes are processed
1180
1444
 
1181
- if ( onProgress !== null ) {
1445
+ if ( compilationPromises.length > 0 ) {
1182
1446
 
1183
- onProgress( new ProgressEvent( 'progress', { lengthComputable: true, loaded, total } ) );
1447
+ const promise = Promise.all( compilationPromises ).then( () => {
1448
+
1449
+ compilingPipelines.delete( promise );
1450
+ onLoaded();
1451
+
1452
+ } );
1453
+
1454
+ compilingPipelines.add( promise );
1455
+
1456
+ while ( compilingPipelines.size >= _maxCompilingPipelines ) await Promise.race( compilingPipelines );
1457
+
1458
+ } else {
1459
+
1460
+ onLoaded();
1184
1461
 
1185
1462
  }
1186
1463
 
1187
- if ( loaded < total ) await yieldToMain();
1464
+ await yieldCompile();
1188
1465
 
1189
1466
  }
1190
1467
 
1468
+ await Promise.all( compilingPipelines );
1469
+
1191
1470
  }
1192
1471
 
1193
1472
  /**
@@ -1384,7 +1663,8 @@ class Renderer {
1384
1663
 
1385
1664
  /**
1386
1665
  * Returns `true` if the cached GPU render bundle for the given bundle group is
1387
- * out-of-date and must be recorded again.
1666
+ * out-of-date and must be recorded again. The drawing pipeline decides which objects are
1667
+ * recorded, so bundles recorded by another drawing pipeline are recorded again.
1388
1668
  *
1389
1669
  * @private
1390
1670
  * @param {BundleGroup} bundleGroup - The bundle group.
@@ -1393,7 +1673,43 @@ class Renderer {
1393
1673
  */
1394
1674
  _bundleNeedsUpdate( bundleGroup, renderBundleData ) {
1395
1675
 
1396
- return renderBundleData.bundleGPU === undefined || bundleGroup.version !== renderBundleData.version;
1676
+ if ( renderBundleData.bundleGPU === undefined || bundleGroup.version !== renderBundleData.version || renderBundleData.drawingPipeline !== this.drawingPipeline ) return true;
1677
+
1678
+ // the recorded bundle references the buffers of its attributes. they are only verified after a disposal
1679
+
1680
+ const attributes = this._attributes;
1681
+
1682
+ if ( renderBundleData.attributesDisposeVersion !== attributes.disposeVersion ) {
1683
+
1684
+ renderBundleData.attributesDisposeVersion = attributes.disposeVersion;
1685
+
1686
+ for ( const renderObject of renderBundleData.renderObjects ) {
1687
+
1688
+ const index = renderObject.getIndex();
1689
+
1690
+ let disposed = index !== null && attributes.has( index ) === false;
1691
+
1692
+ for ( const vertexBuffer of renderObject.getVertexBuffers() ) {
1693
+
1694
+ if ( attributes.has( vertexBuffer ) === false ) disposed = true;
1695
+
1696
+ }
1697
+
1698
+ if ( disposed ) {
1699
+
1700
+ // invalidate the recorded version so the bundle is recorded again
1701
+
1702
+ renderBundleData.version = null;
1703
+
1704
+ return true;
1705
+
1706
+ }
1707
+
1708
+ }
1709
+
1710
+ }
1711
+
1712
+ return false;
1397
1713
 
1398
1714
  }
1399
1715
 
@@ -1421,8 +1737,17 @@ class Renderer {
1421
1737
 
1422
1738
  this.backend.beginBundle( renderContext );
1423
1739
 
1740
+ // nested renders, like shadow maps updated by the objects of the bundle, record their own bundles
1741
+
1742
+ const previousRenderBundle = this._currentRenderBundle;
1743
+
1424
1744
  this._currentRenderBundle = renderBundle;
1425
1745
 
1746
+ // objects whose pipelines are not ready yet reset the version, so the bundle is recorded again
1747
+
1748
+ renderBundleData.version = bundleGroup.version;
1749
+ renderBundleData.drawingPipeline = this.drawingPipeline;
1750
+
1426
1751
  const {
1427
1752
  transparentDoublePass: transparentDoublePassObjects,
1428
1753
  transparent: transparentObjects,
@@ -1432,14 +1757,12 @@ class Renderer {
1432
1757
  if ( this.opaque === true && opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode );
1433
1758
  if ( this.transparent === true && transparentObjects.length > 0 ) this._renderTransparents( transparentObjects, transparentDoublePassObjects, camera, sceneRef, lightsNode );
1434
1759
 
1435
- this._currentRenderBundle = null;
1760
+ this._currentRenderBundle = previousRenderBundle;
1436
1761
 
1437
1762
  //
1438
1763
 
1439
1764
  this.backend.finishBundle( renderContext, renderBundle );
1440
1765
 
1441
- renderBundleData.version = bundleGroup.version;
1442
-
1443
1766
  } else {
1444
1767
 
1445
1768
  const { renderObjects } = renderBundleData;
@@ -1502,6 +1825,8 @@ class Renderer {
1502
1825
 
1503
1826
  }
1504
1827
 
1828
+ this._animation.start();
1829
+
1505
1830
  this._renderScene( scene, camera );
1506
1831
 
1507
1832
  }
@@ -1595,6 +1920,16 @@ class Renderer {
1595
1920
 
1596
1921
  this._frameBufferTargets.delete( target );
1597
1922
 
1923
+ const quadData = this._quadCache.get( frameBufferTarget );
1924
+
1925
+ if ( quadData !== undefined ) {
1926
+
1927
+ quadData.quad.material.dispose();
1928
+
1929
+ this._quadCache.delete( frameBufferTarget );
1930
+
1931
+ }
1932
+
1598
1933
  };
1599
1934
 
1600
1935
  target.addEventListener( 'dispose', dispose );
@@ -1676,6 +2011,11 @@ class Renderer {
1676
2011
  const previousRenderContext = this._currentRenderContext;
1677
2012
  const previousRenderObjectFunction = this._currentRenderObjectFunction;
1678
2013
  const previousHandleObjectFunction = this._handleObjectFunction;
2014
+ const previousRenderBundle = this._currentRenderBundle;
2015
+
2016
+ // a render nested in the recording of a render bundle draws its objects directly
2017
+
2018
+ this._currentRenderBundle = null;
1679
2019
 
1680
2020
  this.lighting.beginRender( scene );
1681
2021
 
@@ -1731,7 +2071,7 @@ class Renderer {
1731
2071
 
1732
2072
  //
1733
2073
 
1734
- const renderContext = this._renderContexts.get( renderTarget, this._mrt, this._callDepth );
2074
+ const renderContext = this._renderContexts.get( renderTarget, this._mrt, this._callDepth, camera );
1735
2075
 
1736
2076
  this._currentRenderContext = renderContext;
1737
2077
  this._currentRenderObjectFunction = this._renderObjectFunction || this.renderObject;
@@ -1763,20 +2103,18 @@ class Renderer {
1763
2103
 
1764
2104
  let viewport = canvasTarget._viewport;
1765
2105
  let scissor = canvasTarget._scissor;
2106
+ let scissorTest = canvasTarget._scissorTest;
1766
2107
  let pixelRatio = canvasTarget._pixelRatio;
1767
2108
 
1768
2109
  if ( renderTarget !== null ) {
1769
2110
 
1770
2111
  viewport = renderTarget.viewport;
1771
2112
  scissor = renderTarget.scissor;
2113
+ scissorTest = renderTarget.scissorTest;
1772
2114
  pixelRatio = 1;
1773
2115
 
1774
2116
  }
1775
2117
 
1776
- this.getDrawingBufferSize( _drawingBufferSize );
1777
-
1778
- _screen.set( 0, 0, _drawingBufferSize.width, _drawingBufferSize.height );
1779
-
1780
2118
  const minDepth = ( viewport.minDepth === undefined ) ? 0 : viewport.minDepth;
1781
2119
  const maxDepth = ( viewport.maxDepth === undefined ) ? 1 : viewport.maxDepth;
1782
2120
 
@@ -1785,10 +2123,8 @@ class Renderer {
1785
2123
  renderContext.viewportValue.height >>= activeMipmapLevel;
1786
2124
  renderContext.viewportValue.minDepth = minDepth;
1787
2125
  renderContext.viewportValue.maxDepth = maxDepth;
1788
- renderContext.viewport = renderContext.viewportValue.equals( _screen ) === false;
1789
2126
 
1790
2127
  renderContext.scissorValue.copy( scissor ).multiplyScalar( pixelRatio ).floor();
1791
- renderContext.scissor = canvasTarget._scissorTest && renderContext.scissorValue.equals( _screen ) === false;
1792
2128
  renderContext.scissorValue.width >>= activeMipmapLevel;
1793
2129
  renderContext.scissorValue.height >>= activeMipmapLevel;
1794
2130
 
@@ -1801,26 +2137,16 @@ class Renderer {
1801
2137
 
1802
2138
  //
1803
2139
 
1804
- _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
1805
-
1806
- if ( camera.isArrayCamera ) {
1807
-
1808
- _frustumArray.setFromArrayCamera( camera );
1809
-
1810
- } else {
1811
-
1812
- _frustum.setFromProjectionMatrix( _projScreenMatrix, camera.coordinateSystem, camera.reversedDepth );
1813
-
1814
- }
2140
+ this.drawingPipeline.begin( camera, renderContext );
1815
2141
 
1816
2142
  this._renderLists.update( nodeFrame.frameId );
1817
2143
 
1818
2144
  const renderList = this._renderLists.get( scene, camera, this.lighting );
1819
- renderList.begin();
2145
+ this.drawingPipeline.beginRenderList( renderList );
1820
2146
 
1821
- this._projectObject( scene, camera, 0, renderList, renderContext.clippingContext );
2147
+ this.drawingPipeline.project( scene, camera, 0, renderList, renderContext.clippingContext );
1822
2148
 
1823
- renderList.finish();
2149
+ this.drawingPipeline.finishRenderList( renderList );
1824
2150
 
1825
2151
  if ( this.sortObjects === true ) {
1826
2152
 
@@ -1846,6 +2172,8 @@ class Renderer {
1846
2172
 
1847
2173
  } else {
1848
2174
 
2175
+ this.getDrawingBufferSize( _drawingBufferSize );
2176
+
1849
2177
  renderContext.textures = null;
1850
2178
  renderContext.depthTexture = null;
1851
2179
  renderContext.width = _drawingBufferSize.width;
@@ -1878,6 +2206,11 @@ class Renderer {
1878
2206
 
1879
2207
  }
1880
2208
 
2209
+ _screen.set( 0, 0, renderContext.width, renderContext.height );
2210
+
2211
+ renderContext.viewport = renderContext.viewportValue.equals( _screen ) === false;
2212
+ renderContext.scissor = scissorTest && renderContext.scissorValue.equals( _screen ) === false;
2213
+
1881
2214
  //
1882
2215
 
1883
2216
  this._background.update( sceneRef, renderList, renderContext );
@@ -1911,6 +2244,7 @@ class Renderer {
1911
2244
  this._currentRenderContext = previousRenderContext;
1912
2245
  this._currentRenderObjectFunction = previousRenderObjectFunction;
1913
2246
  this._handleObjectFunction = previousHandleObjectFunction;
2247
+ this._currentRenderBundle = previousRenderBundle;
1914
2248
 
1915
2249
  this.lighting.finishRender( scene );
1916
2250
 
@@ -1961,7 +2295,7 @@ class Renderer {
1961
2295
 
1962
2296
  const cacheKey = this._nodes.getOutputCacheKey();
1963
2297
 
1964
- let quadData = this._quadCache.get( renderTarget.texture );
2298
+ let quadData = this._quadCache.get( renderTarget );
1965
2299
  let quad;
1966
2300
 
1967
2301
  if ( quadData === undefined ) {
@@ -1977,21 +2311,7 @@ class Renderer {
1977
2311
  cacheKey
1978
2312
  };
1979
2313
 
1980
- this._quadCache.set( renderTarget.texture, quadData );
1981
-
1982
- // dispose logic
1983
-
1984
- const dispose = () => {
1985
-
1986
- quad.material.dispose();
1987
-
1988
- this._quadCache.delete( renderTarget.texture );
1989
-
1990
- renderTarget.texture.removeEventListener( 'dispose', dispose );
1991
-
1992
- };
1993
-
1994
- renderTarget.texture.addEventListener( 'dispose', dispose );
2314
+ this._quadCache.set( renderTarget, quadData );
1995
2315
 
1996
2316
  } else {
1997
2317
 
@@ -2069,6 +2389,9 @@ class Renderer {
2069
2389
 
2070
2390
  if ( this._initialized === false ) await this.init();
2071
2391
 
2392
+ // started before assigning the callback, so it first runs on the next frame
2393
+
2394
+ if ( callback !== null ) this._animation.start();
2072
2395
  this._animation.setAnimationLoop( callback );
2073
2396
 
2074
2397
  }
@@ -2089,10 +2412,10 @@ class Renderer {
2089
2412
  * from the GPU to the CPU in context of compute shaders.
2090
2413
  *
2091
2414
  * @async
2092
- * @param {BufferAttribute} attribute - The storage buffer attribute to read frm.
2093
- * @param {ReadbackBuffer|ArrayBuffer} target - The storage buffer attribute.
2094
- * @param {number} offset - The storage buffer attribute.
2095
- * @param {number} count - The offset from which to start reading the
2415
+ * @param {BufferAttribute} attribute - The storage buffer attribute to read from.
2416
+ * @param {?(ReadbackBuffer|ArrayBuffer)} [target=null] - The readback buffer or array buffer that receives the data. If `null`, a new array buffer is returned.
2417
+ * @param {number} [offset=0] - The byte offset to start reading from. Must be a multiple of 4.
2418
+ * @param {number} [count=-1] - The number of bytes to read. Must be a multiple of 4, or `-1` to read to the end of the buffer.
2096
2419
  * @return {Promise<ArrayBuffer|ReadbackBuffer>} A promise that resolves with the buffer data when the data are ready.
2097
2420
  */
2098
2421
  async getArrayBufferAsync( attribute, target = null, offset = 0, count = - 1 ) {
@@ -2696,10 +3019,21 @@ class Renderer {
2696
3019
  */
2697
3020
  async dispose() {
2698
3021
 
3022
+ // edge case: If dispose() is called during an init, wait for the finish
3023
+
3024
+ if ( this._initPromise !== null ) {
3025
+
3026
+ await this.init();
3027
+
3028
+ }
3029
+
2699
3030
  if ( this._initialized === true ) {
2700
3031
 
2701
- this.info.dispose();
3032
+ // the drawing pipeline frees its resources while the managers of the renderer still track them
2702
3033
 
3034
+ this.drawingPipeline.dispose();
3035
+
3036
+ this.lighting.dispose();
2703
3037
  this._inspector.dispose();
2704
3038
  this._animation.dispose();
2705
3039
  this._objects.dispose();
@@ -2710,7 +3044,6 @@ class Renderer {
2710
3044
  this._bindings.dispose();
2711
3045
  this._renderLists.dispose();
2712
3046
  this._renderContexts.dispose();
2713
- this._textures.dispose();
2714
3047
 
2715
3048
  for ( const canvasTarget of this._frameBufferTargets.keys() ) {
2716
3049
 
@@ -2718,12 +3051,16 @@ class Renderer {
2718
3051
 
2719
3052
  }
2720
3053
 
3054
+ this._destroyCanvasTarget( this._canvasTarget );
3055
+
3056
+ this._textures.dispose();
3057
+ this.info.dispose();
3058
+
2721
3059
  await this.backend.dispose();
2722
3060
 
2723
3061
  }
2724
3062
 
2725
3063
  this.setRenderTarget( null );
2726
- this.setAnimationLoop( null );
2727
3064
 
2728
3065
  }
2729
3066
 
@@ -2747,6 +3084,7 @@ class Renderer {
2747
3084
 
2748
3085
  const renderObjects = this._objects._renderObjects;
2749
3086
  const buffers = new Set();
3087
+ const bufferOf = ( attribute ) => this.backend.getBufferAttribute( attribute );
2750
3088
 
2751
3089
  for ( const renderObject of Array.from( renderObjects ) ) {
2752
3090
 
@@ -2755,11 +3093,11 @@ class Renderer {
2755
3093
  if ( renderObject._nodeBuilderState ) {
2756
3094
 
2757
3095
  const geometry = renderObject.geometry;
2758
- const own = new Set( Object.values( geometry.attributes ) );
3096
+ const own = new Set( Object.values( geometry.attributes ).map( bufferOf ) );
2759
3097
 
2760
3098
  for ( const attribute of renderObject.getAttributes() ) {
2761
3099
 
2762
- if ( own.has( attribute ) === false ) buffers.add( attribute );
3100
+ if ( own.has( bufferOf( attribute ) ) === false ) buffers.add( bufferOf( attribute ) );
2763
3101
 
2764
3102
  }
2765
3103
 
@@ -2775,7 +3113,7 @@ class Renderer {
2775
3113
 
2776
3114
  if ( ! renderObject._nodeBuilderState ) continue;
2777
3115
 
2778
- for ( const attribute of renderObject.getAttributes() ) buffers.delete( attribute );
3116
+ for ( const attribute of renderObject.getAttributes() ) buffers.delete( bufferOf( attribute ) );
2779
3117
 
2780
3118
  }
2781
3119
 
@@ -2842,9 +3180,12 @@ class Renderer {
2842
3180
  setCanvasTarget( canvasTarget ) {
2843
3181
 
2844
3182
  this._canvasTarget.removeEventListener( 'resize', this._onCanvasTargetResize );
3183
+ // keep any dispose event listener attached for later use
2845
3184
 
2846
3185
  this._canvasTarget = canvasTarget;
3186
+
2847
3187
  this._canvasTarget.addEventListener( 'resize', this._onCanvasTargetResize );
3188
+ this._canvasTarget.addEventListener( 'dispose', this._onCanvasTargetDispose );
2848
3189
 
2849
3190
  }
2850
3191
 
@@ -2944,8 +3285,24 @@ class Renderer {
2944
3285
 
2945
3286
  }
2946
3287
 
3288
+ const computeList = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ];
3289
+
3290
+ if ( computeList.length === 0 || computeList.some( computeNode => computeNode?.isComputeNode !== true ) ) {
3291
+
3292
+ throw new Error( 'THREE.Renderer: ".compute()" expects a "ComputeNode".' );
3293
+
3294
+ }
3295
+
3296
+ if ( dispatchSize !== null && computeList.some( computeNode => computeNode.count !== null || computeNode.dispatchSize !== null ) ) {
3297
+
3298
+ throw new Error( 'THREE.Renderer: A dispatch size cannot be passed to "renderer.compute()" for nodes created with "compute( count )". Use "computeKernel()" instead.' );
3299
+
3300
+ }
3301
+
2947
3302
  //
2948
3303
 
3304
+ this._animation.start();
3305
+
2949
3306
  const nodeFrame = this._nodes.nodeFrame;
2950
3307
 
2951
3308
  const previousRenderId = nodeFrame.renderId;
@@ -2971,14 +3328,6 @@ class Renderer {
2971
3328
  const bindings = this._bindings;
2972
3329
  const nodes = this._nodes;
2973
3330
 
2974
- const computeList = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ];
2975
-
2976
- if ( computeList[ 0 ] === undefined || computeList[ 0 ].isComputeNode !== true ) {
2977
-
2978
- throw new Error( 'THREE.Renderer: .compute() expects a ComputeNode.' );
2979
-
2980
- }
2981
-
2982
3331
  backend.beginCompute( computeNodes );
2983
3332
 
2984
3333
  for ( const computeNode of computeList ) {
@@ -3018,6 +3367,8 @@ class Renderer {
3018
3367
  const computeBindings = bindings.getForCompute( computeNode );
3019
3368
  const computePipeline = pipelines.getForCompute( computeNode, computeBindings );
3020
3369
 
3370
+ this._updateDispatchSize( computeNode, dispatchSize );
3371
+
3021
3372
  backend.compute( computeNodes, computeNode, computeBindings, computePipeline, dispatchSize );
3022
3373
 
3023
3374
  nodes.updateAfterForCompute( computeNode );
@@ -3345,175 +3696,6 @@ class Renderer {
3345
3696
 
3346
3697
  }
3347
3698
 
3348
- /**
3349
- * Analyzes the given 3D object's hierarchy and builds render lists from the
3350
- * processed hierarchy.
3351
- *
3352
- * @private
3353
- * @param {Object3D} object - The 3D object to process (usually a scene).
3354
- * @param {Camera} camera - The camera the object is rendered with.
3355
- * @param {number} groupOrder - The group order is derived from the `renderOrder` of groups and is used to group 3D objects within groups.
3356
- * @param {RenderList} renderList - The current render list.
3357
- * @param {ClippingContext} clippingContext - The current clipping context.
3358
- */
3359
- _projectObject( object, camera, groupOrder, renderList, clippingContext ) {
3360
-
3361
- if ( object.visible === false ) return;
3362
-
3363
- const visible = object.layers.test( camera.layers );
3364
-
3365
- if ( visible ) {
3366
-
3367
- if ( object.isGroup ) {
3368
-
3369
- groupOrder = object.renderOrder;
3370
-
3371
- if ( object.isClippingGroup && object.enabled ) clippingContext = clippingContext.getGroupContext( object );
3372
-
3373
- } else if ( object.isLOD ) {
3374
-
3375
- if ( object.autoUpdate === true ) object.update( camera );
3376
-
3377
- } else if ( object.isLight ) {
3378
-
3379
- renderList.pushLight( object );
3380
-
3381
- } else if ( object.isSprite ) {
3382
-
3383
- const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
3384
-
3385
- if ( ! object.frustumCulled || object.intersectsFrustum( frustum ) ) {
3386
-
3387
- if ( this.sortObjects === true ) {
3388
-
3389
- _vector4.setFromMatrixPosition( object.matrixWorld ).applyMatrix4( _projScreenMatrix );
3390
-
3391
- }
3392
-
3393
- const { geometry, material } = object;
3394
-
3395
- if ( material.visible ) {
3396
-
3397
- renderList.push( object, geometry, material, groupOrder, _vector4.z, null, clippingContext );
3398
-
3399
- }
3400
-
3401
- }
3402
-
3403
- } else if ( object.isLineLoop ) {
3404
-
3405
- error( 'Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.' );
3406
-
3407
- } else if ( object.isMesh || object.isLine || object.isPoints ) {
3408
-
3409
- const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
3410
-
3411
- if ( ! object.frustumCulled || object.intersectsFrustum( frustum ) ) {
3412
-
3413
- const { geometry, material } = object;
3414
-
3415
- if ( this.sortObjects === true ) {
3416
-
3417
- if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
3418
-
3419
- _vector4
3420
- .copy( geometry.boundingSphere.center )
3421
- .applyMatrix4( object.matrixWorld )
3422
- .applyMatrix4( _projScreenMatrix );
3423
-
3424
- }
3425
-
3426
- if ( Array.isArray( material ) ) {
3427
-
3428
- const groups = geometry.groups;
3429
-
3430
- for ( let i = 0, l = groups.length; i < l; i ++ ) {
3431
-
3432
- const group = groups[ i ];
3433
- const groupMaterial = material[ group.materialIndex ];
3434
-
3435
- if ( groupMaterial && groupMaterial.visible ) {
3436
-
3437
- renderList.push( object, geometry, groupMaterial, groupOrder, _vector4.z, group, clippingContext );
3438
-
3439
- }
3440
-
3441
- }
3442
-
3443
- } else if ( material.visible ) {
3444
-
3445
- renderList.push( object, geometry, material, groupOrder, _vector4.z, null, clippingContext );
3446
-
3447
- }
3448
-
3449
- }
3450
-
3451
- }
3452
-
3453
- }
3454
-
3455
- if ( object.isBundleGroup === true && this.backend.beginBundle !== undefined ) {
3456
-
3457
- const baseRenderList = renderList;
3458
-
3459
- // replace render list
3460
-
3461
- renderList = this._renderLists.get( object, camera, this.lighting );
3462
-
3463
- const renderBundle = this._bundles.get( object, camera, this._currentRenderContext );
3464
- const renderBundleData = this.backend.get( renderBundle );
3465
- const renderBundleNeedsUpdate = this._bundleNeedsUpdate( object, renderBundleData );
3466
-
3467
- if ( renderBundleNeedsUpdate ) {
3468
-
3469
- // update render list if necessary
3470
-
3471
- renderList.begin();
3472
-
3473
- if ( renderBundleData.renderObjects === undefined ) {
3474
-
3475
- renderBundleData.renderObjects = [];
3476
-
3477
- } else {
3478
-
3479
- renderBundleData.renderObjects.length = 0;
3480
-
3481
- }
3482
-
3483
- const children = object.children;
3484
-
3485
- for ( let i = 0, l = children.length; i < l; i ++ ) {
3486
-
3487
- this._projectObject( children[ i ], camera, groupOrder, renderList, clippingContext );
3488
-
3489
- }
3490
-
3491
- renderList.finish();
3492
-
3493
- }
3494
-
3495
- baseRenderList.pushBundle( {
3496
- bundleGroup: object,
3497
- camera,
3498
- renderList,
3499
- } );
3500
-
3501
- return;
3502
-
3503
- }
3504
-
3505
- //
3506
-
3507
- const children = object.children;
3508
-
3509
- for ( let i = 0, l = children.length; i < l; i ++ ) {
3510
-
3511
- this._projectObject( children[ i ], camera, groupOrder, renderList, clippingContext );
3512
-
3513
- }
3514
-
3515
- }
3516
-
3517
3699
  /**
3518
3700
  * Renders the given render bundles.
3519
3701
  *
@@ -3724,8 +3906,9 @@ class Renderer {
3724
3906
  _updateCamera( camera, useXRCamera ) {
3725
3907
 
3726
3908
  const xr = this.xr;
3909
+ const useXR = xr.enabled === true && xr.isPresenting === true && useXRCamera === true;
3727
3910
 
3728
- if ( xr.isPresenting === false || useXRCamera === false ) {
3911
+ if ( useXR === false ) {
3729
3912
 
3730
3913
  let projectionMatrixNeedsUpdate = false;
3731
3914
 
@@ -3795,7 +3978,7 @@ class Renderer {
3795
3978
 
3796
3979
  // handle XR
3797
3980
 
3798
- if ( useXRCamera === true && xr.enabled === true && xr.isPresenting === true ) {
3981
+ if ( useXR === true ) {
3799
3982
 
3800
3983
  if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera );
3801
3984
  camera = xr.getCamera(); // use XR camera for rendering
@@ -3806,6 +3989,26 @@ class Renderer {
3806
3989
 
3807
3990
  }
3808
3991
 
3992
+ /**
3993
+ * Updates the indirect storage attribute that defines the dispatch size
3994
+ * of the given compute node, if any.
3995
+ *
3996
+ * @private
3997
+ * @param {ComputeNode} computeNode - The compute node.
3998
+ * @param {?(number|Array<number>|IndirectStorageBufferAttribute)} dispatchSize - The dispatch size of the compute call.
3999
+ */
4000
+ _updateDispatchSize( computeNode, dispatchSize ) {
4001
+
4002
+ const indirect = dispatchSize !== null ? dispatchSize : computeNode.dispatchSize;
4003
+
4004
+ if ( indirect && indirect.isIndirectStorageBufferAttribute === true ) {
4005
+
4006
+ this._attributes.update( indirect, AttributeType.INDIRECT );
4007
+
4008
+ }
4009
+
4010
+ }
4011
+
3809
4012
  /**
3810
4013
  * This method represents the default render object function that manages the render lifecycle
3811
4014
  * of the object.
@@ -3862,7 +4065,7 @@ class Renderer {
3862
4065
 
3863
4066
  }
3864
4067
 
3865
- overrideMaterial.alphaTest = material.alphaTest;
4068
+ overrideMaterial._alphaTest = material.alphaTest; // bypass the setter so the version doesn't change
3866
4069
  overrideMaterial.alphaMap = material.alphaMap;
3867
4070
  overrideMaterial.displacementMap = material.displacementMap;
3868
4071
  overrideMaterial.displacementScale = material.displacementScale;
@@ -4015,6 +4218,10 @@ class Renderer {
4015
4218
 
4016
4219
  if ( refreshType !== RenderObjectRefreshType.NONE ) this._nodes.updateAfter( renderObject );
4017
4220
 
4221
+ } else if ( this._currentRenderBundle !== null ) {
4222
+
4223
+ this.backend.get( this._currentRenderBundle ).version = - 1;
4224
+
4018
4225
  }
4019
4226
 
4020
4227
  }
@@ -4038,17 +4245,26 @@ class Renderer {
4038
4245
  // If in async compilation mode, queue the work for sequential execution
4039
4246
  if ( this._compilationPromises !== null ) {
4040
4247
 
4041
- // Store work items instead of promises - will be processed sequentially
4248
+ // Store work items instead of promises - will be processed sequentially.
4249
+ // The side is stored since the renderer might have changed it temporarily.
4042
4250
  this._compilationPromises.push( {
4043
4251
  object,
4044
4252
  material,
4253
+ side: material.side,
4045
4254
  scene,
4046
4255
  camera,
4047
4256
  lightsNode,
4048
4257
  group,
4049
4258
  clippingContext,
4050
4259
  passId,
4051
- renderContext: this._currentRenderContext
4260
+ renderContext: this._currentRenderContext,
4261
+ precompilationState: {
4262
+ ...this._precompilationState,
4263
+ useFrameBufferTarget: true,
4264
+ renderTarget: this.getRenderTarget(),
4265
+ mrt: this.getMRT(),
4266
+ renderContext: this._currentRenderContext
4267
+ }
4052
4268
  } );
4053
4269
 
4054
4270
  return;
@@ -4086,6 +4302,32 @@ class Renderer {
4086
4302
 
4087
4303
  }
4088
4304
 
4305
+ /**
4306
+ * Callback when a canvas target has been disposed.
4307
+ *
4308
+ * @private
4309
+ * @param {Object} event - The dispose event.
4310
+ */
4311
+ _onCanvasTargetDispose( event ) {
4312
+
4313
+ this._destroyCanvasTarget( event.target );
4314
+
4315
+ }
4316
+
4317
+ /**
4318
+ * Frees the GPU resources of the given canvas target.
4319
+ *
4320
+ * @private
4321
+ * @param {CanvasTarget} canvasTarget - The canvas target.
4322
+ */
4323
+ _destroyCanvasTarget( canvasTarget ) {
4324
+
4325
+ canvasTarget.removeEventListener( 'dispose', this._onCanvasTargetDispose );
4326
+
4327
+ if ( this._initialized ) this.backend.destroyCanvasTarget( canvasTarget );
4328
+
4329
+ }
4330
+
4089
4331
  /**
4090
4332
  * Alias for `compileAsync()`.
4091
4333
  *