super-three 0.172.0 → 0.173.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 (180) hide show
  1. package/LICENSE +1 -1
  2. package/build/three.cjs +439 -380
  3. package/build/three.core.js +413 -41
  4. package/build/three.core.min.js +2 -2
  5. package/build/three.module.js +28 -344
  6. package/build/three.module.min.js +2 -2
  7. package/build/three.tsl.js +11 -3
  8. package/build/three.tsl.min.js +2 -2
  9. package/build/three.webgpu.js +7550 -1798
  10. package/build/three.webgpu.min.js +2 -2
  11. package/build/three.webgpu.nodes.js +7551 -1798
  12. package/build/three.webgpu.nodes.min.js +2 -2
  13. package/examples/jsm/animation/CCDIKSolver.js +6 -5
  14. package/examples/jsm/capabilities/WebGPU.js +1 -1
  15. package/examples/jsm/controls/ArcballControls.js +23 -21
  16. package/examples/jsm/exporters/GLTFExporter.js +26 -25
  17. package/examples/jsm/geometries/TextGeometry.js +1 -12
  18. package/examples/jsm/interactive/InteractiveGroup.js +108 -51
  19. package/examples/jsm/libs/demuxer_mp4.js +109 -0
  20. package/examples/jsm/loaders/GCodeLoader.js +3 -1
  21. package/examples/jsm/loaders/GLTFLoader.js +0 -2
  22. package/examples/jsm/loaders/TDSLoader.js +0 -1
  23. package/examples/jsm/materials/MeshGouraudMaterial.js +2 -0
  24. package/examples/jsm/misc/GPUComputationRenderer.js +6 -7
  25. package/examples/jsm/misc/ProgressiveLightMap.js +4 -3
  26. package/examples/jsm/misc/ProgressiveLightMapGPU.js +4 -3
  27. package/examples/jsm/misc/Volume.js +7 -5
  28. package/examples/jsm/misc/VolumeSlice.js +5 -3
  29. package/examples/jsm/objects/WaterMesh.js +25 -20
  30. package/examples/jsm/physics/JoltPhysics.js +7 -7
  31. package/examples/jsm/physics/RapierPhysics.js +4 -4
  32. package/examples/jsm/postprocessing/EffectComposer.js +23 -2
  33. package/examples/jsm/postprocessing/OutputPass.js +2 -0
  34. package/examples/jsm/postprocessing/Pass.js +6 -1
  35. package/examples/jsm/shaders/OutputShader.js +5 -1
  36. package/examples/jsm/transpiler/GLSLDecoder.js +2 -2
  37. package/examples/jsm/transpiler/TSLEncoder.js +2 -0
  38. package/package.json +1 -1
  39. package/src/Three.Core.js +2 -0
  40. package/src/Three.TSL.js +9 -1
  41. package/src/cameras/ArrayCamera.js +1 -0
  42. package/src/constants.js +6 -1
  43. package/src/core/BufferAttribute.js +4 -0
  44. package/src/core/EventDispatcher.js +8 -6
  45. package/src/extras/ImageUtils.js +1 -11
  46. package/src/loaders/nodes/NodeObjectLoader.js +1 -1
  47. package/src/materials/nodes/MeshBasicNodeMaterial.js +1 -1
  48. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +1 -1
  49. package/src/materials/nodes/NodeMaterial.js +5 -5
  50. package/src/materials/nodes/NodeMaterials.js +0 -1
  51. package/src/materials/nodes/PointsNodeMaterial.js +109 -7
  52. package/src/materials/nodes/SpriteNodeMaterial.js +1 -1
  53. package/src/materials/nodes/VolumeNodeMaterial.js +3 -3
  54. package/src/materials/nodes/manager/NodeMaterialObserver.js +8 -0
  55. package/src/nodes/Nodes.js +4 -0
  56. package/src/nodes/TSL.js +4 -0
  57. package/src/nodes/accessors/Arrays.js +30 -8
  58. package/src/nodes/accessors/BatchNode.js +3 -3
  59. package/src/nodes/accessors/BufferAttributeNode.js +1 -1
  60. package/src/nodes/accessors/Camera.js +64 -3
  61. package/src/nodes/accessors/InstanceNode.js +1 -1
  62. package/src/nodes/accessors/MaterialNode.js +9 -9
  63. package/src/nodes/accessors/ModelViewProjectionNode.js +1 -1
  64. package/src/nodes/accessors/Normal.js +6 -2
  65. package/src/nodes/accessors/Object3DNode.js +0 -1
  66. package/src/nodes/accessors/Position.js +6 -6
  67. package/src/nodes/accessors/ReferenceBaseNode.js +2 -4
  68. package/src/nodes/accessors/ReferenceNode.js +2 -3
  69. package/src/nodes/accessors/StorageBufferNode.js +42 -5
  70. package/src/nodes/accessors/Tangent.js +2 -2
  71. package/src/nodes/accessors/Texture3DNode.js +1 -1
  72. package/src/nodes/accessors/TextureNode.js +12 -5
  73. package/src/nodes/accessors/UniformArrayNode.js +9 -3
  74. package/src/nodes/accessors/VelocityNode.js +0 -2
  75. package/src/nodes/code/ScriptableNode.js +3 -3
  76. package/src/nodes/core/ArrayNode.js +125 -0
  77. package/src/nodes/core/ConstNode.js +8 -0
  78. package/src/nodes/core/Node.js +14 -1
  79. package/src/nodes/core/NodeBuilder.js +229 -19
  80. package/src/nodes/core/NodeUtils.js +11 -1
  81. package/src/nodes/core/NodeVar.js +17 -1
  82. package/src/nodes/core/OutputStructNode.js +19 -9
  83. package/src/nodes/core/StackNode.js +20 -1
  84. package/src/nodes/core/StructNode.js +121 -0
  85. package/src/nodes/core/StructType.js +13 -0
  86. package/src/nodes/core/StructTypeNode.js +82 -21
  87. package/src/nodes/core/TempNode.js +1 -1
  88. package/src/nodes/core/VarNode.js +94 -7
  89. package/src/nodes/core/VaryingNode.js +19 -3
  90. package/src/nodes/display/BlendModes.js +88 -1
  91. package/src/nodes/display/BumpMapNode.js +6 -6
  92. package/src/nodes/display/NormalMapNode.js +6 -6
  93. package/src/nodes/display/PassNode.js +3 -1
  94. package/src/nodes/display/ScreenNode.js +9 -0
  95. package/src/nodes/fog/Fog.js +17 -0
  96. package/src/nodes/gpgpu/AtomicFunctionNode.js +20 -4
  97. package/src/nodes/gpgpu/ComputeBuiltinNode.js +8 -0
  98. package/src/nodes/gpgpu/WorkgroupInfoNode.js +1 -1
  99. package/src/nodes/lighting/ShadowNode.js +1 -1
  100. package/src/nodes/math/ConditionalNode.js +8 -1
  101. package/src/nodes/math/MathNode.js +14 -1
  102. package/src/nodes/math/OperatorNode.js +96 -18
  103. package/src/nodes/pmrem/PMREMUtils.js +1 -1
  104. package/src/nodes/shapes/Shapes.js +33 -0
  105. package/src/nodes/tsl/TSLBase.js +1 -0
  106. package/src/nodes/tsl/TSLCore.js +22 -2
  107. package/src/nodes/utils/ArrayElementNode.js +1 -1
  108. package/src/nodes/utils/LoopNode.js +8 -1
  109. package/src/nodes/utils/MemberNode.js +68 -0
  110. package/src/nodes/utils/StorageArrayElementNode.js +14 -0
  111. package/src/nodes/utils/Timer.js +21 -0
  112. package/src/objects/BatchedMesh.js +1 -1
  113. package/src/objects/Line.js +6 -6
  114. package/src/renderers/WebGLRenderer.js +7 -0
  115. package/src/renderers/common/Animation.js +23 -1
  116. package/src/renderers/common/Backend.js +58 -15
  117. package/src/renderers/common/Background.js +14 -0
  118. package/src/renderers/common/Binding.js +1 -1
  119. package/src/renderers/common/BufferUtils.js +1 -1
  120. package/src/renderers/common/BundleGroup.js +1 -1
  121. package/src/renderers/common/ChainMap.js +9 -7
  122. package/src/renderers/common/ClippingContext.js +1 -1
  123. package/src/renderers/common/Color4.js +7 -3
  124. package/src/renderers/common/Geometries.js +2 -23
  125. package/src/renderers/common/Info.js +1 -45
  126. package/src/renderers/common/Lighting.js +8 -6
  127. package/src/renderers/common/Pipelines.js +3 -3
  128. package/src/renderers/common/PostProcessing.js +24 -8
  129. package/src/renderers/common/QuadMesh.js +1 -1
  130. package/src/renderers/common/RenderBundles.js +9 -3
  131. package/src/renderers/common/RenderContext.js +37 -3
  132. package/src/renderers/common/RenderContexts.js +30 -17
  133. package/src/renderers/common/RenderList.js +2 -2
  134. package/src/renderers/common/RenderLists.js +9 -3
  135. package/src/renderers/common/RenderObject.js +76 -17
  136. package/src/renderers/common/RenderObjects.js +9 -7
  137. package/src/renderers/common/Renderer.js +86 -67
  138. package/src/renderers/common/SampledTexture.js +0 -1
  139. package/src/renderers/common/StorageBufferAttribute.js +1 -1
  140. package/src/renderers/common/StorageInstancedBufferAttribute.js +1 -1
  141. package/src/renderers/common/StorageTexture.js +1 -1
  142. package/src/renderers/common/Textures.js +14 -7
  143. package/src/renderers/common/TimestampQueryPool.js +39 -0
  144. package/src/renderers/common/Uniform.js +37 -1
  145. package/src/renderers/common/UniformsGroup.js +2 -0
  146. package/src/renderers/common/XRManager.js +1193 -0
  147. package/src/renderers/common/XRRenderTarget.js +74 -0
  148. package/src/renderers/common/extras/PMREMGenerator.js +53 -8
  149. package/src/renderers/common/nodes/NodeBuilderState.js +4 -4
  150. package/src/renderers/common/nodes/NodeLibrary.js +5 -5
  151. package/src/renderers/common/nodes/NodeSampledTexture.js +0 -1
  152. package/src/renderers/common/nodes/NodeUniform.js +54 -2
  153. package/src/renderers/common/nodes/Nodes.js +25 -18
  154. package/src/renderers/webgl/WebGLBackground.js +4 -0
  155. package/src/renderers/webgl-fallback/WebGLBackend.js +295 -110
  156. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +347 -17
  157. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +57 -0
  158. package/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +28 -0
  159. package/src/renderers/webgl-fallback/utils/WebGLExtensions.js +45 -0
  160. package/src/renderers/webgl-fallback/utils/WebGLState.js +323 -11
  161. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +167 -21
  162. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +359 -0
  163. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +43 -0
  164. package/src/renderers/webgpu/WebGPUBackend.js +132 -149
  165. package/src/renderers/webgpu/WebGPURenderer.Nodes.js +6 -4
  166. package/src/renderers/webgpu/WebGPURenderer.js +5 -4
  167. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +615 -41
  168. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +85 -6
  169. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +85 -0
  170. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +102 -3
  171. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +98 -1
  172. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +257 -9
  173. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +274 -0
  174. package/src/renderers/webgpu/utils/WebGPUUtils.js +86 -4
  175. package/src/renderers/webxr/WebXRManager.js +13 -2
  176. package/src/textures/VideoFrameTexture.js +35 -0
  177. package/examples/jsm/geometries/InstancedPointsGeometry.js +0 -176
  178. package/examples/jsm/objects/InstancedPoints.js +0 -19
  179. package/src/materials/nodes/InstancedPointsNodeMaterial.js +0 -209
  180. package/src/nodes/accessors/InstancedPointsMaterialNode.js +0 -37
@@ -13,6 +13,7 @@ import { WebGLBufferRenderer } from './WebGLBufferRenderer.js';
13
13
 
14
14
  import { warnOnce } from '../../utils.js';
15
15
  import { WebGLCoordinateSystem } from '../../constants.js';
16
+ import WebGLTimestampQueryPool from './utils/WebGLTimestampQueryPool.js';
16
17
 
17
18
  /**
18
19
  * A backend implementation targeting WebGL 2.
@@ -32,7 +33,7 @@ class WebGLBackend extends Backend {
32
33
  * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
33
34
  * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
34
35
  * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default.
35
- * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses it WebGL 2 backend no matter if WebGPU is supported or not.
36
+ * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not.
36
37
  * @param {WebGL2RenderingContext} [parameters.context=undefined] - A WebGL 2 rendering context.
37
38
  */
38
39
  constructor( parameters = {} ) {
@@ -185,6 +186,16 @@ class WebGLBackend extends Backend {
185
186
  */
186
187
  this._knownBindings = new WeakSet();
187
188
 
189
+ /**
190
+ * The target framebuffer when rendering with
191
+ * the WebXR device API.
192
+ *
193
+ * @private
194
+ * @type {WebGLFramebuffer}
195
+ * @default null
196
+ */
197
+ this._xrFamebuffer = null;
198
+
188
199
  }
189
200
 
190
201
  /**
@@ -200,7 +211,14 @@ class WebGLBackend extends Backend {
200
211
 
201
212
  const parameters = this.parameters;
202
213
 
203
- const glContext = ( parameters.context !== undefined ) ? parameters.context : renderer.domElement.getContext( 'webgl2' );
214
+ const contextAttributes = {
215
+ antialias: false, // MSAA is applied via a custom renderbuffer
216
+ alpha: true, // always true for performance reasons
217
+ depth: false, // depth and stencil are set to false since the engine always renders into a framebuffer target first
218
+ stencil: false
219
+ };
220
+
221
+ const glContext = ( parameters.context !== undefined ) ? parameters.context : renderer.domElement.getContext( 'webgl2', contextAttributes );
204
222
 
205
223
  function onContextLost( event ) {
206
224
 
@@ -258,8 +276,8 @@ class WebGLBackend extends Backend {
258
276
  }
259
277
 
260
278
  /**
261
- * Transfers buffer data from a storage buffer attribute
262
- * from the GPU to the CPU in context of compute shaders.
279
+ * This method performs a readback operation by moving buffer data from
280
+ * a storage buffer attribute from the GPU to the CPU.
263
281
  *
264
282
  * @async
265
283
  * @param {StorageBufferAttribute} attribute - The storage buffer attribute.
@@ -285,68 +303,61 @@ class WebGLBackend extends Backend {
285
303
  }
286
304
 
287
305
  /**
288
- * Inits a time stamp query for the given render context.
306
+ * Ensures the backend is XR compatible.
289
307
  *
290
- * @param {RenderContext} renderContext - The render context.
308
+ * @async
309
+ * @return {Promise} A Promise that resolve when the renderer is XR compatible.
291
310
  */
292
- initTimestampQuery( renderContext ) {
293
-
294
- if ( ! this.disjoint || ! this.trackTimestamp ) return;
311
+ async makeXRCompatible() {
295
312
 
296
- const renderContextData = this.get( renderContext );
313
+ const attributes = this.gl.getContextAttributes();
297
314
 
298
- if ( this.queryRunning ) {
315
+ if ( attributes.xrCompatible !== true ) {
299
316
 
300
- if ( ! renderContextData.queryQueue ) renderContextData.queryQueue = [];
301
- renderContextData.queryQueue.push( renderContext );
302
- return;
317
+ await this.gl.makeXRCompatible();
303
318
 
304
319
  }
305
320
 
306
- if ( renderContextData.activeQuery ) {
307
-
308
- this.gl.endQuery( this.disjoint.TIME_ELAPSED_EXT );
309
- renderContextData.activeQuery = null;
310
-
311
- }
312
-
313
- renderContextData.activeQuery = this.gl.createQuery();
314
-
315
- if ( renderContextData.activeQuery !== null ) {
316
-
317
- this.gl.beginQuery( this.disjoint.TIME_ELAPSED_EXT, renderContextData.activeQuery );
318
- this.queryRunning = true;
321
+ }
322
+ /**
323
+ * Sets the XR rendering destination.
324
+ *
325
+ * @param {WebGLFramebuffer} xrFamebuffer - The XR framebuffer.
326
+ */
327
+ setXRTarget( xrFamebuffer ) {
319
328
 
320
- }
329
+ this._xrFamebuffer = xrFamebuffer;
321
330
 
322
331
  }
323
332
 
324
- // timestamp utils
325
-
326
333
  /**
327
- * Prepares the timestamp buffer.
334
+ * Configures the given XR render target with external textures.
328
335
  *
329
- * @param {RenderContext} renderContext - The render context.
336
+ * This method is only relevant when using the WebXR Layers API.
337
+ *
338
+ * @param {XRRenderTarget} renderTarget - The XR render target.
339
+ * @param {WebGLTexture} colorTexture - A native color texture.
340
+ * @param {WebGLTexture?} [depthTexture=null] - A native depth texture.
330
341
  */
331
- prepareTimestampBuffer( renderContext ) {
342
+ setXRRenderTargetTextures( renderTarget, colorTexture, depthTexture = null ) {
332
343
 
333
- if ( ! this.disjoint || ! this.trackTimestamp ) return;
344
+ const gl = this.gl;
334
345
 
335
- const renderContextData = this.get( renderContext );
346
+ this.set( renderTarget.texture, { textureGPU: colorTexture, glInternalFormat: gl.RGBA8 } ); // see #24698 why RGBA8 and not SRGB8_ALPHA8 is used
347
+
348
+ if ( depthTexture !== null ) {
336
349
 
337
- if ( renderContextData.activeQuery ) {
350
+ const glInternalFormat = renderTarget.stencilBuffer ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
338
351
 
339
- this.gl.endQuery( this.disjoint.TIME_ELAPSED_EXT );
352
+ this.set( renderTarget.depthTexture, { textureGPU: depthTexture, glInternalFormat: glInternalFormat } );
340
353
 
341
- if ( ! renderContextData.gpuQueries ) renderContextData.gpuQueries = [];
342
- renderContextData.gpuQueries.push( { query: renderContextData.activeQuery } );
343
- renderContextData.activeQuery = null;
344
- this.queryRunning = false;
354
+ renderTarget.autoAllocateDepthBuffer = false;
345
355
 
346
- if ( renderContextData.queryQueue && renderContextData.queryQueue.length > 0 ) {
356
+ // The multisample_render_to_texture extension doesn't work properly if there
357
+ // are midframe flushes and an external depth texture.
358
+ if ( this.extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) {
347
359
 
348
- const nextRenderContext = renderContextData.queryQueue.shift();
349
- this.initTimestampQuery( nextRenderContext );
360
+ console.warn( 'THREE.WebGLBackend: Render-to-texture extension was disabled because an external texture was provided' );
350
361
 
351
362
  }
352
363
 
@@ -355,42 +366,54 @@ class WebGLBackend extends Backend {
355
366
  }
356
367
 
357
368
  /**
358
- * Resolves the time stamp for the given render context and type.
369
+ * Inits a time stamp query for the given render context.
359
370
  *
360
- * @async
361
371
  * @param {RenderContext} renderContext - The render context.
362
- * @param {String} type - The render context.
363
- * @return {Promise} A Promise that resolves when the time stamp has been computed.
364
372
  */
365
- async resolveTimestampAsync( renderContext, type = 'render' ) {
373
+ initTimestampQuery( renderContext ) {
366
374
 
367
375
  if ( ! this.disjoint || ! this.trackTimestamp ) return;
368
376
 
369
- const renderContextData = this.get( renderContext );
377
+ const type = renderContext.isComputeNode ? 'compute' : 'render';
370
378
 
371
- if ( ! renderContextData.gpuQueries ) renderContextData.gpuQueries = [];
379
+ if ( ! this.timestampQueryPool[ type ] ) {
372
380
 
373
- for ( let i = 0; i < renderContextData.gpuQueries.length; i ++ ) {
381
+ // TODO: Variable maxQueries?
382
+ this.timestampQueryPool[ type ] = new WebGLTimestampQueryPool( this.gl, type, 2048 );
374
383
 
375
- const queryInfo = renderContextData.gpuQueries[ i ];
376
- const available = this.gl.getQueryParameter( queryInfo.query, this.gl.QUERY_RESULT_AVAILABLE );
377
- const disjoint = this.gl.getParameter( this.disjoint.GPU_DISJOINT_EXT );
384
+ }
378
385
 
379
- if ( available && ! disjoint ) {
386
+ const timestampQueryPool = this.timestampQueryPool[ type ];
380
387
 
381
- const elapsed = this.gl.getQueryParameter( queryInfo.query, this.gl.QUERY_RESULT );
382
- const duration = Number( elapsed ) / 1000000; // Convert nanoseconds to milliseconds
383
- this.gl.deleteQuery( queryInfo.query );
384
- renderContextData.gpuQueries.splice( i, 1 ); // Remove the processed query
385
- i --;
386
- this.renderer.info.updateTimestamp( type, duration );
388
+ const baseOffset = timestampQueryPool.allocateQueriesForContext( renderContext );
387
389
 
388
- }
390
+ if ( baseOffset !== null ) {
391
+
392
+ timestampQueryPool.beginQuery( renderContext );
389
393
 
390
394
  }
391
395
 
392
396
  }
393
397
 
398
+ // timestamp utils
399
+
400
+ /**
401
+ * Prepares the timestamp buffer.
402
+ *
403
+ * @param {RenderContext} renderContext - The render context.
404
+ */
405
+ prepareTimestampBuffer( renderContext ) {
406
+
407
+ if ( ! this.disjoint || ! this.trackTimestamp ) return;
408
+
409
+ const type = renderContext.isComputeNode ? 'compute' : 'render';
410
+ const timestampQueryPool = this.timestampQueryPool[ type ];
411
+
412
+ timestampQueryPool.endQuery( renderContext );
413
+
414
+ }
415
+
416
+
394
417
  /**
395
418
  * Returns the backend's rendering context.
396
419
  *
@@ -410,7 +433,7 @@ class WebGLBackend extends Backend {
410
433
  */
411
434
  beginRender( renderContext ) {
412
435
 
413
- const { gl } = this;
436
+ const { state, gl } = this;
414
437
  const renderContextData = this.get( renderContext );
415
438
 
416
439
  //
@@ -433,7 +456,7 @@ class WebGLBackend extends Backend {
433
456
 
434
457
  } else {
435
458
 
436
- gl.viewport( 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight );
459
+ state.viewport( 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight );
437
460
 
438
461
  }
439
462
 
@@ -441,7 +464,7 @@ class WebGLBackend extends Backend {
441
464
 
442
465
  const { x, y, width, height } = renderContext.scissorValue;
443
466
 
444
- gl.scissor( x, renderContext.height - height - y, width, height );
467
+ state.scissor( x, renderContext.height - height - y, width, height );
445
468
 
446
469
  }
447
470
 
@@ -515,7 +538,7 @@ class WebGLBackend extends Backend {
515
538
 
516
539
  const { samples } = renderContext.renderTarget;
517
540
 
518
- if ( samples > 0 ) {
541
+ if ( samples > 0 && this._useMultisampledRTT( renderContext.renderTarget ) === false ) {
519
542
 
520
543
  const fb = renderTargetContextData.framebuffers[ renderContext.getCacheKey() ];
521
544
 
@@ -565,7 +588,7 @@ class WebGLBackend extends Backend {
565
588
 
566
589
  } else {
567
590
 
568
- gl.viewport( 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight );
591
+ state.viewport( 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight );
569
592
 
570
593
  }
571
594
 
@@ -611,7 +634,7 @@ class WebGLBackend extends Backend {
611
634
 
612
635
  if ( gl.getQueryParameter( query, gl.QUERY_RESULT_AVAILABLE ) ) {
613
636
 
614
- if ( gl.getQueryParameter( query, gl.QUERY_RESULT ) > 0 ) occluded.add( currentOcclusionQueryObjects[ i ] );
637
+ if ( gl.getQueryParameter( query, gl.QUERY_RESULT ) === 0 ) occluded.add( currentOcclusionQueryObjects[ i ] );
615
638
 
616
639
  currentOcclusionQueries[ i ] = null;
617
640
  gl.deleteQuery( query );
@@ -663,10 +686,10 @@ class WebGLBackend extends Backend {
663
686
  */
664
687
  updateViewport( renderContext ) {
665
688
 
666
- const gl = this.gl;
689
+ const { state } = this;
667
690
  const { x, y, width, height } = renderContext.viewportValue;
668
691
 
669
- gl.viewport( x, renderContext.height - height - y, width, height );
692
+ state.viewport( x, renderContext.height - height - y, width, height );
670
693
 
671
694
  }
672
695
 
@@ -677,17 +700,9 @@ class WebGLBackend extends Backend {
677
700
  */
678
701
  setScissorTest( boolean ) {
679
702
 
680
- const gl = this.gl;
681
-
682
- if ( boolean ) {
703
+ const state = this.state;
683
704
 
684
- gl.enable( gl.SCISSOR_TEST );
685
-
686
- } else {
687
-
688
- gl.disable( gl.SCISSOR_TEST );
689
-
690
- }
705
+ state.setScissorTest( boolean );
691
706
 
692
707
  }
693
708
 
@@ -1043,31 +1058,101 @@ class WebGLBackend extends Backend {
1043
1058
 
1044
1059
  }
1045
1060
 
1046
- if ( object.isBatchedMesh ) {
1061
+ const draw = () => {
1062
+
1063
+ if ( object.isBatchedMesh ) {
1047
1064
 
1048
- if ( object._multiDrawInstances !== null ) {
1065
+ if ( object._multiDrawInstances !== null ) {
1049
1066
 
1050
- renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances );
1067
+ renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances );
1051
1068
 
1052
- } else if ( ! this.hasFeature( 'WEBGL_multi_draw' ) ) {
1069
+ } else if ( ! this.hasFeature( 'WEBGL_multi_draw' ) ) {
1053
1070
 
1054
- warnOnce( 'THREE.WebGLRenderer: WEBGL_multi_draw not supported.' );
1071
+ warnOnce( 'THREE.WebGLRenderer: WEBGL_multi_draw not supported.' );
1072
+
1073
+ } else {
1074
+
1075
+ renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount );
1076
+
1077
+ }
1078
+
1079
+ } else if ( instanceCount > 1 ) {
1080
+
1081
+ renderer.renderInstances( firstVertex, vertexCount, instanceCount );
1055
1082
 
1056
1083
  } else {
1057
1084
 
1058
- renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount );
1085
+ renderer.render( firstVertex, vertexCount );
1059
1086
 
1060
1087
  }
1061
1088
 
1062
- } else if ( instanceCount > 1 ) {
1089
+ };
1090
+
1091
+ if ( renderObject.camera.isArrayCamera && renderObject.camera.cameras.length > 0 ) {
1092
+
1093
+ const cameraData = this.get( renderObject.camera );
1094
+ const cameras = renderObject.camera.cameras;
1095
+ const cameraIndex = renderObject.getBindingGroup( 'cameraIndex' ).bindings[ 0 ];
1096
+
1097
+ if ( cameraData.indexesGPU === undefined || cameraData.indexesGPU.length !== cameras.length ) {
1098
+
1099
+ const data = new Uint32Array( [ 0, 0, 0, 0 ] );
1100
+ const indexesGPU = [];
1101
+
1102
+ for ( let i = 0, len = cameras.length; i < len; i ++ ) {
1103
+
1104
+ const bufferGPU = gl.createBuffer();
1105
+
1106
+ data[ 0 ] = i;
1063
1107
 
1064
- renderer.renderInstances( firstVertex, vertexCount, instanceCount );
1108
+ gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU );
1109
+ gl.bufferData( gl.UNIFORM_BUFFER, data, gl.STATIC_DRAW );
1110
+
1111
+ indexesGPU.push( bufferGPU );
1112
+
1113
+ }
1114
+
1115
+ cameraData.indexesGPU = indexesGPU; // TODO: Create a global library for this
1116
+
1117
+ }
1118
+
1119
+ const cameraIndexData = this.get( cameraIndex );
1120
+ const pixelRatio = this.renderer.getPixelRatio();
1121
+
1122
+ for ( let i = 0, len = cameras.length; i < len; i ++ ) {
1123
+
1124
+ const subCamera = cameras[ i ];
1125
+
1126
+ if ( object.layers.test( subCamera.layers ) ) {
1127
+
1128
+ const vp = subCamera.viewport;
1129
+
1130
+ const x = vp.x * pixelRatio;
1131
+ const y = vp.y * pixelRatio;
1132
+ const width = vp.width * pixelRatio;
1133
+ const height = vp.height * pixelRatio;
1134
+
1135
+ state.viewport(
1136
+ Math.floor( x ),
1137
+ Math.floor( renderObject.context.height - height - y ),
1138
+ Math.floor( width ),
1139
+ Math.floor( height )
1140
+ );
1141
+
1142
+ state.bindBufferBase( gl.UNIFORM_BUFFER, cameraIndexData.index, cameraData.indexesGPU[ i ] );
1143
+
1144
+ draw();
1145
+
1146
+ }
1147
+
1148
+ }
1065
1149
 
1066
1150
  } else {
1067
1151
 
1068
- renderer.render( firstVertex, vertexCount );
1152
+ draw();
1069
1153
 
1070
1154
  }
1155
+
1071
1156
  //
1072
1157
 
1073
1158
  gl.bindVertexArray( null );
@@ -1137,7 +1222,7 @@ class WebGLBackend extends Backend {
1137
1222
  }
1138
1223
 
1139
1224
  /**
1140
- * Generates mipmaps for the given texture
1225
+ * Generates mipmaps for the given texture.
1141
1226
  *
1142
1227
  * @param {Texture} texture - The texture.
1143
1228
  */
@@ -1161,15 +1246,16 @@ class WebGLBackend extends Backend {
1161
1246
  /**
1162
1247
  * Returns texture data as a typed array.
1163
1248
  *
1249
+ * @async
1164
1250
  * @param {Texture} texture - The texture to copy.
1165
1251
  * @param {Number} x - The x coordinate of the copy origin.
1166
1252
  * @param {Number} y - The y coordinate of the copy origin.
1167
1253
  * @param {Number} width - The width of the copy.
1168
1254
  * @param {Number} height - The height of the copy.
1169
1255
  * @param {Number} faceIndex - The face index.
1170
- * @return {TypedArray} The texture data as a typed array.
1256
+ * @return {Promise<TypedArray>} A Promise that resolves with a typed array when the copy operation has finished.
1171
1257
  */
1172
- copyTextureToBuffer( texture, x, y, width, height, faceIndex ) {
1258
+ async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) {
1173
1259
 
1174
1260
  return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex );
1175
1261
 
@@ -1660,7 +1746,7 @@ class WebGLBackend extends Backend {
1660
1746
  // attributes
1661
1747
 
1662
1748
  /**
1663
- * Creates the buffer of an indexed shader attribute.
1749
+ * Creates the GPU buffer of an indexed shader attribute.
1664
1750
  *
1665
1751
  * @param {BufferAttribute} attribute - The indexed buffer attribute.
1666
1752
  */
@@ -1673,7 +1759,7 @@ class WebGLBackend extends Backend {
1673
1759
  }
1674
1760
 
1675
1761
  /**
1676
- * Creates the buffer of a shader attribute.
1762
+ * Creates the GPU buffer of a shader attribute.
1677
1763
  *
1678
1764
  * @param {BufferAttribute} attribute - The buffer attribute.
1679
1765
  */
@@ -1688,7 +1774,7 @@ class WebGLBackend extends Backend {
1688
1774
  }
1689
1775
 
1690
1776
  /**
1691
- * Creates the buffer of a storage attribute.
1777
+ * Creates the GPU buffer of a storage attribute.
1692
1778
  *
1693
1779
  * @param {BufferAttribute} attribute - The buffer attribute.
1694
1780
  */
@@ -1703,7 +1789,7 @@ class WebGLBackend extends Backend {
1703
1789
  }
1704
1790
 
1705
1791
  /**
1706
- * Updates the buffer of a shader attribute.
1792
+ * Updates the GPU buffer of a shader attribute.
1707
1793
  *
1708
1794
  * @param {BufferAttribute} attribute - The buffer attribute to update.
1709
1795
  */
@@ -1714,7 +1800,7 @@ class WebGLBackend extends Backend {
1714
1800
  }
1715
1801
 
1716
1802
  /**
1717
- * Destroys the buffer of a shader attribute.
1803
+ * Destroys the GPU buffer of a shader attribute.
1718
1804
  *
1719
1805
  * @param {BufferAttribute} attribute - The buffer attribute to destroy.
1720
1806
  */
@@ -1806,9 +1892,13 @@ class WebGLBackend extends Backend {
1806
1892
  const isCube = renderTarget.isWebGLCubeRenderTarget === true;
1807
1893
  const isRenderTarget3D = renderTarget.isRenderTarget3D === true;
1808
1894
  const isRenderTargetArray = renderTarget.isRenderTargetArray === true;
1895
+ const isXRRenderTarget = renderTarget.isXRRenderTarget === true;
1896
+ const hasExternalTextures = ( isXRRenderTarget === true && renderTarget.hasExternalTextures === true );
1809
1897
 
1810
1898
  let msaaFb = renderTargetContextData.msaaFrameBuffer;
1811
1899
  let depthRenderbuffer = renderTargetContextData.depthRenderbuffer;
1900
+ const multisampledRTTExt = this.extensions.get( 'WEBGL_multisampled_render_to_texture' );
1901
+ const useMultisampledRTT = this._useMultisampledRTT( renderTarget );
1812
1902
 
1813
1903
  const cacheKey = getCacheKey( descriptor );
1814
1904
 
@@ -1820,6 +1910,10 @@ class WebGLBackend extends Backend {
1820
1910
 
1821
1911
  fb = renderTargetContextData.cubeFramebuffers[ cacheKey ];
1822
1912
 
1913
+ } else if ( isXRRenderTarget && hasExternalTextures === false ) {
1914
+
1915
+ fb = this._xrFamebuffer;
1916
+
1823
1917
  } else {
1824
1918
 
1825
1919
  renderTargetContextData.framebuffers || ( renderTargetContextData.framebuffers = {} );
@@ -1867,11 +1961,17 @@ class WebGLBackend extends Backend {
1867
1961
 
1868
1962
  } else {
1869
1963
 
1870
- gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 );
1964
+ if ( useMultisampledRTT ) {
1871
1965
 
1872
- }
1966
+ multisampledRTTExt.framebufferTexture2DMultisampleEXT( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0, samples );
1967
+
1968
+ } else {
1873
1969
 
1970
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 );
1874
1971
 
1972
+ }
1973
+
1974
+ }
1875
1975
 
1876
1976
  }
1877
1977
 
@@ -1879,20 +1979,88 @@ class WebGLBackend extends Backend {
1879
1979
 
1880
1980
  }
1881
1981
 
1882
- if ( descriptor.depthTexture !== null ) {
1982
+ if ( renderTarget.isXRRenderTarget && renderTarget.autoAllocateDepthBuffer === true ) {
1983
+
1984
+ const renderbuffer = gl.createRenderbuffer();
1985
+ this.textureUtils.setupRenderBufferStorage( renderbuffer, descriptor, 0, useMultisampledRTT );
1986
+ renderTargetContextData.xrDepthRenderbuffer = renderbuffer;
1987
+
1988
+ } else {
1989
+
1990
+ if ( descriptor.depthTexture !== null ) {
1991
+
1992
+ const textureData = this.get( descriptor.depthTexture );
1993
+ const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
1994
+ textureData.renderTarget = descriptor.renderTarget;
1995
+ textureData.cacheKey = cacheKey; // required for copyTextureToTexture()
1996
+
1997
+ if ( useMultisampledRTT ) {
1998
+
1999
+ multisampledRTTExt.framebufferTexture2DMultisampleEXT( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0, samples );
2000
+
2001
+ } else {
2002
+
2003
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0 );
2004
+
2005
+ }
2006
+
2007
+ }
2008
+
2009
+ }
2010
+
2011
+ } else {
2012
+
2013
+ // rebind external XR textures
2014
+
2015
+ if ( isXRRenderTarget && hasExternalTextures ) {
2016
+
2017
+ state.bindFramebuffer( gl.FRAMEBUFFER, fb );
2018
+
2019
+ // rebind color
2020
+
2021
+ const textureData = this.get( descriptor.textures[ 0 ] );
2022
+
2023
+ if ( useMultisampledRTT ) {
2024
+
2025
+ multisampledRTTExt.framebufferTexture2DMultisampleEXT( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureData.textureGPU, 0, samples );
2026
+
2027
+ } else {
2028
+
2029
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureData.textureGPU, 0 );
2030
+
2031
+ }
2032
+
2033
+ // rebind depth
1883
2034
 
1884
- const textureData = this.get( descriptor.depthTexture );
1885
2035
  const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
1886
- textureData.renderTarget = descriptor.renderTarget;
1887
- textureData.cacheKey = cacheKey; // required for copyTextureToTexture()
1888
2036
 
1889
- gl.framebufferTexture2D( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0 );
2037
+ if ( renderTarget.autoAllocateDepthBuffer === true ) {
2038
+
2039
+ const renderbuffer = renderTargetContextData.xrDepthRenderbuffer;
2040
+ gl.bindRenderbuffer( gl.RENDERBUFFER, renderbuffer );
2041
+ gl.framebufferRenderbuffer( gl.FRAMEBUFFER, depthStyle, gl.RENDERBUFFER, renderbuffer );
2042
+
2043
+ } else {
2044
+
2045
+ const textureData = this.get( descriptor.depthTexture );
2046
+
2047
+ if ( useMultisampledRTT ) {
2048
+
2049
+ multisampledRTTExt.framebufferTexture2DMultisampleEXT( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0, samples );
2050
+
2051
+ } else {
2052
+
2053
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0 );
2054
+
2055
+ }
2056
+
2057
+ }
1890
2058
 
1891
2059
  }
1892
2060
 
1893
2061
  }
1894
2062
 
1895
- if ( samples > 0 ) {
2063
+ if ( samples > 0 && useMultisampledRTT === false ) {
1896
2064
 
1897
2065
  if ( msaaFb === undefined ) {
1898
2066
 
@@ -1936,7 +2104,7 @@ class WebGLBackend extends Backend {
1936
2104
  if ( depthRenderbuffer === undefined ) {
1937
2105
 
1938
2106
  depthRenderbuffer = gl.createRenderbuffer();
1939
- this.textureUtils.setupRenderBufferStorage( depthRenderbuffer, descriptor );
2107
+ this.textureUtils.setupRenderBufferStorage( depthRenderbuffer, descriptor, samples );
1940
2108
 
1941
2109
  renderTargetContextData.depthRenderbuffer = depthRenderbuffer;
1942
2110
 
@@ -2081,11 +2249,11 @@ class WebGLBackend extends Backend {
2081
2249
  }
2082
2250
 
2083
2251
  /**
2084
- * Creates a tranform feedback from the given transform buffers.
2252
+ * Creates a transform feedback from the given transform buffers.
2085
2253
  *
2086
2254
  * @private
2087
- * @param {Array<DualAttributeData>} transformBuffers - The tranform buffers.
2088
- * @return {WebGLTransformFeedback} The tranform feedback.
2255
+ * @param {Array<DualAttributeData>} transformBuffers - The transform buffers.
2256
+ * @return {WebGLTransformFeedback} The transform feedback.
2089
2257
  */
2090
2258
  _getTransformFeedback( transformBuffers ) {
2091
2259
 
@@ -2197,11 +2365,28 @@ class WebGLBackend extends Backend {
2197
2365
 
2198
2366
  }
2199
2367
 
2368
+ /**
2369
+ * Returns `true` if the `WEBGL_multisampled_render_to_texture` extension
2370
+ * should be used when MSAA is enabled.
2371
+ *
2372
+ * @private
2373
+ * @param {RenderTarget} renderTarget - The render target that should be multisampled.
2374
+ * @return {Boolean} Whether to use the `WEBGL_multisampled_render_to_texture` extension for MSAA or not.
2375
+ */
2376
+ _useMultisampledRTT( renderTarget ) {
2377
+
2378
+ return renderTarget.samples > 0 && this.extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTarget.autoAllocateDepthBuffer !== false;
2379
+
2380
+ }
2381
+
2200
2382
  /**
2201
2383
  * Frees internal resources.
2202
2384
  */
2203
2385
  dispose() {
2204
2386
 
2387
+ const extension = this.extensions.get( 'WEBGL_lose_context' );
2388
+ if ( extension ) extension.loseContext();
2389
+
2205
2390
  this.renderer.domElement.removeEventListener( 'webglcontextlost', this._onContextLost );
2206
2391
 
2207
2392
  }