super-three 0.170.0 → 0.170.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/build/three.cjs +24410 -24422
  2. package/build/three.core.js +37002 -0
  3. package/build/three.core.min.js +6 -0
  4. package/build/three.module.js +10573 -47578
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +533 -0
  7. package/build/three.tsl.min.js +6 -0
  8. package/build/three.webgpu.js +2907 -37975
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +2914 -37959
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/jsm/capabilities/WebGPU.js +1 -10
  13. package/examples/jsm/controls/ArcballControls.js +25 -21
  14. package/examples/jsm/controls/OrbitControls.js +41 -9
  15. package/examples/jsm/controls/PointerLockControls.js +2 -5
  16. package/examples/jsm/csm/CSMShadowNode.js +7 -5
  17. package/examples/jsm/geometries/DecalGeometry.js +5 -1
  18. package/examples/jsm/lighting/TiledLighting.js +1 -1
  19. package/examples/jsm/lines/LineGeometry.js +25 -0
  20. package/examples/jsm/lines/LineMaterial.js +1 -7
  21. package/examples/jsm/lines/webgpu/Line2.js +2 -1
  22. package/examples/jsm/lines/webgpu/LineSegments2.js +2 -1
  23. package/examples/jsm/lines/webgpu/Wireframe.js +2 -1
  24. package/examples/jsm/loaders/KTX2Loader.js +3 -0
  25. package/examples/jsm/loaders/MMDLoader.js +2 -6
  26. package/examples/jsm/loaders/MaterialXLoader.js +2 -2
  27. package/examples/jsm/materials/MeshGouraudMaterial.js +2 -6
  28. package/examples/jsm/misc/ProgressiveLightMapGPU.js +2 -2
  29. package/examples/jsm/objects/InstancedPoints.js +2 -4
  30. package/examples/jsm/objects/LensflareMesh.js +4 -2
  31. package/examples/jsm/objects/SkyMesh.js +5 -3
  32. package/examples/jsm/objects/Water2Mesh.js +7 -3
  33. package/examples/jsm/objects/WaterMesh.js +5 -3
  34. package/examples/jsm/transpiler/AST.js +2 -2
  35. package/examples/jsm/transpiler/GLSLDecoder.js +57 -25
  36. package/examples/jsm/transpiler/TSLEncoder.js +11 -6
  37. package/examples/jsm/tsl/display/AfterImageNode.js +3 -3
  38. package/examples/jsm/tsl/display/AnaglyphPassNode.js +2 -2
  39. package/examples/jsm/tsl/display/AnamorphicNode.js +2 -2
  40. package/examples/jsm/tsl/display/BloomNode.js +3 -3
  41. package/examples/jsm/tsl/display/DenoiseNode.js +48 -12
  42. package/examples/jsm/tsl/display/DepthOfFieldNode.js +3 -2
  43. package/examples/jsm/tsl/display/DotScreenNode.js +2 -2
  44. package/examples/jsm/tsl/display/FXAANode.js +3 -3
  45. package/examples/jsm/tsl/display/FilmNode.js +3 -2
  46. package/examples/jsm/tsl/display/GTAONode.js +62 -27
  47. package/examples/jsm/tsl/display/GaussianBlurNode.js +6 -8
  48. package/examples/jsm/tsl/display/LensflareNode.js +3 -3
  49. package/examples/jsm/tsl/display/Lut3DNode.js +3 -2
  50. package/examples/jsm/tsl/display/OutlineNode.js +2 -2
  51. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +2 -1
  52. package/examples/jsm/tsl/display/PixelationPassNode.js +4 -4
  53. package/examples/jsm/tsl/display/RGBShiftNode.js +2 -1
  54. package/examples/jsm/tsl/display/SMAANode.js +3 -3
  55. package/examples/jsm/tsl/display/SSAAPassNode.js +2 -2
  56. package/examples/jsm/tsl/display/SSRNode.js +31 -8
  57. package/examples/jsm/tsl/display/SobelOperatorNode.js +3 -3
  58. package/examples/jsm/tsl/display/StereoCompositePassNode.js +4 -4
  59. package/examples/jsm/tsl/display/StereoPassNode.js +2 -2
  60. package/examples/jsm/tsl/display/TRAAPassNode.js +2 -2
  61. package/examples/jsm/tsl/display/TransitionNode.js +3 -2
  62. package/examples/jsm/tsl/lighting/TiledLightsNode.js +6 -9
  63. package/examples/jsm/utils/SceneOptimizer.js +410 -0
  64. package/examples/jsm/utils/UVsDebug.js +1 -1
  65. package/package.json +3 -3
  66. package/src/Three.Core.js +178 -0
  67. package/src/Three.TSL.js +526 -0
  68. package/src/Three.WebGPU.Nodes.js +5 -186
  69. package/src/Three.WebGPU.js +4 -186
  70. package/src/Three.js +1 -177
  71. package/src/animation/AnimationClip.js +2 -2
  72. package/src/animation/AnimationObjectGroup.js +2 -2
  73. package/src/audio/Audio.js +38 -0
  74. package/src/cameras/PerspectiveCamera.js +6 -6
  75. package/src/cameras/StereoCamera.js +2 -2
  76. package/src/constants.js +1 -1
  77. package/src/core/BufferGeometry.js +5 -3
  78. package/src/core/InterleavedBuffer.js +4 -4
  79. package/src/core/Object3D.js +2 -2
  80. package/src/extras/core/Curve.js +3 -3
  81. package/src/extras/core/Shape.js +2 -2
  82. package/src/geometries/EdgesGeometry.js +2 -2
  83. package/src/geometries/LatheGeometry.js +2 -2
  84. package/src/lights/SpotLightShadow.js +2 -2
  85. package/src/materials/LineBasicMaterial.js +2 -6
  86. package/src/materials/LineDashedMaterial.js +1 -6
  87. package/src/materials/Material.js +3 -16
  88. package/src/materials/MeshBasicMaterial.js +2 -6
  89. package/src/materials/MeshDepthMaterial.js +2 -6
  90. package/src/materials/MeshDistanceMaterial.js +2 -6
  91. package/src/materials/MeshLambertMaterial.js +2 -6
  92. package/src/materials/MeshMatcapMaterial.js +2 -6
  93. package/src/materials/MeshNormalMaterial.js +2 -6
  94. package/src/materials/MeshPhongMaterial.js +3 -7
  95. package/src/materials/MeshPhysicalMaterial.js +4 -8
  96. package/src/materials/MeshStandardMaterial.js +2 -6
  97. package/src/materials/MeshToonMaterial.js +2 -6
  98. package/src/materials/PointsMaterial.js +2 -6
  99. package/src/materials/RawShaderMaterial.js +2 -6
  100. package/src/materials/ShaderMaterial.js +2 -6
  101. package/src/materials/ShadowMaterial.js +2 -6
  102. package/src/materials/SpriteMaterial.js +2 -6
  103. package/src/materials/nodes/Line2NodeMaterial.js +32 -13
  104. package/src/materials/nodes/LineDashedNodeMaterial.js +4 -2
  105. package/src/materials/nodes/NodeMaterial.js +64 -16
  106. package/src/materials/nodes/manager/NodeMaterialObserver.js +13 -10
  107. package/src/math/ColorManagement.js +130 -122
  108. package/src/math/Line3.js +2 -2
  109. package/src/math/Quaternion.js +2 -2
  110. package/src/math/Spherical.js +3 -3
  111. package/src/math/Vector2.js +7 -7
  112. package/src/math/Vector3.js +9 -9
  113. package/src/math/Vector4.js +11 -9
  114. package/src/nodes/Nodes.js +1 -0
  115. package/src/nodes/TSL.js +3 -1
  116. package/src/nodes/accessors/Arrays.js +27 -0
  117. package/src/nodes/accessors/BuiltinNode.js +26 -0
  118. package/src/nodes/accessors/ClippingNode.js +76 -42
  119. package/src/nodes/accessors/InstanceNode.js +17 -20
  120. package/src/nodes/accessors/InstancedMeshNode.js +26 -0
  121. package/src/nodes/accessors/Lights.js +32 -0
  122. package/src/nodes/accessors/StorageBufferNode.js +29 -9
  123. package/src/nodes/accessors/StorageTextureNode.js +10 -4
  124. package/src/nodes/accessors/TextureNode.js +1 -1
  125. package/src/nodes/core/NodeBuilder.js +2 -9
  126. package/src/nodes/core/NodeUtils.js +28 -0
  127. package/src/nodes/core/constants.js +6 -0
  128. package/src/nodes/display/BlendModes.js +99 -0
  129. package/src/nodes/display/ToonOutlinePassNode.js +3 -3
  130. package/src/nodes/display/ViewportDepthNode.js +21 -6
  131. package/src/nodes/functions/material/getAlphaHashThreshold.js +13 -7
  132. package/src/nodes/functions/material/getParallaxCorrectNormal.js +1 -1
  133. package/src/nodes/lighting/AnalyticLightNode.js +12 -4
  134. package/src/nodes/lighting/PointLightNode.js +10 -1
  135. package/src/nodes/lighting/PointShadowNode.js +254 -0
  136. package/src/nodes/lighting/ShadowNode.js +176 -67
  137. package/src/nodes/lighting/SpotLightNode.js +14 -2
  138. package/src/nodes/utils/RTTNode.js +9 -1
  139. package/src/nodes/utils/StorageArrayElementNode.js +2 -2
  140. package/src/objects/BatchedMesh.js +54 -95
  141. package/src/objects/ClippingGroup.js +19 -0
  142. package/src/objects/Skeleton.js +2 -2
  143. package/src/renderers/WebGLRenderer.js +94 -23
  144. package/src/renderers/common/Animation.js +23 -11
  145. package/src/renderers/common/Background.js +1 -1
  146. package/src/renderers/common/Bindings.js +20 -4
  147. package/src/renderers/common/ClippingContext.js +77 -85
  148. package/src/renderers/common/RenderList.js +9 -6
  149. package/src/renderers/common/RenderObject.js +27 -27
  150. package/src/renderers/common/RenderObjects.js +12 -6
  151. package/src/renderers/common/Renderer.js +63 -57
  152. package/src/renderers/common/Textures.js +11 -3
  153. package/src/renderers/common/UniformsGroup.js +16 -4
  154. package/src/renderers/common/extras/PMREMGenerator.js +89 -13
  155. package/src/renderers/common/nodes/NodeLibrary.js +2 -2
  156. package/src/renderers/common/nodes/NodeStorageBuffer.js +2 -3
  157. package/src/renderers/common/nodes/NodeUniform.js +42 -0
  158. package/src/renderers/webgl/WebGLBackground.js +20 -1
  159. package/src/renderers/webgl/WebGLGeometries.js +0 -28
  160. package/src/renderers/webgl-fallback/WebGLBackend.js +13 -6
  161. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +43 -12
  162. package/src/renderers/webgl-fallback/utils/WebGLState.js +26 -1
  163. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +4 -1
  164. package/src/renderers/webgpu/WebGPUBackend.js +47 -31
  165. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +13 -26
  166. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +184 -74
  167. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +15 -2
  168. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +72 -7
  169. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +5 -1
  170. package/src/textures/Source.js +2 -2
  171. package/src/textures/Texture.js +2 -2
  172. package/src/nodes/display/BlendMode.js +0 -54
@@ -11,12 +11,27 @@ import { NodeBuilder, CodeNode } from '../../../nodes/Nodes.js';
11
11
  import { getFormat } from '../utils/WebGPUTextureUtils.js';
12
12
 
13
13
  import WGSLNodeParser from './WGSLNodeParser.js';
14
- import { GPUBufferBindingType, GPUStorageTextureAccess } from '../utils/WebGPUConstants.js';
14
+ import { NodeAccess } from '../../../nodes/core/constants.js';
15
15
 
16
- import { NoColorSpace, FloatType } from '../../../constants.js';
16
+ import VarNode from '../../../nodes/core/VarNode.js';
17
+ import ExpressionNode from '../../../nodes/code/ExpressionNode.js';
18
+
19
+ import { NoColorSpace, FloatType, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestFilter } from '../../../constants.js';
17
20
 
18
21
  // GPUShaderStage is not defined in browsers not supporting WebGPU
19
- const GPUShaderStage = self.GPUShaderStage;
22
+ const GPUShaderStage = ( typeof self !== 'undefined' ) ? self.GPUShaderStage : { VERTEX: 1, FRAGMENT: 2, COMPUTE: 4 };
23
+
24
+ const accessNames = {
25
+ [ NodeAccess.READ_ONLY ]: 'read',
26
+ [ NodeAccess.WRITE_ONLY ]: 'write',
27
+ [ NodeAccess.READ_WRITE ]: 'read_write'
28
+ };
29
+
30
+ const wrapNames = {
31
+ [ RepeatWrapping ]: 'repeat',
32
+ [ ClampToEdgeWrapping ]: 'clamp',
33
+ [ MirroredRepeatWrapping ]: 'mirror'
34
+ };
20
35
 
21
36
  const gpuShaderStageLib = {
22
37
  'vertex': GPUShaderStage ? GPUShaderStage.VERTEX : 1,
@@ -61,6 +76,8 @@ const wgslTypeLib = {
61
76
  mat4: 'mat4x4<f32>'
62
77
  };
63
78
 
79
+ const wgslCodeCache = {};
80
+
64
81
  const wgslPolyfill = {
65
82
  tsl_xor: new CodeNode( 'fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }' ),
66
83
  mod_float: new CodeNode( 'fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }' ),
@@ -71,19 +88,12 @@ const wgslPolyfill = {
71
88
  equals_bvec2: new CodeNode( 'fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2<bool> { return vec2<bool>( a.x == b.x, a.y == b.y ); }' ),
72
89
  equals_bvec3: new CodeNode( 'fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3<bool> { return vec3<bool>( a.x == b.x, a.y == b.y, a.z == b.z ); }' ),
73
90
  equals_bvec4: new CodeNode( 'fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4<bool> { return vec4<bool>( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }' ),
74
- repeatWrapping: new CodeNode( /* wgsl */`
75
- fn tsl_repeatWrapping( uv : vec2<f32>, dimension : vec2<u32> ) -> vec2<u32> {
76
-
77
- let uvScaled = vec2<u32>( uv * vec2<f32>( dimension ) );
78
-
79
- return ( ( uvScaled % dimension ) + dimension ) % dimension;
80
-
81
- }
82
- ` ),
91
+ repeatWrapping_float: new CodeNode( 'fn tsl_repeatWrapping_float( coord: f32 ) -> f32 { return fract( coord ); }' ),
92
+ mirrorWrapping_float: new CodeNode( 'fn tsl_mirrorWrapping_float( coord: f32 ) -> f32 { let mirrored = fract( coord * 0.5 ) * 2.0; return 1.0 - abs( 1.0 - mirrored ); }' ),
93
+ clampWrapping_float: new CodeNode( 'fn tsl_clampWrapping_float( coord: f32 ) -> f32 { return clamp( coord, 0.0, 1.0 ); }' ),
83
94
  biquadraticTexture: new CodeNode( /* wgsl */`
84
- fn tsl_biquadraticTexture( map : texture_2d<f32>, coord : vec2f, level : i32 ) -> vec4f {
95
+ fn tsl_biquadraticTexture( map : texture_2d<f32>, coord : vec2f, iRes : vec2u, level : u32 ) -> vec4f {
85
96
 
86
- let iRes = vec2i( textureDimensions( map, level ) );
87
97
  let res = vec2f( iRes );
88
98
 
89
99
  let uvScaled = coord * res;
@@ -95,10 +105,10 @@ fn tsl_biquadraticTexture( map : texture_2d<f32>, coord : vec2f, level : i32 ) -
95
105
  let iuv = floor( uv );
96
106
  let f = fract( uv );
97
107
 
98
- let rg1 = textureLoad( map, vec2i( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );
99
- let rg2 = textureLoad( map, vec2i( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );
100
- let rg3 = textureLoad( map, vec2i( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );
101
- let rg4 = textureLoad( map, vec2i( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );
108
+ let rg1 = textureLoad( map, vec2u( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );
109
+ let rg2 = textureLoad( map, vec2u( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );
110
+ let rg3 = textureLoad( map, vec2u( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );
111
+ let rg4 = textureLoad( map, vec2u( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );
102
112
 
103
113
  return mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );
104
114
 
@@ -123,7 +133,7 @@ const wgslMethods = {
123
133
 
124
134
  // WebGPU issue: does not support pow() with negative base on Windows
125
135
 
126
- if ( /Windows/g.test( navigator.userAgent ) ) {
136
+ if ( typeof navigator !== 'undefined' && /Windows/g.test( navigator.userAgent ) ) {
127
137
 
128
138
  wgslPolyfill.pow_float = new CodeNode( 'fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }' );
129
139
  wgslPolyfill.pow_vec2 = new CodeNode( 'fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }', [ wgslPolyfill.pow_float ] );
@@ -141,7 +151,7 @@ if ( /Windows/g.test( navigator.userAgent ) ) {
141
151
 
142
152
  let diagnostics = '';
143
153
 
144
- if ( /Firefox|Deno/g.test( navigator.userAgent ) !== true ) {
154
+ if ( ( typeof navigator !== 'undefined' && /Firefox|Deno/g.test( navigator.userAgent ) ) !== true ) {
145
155
 
146
156
  diagnostics += 'diagnostic( off, derivative_uniformity );\n';
147
157
 
@@ -191,7 +201,7 @@ class WGSLNodeBuilder extends NodeBuilder {
191
201
 
192
202
  } else {
193
203
 
194
- return this.generateTextureLod( texture, textureProperty, uvSnippet, '0' );
204
+ return this.generateTextureLod( texture, textureProperty, uvSnippet, depthSnippet, '0' );
195
205
 
196
206
  }
197
207
 
@@ -223,39 +233,139 @@ class WGSLNodeBuilder extends NodeBuilder {
223
233
 
224
234
  } else {
225
235
 
226
- return this.generateTextureLod( texture, textureProperty, uvSnippet, levelSnippet );
236
+ return this.generateTextureLod( texture, textureProperty, uvSnippet, depthSnippet, levelSnippet );
237
+
238
+ }
239
+
240
+ }
241
+
242
+ generateWrapFunction( texture ) {
243
+
244
+ const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }T`;
245
+
246
+ let nodeCode = wgslCodeCache[ functionName ];
247
+
248
+ if ( nodeCode === undefined ) {
249
+
250
+ const includes = [];
251
+
252
+ let code = `fn ${ functionName }( coord : vec2f ) -> vec2f {\n\n\treturn vec2f(\n`;
253
+
254
+ const addWrapSnippet = ( wrap, axis ) => {
255
+
256
+ if ( wrap === RepeatWrapping ) {
257
+
258
+ includes.push( wgslPolyfill.repeatWrapping_float );
259
+
260
+ code += `\t\ttsl_repeatWrapping_float( coord.${ axis } )`;
261
+
262
+ } else if ( wrap === ClampToEdgeWrapping ) {
263
+
264
+ includes.push( wgslPolyfill.clampWrapping_float );
265
+
266
+ code += `\t\ttsl_clampWrapping_float( coord.${ axis } )`;
267
+
268
+ } else if ( wrap === MirroredRepeatWrapping ) {
269
+
270
+ includes.push( wgslPolyfill.mirrorWrapping_float );
271
+
272
+ code += `\t\ttsl_mirrorWrapping_float( coord.${ axis } )`;
273
+
274
+ } else {
275
+
276
+ code += `\t\tcoord.${ axis }`;
277
+
278
+ console.warn( `WebGPURenderer: Unsupported texture wrap type "${ wrap }" for vertex shader.` );
279
+
280
+ }
281
+
282
+ };
283
+
284
+ addWrapSnippet( texture.wrapS, 'x' );
285
+
286
+ code += ',\n';
287
+
288
+ addWrapSnippet( texture.wrapT, 'y' );
289
+
290
+ code += '\n\t);\n\n}\n';
291
+
292
+ wgslCodeCache[ functionName ] = nodeCode = new CodeNode( code, includes );
293
+
294
+ }
295
+
296
+ nodeCode.build( this );
297
+
298
+ return functionName;
299
+
300
+ }
301
+
302
+ generateTextureDimension( texture, textureProperty, levelSnippet ) {
303
+
304
+ const textureData = this.getDataFromNode( texture, this.shaderStage, this.globalCache );
305
+
306
+ if ( textureData.dimensionsSnippet === undefined ) textureData.dimensionsSnippet = {};
307
+
308
+ let textureDimensionNode = textureData.dimensionsSnippet[ levelSnippet ];
309
+
310
+ if ( textureData.dimensionsSnippet[ levelSnippet ] === undefined ) {
311
+
312
+ let textureDimensionsParams;
313
+
314
+ if ( texture.isMultisampleRenderTargetTexture === true ) {
315
+
316
+ textureDimensionsParams = textureProperty;
317
+
318
+ } else {
319
+
320
+ textureDimensionsParams = `${ textureProperty }, u32( ${ levelSnippet } )`;
321
+
322
+ }
323
+
324
+ textureDimensionNode = new VarNode( new ExpressionNode( `textureDimensions( ${ textureDimensionsParams } )`, 'uvec2' ) );
325
+
326
+ textureData.dimensionsSnippet[ levelSnippet ] = textureDimensionNode;
227
327
 
228
328
  }
229
329
 
330
+ return textureDimensionNode.build( this );
331
+
230
332
  }
231
333
 
232
- generateFilteredTexture( texture, textureProperty, uvSnippet, levelSnippet = '0' ) {
334
+ generateFilteredTexture( texture, textureProperty, uvSnippet, levelSnippet = '0u' ) {
233
335
 
234
336
  this._include( 'biquadraticTexture' );
235
337
 
236
- return `tsl_biquadraticTexture( ${ textureProperty }, ${ uvSnippet }, i32( ${ levelSnippet } ) )`;
338
+ const wrapFunction = this.generateWrapFunction( texture );
339
+ const textureDimension = this.generateTextureDimension( texture, textureProperty, levelSnippet );
340
+
341
+ return `tsl_biquadraticTexture( ${ textureProperty }, ${ wrapFunction }( ${ uvSnippet } ), ${ textureDimension }, u32( ${ levelSnippet } ) )`;
237
342
 
238
343
  }
239
344
 
240
- generateTextureLod( texture, textureProperty, uvSnippet, levelSnippet = '0' ) {
345
+ generateTextureLod( texture, textureProperty, uvSnippet, depthSnippet, levelSnippet = '0u' ) {
241
346
 
242
- this._include( 'repeatWrapping' );
347
+ const wrapFunction = this.generateWrapFunction( texture );
348
+ const textureDimension = this.generateTextureDimension( texture, textureProperty, levelSnippet );
243
349
 
244
- const dimension = texture.isMultisampleRenderTargetTexture === true ? `textureDimensions( ${ textureProperty } )` : `textureDimensions( ${ textureProperty }, 0 )`;
350
+ const coordSnippet = `vec2u( ${ wrapFunction }( ${ uvSnippet } ) * vec2f( ${ textureDimension } ) )`;
245
351
 
246
- return `textureLoad( ${ textureProperty }, tsl_repeatWrapping( ${ uvSnippet }, ${ dimension } ), i32( ${ levelSnippet } ) )`;
352
+ return this.generateTextureLoad( texture, textureProperty, coordSnippet, depthSnippet, levelSnippet );
247
353
 
248
354
  }
249
355
 
250
356
  generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0u' ) {
251
357
 
252
- if ( depthSnippet ) {
358
+ if ( texture.isVideoTexture === true || texture.isStorageTexture === true ) {
359
+
360
+ return `textureLoad( ${ textureProperty }, ${ uvIndexSnippet } )`;
253
361
 
254
- return `textureLoad( ${ textureProperty }, ${ uvIndexSnippet }, ${ depthSnippet }, ${ levelSnippet } )`;
362
+ } else if ( depthSnippet ) {
363
+
364
+ return `textureLoad( ${ textureProperty }, ${ uvIndexSnippet }, ${ depthSnippet }, u32( ${ levelSnippet } ) )`;
255
365
 
256
366
  } else {
257
367
 
258
- return `textureLoad( ${ textureProperty }, ${ uvIndexSnippet }, ${ levelSnippet } )`;
368
+ return `textureLoad( ${ textureProperty }, ${ uvIndexSnippet }, u32( ${ levelSnippet } ) )`;
259
369
 
260
370
  }
261
371
 
@@ -267,9 +377,18 @@ class WGSLNodeBuilder extends NodeBuilder {
267
377
 
268
378
  }
269
379
 
380
+ isSampleCompare( texture ) {
381
+
382
+ return texture.isDepthTexture === true && texture.compareFunction !== null;
383
+
384
+ }
385
+
270
386
  isUnfilterable( texture ) {
271
387
 
272
- return this.getComponentTypeFromTexture( texture ) !== 'float' || ( ! this.isAvailable( 'float32Filterable' ) && texture.isDataTexture === true && texture.type === FloatType ) || texture.isMultisampleRenderTargetTexture === true;
388
+ return this.getComponentTypeFromTexture( texture ) !== 'float' ||
389
+ ( ! this.isAvailable( 'float32Filterable' ) && texture.isDataTexture === true && texture.type === FloatType ) ||
390
+ ( this.isSampleCompare( texture ) === false && texture.minFilter === NearestFilter && texture.magFilter === NearestFilter ) ||
391
+ texture.isMultisampleRenderTargetTexture === true;
273
392
 
274
393
  }
275
394
 
@@ -283,7 +402,7 @@ class WGSLNodeBuilder extends NodeBuilder {
283
402
 
284
403
  } else if ( this.isUnfilterable( texture ) ) {
285
404
 
286
- snippet = this.generateTextureLod( texture, textureProperty, uvSnippet, '0', depthSnippet, shaderStage );
405
+ snippet = this.generateTextureLod( texture, textureProperty, uvSnippet, depthSnippet, '0', shaderStage );
287
406
 
288
407
  } else {
289
408
 
@@ -419,46 +538,18 @@ class WGSLNodeBuilder extends NodeBuilder {
419
538
 
420
539
  }
421
540
 
422
- getStorageAccess( node ) {
423
-
424
- if ( node.isStorageTextureNode ) {
425
-
426
- switch ( node.access ) {
427
-
428
- case GPUStorageTextureAccess.ReadOnly:
429
-
430
- return 'read';
431
-
432
- case GPUStorageTextureAccess.WriteOnly:
433
-
434
- return 'write';
541
+ getNodeAccess( node, shaderStage ) {
435
542
 
436
- default:
543
+ if ( shaderStage !== 'compute' )
544
+ return NodeAccess.READ_ONLY;
437
545
 
438
- return 'read_write';
546
+ return node.access;
439
547
 
440
- }
441
-
442
- } else {
443
-
444
- switch ( node.access ) {
445
-
446
- case GPUBufferBindingType.Storage:
447
-
448
- return 'read_write';
449
-
450
-
451
- case GPUBufferBindingType.ReadOnlyStorage:
452
-
453
- return 'read';
454
-
455
- default:
548
+ }
456
549
 
457
- return 'write';
550
+ getStorageAccess( node, shaderStage ) {
458
551
 
459
- }
460
-
461
- }
552
+ return accessNames[ this.getNodeAccess( node, shaderStage ) ];
462
553
 
463
554
  }
464
555
 
@@ -480,17 +571,19 @@ class WGSLNodeBuilder extends NodeBuilder {
480
571
 
481
572
  let texture = null;
482
573
 
574
+ const access = this.getNodeAccess( node, shaderStage );
575
+
483
576
  if ( type === 'texture' || type === 'storageTexture' ) {
484
577
 
485
- texture = new NodeSampledTexture( uniformNode.name, uniformNode.node, group, node.access ? node.access : null );
578
+ texture = new NodeSampledTexture( uniformNode.name, uniformNode.node, group, access );
486
579
 
487
580
  } else if ( type === 'cubeTexture' ) {
488
581
 
489
- texture = new NodeSampledCubeTexture( uniformNode.name, uniformNode.node, group, node.access ? node.access : null );
582
+ texture = new NodeSampledCubeTexture( uniformNode.name, uniformNode.node, group, access );
490
583
 
491
584
  } else if ( type === 'texture3D' ) {
492
585
 
493
- texture = new NodeSampledTexture3D( uniformNode.name, uniformNode.node, group, node.access ? node.access : null );
586
+ texture = new NodeSampledTexture3D( uniformNode.name, uniformNode.node, group, access );
494
587
 
495
588
  }
496
589
 
@@ -692,6 +785,12 @@ ${ flowData.code }
692
785
 
693
786
  }
694
787
 
788
+ getClipDistance() {
789
+
790
+ return 'varyings.hw_clip_distances';
791
+
792
+ }
793
+
695
794
  isFlipY() {
696
795
 
697
796
  return false;
@@ -754,6 +853,13 @@ ${ flowData.code }
754
853
 
755
854
  }
756
855
 
856
+ enableHardwareClipping( planeCount ) {
857
+
858
+ this.enableClipDistances();
859
+ this.getBuiltin( 'clip_distances', 'hw_clip_distances', `array<f32, ${ planeCount } >`, 'vertex' );
860
+
861
+ }
862
+
757
863
  getBuiltins( shaderStage ) {
758
864
 
759
865
  const snippets = [];
@@ -998,7 +1104,7 @@ ${ flowData.code }
998
1104
 
999
1105
  if ( shaderStage === 'fragment' && this.isUnfilterable( texture ) === false && uniform.node.isStorageTextureNode !== true ) {
1000
1106
 
1001
- if ( texture.isDepthTexture === true && texture.compareFunction !== null ) {
1107
+ if ( this.isSampleCompare( texture ) ) {
1002
1108
 
1003
1109
  bindingSnippets.push( `@binding( ${ uniformIndexes.binding ++ } ) @group( ${ uniformIndexes.group } ) var ${ uniform.name }_sampler : sampler_comparison;` );
1004
1110
 
@@ -1043,7 +1149,7 @@ ${ flowData.code }
1043
1149
  } else if ( uniform.node.isStorageTextureNode === true ) {
1044
1150
 
1045
1151
  const format = getFormat( texture );
1046
- const access = this.getStorageAccess( uniform.node );
1152
+ const access = this.getStorageAccess( uniform.node, shaderStage );
1047
1153
 
1048
1154
  textureType = `texture_storage_2d<${ format }, ${ access }>`;
1049
1155
 
@@ -1066,7 +1172,7 @@ ${ flowData.code }
1066
1172
  const bufferCountSnippet = bufferCount > 0 && uniform.type === 'buffer' ? ', ' + bufferCount : '';
1067
1173
  const bufferTypeSnippet = bufferNode.isAtomic ? `atomic<${bufferType}>` : `${bufferType}`;
1068
1174
  const bufferSnippet = `\t${ uniform.name } : array< ${ bufferTypeSnippet }${ bufferCountSnippet } >\n`;
1069
- const bufferAccessMode = bufferNode.isStorageBufferNode ? `storage, ${ this.getStorageAccess( bufferNode ) }` : 'uniform';
1175
+ const bufferAccessMode = bufferNode.isStorageBufferNode ? `storage, ${ this.getStorageAccess( bufferNode, shaderStage ) }` : 'uniform';
1070
1176
 
1071
1177
  bufferSnippets.push( this._getWGSLStructBinding( 'NodeBuffer_' + bufferNode.id, bufferSnippet, bufferAccessMode, uniformIndexes.binding ++, uniformIndexes.group ) );
1072
1178
 
@@ -1239,6 +1345,10 @@ ${ flowData.code }
1239
1345
 
1240
1346
  result = this.renderer.hasFeature( 'float32-filterable' );
1241
1347
 
1348
+ } else if ( name === 'clipDistance' ) {
1349
+
1350
+ result = this.renderer.hasFeature( 'clip-distances' );
1351
+
1242
1352
  }
1243
1353
 
1244
1354
  supports[ name ] = result;
@@ -108,6 +108,7 @@ class WebGPUAttributeUtils {
108
108
  const buffer = backend.get( bufferAttribute ).buffer;
109
109
 
110
110
  const array = bufferAttribute.array;
111
+ const isTypedArray = this._isTypedArray( array );
111
112
  const updateRanges = bufferAttribute.updateRanges;
112
113
 
113
114
  if ( updateRanges.length === 0 ) {
@@ -123,15 +124,21 @@ class WebGPUAttributeUtils {
123
124
 
124
125
  } else {
125
126
 
127
+ const byteOffsetFactor = isTypedArray ? 1 : array.BYTES_PER_ELEMENT;
128
+
126
129
  for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
127
130
 
128
131
  const range = updateRanges[ i ];
132
+
133
+ const dataOffset = range.start * byteOffsetFactor;
134
+ const size = range.count * byteOffsetFactor;
135
+
129
136
  device.queue.writeBuffer(
130
137
  buffer,
131
138
  0,
132
139
  array,
133
- range.start * array.BYTES_PER_ELEMENT,
134
- range.count * array.BYTES_PER_ELEMENT
140
+ dataOffset,
141
+ size
135
142
  );
136
143
 
137
144
  }
@@ -299,6 +306,12 @@ class WebGPUAttributeUtils {
299
306
 
300
307
  }
301
308
 
309
+ _isTypedArray( array ) {
310
+
311
+ return ArrayBuffer.isView( array ) && ! ( array instanceof DataView );
312
+
313
+ }
314
+
302
315
  _getBufferAttribute( attribute ) {
303
316
 
304
317
  if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
@@ -1,8 +1,9 @@
1
1
  import {
2
- GPUTextureAspect, GPUTextureViewDimension, GPUTextureSampleType
2
+ GPUTextureAspect, GPUTextureViewDimension, GPUTextureSampleType, GPUBufferBindingType, GPUStorageTextureAccess
3
3
  } from './WebGPUConstants.js';
4
4
 
5
5
  import { FloatType, IntType, UnsignedIntType } from '../../../constants.js';
6
+ import { NodeAccess } from '../../../nodes/core/constants.js';
6
7
 
7
8
  class WebGPUBindingUtils {
8
9
 
@@ -35,7 +36,25 @@ class WebGPUBindingUtils {
35
36
 
36
37
  if ( binding.isStorageBuffer ) {
37
38
 
38
- buffer.type = binding.access;
39
+ if ( binding.visibility & 4 ) {
40
+
41
+ // compute
42
+
43
+ if ( binding.access === NodeAccess.READ_WRITE || binding.access === NodeAccess.WRITE_ONLY ) {
44
+
45
+ buffer.type = GPUBufferBindingType.Storage;
46
+
47
+ } else {
48
+
49
+ buffer.type = GPUBufferBindingType.ReadOnlyStorage;
50
+
51
+ }
52
+
53
+ } else {
54
+
55
+ buffer.type = GPUBufferBindingType.ReadOnlyStorage;
56
+
57
+ }
39
58
 
40
59
  }
41
60
 
@@ -63,10 +82,26 @@ class WebGPUBindingUtils {
63
82
 
64
83
  } else if ( binding.isSampledTexture && binding.store ) {
65
84
 
66
- const format = this.backend.get( binding.texture ).texture.format;
85
+ const storageTexture = {}; // GPUStorageTextureBindingLayout
86
+ storageTexture.format = this.backend.get( binding.texture ).texture.format;
87
+
67
88
  const access = binding.access;
68
89
 
69
- bindingGPU.storageTexture = { format, access }; // GPUStorageTextureBindingLayout
90
+ if ( access === NodeAccess.READ_WRITE ) {
91
+
92
+ storageTexture.access = GPUStorageTextureAccess.ReadWrite;
93
+
94
+ } else if ( access === NodeAccess.WRITE_ONLY ) {
95
+
96
+ storageTexture.access = GPUStorageTextureAccess.WriteOnly;
97
+
98
+ } else {
99
+
100
+ storageTexture.access = GPUStorageTextureAccess.ReadOnly;
101
+
102
+ }
103
+
104
+ bindingGPU.storageTexture = storageTexture;
70
105
 
71
106
  } else if ( binding.isSampledTexture ) {
72
107
 
@@ -140,7 +175,7 @@ class WebGPUBindingUtils {
140
175
 
141
176
  }
142
177
 
143
- createBindings( bindGroup ) {
178
+ createBindings( bindGroup, bindings, cacheIndex, version = 0 ) {
144
179
 
145
180
  const { backend, bindGroupLayoutCache } = this;
146
181
  const bindingsData = backend.get( bindGroup );
@@ -156,10 +191,40 @@ class WebGPUBindingUtils {
156
191
 
157
192
  }
158
193
 
159
- const bindGroupGPU = this.createBindGroup( bindGroup, bindLayoutGPU );
194
+ let bindGroupGPU;
195
+
196
+ if ( cacheIndex > 0 ) {
197
+
198
+ if ( bindingsData.groups === undefined ) {
199
+
200
+ bindingsData.groups = [];
201
+ bindingsData.versions = [];
202
+
203
+ }
204
+
205
+ if ( bindingsData.versions[ cacheIndex ] === version ) {
206
+
207
+ bindGroupGPU = bindingsData.groups[ cacheIndex ];
208
+
209
+ }
210
+
211
+ }
212
+
213
+ if ( bindGroupGPU === undefined ) {
214
+
215
+ bindGroupGPU = this.createBindGroup( bindGroup, bindLayoutGPU );
216
+
217
+ if ( cacheIndex > 0 ) {
218
+
219
+ bindingsData.groups[ cacheIndex ] = bindGroupGPU;
220
+ bindingsData.versions[ cacheIndex ] = version;
221
+
222
+ }
223
+
224
+ }
160
225
 
161
- bindingsData.layout = bindLayoutGPU;
162
226
  bindingsData.group = bindGroupGPU;
227
+ bindingsData.layout = bindLayoutGPU;
163
228
 
164
229
  }
165
230
 
@@ -230,7 +230,7 @@ class WebGPUTextureUtils {
230
230
  const backend = this.backend;
231
231
  const textureData = backend.get( texture );
232
232
 
233
- textureData.texture.destroy();
233
+ if ( textureData.texture !== undefined ) textureData.texture.destroy();
234
234
 
235
235
  if ( textureData.msaaTexture !== undefined ) textureData.msaaTexture.destroy();
236
236
 
@@ -952,6 +952,10 @@ export function getFormat( texture, device = null ) {
952
952
  formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x12UnormSRGB : GPUTextureFormat.ASTC12x12Unorm;
953
953
  break;
954
954
 
955
+ case RGBAFormat:
956
+ formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm;
957
+ break;
958
+
955
959
  default:
956
960
  console.error( 'WebGPURenderer: Unsupported texture format.', format );
957
961
 
@@ -1,5 +1,5 @@
1
1
  import { ImageUtils } from '../extras/ImageUtils.js';
2
- import * as MathUtils from '../math/MathUtils.js';
2
+ import { generateUUID } from '../math/MathUtils.js';
3
3
 
4
4
  let _sourceId = 0;
5
5
 
@@ -11,7 +11,7 @@ class Source {
11
11
 
12
12
  Object.defineProperty( this, 'id', { value: _sourceId ++ } );
13
13
 
14
- this.uuid = MathUtils.generateUUID();
14
+ this.uuid = generateUUID();
15
15
 
16
16
  this.data = data;
17
17
  this.dataReady = true;
@@ -10,7 +10,7 @@ import {
10
10
  UVMapping,
11
11
  NoColorSpace,
12
12
  } from '../constants.js';
13
- import * as MathUtils from '../math/MathUtils.js';
13
+ import { generateUUID } from '../math/MathUtils.js';
14
14
  import { Vector2 } from '../math/Vector2.js';
15
15
  import { Matrix3 } from '../math/Matrix3.js';
16
16
  import { Source } from './Source.js';
@@ -27,7 +27,7 @@ class Texture extends EventDispatcher {
27
27
 
28
28
  Object.defineProperty( this, 'id', { value: _textureId ++ } );
29
29
 
30
- this.uuid = MathUtils.generateUUID();
30
+ this.uuid = generateUUID();
31
31
 
32
32
  this.name = '';
33
33
 
@@ -1,54 +0,0 @@
1
- import { Fn } from '../tsl/TSLBase.js';
2
- import { mix, min, step } from '../math/MathNode.js';
3
-
4
- export const burn = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
5
-
6
- return min( 1.0, base.oneMinus().div( blend ) ).oneMinus();
7
-
8
- } ).setLayout( {
9
- name: 'burnBlend',
10
- type: 'vec3',
11
- inputs: [
12
- { name: 'base', type: 'vec3' },
13
- { name: 'blend', type: 'vec3' }
14
- ]
15
- } );
16
-
17
- export const dodge = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
18
-
19
- return min( base.div( blend.oneMinus() ), 1.0 );
20
-
21
- } ).setLayout( {
22
- name: 'dodgeBlend',
23
- type: 'vec3',
24
- inputs: [
25
- { name: 'base', type: 'vec3' },
26
- { name: 'blend', type: 'vec3' }
27
- ]
28
- } );
29
-
30
- export const screen = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
31
-
32
- return base.oneMinus().mul( blend.oneMinus() ).oneMinus();
33
-
34
- } ).setLayout( {
35
- name: 'screenBlend',
36
- type: 'vec3',
37
- inputs: [
38
- { name: 'base', type: 'vec3' },
39
- { name: 'blend', type: 'vec3' }
40
- ]
41
- } );
42
-
43
- export const overlay = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
44
-
45
- return mix( base.mul( 2.0 ).mul( blend ), base.oneMinus().mul( 2.0 ).mul( blend.oneMinus() ).oneMinus(), step( 0.5, base ) );
46
-
47
- } ).setLayout( {
48
- name: 'overlayBlend',
49
- type: 'vec3',
50
- inputs: [
51
- { name: 'base', type: 'vec3' },
52
- { name: 'blend', type: 'vec3' }
53
- ]
54
- } );