@plastic-software/three 0.183.4 → 0.184.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/build/three.cjs +775 -287
  2. package/build/three.core.js +372 -110
  3. package/build/three.core.min.js +1 -1
  4. package/build/three.module.js +428 -181
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +7 -1
  7. package/build/three.tsl.min.js +1 -1
  8. package/build/three.webgpu.js +2979 -1281
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +2942 -1281
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/jsm/Addons.js +11 -0
  13. package/examples/jsm/animation/CCDIKSolver.js +5 -1
  14. package/examples/jsm/controls/ArcballControls.js +4 -1
  15. package/examples/jsm/controls/DragControls.js +2 -2
  16. package/examples/jsm/controls/FirstPersonControls.js +58 -54
  17. package/examples/jsm/controls/FlyControls.js +4 -0
  18. package/examples/jsm/controls/OrbitControls.js +2 -2
  19. package/examples/jsm/controls/TrackballControls.js +2 -2
  20. package/examples/jsm/controls/TransformControls.js +34 -2
  21. package/examples/jsm/csm/CSMShadowNode.js +6 -2
  22. package/examples/jsm/exporters/GLTFExporter.js +21 -5
  23. package/examples/jsm/geometries/TextGeometry.js +18 -0
  24. package/examples/jsm/helpers/LightProbeGridHelper.js +221 -0
  25. package/examples/jsm/inspector/Extension.js +13 -0
  26. package/examples/jsm/inspector/Inspector.js +169 -114
  27. package/examples/jsm/inspector/RendererInspector.js +2 -2
  28. package/examples/jsm/inspector/extensions/extensions.json +6 -0
  29. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +916 -0
  30. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +281 -0
  31. package/examples/jsm/inspector/tabs/Memory.js +128 -0
  32. package/examples/jsm/inspector/tabs/Parameters.js +34 -2
  33. package/examples/jsm/inspector/tabs/Performance.js +2 -2
  34. package/examples/jsm/inspector/tabs/Settings.js +264 -0
  35. package/examples/jsm/inspector/tabs/Timeline.js +1611 -0
  36. package/examples/jsm/inspector/tabs/Viewer.js +105 -3
  37. package/examples/jsm/inspector/ui/Graph.js +2 -2
  38. package/examples/jsm/inspector/ui/List.js +1 -1
  39. package/examples/jsm/inspector/ui/Profiler.js +273 -176
  40. package/examples/jsm/inspector/ui/Style.js +64 -10
  41. package/examples/jsm/inspector/ui/Tab.js +39 -7
  42. package/examples/jsm/inspector/ui/Values.js +39 -2
  43. package/examples/jsm/inspector/ui/utils.js +13 -0
  44. package/examples/jsm/interaction/InteractionManager.js +226 -0
  45. package/examples/jsm/libs/meshopt_decoder.module.js +8 -8
  46. package/examples/jsm/lighting/DynamicLighting.js +82 -0
  47. package/examples/jsm/lighting/LightProbeGrid.js +651 -0
  48. package/examples/jsm/lines/LineMaterial.js +1 -1
  49. package/examples/jsm/loaders/EXRLoader.js +682 -43
  50. package/examples/jsm/loaders/FBXLoader.js +233 -33
  51. package/examples/jsm/loaders/GLTFLoader.js +24 -7
  52. package/examples/jsm/loaders/HDRLoader.js +1 -1
  53. package/examples/jsm/loaders/KTX2Loader.js +8 -2
  54. package/examples/jsm/loaders/LDrawLoader.js +39 -47
  55. package/examples/jsm/loaders/SVGLoader.js +1 -1
  56. package/examples/jsm/loaders/VTKLoader.js +5 -1
  57. package/examples/jsm/loaders/collada/ColladaComposer.js +101 -7
  58. package/examples/jsm/loaders/collada/ColladaParser.js +19 -4
  59. package/examples/jsm/loaders/usd/USDAParser.js +6 -0
  60. package/examples/jsm/loaders/usd/USDCParser.js +26 -0
  61. package/examples/jsm/loaders/usd/USDComposer.js +656 -103
  62. package/examples/jsm/misc/GPUComputationRenderer.js +2 -0
  63. package/examples/jsm/misc/RollerCoaster.js +42 -4
  64. package/examples/jsm/modifiers/TessellateModifier.js +1 -1
  65. package/examples/jsm/objects/Reflector.js +73 -25
  66. package/examples/jsm/objects/Sky.js +14 -2
  67. package/examples/jsm/objects/SkyMesh.js +23 -6
  68. package/examples/jsm/renderers/Projector.js +18 -38
  69. package/examples/jsm/renderers/SVGRenderer.js +6 -25
  70. package/examples/jsm/transpiler/GLSLDecoder.js +2 -2
  71. package/examples/jsm/tsl/WebGLNodesHandler.js +605 -0
  72. package/examples/jsm/tsl/display/AfterImageNode.js +10 -0
  73. package/examples/jsm/tsl/display/AnamorphicNode.js +11 -0
  74. package/examples/jsm/tsl/display/BilateralBlurNode.js +10 -0
  75. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +3 -36
  76. package/examples/jsm/tsl/display/FSR1Node.js +477 -0
  77. package/examples/jsm/tsl/display/GTAONode.js +2 -1
  78. package/examples/jsm/tsl/display/GaussianBlurNode.js +10 -0
  79. package/examples/jsm/tsl/display/GodraysNode.js +2 -11
  80. package/examples/jsm/tsl/display/OutlineNode.js +66 -16
  81. package/examples/jsm/tsl/display/SSGINode.js +0 -4
  82. package/examples/jsm/tsl/display/SharpenNode.js +283 -0
  83. package/examples/jsm/tsl/display/TAAUNode.js +835 -0
  84. package/examples/jsm/tsl/display/TRAANode.js +48 -7
  85. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +300 -0
  86. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +61 -0
  87. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +111 -0
  88. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +99 -0
  89. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +134 -0
  90. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +161 -0
  91. package/examples/jsm/tsl/math/Bayer.js +13 -2
  92. package/examples/jsm/utils/BufferGeometryUtils.js +2 -3
  93. package/examples/jsm/utils/ColorUtils.js +76 -0
  94. package/examples/jsm/utils/SkeletonUtils.js +14 -8
  95. package/examples/jsm/webxr/XRHandMeshModel.js +36 -10
  96. package/examples/jsm/webxr/XRHandModelFactory.js +2 -1
  97. package/package.json +4 -4
  98. package/src/Three.Core.js +1 -0
  99. package/src/Three.TSL.js +6 -0
  100. package/src/Three.WebGPU.Nodes.js +3 -0
  101. package/src/Three.WebGPU.js +6 -0
  102. package/src/animation/AnimationAction.js +11 -1
  103. package/src/audio/AudioContext.js +2 -2
  104. package/src/constants.js +1 -1
  105. package/src/core/BufferAttribute.js +13 -1
  106. package/src/core/Clock.js +1 -1
  107. package/src/core/Object3D.js +1 -5
  108. package/src/core/RenderTarget.js +1 -0
  109. package/src/extras/curves/CatmullRomCurve3.js +3 -2
  110. package/src/loaders/AudioLoader.js +11 -1
  111. package/src/loaders/DataTextureLoader.js +6 -4
  112. package/src/loaders/FileLoader.js +1 -2
  113. package/src/loaders/ImageBitmapLoader.js +4 -6
  114. package/src/loaders/MaterialLoader.js +1 -1
  115. package/src/loaders/ObjectLoader.js +25 -4
  116. package/src/loaders/nodes/NodeObjectLoader.js +18 -0
  117. package/src/materials/MeshToonMaterial.js +1 -1
  118. package/src/materials/nodes/Line2NodeMaterial.js +27 -0
  119. package/src/materials/nodes/NodeMaterial.js +0 -27
  120. package/src/materials/nodes/manager/NodeMaterialObserver.js +188 -89
  121. package/src/math/Line3.js +3 -0
  122. package/src/math/Matrix2.js +13 -9
  123. package/src/math/Matrix3.js +13 -9
  124. package/src/math/Matrix4.js +13 -9
  125. package/src/math/Plane.js +4 -3
  126. package/src/math/Triangle.js +1 -1
  127. package/src/math/Vector2.js +11 -7
  128. package/src/math/Vector3.js +12 -8
  129. package/src/math/Vector4.js +13 -9
  130. package/src/nodes/Nodes.js +0 -1
  131. package/src/nodes/TSL.js +1 -1
  132. package/src/nodes/accessors/BufferAttributeNode.js +9 -3
  133. package/src/nodes/accessors/CubeTextureNode.js +7 -1
  134. package/src/nodes/accessors/MaterialProperties.js +2 -5
  135. package/src/nodes/accessors/Object3DNode.js +1 -1
  136. package/src/nodes/accessors/ReferenceBaseNode.js +2 -2
  137. package/src/nodes/accessors/ReferenceNode.js +4 -4
  138. package/src/nodes/accessors/SceneProperties.js +2 -8
  139. package/src/nodes/accessors/StorageBufferNode.js +10 -4
  140. package/src/nodes/accessors/StorageTextureNode.js +4 -9
  141. package/src/nodes/accessors/TextureNode.js +10 -2
  142. package/src/nodes/accessors/UniformArrayNode.js +2 -2
  143. package/src/nodes/code/FunctionCallNode.js +1 -1
  144. package/src/nodes/code/FunctionNode.js +1 -1
  145. package/src/nodes/core/ArrayNode.js +1 -1
  146. package/src/nodes/core/AssignNode.js +1 -1
  147. package/src/nodes/core/AttributeNode.js +1 -1
  148. package/src/nodes/core/BypassNode.js +1 -1
  149. package/src/nodes/core/ContextNode.js +1 -1
  150. package/src/nodes/core/IndexNode.js +2 -1
  151. package/src/nodes/core/InputNode.js +1 -1
  152. package/src/nodes/core/InspectorNode.js +1 -1
  153. package/src/nodes/core/IsolateNode.js +1 -1
  154. package/src/nodes/core/Node.js +83 -12
  155. package/src/nodes/core/NodeBuilder.js +117 -16
  156. package/src/nodes/core/NodeUtils.js +1 -1
  157. package/src/nodes/core/OutputStructNode.js +1 -1
  158. package/src/nodes/core/ParameterNode.js +1 -1
  159. package/src/nodes/core/StackNode.js +1 -1
  160. package/src/nodes/core/StructNode.js +1 -1
  161. package/src/nodes/core/StructTypeNode.js +1 -1
  162. package/src/nodes/core/SubBuildNode.js +1 -1
  163. package/src/nodes/core/UniformGroupNode.js +36 -6
  164. package/src/nodes/core/VarNode.js +1 -1
  165. package/src/nodes/core/VaryingNode.js +1 -1
  166. package/src/nodes/display/NormalMapNode.js +2 -2
  167. package/src/nodes/display/PassNode.js +27 -7
  168. package/src/nodes/display/RenderOutputNode.js +4 -4
  169. package/src/nodes/display/ScreenNode.js +1 -1
  170. package/src/nodes/display/ViewportDepthTextureNode.js +11 -15
  171. package/src/nodes/display/ViewportTextureNode.js +18 -7
  172. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +2 -2
  173. package/src/nodes/geometry/RangeNode.js +1 -1
  174. package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
  175. package/src/nodes/gpgpu/BarrierNode.js +9 -0
  176. package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -1
  177. package/src/nodes/gpgpu/ComputeNode.js +69 -44
  178. package/src/nodes/gpgpu/SubgroupFunctionNode.js +1 -1
  179. package/src/nodes/lighting/LightsNode.js +6 -27
  180. package/src/nodes/lighting/ShadowNode.js +24 -2
  181. package/src/nodes/math/BitcastNode.js +1 -1
  182. package/src/nodes/math/ConditionalNode.js +1 -1
  183. package/src/nodes/math/MathNode.js +73 -1
  184. package/src/nodes/math/OperatorNode.js +1 -1
  185. package/src/nodes/math/PackFloatNode.js +1 -1
  186. package/src/nodes/math/UnpackFloatNode.js +1 -1
  187. package/src/nodes/tsl/TSLBase.js +1 -1
  188. package/src/nodes/tsl/TSLCore.js +21 -3
  189. package/src/nodes/utils/ArrayElementNode.js +1 -1
  190. package/src/nodes/utils/ConvertNode.js +1 -1
  191. package/src/nodes/utils/DebugNode.js +1 -1
  192. package/src/nodes/utils/EventNode.js +30 -0
  193. package/src/nodes/utils/FlipNode.js +1 -1
  194. package/src/nodes/utils/FunctionOverloadingNode.js +1 -1
  195. package/src/nodes/utils/JoinNode.js +1 -1
  196. package/src/nodes/utils/MemberNode.js +1 -1
  197. package/src/nodes/utils/Remap.js +48 -0
  198. package/src/nodes/utils/RotateNode.js +1 -1
  199. package/src/nodes/utils/SetNode.js +1 -1
  200. package/src/nodes/utils/SplitNode.js +1 -1
  201. package/src/objects/BatchedMesh.js +17 -2
  202. package/src/objects/InstancedMesh.js +19 -3
  203. package/src/objects/SkinnedMesh.js +26 -9
  204. package/src/renderers/WebGLRenderer.js +147 -48
  205. package/src/renderers/common/Animation.js +3 -3
  206. package/src/renderers/common/Attributes.js +15 -1
  207. package/src/renderers/common/Backend.js +0 -8
  208. package/src/renderers/common/Background.js +2 -2
  209. package/src/renderers/common/BindGroup.js +1 -8
  210. package/src/renderers/common/Bindings.js +2 -2
  211. package/src/renderers/common/ComputePipeline.js +1 -1
  212. package/src/renderers/common/CubeRenderTarget.js +1 -1
  213. package/src/renderers/common/Info.js +333 -4
  214. package/src/renderers/common/InspectorBase.js +6 -1
  215. package/src/renderers/common/Pipelines.js +36 -3
  216. package/src/renderers/common/ReadbackBuffer.js +78 -0
  217. package/src/renderers/common/RenderBundle.js +3 -1
  218. package/src/renderers/common/RenderBundles.js +5 -2
  219. package/src/renderers/common/RenderObject.js +2 -2
  220. package/src/renderers/common/RenderObjects.js +3 -3
  221. package/src/renderers/common/RenderPipeline.js +35 -6
  222. package/src/renderers/common/Renderer.js +232 -53
  223. package/src/renderers/common/Textures.js +72 -3
  224. package/src/renderers/common/UniformsGroup.js +1 -1
  225. package/src/renderers/common/XRManager.js +34 -27
  226. package/src/renderers/common/extras/PMREMGenerator.js +23 -15
  227. package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
  228. package/src/renderers/common/nodes/NodeManager.js +230 -99
  229. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +0 -1
  230. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +1 -1
  231. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +80 -0
  232. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +8 -0
  233. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +2 -0
  234. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +1 -3
  235. package/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +7 -0
  236. package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +0 -1
  237. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +12 -2
  238. package/src/renderers/shaders/ShaderChunk.js +2 -0
  239. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +1 -2
  240. package/src/renderers/shaders/ShaderLib.js +0 -1
  241. package/src/renderers/shaders/UniformsLib.js +7 -2
  242. package/src/renderers/shaders/UniformsUtils.js +27 -5
  243. package/src/renderers/webgl/WebGLAnimation.js +2 -1
  244. package/src/renderers/webgl/WebGLBackground.js +13 -13
  245. package/src/renderers/webgl/WebGLBufferRenderer.js +0 -32
  246. package/src/renderers/webgl/WebGLCapabilities.js +6 -0
  247. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +0 -32
  248. package/src/renderers/webgl/WebGLMaterials.js +12 -13
  249. package/src/renderers/webgl/WebGLOutput.js +4 -1
  250. package/src/renderers/webgl/WebGLProgram.js +4 -0
  251. package/src/renderers/webgl/WebGLPrograms.js +21 -4
  252. package/src/renderers/webgl/WebGLRenderStates.js +13 -2
  253. package/src/renderers/webgl/WebGLState.js +43 -0
  254. package/src/renderers/webgl/WebGLTextures.js +129 -26
  255. package/src/renderers/webgl/WebGLUniformsGroups.js +19 -0
  256. package/src/renderers/webgl-fallback/WebGLBackend.js +106 -65
  257. package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +0 -41
  258. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +29 -51
  259. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +53 -19
  260. package/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +25 -0
  261. package/src/renderers/webgl-fallback/utils/WebGLState.js +42 -1
  262. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +63 -50
  263. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +1 -1
  264. package/src/renderers/webgpu/WebGPUBackend.js +160 -146
  265. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +55 -33
  266. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +103 -17
  267. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
  268. package/src/renderers/webgpu/utils/WebGPUCapabilities.js +48 -0
  269. package/src/renderers/webgpu/utils/WebGPUConstants.js +8 -0
  270. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +91 -17
  271. package/src/renderers/webgpu/utils/WebGPUUtils.js +18 -2
  272. package/src/renderers/webxr/WebXRController.js +12 -0
  273. package/src/textures/HTMLTexture.js +74 -0
  274. package/src/textures/Source.js +1 -1
  275. package/src/textures/Texture.js +13 -2
  276. package/src/utils.js +23 -1
  277. package/src/nodes/utils/RemapNode.js +0 -125
@@ -36,7 +36,7 @@ import { float, vec3, vec4, Fn } from '../../nodes/tsl/TSLCore.js';
36
36
  import { reference } from '../../nodes/accessors/ReferenceNode.js';
37
37
  import { highpModelNormalViewMatrix, highpModelViewMatrix } from '../../nodes/accessors/ModelNode.js';
38
38
  import { context } from '../../nodes/core/ContextNode.js';
39
- import { error, warn, warnOnce } from '../../utils.js';
39
+ import { error, warn, warnOnce, yieldToMain } from '../../utils.js';
40
40
 
41
41
  const _scene = /*@__PURE__*/ new Scene();
42
42
  const _drawingBufferSize = /*@__PURE__*/ new Vector2();
@@ -418,15 +418,14 @@ class Renderer {
418
418
  this._background = null;
419
419
 
420
420
  /**
421
+ * Cache for the fullscreen quad.
421
422
  * This fullscreen quad is used for internal render passes
422
423
  * like the tone mapping and color space output pass.
423
424
  *
424
425
  * @private
425
- * @type {QuadMesh}
426
+ * @type {Map<Texture,QuadMesh>}
426
427
  */
427
- this._quad = new QuadMesh( new NodeMaterial() );
428
- this._quad.name = 'Output Color Transform';
429
- this._quad.material.name = 'outputColorTransform';
428
+ this._quadCache = new Map();
430
429
 
431
430
  /**
432
431
  * A reference to the current render context.
@@ -456,13 +455,12 @@ class Renderer {
456
455
  this._transparentSort = null;
457
456
 
458
457
  /**
459
- * The framebuffer target.
458
+ * Cache of framebuffer targets per canvas target.
460
459
  *
461
460
  * @private
462
- * @type {?RenderTarget}
463
- * @default null
461
+ * @type {Map<CanvasTarget, RenderTarget>}
464
462
  */
465
- this._frameBufferTarget = null;
463
+ this._frameBufferTargets = new Map();
466
464
 
467
465
  const alphaClear = this.alpha === true ? 0 : 1;
468
466
 
@@ -787,11 +785,11 @@ class Renderer {
787
785
 
788
786
  this._nodes = new NodeManager( this, backend );
789
787
  this._animation = new Animation( this, this._nodes, this.info );
790
- this._attributes = new Attributes( backend );
788
+ this._attributes = new Attributes( backend, this.info );
791
789
  this._background = new Background( this, this._nodes );
792
790
  this._geometries = new Geometries( this._attributes, this.info );
793
791
  this._textures = new Textures( this, backend, this.info );
794
- this._pipelines = new Pipelines( backend, this._nodes );
792
+ this._pipelines = new Pipelines( backend, this._nodes, this.info );
795
793
  this._bindings = new Bindings( backend, this._nodes, this._textures, this._attributes, this._pipelines, this.info );
796
794
  this._objects = new RenderObjects( this, this._nodes, this._geometries, this._pipelines, this._bindings, this.info );
797
795
  this._renderLists = new RenderLists( this.lighting );
@@ -877,11 +875,15 @@ class Renderer {
877
875
 
878
876
  //
879
877
 
880
- const sceneRef = ( scene.isScene === true ) ? scene : _scene;
881
-
882
878
  if ( targetScene === null ) targetScene = scene;
883
879
 
884
- const renderTarget = this._renderTarget;
880
+ // Use the actual scene for caching when compiling individual objects
881
+ // This ensures cache keys match between compileAsync and render
882
+ const sceneRef = ( scene.isScene === true ) ? scene : ( targetScene.isScene === true ) ? targetScene : _scene;
883
+
884
+ // Match render()'s logic: use frameBufferTarget when needsFrameBufferTarget is true
885
+ const useFrameBufferTarget = this.needsFrameBufferTarget && this._renderTarget === null;
886
+ const renderTarget = useFrameBufferTarget ? this._getFrameBufferTarget() : ( this._renderTarget || this._outputRenderTarget );
885
887
  const renderContext = this._renderContexts.get( renderTarget, this._mrt );
886
888
  const activeMipmapLevel = this._activeMipmapLevel;
887
889
 
@@ -914,7 +916,8 @@ class Renderer {
914
916
 
915
917
  //
916
918
 
917
- const renderList = this._renderLists.get( scene, camera );
919
+ // Use sceneRef for render list to ensure lightsNode matches between compileAsync and render
920
+ const renderList = this._renderLists.get( sceneRef, camera );
918
921
  renderList.begin();
919
922
 
920
923
  this._projectObject( scene, camera, 0, renderList, renderContext.clippingContext );
@@ -966,7 +969,7 @@ class Renderer {
966
969
 
967
970
  }
968
971
 
969
- // process render lists
972
+ // process render lists - _createObjectPipeline will push async promises to _compilationPromises
970
973
 
971
974
  const opaqueObjects = renderList.opaque;
972
975
  const transparentObjects = renderList.transparent;
@@ -985,9 +988,39 @@ class Renderer {
985
988
  this._handleObjectFunction = previousHandleObjectFunction;
986
989
  this._compilationPromises = previousCompilationPromises;
987
990
 
988
- // wait for all promises setup by backends awaiting compilation/linking/pipeline creation to complete
991
+ // Process compilation work items sequentially to avoid freezing
992
+ // Yields between objects to keep animation smooth
993
+
994
+ for ( const item of compilationPromises ) {
989
995
 
990
- await Promise.all( compilationPromises );
996
+ const renderObject = this._objects.get( item.object, item.material, item.scene, item.camera, item.lightsNode, item.renderContext, item.clippingContext, item.passId );
997
+ renderObject.drawRange = item.object.geometry.drawRange;
998
+ renderObject.group = item.group;
999
+
1000
+ this._geometries.updateForRender( renderObject );
1001
+
1002
+ // Use async node building to yield to main thread
1003
+ await this._nodes.getForRenderAsync( renderObject );
1004
+
1005
+ this._nodes.updateBefore( renderObject );
1006
+ this._nodes.updateForRender( renderObject );
1007
+ this._bindings.updateForRender( renderObject );
1008
+
1009
+ // Wait for pipeline creation
1010
+ const pipelinePromises = [];
1011
+ this._pipelines.getForRender( renderObject, pipelinePromises );
1012
+ if ( pipelinePromises.length > 0 ) {
1013
+
1014
+ await Promise.all( pipelinePromises );
1015
+
1016
+ }
1017
+
1018
+ this._nodes.updateAfter( renderObject );
1019
+
1020
+ // Yield between objects to allow animation frames
1021
+ await yieldToMain();
1022
+
1023
+ }
991
1024
 
992
1025
  }
993
1026
 
@@ -1179,17 +1212,11 @@ class Renderer {
1179
1212
 
1180
1213
  //
1181
1214
 
1182
- const renderBundle = this._bundles.get( bundleGroup, camera );
1215
+ const renderBundle = this._bundles.get( bundleGroup, camera, renderContext );
1183
1216
  const renderBundleData = this.backend.get( renderBundle );
1184
1217
 
1185
- if ( renderBundleData.renderContexts === undefined ) renderBundleData.renderContexts = new Set();
1186
-
1187
- //
1188
-
1189
1218
  const needsUpdate = bundleGroup.version !== renderBundleData.version;
1190
- const renderBundleNeedsUpdate = renderBundleData.renderContexts.has( renderContext ) === false || needsUpdate;
1191
-
1192
- renderBundleData.renderContexts.add( renderContext );
1219
+ const renderBundleNeedsUpdate = needsUpdate || renderBundleData.bundleGPU === undefined;
1193
1220
 
1194
1221
  if ( renderBundleNeedsUpdate ) {
1195
1222
 
@@ -1306,9 +1333,12 @@ class Renderer {
1306
1333
  const { width, height } = this.getDrawingBufferSize( _drawingBufferSize );
1307
1334
  const { depth, stencil } = this;
1308
1335
 
1309
- let frameBufferTarget = this._frameBufferTarget;
1336
+ // TODO: Unify CanvasTarget and OutputRenderTarget
1337
+ const target = this._outputRenderTarget || this._canvasTarget;
1338
+
1339
+ let frameBufferTarget = this._frameBufferTargets.get( target );
1310
1340
 
1311
- if ( frameBufferTarget === null ) {
1341
+ if ( frameBufferTarget === undefined ) {
1312
1342
 
1313
1343
  frameBufferTarget = new RenderTarget( width, height, {
1314
1344
  depthBuffer: depth,
@@ -1324,7 +1354,19 @@ class Renderer {
1324
1354
 
1325
1355
  frameBufferTarget.isPostProcessingRenderTarget = true;
1326
1356
 
1327
- this._frameBufferTarget = frameBufferTarget;
1357
+ const dispose = () => {
1358
+
1359
+ target.removeEventListener( 'dispose', dispose );
1360
+
1361
+ frameBufferTarget.dispose();
1362
+
1363
+ this._frameBufferTargets.delete( target );
1364
+
1365
+ };
1366
+
1367
+ target.addEventListener( 'dispose', dispose );
1368
+
1369
+ this._frameBufferTargets.set( target, frameBufferTarget );
1328
1370
 
1329
1371
  }
1330
1372
 
@@ -1332,6 +1374,7 @@ class Renderer {
1332
1374
 
1333
1375
  frameBufferTarget.depthBuffer = depth;
1334
1376
  frameBufferTarget.stencilBuffer = stencil;
1377
+
1335
1378
  if ( outputRenderTarget !== null ) {
1336
1379
 
1337
1380
  frameBufferTarget.setSize( outputRenderTarget.width, outputRenderTarget.height, outputRenderTarget.depth );
@@ -1342,13 +1385,18 @@ class Renderer {
1342
1385
 
1343
1386
  }
1344
1387
 
1345
- const canvasTarget = this._canvasTarget;
1388
+ // RenderTarget || CanvasTarget
1389
+
1390
+ const viewport = this._outputRenderTarget ? this._outputRenderTarget.viewport : target._viewport;
1391
+ const scissor = this._outputRenderTarget ? this._outputRenderTarget.scissor : target._scissor;
1392
+ const pixelRatio = this._outputRenderTarget ? 1 : target._pixelRatio;
1393
+ const scissorTest = this._outputRenderTarget ? this._outputRenderTarget.scissorTest : target._scissorTest;
1346
1394
 
1347
- frameBufferTarget.viewport.copy( canvasTarget._viewport );
1348
- frameBufferTarget.scissor.copy( canvasTarget._scissor );
1349
- frameBufferTarget.viewport.multiplyScalar( canvasTarget._pixelRatio );
1350
- frameBufferTarget.scissor.multiplyScalar( canvasTarget._pixelRatio );
1351
- frameBufferTarget.scissorTest = canvasTarget._scissorTest;
1395
+ frameBufferTarget.viewport.copy( viewport );
1396
+ frameBufferTarget.scissor.copy( scissor );
1397
+ frameBufferTarget.viewport.multiplyScalar( pixelRatio );
1398
+ frameBufferTarget.scissor.multiplyScalar( pixelRatio );
1399
+ frameBufferTarget.scissorTest = scissorTest;
1352
1400
  frameBufferTarget.multiview = outputRenderTarget !== null ? outputRenderTarget.multiview : false;
1353
1401
  frameBufferTarget.resolveDepthBuffer = outputRenderTarget !== null ? outputRenderTarget.resolveDepthBuffer : true;
1354
1402
  frameBufferTarget._autoAllocateDepthBuffer = outputRenderTarget !== null ? outputRenderTarget._autoAllocateDepthBuffer : false;
@@ -1410,6 +1458,28 @@ class Renderer {
1410
1458
 
1411
1459
  }
1412
1460
 
1461
+ // make sure a new render target has correct default depth values
1462
+
1463
+ if ( renderTarget !== null && renderTarget.depthBuffer === true ) {
1464
+
1465
+ const renderTargetData = this._textures.get( renderTarget );
1466
+
1467
+ if ( renderTargetData.depthInitialized !== true ) {
1468
+
1469
+ // we need a single manual clear if auto clear depth is disabled
1470
+
1471
+ if ( this.autoClear === false || ( this.autoClear === true && this.autoClearDepth === false ) ) {
1472
+
1473
+ this.clearDepth();
1474
+
1475
+ }
1476
+
1477
+ renderTargetData.depthInitialized = true;
1478
+
1479
+ }
1480
+
1481
+ }
1482
+
1413
1483
  //
1414
1484
 
1415
1485
  const renderContext = this._renderContexts.get( renderTarget, this._mrt, this._callDepth );
@@ -1711,12 +1781,52 @@ class Renderer {
1711
1781
  */
1712
1782
  _renderOutput( renderTarget ) {
1713
1783
 
1714
- const quad = this._quad;
1784
+ const cacheKey = this._nodes.getOutputCacheKey();
1785
+
1786
+ let quadData = this._quadCache.get( renderTarget.texture );
1787
+ let quad;
1715
1788
 
1716
- if ( this._nodes.hasOutputChange( renderTarget.texture ) ) {
1789
+ if ( quadData === undefined ) {
1790
+
1791
+ quad = new QuadMesh( new NodeMaterial() );
1792
+ quad.name = 'Output Color Transform';
1793
+ quad.material.name = 'outputColorTransform';
1717
1794
 
1718
1795
  quad.material.fragmentNode = this._nodes.getOutputNode( renderTarget.texture );
1719
- quad.material.needsUpdate = true;
1796
+
1797
+ quadData = {
1798
+ quad,
1799
+ cacheKey
1800
+ };
1801
+
1802
+ this._quadCache.set( renderTarget.texture, quadData );
1803
+
1804
+ // dispose logic
1805
+
1806
+ const dispose = () => {
1807
+
1808
+ quad.material.dispose();
1809
+
1810
+ this._quadCache.delete( renderTarget.texture );
1811
+
1812
+ renderTarget.texture.removeEventListener( 'dispose', dispose );
1813
+
1814
+ };
1815
+
1816
+ renderTarget.texture.addEventListener( 'dispose', dispose );
1817
+
1818
+ } else {
1819
+
1820
+ quad = quadData.quad;
1821
+
1822
+ if ( quadData.cacheKey !== cacheKey ) {
1823
+
1824
+ quad.material.fragmentNode = this._nodes.getOutputNode( renderTarget.texture );
1825
+ quad.material.needsUpdate = true;
1826
+
1827
+ quadData.cacheKey = cacheKey;
1828
+
1829
+ }
1720
1830
 
1721
1831
  }
1722
1832
 
@@ -1743,7 +1853,7 @@ class Renderer {
1743
1853
  */
1744
1854
  getMaxAnisotropy() {
1745
1855
 
1746
- return this.backend.getMaxAnisotropy();
1856
+ return this.backend.capabilities.getMaxAnisotropy();
1747
1857
 
1748
1858
  }
1749
1859
 
@@ -1802,12 +1912,42 @@ class Renderer {
1802
1912
  * from the GPU to the CPU in context of compute shaders.
1803
1913
  *
1804
1914
  * @async
1805
- * @param {StorageBufferAttribute} attribute - The storage buffer attribute.
1806
- * @return {Promise<ArrayBuffer>} A promise that resolves with the buffer data when the data are ready.
1915
+ * @param {BufferAttribute} attribute - The storage buffer attribute to read frm.
1916
+ * @param {ReadbackBuffer|ArrayBuffer} target - The storage buffer attribute.
1917
+ * @param {number} offset - The storage buffer attribute.
1918
+ * @param {number} count - The offset from which to start reading the
1919
+ * @return {Promise<ArrayBuffer|ReadbackBuffer>} A promise that resolves with the buffer data when the data are ready.
1807
1920
  */
1808
- async getArrayBufferAsync( attribute ) {
1921
+ async getArrayBufferAsync( attribute, target = null, offset = 0, count = - 1 ) {
1922
+
1923
+ // tally the memory for this readback buffer
1924
+ if ( target !== null && target.isReadbackBuffer ) {
1925
+
1926
+ if ( this.info.memoryMap.has( target ) === false ) {
1927
+
1928
+ this.info.createReadbackBuffer( target );
1929
+
1930
+ const disposeInfo = () => {
1931
+
1932
+ target.removeEventListener( 'dispose', disposeInfo );
1809
1933
 
1810
- return await this.backend.getArrayBufferAsync( attribute );
1934
+ this.info.destroyReadbackBuffer( target );
1935
+
1936
+ };
1937
+
1938
+ target.addEventListener( 'dispose', disposeInfo );
1939
+
1940
+ }
1941
+
1942
+ }
1943
+
1944
+ if ( offset % 4 !== 0 || ( count > 0 && count % 4 !== 0 ) ) {
1945
+
1946
+ throw new Error( 'THREE.Renderer: "getArrayBufferAsync()" offset and count must be a multiple of 4.' );
1947
+
1948
+ }
1949
+
1950
+ return await this.backend.getArrayBufferAsync( attribute, target, offset, count );
1811
1951
 
1812
1952
  }
1813
1953
 
@@ -1999,7 +2139,7 @@ class Renderer {
1999
2139
  * Defines the viewport.
2000
2140
  *
2001
2141
  * @param {number | Vector4} x - The horizontal coordinate for the upper left corner of the viewport origin in logical pixel unit.
2002
- * @param {number} y - The vertical coordinate for the upper left corner of the viewport origin in logical pixel unit.
2142
+ * @param {number} y - The vertical coordinate for the upper left corner of the viewport origin in logical pixel unit.
2003
2143
  * @param {number} width - The width of the viewport in logical pixel unit.
2004
2144
  * @param {number} height - The height of the viewport in logical pixel unit.
2005
2145
  * @param {number} minDepth - The minimum depth value of the viewport. WebGPU only.
@@ -2143,7 +2283,7 @@ class Renderer {
2143
2283
 
2144
2284
  const renderTargetData = this._textures.get( renderTarget );
2145
2285
 
2146
- renderContext = this._renderContexts.get( renderTarget );
2286
+ renderContext = this._renderContexts.get( renderTarget, null, - 1 ); // using - 1 for the call depth to get a render context for the clear operation
2147
2287
  renderContext.textures = renderTargetData.textures;
2148
2288
  renderContext.depthTexture = renderTargetData.depthTexture;
2149
2289
  renderContext.width = renderTargetData.width;
@@ -2162,6 +2302,8 @@ class Renderer {
2162
2302
  renderContext.activeCubeFace = this.getActiveCubeFace();
2163
2303
  renderContext.activeMipmapLevel = this.getActiveMipmapLevel();
2164
2304
 
2305
+ if ( renderTarget.depthBuffer === true ) renderTargetData.depthInitialized = true;
2306
+
2165
2307
  }
2166
2308
 
2167
2309
  this.backend.clear( color, depth, stencil, renderContext );
@@ -2375,7 +2517,11 @@ class Renderer {
2375
2517
  this._renderContexts.dispose();
2376
2518
  this._textures.dispose();
2377
2519
 
2378
- if ( this._frameBufferTarget !== null ) this._frameBufferTarget.dispose();
2520
+ for ( const canvasTarget of this._frameBufferTargets.keys() ) {
2521
+
2522
+ canvasTarget.dispose();
2523
+
2524
+ }
2379
2525
 
2380
2526
  Object.values( this.backend.timestampQueryPool ).forEach( queryPool => {
2381
2527
 
@@ -2421,7 +2567,7 @@ class Renderer {
2421
2567
  /**
2422
2568
  * Sets the output render target for the renderer.
2423
2569
  *
2424
- * @param {Object} renderTarget - The render target to set as the output target.
2570
+ * @param {?RenderTarget} renderTarget - The render target to set as the output target.
2425
2571
  */
2426
2572
  setOutputRenderTarget( renderTarget ) {
2427
2573
 
@@ -2477,8 +2623,11 @@ class Renderer {
2477
2623
  this.setOutputRenderTarget( null );
2478
2624
  this.setRenderTarget( null );
2479
2625
 
2480
- this._frameBufferTarget.dispose();
2481
- this._frameBufferTarget = null;
2626
+ for ( const canvasTarget of this._frameBufferTargets.keys() ) {
2627
+
2628
+ canvasTarget.dispose();
2629
+
2630
+ }
2482
2631
 
2483
2632
  }
2484
2633
 
@@ -3334,14 +3483,19 @@ class Renderer {
3334
3483
  }
3335
3484
 
3336
3485
  /**
3337
- * Checks if the given compatibility is supported by the selected backend. If the
3338
- * renderer has not been initialized, this method always returns `false`.
3486
+ * Checks if the given compatibility is supported by the selected backend.
3339
3487
  *
3340
3488
  * @param {string} name - The compatibility's name.
3341
3489
  * @return {boolean} Whether the compatibility is supported or not.
3342
3490
  */
3343
3491
  hasCompatibility( name ) {
3344
3492
 
3493
+ if ( this._initialized === false ) {
3494
+
3495
+ throw new Error( 'Renderer: .hasCompatibility() called before the backend is initialized. Use "await renderer.init();" before using this method.' );
3496
+
3497
+ }
3498
+
3345
3499
  return this.backend.hasCompatibility( name );
3346
3500
 
3347
3501
  }
@@ -3395,9 +3549,13 @@ class Renderer {
3395
3549
 
3396
3550
  //
3397
3551
 
3398
- this.backend.draw( renderObject, this.info );
3552
+ if ( this._pipelines.isReady( renderObject ) ) {
3399
3553
 
3400
- if ( needsRefresh ) this._nodes.updateAfter( renderObject );
3554
+ this.backend.draw( renderObject, this.info );
3555
+
3556
+ if ( needsRefresh ) this._nodes.updateAfter( renderObject );
3557
+
3558
+ }
3401
3559
 
3402
3560
  }
3403
3561
 
@@ -3417,6 +3575,27 @@ class Renderer {
3417
3575
  */
3418
3576
  _createObjectPipeline( object, material, scene, camera, lightsNode, group, clippingContext, passId ) {
3419
3577
 
3578
+ // If in async compilation mode, queue the work for sequential execution
3579
+ if ( this._compilationPromises !== null ) {
3580
+
3581
+ // Store work items instead of promises - will be processed sequentially
3582
+ this._compilationPromises.push( {
3583
+ object,
3584
+ material,
3585
+ scene,
3586
+ camera,
3587
+ lightsNode,
3588
+ group,
3589
+ clippingContext,
3590
+ passId,
3591
+ renderContext: this._currentRenderContext
3592
+ } );
3593
+
3594
+ return;
3595
+
3596
+ }
3597
+
3598
+ // Sync path
3420
3599
  const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId );
3421
3600
  renderObject.drawRange = object.geometry.drawRange;
3422
3601
  renderObject.group = group;
@@ -48,6 +48,13 @@ class Textures extends DataMap {
48
48
  */
49
49
  this.info = info;
50
50
 
51
+ /**
52
+ * A set of HTMLTextures that need paint updates.
53
+ *
54
+ * @type {Set<HTMLTexture>}
55
+ */
56
+ this._htmlTextures = new Set();
57
+
51
58
  }
52
59
 
53
60
  /**
@@ -162,6 +169,8 @@ class Textures extends DataMap {
162
169
 
163
170
  renderTargetData.initialized = true;
164
171
 
172
+ this.info.memory.renderTargets ++;
173
+
165
174
  // dispose
166
175
 
167
176
  renderTargetData.onDispose = () => {
@@ -218,6 +227,56 @@ class Textures extends DataMap {
218
227
 
219
228
  }
220
229
 
230
+ // Ensure HTMLTexture elements are in the canvas before measuring size.
231
+
232
+ if ( texture.isHTMLTexture && texture.image ) {
233
+
234
+ const canvas = this.renderer.domElement;
235
+
236
+ if ( 'requestPaint' in canvas ) {
237
+
238
+ if ( ! canvas.hasAttribute( 'layoutsubtree' ) ) {
239
+
240
+ canvas.setAttribute( 'layoutsubtree', 'true' );
241
+
242
+ }
243
+
244
+ if ( texture.image.parentNode !== canvas ) {
245
+
246
+ canvas.appendChild( texture.image );
247
+
248
+ }
249
+
250
+ // Set up shared paint callback for all HTMLTextures.
251
+
252
+ if ( this._htmlTextures.size === 0 ) {
253
+
254
+ const htmlTextures = this._htmlTextures;
255
+
256
+ canvas.onpaint = ( event ) => {
257
+
258
+ const changed = event && event.changedElements;
259
+
260
+ for ( const t of htmlTextures ) {
261
+
262
+ if ( ! changed || changed.includes( t.image ) ) {
263
+
264
+ t.needsUpdate = true;
265
+
266
+ }
267
+
268
+ }
269
+
270
+ };
271
+
272
+ }
273
+
274
+ this._htmlTextures.add( texture );
275
+
276
+ }
277
+
278
+ }
279
+
221
280
  //
222
281
 
223
282
  const { width, height, depth } = this.getSize( texture );
@@ -322,7 +381,7 @@ class Textures extends DataMap {
322
381
 
323
382
  //
324
383
 
325
- this.info.memory.textures ++;
384
+ this.info.createTexture( texture );
326
385
 
327
386
  //
328
387
 
@@ -388,7 +447,13 @@ class Textures extends DataMap {
388
447
 
389
448
  if ( image.image !== undefined ) image = image.image;
390
449
 
391
- if ( ( typeof HTMLVideoElement !== 'undefined' ) && ( image instanceof HTMLVideoElement ) ) {
450
+ if ( texture.isHTMLTexture ) {
451
+
452
+ target.width = image.offsetWidth || 1;
453
+ target.height = image.offsetHeight || 1;
454
+ target.depth = 1;
455
+
456
+ } else if ( ( typeof HTMLVideoElement !== 'undefined' ) && ( image instanceof HTMLVideoElement ) ) {
392
457
 
393
458
  target.width = image.videoWidth || 1;
394
459
  target.height = image.videoHeight || 1;
@@ -504,6 +569,8 @@ class Textures extends DataMap {
504
569
  this.delete( renderTarget );
505
570
  this.backend.delete( renderTarget );
506
571
 
572
+ this.info.memory.renderTargets --;
573
+
507
574
  }
508
575
 
509
576
  }
@@ -547,9 +614,11 @@ class Textures extends DataMap {
547
614
 
548
615
  }
549
616
 
617
+ this._htmlTextures.delete( texture );
618
+
550
619
  this.delete( texture );
551
620
 
552
- this.info.memory.textures --;
621
+ this.info.destroyTexture( texture );
553
622
 
554
623
  }
555
624
 
@@ -369,7 +369,7 @@ class UniformsGroup extends UniformBuffer {
369
369
  const offset = uniform.offset;
370
370
  const type = uniform.getType();
371
371
 
372
- if ( a[ offset + 0 ] !== v.x || a[ offset + 1 ] !== v.y || a[ offset + 2 ] !== v.z || a[ offset + 4 ] !== v.w ) {
372
+ if ( a[ offset + 0 ] !== v.x || a[ offset + 1 ] !== v.y || a[ offset + 2 ] !== v.z || a[ offset + 3 ] !== v.w ) {
373
373
 
374
374
  const b = this._getBufferForType( type );
375
375