super-three 0.160.1 → 0.161.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/LICENSE +1 -1
  2. package/build/three.cjs +379 -108
  3. package/build/three.module.js +380 -108
  4. package/build/three.module.min.js +1 -1
  5. package/examples/jsm/Addons.js +5 -1
  6. package/examples/jsm/capabilities/WebGPU.js +13 -9
  7. package/examples/jsm/controls/OrbitControls.js +102 -13
  8. package/examples/jsm/curves/NURBSUtils.js +59 -4
  9. package/examples/jsm/curves/NURBSVolume.js +62 -0
  10. package/examples/jsm/exporters/USDZExporter.js +8 -7
  11. package/examples/jsm/helpers/TextureHelper.js +3 -3
  12. package/examples/jsm/loaders/3DMLoader.js +44 -43
  13. package/examples/jsm/loaders/DDSLoader.js +1 -0
  14. package/examples/jsm/loaders/KTX2Loader.js +20 -5
  15. package/examples/jsm/loaders/LUT3dlLoader.js +78 -46
  16. package/examples/jsm/loaders/LUTCubeLoader.js +81 -67
  17. package/examples/jsm/loaders/LUTImageLoader.js +3 -2
  18. package/examples/jsm/loaders/MaterialXLoader.js +115 -16
  19. package/examples/jsm/loaders/SVGLoader.js +4 -3
  20. package/examples/jsm/loaders/VRMLLoader.js +1 -1
  21. package/examples/jsm/materials/MeshPostProcessingMaterial.js +144 -0
  22. package/examples/jsm/misc/Timer.js +13 -4
  23. package/examples/jsm/nodes/Nodes.js +16 -5
  24. package/examples/jsm/nodes/accessors/BufferAttributeNode.js +5 -3
  25. package/examples/jsm/nodes/accessors/CameraNode.js +9 -4
  26. package/examples/jsm/nodes/accessors/CubeTextureNode.js +12 -1
  27. package/examples/jsm/nodes/accessors/StorageBufferNode.js +27 -0
  28. package/examples/jsm/nodes/accessors/TextureStoreNode.js +56 -3
  29. package/examples/jsm/nodes/accessors/VertexColorNode.js +70 -0
  30. package/examples/jsm/nodes/core/AttributeNode.js +1 -1
  31. package/examples/jsm/nodes/core/NodeBuilder.js +23 -18
  32. package/examples/jsm/nodes/core/NodeFrame.js +16 -8
  33. package/examples/jsm/nodes/core/constants.js +1 -0
  34. package/examples/jsm/nodes/display/AfterImageNode.js +148 -0
  35. package/examples/jsm/nodes/display/AnamorphicNode.js +148 -0
  36. package/examples/jsm/nodes/display/ColorAdjustmentNode.js +3 -0
  37. package/examples/jsm/nodes/display/GaussianBlurNode.js +33 -13
  38. package/examples/jsm/nodes/display/PassNode.js +3 -2
  39. package/examples/jsm/nodes/display/ToneMappingNode.js +46 -3
  40. package/examples/jsm/nodes/display/ViewportDepthTextureNode.js +1 -4
  41. package/examples/jsm/nodes/display/ViewportNode.js +0 -2
  42. package/examples/jsm/nodes/display/ViewportSharedTextureNode.js +4 -4
  43. package/examples/jsm/nodes/fog/FogNode.js +2 -1
  44. package/examples/jsm/nodes/lighting/AmbientLightNode.js +1 -1
  45. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +13 -5
  46. package/examples/jsm/nodes/lighting/LightingContextNode.js +1 -1
  47. package/examples/jsm/nodes/lighting/LightsNode.js +1 -1
  48. package/examples/jsm/nodes/materials/Line2NodeMaterial.js +18 -30
  49. package/examples/jsm/nodes/materials/Materials.js +1 -0
  50. package/examples/jsm/nodes/materials/MeshSSSNodeMaterial.js +84 -0
  51. package/examples/jsm/nodes/materials/NodeMaterial.js +6 -4
  52. package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +1 -7
  53. package/examples/jsm/nodes/math/MathNode.js +12 -2
  54. package/examples/jsm/nodes/math/MathUtils.js +15 -0
  55. package/examples/jsm/nodes/math/OperatorNode.js +13 -5
  56. package/examples/jsm/nodes/math/TriNoise3D.js +71 -0
  57. package/examples/jsm/nodes/shadernode/ShaderNode.js +10 -1
  58. package/examples/jsm/nodes/utils/ArrayElementNode.js +6 -0
  59. package/examples/jsm/nodes/utils/JoinNode.js +2 -2
  60. package/examples/jsm/nodes/utils/LoopNode.js +3 -3
  61. package/examples/jsm/nodes/utils/ReflectorNode.js +227 -0
  62. package/examples/jsm/nodes/utils/RotateNode.js +68 -0
  63. package/examples/jsm/nodes/utils/RotateUVNode.js +1 -9
  64. package/examples/jsm/nodes/utils/SplitNode.js +4 -4
  65. package/examples/jsm/objects/GroundedSkybox.js +50 -0
  66. package/examples/jsm/objects/QuadMesh.js +8 -2
  67. package/examples/jsm/objects/Water2.js +8 -8
  68. package/examples/jsm/postprocessing/GTAOPass.js +11 -1
  69. package/examples/jsm/renderers/common/Backend.js +14 -0
  70. package/examples/jsm/renderers/common/Bindings.js +1 -1
  71. package/examples/jsm/renderers/common/DataMap.js +1 -1
  72. package/examples/jsm/renderers/common/Info.js +25 -1
  73. package/examples/jsm/renderers/common/Pipelines.js +8 -8
  74. package/examples/jsm/renderers/common/PostProcessing.js +2 -2
  75. package/examples/jsm/renderers/common/ProgrammableStage.js +3 -1
  76. package/examples/jsm/renderers/common/RenderObject.js +2 -0
  77. package/examples/jsm/renderers/common/Renderer.js +238 -22
  78. package/examples/jsm/renderers/common/StorageBufferAttribute.js +17 -0
  79. package/examples/jsm/renderers/common/Textures.js +25 -5
  80. package/examples/jsm/renderers/common/nodes/NodeBuilderState.js +2 -1
  81. package/examples/jsm/renderers/common/nodes/Nodes.js +4 -2
  82. package/examples/jsm/renderers/webgl/WebGLBackend.js +631 -270
  83. package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +37 -30
  84. package/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js +89 -8
  85. package/examples/jsm/renderers/webgl/utils/WebGLConstants.js +11 -0
  86. package/examples/jsm/renderers/webgl/utils/WebGLState.js +197 -0
  87. package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +377 -11
  88. package/examples/jsm/renderers/webgl/utils/WebGLUtils.js +2 -2
  89. package/examples/jsm/renderers/webgl-legacy/nodes/GLSL1NodeBuilder.js +1 -21
  90. package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js +2 -2
  91. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +289 -102
  92. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +7 -2
  93. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +56 -39
  94. package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +9 -1
  95. package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +38 -4
  96. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +85 -12
  97. package/examples/jsm/transpiler/AST.js +1 -1
  98. package/examples/jsm/transpiler/GLSLDecoder.js +1 -1
  99. package/examples/jsm/transpiler/ShaderToyDecoder.js +1 -1
  100. package/examples/jsm/transpiler/TSLEncoder.js +1 -1
  101. package/examples/jsm/utils/BufferGeometryUtils.js +23 -27
  102. package/examples/jsm/utils/SortUtils.js +2 -0
  103. package/examples/jsm/webxr/ARButton.js +12 -2
  104. package/examples/jsm/webxr/VRButton.js +12 -2
  105. package/examples/jsm/webxr/XRButton.js +12 -2
  106. package/examples/jsm/webxr/XRControllerModelFactory.js +6 -1
  107. package/examples/jsm/webxr/XRHandMeshModel.js +3 -1
  108. package/package.json +2 -2
  109. package/src/audio/Audio.js +1 -3
  110. package/src/cameras/PerspectiveCamera.js +35 -0
  111. package/src/constants.js +1 -2
  112. package/src/core/BufferAttribute.js +2 -1
  113. package/src/core/InterleavedBuffer.js +2 -1
  114. package/src/core/InterleavedBufferAttribute.js +20 -0
  115. package/src/materials/ShaderMaterial.js +2 -1
  116. package/src/math/Triangle.js +0 -30
  117. package/src/objects/BatchedMesh.js +6 -7
  118. package/src/objects/SkinnedMesh.js +0 -8
  119. package/src/renderers/WebGLRenderer.js +5 -1
  120. package/src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl.js +9 -0
  121. package/src/renderers/shaders/ShaderChunk/clipping_planes_fragment.glsl.js +56 -11
  122. package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +15 -7
  123. package/src/renderers/shaders/ShaderLib/depth.glsl.js +1 -2
  124. package/src/renderers/shaders/ShaderLib/distanceRGBA.glsl.js +1 -2
  125. package/src/renderers/shaders/ShaderLib/linedashed.glsl.js +1 -1
  126. package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +1 -2
  127. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +1 -1
  128. package/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js +1 -2
  129. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +3 -1
  130. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +1 -1
  131. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +1 -1
  132. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +1 -1
  133. package/src/renderers/shaders/ShaderLib/points.glsl.js +1 -1
  134. package/src/renderers/shaders/ShaderLib/sprite.glsl.js +1 -1
  135. package/src/renderers/webgl/WebGLAttributes.js +2 -2
  136. package/src/renderers/webgl/WebGLCubeMaps.js +1 -1
  137. package/src/renderers/webgl/WebGLProgram.js +30 -3
  138. package/src/renderers/webgl/WebGLPrograms.js +19 -11
  139. package/src/renderers/webgl/WebGLTextures.js +90 -16
  140. package/src/renderers/webxr/WebXRDepthSensing.js +105 -0
  141. package/src/renderers/webxr/WebXRManager.js +46 -0
  142. package/src/textures/Source.js +1 -0
  143. package/build/three.js +0 -54519
  144. package/build/three.min.js +0 -7
  145. package/examples/jsm/objects/GroundProjectedSkybox.js +0 -172
@@ -9,6 +9,7 @@ import WebGLUtils from './utils/WebGLUtils.js';
9
9
  import WebGLTextureUtils from './utils/WebGLTextureUtils.js';
10
10
  import WebGLExtensions from './utils/WebGLExtensions.js';
11
11
  import WebGLCapabilities from './utils/WebGLCapabilities.js';
12
+ import { GLFeatureName } from './utils/WebGLConstants.js';
12
13
 
13
14
  //
14
15
 
@@ -22,9 +23,9 @@ class WebGLBackend extends Backend {
22
23
 
23
24
  }
24
25
 
25
- async init( renderer ) {
26
+ init( renderer ) {
26
27
 
27
- await super.init( renderer );
28
+ super.init( renderer );
28
29
 
29
30
  //
30
31
 
@@ -40,9 +41,13 @@ class WebGLBackend extends Backend {
40
41
  this.textureUtils = new WebGLTextureUtils( this );
41
42
  this.state = new WebGLState( this );
42
43
  this.utils = new WebGLUtils( this );
43
- this.defaultTextures = {};
44
+
45
+ this.vaoCache = {};
46
+ this.transformFeedbackCache = {};
47
+ this.discard = false;
44
48
 
45
49
  this.extensions.get( 'EXT_color_buffer_float' );
50
+ this.parallel = this.extensions.get( 'KHR_parallel_shader_compile' );
46
51
  this._currentContext = null;
47
52
 
48
53
  }
@@ -59,6 +64,12 @@ class WebGLBackend extends Backend {
59
64
 
60
65
  }
61
66
 
67
+ getContext() {
68
+
69
+ return this.gl;
70
+
71
+ }
72
+
62
73
  beginRender( renderContext ) {
63
74
 
64
75
  const { gl } = this;
@@ -66,6 +77,8 @@ class WebGLBackend extends Backend {
66
77
 
67
78
  //
68
79
 
80
+ //
81
+
69
82
  renderContextData.previousContext = this._currentContext;
70
83
  this._currentContext = renderContext;
71
84
 
@@ -74,7 +87,6 @@ class WebGLBackend extends Backend {
74
87
  this.clear( renderContext.clearColor, renderContext.clearDepth, renderContext.clearStencil, renderContext );
75
88
 
76
89
  //
77
-
78
90
  if ( renderContext.viewport ) {
79
91
 
80
92
  this.updateViewport( renderContext );
@@ -85,6 +97,14 @@ class WebGLBackend extends Backend {
85
97
 
86
98
  }
87
99
 
100
+ if ( renderContext.scissor ) {
101
+
102
+ const { x, y, width, height } = renderContext.scissorValue;
103
+
104
+ gl.scissor( x, y, width, height );
105
+
106
+ }
107
+
88
108
  const occlusionQueryCount = renderContext.occlusionQueryCount;
89
109
 
90
110
  if ( occlusionQueryCount > 0 ) {
@@ -105,11 +125,64 @@ class WebGLBackend extends Backend {
105
125
 
106
126
  finishRender( renderContext ) {
107
127
 
128
+ const { gl, state } = this;
108
129
  const renderContextData = this.get( renderContext );
109
130
  const previousContext = renderContextData.previousContext;
110
131
 
132
+ const textures = renderContext.textures;
133
+
134
+ if ( textures !== null ) {
135
+
136
+ for ( let i = 0; i < textures.length; i ++ ) {
137
+
138
+ const texture = textures[ i ];
139
+
140
+ if ( texture.generateMipmaps ) {
141
+
142
+ this.generateMipmaps( texture );
143
+
144
+ }
145
+
146
+ }
147
+
148
+ }
149
+
111
150
  this._currentContext = previousContext;
112
151
 
152
+
153
+ if ( renderContext.textures !== null && renderContext.renderTarget ) {
154
+
155
+ const renderTargetContextData = this.get( renderContext.renderTarget );
156
+
157
+ const { samples } = renderContext.renderTarget;
158
+ const fb = renderTargetContextData.framebuffer;
159
+
160
+ const mask = gl.COLOR_BUFFER_BIT;
161
+
162
+ if ( samples > 0 ) {
163
+
164
+ const msaaFrameBuffer = renderTargetContextData.msaaFrameBuffer;
165
+
166
+ const textures = renderContext.textures;
167
+
168
+ state.bindFramebuffer( gl.READ_FRAMEBUFFER, msaaFrameBuffer );
169
+ state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb );
170
+
171
+ for ( let i = 0; i < textures.length; i ++ ) {
172
+
173
+ // TODO Add support for MRT
174
+
175
+ gl.blitFramebuffer( 0, 0, renderContext.width, renderContext.height, 0, 0, renderContext.width, renderContext.height, mask, gl.NEAREST );
176
+
177
+ gl.invalidateFramebuffer( gl.READ_FRAMEBUFFER, renderTargetContextData.invalidationArray );
178
+
179
+ }
180
+
181
+ }
182
+
183
+
184
+ }
185
+
113
186
  if ( previousContext !== null ) {
114
187
 
115
188
  this._setFramebuffer( previousContext );
@@ -146,6 +219,7 @@ class WebGLBackend extends Backend {
146
219
 
147
220
  }
148
221
 
222
+
149
223
  }
150
224
 
151
225
  resolveOccludedAsync( renderContext ) {
@@ -223,6 +297,22 @@ class WebGLBackend extends Backend {
223
297
 
224
298
  }
225
299
 
300
+ setScissorTest( boolean ) {
301
+
302
+ const gl = this.gl;
303
+
304
+ if ( boolean ) {
305
+
306
+ gl.enable( gl.SCISSOR_TEST );
307
+
308
+ } else {
309
+
310
+ gl.disable( gl.SCISSOR_TEST );
311
+
312
+ }
313
+
314
+ }
315
+
226
316
  clear( color, depth, stencil, descriptor = null ) {
227
317
 
228
318
  const { gl } = this;
@@ -289,26 +379,77 @@ class WebGLBackend extends Backend {
289
379
 
290
380
  beginCompute( /*computeGroup*/ ) {
291
381
 
292
- console.warn( 'Abstract class.' );
382
+ const gl = this.gl;
383
+
384
+ gl.bindFramebuffer( gl.FRAMEBUFFER, null );
293
385
 
294
386
  }
295
387
 
296
- compute( /*computeGroup, computeNode, bindings, pipeline*/ ) {
388
+ compute( computeGroup, computeNode, bindings, pipeline ) {
297
389
 
298
- console.warn( 'Abstract class.' );
390
+ const gl = this.gl;
391
+
392
+ if ( ! this.discard ) {
393
+
394
+ // required here to handle async behaviour of render.compute()
395
+ gl.enable( gl.RASTERIZER_DISCARD );
396
+ this.discard = true;
397
+
398
+ }
399
+
400
+ const { programGPU, transformBuffers, attributes } = this.get( pipeline );
401
+
402
+ const vaoKey = this._getVaoKey( null, attributes );
403
+
404
+ const vaoGPU = this.vaoCache[ vaoKey ];
405
+
406
+ if ( vaoGPU === undefined ) {
407
+
408
+ this._createVao( null, attributes );
409
+
410
+ } else {
411
+
412
+ gl.bindVertexArray( vaoGPU );
413
+
414
+ }
415
+
416
+ gl.useProgram( programGPU );
417
+
418
+ this._bindUniforms( bindings );
419
+
420
+ const transformFeedbackGPU = this._getTransformFeedback( transformBuffers );
421
+
422
+ gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, transformFeedbackGPU );
423
+ gl.beginTransformFeedback( gl.POINTS );
424
+
425
+ gl.drawArraysInstanced( gl.POINTS, 0, 1, computeNode.count );
426
+
427
+ gl.endTransformFeedback();
428
+ gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, null );
429
+
430
+ // switch active buffers
431
+ for ( let i = 0; i < transformBuffers.length; i ++ ) {
432
+
433
+ transformBuffers[ i ].switchBuffers();
434
+
435
+ }
299
436
 
300
437
  }
301
438
 
302
439
  finishCompute( /*computeGroup*/ ) {
303
440
 
304
- console.warn( 'Abstract class.' );
441
+ const gl = this.gl;
442
+
443
+ this.discard = false;
444
+
445
+ gl.disable( gl.RASTERIZER_DISCARD );
305
446
 
306
447
  }
307
448
 
308
449
  draw( renderObject, info ) {
309
450
 
310
451
  const { pipeline, material, context } = renderObject;
311
- const { programGPU, vaoGPU } = this.get( pipeline );
452
+ const { programGPU } = this.get( pipeline );
312
453
 
313
454
  const { gl, state } = this;
314
455
 
@@ -316,29 +457,34 @@ class WebGLBackend extends Backend {
316
457
 
317
458
  //
318
459
 
319
- const bindings = renderObject.getBindings();
460
+ this._bindUniforms( renderObject.getBindings() );
320
461
 
321
- for ( const binding of bindings ) {
462
+ state.setMaterial( material );
322
463
 
323
- const bindingData = this.get( binding );
324
- const index = bindingData.index;
464
+ gl.useProgram( programGPU );
325
465
 
326
- if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
466
+ //
327
467
 
328
- gl.bindBufferBase( gl.UNIFORM_BUFFER, index, bindingData.bufferGPU );
468
+ let vaoGPU = renderObject.staticVao;
329
469
 
330
- } else if ( binding.isSampledTexture ) {
470
+ if ( vaoGPU === undefined ) {
331
471
 
332
- gl.activeTexture( gl.TEXTURE0 + index );
333
- gl.bindTexture( bindingData.glTextureType, bindingData.textureGPU );
472
+ const vaoKey = this._getVaoKey( renderObject.getIndex(), renderObject.getAttributes() );
473
+
474
+ vaoGPU = this.vaoCache[ vaoKey ];
475
+
476
+ if ( vaoGPU === undefined ) {
477
+
478
+ let staticVao;
479
+
480
+ ( { vaoGPU, staticVao } = this._createVao( renderObject.getIndex(), renderObject.getAttributes() ) );
481
+
482
+ if ( staticVao ) renderObject.staticVao = vaoGPU;
334
483
 
335
484
  }
336
485
 
337
486
  }
338
487
 
339
- state.setMaterial( material );
340
-
341
- gl.useProgram( programGPU );
342
488
  gl.bindVertexArray( vaoGPU );
343
489
 
344
490
  //
@@ -386,7 +532,20 @@ class WebGLBackend extends Backend {
386
532
  else if ( object.isLineSegments ) mode = gl.LINES;
387
533
  else if ( object.isLine ) mode = gl.LINE_STRIP;
388
534
  else if ( object.isLineLoop ) mode = gl.LINE_LOOP;
389
- else mode = gl.TRIANGLES;
535
+ else {
536
+
537
+ if ( material.wireframe === true ) {
538
+
539
+ state.setLineWidth( material.wireframeLinewidth * this.renderer.getPixelRatio() );
540
+ mode = gl.LINES;
541
+
542
+ } else {
543
+
544
+ mode = gl.TRIANGLES;
545
+
546
+ }
547
+
548
+ }
390
549
 
391
550
  //
392
551
 
@@ -407,7 +566,6 @@ class WebGLBackend extends Backend {
407
566
 
408
567
  }
409
568
 
410
-
411
569
  info.update( object, indexCount, 1 );
412
570
 
413
571
  } else {
@@ -431,15 +589,13 @@ class WebGLBackend extends Backend {
431
589
 
432
590
  }
433
591
 
434
-
435
-
436
592
  //
437
593
 
438
594
  gl.bindVertexArray( null );
439
595
 
440
596
  }
441
597
 
442
- needsRenderUpdate( renderObject ) {
598
+ needsRenderUpdate( /*renderObject*/ ) {
443
599
 
444
600
  return false;
445
601
 
@@ -453,221 +609,213 @@ class WebGLBackend extends Backend {
453
609
 
454
610
  // textures
455
611
 
456
- createSampler( /*texture*/ ) {
457
-
458
- //console.warn( 'Abstract class.' );
459
-
460
- }
461
-
462
612
  createDefaultTexture( texture ) {
463
613
 
464
- const { gl, textureUtils, defaultTextures } = this;
614
+ this.textureUtils.createDefaultTexture( texture );
465
615
 
466
- const glTextureType = textureUtils.getGLTextureType( texture );
616
+ }
467
617
 
468
- let textureGPU = defaultTextures[ glTextureType ];
618
+ createTexture( texture, options ) {
469
619
 
470
- if ( textureGPU === undefined ) {
620
+ this.textureUtils.createTexture( texture, options );
471
621
 
472
- textureGPU = gl.createTexture();
622
+ }
473
623
 
474
- gl.bindTexture( glTextureType, textureGPU );
475
- gl.texParameteri( glTextureType, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
476
- gl.texParameteri( glTextureType, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
624
+ updateTexture( texture, options ) {
477
625
 
478
- //gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
626
+ this.textureUtils.updateTexture( texture, options );
479
627
 
480
- defaultTextures[ glTextureType ] = textureGPU;
628
+ }
481
629
 
482
- }
630
+ generateMipmaps( texture ) {
483
631
 
484
- this.set( texture, {
485
- textureGPU,
486
- glTextureType,
487
- isDefault: true
488
- } );
632
+ this.textureUtils.generateMipmaps( texture );
489
633
 
490
634
  }
491
635
 
492
- createTexture( texture, options ) {
493
636
 
494
- const { gl, utils, textureUtils } = this;
495
- const { levels, width, height, depth } = options;
637
+ destroyTexture( texture ) {
496
638
 
497
- const glFormat = utils.convert( texture.format, texture.colorSpace );
498
- const glType = utils.convert( texture.type );
499
- const glInternalFormat = textureUtils.getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture );
639
+ this.textureUtils.destroyTexture( texture );
500
640
 
501
- const textureGPU = gl.createTexture();
502
- const glTextureType = textureUtils.getGLTextureType( texture );
641
+ }
503
642
 
504
- gl.bindTexture( glTextureType, textureGPU );
643
+ copyTextureToBuffer( texture, x, y, width, height ) {
505
644
 
506
- gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
507
- gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
508
- gl.pixelStorei( gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
509
- gl.pixelStorei( gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE );
645
+ return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height );
510
646
 
511
- textureUtils.setTextureParameters( glTextureType, texture );
647
+ }
512
648
 
513
- gl.bindTexture( glTextureType, textureGPU );
649
+ createSampler( /*texture*/ ) {
514
650
 
515
- if ( texture.isDataArrayTexture ) {
651
+ //console.warn( 'Abstract class.' );
516
652
 
517
- gl.texStorage3D( gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, width, height, depth );
653
+ }
518
654
 
519
- } else if ( ! texture.isVideoTexture ) {
655
+ destroySampler() {}
520
656
 
521
- gl.texStorage2D( glTextureType, levels, glInternalFormat, width, height );
657
+ // node builder
522
658
 
523
- }
659
+ createNodeBuilder( object, renderer, scene = null ) {
524
660
 
525
- this.set( texture, {
526
- textureGPU,
527
- glTextureType,
528
- glFormat,
529
- glType,
530
- glInternalFormat
531
- } );
661
+ return new GLSLNodeBuilder( object, renderer, scene );
532
662
 
533
663
  }
534
664
 
535
- updateTexture( texture, options ) {
665
+ // program
536
666
 
537
- const { gl } = this;
538
- const { width, height } = options;
539
- const { textureGPU, glTextureType, glFormat, glType, glInternalFormat } = this.get( texture );
667
+ createProgram( program ) {
540
668
 
541
- const getImage = ( source ) => {
669
+ const gl = this.gl;
670
+ const { stage, code } = program;
542
671
 
543
- if ( source.isDataTexture ) {
672
+ const shader = stage === 'fragment' ? gl.createShader( gl.FRAGMENT_SHADER ) : gl.createShader( gl.VERTEX_SHADER );
544
673
 
545
- return source.image.data;
674
+ gl.shaderSource( shader, code );
675
+ gl.compileShader( shader );
546
676
 
547
- } else if ( source instanceof ImageBitmap || source instanceof OffscreenCanvas || source instanceof HTMLImageElement || source instanceof HTMLCanvasElement ) {
677
+ this.set( program, {
678
+ shaderGPU: shader
679
+ } );
548
680
 
549
- return source;
681
+ }
550
682
 
551
- }
683
+ destroyProgram( /*program*/ ) {
552
684
 
553
- return source.data;
685
+ console.warn( 'Abstract class.' );
554
686
 
555
- };
687
+ }
556
688
 
557
- gl.bindTexture( glTextureType, textureGPU );
689
+ createRenderPipeline( renderObject, promises ) {
558
690
 
559
- if ( texture.isCubeTexture ) {
691
+ const gl = this.gl;
692
+ const pipeline = renderObject.pipeline;
560
693
 
561
- const images = options.images;
694
+ // Program
562
695
 
563
- for ( let i = 0; i < 6; i ++ ) {
696
+ const { fragmentProgram, vertexProgram } = pipeline;
564
697
 
565
- const image = getImage( images[ i ] );
698
+ const programGPU = gl.createProgram();
566
699
 
567
- gl.texSubImage2D( gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, width, height, glFormat, glType, image );
700
+ const fragmentShader = this.get( fragmentProgram ).shaderGPU;
701
+ const vertexShader = this.get( vertexProgram ).shaderGPU;
568
702
 
569
- }
703
+ gl.attachShader( programGPU, fragmentShader );
704
+ gl.attachShader( programGPU, vertexShader );
705
+ gl.linkProgram( programGPU );
570
706
 
571
- } else if ( texture.isDataArrayTexture ) {
707
+ this.set( pipeline, {
708
+ programGPU,
709
+ fragmentShader,
710
+ vertexShader
711
+ } );
572
712
 
573
- const image = options.image;
713
+ if ( promises !== null && this.parallel ) {
574
714
 
575
- gl.texSubImage3D( gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
715
+ const p = new Promise( ( resolve /*, reject*/ ) => {
576
716
 
577
- } else if ( texture.isVideoTexture ) {
717
+ const parallel = this.parallel;
718
+ const checkStatus = () => {
578
719
 
579
- texture.update();
720
+ if ( gl.getProgramParameter( programGPU, parallel.COMPLETION_STATUS_KHR ) ) {
580
721
 
581
- gl.texImage2D( glTextureType, 0, glInternalFormat, glFormat, glType, options.image );
722
+ this._completeCompile( renderObject, pipeline );
723
+ resolve();
582
724
 
725
+ } else {
583
726
 
584
- } else {
727
+ requestAnimationFrame( checkStatus );
585
728
 
586
- const image = getImage( options.image );
729
+ }
587
730
 
588
- gl.texSubImage2D( glTextureType, 0, 0, 0, width, height, glFormat, glType, image );
731
+ };
589
732
 
590
- }
733
+ checkStatus();
591
734
 
592
- }
735
+ } );
593
736
 
594
- generateMipmaps( texture ) {
737
+ promises.push( p );
595
738
 
596
- const { gl } = this;
597
- const { textureGPU, glTextureType } = this.get( texture );
739
+ return;
598
740
 
599
- gl.bindTexture( glTextureType, textureGPU );
600
- gl.generateMipmap( glTextureType );
741
+ }
601
742
 
602
- }
743
+ this._completeCompile( renderObject, pipeline );
603
744
 
604
- destroyTexture( texture ) {
745
+ }
605
746
 
606
- const { gl } = this;
607
- const { textureGPU } = this.get( texture );
747
+ _completeCompile( renderObject, pipeline ) {
608
748
 
609
- gl.deleteTexture( textureGPU );
749
+ const gl = this.gl;
750
+ const pipelineData = this.get( pipeline );
751
+ const { programGPU, fragmentShader, vertexShader } = pipelineData;
610
752
 
611
- this.delete( texture );
753
+ if ( gl.getProgramParameter( programGPU, gl.LINK_STATUS ) === false ) {
612
754
 
613
- }
755
+ console.error( 'THREE.WebGLBackend:', gl.getProgramInfoLog( programGPU ) );
614
756
 
615
- destroySampler() {}
757
+ console.error( 'THREE.WebGLBackend:', gl.getShaderInfoLog( fragmentShader ) );
758
+ console.error( 'THREE.WebGLBackend:', gl.getShaderInfoLog( vertexShader ) );
616
759
 
617
- copyTextureToBuffer( texture, x, y, width, height ) {
760
+ }
618
761
 
619
- return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height );
762
+ gl.useProgram( programGPU );
620
763
 
621
- }
764
+ // Bindings
622
765
 
623
- // node builder
766
+ this._setupBindings( renderObject.getBindings(), programGPU );
624
767
 
625
- createNodeBuilder( object, renderer, scene = null ) {
768
+ //
626
769
 
627
- return new GLSLNodeBuilder( object, renderer, scene );
770
+ this.set( pipeline, {
771
+ programGPU
772
+ } );
628
773
 
629
774
  }
630
775
 
631
- // program
632
-
633
- createProgram( program ) {
776
+ createComputePipeline( computePipeline, bindings ) {
634
777
 
635
778
  const gl = this.gl;
636
- const { stage, code } = program;
637
779
 
638
- const shader = stage === 'vertex' ? gl.createShader( gl.VERTEX_SHADER ) : gl.createShader( gl.FRAGMENT_SHADER );
639
-
640
- gl.shaderSource( shader, code );
641
- gl.compileShader( shader );
780
+ // Program
642
781
 
643
- this.set( program, {
644
- shaderGPU: shader
645
- } );
782
+ const fragmentProgram = {
783
+ stage: 'fragment',
784
+ code: '#version 300 es\nprecision highp float;\nvoid main() {}'
785
+ };
646
786
 
647
- }
787
+ this.createProgram( fragmentProgram );
648
788
 
649
- destroyProgram( /*program*/ ) {
789
+ const { computeProgram } = computePipeline;
650
790
 
651
- console.warn( 'Abstract class.' );
791
+ const programGPU = gl.createProgram();
652
792
 
653
- }
793
+ const fragmentShader = this.get( fragmentProgram ).shaderGPU;
794
+ const vertexShader = this.get( computeProgram ).shaderGPU;
654
795
 
655
- createRenderPipeline( renderObject ) {
796
+ const transforms = computeProgram.transforms;
656
797
 
657
- const gl = this.gl;
658
- const pipeline = renderObject.pipeline;
798
+ const transformVaryingNames = [];
799
+ const transformAttributeNodes = [];
659
800
 
660
- // Program
801
+ for ( let i = 0; i < transforms.length; i ++ ) {
661
802
 
662
- const { fragmentProgram, vertexProgram } = pipeline;
803
+ const transform = transforms[ i ];
663
804
 
664
- const programGPU = gl.createProgram();
805
+ transformVaryingNames.push( transform.varyingName );
806
+ transformAttributeNodes.push( transform.attributeNode );
665
807
 
666
- const fragmentShader = this.get( fragmentProgram ).shaderGPU;
667
- const vertexShader = this.get( vertexProgram ).shaderGPU;
808
+ }
668
809
 
669
810
  gl.attachShader( programGPU, fragmentShader );
670
811
  gl.attachShader( programGPU, vertexShader );
812
+
813
+ gl.transformFeedbackVaryings(
814
+ programGPU,
815
+ transformVaryingNames,
816
+ gl.SEPARATE_ATTRIBS,
817
+ );
818
+
671
819
  gl.linkProgram( programGPU );
672
820
 
673
821
  if ( gl.getProgramParameter( programGPU, gl.LINK_STATUS ) === false ) {
@@ -683,105 +831,46 @@ class WebGLBackend extends Backend {
683
831
 
684
832
  // Bindings
685
833
 
686
- const bindings = renderObject.getBindings();
687
-
688
- for ( const binding of bindings ) {
834
+ this.createBindings( bindings );
689
835
 
690
- const bindingData = this.get( binding );
691
- const index = bindingData.index;
836
+ this._setupBindings( bindings, programGPU );
692
837
 
693
- if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
838
+ const attributeNodes = computeProgram.attributes;
839
+ const attributes = [];
840
+ const transformBuffers = [];
694
841
 
695
- const location = gl.getUniformBlockIndex( programGPU, binding.name );
696
- gl.uniformBlockBinding( programGPU, location, index );
842
+ for ( let i = 0; i < attributeNodes.length; i ++ ) {
697
843
 
698
- } else if ( binding.isSampledTexture ) {
844
+ const attribute = attributeNodes[ i ].node.attribute;
699
845
 
700
- const location = gl.getUniformLocation( programGPU, binding.name );
701
- gl.uniform1i( location, index );
846
+ attributes.push( attribute );
702
847
 
703
- }
848
+ if ( ! this.has( attribute ) ) this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER );
704
849
 
705
850
  }
706
851
 
707
- // VAO
852
+ for ( let i = 0; i < transformAttributeNodes.length; i ++ ) {
708
853
 
709
- const vaoGPU = gl.createVertexArray();
854
+ const attribute = transformAttributeNodes[ i ].attribute;
710
855
 
711
- const index = renderObject.getIndex();
712
- const attributes = renderObject.getAttributes();
856
+ if ( ! this.has( attribute ) ) this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER );
713
857
 
714
- gl.bindVertexArray( vaoGPU );
715
-
716
- if ( index !== null ) {
717
-
718
- const indexData = this.get( index );
719
-
720
- gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, indexData.bufferGPU );
721
-
722
- }
723
-
724
- for ( let i = 0; i < attributes.length; i ++ ) {
725
-
726
- const attribute = attributes[ i ];
727
858
  const attributeData = this.get( attribute );
728
859
 
729
- gl.bindBuffer( gl.ARRAY_BUFFER, attributeData.bufferGPU );
730
- gl.enableVertexAttribArray( i );
731
-
732
- let stride, offset;
733
-
734
- if ( attribute.isInterleavedBufferAttribute === true ) {
735
-
736
- stride = attribute.data.stride * attributeData.bytesPerElement;
737
- offset = attribute.offset * attributeData.bytesPerElement;
738
-
739
- } else {
740
-
741
- stride = 0;
742
- offset = 0;
743
-
744
- }
745
-
746
- if ( attributeData.isInteger ) {
747
-
748
- gl.vertexAttribIPointer( i, attribute.itemSize, attributeData.type, stride, offset );
749
-
750
- } else {
751
-
752
- gl.vertexAttribPointer( i, attribute.itemSize, attributeData.type, attribute.normalized, stride, offset );
753
-
754
- }
755
-
756
- if ( attribute.isInstancedBufferAttribute && ! attribute.isInterleavedBufferAttribute ) {
757
-
758
- gl.vertexAttribDivisor( i, attribute.meshPerAttribute );
759
-
760
- } else if ( attribute.isInterleavedBufferAttribute && attribute.data.isInstancedInterleavedBuffer ) {
761
-
762
- gl.vertexAttribDivisor( i, attribute.data.meshPerAttribute );
763
-
764
- }
860
+ transformBuffers.push( attributeData );
765
861
 
766
862
  }
767
863
 
768
- gl.bindVertexArray( null );
769
-
770
864
  //
771
865
 
772
- this.set( pipeline, {
866
+ this.set( computePipeline, {
773
867
  programGPU,
774
- vaoGPU
868
+ transformBuffers,
869
+ attributes
775
870
  } );
776
871
 
777
872
  }
778
873
 
779
- createComputePipeline( /*computePipeline, bindings*/ ) {
780
-
781
- console.warn( 'Abstract class.' );
782
-
783
- }
784
-
785
874
  createBindings( bindings ) {
786
875
 
787
876
  this.updateBindings( bindings );
@@ -856,15 +945,17 @@ class WebGLBackend extends Backend {
856
945
 
857
946
  createAttribute( attribute ) {
858
947
 
948
+ if ( this.has( attribute ) ) return;
949
+
859
950
  const gl = this.gl;
860
951
 
861
952
  this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER );
862
953
 
863
954
  }
864
955
 
865
- createStorageAttribute( /*attribute*/ ) {
956
+ createStorageAttribute( attribute ) {
866
957
 
867
- console.warn( 'Abstract class.' );
958
+ //console.warn( 'Abstract class.' );
868
959
 
869
960
  }
870
961
 
@@ -874,9 +965,9 @@ class WebGLBackend extends Backend {
874
965
 
875
966
  }
876
967
 
877
- destroyAttribute( /*attribute*/ ) {
968
+ destroyAttribute( attribute ) {
878
969
 
879
- console.warn( 'Abstract class.' );
970
+ this.attributeUtils.destroyAttribute( attribute );
880
971
 
881
972
  }
882
973
 
@@ -886,12 +977,30 @@ class WebGLBackend extends Backend {
886
977
 
887
978
  }
888
979
 
889
- hasFeature( /*name*/ ) {
980
+ async hasFeatureAsync( name ) {
890
981
 
891
- return true;
982
+ return this.hasFeature( name );
892
983
 
893
984
  }
894
985
 
986
+ hasFeature( name ) {
987
+
988
+ const keysMatching = Object.keys( GLFeatureName ).filter( key => GLFeatureName[ key ] === name );
989
+
990
+ const extensions = this.extensions;
991
+
992
+ for ( let i = 0; i < keysMatching.length; i ++ ) {
993
+
994
+
995
+ if ( extensions.has( keysMatching[ i ] ) ) return true;
996
+
997
+ }
998
+
999
+ return false;
1000
+
1001
+ }
1002
+
1003
+
895
1004
  getMaxAnisotropy() {
896
1005
 
897
1006
  return this.capabilities.getMaxAnisotropy();
@@ -900,97 +1009,349 @@ class WebGLBackend extends Backend {
900
1009
 
901
1010
  copyFramebufferToTexture( texture, renderContext ) {
902
1011
 
903
- const { gl } = this;
1012
+ this.textureUtils.copyFramebufferToTexture( texture, renderContext );
904
1013
 
905
- const { textureGPU } = this.get( texture );
1014
+ }
906
1015
 
907
- const width = texture.image.width;
908
- const height = texture.image.height;
1016
+ _setFramebuffer( renderContext ) {
909
1017
 
910
- gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null );
1018
+ const { gl, state } = this;
1019
+
1020
+ let currentFrameBuffer = null;
911
1021
 
912
- if ( texture.isDepthTexture ) {
1022
+ if ( renderContext.textures !== null ) {
913
1023
 
914
- const fb = gl.createFramebuffer();
1024
+ const renderTarget = renderContext.renderTarget;
1025
+ const renderTargetContextData = this.get( renderTarget );
1026
+ const { samples, depthBuffer, stencilBuffer } = renderTarget;
1027
+ const cubeFace = this.renderer._activeCubeFace;
1028
+ const isCube = renderTarget.isWebGLCubeRenderTarget === true;
915
1029
 
916
- gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb );
1030
+ let msaaFb = renderTargetContextData.msaaFrameBuffer;
1031
+ let depthRenderbuffer = renderTargetContextData.depthRenderbuffer;
917
1032
 
918
- gl.framebufferTexture2D( gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, textureGPU, 0 );
1033
+ let fb;
919
1034
 
920
- gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, gl.DEPTH_BUFFER_BIT, gl.NEAREST );
1035
+ if ( isCube ) {
921
1036
 
922
- gl.deleteFramebuffer( fb );
1037
+ if ( renderTargetContextData.cubeFramebuffers === undefined ) {
923
1038
 
1039
+ renderTargetContextData.cubeFramebuffers = [];
924
1040
 
925
- } else {
1041
+ }
1042
+
1043
+ fb = renderTargetContextData.cubeFramebuffers[ cubeFace ];
1044
+
1045
+ } else {
1046
+
1047
+ fb = renderTargetContextData.framebuffer;
1048
+
1049
+ }
1050
+
1051
+ if ( fb === undefined ) {
1052
+
1053
+ fb = gl.createFramebuffer();
1054
+
1055
+ state.bindFramebuffer( gl.FRAMEBUFFER, fb );
1056
+
1057
+ const textures = renderContext.textures;
1058
+
1059
+ if ( isCube ) {
1060
+
1061
+ renderTargetContextData.cubeFramebuffers[ cubeFace ] = fb;
1062
+ const { textureGPU } = this.get( textures[ 0 ] );
1063
+
1064
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, textureGPU, 0 );
1065
+
1066
+ } else {
1067
+
1068
+ for ( let i = 0; i < textures.length; i ++ ) {
1069
+
1070
+ const texture = textures[ i ];
1071
+ const textureData = this.get( texture );
1072
+ textureData.renderTarget = renderContext.renderTarget;
1073
+
1074
+ const attachment = gl.COLOR_ATTACHMENT0 + i;
1075
+
1076
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 );
1077
+
1078
+ }
1079
+
1080
+ renderTargetContextData.framebuffer = fb;
1081
+
1082
+ state.drawBuffers( renderContext, fb );
1083
+
1084
+ }
1085
+
1086
+ if ( renderContext.depthTexture !== null ) {
1087
+
1088
+ const textureData = this.get( renderContext.depthTexture );
1089
+ const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
1090
+
1091
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0 );
1092
+
1093
+ }
1094
+
1095
+ }
1096
+
1097
+ if ( samples > 0 ) {
1098
+
1099
+ if ( msaaFb === undefined ) {
1100
+
1101
+ const invalidationArray = [];
1102
+
1103
+ msaaFb = gl.createFramebuffer();
1104
+
1105
+ state.bindFramebuffer( gl.FRAMEBUFFER, msaaFb );
1106
+
1107
+ const msaaRenderbuffers = [];
1108
+
1109
+ const textures = renderContext.textures;
1110
+
1111
+ for ( let i = 0; i < textures.length; i ++ ) {
1112
+
1113
+
1114
+ msaaRenderbuffers[ i ] = gl.createRenderbuffer();
1115
+
1116
+ gl.bindRenderbuffer( gl.RENDERBUFFER, msaaRenderbuffers[ i ] );
1117
+
1118
+ invalidationArray.push( gl.COLOR_ATTACHMENT0 + i );
1119
+
1120
+ if ( depthBuffer ) {
1121
+
1122
+ const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
1123
+ invalidationArray.push( depthStyle );
1124
+
1125
+ }
1126
+
1127
+ const texture = renderContext.textures[ i ];
1128
+ const textureData = this.get( texture );
1129
+
1130
+ gl.renderbufferStorageMultisample( gl.RENDERBUFFER, samples, textureData.glInternalFormat, renderContext.width, renderContext.height );
1131
+ gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, msaaRenderbuffers[ i ] );
1132
+
1133
+
1134
+ }
1135
+
1136
+ renderTargetContextData.msaaFrameBuffer = msaaFb;
1137
+ renderTargetContextData.msaaRenderbuffers = msaaRenderbuffers;
1138
+
1139
+ if ( depthRenderbuffer === undefined ) {
1140
+
1141
+ depthRenderbuffer = gl.createRenderbuffer();
1142
+ this.textureUtils.setupRenderBufferStorage( depthRenderbuffer, renderContext );
1143
+
1144
+ renderTargetContextData.depthRenderbuffer = depthRenderbuffer;
1145
+
1146
+ const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
1147
+ invalidationArray.push( depthStyle );
926
1148
 
927
- gl.bindTexture( gl.TEXTURE_2D, textureGPU );
928
- gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height );
1149
+ }
1150
+
1151
+ renderTargetContextData.invalidationArray = invalidationArray;
1152
+
1153
+ }
1154
+
1155
+ currentFrameBuffer = renderTargetContextData.msaaFrameBuffer;
929
1156
 
930
- gl.bindTexture( gl.TEXTURE_2D, null );
1157
+ } else {
1158
+
1159
+ currentFrameBuffer = fb;
1160
+
1161
+ }
931
1162
 
932
1163
  }
933
1164
 
934
- if ( texture.generateMipmaps ) this.generateMipmaps( texture );
1165
+ state.bindFramebuffer( gl.FRAMEBUFFER, currentFrameBuffer );
935
1166
 
936
- this._setFramebuffer( renderContext );
1167
+ }
1168
+
1169
+
1170
+ _getVaoKey( index, attributes ) {
1171
+
1172
+ let key = [];
1173
+
1174
+ if ( index !== null ) {
1175
+
1176
+ const indexData = this.get( index );
1177
+
1178
+ key += ':' + indexData.id;
1179
+
1180
+ }
1181
+
1182
+ for ( let i = 0; i < attributes.length; i ++ ) {
1183
+
1184
+ const attributeData = this.get( attributes[ i ] );
1185
+
1186
+ key += ':' + attributeData.id;
1187
+
1188
+ }
1189
+
1190
+ return key;
937
1191
 
938
1192
  }
939
1193
 
940
- _setFramebuffer( renderContext ) {
1194
+ _createVao( index, attributes ) {
941
1195
 
942
1196
  const { gl } = this;
943
1197
 
944
- if ( renderContext.textures !== null ) {
1198
+ const vaoGPU = gl.createVertexArray();
1199
+ let key = '';
945
1200
 
946
- const renderContextData = this.get( renderContext.renderTarget );
1201
+ let staticVao = true;
947
1202
 
948
- let fb = renderContextData.framebuffer;
1203
+ gl.bindVertexArray( vaoGPU );
949
1204
 
950
- if ( fb === undefined ) {
1205
+ if ( index !== null ) {
951
1206
 
952
- fb = gl.createFramebuffer();
1207
+ const indexData = this.get( index );
953
1208
 
954
- gl.bindFramebuffer( gl.FRAMEBUFFER, fb );
1209
+ gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, indexData.bufferGPU );
955
1210
 
956
- const textures = renderContext.textures;
1211
+ key += ':' + indexData.id;
957
1212
 
958
- const drawBuffers = [];
1213
+ }
959
1214
 
960
- for ( let i = 0; i < textures.length; i ++ ) {
1215
+ for ( let i = 0; i < attributes.length; i ++ ) {
961
1216
 
962
- const texture = textures[ i ];
963
- const { textureGPU } = this.get( texture );
1217
+ const attribute = attributes[ i ];
1218
+ const attributeData = this.get( attribute );
964
1219
 
965
- const attachment = gl.COLOR_ATTACHMENT0 + i;
1220
+ key += ':' + attributeData.id;
1221
+
1222
+ gl.bindBuffer( gl.ARRAY_BUFFER, attributeData.bufferGPU );
1223
+ gl.enableVertexAttribArray( i );
966
1224
 
967
- gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, textureGPU, 0 );
1225
+ if ( attribute.isStorageBufferAttribute ) staticVao = false;
968
1226
 
969
- drawBuffers.push( attachment );
1227
+ let stride, offset;
970
1228
 
971
- }
1229
+ if ( attribute.isInterleavedBufferAttribute === true ) {
972
1230
 
973
- gl.drawBuffers( drawBuffers );
1231
+ stride = attribute.data.stride * attributeData.bytesPerElement;
1232
+ offset = attribute.offset * attributeData.bytesPerElement;
974
1233
 
975
- if ( renderContext.depthTexture !== null ) {
1234
+ } else {
976
1235
 
977
- const { textureGPU } = this.get( renderContext.depthTexture );
1236
+ stride = 0;
1237
+ offset = 0;
978
1238
 
979
- gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, textureGPU, 0 );
1239
+ }
980
1240
 
981
- }
1241
+ if ( attributeData.isInteger ) {
982
1242
 
983
- renderContextData.framebuffer = fb;
1243
+ gl.vertexAttribIPointer( i, attribute.itemSize, attributeData.type, stride, offset );
984
1244
 
985
1245
  } else {
986
1246
 
987
- gl.bindFramebuffer( gl.FRAMEBUFFER, fb );
1247
+ gl.vertexAttribPointer( i, attribute.itemSize, attributeData.type, attribute.normalized, stride, offset );
988
1248
 
989
1249
  }
990
1250
 
991
- } else {
1251
+ if ( attribute.isInstancedBufferAttribute && ! attribute.isInterleavedBufferAttribute ) {
1252
+
1253
+ gl.vertexAttribDivisor( i, attribute.meshPerAttribute );
1254
+
1255
+ } else if ( attribute.isInterleavedBufferAttribute && attribute.data.isInstancedInterleavedBuffer ) {
1256
+
1257
+ gl.vertexAttribDivisor( i, attribute.data.meshPerAttribute );
1258
+
1259
+ }
1260
+
1261
+ }
992
1262
 
993
- gl.bindFramebuffer( gl.FRAMEBUFFER, null );
1263
+ gl.bindBuffer( gl.ARRAY_BUFFER, null );
1264
+
1265
+ this.vaoCache[ key ] = vaoGPU;
1266
+
1267
+ return { vaoGPU, staticVao };
1268
+
1269
+ }
1270
+
1271
+ _getTransformFeedback( transformBuffers ) {
1272
+
1273
+ let key = '';
1274
+
1275
+ for ( let i = 0; i < transformBuffers.length; i ++ ) {
1276
+
1277
+ key += ':' + transformBuffers[ i ].id;
1278
+
1279
+ }
1280
+
1281
+ let transformFeedbackGPU = this.transformFeedbackCache[ key ];
1282
+
1283
+ if ( transformFeedbackGPU !== undefined ) {
1284
+
1285
+ return transformFeedbackGPU;
1286
+
1287
+ }
1288
+
1289
+ const gl = this.gl;
1290
+
1291
+ transformFeedbackGPU = gl.createTransformFeedback();
1292
+
1293
+ gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, transformFeedbackGPU );
1294
+
1295
+ for ( let i = 0; i < transformBuffers.length; i ++ ) {
1296
+
1297
+ const attributeData = transformBuffers[ i ];
1298
+
1299
+ gl.bindBufferBase( gl.TRANSFORM_FEEDBACK_BUFFER, i, attributeData.transformBuffer );
1300
+
1301
+ }
1302
+
1303
+ gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, null );
1304
+
1305
+ this.transformFeedbackCache[ key ] = transformFeedbackGPU;
1306
+
1307
+ return transformFeedbackGPU;
1308
+
1309
+ }
1310
+
1311
+
1312
+ _setupBindings( bindings, programGPU ) {
1313
+
1314
+ const gl = this.gl;
1315
+
1316
+ for ( const binding of bindings ) {
1317
+
1318
+ const bindingData = this.get( binding );
1319
+ const index = bindingData.index;
1320
+
1321
+ if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
1322
+
1323
+ const location = gl.getUniformBlockIndex( programGPU, binding.name );
1324
+ gl.uniformBlockBinding( programGPU, location, index );
1325
+
1326
+ } else if ( binding.isSampledTexture ) {
1327
+
1328
+ const location = gl.getUniformLocation( programGPU, binding.name );
1329
+ gl.uniform1i( location, index );
1330
+
1331
+ }
1332
+
1333
+ }
1334
+
1335
+ }
1336
+
1337
+ _bindUniforms( bindings ) {
1338
+
1339
+ const { gl, state } = this;
1340
+
1341
+ for ( const binding of bindings ) {
1342
+
1343
+ const bindingData = this.get( binding );
1344
+ const index = bindingData.index;
1345
+
1346
+ if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
1347
+
1348
+ gl.bindBufferBase( gl.UNIFORM_BUFFER, index, bindingData.bufferGPU );
1349
+
1350
+ } else if ( binding.isSampledTexture ) {
1351
+
1352
+ state.bindTexture( bindingData.glTextureType, bindingData.textureGPU, gl.TEXTURE0 + index );
1353
+
1354
+ }
994
1355
 
995
1356
  }
996
1357