super-three 0.155.0 → 0.156.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 (108) hide show
  1. package/build/three.cjs +107 -125
  2. package/build/three.js +107 -125
  3. package/build/three.min.js +1 -1
  4. package/build/three.module.js +104 -126
  5. package/build/three.module.min.js +1 -1
  6. package/examples/jsm/controls/OrbitControls.js +13 -5
  7. package/examples/jsm/csm/CSMShader.js +35 -1
  8. package/examples/jsm/libs/tween.module.js +790 -735
  9. package/examples/jsm/libs/utif.module.js +1644 -1558
  10. package/examples/jsm/loaders/DDSLoader.js +46 -3
  11. package/examples/jsm/loaders/EXRLoader.js +4 -4
  12. package/examples/jsm/loaders/FBXLoader.js +2 -0
  13. package/examples/jsm/loaders/GLTFLoader.js +17 -7
  14. package/examples/jsm/loaders/KTX2Loader.js +126 -77
  15. package/examples/jsm/loaders/LogLuvLoader.js +2 -2
  16. package/examples/jsm/loaders/MMDLoader.js +10 -7
  17. package/examples/jsm/loaders/RGBELoader.js +48 -66
  18. package/examples/jsm/loaders/STLLoader.js +7 -0
  19. package/examples/jsm/nodes/Nodes.js +3 -0
  20. package/examples/jsm/nodes/accessors/BufferAttributeNode.js +28 -2
  21. package/examples/jsm/nodes/accessors/CubeTextureNode.js +18 -3
  22. package/examples/jsm/nodes/accessors/ExtendedMaterialNode.js +2 -4
  23. package/examples/jsm/nodes/accessors/LineMaterialNode.js +31 -0
  24. package/examples/jsm/nodes/accessors/MaterialNode.js +55 -33
  25. package/examples/jsm/nodes/accessors/MaterialReferenceNode.js +3 -0
  26. package/examples/jsm/nodes/accessors/Object3DNode.js +2 -2
  27. package/examples/jsm/nodes/accessors/TextureNode.js +6 -2
  28. package/examples/jsm/nodes/accessors/TextureStoreNode.js +29 -0
  29. package/examples/jsm/nodes/core/AttributeNode.js +2 -2
  30. package/examples/jsm/nodes/core/Node.js +17 -1
  31. package/examples/jsm/nodes/core/NodeBuilder.js +94 -12
  32. package/examples/jsm/nodes/core/NodeUniform.js +1 -1
  33. package/examples/jsm/nodes/core/OutputStructNode.js +58 -0
  34. package/examples/jsm/nodes/core/PropertyNode.js +2 -0
  35. package/examples/jsm/nodes/core/StackNode.js +4 -4
  36. package/examples/jsm/nodes/core/StructTypeNode.js +24 -0
  37. package/examples/jsm/nodes/display/ViewportNode.js +19 -5
  38. package/examples/jsm/nodes/materials/LineDashedNodeMaterial.js +54 -0
  39. package/examples/jsm/nodes/materials/Materials.js +1 -0
  40. package/examples/jsm/nodes/materials/NodeMaterial.js +12 -3
  41. package/examples/jsm/nodes/math/HashNode.js +35 -0
  42. package/examples/jsm/nodes/shadernode/ShaderNode.js +4 -0
  43. package/examples/jsm/nodes/utils/SplitNode.js +1 -1
  44. package/examples/jsm/postprocessing/FilmPass.js +3 -5
  45. package/examples/jsm/postprocessing/RenderPass.js +30 -12
  46. package/examples/jsm/postprocessing/SAOPass.js +23 -98
  47. package/examples/jsm/postprocessing/SSAOPass.js +10 -30
  48. package/examples/jsm/renderers/common/Backend.js +11 -8
  49. package/examples/jsm/renderers/common/Binding.js +6 -0
  50. package/examples/jsm/renderers/common/Bindings.js +5 -4
  51. package/examples/jsm/renderers/common/Pipelines.js +2 -2
  52. package/examples/jsm/renderers/common/RenderContexts.js +26 -1
  53. package/examples/jsm/renderers/common/RenderList.js +12 -4
  54. package/examples/jsm/renderers/common/RenderObject.js +6 -2
  55. package/examples/jsm/renderers/common/Renderer.js +12 -3
  56. package/examples/jsm/renderers/common/SampledTexture.js +2 -1
  57. package/examples/jsm/renderers/common/Sampler.js +1 -1
  58. package/examples/jsm/renderers/common/StorageBuffer.js +1 -1
  59. package/examples/jsm/renderers/common/Textures.js +155 -15
  60. package/examples/jsm/renderers/common/nodes/NodeSampledTexture.js +2 -2
  61. package/examples/jsm/renderers/common/nodes/NodeSampler.js +1 -1
  62. package/examples/jsm/renderers/common/nodes/Nodes.js +43 -9
  63. package/examples/jsm/renderers/webgl/WebGLBackend.js +607 -0
  64. package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +118 -17
  65. package/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js +84 -0
  66. package/examples/jsm/renderers/webgl/utils/WebGLExtensions.js +26 -0
  67. package/examples/jsm/renderers/webgl/utils/WebGLState.js +529 -0
  68. package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +199 -0
  69. package/examples/jsm/renderers/webgl/utils/WebGLUtils.js +242 -0
  70. package/examples/jsm/renderers/webgl-legacy/nodes/GLSL1NodeBuilder.js +340 -0
  71. package/examples/jsm/renderers/{webgl → webgl-legacy}/nodes/WebGLNodeBuilder.js +1 -1
  72. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +279 -40
  73. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +18 -2
  74. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +89 -59
  75. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeFunction.js +2 -2
  76. package/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +15 -2
  77. package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +34 -9
  78. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +26 -135
  79. package/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js +6 -5
  80. package/examples/jsm/shaders/FilmShader.js +11 -54
  81. package/examples/jsm/shaders/SAOShader.js +0 -13
  82. package/examples/jsm/shaders/SSAOShader.js +33 -26
  83. package/package.json +1 -1
  84. package/src/Three.js +1 -0
  85. package/src/audio/Audio.js +6 -0
  86. package/src/constants.js +4 -1
  87. package/src/core/Object3D.js +1 -14
  88. package/src/core/UniformsGroup.js +2 -2
  89. package/src/loaders/DataTextureLoader.js +0 -2
  90. package/src/materials/Material.js +2 -2
  91. package/src/math/Vector2.js +2 -2
  92. package/src/math/Vector3.js +3 -3
  93. package/src/math/Vector4.js +4 -4
  94. package/src/objects/Line.js +1 -1
  95. package/src/objects/Mesh.js +1 -1
  96. package/src/objects/Points.js +1 -1
  97. package/src/renderers/WebGLRenderer.js +21 -49
  98. package/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +11 -1
  99. package/src/renderers/shaders/ShaderLib/background.glsl.js +8 -0
  100. package/src/renderers/webgl/WebGLBackground.js +5 -14
  101. package/src/renderers/webgl/WebGLProgram.js +2 -0
  102. package/src/renderers/webgl/WebGLPrograms.js +5 -1
  103. package/src/renderers/webgl/WebGLTextures.js +4 -4
  104. package/src/renderers/webgl/WebGLUtils.js +27 -20
  105. package/src/textures/Texture.js +2 -2
  106. package/src/utils.js +9 -1
  107. /package/examples/jsm/renderers/{webgl → webgl-legacy}/nodes/SlotNode.js +0 -0
  108. /package/examples/jsm/renderers/{webgl → webgl-legacy}/nodes/WebGLNodes.js +0 -0
@@ -1,4 +1,4 @@
1
- import { lights } from '../../nodes/Nodes.js';
1
+ import { LightsNode } from '../../nodes/Nodes.js';
2
2
 
3
3
  function painterSortStable( a, b ) {
4
4
 
@@ -58,12 +58,14 @@ class RenderList {
58
58
  this.opaque = [];
59
59
  this.transparent = [];
60
60
 
61
- this.lightsNode = lights( [] );
61
+ this.lightsNode = new LightsNode( [] );
62
62
  this.lightsArray = [];
63
63
 
64
+ this.occlusionQueryCount = 0;
65
+
64
66
  }
65
67
 
66
- init() {
68
+ begin() {
67
69
 
68
70
  this.renderItemsIndex = 0;
69
71
 
@@ -71,6 +73,8 @@ class RenderList {
71
73
  this.transparent.length = 0;
72
74
  this.lightsArray.length = 0;
73
75
 
76
+ this.occlusionQueryCount = 0;
77
+
74
78
  return this;
75
79
 
76
80
  }
@@ -117,6 +121,8 @@ class RenderList {
117
121
 
118
122
  const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group );
119
123
 
124
+ if ( object.occlusionTest === true ) this.occlusionQueryCount ++;
125
+
120
126
  ( material.transparent === true ? this.transparent : this.opaque ).push( renderItem );
121
127
 
122
128
  }
@@ -166,7 +172,9 @@ class RenderList {
166
172
  renderItem.object = null;
167
173
  renderItem.geometry = null;
168
174
  renderItem.material = null;
169
- renderItem.program = null;
175
+ renderItem.groupOrder = null;
176
+ renderItem.renderOrder = null;
177
+ renderItem.z = null;
170
178
  renderItem.group = null;
171
179
 
172
180
  }
@@ -23,11 +23,15 @@ export default class RenderObject {
23
23
  this.pipeline = null;
24
24
  this.vertexBuffers = null;
25
25
 
26
+ this._nodeBuilder = null;
27
+ this._bindings = null;
26
28
  this._materialVersion = - 1;
27
29
  this._materialCacheKey = '';
28
30
 
29
31
  this.onDispose = null;
30
32
 
33
+ this.isRenderObject = true;
34
+
31
35
  this.onMaterialDispose = () => {
32
36
 
33
37
  this.dispose();
@@ -40,13 +44,13 @@ export default class RenderObject {
40
44
 
41
45
  getNodeBuilder() {
42
46
 
43
- return this._nodes.getForRender( this );
47
+ return this._nodeBuilder || ( this._nodeBuilder = this._nodes.getForRender( this ) );
44
48
 
45
49
  }
46
50
 
47
51
  getBindings() {
48
52
 
49
- return this.getNodeBuilder().getBindings();
53
+ return this._bindings || ( this._bindings = this.getNodeBuilder().createBindings() );
50
54
 
51
55
  }
52
56
 
@@ -258,7 +258,7 @@ class Renderer {
258
258
  _frustum.setFromProjectionMatrix( _projScreenMatrix, coordinateSystem );
259
259
 
260
260
  const renderList = this._renderLists.get( scene, camera );
261
- renderList.init();
261
+ renderList.begin();
262
262
 
263
263
  this._projectObject( scene, camera, 0, renderList );
264
264
 
@@ -278,17 +278,18 @@ class Renderer {
278
278
 
279
279
  const renderTargetData = this._textures.get( renderTarget );
280
280
 
281
- renderContext.texture = renderTargetData.texture;
281
+ renderContext.textures = renderTargetData.textures;
282
282
  renderContext.depthTexture = renderTargetData.depthTexture;
283
283
 
284
284
  } else {
285
285
 
286
- renderContext.texture = null;
286
+ renderContext.textures = null;
287
287
  renderContext.depthTexture = null;
288
288
 
289
289
  }
290
290
 
291
291
  renderContext.activeCubeFace = activeCubeFace;
292
+ renderContext.occlusionQueryCount = renderList.occlusionQueryCount;
292
293
 
293
294
  //
294
295
 
@@ -550,6 +551,14 @@ class Renderer {
550
551
 
551
552
  }
552
553
 
554
+ isOccluded( object ) {
555
+
556
+ const renderContext = this._currentRenderContext || this._lastRenderContext;
557
+
558
+ return renderContext && this.backend.isOccluded( renderContext, object );
559
+
560
+ }
561
+
553
562
  clear( color = true, depth = true, stencil = true ) {
554
563
 
555
564
  const renderContext = this._currentRenderContext || this._lastRenderContext;
@@ -11,7 +11,8 @@ class SampledTexture extends Binding {
11
11
  this.id = id ++;
12
12
 
13
13
  this.texture = texture;
14
- this.version = texture.version;
14
+ this.version = texture ? texture.version : 0;
15
+ this.store = false;
15
16
 
16
17
  this.isSampledTexture = true;
17
18
 
@@ -7,7 +7,7 @@ class Sampler extends Binding {
7
7
  super( name );
8
8
 
9
9
  this.texture = texture;
10
- this.version = texture.version;
10
+ this.version = texture ? texture.version : 0;
11
11
 
12
12
  this.isSampler = true;
13
13
 
@@ -4,7 +4,7 @@ class StorageBuffer extends Buffer {
4
4
 
5
5
  constructor( name, attribute ) {
6
6
 
7
- super( name, attribute.array );
7
+ super( name, attribute ? attribute.array : null );
8
8
 
9
9
  this.attribute = attribute;
10
10
 
@@ -1,7 +1,8 @@
1
1
  import DataMap from './DataMap.js';
2
- import { Vector2, DepthTexture, DepthStencilFormat, UnsignedInt248Type } from 'three';
3
2
 
4
- const _size = new Vector2();
3
+ import { Vector3, DepthTexture, DepthStencilFormat, UnsignedInt248Type, LinearFilter, NearestFilter, EquirectangularReflectionMapping, EquirectangularRefractionMapping, CubeReflectionMapping, CubeRefractionMapping } from 'three';
4
+
5
+ const _size = new Vector3();
5
6
 
6
7
  class Textures extends DataMap {
7
8
 
@@ -19,10 +20,24 @@ class Textures extends DataMap {
19
20
  const renderTargetData = this.get( renderTarget );
20
21
  const sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples;
21
22
 
22
- const texture = renderTarget.texture;
23
+ let texture, textures;
24
+
25
+ if ( renderTarget.isWebGLMultipleRenderTargets ) {
26
+
27
+ textures = renderTarget.texture;
28
+ texture = renderTarget.texture[ 0 ];
29
+
30
+ } else {
31
+
32
+ textures = [ renderTarget.texture ];
33
+ texture = renderTarget.texture;
34
+
35
+ }
36
+
23
37
  const size = this.getSize( texture );
24
38
 
25
39
  let depthTexture = renderTarget.depthTexture || renderTargetData.depthTexture;
40
+ let textureNeedsUpdate = false;
26
41
 
27
42
  if ( depthTexture === undefined ) {
28
43
 
@@ -36,7 +51,7 @@ class Textures extends DataMap {
36
51
 
37
52
  if ( renderTargetData.width !== size.width || size.height !== renderTargetData.height ) {
38
53
 
39
- texture.needsUpdate = true;
54
+ textureNeedsUpdate = true;
40
55
  depthTexture.needsUpdate = true;
41
56
 
42
57
  depthTexture.image.width = size.width;
@@ -46,12 +61,12 @@ class Textures extends DataMap {
46
61
 
47
62
  renderTargetData.width = size.width;
48
63
  renderTargetData.height = size.height;
49
- renderTargetData.texture = texture;
64
+ renderTargetData.textures = textures;
50
65
  renderTargetData.depthTexture = depthTexture;
51
66
 
52
67
  if ( renderTargetData.sampleCount !== sampleCount ) {
53
68
 
54
- texture.needsUpdate = true;
69
+ textureNeedsUpdate = true;
55
70
  depthTexture.needsUpdate = true;
56
71
 
57
72
  renderTargetData.sampleCount = sampleCount;
@@ -60,7 +75,17 @@ class Textures extends DataMap {
60
75
 
61
76
  const options = { sampleCount };
62
77
 
63
- this.updateTexture( texture, options );
78
+
79
+ for ( let i = 0; i < textures.length; i ++ ) {
80
+
81
+ const texture = textures[ i ];
82
+
83
+ if ( textureNeedsUpdate ) texture.needsUpdate = true;
84
+
85
+ this.updateTexture( texture, options );
86
+
87
+ }
88
+
64
89
  this.updateTexture( depthTexture, options );
65
90
 
66
91
  // dispose handler
@@ -75,7 +100,20 @@ class Textures extends DataMap {
75
100
 
76
101
  renderTarget.removeEventListener( 'dispose', onDispose );
77
102
 
78
- this._destroyTexture( texture );
103
+ if ( textures !== undefined ) {
104
+
105
+ for ( let i = 0; i < textures.length; i ++ ) {
106
+
107
+ this._destroyTexture( textures[ i ] );
108
+
109
+ }
110
+
111
+ } else {
112
+
113
+ this._destroyTexture( texture );
114
+
115
+ }
116
+
79
117
  this._destroyTexture( depthTexture );
80
118
 
81
119
  };
@@ -105,7 +143,19 @@ class Textures extends DataMap {
105
143
 
106
144
  //
107
145
 
108
- if ( isRenderTarget ) {
146
+ const { width, height, depth } = this.getSize( texture );
147
+
148
+ options.width = width;
149
+ options.height = height;
150
+ options.depth = depth;
151
+ options.needsMipmaps = this.needsMipmaps( texture );
152
+ options.levels = options.needsMipmaps ? this.getMipLevels( texture, width, height ) : 1;
153
+
154
+ //
155
+
156
+ if ( isRenderTarget || options.store === true ) {
157
+
158
+ //if ( options.store === true ) options.levels = 1; /* no mipmaps? */
109
159
 
110
160
  backend.createSampler( texture );
111
161
  backend.createTexture( texture, options );
@@ -130,6 +180,24 @@ class Textures extends DataMap {
130
180
 
131
181
  } else {
132
182
 
183
+ if ( texture.images ) {
184
+
185
+ const images = [];
186
+
187
+ for ( const image of texture.images ) {
188
+
189
+ images.push( this._getUploadImage( image ) );
190
+
191
+ }
192
+
193
+ options.images = images;
194
+
195
+ } else {
196
+
197
+ options.image = this._getUploadImage( image );
198
+
199
+ }
200
+
133
201
  if ( textureData.isDefaultTexture === undefined || textureData.isDefaultTexture === true ) {
134
202
 
135
203
  backend.createTexture( texture, options );
@@ -138,7 +206,9 @@ class Textures extends DataMap {
138
206
 
139
207
  }
140
208
 
141
- backend.updateTexture( texture );
209
+ backend.updateTexture( texture, options );
210
+
211
+ if ( options.needsMipmaps ) backend.generateMipmaps( texture );
142
212
 
143
213
  }
144
214
 
@@ -188,15 +258,19 @@ class Textures extends DataMap {
188
258
 
189
259
  getSize( texture, target = _size ) {
190
260
 
191
- if ( texture.isCubeTexture ) {
261
+ let image = texture.images ? texture.images[ 0 ] : texture.image;
192
262
 
193
- target.width = texture.image[ 0 ].width;
194
- target.height = texture.image[ 0 ].height;
263
+ if ( image ) {
264
+
265
+ if ( image.image !== undefined ) image = image.image;
266
+
267
+ target.width = image.width;
268
+ target.height = image.height;
269
+ target.depth = texture.isCubeTexture ? 6 : ( image.depth || 1 );
195
270
 
196
271
  } else {
197
272
 
198
- target.width = texture.image.width;
199
- target.height = texture.image.height;
273
+ target.width = target.height = target.depth = 1;
200
274
 
201
275
  }
202
276
 
@@ -204,6 +278,72 @@ class Textures extends DataMap {
204
278
 
205
279
  }
206
280
 
281
+ getMipLevels( texture, width, height ) {
282
+
283
+ let mipLevelCount;
284
+
285
+ if ( texture.isCompressedTexture ) {
286
+
287
+ mipLevelCount = texture.mipmaps.length;
288
+
289
+ } else {
290
+
291
+ mipLevelCount = Math.floor( Math.log2( Math.max( width, height ) ) ) + 1;
292
+
293
+ }
294
+
295
+ return mipLevelCount;
296
+
297
+ }
298
+
299
+ needsMipmaps( texture ) {
300
+
301
+ if ( this.isEnvironmentTexture( texture ) ) return true;
302
+
303
+ return ( texture.isCompressedTexture !== true ) /*&& ( texture.generateMipmaps === true )*/ && ( texture.minFilter !== NearestFilter ) && ( texture.minFilter !== LinearFilter );
304
+
305
+ }
306
+
307
+ isEnvironmentTexture( texture ) {
308
+
309
+ const mapping = texture.mapping;
310
+
311
+ return ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) || ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
312
+
313
+ }
314
+
315
+ _getUploadImage( image ) {
316
+
317
+ if ( this._isHTMLImage( image ) ) {
318
+
319
+ return this._imageToCanvas( image );
320
+
321
+ }
322
+
323
+ return image;
324
+
325
+ }
326
+
327
+ _imageToCanvas( image ) {
328
+
329
+ const { width, height } = image;
330
+
331
+ // eslint-disable-next-line compat/compat
332
+ const canvas = new OffscreenCanvas( width, height );
333
+
334
+ const context = canvas.getContext( '2d' );
335
+ context.drawImage( image, 0, 0, width, height );
336
+
337
+ return canvas;
338
+
339
+ }
340
+
341
+ _isHTMLImage( image ) {
342
+
343
+ return ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement );
344
+
345
+ }
346
+
207
347
  _destroyTexture( texture ) {
208
348
 
209
349
  this.backend.destroySampler( texture );
@@ -4,7 +4,7 @@ class NodeSampledTexture extends SampledTexture {
4
4
 
5
5
  constructor( name, textureNode ) {
6
6
 
7
- super( name, textureNode.value );
7
+ super( name, textureNode ? textureNode.value : null );
8
8
 
9
9
  this.textureNode = textureNode;
10
10
 
@@ -22,7 +22,7 @@ class NodeSampledCubeTexture extends SampledCubeTexture {
22
22
 
23
23
  constructor( name, textureNode ) {
24
24
 
25
- super( name, textureNode.value );
25
+ super( name, textureNode ? textureNode.value : null );
26
26
 
27
27
  this.textureNode = textureNode;
28
28
 
@@ -4,7 +4,7 @@ class NodeSampler extends Sampler {
4
4
 
5
5
  constructor( name, textureNode ) {
6
6
 
7
- super( name, textureNode.value );
7
+ super( name, textureNode ? textureNode.value : null );
8
8
 
9
9
  this.textureNode = textureNode;
10
10
 
@@ -1,4 +1,5 @@
1
1
  import DataMap from '../DataMap.js';
2
+ import ChainMap from '../ChainMap.js';
2
3
  import { NoToneMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from 'three';
3
4
  import { NodeFrame, cubeTexture, texture, rangeFog, densityFog, reference, toneMapping, equirectUV, viewportBottomLeft, normalWorld } from '../../../nodes/Nodes.js';
4
5
 
@@ -11,6 +12,15 @@ class Nodes extends DataMap {
11
12
  this.renderer = renderer;
12
13
  this.backend = backend;
13
14
  this.nodeFrame = new NodeFrame();
15
+ this.cache = new ChainMap();
16
+
17
+ }
18
+
19
+ getForRenderChainKey( renderObject ) {
20
+
21
+ const { object, material, lightsNode, context } = renderObject;
22
+
23
+ return [ object.geometry, material, lightsNode, context ];
14
24
 
15
25
  }
16
26
 
@@ -22,13 +32,25 @@ class Nodes extends DataMap {
22
32
 
23
33
  if ( nodeBuilder === undefined ) {
24
34
 
25
- nodeBuilder = this.backend.createNodeBuilder( renderObject.object, this.renderer, renderObject.scene );
26
- nodeBuilder.material = renderObject.material;
27
- nodeBuilder.lightsNode = renderObject.lightsNode;
28
- nodeBuilder.environmentNode = this.getEnvironmentNode( renderObject.scene );
29
- nodeBuilder.fogNode = this.getFogNode( renderObject.scene );
30
- nodeBuilder.toneMappingNode = this.getToneMappingNode();
31
- nodeBuilder.build();
35
+ const { cache } = this;
36
+
37
+ const chainKey = this.getForRenderChainKey( renderObject );
38
+
39
+ nodeBuilder = cache.get( chainKey );
40
+
41
+ if ( nodeBuilder === undefined ) {
42
+
43
+ nodeBuilder = this.backend.createNodeBuilder( renderObject.object, this.renderer, renderObject.scene );
44
+ nodeBuilder.material = renderObject.material;
45
+ nodeBuilder.lightsNode = renderObject.lightsNode;
46
+ nodeBuilder.environmentNode = this.getEnvironmentNode( renderObject.scene );
47
+ nodeBuilder.fogNode = this.getFogNode( renderObject.scene );
48
+ nodeBuilder.toneMappingNode = this.getToneMappingNode();
49
+ nodeBuilder.build();
50
+
51
+ cache.set( chainKey, nodeBuilder );
52
+
53
+ }
32
54
 
33
55
  renderObjectData.nodeBuilder = nodeBuilder;
34
56
 
@@ -38,6 +60,18 @@ class Nodes extends DataMap {
38
60
 
39
61
  }
40
62
 
63
+ delete( object ) {
64
+
65
+ if ( object.isRenderObject ) {
66
+
67
+ this.cache.delete( this.getForRenderChainKey( object ) );
68
+
69
+ }
70
+
71
+ return super.delete( object );
72
+
73
+ }
74
+
41
75
  getForCompute( computeNode ) {
42
76
 
43
77
  const computeData = this.get( computeNode );
@@ -292,7 +326,7 @@ class Nodes extends DataMap {
292
326
  updateBefore( renderObject ) {
293
327
 
294
328
  const nodeFrame = this.getNodeFrame( renderObject );
295
- const nodeBuilder = this.getForRender( renderObject );
329
+ const nodeBuilder = renderObject.getNodeBuilder();
296
330
 
297
331
  for ( const node of nodeBuilder.updateBeforeNodes ) {
298
332
 
@@ -307,7 +341,7 @@ class Nodes extends DataMap {
307
341
  updateForRender( renderObject ) {
308
342
 
309
343
  const nodeFrame = this.getNodeFrame( renderObject );
310
- const nodeBuilder = this.getForRender( renderObject );
344
+ const nodeBuilder = renderObject.getNodeBuilder();
311
345
 
312
346
  for ( const node of nodeBuilder.updateNodes ) {
313
347