@plastic-software/three 0.179.0 → 0.180.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 (173) hide show
  1. package/build/three.cjs +166 -106
  2. package/build/three.core.js +112 -20
  3. package/build/three.core.min.js +1 -1
  4. package/build/three.module.js +55 -89
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +30 -5
  7. package/build/three.tsl.min.js +1 -1
  8. package/build/three.webgpu.js +2896 -1048
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +2896 -1048
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/jsm/Addons.js +1 -1
  13. package/examples/jsm/controls/ArcballControls.js +7 -7
  14. package/examples/jsm/controls/DragControls.js +6 -56
  15. package/examples/jsm/controls/FirstPersonControls.js +2 -2
  16. package/examples/jsm/controls/PointerLockControls.js +0 -8
  17. package/examples/jsm/exporters/GLTFExporter.js +30 -22
  18. package/examples/jsm/exporters/KTX2Exporter.js +4 -2
  19. package/examples/jsm/exporters/PLYExporter.js +1 -1
  20. package/examples/jsm/libs/ktx-parse.module.js +1 -1
  21. package/examples/jsm/lines/Line2.js +3 -3
  22. package/examples/jsm/lines/LineGeometry.js +1 -1
  23. package/examples/jsm/lines/LineSegments2.js +2 -2
  24. package/examples/jsm/lines/Wireframe.js +2 -2
  25. package/examples/jsm/lines/WireframeGeometry2.js +1 -1
  26. package/examples/jsm/lines/webgpu/LineSegments2.js +1 -1
  27. package/examples/jsm/lines/webgpu/Wireframe.js +1 -1
  28. package/examples/jsm/loaders/ColladaLoader.js +1 -1
  29. package/examples/jsm/loaders/EXRLoader.js +5 -5
  30. package/examples/jsm/loaders/GLTFLoader.js +9 -5
  31. package/examples/jsm/loaders/HDRCubeTextureLoader.js +5 -5
  32. package/examples/jsm/loaders/HDRLoader.js +486 -0
  33. package/examples/jsm/loaders/KTX2Loader.js +112 -32
  34. package/examples/jsm/loaders/RGBELoader.js +7 -473
  35. package/examples/jsm/loaders/TTFLoader.js +4 -4
  36. package/examples/jsm/loaders/UltraHDRLoader.js +1 -1
  37. package/examples/jsm/loaders/lwo/IFFParser.js +1 -1
  38. package/examples/jsm/materials/WoodNodeMaterial.js +533 -0
  39. package/examples/jsm/math/ColorSpaces.js +19 -1
  40. package/examples/jsm/math/ConvexHull.js +2 -2
  41. package/examples/jsm/math/Lut.js +2 -2
  42. package/examples/jsm/misc/MD2CharacterComplex.js +1 -1
  43. package/examples/jsm/misc/ProgressiveLightMap.js +1 -1
  44. package/examples/jsm/misc/Volume.js +1 -1
  45. package/examples/jsm/postprocessing/OutlinePass.js +1 -1
  46. package/examples/jsm/postprocessing/SSRPass.js +37 -8
  47. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +1 -1
  48. package/examples/jsm/transpiler/GLSLDecoder.js +22 -19
  49. package/examples/jsm/transpiler/TSLEncoder.js +2 -10
  50. package/examples/jsm/transpiler/WGSLEncoder.js +24 -0
  51. package/examples/jsm/tsl/display/AnamorphicNode.js +27 -4
  52. package/examples/jsm/tsl/display/BloomNode.js +3 -3
  53. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +2 -1
  54. package/examples/jsm/tsl/display/DepthOfFieldNode.js +439 -90
  55. package/examples/jsm/tsl/display/GTAONode.js +8 -0
  56. package/examples/jsm/tsl/display/GaussianBlurNode.js +47 -35
  57. package/examples/jsm/tsl/display/OutlineNode.js +2 -2
  58. package/examples/jsm/tsl/display/SSRNode.js +180 -65
  59. package/examples/jsm/tsl/display/TRAANode.js +1 -1
  60. package/examples/jsm/tsl/display/boxBlur.js +64 -0
  61. package/examples/jsm/tsl/display/hashBlur.js +15 -18
  62. package/examples/jsm/utils/BufferGeometryUtils.js +1 -1
  63. package/examples/jsm/utils/ShadowMapViewerGPU.js +12 -5
  64. package/examples/jsm/webxr/OculusHandModel.js +1 -1
  65. package/package.json +1 -1
  66. package/src/Three.Core.js +1 -0
  67. package/src/Three.TSL.js +29 -4
  68. package/src/animation/AnimationClip.js +17 -2
  69. package/src/constants.js +11 -3
  70. package/src/core/BufferGeometry.js +2 -2
  71. package/src/extras/TextureUtils.js +2 -1
  72. package/src/extras/lib/earcut.js +1 -1
  73. package/src/lights/webgpu/ProjectorLight.js +1 -1
  74. package/src/materials/Material.js +12 -0
  75. package/src/materials/MeshDistanceMaterial.js +1 -1
  76. package/src/materials/nodes/PointsNodeMaterial.js +81 -28
  77. package/src/materials/nodes/SpriteNodeMaterial.js +3 -15
  78. package/src/materials/nodes/manager/NodeMaterialObserver.js +1 -1
  79. package/src/math/ColorManagement.js +7 -1
  80. package/src/nodes/Nodes.js +3 -0
  81. package/src/nodes/TSL.js +3 -0
  82. package/src/nodes/accessors/BufferNode.js +1 -1
  83. package/src/nodes/accessors/Camera.js +133 -7
  84. package/src/nodes/accessors/ClippingNode.js +6 -5
  85. package/src/nodes/accessors/CubeTextureNode.js +2 -2
  86. package/src/nodes/accessors/InstanceNode.js +3 -1
  87. package/src/nodes/accessors/Object3DNode.js +1 -1
  88. package/src/nodes/accessors/ReferenceBaseNode.js +1 -1
  89. package/src/nodes/accessors/ReferenceNode.js +1 -1
  90. package/src/nodes/accessors/Texture3DNode.js +13 -0
  91. package/src/nodes/accessors/TextureNode.js +71 -19
  92. package/src/nodes/code/FunctionCallNode.js +19 -0
  93. package/src/nodes/code/FunctionNode.js +23 -0
  94. package/src/nodes/core/AssignNode.js +4 -3
  95. package/src/nodes/core/ContextNode.js +24 -0
  96. package/src/nodes/core/Node.js +16 -20
  97. package/src/nodes/core/NodeBuilder.js +48 -14
  98. package/src/nodes/core/NodeFrame.js +1 -1
  99. package/src/nodes/core/NodeUniform.js +1 -1
  100. package/src/nodes/core/NodeUtils.js +1 -2
  101. package/src/nodes/core/StackNode.js +29 -4
  102. package/src/nodes/core/StructNode.js +5 -5
  103. package/src/nodes/core/StructTypeNode.js +1 -0
  104. package/src/nodes/core/SubBuildNode.js +2 -2
  105. package/src/nodes/core/UniformNode.js +16 -9
  106. package/src/nodes/core/VarNode.js +0 -21
  107. package/src/nodes/display/FrontFacingNode.js +4 -8
  108. package/src/nodes/display/PassNode.js +1 -1
  109. package/src/nodes/display/ScreenNode.js +42 -13
  110. package/src/nodes/display/ViewportDepthTextureNode.js +16 -4
  111. package/src/nodes/display/ViewportSharedTextureNode.js +12 -0
  112. package/src/nodes/display/ViewportTextureNode.js +42 -12
  113. package/src/nodes/gpgpu/SubgroupFunctionNode.js +430 -0
  114. package/src/nodes/lighting/LightsNode.js +1 -1
  115. package/src/nodes/math/BitcastNode.js +156 -0
  116. package/src/nodes/math/ConditionalNode.js +18 -2
  117. package/src/nodes/math/MathNode.js +3 -15
  118. package/src/nodes/math/OperatorNode.js +4 -3
  119. package/src/nodes/tsl/TSLCore.js +432 -152
  120. package/src/nodes/utils/JoinNode.js +3 -1
  121. package/src/nodes/utils/MemberNode.js +58 -7
  122. package/src/nodes/utils/RTTNode.js +1 -1
  123. package/src/nodes/utils/ReflectorNode.js +51 -7
  124. package/src/nodes/utils/SampleNode.js +12 -2
  125. package/src/nodes/utils/SplitNode.js +11 -0
  126. package/src/nodes/utils/Timer.js +0 -47
  127. package/src/objects/BatchedMesh.js +2 -2
  128. package/src/objects/LOD.js +1 -1
  129. package/src/objects/Sprite.js +2 -2
  130. package/src/renderers/WebGLRenderer.js +0 -9
  131. package/src/renderers/common/Attributes.js +1 -1
  132. package/src/renderers/common/Backend.js +19 -1
  133. package/src/renderers/common/Bindings.js +2 -0
  134. package/src/renderers/common/ChainMap.js +1 -1
  135. package/src/renderers/common/DataMap.js +1 -1
  136. package/src/renderers/common/Pipelines.js +1 -1
  137. package/src/renderers/common/RenderContext.js +2 -2
  138. package/src/renderers/common/RenderObject.js +14 -2
  139. package/src/renderers/common/Renderer.js +39 -19
  140. package/src/renderers/common/SampledTexture.js +1 -1
  141. package/src/renderers/common/Sampler.js +25 -13
  142. package/src/renderers/common/Textures.js +34 -12
  143. package/src/renderers/common/TimestampQueryPool.js +3 -3
  144. package/src/renderers/common/XRManager.js +35 -19
  145. package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
  146. package/src/renderers/common/nodes/NodeLibrary.js +5 -5
  147. package/src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl.js +1 -1
  148. package/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl.js +1 -1
  149. package/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl.js +1 -1
  150. package/src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl.js +1 -1
  151. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +7 -15
  152. package/src/renderers/shaders/ShaderLib/depth.glsl.js +1 -1
  153. package/src/renderers/webgl/WebGLProgram.js +4 -4
  154. package/src/renderers/webgl/WebGLShadowMap.js +1 -1
  155. package/src/renderers/webgl/WebGLTextures.js +1 -0
  156. package/src/renderers/webgl/WebGLUtils.js +3 -2
  157. package/src/renderers/webgl-fallback/WebGLBackend.js +186 -135
  158. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +110 -17
  159. package/src/renderers/webgl-fallback/utils/WebGLState.js +1 -1
  160. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +52 -3
  161. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +9 -10
  162. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +3 -2
  163. package/src/renderers/webgpu/WebGPUBackend.js +35 -31
  164. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +124 -34
  165. package/src/renderers/webgpu/utils/WebGPUConstants.js +2 -2
  166. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +9 -18
  167. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +114 -25
  168. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +3 -3
  169. package/src/renderers/webxr/WebXRManager.js +39 -24
  170. package/src/textures/ExternalTexture.js +15 -4
  171. package/src/textures/Source.js +1 -1
  172. package/src/textures/VideoTexture.js +0 -3
  173. package/examples/jsm/loaders/RGBMLoader.js +0 -1148
package/src/nodes/TSL.js CHANGED
@@ -19,6 +19,7 @@ export * from './core/OutputStructNode.js';
19
19
  export * from './core/MRTNode.js';
20
20
 
21
21
  // math
22
+ export * from './math/BitcastNode.js';
22
23
  export * from './math/Hash.js';
23
24
  export * from './math/MathUtils.js';
24
25
  export * from './math/TriNoise3D.js';
@@ -55,6 +56,7 @@ export * from './accessors/UniformArrayNode.js';
55
56
  export * from './accessors/Bitangent.js';
56
57
  export * from './accessors/BufferAttributeNode.js';
57
58
  export * from './accessors/BufferNode.js';
59
+ export * from './accessors/BuiltinNode.js';
58
60
  export * from './accessors/Camera.js';
59
61
  export * from './accessors/VertexColorNode.js';
60
62
  export * from './accessors/CubeTextureNode.js';
@@ -129,6 +131,7 @@ export * from './gpgpu/ComputeBuiltinNode.js';
129
131
  export * from './gpgpu/BarrierNode.js';
130
132
  export * from './gpgpu/WorkgroupInfoNode.js';
131
133
  export * from './gpgpu/AtomicFunctionNode.js';
134
+ export * from './gpgpu/SubgroupFunctionNode.js';
132
135
 
133
136
  // lighting
134
137
  export * from './accessors/Lights.js';
@@ -93,7 +93,7 @@ export default BufferNode;
93
93
  *
94
94
  * @tsl
95
95
  * @function
96
- * @param {Array} value - Array-like buffer data.
96
+ * @param {Array<number>} value - Array-like buffer data.
97
97
  * @param {string} type - The data type of a buffer element.
98
98
  * @param {number} count - The count of buffer elements.
99
99
  * @returns {BufferNode}
@@ -1,9 +1,10 @@
1
1
  import { uniform } from '../core/UniformNode.js';
2
2
  import { renderGroup, sharedUniformGroup } from '../core/UniformGroupNode.js';
3
3
  import { Vector3 } from '../../math/Vector3.js';
4
- import { Fn } from '../tsl/TSLBase.js';
4
+ import { Fn, vec4 } from '../tsl/TSLBase.js';
5
5
  import { uniformArray } from './UniformArrayNode.js';
6
6
  import { builtin } from './BuiltinNode.js';
7
+ import { screenSize } from '../display/ScreenNode.js';
7
8
 
8
9
  /**
9
10
  * TSL object that represents the current `index` value of the camera if used ArrayCamera.
@@ -51,7 +52,7 @@ export const cameraProjectionMatrix = /*@__PURE__*/ ( Fn( ( { camera } ) => {
51
52
 
52
53
  const cameraProjectionMatrices = uniformArray( matrices ).setGroup( renderGroup ).setName( 'cameraProjectionMatrices' );
53
54
 
54
- cameraProjectionMatrix = cameraProjectionMatrices.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toVar( 'cameraProjectionMatrix' );
55
+ cameraProjectionMatrix = cameraProjectionMatrices.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toConst( 'cameraProjectionMatrix' );
55
56
 
56
57
  } else {
57
58
 
@@ -85,7 +86,7 @@ export const cameraProjectionMatrixInverse = /*@__PURE__*/ ( Fn( ( { camera } )
85
86
 
86
87
  const cameraProjectionMatricesInverse = uniformArray( matrices ).setGroup( renderGroup ).setName( 'cameraProjectionMatricesInverse' );
87
88
 
88
- cameraProjectionMatrixInverse = cameraProjectionMatricesInverse.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toVar( 'cameraProjectionMatrixInverse' );
89
+ cameraProjectionMatrixInverse = cameraProjectionMatricesInverse.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toConst( 'cameraProjectionMatrixInverse' );
89
90
 
90
91
  } else {
91
92
 
@@ -119,7 +120,7 @@ export const cameraViewMatrix = /*@__PURE__*/ ( Fn( ( { camera } ) => {
119
120
 
120
121
  const cameraViewMatrices = uniformArray( matrices ).setGroup( renderGroup ).setName( 'cameraViewMatrices' );
121
122
 
122
- cameraViewMatrix = cameraViewMatrices.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toVar( 'cameraViewMatrix' );
123
+ cameraViewMatrix = cameraViewMatrices.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toConst( 'cameraViewMatrix' );
123
124
 
124
125
  } else {
125
126
 
@@ -137,7 +138,33 @@ export const cameraViewMatrix = /*@__PURE__*/ ( Fn( ( { camera } ) => {
137
138
  * @tsl
138
139
  * @type {UniformNode<mat4>}
139
140
  */
140
- export const cameraWorldMatrix = /*@__PURE__*/ uniform( 'mat4' ).setName( 'cameraWorldMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorld );
141
+ export const cameraWorldMatrix = /*@__PURE__*/ ( Fn( ( { camera } ) => {
142
+
143
+ let cameraWorldMatrix;
144
+
145
+ if ( camera.isArrayCamera && camera.cameras.length > 0 ) {
146
+
147
+ const matrices = [];
148
+
149
+ for ( const subCamera of camera.cameras ) {
150
+
151
+ matrices.push( subCamera.matrixWorld );
152
+
153
+ }
154
+
155
+ const cameraWorldMatrices = uniformArray( matrices ).setGroup( renderGroup ).setName( 'cameraWorldMatrices' );
156
+
157
+ cameraWorldMatrix = cameraWorldMatrices.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toConst( 'cameraWorldMatrix' );
158
+
159
+ } else {
160
+
161
+ cameraWorldMatrix = uniform( 'mat4' ).setName( 'cameraWorldMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorld );
162
+
163
+ }
164
+
165
+ return cameraWorldMatrix;
166
+
167
+ } ).once() )();
141
168
 
142
169
  /**
143
170
  * TSL object that represents the normal matrix of the camera used for the current render.
@@ -145,7 +172,33 @@ export const cameraWorldMatrix = /*@__PURE__*/ uniform( 'mat4' ).setName( 'camer
145
172
  * @tsl
146
173
  * @type {UniformNode<mat3>}
147
174
  */
148
- export const cameraNormalMatrix = /*@__PURE__*/ uniform( 'mat3' ).setName( 'cameraNormalMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.normalMatrix );
175
+ export const cameraNormalMatrix = /*@__PURE__*/ ( Fn( ( { camera } ) => {
176
+
177
+ let cameraNormalMatrix;
178
+
179
+ if ( camera.isArrayCamera && camera.cameras.length > 0 ) {
180
+
181
+ const matrices = [];
182
+
183
+ for ( const subCamera of camera.cameras ) {
184
+
185
+ matrices.push( subCamera.normalMatrix );
186
+
187
+ }
188
+
189
+ const cameraNormalMatrices = uniformArray( matrices ).setGroup( renderGroup ).setName( 'cameraNormalMatrices' );
190
+
191
+ cameraNormalMatrix = cameraNormalMatrices.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toConst( 'cameraNormalMatrix' );
192
+
193
+ } else {
194
+
195
+ cameraNormalMatrix = uniform( 'mat3' ).setName( 'cameraNormalMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.normalMatrix );
196
+
197
+ }
198
+
199
+ return cameraNormalMatrix;
200
+
201
+ } ).once() )();
149
202
 
150
203
  /**
151
204
  * TSL object that represents the position in world space of the camera used for the current render.
@@ -153,4 +206,77 @@ export const cameraNormalMatrix = /*@__PURE__*/ uniform( 'mat3' ).setName( 'came
153
206
  * @tsl
154
207
  * @type {UniformNode<vec3>}
155
208
  */
156
- export const cameraPosition = /*@__PURE__*/ uniform( new Vector3() ).setName( 'cameraPosition' ).setGroup( renderGroup ).onRenderUpdate( ( { camera }, self ) => self.value.setFromMatrixPosition( camera.matrixWorld ) );
209
+ export const cameraPosition = /*@__PURE__*/ ( Fn( ( { camera } ) => {
210
+
211
+ let cameraPosition;
212
+
213
+ if ( camera.isArrayCamera && camera.cameras.length > 0 ) {
214
+
215
+ const positions = [];
216
+
217
+ for ( let i = 0, l = camera.cameras.length; i < l; i ++ ) {
218
+
219
+ positions.push( new Vector3() );
220
+
221
+ }
222
+
223
+ const cameraPositions = uniformArray( positions ).setGroup( renderGroup ).setName( 'cameraPositions' ).onRenderUpdate( ( { camera }, self ) => {
224
+
225
+ const subCameras = camera.cameras;
226
+ const array = self.array;
227
+
228
+ for ( let i = 0, l = subCameras.length; i < l; i ++ ) {
229
+
230
+ array[ i ].setFromMatrixPosition( subCameras[ i ].matrixWorld );
231
+
232
+ }
233
+
234
+ } );
235
+
236
+ cameraPosition = cameraPositions.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toConst( 'cameraPosition' );
237
+
238
+ } else {
239
+
240
+ cameraPosition = uniform( new Vector3() ).setName( 'cameraPosition' ).setGroup( renderGroup ).onRenderUpdate( ( { camera }, self ) => self.value.setFromMatrixPosition( camera.matrixWorld ) );
241
+
242
+ }
243
+
244
+ return cameraPosition;
245
+
246
+ } ).once() )();
247
+
248
+
249
+ /**
250
+ * TSL object that represents the viewport of the camera used for the current render.
251
+ *
252
+ * @tsl
253
+ * @type {UniformNode<vec4>}
254
+ */
255
+ export const cameraViewport = /*@__PURE__*/ ( Fn( ( { camera } ) => {
256
+
257
+ let cameraViewport;
258
+
259
+ if ( camera.isArrayCamera && camera.cameras.length > 0 ) {
260
+
261
+ const viewports = [];
262
+
263
+ for ( const subCamera of camera.cameras ) {
264
+
265
+ viewports.push( subCamera.viewport );
266
+
267
+ }
268
+
269
+ const cameraViewports = uniformArray( viewports, 'vec4' ).setGroup( renderGroup ).setName( 'cameraViewports' );
270
+
271
+ cameraViewport = cameraViewports.element( cameraIndex ).toConst( 'cameraViewport' );
272
+
273
+ } else {
274
+
275
+ // Fallback for single camera
276
+ cameraViewport = vec4( 0, 0, screenSize.x, screenSize.y ).toConst( 'cameraViewport' );
277
+
278
+ }
279
+
280
+ return cameraViewport;
281
+
282
+ } ).once() )();
@@ -7,6 +7,7 @@ import { Loop } from '../utils/LoopNode.js';
7
7
  import { smoothstep } from '../math/MathNode.js';
8
8
  import { uniformArray } from './UniformArrayNode.js';
9
9
  import { builtin } from './BuiltinNode.js';
10
+ import { renderGroup } from '../core/UniformGroupNode.js';
10
11
 
11
12
  /**
12
13
  * This node is used in {@link NodeMaterial} to setup the clipping
@@ -94,7 +95,7 @@ class ClippingNode extends Node {
94
95
 
95
96
  if ( this.hardwareClipping === false && numUnionPlanes > 0 ) {
96
97
 
97
- const clippingPlanes = uniformArray( unionPlanes );
98
+ const clippingPlanes = uniformArray( unionPlanes ).setGroup( renderGroup );
98
99
 
99
100
  Loop( numUnionPlanes, ( { i } ) => {
100
101
 
@@ -113,7 +114,7 @@ class ClippingNode extends Node {
113
114
 
114
115
  if ( numIntersectionPlanes > 0 ) {
115
116
 
116
- const clippingPlanes = uniformArray( intersectionPlanes );
117
+ const clippingPlanes = uniformArray( intersectionPlanes ).setGroup( renderGroup );
117
118
  const intersectionClipOpacity = float( 1 ).toVar( 'intersectionClipOpacity' );
118
119
 
119
120
  Loop( numIntersectionPlanes, ( { i } ) => {
@@ -154,7 +155,7 @@ class ClippingNode extends Node {
154
155
 
155
156
  if ( this.hardwareClipping === false && numUnionPlanes > 0 ) {
156
157
 
157
- const clippingPlanes = uniformArray( unionPlanes );
158
+ const clippingPlanes = uniformArray( unionPlanes ).setGroup( renderGroup );
158
159
 
159
160
  Loop( numUnionPlanes, ( { i } ) => {
160
161
 
@@ -169,7 +170,7 @@ class ClippingNode extends Node {
169
170
 
170
171
  if ( numIntersectionPlanes > 0 ) {
171
172
 
172
- const clippingPlanes = uniformArray( intersectionPlanes );
173
+ const clippingPlanes = uniformArray( intersectionPlanes ).setGroup( renderGroup );
173
174
  const clipped = bool( true ).toVar( 'clipped' );
174
175
 
175
176
  Loop( numIntersectionPlanes, ( { i } ) => {
@@ -202,7 +203,7 @@ class ClippingNode extends Node {
202
203
 
203
204
  return Fn( () => {
204
205
 
205
- const clippingPlanes = uniformArray( unionPlanes );
206
+ const clippingPlanes = uniformArray( unionPlanes ).setGroup( renderGroup );
206
207
  const hw_clip_distances = builtin( builder.getClipDistance() );
207
208
 
208
209
  Loop( numUnionPlanes, ( { i } ) => {
@@ -149,7 +149,7 @@ export const cubeTextureBase = /*@__PURE__*/ nodeProxy( CubeTextureNode ).setPar
149
149
  *
150
150
  * @tsl
151
151
  * @function
152
- * @param {?CubeTexture|CubeTextureNode} [value=EmptyTexture] - The cube texture.
152
+ * @param {?(CubeTexture|CubeTextureNode)} [value=EmptyTexture] - The cube texture.
153
153
  * @param {?Node<vec3>} [uvNode=null] - The uv node.
154
154
  * @param {?Node<int>} [levelNode=null] - The level node.
155
155
  * @param {?Node<float>} [biasNode=null] - The bias node.
@@ -162,7 +162,7 @@ export const cubeTexture = ( value = EmptyTexture, uvNode = null, levelNode = nu
162
162
  if ( value && value.isCubeTextureNode === true ) {
163
163
 
164
164
  textureNode = nodeObject( value.clone() );
165
- textureNode.referenceNode = value.getSelf(); // Ensure the reference is set to the original node
165
+ textureNode.referenceNode = value; // Ensure the reference is set to the original node
166
166
 
167
167
  if ( uvNode !== null ) textureNode.uvNode = nodeObject( uvNode );
168
168
  if ( levelNode !== null ) textureNode.levelNode = nodeObject( levelNode );
@@ -109,7 +109,9 @@ class InstanceNode extends Node {
109
109
  */
110
110
  setup( builder ) {
111
111
 
112
- const { count, instanceMatrix, instanceColor } = this;
112
+ const { instanceMatrix, instanceColor } = this;
113
+
114
+ const { count } = instanceMatrix;
113
115
 
114
116
  let { instanceMatrixNode, instanceColorNode } = this;
115
117
 
@@ -73,7 +73,7 @@ class Object3DNode extends Node {
73
73
  /**
74
74
  * Overwritten since the node type is inferred from the scope.
75
75
  *
76
- * @return {string} The node type.
76
+ * @return {('mat4'|'vec3'|'float')} The node type.
77
77
  */
78
78
  getNodeType() {
79
79
 
@@ -211,7 +211,7 @@ class ReferenceBaseNode extends Node {
211
211
  */
212
212
  setNodeType( uniformType ) {
213
213
 
214
- const node = uniform( null, uniformType ).getSelf();
214
+ const node = uniform( null, uniformType );
215
215
 
216
216
  if ( this.group !== null ) {
217
217
 
@@ -284,7 +284,7 @@ class ReferenceNode extends Node {
284
284
 
285
285
  if ( this.name !== null ) node.setName( this.name );
286
286
 
287
- this.node = node.getSelf();
287
+ this.node = node;
288
288
 
289
289
  }
290
290
 
@@ -157,6 +157,19 @@ class Texture3DNode extends TextureNode {
157
157
 
158
158
  }
159
159
 
160
+ /**
161
+ * Generates the offset code snippet.
162
+ *
163
+ * @param {NodeBuilder} builder - The current node builder.
164
+ * @param {Node} offsetNode - The offset node to generate code for.
165
+ * @return {string} The generated code snippet.
166
+ */
167
+ generateOffset( builder, offsetNode ) {
168
+
169
+ return offsetNode.build( builder, 'ivec3' );
170
+
171
+ }
172
+
160
173
  /**
161
174
  * TODO.
162
175
  *
@@ -95,6 +95,15 @@ class TextureNode extends UniformNode {
95
95
  */
96
96
  this.gradNode = null;
97
97
 
98
+ /**
99
+ * Represents the optional texel offset applied to the unnormalized texture
100
+ * coordinate before sampling the texture.
101
+ *
102
+ * @type {?Node<ivec2|ivec3>}
103
+ * @default null
104
+ */
105
+ this.offsetNode = null;
106
+
98
107
  /**
99
108
  * Whether texture values should be sampled or fetched.
100
109
  *
@@ -364,6 +373,7 @@ class TextureNode extends UniformNode {
364
373
  properties.compareNode = this.compareNode;
365
374
  properties.gradNode = this.gradNode;
366
375
  properties.depthNode = this.depthNode;
376
+ properties.offsetNode = this.offsetNode;
367
377
 
368
378
  }
369
379
 
@@ -380,6 +390,19 @@ class TextureNode extends UniformNode {
380
390
 
381
391
  }
382
392
 
393
+ /**
394
+ * Generates the offset code snippet.
395
+ *
396
+ * @param {NodeBuilder} builder - The current node builder.
397
+ * @param {Node} offsetNode - The offset node to generate code for.
398
+ * @return {string} The generated code snippet.
399
+ */
400
+ generateOffset( builder, offsetNode ) {
401
+
402
+ return offsetNode.build( builder, 'ivec2' );
403
+
404
+ }
405
+
383
406
  /**
384
407
  * Generates the snippet for the texture sampling.
385
408
  *
@@ -391,9 +414,10 @@ class TextureNode extends UniformNode {
391
414
  * @param {?string} depthSnippet - The depth snippet.
392
415
  * @param {?string} compareSnippet - The compare snippet.
393
416
  * @param {?Array<string>} gradSnippet - The grad snippet.
417
+ * @param {?string} offsetSnippet - The offset snippet.
394
418
  * @return {string} The generated code snippet.
395
419
  */
396
- generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet ) {
420
+ generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet, offsetSnippet ) {
397
421
 
398
422
  const texture = this.value;
399
423
 
@@ -401,27 +425,27 @@ class TextureNode extends UniformNode {
401
425
 
402
426
  if ( levelSnippet ) {
403
427
 
404
- snippet = builder.generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet );
428
+ snippet = builder.generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, offsetSnippet );
405
429
 
406
430
  } else if ( biasSnippet ) {
407
431
 
408
- snippet = builder.generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet );
432
+ snippet = builder.generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet, offsetSnippet );
409
433
 
410
434
  } else if ( gradSnippet ) {
411
435
 
412
- snippet = builder.generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet );
436
+ snippet = builder.generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet, offsetSnippet );
413
437
 
414
438
  } else if ( compareSnippet ) {
415
439
 
416
- snippet = builder.generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet );
440
+ snippet = builder.generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, offsetSnippet );
417
441
 
418
442
  } else if ( this.sampler === false ) {
419
443
 
420
- snippet = builder.generateTextureLoad( texture, textureProperty, uvSnippet, depthSnippet );
444
+ snippet = builder.generateTextureLoad( texture, textureProperty, uvSnippet, depthSnippet, offsetSnippet );
421
445
 
422
446
  } else {
423
447
 
424
- snippet = builder.generateTexture( texture, textureProperty, uvSnippet, depthSnippet );
448
+ snippet = builder.generateTexture( texture, textureProperty, uvSnippet, depthSnippet, offsetSnippet );
425
449
 
426
450
  }
427
451
 
@@ -459,7 +483,7 @@ class TextureNode extends UniformNode {
459
483
 
460
484
  if ( propertyName === undefined ) {
461
485
 
462
- const { uvNode, levelNode, biasNode, compareNode, depthNode, gradNode } = properties;
486
+ const { uvNode, levelNode, biasNode, compareNode, depthNode, gradNode, offsetNode } = properties;
463
487
 
464
488
  const uvSnippet = this.generateUV( builder, uvNode );
465
489
  const levelSnippet = levelNode ? levelNode.build( builder, 'float' ) : null;
@@ -467,12 +491,13 @@ class TextureNode extends UniformNode {
467
491
  const depthSnippet = depthNode ? depthNode.build( builder, 'int' ) : null;
468
492
  const compareSnippet = compareNode ? compareNode.build( builder, 'float' ) : null;
469
493
  const gradSnippet = gradNode ? [ gradNode[ 0 ].build( builder, 'vec2' ), gradNode[ 1 ].build( builder, 'vec2' ) ] : null;
494
+ const offsetSnippet = offsetNode ? this.generateOffset( builder, offsetNode ) : null;
470
495
 
471
496
  const nodeVar = builder.getVarFromNode( this );
472
497
 
473
498
  propertyName = builder.getPropertyName( nodeVar );
474
499
 
475
- const snippet = this.generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet );
500
+ const snippet = this.generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet, offsetSnippet );
476
501
 
477
502
  builder.addLineFlowCode( `${propertyName} = ${snippet}`, this );
478
503
 
@@ -548,7 +573,7 @@ class TextureNode extends UniformNode {
548
573
 
549
574
  const textureNode = this.clone();
550
575
  textureNode.uvNode = nodeObject( uvNode );
551
- textureNode.referenceNode = this.getSelf();
576
+ textureNode.referenceNode = this.getBase();
552
577
 
553
578
  return nodeObject( textureNode );
554
579
 
@@ -576,7 +601,7 @@ class TextureNode extends UniformNode {
576
601
 
577
602
  const textureNode = this.clone();
578
603
  textureNode.biasNode = nodeObject( amountNode ).mul( maxMipLevel( textureNode ) );
579
- textureNode.referenceNode = this.getSelf();
604
+ textureNode.referenceNode = this.getBase();
580
605
 
581
606
  const map = textureNode.value;
582
607
 
@@ -602,7 +627,7 @@ class TextureNode extends UniformNode {
602
627
 
603
628
  const textureNode = this.clone();
604
629
  textureNode.levelNode = nodeObject( levelNode );
605
- textureNode.referenceNode = this.getSelf();
630
+ textureNode.referenceNode = this.getBase();
606
631
 
607
632
  return nodeObject( textureNode );
608
633
 
@@ -630,12 +655,22 @@ class TextureNode extends UniformNode {
630
655
 
631
656
  const textureNode = this.clone();
632
657
  textureNode.biasNode = nodeObject( biasNode );
633
- textureNode.referenceNode = this.getSelf();
658
+ textureNode.referenceNode = this.getBase();
634
659
 
635
660
  return nodeObject( textureNode );
636
661
 
637
662
  }
638
663
 
664
+ /**
665
+ * Returns the base texture of this node.
666
+ * @return {TextureNode} The base texture node.
667
+ */
668
+ getBase() {
669
+
670
+ return this.referenceNode ? this.referenceNode.getBase() : this;
671
+
672
+ }
673
+
639
674
  /**
640
675
  * Samples the texture by executing a compare operation.
641
676
  *
@@ -646,7 +681,7 @@ class TextureNode extends UniformNode {
646
681
 
647
682
  const textureNode = this.clone();
648
683
  textureNode.compareNode = nodeObject( compareNode );
649
- textureNode.referenceNode = this.getSelf();
684
+ textureNode.referenceNode = this.getBase();
650
685
 
651
686
  return nodeObject( textureNode );
652
687
 
@@ -663,7 +698,7 @@ class TextureNode extends UniformNode {
663
698
 
664
699
  const textureNode = this.clone();
665
700
  textureNode.gradNode = [ nodeObject( gradNodeX ), nodeObject( gradNodeY ) ];
666
- textureNode.referenceNode = this.getSelf();
701
+ textureNode.referenceNode = this.getBase();
667
702
 
668
703
  return nodeObject( textureNode );
669
704
 
@@ -679,7 +714,23 @@ class TextureNode extends UniformNode {
679
714
 
680
715
  const textureNode = this.clone();
681
716
  textureNode.depthNode = nodeObject( depthNode );
682
- textureNode.referenceNode = this.getSelf();
717
+ textureNode.referenceNode = this.getBase();
718
+
719
+ return nodeObject( textureNode );
720
+
721
+ }
722
+
723
+ /**
724
+ * Samples the texture by defining an offset node.
725
+ *
726
+ * @param {Node<ivec2>} offsetNode - The offset node.
727
+ * @return {TextureNode} A texture node representing the texture sample.
728
+ */
729
+ offset( offsetNode ) {
730
+
731
+ const textureNode = this.clone();
732
+ textureNode.offsetNode = nodeObject( offsetNode );
733
+ textureNode.referenceNode = this.getBase();
683
734
 
684
735
  return nodeObject( textureNode );
685
736
 
@@ -739,6 +790,7 @@ class TextureNode extends UniformNode {
739
790
  newNode.depthNode = this.depthNode;
740
791
  newNode.compareNode = this.compareNode;
741
792
  newNode.gradNode = this.gradNode;
793
+ newNode.offsetNode = this.offsetNode;
742
794
 
743
795
  return newNode;
744
796
 
@@ -766,7 +818,7 @@ const textureBase = /*@__PURE__*/ nodeProxy( TextureNode ).setParameterLength( 1
766
818
  *
767
819
  * @tsl
768
820
  * @function
769
- * @param {?Texture|TextureNode} [value=EmptyTexture] - The texture.
821
+ * @param {?(Texture|TextureNode)} [value=EmptyTexture] - The texture.
770
822
  * @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
771
823
  * @param {?Node<int>} [levelNode=null] - The level node.
772
824
  * @param {?Node<float>} [biasNode=null] - The bias node.
@@ -779,7 +831,7 @@ export const texture = ( value = EmptyTexture, uvNode = null, levelNode = null,
779
831
  if ( value && value.isTextureNode === true ) {
780
832
 
781
833
  textureNode = nodeObject( value.clone() );
782
- textureNode.referenceNode = value.getSelf(); // Ensure the reference is set to the original node
834
+ textureNode.referenceNode = value.getBase(); // Ensure the reference is set to the original node
783
835
 
784
836
  if ( uvNode !== null ) textureNode.uvNode = nodeObject( uvNode );
785
837
  if ( levelNode !== null ) textureNode.levelNode = nodeObject( levelNode );
@@ -810,7 +862,7 @@ export const uniformTexture = ( value = EmptyTexture ) => texture( value );
810
862
  *
811
863
  * @tsl
812
864
  * @function
813
- * @param {?Texture|TextureNode} [value=EmptyTexture] - The texture.
865
+ * @param {?(Texture|TextureNode)} [value=EmptyTexture] - The texture.
814
866
  * @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
815
867
  * @param {?Node<int>} [levelNode=null] - The level node.
816
868
  * @param {?Node<float>} [biasNode=null] - The bias node.
@@ -69,12 +69,31 @@ class FunctionCallNode extends TempNode {
69
69
 
70
70
  }
71
71
 
72
+ /**
73
+ * Returns the type of this function call node.
74
+ *
75
+ * @param {NodeBuilder} builder - The current node builder.
76
+ * @returns {string} The type of this node.
77
+ */
72
78
  getNodeType( builder ) {
73
79
 
74
80
  return this.functionNode.getNodeType( builder );
75
81
 
76
82
  }
77
83
 
84
+ /**
85
+ * Returns the function node of this function call node.
86
+ *
87
+ * @param {NodeBuilder} builder - The current node builder.
88
+ * @param {string} [name] - The name of the member.
89
+ * @returns {string} The type of the member.
90
+ */
91
+ getMemberType( builder, name ) {
92
+
93
+ return this.functionNode.getMemberType( builder, name );
94
+
95
+ }
96
+
78
97
  generate( builder ) {
79
98
 
80
99
  const params = [];
@@ -48,12 +48,35 @@ class FunctionNode extends CodeNode {
48
48
 
49
49
  }
50
50
 
51
+ /**
52
+ * Returns the type of this function node.
53
+ *
54
+ * @param {NodeBuilder} builder - The current node builder.
55
+ * @return {string} The type.
56
+ */
51
57
  getNodeType( builder ) {
52
58
 
53
59
  return this.getNodeFunction( builder ).type;
54
60
 
55
61
  }
56
62
 
63
+ /**
64
+ * Returns the type of a member of this function node.
65
+ *
66
+ * @param {NodeBuilder} builder - The current node builder.
67
+ * @param {string} name - The name of the member.
68
+ * @return {string} The type of the member.
69
+ */
70
+ getMemberType( builder, name ) {
71
+
72
+ const type = this.getNodeType( builder );
73
+
74
+ const structType = builder.getStructTypeNode( type );
75
+
76
+ return structType.getMemberType( builder, name );
77
+
78
+ }
79
+
57
80
  /**
58
81
  * Returns the inputs of this function node.
59
82
  *
@@ -97,7 +97,9 @@ class AssignNode extends TempNode {
97
97
 
98
98
  const { targetNode, sourceNode } = this;
99
99
 
100
- const targetProperties = builder.getNodeProperties( targetNode );
100
+ const scope = targetNode.getScope();
101
+
102
+ const targetProperties = builder.getNodeProperties( scope );
101
103
  targetProperties.assign = true;
102
104
 
103
105
  const properties = builder.getNodeProperties( this );
@@ -112,11 +114,10 @@ class AssignNode extends TempNode {
112
114
 
113
115
  const needsSplitAssign = this.needsSplitAssign( builder );
114
116
 
117
+ const target = targetNode.build( builder );
115
118
  const targetType = targetNode.getNodeType( builder );
116
119
 
117
- const target = targetNode.build( builder );
118
120
  const source = sourceNode.build( builder, targetType );
119
-
120
121
  const sourceType = sourceNode.getNodeType( builder );
121
122
 
122
123
  const nodeData = builder.getDataFromNode( this );