@plastic-software/three 0.182.0 → 0.183.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 (298) hide show
  1. package/LICENSE +1 -1
  2. package/build/three.cjs +11520 -10877
  3. package/build/three.core.js +11732 -11340
  4. package/build/three.core.min.js +2 -2
  5. package/build/three.module.js +509 -262
  6. package/build/three.module.min.js +2 -2
  7. package/build/three.tsl.js +7 -11
  8. package/build/three.tsl.min.js +2 -2
  9. package/build/three.webgpu.js +3072 -2607
  10. package/build/three.webgpu.min.js +2 -2
  11. package/build/three.webgpu.nodes.js +3071 -2607
  12. package/build/three.webgpu.nodes.min.js +2 -2
  13. package/examples/jsm/Addons.js +0 -3
  14. package/examples/jsm/animation/CCDIKSolver.js +2 -2
  15. package/examples/jsm/controls/ArcballControls.js +3 -3
  16. package/examples/jsm/controls/OrbitControls.js +103 -0
  17. package/examples/jsm/effects/AnaglyphEffect.js +102 -7
  18. package/examples/jsm/environments/ColorEnvironment.js +59 -0
  19. package/examples/jsm/environments/RoomEnvironment.js +1 -0
  20. package/examples/jsm/exporters/EXRExporter.js +1 -1
  21. package/examples/jsm/exporters/GLTFExporter.js +131 -4
  22. package/examples/jsm/exporters/USDZExporter.js +22 -3
  23. package/examples/jsm/helpers/AnimationPathHelper.js +302 -0
  24. package/examples/jsm/helpers/ViewHelper.js +67 -8
  25. package/examples/jsm/inspector/Inspector.js +21 -5
  26. package/examples/jsm/inspector/tabs/Console.js +39 -5
  27. package/examples/jsm/inspector/tabs/Parameters.js +16 -0
  28. package/examples/jsm/inspector/ui/Style.js +25 -1
  29. package/examples/jsm/libs/meshopt_decoder.module.js +6 -5
  30. package/examples/jsm/lines/LineMaterial.js +6 -0
  31. package/examples/jsm/loaders/3MFLoader.js +2 -2
  32. package/examples/jsm/loaders/AMFLoader.js +2 -2
  33. package/examples/jsm/loaders/ColladaLoader.js +24 -4026
  34. package/examples/jsm/loaders/EXRLoader.js +5 -5
  35. package/examples/jsm/loaders/FBXLoader.js +2 -2
  36. package/examples/jsm/loaders/GCodeLoader.js +34 -8
  37. package/examples/jsm/loaders/GLTFLoader.js +122 -171
  38. package/examples/jsm/loaders/KMZLoader.js +5 -5
  39. package/examples/jsm/loaders/KTX2Loader.js +5 -5
  40. package/examples/jsm/loaders/LWOLoader.js +7 -39
  41. package/examples/jsm/loaders/NRRDLoader.js +2 -2
  42. package/examples/jsm/loaders/PCDLoader.js +3 -2
  43. package/examples/jsm/loaders/USDLoader.js +100 -40
  44. package/examples/jsm/loaders/UltraHDRLoader.js +182 -30
  45. package/examples/jsm/loaders/VRMLLoader.js +77 -0
  46. package/examples/jsm/loaders/VTKLoader.js +37 -24
  47. package/examples/jsm/loaders/collada/ColladaComposer.js +2950 -0
  48. package/examples/jsm/loaders/collada/ColladaParser.js +1962 -0
  49. package/examples/jsm/loaders/usd/USDAParser.js +447 -366
  50. package/examples/jsm/loaders/usd/USDCParser.js +1841 -6
  51. package/examples/jsm/loaders/usd/USDComposer.js +4041 -0
  52. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +2 -2
  53. package/examples/jsm/objects/LensflareMesh.js +1 -1
  54. package/examples/jsm/objects/Sky.js +76 -4
  55. package/examples/jsm/objects/SkyMesh.js +114 -7
  56. package/examples/jsm/objects/Water.js +4 -3
  57. package/examples/jsm/objects/Water2.js +5 -3
  58. package/examples/jsm/objects/WaterMesh.js +5 -7
  59. package/examples/jsm/physics/JoltPhysics.js +7 -5
  60. package/examples/jsm/physics/RapierPhysics.js +6 -4
  61. package/examples/jsm/postprocessing/EffectComposer.js +7 -5
  62. package/examples/jsm/postprocessing/RenderTransitionPass.js +1 -1
  63. package/examples/jsm/renderers/CSS3DRenderer.js +1 -1
  64. package/examples/jsm/renderers/SVGRenderer.js +2 -2
  65. package/examples/jsm/shaders/GTAOShader.js +19 -6
  66. package/examples/jsm/shaders/HalftoneShader.js +12 -1
  67. package/examples/jsm/shaders/PoissonDenoiseShader.js +6 -2
  68. package/examples/jsm/shaders/SAOShader.js +17 -4
  69. package/examples/jsm/shaders/SSAOShader.js +11 -1
  70. package/examples/jsm/shaders/SSRShader.js +6 -5
  71. package/examples/jsm/shaders/VignetteShader.js +1 -1
  72. package/examples/jsm/tsl/display/AfterImageNode.js +1 -1
  73. package/examples/jsm/tsl/display/AnaglyphPassNode.js +456 -16
  74. package/examples/jsm/tsl/display/AnamorphicNode.js +1 -1
  75. package/examples/jsm/tsl/display/BilateralBlurNode.js +364 -0
  76. package/examples/jsm/tsl/display/BloomNode.js +5 -5
  77. package/examples/jsm/tsl/display/CRT.js +150 -0
  78. package/examples/jsm/tsl/display/DenoiseNode.js +1 -1
  79. package/examples/jsm/tsl/display/DepthOfFieldNode.js +1 -1
  80. package/examples/jsm/tsl/display/DotScreenNode.js +1 -1
  81. package/examples/jsm/tsl/display/FXAANode.js +2 -2
  82. package/examples/jsm/tsl/display/GTAONode.js +2 -2
  83. package/examples/jsm/tsl/display/GaussianBlurNode.js +11 -2
  84. package/examples/jsm/tsl/display/GodraysNode.js +624 -0
  85. package/examples/jsm/tsl/display/LensflareNode.js +1 -1
  86. package/examples/jsm/tsl/display/Lut3DNode.js +1 -1
  87. package/examples/jsm/tsl/display/OutlineNode.js +3 -3
  88. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +2 -2
  89. package/examples/jsm/tsl/display/PixelationPassNode.js +5 -5
  90. package/examples/jsm/tsl/display/RGBShiftNode.js +2 -2
  91. package/examples/jsm/tsl/display/RetroPassNode.js +263 -0
  92. package/examples/jsm/tsl/display/SMAANode.js +2 -2
  93. package/examples/jsm/tsl/display/SSAAPassNode.js +2 -2
  94. package/examples/jsm/tsl/display/SSGINode.js +2 -2
  95. package/examples/jsm/tsl/display/SSRNode.js +7 -7
  96. package/examples/jsm/tsl/display/SSSNode.js +2 -2
  97. package/examples/jsm/tsl/display/Shape.js +29 -0
  98. package/examples/jsm/tsl/display/SobelOperatorNode.js +2 -2
  99. package/examples/jsm/tsl/display/StereoPassNode.js +1 -2
  100. package/examples/jsm/tsl/display/TRAANode.js +9 -12
  101. package/examples/jsm/tsl/display/TransitionNode.js +1 -1
  102. package/examples/jsm/tsl/display/depthAwareBlend.js +80 -0
  103. package/examples/jsm/tsl/math/Bayer.js +40 -1
  104. package/examples/jsm/utils/LDrawUtils.js +1 -1
  105. package/package.json +11 -19
  106. package/src/Three.Core.js +1 -1
  107. package/src/Three.TSL.js +5 -9
  108. package/src/Three.WebGPU.Nodes.js +2 -0
  109. package/src/Three.WebGPU.js +3 -0
  110. package/src/Three.js +1 -0
  111. package/src/animation/AnimationAction.js +1 -1
  112. package/src/animation/AnimationClip.js +1 -1
  113. package/src/animation/AnimationMixer.js +6 -0
  114. package/src/animation/KeyframeTrack.js +46 -7
  115. package/src/animation/PropertyMixer.js +4 -4
  116. package/src/audio/Audio.js +1 -1
  117. package/src/audio/AudioListener.js +5 -3
  118. package/src/cameras/Camera.js +32 -2
  119. package/src/cameras/CubeCamera.js +20 -0
  120. package/src/constants.js +30 -1
  121. package/src/core/Clock.js +7 -0
  122. package/src/core/Object3D.js +56 -4
  123. package/src/core/RenderTarget.js +3 -4
  124. package/src/extras/PMREMGenerator.js +4 -8
  125. package/src/geometries/TorusGeometry.js +8 -3
  126. package/src/helpers/CameraHelper.js +3 -0
  127. package/src/helpers/DirectionalLightHelper.js +4 -1
  128. package/src/helpers/HemisphereLightHelper.js +3 -0
  129. package/src/helpers/PointLightHelper.js +0 -24
  130. package/src/helpers/SpotLightHelper.js +3 -0
  131. package/src/lights/LightShadow.js +15 -3
  132. package/src/lights/webgpu/IESSpotLight.js +2 -1
  133. package/src/loaders/Cache.js +28 -0
  134. package/src/loaders/FileLoader.js +1 -1
  135. package/src/loaders/ImageBitmapLoader.js +8 -3
  136. package/src/loaders/Loader.js +6 -0
  137. package/src/loaders/ObjectLoader.js +18 -1
  138. package/src/materials/MeshLambertMaterial.js +9 -0
  139. package/src/materials/MeshPhongMaterial.js +9 -0
  140. package/src/materials/nodes/Line2NodeMaterial.js +5 -5
  141. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +2 -0
  142. package/src/materials/nodes/NodeMaterial.js +15 -24
  143. package/src/materials/nodes/manager/NodeMaterialObserver.js +9 -3
  144. package/src/math/Line3.js +3 -5
  145. package/src/math/MathUtils.js +10 -10
  146. package/src/math/Matrix4.js +35 -26
  147. package/src/math/Quaternion.js +3 -29
  148. package/src/math/Vector3.js +3 -3
  149. package/src/math/interpolants/BezierInterpolant.js +108 -0
  150. package/src/nodes/Nodes.js +87 -68
  151. package/src/nodes/TSL.js +2 -5
  152. package/src/nodes/accessors/Arrays.js +1 -1
  153. package/src/nodes/accessors/Bitangent.js +5 -5
  154. package/src/nodes/accessors/BufferAttributeNode.js +1 -1
  155. package/src/nodes/accessors/Camera.js +149 -28
  156. package/src/nodes/accessors/InstanceNode.js +105 -40
  157. package/src/nodes/accessors/Normal.js +9 -9
  158. package/src/nodes/accessors/Position.js +34 -2
  159. package/src/nodes/accessors/SceneProperties.js +53 -0
  160. package/src/nodes/accessors/SkinningNode.js +12 -24
  161. package/src/nodes/accessors/StorageBufferNode.js +0 -19
  162. package/src/nodes/accessors/StorageTextureNode.js +37 -1
  163. package/src/nodes/accessors/Tangent.js +3 -3
  164. package/src/nodes/accessors/Texture3DNode.js +6 -34
  165. package/src/nodes/accessors/TextureNode.js +58 -22
  166. package/src/nodes/accessors/UniformArrayNode.js +2 -0
  167. package/src/nodes/core/MRTNode.js +48 -2
  168. package/src/nodes/core/Node.js +29 -3
  169. package/src/nodes/core/NodeBuilder.js +115 -40
  170. package/src/nodes/core/NodeError.js +28 -0
  171. package/src/nodes/core/NodeUtils.js +5 -3
  172. package/src/nodes/core/OutputStructNode.js +12 -10
  173. package/src/nodes/core/ParameterNode.js +2 -1
  174. package/src/nodes/core/StackNode.js +9 -8
  175. package/src/nodes/core/StackTrace.js +139 -0
  176. package/src/nodes/core/StructNode.js +15 -0
  177. package/src/nodes/core/SubBuildNode.js +1 -1
  178. package/src/nodes/core/UniformNode.js +2 -1
  179. package/src/nodes/core/VarNode.js +1 -1
  180. package/src/nodes/core/VaryingNode.js +1 -18
  181. package/src/nodes/display/BlendModes.js +0 -64
  182. package/src/nodes/display/ColorAdjustment.js +17 -0
  183. package/src/nodes/display/ColorSpaceNode.js +3 -3
  184. package/src/nodes/display/NormalMapNode.js +2 -2
  185. package/src/nodes/display/PassNode.js +21 -2
  186. package/src/nodes/display/RenderOutputNode.js +3 -3
  187. package/src/nodes/display/ScreenNode.js +2 -1
  188. package/src/nodes/display/ToneMappingNode.js +1 -1
  189. package/src/nodes/display/ToonOutlinePassNode.js +2 -2
  190. package/src/nodes/display/ViewportDepthNode.js +52 -4
  191. package/src/nodes/display/ViewportTextureNode.js +21 -4
  192. package/src/nodes/fog/Fog.js +18 -35
  193. package/src/nodes/functions/PhysicalLightingModel.js +25 -3
  194. package/src/nodes/geometry/RangeNode.js +4 -2
  195. package/src/nodes/gpgpu/ComputeNode.js +5 -4
  196. package/src/nodes/gpgpu/WorkgroupInfoNode.js +2 -1
  197. package/src/nodes/lighting/EnvironmentNode.js +28 -3
  198. package/src/nodes/lighting/PointShadowNode.js +24 -12
  199. package/src/nodes/lighting/ShadowFilterNode.js +15 -43
  200. package/src/nodes/lighting/ShadowNode.js +54 -32
  201. package/src/nodes/math/ConditionalNode.js +2 -2
  202. package/src/nodes/math/MathNode.js +3 -40
  203. package/src/nodes/math/OperatorNode.js +2 -1
  204. package/src/nodes/pmrem/PMREMUtils.js +9 -15
  205. package/src/nodes/tsl/TSLCore.js +13 -10
  206. package/src/nodes/utils/DebugNode.js +11 -11
  207. package/src/nodes/utils/JoinNode.js +2 -2
  208. package/src/nodes/utils/LoopNode.js +1 -1
  209. package/src/nodes/utils/MemberNode.js +1 -1
  210. package/src/nodes/utils/RTTNode.js +1 -1
  211. package/src/nodes/utils/ReflectorNode.js +2 -3
  212. package/src/nodes/utils/SpriteSheetUV.js +35 -0
  213. package/src/nodes/utils/UVUtils.js +4 -2
  214. package/src/objects/BatchedMesh.js +22 -12
  215. package/src/objects/InstancedMesh.js +11 -0
  216. package/src/renderers/WebGLRenderer.js +34 -60
  217. package/src/renderers/common/Backend.js +21 -0
  218. package/src/renderers/common/Background.js +7 -4
  219. package/src/renderers/common/BindGroup.js +1 -9
  220. package/src/renderers/common/Bindings.js +20 -5
  221. package/src/renderers/common/BlendMode.js +143 -0
  222. package/src/renderers/common/BundleGroup.js +1 -1
  223. package/src/renderers/common/CubeRenderTarget.js +50 -6
  224. package/src/renderers/common/Geometries.js +17 -3
  225. package/src/renderers/common/Lighting.js +5 -21
  226. package/src/renderers/common/Pipelines.js +4 -4
  227. package/src/renderers/common/PostProcessing.js +8 -206
  228. package/src/renderers/common/RenderBundles.js +2 -1
  229. package/src/renderers/common/RenderContext.js +16 -0
  230. package/src/renderers/common/RenderContexts.js +33 -56
  231. package/src/renderers/common/RenderLists.js +2 -1
  232. package/src/renderers/common/RenderObject.js +2 -3
  233. package/src/renderers/common/RenderObjectPipeline.js +40 -0
  234. package/src/renderers/common/RenderObjects.js +18 -2
  235. package/src/renderers/common/RenderPipeline.js +203 -17
  236. package/src/renderers/common/Renderer.js +207 -40
  237. package/src/renderers/common/Sampler.js +4 -4
  238. package/src/renderers/common/StorageBuffer.js +13 -1
  239. package/src/renderers/common/Textures.js +16 -0
  240. package/src/renderers/common/TimestampQueryPool.js +5 -3
  241. package/src/renderers/common/Uniform.js +8 -0
  242. package/src/renderers/common/UniformsGroup.js +60 -0
  243. package/src/renderers/common/XRManager.js +2 -2
  244. package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
  245. package/src/renderers/common/nodes/{Nodes.js → NodeManager.js} +18 -6
  246. package/src/renderers/common/nodes/NodeStorageBuffer.js +13 -2
  247. package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +2 -2
  248. package/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js +1 -5
  249. package/src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl.js +1 -5
  250. package/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js +1 -5
  251. package/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js +8 -10
  252. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +7 -11
  253. package/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js +6 -0
  254. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +6 -2
  255. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +23 -1
  256. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +20 -4
  257. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +55 -24
  258. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +2 -0
  259. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +2 -0
  260. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +1 -0
  261. package/src/renderers/shaders/ShaderLib.js +4 -2
  262. package/src/renderers/shaders/UniformsLib.js +0 -3
  263. package/src/renderers/webgl/WebGLBackground.js +2 -2
  264. package/src/renderers/webgl/WebGLBindingStates.js +99 -27
  265. package/src/renderers/webgl/WebGLEnvironments.js +228 -0
  266. package/src/renderers/webgl/WebGLGeometries.js +10 -7
  267. package/src/renderers/webgl/WebGLMaterials.js +12 -0
  268. package/src/renderers/webgl/WebGLObjects.js +3 -1
  269. package/src/renderers/webgl/WebGLProgram.js +2 -2
  270. package/src/renderers/webgl/WebGLPrograms.js +10 -4
  271. package/src/renderers/webgl/WebGLRenderLists.js +15 -0
  272. package/src/renderers/webgl/WebGLShadowMap.js +5 -4
  273. package/src/renderers/webgl/WebGLState.js +12 -17
  274. package/src/renderers/webgl-fallback/WebGLBackend.js +71 -7
  275. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +98 -29
  276. package/src/renderers/webgl-fallback/utils/WebGLState.js +168 -7
  277. package/src/renderers/webgpu/WebGPUBackend.js +58 -9
  278. package/src/renderers/webgpu/WebGPURenderer.js +1 -0
  279. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +257 -45
  280. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +8 -19
  281. package/src/renderers/webgpu/utils/WebGPUConstants.js +1 -1
  282. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +56 -31
  283. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +152 -200
  284. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +25 -25
  285. package/src/renderers/webgpu/utils/WebGPUUtils.js +10 -6
  286. package/src/renderers/webxr/WebXRManager.js +2 -2
  287. package/src/textures/Texture.js +2 -2
  288. package/src/utils.js +246 -3
  289. package/examples/jsm/materials/MeshGouraudMaterial.js +0 -433
  290. package/examples/jsm/materials/MeshPostProcessingMaterial.js +0 -167
  291. package/examples/jsm/shaders/GodRaysShader.js +0 -333
  292. package/src/nodes/accessors/SceneNode.js +0 -145
  293. package/src/nodes/code/ScriptableNode.js +0 -726
  294. package/src/nodes/code/ScriptableValueNode.js +0 -253
  295. package/src/nodes/display/PosterizeNode.js +0 -65
  296. package/src/nodes/utils/SpriteSheetUVNode.js +0 -90
  297. package/src/renderers/webgl/WebGLCubeMaps.js +0 -99
  298. package/src/renderers/webgl/WebGLCubeUVMaps.js +0 -134
@@ -13,7 +13,7 @@ import WebGPUBindingUtils from './utils/WebGPUBindingUtils.js';
13
13
  import WebGPUPipelineUtils from './utils/WebGPUPipelineUtils.js';
14
14
  import WebGPUTextureUtils from './utils/WebGPUTextureUtils.js';
15
15
 
16
- import { WebGPUCoordinateSystem, TimestampQuery, REVISION, HalfFloatType } from '../../constants.js';
16
+ import { WebGPUCoordinateSystem, TimestampQuery, REVISION, HalfFloatType, Compatibility } from '../../constants.js';
17
17
  import WebGPUTimestampQueryPool from './utils/WebGPUTimestampQueryPool.js';
18
18
  import { warnOnce, error } from '../../utils.js';
19
19
 
@@ -30,8 +30,8 @@ class WebGPUBackend extends Backend {
30
30
  *
31
31
  * @typedef {Object} WebGPUBackend~Options
32
32
  * @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
33
+ * @property {boolean} [reversedDepthBuffer=false] - Whether reversed depth buffer is enabled or not.
33
34
  * @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
34
- * @property {boolean} [compatibilityMode=false] - Whether the backend should be in compatibility mode or not.
35
35
  * @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
36
36
  * @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
37
37
  * @property {boolean} [antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
@@ -64,16 +64,18 @@ class WebGPUBackend extends Backend {
64
64
 
65
65
  // some parameters require default values other than "undefined"
66
66
  this.parameters.alpha = ( parameters.alpha === undefined ) ? true : parameters.alpha;
67
- this.parameters.compatibilityMode = ( parameters.compatibilityMode === undefined ) ? false : parameters.compatibilityMode;
68
67
 
69
68
  this.parameters.requiredLimits = ( parameters.requiredLimits === undefined ) ? {} : parameters.requiredLimits;
70
69
 
71
70
  /**
72
- * Indicates whether the backend is in compatibility mode or not.
73
- * @type {boolean}
74
- * @default false
71
+ * Indicates whether the backend is in WebGPU compatibility mode or not.
72
+ * The backend must be initialized before the property can be evaluated.
73
+ *
74
+ * @type {?boolean}
75
+ * @readonly
76
+ * @default null
75
77
  */
76
- this.compatibilityMode = this.parameters.compatibilityMode;
78
+ this.compatibilityMode = null;
77
79
 
78
80
  /**
79
81
  * A reference to the device.
@@ -137,6 +139,19 @@ class WebGPUBackend extends Backend {
137
139
  */
138
140
  this.occludedResolveCache = new Map();
139
141
 
142
+ // compatibility checks
143
+
144
+ const compatibilityTextureCompare = typeof navigator === 'undefined' ? true : /Android/.test( navigator.userAgent ) === false;
145
+
146
+ /**
147
+ * A map of compatibility checks.
148
+ *
149
+ * @type {Object}
150
+ */
151
+ this._compatibility = {
152
+ [ Compatibility.TEXTURE_COMPARE ]: compatibilityTextureCompare
153
+ };
154
+
140
155
  }
141
156
 
142
157
  /**
@@ -162,7 +177,7 @@ class WebGPUBackend extends Backend {
162
177
 
163
178
  const adapterOptions = {
164
179
  powerPreference: parameters.powerPreference,
165
- featureLevel: parameters.compatibilityMode ? 'compatibility' : undefined
180
+ featureLevel: 'compatibility'
166
181
  };
167
182
 
168
183
  const adapter = ( typeof navigator !== 'undefined' ) ? await navigator.gpu.requestAdapter( adapterOptions ) : null;
@@ -202,6 +217,14 @@ class WebGPUBackend extends Backend {
202
217
 
203
218
  }
204
219
 
220
+ this.compatibilityMode = ! device.features.has( 'core-features-and-limits' );
221
+
222
+ if ( this.compatibilityMode ) {
223
+
224
+ renderer._samples = 0;
225
+
226
+ }
227
+
205
228
  device.lost.then( ( info ) => {
206
229
 
207
230
  if ( info.reason === 'destroyed' ) return;
@@ -1574,6 +1597,14 @@ class WebGPUBackend extends Backend {
1574
1597
 
1575
1598
  }
1576
1599
 
1600
+ let bytesPerElement = ( hasIndex === true ) ? index.array.BYTES_PER_ELEMENT : 1;
1601
+
1602
+ if ( material.wireframe ) {
1603
+
1604
+ bytesPerElement = object.geometry.attributes.position.count > 65535 ? 4 : 2;
1605
+
1606
+ }
1607
+
1577
1608
  for ( let i = 0; i < drawCount; i ++ ) {
1578
1609
 
1579
1610
  const count = drawInstances ? drawInstances[ i ] : 1;
@@ -1581,7 +1612,7 @@ class WebGPUBackend extends Backend {
1581
1612
 
1582
1613
  if ( hasIndex === true ) {
1583
1614
 
1584
- passEncoderGPU.drawIndexed( counts[ i ], count, starts[ i ] / index.array.BYTES_PER_ELEMENT, 0, firstInstance );
1615
+ passEncoderGPU.drawIndexed( counts[ i ], count, starts[ i ] / bytesPerElement, 0, firstInstance );
1585
1616
 
1586
1617
  } else {
1587
1618
 
@@ -2499,6 +2530,24 @@ class WebGPUBackend extends Backend {
2499
2530
 
2500
2531
  }
2501
2532
 
2533
+ /**
2534
+ * Checks if the given compatibility is supported by the backend.
2535
+ *
2536
+ * @param {string} name - The compatibility name.
2537
+ * @return {boolean} Whether the compatibility is supported or not.
2538
+ */
2539
+ hasCompatibility( name ) {
2540
+
2541
+ if ( this._compatibility[ Compatibility.TEXTURE_COMPARE ] !== undefined ) {
2542
+
2543
+ return this._compatibility[ Compatibility.TEXTURE_COMPARE ];
2544
+
2545
+ }
2546
+
2547
+ return super.hasCompatibility( name );
2548
+
2549
+ }
2550
+
2502
2551
  dispose() {
2503
2552
 
2504
2553
  this.bindingUtils.dispose();
@@ -32,6 +32,7 @@ class WebGPURenderer extends Renderer {
32
32
  *
33
33
  * @typedef {Object} WebGPURenderer~Options
34
34
  * @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
35
+ * @property {boolean} [reversedDepthBuffer=false] - Whether reversed depth buffer is enabled or not.
35
36
  * @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
36
37
  * @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
37
38
  * @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
@@ -16,7 +16,7 @@ import { NodeAccess } from '../../../nodes/core/constants.js';
16
16
  import VarNode from '../../../nodes/core/VarNode.js';
17
17
  import ExpressionNode from '../../../nodes/code/ExpressionNode.js';
18
18
 
19
- import { FloatType, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestFilter } from '../../../constants.js';
19
+ import { FloatType, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestFilter, Compatibility } from '../../../constants.js';
20
20
  import { warn, error } from '../../../utils.js';
21
21
 
22
22
  import { GPUShaderStage } from '../utils/WebGPUConstants.js';
@@ -112,6 +112,29 @@ fn tsl_biquadraticTexture( map : texture_2d<f32>, coord : vec2f, iRes : vec2u, l
112
112
 
113
113
  return mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );
114
114
 
115
+ }
116
+ ` ),
117
+ biquadraticTextureArray: new CodeNode( /* wgsl */`
118
+ fn tsl_biquadraticTexture_array( map : texture_2d_array<f32>, coord : vec2f, iRes : vec2u, layer : u32, level : u32 ) -> vec4f {
119
+
120
+ let res = vec2f( iRes );
121
+
122
+ let uvScaled = coord * res;
123
+ let uvWrapping = ( ( uvScaled % res ) + res ) % res;
124
+
125
+ // https://www.shadertoy.com/view/WtyXRy
126
+
127
+ let uv = uvWrapping - 0.5;
128
+ let iuv = floor( uv );
129
+ let f = fract( uv );
130
+
131
+ let rg1 = textureLoad( map, vec2u( iuv + vec2( 0.5, 0.5 ) ) % iRes, layer, level );
132
+ let rg2 = textureLoad( map, vec2u( iuv + vec2( 1.5, 0.5 ) ) % iRes, layer, level );
133
+ let rg3 = textureLoad( map, vec2u( iuv + vec2( 0.5, 1.5 ) ) % iRes, layer, level );
134
+ let rg4 = textureLoad( map, vec2u( iuv + vec2( 1.5, 1.5 ) ) % iRes, layer, level );
135
+
136
+ return mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );
137
+
115
138
  }
116
139
  ` )
117
140
  };
@@ -177,6 +200,14 @@ class WGSLNodeBuilder extends NodeBuilder {
177
200
  */
178
201
  this.uniformGroups = {};
179
202
 
203
+ /**
204
+ * A dictionary that holds the assigned binding indices for each uniform group.
205
+ * This ensures the same binding index is used across all shader stages.
206
+ *
207
+ * @type {Object<string,{index: number, id: number}>}
208
+ */
209
+ this.uniformGroupsBindings = {};
210
+
180
211
  /**
181
212
  * A dictionary that holds for each shader stage a Map of builtins.
182
213
  *
@@ -263,17 +294,31 @@ class WGSLNodeBuilder extends NodeBuilder {
263
294
 
264
295
  if ( this.isUnfilterable( texture ) === false ) {
265
296
 
266
- if ( offsetSnippet ) {
297
+ if ( depthSnippet ) {
267
298
 
268
- return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet }, ${ offsetSnippet } )`;
299
+ if ( offsetSnippet ) {
269
300
 
270
- }
301
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet }, ${ levelSnippet }, ${ offsetSnippet } )`;
302
+
303
+ }
304
+
305
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet }, ${ levelSnippet } )`;
271
306
 
272
- return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet } )`;
307
+ } else {
308
+
309
+ if ( offsetSnippet ) {
310
+
311
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet }, ${ offsetSnippet } )`;
312
+
313
+ }
314
+
315
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet } )`;
316
+
317
+ }
273
318
 
274
319
  } else if ( this.isFilteredTexture( texture ) ) {
275
320
 
276
- return this.generateFilteredTexture( texture, textureProperty, uvSnippet, offsetSnippet, levelSnippet );
321
+ return this.generateFilteredTexture( texture, textureProperty, uvSnippet, offsetSnippet, levelSnippet, depthSnippet );
277
322
 
278
323
  } else {
279
324
 
@@ -457,11 +502,10 @@ class WGSLNodeBuilder extends NodeBuilder {
457
502
  * @param {string} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling.
458
503
  * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
459
504
  * @param {string} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
505
+ * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
460
506
  * @return {string} The WGSL snippet.
461
507
  */
462
- generateFilteredTexture( texture, textureProperty, uvSnippet, offsetSnippet, levelSnippet = '0u' ) {
463
-
464
- this._include( 'biquadraticTexture' );
508
+ generateFilteredTexture( texture, textureProperty, uvSnippet, offsetSnippet, levelSnippet = '0u', depthSnippet ) {
465
509
 
466
510
  const wrapFunction = this.generateWrapFunction( texture );
467
511
  const textureDimension = this.generateTextureDimension( texture, textureProperty, levelSnippet );
@@ -472,6 +516,16 @@ class WGSLNodeBuilder extends NodeBuilder {
472
516
 
473
517
  }
474
518
 
519
+ if ( depthSnippet ) {
520
+
521
+ this._include( 'biquadraticTextureArray' );
522
+
523
+ return `tsl_biquadraticTexture_array( ${ textureProperty }, ${ wrapFunction }( ${ uvSnippet } ), ${ textureDimension }, u32( ${ depthSnippet } ), u32( ${ levelSnippet } ) )`;
524
+
525
+ }
526
+
527
+ this._include( 'biquadraticTexture' );
528
+
475
529
  return `tsl_biquadraticTexture( ${ textureProperty }, ${ wrapFunction }( ${ uvSnippet } ), ${ textureDimension }, u32( ${ levelSnippet } ) )`;
476
530
 
477
531
  }
@@ -490,10 +544,27 @@ class WGSLNodeBuilder extends NodeBuilder {
490
544
  */
491
545
  generateTextureLod( texture, textureProperty, uvSnippet, depthSnippet, offsetSnippet, levelSnippet = '0u' ) {
492
546
 
547
+ // Cube textures cannot use textureLoad in WGSL, must use textureSampleLevel
548
+ if ( texture.isCubeTexture === true ) {
549
+
550
+ if ( offsetSnippet ) {
551
+
552
+ uvSnippet = `${ uvSnippet } + vec3<f32>(${ offsetSnippet })`;
553
+
554
+ }
555
+
556
+ // Depth textures require integer level, regular textures use float
557
+ const levelType = texture.isDepthTexture ? 'u32' : 'f32';
558
+
559
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelType }( ${ levelSnippet } ) )`;
560
+
561
+ }
562
+
493
563
  const wrapFunction = this.generateWrapFunction( texture );
494
564
  const textureDimension = this.generateTextureDimension( texture, textureProperty, levelSnippet );
495
565
 
496
566
  const vecType = texture.is3DTexture || texture.isData3DTexture ? 'vec3' : 'vec2';
567
+ const textureDimensionMargin = ( vecType === 'vec3' ) ? 'vec3<u32>( 1, 1, 1 )' : 'vec2<u32>( 1, 1 )';
497
568
 
498
569
  if ( offsetSnippet ) {
499
570
 
@@ -501,9 +572,47 @@ class WGSLNodeBuilder extends NodeBuilder {
501
572
 
502
573
  }
503
574
 
504
- const coordSnippet = `${ vecType }<u32>( ${ wrapFunction }( ${ uvSnippet } ) * ${ vecType }<f32>( ${ textureDimension } ) )`;
575
+ const clampMin = `${ vecType }<f32>( 0 )`;
576
+ const clampMax = `${ vecType }<f32>( ${ textureDimension } - ${ textureDimensionMargin } )`;
577
+
578
+ uvSnippet = `${ vecType }<u32>( clamp( floor( ${ wrapFunction }( ${ uvSnippet } ) * ${ vecType }<f32>( ${ textureDimension } ) ), ${ clampMin }, ${ clampMax } ) )`;
579
+
580
+ return this.generateTextureLoad( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, null );
581
+
582
+ }
583
+
584
+ /**
585
+ * Generates the WGSL snippet that reads a single texel from a storage texture.
586
+ *
587
+ * @param {Texture} texture - The texture.
588
+ * @param {string} textureProperty - The name of the texture uniform in the shader.
589
+ * @param {string} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling.
590
+ * @param {?string} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture.
591
+ * @param {?string} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample.
592
+ * @param {?string} offsetSnippet - A WGSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
593
+ * @return {string} The WGSL snippet.
594
+ */
595
+ generateStorageTextureLoad( texture, textureProperty, uvIndexSnippet, levelSnippet, depthSnippet, offsetSnippet ) {
596
+
597
+ if ( offsetSnippet ) {
598
+
599
+ uvIndexSnippet = `${ uvIndexSnippet } + ${ offsetSnippet }`;
600
+
601
+ }
602
+
603
+ let snippet;
604
+
605
+ if ( depthSnippet ) {
606
+
607
+ snippet = `textureLoad( ${ textureProperty }, ${ uvIndexSnippet }, ${ depthSnippet } )`;
608
+
609
+ } else {
610
+
611
+ snippet = `textureLoad( ${ textureProperty }, ${ uvIndexSnippet } )`;
505
612
 
506
- return this.generateTextureLoad( texture, textureProperty, coordSnippet, levelSnippet, depthSnippet, null );
613
+ }
614
+
615
+ return snippet;
507
616
 
508
617
  }
509
618
 
@@ -586,7 +695,7 @@ class WGSLNodeBuilder extends NodeBuilder {
586
695
  */
587
696
  isSampleCompare( texture ) {
588
697
 
589
- return texture.isDepthTexture === true && texture.compareFunction !== null;
698
+ return texture.isDepthTexture === true && texture.compareFunction !== null && this.renderer.hasCompatibility( Compatibility.TEXTURE_COMPARE );
590
699
 
591
700
  }
592
701
 
@@ -650,14 +759,27 @@ class WGSLNodeBuilder extends NodeBuilder {
650
759
 
651
760
  if ( shaderStage === 'fragment' ) {
652
761
 
653
- // TODO handle i32 or u32 --> uvSnippet, array_index: A, ddx, ddy
654
- if ( offsetSnippet ) {
762
+ if ( depthSnippet ) {
655
763
 
656
- return `textureSampleGrad( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] }, ${ offsetSnippet } )`;
764
+ if ( offsetSnippet ) {
657
765
 
658
- }
766
+ return `textureSampleGrad( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] }, ${ offsetSnippet } )`;
767
+
768
+ }
769
+
770
+ return `textureSampleGrad( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`;
771
+
772
+ } else {
773
+
774
+ if ( offsetSnippet ) {
775
+
776
+ return `textureSampleGrad( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] }, ${ offsetSnippet } )`;
777
+
778
+ }
659
779
 
660
- return `textureSampleGrad( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`;
780
+ return `textureSampleGrad( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`;
781
+
782
+ }
661
783
 
662
784
  } else {
663
785
 
@@ -728,17 +850,31 @@ class WGSLNodeBuilder extends NodeBuilder {
728
850
 
729
851
  if ( this.isUnfilterable( texture ) === false ) {
730
852
 
731
- if ( offsetSnippet ) {
853
+ if ( depthSnippet ) {
732
854
 
733
- return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet }, ${ offsetSnippet } )`;
855
+ if ( offsetSnippet ) {
734
856
 
735
- }
857
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet }, ${ levelSnippet }, ${ offsetSnippet } )`;
858
+
859
+ }
860
+
861
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet }, ${ levelSnippet } )`;
862
+
863
+ } else {
864
+
865
+ if ( offsetSnippet ) {
866
+
867
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet }, ${ offsetSnippet } )`;
868
+
869
+ }
736
870
 
737
- return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet } )`;
871
+ return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet } )`;
872
+
873
+ }
738
874
 
739
875
  } else if ( this.isFilteredTexture( texture ) ) {
740
876
 
741
- return this.generateFilteredTexture( texture, textureProperty, uvSnippet, offsetSnippet, levelSnippet );
877
+ return this.generateFilteredTexture( texture, textureProperty, uvSnippet, offsetSnippet, levelSnippet, depthSnippet );
742
878
 
743
879
  } else {
744
880
 
@@ -764,13 +900,27 @@ class WGSLNodeBuilder extends NodeBuilder {
764
900
 
765
901
  if ( shaderStage === 'fragment' ) {
766
902
 
767
- if ( offsetSnippet ) {
903
+ if ( depthSnippet ) {
904
+
905
+ if ( offsetSnippet ) {
768
906
 
769
- return `textureSampleBias( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ biasSnippet }, ${ offsetSnippet } )`;
907
+ return `textureSampleBias( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet }, ${ biasSnippet }, ${ offsetSnippet } )`;
770
908
 
771
- }
909
+ }
910
+
911
+ return `textureSampleBias( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet }, ${ biasSnippet } )`;
912
+
913
+ } else {
914
+
915
+ if ( offsetSnippet ) {
916
+
917
+ return `textureSampleBias( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ biasSnippet }, ${ offsetSnippet } )`;
918
+
919
+ }
772
920
 
773
- return `textureSampleBias( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ biasSnippet } )`;
921
+ return `textureSampleBias( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ biasSnippet } )`;
922
+
923
+ }
774
924
 
775
925
  } else {
776
926
 
@@ -960,7 +1110,10 @@ class WGSLNodeBuilder extends NodeBuilder {
960
1110
  texture.mipLevel = texture.store ? node.mipLevel : 0;
961
1111
  texture.setVisibility( gpuShaderStageLib[ shaderStage ] );
962
1112
 
963
- if ( this.isUnfilterable( node.value ) === false && texture.store === false ) {
1113
+ // Cube textures always need samplers (they use textureSampleLevel, not textureLoad)
1114
+ const needsSampler = node.value.isCubeTexture === true || ( this.isUnfilterable( node.value ) === false && texture.store === false );
1115
+
1116
+ if ( needsSampler ) {
964
1117
 
965
1118
  const sampler = new NodeSampler( `${ uniformNode.name }_sampler`, uniformNode.node, group );
966
1119
  sampler.setVisibility( gpuShaderStageLib[ shaderStage ] );
@@ -1003,16 +1156,19 @@ class WGSLNodeBuilder extends NodeBuilder {
1003
1156
 
1004
1157
  } else {
1005
1158
 
1006
- const uniformsStage = this.uniformGroups[ shaderStage ] || ( this.uniformGroups[ shaderStage ] = {} );
1007
-
1008
- let uniformsGroup = uniformsStage[ groupName ];
1159
+ let uniformsGroup = this.uniformGroups[ groupName ];
1009
1160
 
1010
1161
  if ( uniformsGroup === undefined ) {
1011
1162
 
1012
1163
  uniformsGroup = new NodeUniformsGroup( groupName, group );
1013
- uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] );
1164
+ uniformsGroup.setVisibility( GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE );
1165
+
1166
+ this.uniformGroups[ groupName ] = uniformsGroup;
1014
1167
 
1015
- uniformsStage[ groupName ] = uniformsGroup;
1168
+ }
1169
+
1170
+ // Add to bindings for this stage if not already present
1171
+ if ( bindings.indexOf( uniformsGroup ) === - 1 ) {
1016
1172
 
1017
1173
  bindings.push( uniformsGroup );
1018
1174
 
@@ -1020,7 +1176,15 @@ class WGSLNodeBuilder extends NodeBuilder {
1020
1176
 
1021
1177
  uniformGPU = this.getNodeUniform( uniformNode, type );
1022
1178
 
1023
- uniformsGroup.addUniform( uniformGPU );
1179
+ // Only add uniform if not already present in the group (check by name to avoid duplicates across stages)
1180
+ const uniformName = uniformGPU.name;
1181
+ const alreadyExists = uniformsGroup.uniforms.some( u => u.name === uniformName );
1182
+
1183
+ if ( ! alreadyExists ) {
1184
+
1185
+ uniformsGroup.addUniform( uniformGPU );
1186
+
1187
+ }
1024
1188
 
1025
1189
  }
1026
1190
 
@@ -1626,7 +1790,7 @@ ${ flowData.code }
1626
1790
 
1627
1791
  if ( shaderStage === 'vertex' ) {
1628
1792
 
1629
- this.getBuiltin( 'position', 'Vertex', 'vec4<f32>', 'vertex' );
1793
+ this.getBuiltin( 'position', 'builtinClipSpace', 'vec4<f32>', 'vertex' );
1630
1794
 
1631
1795
  }
1632
1796
 
@@ -1653,7 +1817,7 @@ ${ flowData.code }
1653
1817
 
1654
1818
  } else if ( /^(int|uint|ivec|uvec)/.test( varying.type ) ) {
1655
1819
 
1656
- attributesSnippet += ` @interpolate( ${ this.renderer.backend.compatibilityMode ? 'flat, either' : 'flat' } )`;
1820
+ attributesSnippet += ' @interpolate(flat, either)';
1657
1821
 
1658
1822
  }
1659
1823
 
@@ -1718,7 +1882,10 @@ ${ flowData.code }
1718
1882
 
1719
1883
  const texture = uniform.node.value;
1720
1884
 
1721
- if ( this.isUnfilterable( texture ) === false && uniform.node.isStorageTextureNode !== true ) {
1885
+ // Cube textures always need samplers (they use textureSampleLevel, not textureLoad)
1886
+ const needsSampler = texture.isCubeTexture === true || ( this.isUnfilterable( texture ) === false && uniform.node.isStorageTextureNode !== true );
1887
+
1888
+ if ( needsSampler ) {
1722
1889
 
1723
1890
  if ( this.isSampleCompare( texture ) ) {
1724
1891
 
@@ -1817,16 +1984,51 @@ ${ flowData.code }
1817
1984
 
1818
1985
  } else {
1819
1986
 
1820
- const vectorType = this.getType( this.getVectorType( uniform.type ) );
1821
1987
  const groupName = uniform.groupNode.name;
1822
1988
 
1823
- const group = uniformGroups[ groupName ] || ( uniformGroups[ groupName ] = {
1824
- index: uniformIndexes.binding ++,
1825
- id: uniformIndexes.group,
1826
- snippets: []
1827
- } );
1989
+ // Check if this group has already been processed in this shader stage
1990
+ if ( uniformGroups[ groupName ] === undefined ) {
1991
+
1992
+ // Get the shared uniform group that contains uniforms from all stages
1993
+ const sharedUniformGroup = this.uniformGroups[ groupName ];
1994
+
1995
+ if ( sharedUniformGroup !== undefined ) {
1996
+
1997
+ // Generate snippets for ALL uniforms in this shared group
1998
+ const snippets = [];
1999
+
2000
+ for ( const sharedUniform of sharedUniformGroup.uniforms ) {
1828
2001
 
1829
- group.snippets.push( `\t${ uniform.name } : ${ vectorType }` );
2002
+ const type = sharedUniform.getType();
2003
+ const vectorType = this.getType( this.getVectorType( type ) );
2004
+ snippets.push( `\t${ sharedUniform.name } : ${ vectorType }` );
2005
+
2006
+ }
2007
+
2008
+ // Check if this group already has an assigned binding index (from another shader stage)
2009
+ let groupBinding = this.uniformGroupsBindings[ groupName ];
2010
+
2011
+ if ( groupBinding === undefined ) {
2012
+
2013
+ // First time processing this group - assign a new binding index
2014
+ groupBinding = {
2015
+ index: uniformIndexes.binding ++,
2016
+ id: uniformIndexes.group
2017
+ };
2018
+
2019
+ this.uniformGroupsBindings[ groupName ] = groupBinding;
2020
+
2021
+ }
2022
+
2023
+ uniformGroups[ groupName ] = {
2024
+ index: groupBinding.index,
2025
+ id: groupBinding.id,
2026
+ snippets: snippets
2027
+ };
2028
+
2029
+ }
2030
+
2031
+ }
1830
2032
 
1831
2033
  }
1832
2034
 
@@ -1901,7 +2103,7 @@ ${ flowData.code }
1901
2103
 
1902
2104
  if ( shaderStage === 'vertex' ) {
1903
2105
 
1904
- flow += `varyings.Vertex = ${ flowSlotData.result };`;
2106
+ flow += `varyings.builtinClipSpace = ${ flowSlotData.result };`;
1905
2107
 
1906
2108
  } else if ( shaderStage === 'fragment' ) {
1907
2109
 
@@ -2036,7 +2238,6 @@ ${ flowData.code }
2036
2238
 
2037
2239
  }
2038
2240
 
2039
-
2040
2241
  /**
2041
2242
  * Returns the WGSL type of the given node data type.
2042
2243
  *
@@ -2079,6 +2280,17 @@ ${ flowData.code }
2079
2280
 
2080
2281
  }
2081
2282
 
2283
+ /**
2284
+ * Returns the maximum uniform buffer size limit.
2285
+ *
2286
+ * @return {number} The maximum uniform buffer size in bytes.
2287
+ */
2288
+ getUniformBufferLimit() {
2289
+
2290
+ return this.renderer.backend.device.limits.maxUniformBufferBindingSize;
2291
+
2292
+ }
2293
+
2082
2294
  /**
2083
2295
  * Returns the native shader method name for a given generic name.
2084
2296
  *