@plastic-software/three 0.181.3 → 0.182.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 (253) hide show
  1. package/README.md +3 -4
  2. package/build/three.cjs +1192 -522
  3. package/build/three.core.js +345 -219
  4. package/build/three.core.min.js +1 -1
  5. package/build/three.module.js +864 -328
  6. package/build/three.module.min.js +1 -1
  7. package/build/three.tsl.js +15 -3
  8. package/build/three.tsl.min.js +1 -1
  9. package/build/three.webgpu.js +3660 -1545
  10. package/build/three.webgpu.min.js +1 -1
  11. package/build/three.webgpu.nodes.js +3659 -1544
  12. package/build/three.webgpu.nodes.min.js +1 -1
  13. package/examples/jsm/controls/MapControls.js +55 -1
  14. package/examples/jsm/controls/OrbitControls.js +6 -6
  15. package/examples/jsm/controls/TrackballControls.js +6 -6
  16. package/examples/jsm/csm/CSM.js +2 -1
  17. package/examples/jsm/environments/RoomEnvironment.js +2 -0
  18. package/examples/jsm/geometries/DecalGeometry.js +1 -1
  19. package/examples/jsm/helpers/LightProbeHelperGPU.js +1 -1
  20. package/examples/jsm/helpers/TextureHelperGPU.js +1 -1
  21. package/examples/jsm/inspector/Inspector.js +53 -9
  22. package/examples/jsm/inspector/RendererInspector.js +12 -2
  23. package/examples/jsm/inspector/tabs/Console.js +2 -2
  24. package/examples/jsm/inspector/tabs/Parameters.js +2 -2
  25. package/examples/jsm/inspector/tabs/Performance.js +2 -2
  26. package/examples/jsm/inspector/tabs/Viewer.js +4 -4
  27. package/examples/jsm/inspector/ui/Profiler.js +1836 -31
  28. package/examples/jsm/inspector/ui/Style.js +948 -13
  29. package/examples/jsm/inspector/ui/Tab.js +188 -1
  30. package/examples/jsm/inspector/ui/Values.js +17 -1
  31. package/examples/jsm/loaders/3DMLoader.js +5 -4
  32. package/examples/jsm/loaders/DRACOLoader.js +5 -5
  33. package/examples/jsm/loaders/FBXLoader.js +0 -2
  34. package/examples/jsm/loaders/HDRLoader.js +0 -1
  35. package/examples/jsm/loaders/KTX2Loader.js +16 -0
  36. package/examples/jsm/loaders/LDrawLoader.js +2 -3
  37. package/examples/jsm/loaders/PCDLoader.js +1 -0
  38. package/examples/jsm/loaders/SVGLoader.js +1 -1
  39. package/examples/jsm/loaders/TDSLoader.js +0 -2
  40. package/examples/jsm/loaders/TGALoader.js +0 -2
  41. package/examples/jsm/loaders/UltraHDRLoader.js +110 -137
  42. package/examples/jsm/loaders/VOXLoader.js +660 -117
  43. package/examples/jsm/loaders/VRMLLoader.js +2 -2
  44. package/examples/jsm/loaders/usd/USDCParser.js +1 -1
  45. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +1 -1
  46. package/examples/jsm/materials/MeshGouraudMaterial.js +0 -1
  47. package/examples/jsm/materials/WoodNodeMaterial.js +11 -11
  48. package/examples/jsm/math/Octree.js +131 -1
  49. package/examples/jsm/misc/Volume.js +0 -1
  50. package/examples/jsm/misc/VolumeSlice.js +0 -1
  51. package/examples/jsm/objects/SkyMesh.js +13 -3
  52. package/examples/jsm/physics/AmmoPhysics.js +12 -7
  53. package/examples/jsm/physics/JoltPhysics.js +3 -1
  54. package/examples/jsm/physics/RapierPhysics.js +3 -1
  55. package/examples/jsm/postprocessing/OutputPass.js +9 -0
  56. package/examples/jsm/postprocessing/RenderPass.js +10 -0
  57. package/examples/jsm/postprocessing/UnrealBloomPass.js +48 -18
  58. package/examples/jsm/renderers/Projector.js +268 -30
  59. package/examples/jsm/renderers/SVGRenderer.js +191 -58
  60. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +2 -4
  61. package/examples/jsm/transpiler/AST.js +44 -0
  62. package/examples/jsm/transpiler/GLSLDecoder.js +61 -4
  63. package/examples/jsm/transpiler/ShaderToyDecoder.js +2 -0
  64. package/examples/jsm/transpiler/TSLEncoder.js +46 -3
  65. package/examples/jsm/transpiler/TranspilerUtils.js +3 -3
  66. package/examples/jsm/transpiler/WGSLEncoder.js +27 -0
  67. package/examples/jsm/tsl/display/AnaglyphPassNode.js +2 -0
  68. package/examples/jsm/tsl/display/BloomNode.js +11 -1
  69. package/examples/jsm/tsl/display/GTAONode.js +3 -2
  70. package/examples/jsm/tsl/display/PixelationPassNode.js +2 -1
  71. package/examples/jsm/tsl/display/SSGINode.js +7 -19
  72. package/examples/jsm/tsl/display/SSRNode.js +1 -1
  73. package/examples/jsm/tsl/display/SSSNode.js +4 -2
  74. package/examples/jsm/tsl/display/StereoCompositePassNode.js +8 -1
  75. package/examples/jsm/tsl/display/TRAANode.js +265 -114
  76. package/examples/jsm/tsl/display/radialBlur.js +68 -0
  77. package/examples/jsm/utils/ShadowMapViewer.js +24 -10
  78. package/examples/jsm/utils/ShadowMapViewerGPU.js +1 -1
  79. package/examples/jsm/utils/WebGPUTextureUtils.js +1 -1
  80. package/package.json +14 -12
  81. package/src/Three.Core.js +1 -0
  82. package/src/Three.TSL.js +14 -2
  83. package/src/animation/AnimationUtils.js +1 -12
  84. package/src/animation/KeyframeTrack.js +1 -1
  85. package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
  86. package/src/animation/tracks/ColorKeyframeTrack.js +1 -1
  87. package/src/animation/tracks/NumberKeyframeTrack.js +1 -1
  88. package/src/animation/tracks/QuaternionKeyframeTrack.js +1 -1
  89. package/src/animation/tracks/StringKeyframeTrack.js +1 -1
  90. package/src/animation/tracks/VectorKeyframeTrack.js +1 -1
  91. package/src/constants.js +61 -5
  92. package/src/core/BufferGeometry.js +14 -2
  93. package/src/core/Raycaster.js +2 -2
  94. package/src/extras/PMREMGenerator.js +3 -10
  95. package/src/extras/TextureUtils.js +5 -1
  96. package/src/geometries/ExtrudeGeometry.js +2 -2
  97. package/src/geometries/PolyhedronGeometry.js +1 -1
  98. package/src/helpers/PointLightHelper.js +1 -1
  99. package/src/lights/DirectionalLight.js +13 -0
  100. package/src/lights/HemisphereLight.js +10 -0
  101. package/src/lights/Light.js +1 -11
  102. package/src/lights/LightProbe.js +0 -15
  103. package/src/lights/LightShadow.js +0 -3
  104. package/src/lights/PointLight.js +15 -0
  105. package/src/lights/PointLightShadow.js +0 -86
  106. package/src/lights/SpotLight.js +22 -1
  107. package/src/loaders/MaterialLoader.js +2 -1
  108. package/src/loaders/ObjectLoader.js +3 -1
  109. package/src/loaders/nodes/NodeLoader.js +2 -2
  110. package/src/materials/Material.js +2 -0
  111. package/src/materials/ShaderMaterial.js +20 -1
  112. package/src/materials/nodes/Line2NodeMaterial.js +2 -2
  113. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +3 -2
  114. package/src/materials/nodes/MeshStandardNodeMaterial.js +5 -4
  115. package/src/materials/nodes/NodeMaterial.js +59 -3
  116. package/src/materials/nodes/manager/NodeMaterialObserver.js +1 -1
  117. package/src/math/Matrix4.js +40 -40
  118. package/src/math/Sphere.js +1 -1
  119. package/src/math/Vector3.js +0 -2
  120. package/src/nodes/TSL.js +4 -1
  121. package/src/nodes/accessors/BatchNode.js +10 -10
  122. package/src/nodes/accessors/BufferAttributeNode.js +98 -12
  123. package/src/nodes/accessors/BufferNode.js +29 -2
  124. package/src/nodes/accessors/ClippingNode.js +4 -4
  125. package/src/nodes/accessors/CubeTextureNode.js +20 -1
  126. package/src/nodes/accessors/InstanceNode.js +69 -29
  127. package/src/nodes/accessors/MaterialNode.js +9 -1
  128. package/src/nodes/accessors/MaterialReferenceNode.js +1 -2
  129. package/src/nodes/accessors/ModelNode.js +1 -1
  130. package/src/nodes/accessors/Normal.js +2 -2
  131. package/src/nodes/accessors/ReferenceBaseNode.js +4 -4
  132. package/src/nodes/accessors/ReferenceNode.js +4 -4
  133. package/src/nodes/accessors/RendererReferenceNode.js +1 -2
  134. package/src/nodes/accessors/SkinningNode.js +15 -2
  135. package/src/nodes/accessors/StorageBufferNode.js +4 -2
  136. package/src/nodes/accessors/Tangent.js +1 -11
  137. package/src/nodes/accessors/Texture3DNode.js +26 -1
  138. package/src/nodes/accessors/UniformArrayNode.js +2 -2
  139. package/src/nodes/accessors/UserDataNode.js +1 -2
  140. package/src/nodes/accessors/VertexColorNode.js +1 -2
  141. package/src/nodes/code/FunctionNode.js +1 -2
  142. package/src/nodes/core/ArrayNode.js +20 -1
  143. package/src/nodes/core/AssignNode.js +2 -2
  144. package/src/nodes/core/AttributeNode.js +2 -2
  145. package/src/nodes/core/ContextNode.js +103 -4
  146. package/src/nodes/core/NodeBuilder.js +56 -14
  147. package/src/nodes/core/NodeFrame.js +12 -4
  148. package/src/nodes/core/NodeUtils.js +5 -5
  149. package/src/nodes/core/ParameterNode.js +1 -2
  150. package/src/nodes/core/PropertyNode.js +19 -3
  151. package/src/nodes/core/StackNode.js +56 -8
  152. package/src/nodes/core/StructNode.js +1 -2
  153. package/src/nodes/core/StructTypeNode.js +11 -17
  154. package/src/nodes/core/UniformNode.js +19 -4
  155. package/src/nodes/core/VarNode.js +46 -21
  156. package/src/nodes/display/NormalMapNode.js +37 -2
  157. package/src/nodes/display/PassNode.js +77 -7
  158. package/src/nodes/display/ScreenNode.js +1 -0
  159. package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +3 -3
  160. package/src/nodes/functions/BSDF/DFGLUT.js +56 -0
  161. package/src/nodes/functions/BSDF/EnvironmentBRDF.js +2 -2
  162. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +1 -1
  163. package/src/nodes/functions/PhysicalLightingModel.js +102 -43
  164. package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -2
  165. package/src/nodes/gpgpu/SubgroupFunctionNode.js +1 -1
  166. package/src/nodes/gpgpu/WorkgroupInfoNode.js +2 -3
  167. package/src/nodes/lighting/AnalyticLightNode.js +53 -0
  168. package/src/nodes/lighting/LightsNode.js +2 -2
  169. package/src/nodes/lighting/PointShadowNode.js +141 -140
  170. package/src/nodes/lighting/ShadowFilterNode.js +53 -37
  171. package/src/nodes/lighting/ShadowNode.js +53 -19
  172. package/src/nodes/math/BitcountNode.js +433 -0
  173. package/src/nodes/math/PackFloatNode.js +98 -0
  174. package/src/nodes/math/UnpackFloatNode.js +96 -0
  175. package/src/nodes/pmrem/PMREMNode.js +1 -1
  176. package/src/nodes/tsl/TSLCore.js +4 -4
  177. package/src/nodes/utils/ArrayElementNode.js +13 -0
  178. package/src/nodes/utils/EventNode.js +1 -2
  179. package/src/nodes/utils/Packing.js +13 -1
  180. package/src/nodes/utils/PostProcessingUtils.js +33 -1
  181. package/src/nodes/utils/ReflectorNode.js +1 -1
  182. package/src/nodes/utils/SampleNode.js +1 -1
  183. package/src/nodes/utils/UVUtils.js +26 -0
  184. package/src/objects/BatchedMesh.js +5 -2
  185. package/src/objects/Line.js +1 -1
  186. package/src/objects/Mesh.js +1 -1
  187. package/src/objects/Points.js +1 -1
  188. package/src/objects/Skeleton.js +9 -0
  189. package/src/renderers/WebGLRenderer.js +145 -33
  190. package/src/renderers/common/Backend.js +8 -0
  191. package/src/renderers/common/Background.js +19 -9
  192. package/src/renderers/common/Binding.js +11 -0
  193. package/src/renderers/common/Bindings.js +7 -7
  194. package/src/renderers/common/Buffer.js +40 -0
  195. package/src/renderers/common/ChainMap.js +30 -6
  196. package/src/renderers/common/Geometries.js +12 -0
  197. package/src/renderers/common/RenderContexts.js +8 -1
  198. package/src/renderers/common/RenderObject.js +14 -1
  199. package/src/renderers/common/Renderer.js +53 -35
  200. package/src/renderers/common/Textures.js +1 -1
  201. package/src/renderers/common/UniformsGroup.js +1 -0
  202. package/src/renderers/common/XRManager.js +1 -0
  203. package/src/renderers/common/extras/PMREMGenerator.js +2 -8
  204. package/src/renderers/common/nodes/NodeUniformBuffer.js +52 -0
  205. package/src/renderers/shaders/DFGLUTData.js +19 -34
  206. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +5 -2
  207. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +8 -4
  208. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +90 -51
  209. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +194 -186
  210. package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +1 -1
  211. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
  212. package/src/renderers/shaders/ShaderChunk.js +3 -3
  213. package/src/renderers/shaders/ShaderLib/depth.glsl.js +3 -0
  214. package/src/renderers/shaders/ShaderLib/{distanceRGBA.glsl.js → distance.glsl.js} +1 -2
  215. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -1
  216. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +1 -2
  217. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
  218. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -9
  219. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +0 -1
  220. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +0 -1
  221. package/src/renderers/shaders/ShaderLib/vsm.glsl.js +4 -6
  222. package/src/renderers/shaders/ShaderLib.js +3 -3
  223. package/src/renderers/webgl/WebGLCapabilities.js +3 -4
  224. package/src/renderers/webgl/WebGLLights.js +18 -1
  225. package/src/renderers/webgl/WebGLOutput.js +267 -0
  226. package/src/renderers/webgl/WebGLProgram.js +43 -107
  227. package/src/renderers/webgl/WebGLPrograms.js +35 -45
  228. package/src/renderers/webgl/WebGLShadowMap.js +188 -25
  229. package/src/renderers/webgl/WebGLState.js +20 -20
  230. package/src/renderers/webgl/WebGLTextures.js +89 -28
  231. package/src/renderers/webgl/WebGLUniforms.js +40 -3
  232. package/src/renderers/webgl/WebGLUtils.js +6 -2
  233. package/src/renderers/webgl-fallback/WebGLBackend.js +79 -13
  234. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +59 -7
  235. package/src/renderers/webgl-fallback/utils/WebGLState.js +18 -3
  236. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +5 -3
  237. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +9 -9
  238. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +6 -2
  239. package/src/renderers/webgpu/WebGPUBackend.js +61 -4
  240. package/src/renderers/webgpu/WebGPURenderer.js +1 -1
  241. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +65 -23
  242. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +4 -17
  243. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +354 -186
  244. package/src/renderers/webgpu/utils/WebGPUConstants.js +2 -0
  245. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +20 -7
  246. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +40 -17
  247. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +7 -7
  248. package/src/renderers/webgpu/utils/WebGPUUtils.js +7 -5
  249. package/src/textures/CubeDepthTexture.js +76 -0
  250. package/src/textures/Source.js +1 -1
  251. package/src/textures/Texture.js +1 -1
  252. package/src/utils.js +13 -1
  253. package/src/nodes/functions/BSDF/DFGApprox.js +0 -71
@@ -1,4 +1,5 @@
1
- import { nodeObject } from '../tsl/TSLBase.js';
1
+ import { nodeObject, vec3, float } from '../tsl/TSLBase.js';
2
+ import { dot, sqrt, saturate } from '../math/MathNode.js';
2
3
 
3
4
  /**
4
5
  * Packs a direction vector into a color value.
@@ -19,3 +20,14 @@ export const directionToColor = ( node ) => nodeObject( node ).mul( 0.5 ).add( 0
19
20
  * @return {Node<vec3>} The direction.
20
21
  */
21
22
  export const colorToDirection = ( node ) => nodeObject( node ).mul( 2.0 ).sub( 1 );
23
+
24
+ /**
25
+ * Unpacks a tangent space normal, reconstructing the Z component by projecting the X,Y coordinates onto the hemisphere.
26
+ * The X,Y coordinates are expected to be in the [-1, 1] range.
27
+ *
28
+ * @tsl
29
+ * @function
30
+ * @param {Node<vec2>} xy - The X,Y coordinates of the normal.
31
+ * @return {Node<vec3>} The resulting normal.
32
+ */
33
+ export const unpackNormal = ( xy ) => vec3( xy, sqrt( saturate( float( 1.0 ).sub( dot( xy, xy ) ) ) ) );
@@ -1,4 +1,5 @@
1
- import { abs, cross, float, Fn, normalize, ivec2, sub, vec2, vec3, vec4, fract, dot } from '../tsl/TSLBase.js';
1
+ import { abs, cross, float, Fn, normalize, ivec2, sub, vec2, vec3, vec4, fract, dot, cos, sin } from '../tsl/TSLBase.js';
2
+ import { sqrt } from '../math/MathNode.js';
2
3
  import { textureSize } from '../accessors/TextureSizeNode.js';
3
4
  import { textureLoad } from '../accessors/TextureNode.js';
4
5
  import { WebGPUCoordinateSystem } from '../../constants.js';
@@ -120,3 +121,34 @@ export const interleavedGradientNoise = Fn( ( [ position ] ) => {
120
121
  { name: 'position', type: 'vec2' }
121
122
  ]
122
123
  } );
124
+
125
+ /**
126
+ * Vogel disk sampling for uniform circular distribution.
127
+ *
128
+ * This function generates sample points distributed uniformly on a disk using the golden angle,
129
+ * resulting in an efficient low-discrepancy sequence for sampling. The rotation parameter (phi)
130
+ * allows randomizing the pattern per-pixel when combined with IGN.
131
+ *
132
+ * @tsl
133
+ * @function
134
+ * @param {Node<int>} sampleIndex - The index of the current sample (0-based).
135
+ * @param {Node<int>} samplesCount - The total number of samples.
136
+ * @param {Node<float>} phi - Rotation angle in radians (typically from IGN * 2π).
137
+ * @return {Node<vec2>} A 2D point on the unit disk.
138
+ */
139
+ export const vogelDiskSample = Fn( ( [ sampleIndex, samplesCount, phi ] ) => {
140
+
141
+ const goldenAngle = float( 2.399963229728653 ); // 2π * (2 - φ) where φ is golden ratio
142
+ const r = sqrt( float( sampleIndex ).add( 0.5 ).div( float( samplesCount ) ) );
143
+ const theta = float( sampleIndex ).mul( goldenAngle ).add( phi );
144
+ return vec2( cos( theta ), sin( theta ) ).mul( r );
145
+
146
+ } ).setLayout( {
147
+ name: 'vogelDiskSample',
148
+ type: 'vec2',
149
+ inputs: [
150
+ { name: 'sampleIndex', type: 'int' },
151
+ { name: 'samplesCount', type: 'int' },
152
+ { name: 'phi', type: 'float' }
153
+ ]
154
+ } );
@@ -625,6 +625,6 @@ class ReflectorBaseNode extends Node {
625
625
  * @param {ReflectorBaseNode} [parameters.reflector] - The reflector base node.
626
626
  * @returns {ReflectorNode}
627
627
  */
628
- export const reflector = ( parameters ) => nodeObject( new ReflectorNode( parameters ) );
628
+ export const reflector = ( parameters ) => new ReflectorNode( parameters );
629
629
 
630
630
  export default ReflectorNode;
@@ -88,4 +88,4 @@ export default SampleNode;
88
88
  * @param {?Node<vec2>} [uv=null] - The UV node to be used in the texture sampling.
89
89
  * @returns {SampleNode} The created SampleNode instance wrapped as a node object.
90
90
  */
91
- export const sample = ( callback, uv = null ) => nodeObject( new SampleNode( callback, nodeObject( uv ) ) );
91
+ export const sample = ( callback, uv = null ) => new SampleNode( callback, nodeObject( uv ) );
@@ -1,5 +1,31 @@
1
1
  import { Fn, vec2 } from '../tsl/TSLBase.js';
2
2
  import { rotate } from './RotateNode.js';
3
+ import { context } from '../core/ContextNode.js';
4
+
5
+ /**
6
+ * Replaces the default UV coordinates used in texture lookups.
7
+ *
8
+ * ```js
9
+ *material.contextNode = replaceDefaultUV( ( textureNode ) => {
10
+ *
11
+ * // ...
12
+ * return customUVCoordinates;
13
+ *
14
+ *} );
15
+ *```
16
+ *
17
+ * @tsl
18
+ * @function
19
+ * @param {function(Node):Node<vec2>} callback - A callback that receives the texture node
20
+ * and must return the new uv coordinates.
21
+ * @param {Node} [node=null] - An optional node to which the context will be applied.
22
+ * @return {ContextNode} A context node that replaces the default UV coordinates.
23
+ */
24
+ export function replaceDefaultUV( callback, node = null ) {
25
+
26
+ return context( node, { getUV: callback } );
27
+
28
+ }
3
29
 
4
30
  /**
5
31
  * Rotates the given uv coordinates around a center point
@@ -871,10 +871,9 @@ class BatchedMesh extends Mesh {
871
871
  }
872
872
 
873
873
  /**
874
- * Repacks the sub geometries in [name] to remove any unused space remaining from
874
+ * Repacks the sub geometries in BatchedMesh to remove any unused space remaining from
875
875
  * previously deleted geometry, freeing up space to add new geometry.
876
876
  *
877
- * @param {number} instanceId - The ID of the instance to remove from the batch.
878
877
  * @return {BatchedMesh} A reference to this batched mesh.
879
878
  */
880
879
  optimize() {
@@ -926,6 +925,7 @@ class BatchedMesh extends Mesh {
926
925
 
927
926
  index.array.copyWithin( nextIndexStart, indexStart, indexStart + reservedIndexCount );
928
927
  index.addUpdateRange( nextIndexStart, reservedIndexCount );
928
+ index.needsUpdate = true;
929
929
 
930
930
  geometryInfo.indexStart = nextIndexStart;
931
931
 
@@ -946,6 +946,7 @@ class BatchedMesh extends Mesh {
946
946
  const { array, itemSize } = attribute;
947
947
  array.copyWithin( nextVertexStart * itemSize, vertexStart * itemSize, ( vertexStart + reservedVertexCount ) * itemSize );
948
948
  attribute.addUpdateRange( nextVertexStart * itemSize, reservedVertexCount * itemSize );
949
+ attribute.needsUpdate = true;
949
950
 
950
951
  }
951
952
 
@@ -962,6 +963,8 @@ class BatchedMesh extends Mesh {
962
963
 
963
964
  }
964
965
 
966
+ this._visibilityChanged = true;
967
+
965
968
  return this;
966
969
 
967
970
  }
@@ -81,7 +81,7 @@ class Line extends Object3D {
81
81
  * morph targets name, the value its attribute index. This member is `undefined`
82
82
  * by default and only set when morph targets are detected in the geometry.
83
83
  *
84
- * @type {Object<String,number>|undefined}
84
+ * @type {Object<string,number>|undefined}
85
85
  * @default undefined
86
86
  */
87
87
  this.morphTargetDictionary = undefined;
@@ -79,7 +79,7 @@ class Mesh extends Object3D {
79
79
  * morph targets name, the value its attribute index. This member is `undefined`
80
80
  * by default and only set when morph targets are detected in the geometry.
81
81
  *
82
- * @type {Object<String,number>|undefined}
82
+ * @type {Object<string,number>|undefined}
83
83
  * @default undefined
84
84
  */
85
85
  this.morphTargetDictionary = undefined;
@@ -59,7 +59,7 @@ class Points extends Object3D {
59
59
  * morph targets name, the value its attribute index. This member is `undefined`
60
60
  * by default and only set when morph targets are detected in the geometry.
61
61
  *
62
- * @type {Object<String,number>|undefined}
62
+ * @type {Object<string,number>|undefined}
63
63
  * @default undefined
64
64
  */
65
65
  this.morphTargetDictionary = undefined;
@@ -70,6 +70,15 @@ class Skeleton {
70
70
  */
71
71
  this.boneMatrices = null;
72
72
 
73
+ /**
74
+ * An array buffer holding the bone data of the previous frame.
75
+ * Required for computing velocity. Maintained in {@link SkinningNode}.
76
+ *
77
+ * @type {?Float32Array}
78
+ * @default null
79
+ */
80
+ this.previousBoneMatrices = null;
81
+
73
82
  /**
74
83
  * A texture holding the bone data for use
75
84
  * in the vertex shader.
@@ -39,6 +39,7 @@ import { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer.j
39
39
  import { WebGLInfo } from './webgl/WebGLInfo.js';
40
40
  import { WebGLMorphtargets } from './webgl/WebGLMorphtargets.js';
41
41
  import { WebGLObjects } from './webgl/WebGLObjects.js';
42
+ import { WebGLOutput } from './webgl/WebGLOutput.js';
42
43
  import { WebGLPrograms } from './webgl/WebGLPrograms.js';
43
44
  import { WebGLProperties } from './webgl/WebGLProperties.js';
44
45
  import { WebGLRenderLists } from './webgl/WebGLRenderLists.js';
@@ -82,6 +83,7 @@ class WebGLRenderer {
82
83
  powerPreference = 'default',
83
84
  failIfMajorPerformanceCaveat = false,
84
85
  reversedDepthBuffer = false,
86
+ outputBufferType = UnsignedByteType,
85
87
  } = parameters;
86
88
 
87
89
  /**
@@ -111,6 +113,8 @@ class WebGLRenderer {
111
113
 
112
114
  }
113
115
 
116
+ const _outputBufferType = outputBufferType;
117
+
114
118
  const INTEGER_FORMATS = new Set( [
115
119
  RGBAIntegerFormat,
116
120
  RGIntegerFormat,
@@ -138,6 +142,10 @@ class WebGLRenderer {
138
142
  const renderListStack = [];
139
143
  const renderStateStack = [];
140
144
 
145
+ // internal render target for non-UnsignedByteType color buffer
146
+
147
+ let output = null;
148
+
141
149
  // public properties
142
150
 
143
151
  /**
@@ -398,10 +406,10 @@ class WebGLRenderer {
398
406
 
399
407
  }
400
408
 
401
- } catch ( error ) {
409
+ } catch ( e ) {
402
410
 
403
- error( 'WebGLRenderer: ' + error.message );
404
- throw error;
411
+ error( 'WebGLRenderer: ' + e.message );
412
+ throw e;
405
413
 
406
414
  }
407
415
 
@@ -533,6 +541,14 @@ class WebGLRenderer {
533
541
 
534
542
  initGLContext();
535
543
 
544
+ // initialize internal render target for non-UnsignedByteType color buffer
545
+
546
+ if ( _outputBufferType !== UnsignedByteType ) {
547
+
548
+ output = new WebGLOutput( _outputBufferType, canvas.width, canvas.height, depth, stencil );
549
+
550
+ }
551
+
536
552
  // xr
537
553
 
538
554
  const xr = new WebXRManager( _this, _gl );
@@ -655,6 +671,12 @@ class WebGLRenderer {
655
671
 
656
672
  }
657
673
 
674
+ if ( output !== null ) {
675
+
676
+ output.setSize( canvas.width, canvas.height );
677
+
678
+ }
679
+
658
680
  this.setViewport( 0, 0, width, height );
659
681
 
660
682
  };
@@ -698,6 +720,39 @@ class WebGLRenderer {
698
720
 
699
721
  };
700
722
 
723
+ /**
724
+ * Sets the post-processing effects to be applied after rendering.
725
+ *
726
+ * @param {Array} effects - An array of post-processing effects.
727
+ */
728
+ this.setEffects = function ( effects ) {
729
+
730
+ if ( _outputBufferType === UnsignedByteType ) {
731
+
732
+ console.error( 'THREE.WebGLRenderer: setEffects() requires outputBufferType set to HalfFloatType or FloatType.' );
733
+ return;
734
+
735
+ }
736
+
737
+ if ( effects ) {
738
+
739
+ for ( let i = 0; i < effects.length; i ++ ) {
740
+
741
+ if ( effects[ i ].isOutputPass === true ) {
742
+
743
+ console.warn( 'THREE.WebGLRenderer: OutputPass is not needed in setEffects(). Tone mapping and color space conversion are applied automatically.' );
744
+ break;
745
+
746
+ }
747
+
748
+ }
749
+
750
+ }
751
+
752
+ output.setEffects( effects || [] );
753
+
754
+ };
755
+
701
756
  /**
702
757
  * Returns the current viewport definition.
703
758
  *
@@ -1547,6 +1602,12 @@ class WebGLRenderer {
1547
1602
 
1548
1603
  if ( _isContextLost === true ) return;
1549
1604
 
1605
+ // use internal render target for HalfFloatType color buffer (only when tone mapping is enabled)
1606
+
1607
+ const isXRPresenting = xr.enabled === true && xr.isPresenting === true;
1608
+
1609
+ const useOutput = output !== null && ( _currentRenderTarget === null || isXRPresenting ) && output.begin( _this, _currentRenderTarget );
1610
+
1550
1611
  // update scene graph
1551
1612
 
1552
1613
  if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
@@ -1555,7 +1616,7 @@ class WebGLRenderer {
1555
1616
 
1556
1617
  if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
1557
1618
 
1558
- if ( xr.enabled === true && xr.isPresenting === true ) {
1619
+ if ( xr.enabled === true && xr.isPresenting === true && ( output === null || output.isCompositing() === false ) ) {
1559
1620
 
1560
1621
  if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera );
1561
1622
 
@@ -1627,46 +1688,52 @@ class WebGLRenderer {
1627
1688
 
1628
1689
  if ( this.info.autoReset === true ) this.info.reset();
1629
1690
 
1630
- // render scene
1691
+ // render scene (skip if first effect is a render pass - it will render the scene itself)
1631
1692
 
1632
- const opaqueObjects = currentRenderList.opaque;
1633
- const transmissiveObjects = currentRenderList.transmissive;
1693
+ const skipSceneRender = useOutput && output.hasRenderPass();
1634
1694
 
1635
- currentRenderState.setupLights();
1695
+ if ( skipSceneRender === false ) {
1636
1696
 
1637
- if ( camera.isArrayCamera ) {
1697
+ const opaqueObjects = currentRenderList.opaque;
1698
+ const transmissiveObjects = currentRenderList.transmissive;
1638
1699
 
1639
- const cameras = camera.cameras;
1700
+ currentRenderState.setupLights();
1640
1701
 
1641
- if ( transmissiveObjects.length > 0 ) {
1702
+ if ( camera.isArrayCamera ) {
1642
1703
 
1643
- for ( let i = 0, l = cameras.length; i < l; i ++ ) {
1704
+ const cameras = camera.cameras;
1644
1705
 
1645
- const camera2 = cameras[ i ];
1706
+ if ( transmissiveObjects.length > 0 ) {
1707
+
1708
+ for ( let i = 0, l = cameras.length; i < l; i ++ ) {
1709
+
1710
+ const camera2 = cameras[ i ];
1646
1711
 
1647
- renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 );
1712
+ renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 );
1713
+
1714
+ }
1648
1715
 
1649
1716
  }
1650
1717
 
1651
- }
1718
+ if ( _renderBackground ) background.render( scene );
1652
1719
 
1653
- if ( _renderBackground ) background.render( scene );
1720
+ for ( let i = 0, l = cameras.length; i < l; i ++ ) {
1654
1721
 
1655
- for ( let i = 0, l = cameras.length; i < l; i ++ ) {
1722
+ const camera2 = cameras[ i ];
1656
1723
 
1657
- const camera2 = cameras[ i ];
1724
+ renderScene( currentRenderList, scene, camera2, camera2.viewport );
1658
1725
 
1659
- renderScene( currentRenderList, scene, camera2, camera2.viewport );
1726
+ }
1660
1727
 
1661
- }
1728
+ } else {
1662
1729
 
1663
- } else {
1730
+ if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera );
1664
1731
 
1665
- if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera );
1732
+ if ( _renderBackground ) background.render( scene );
1666
1733
 
1667
- if ( _renderBackground ) background.render( scene );
1734
+ renderScene( currentRenderList, scene, camera );
1668
1735
 
1669
- renderScene( currentRenderList, scene, camera );
1736
+ }
1670
1737
 
1671
1738
  }
1672
1739
 
@@ -1684,6 +1751,14 @@ class WebGLRenderer {
1684
1751
 
1685
1752
  }
1686
1753
 
1754
+ // copy from internal render target to canvas using fullscreen quad
1755
+
1756
+ if ( useOutput ) {
1757
+
1758
+ output.end( _this );
1759
+
1760
+ }
1761
+
1687
1762
  //
1688
1763
 
1689
1764
  if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
@@ -1872,11 +1947,13 @@ class WebGLRenderer {
1872
1947
 
1873
1948
  if ( currentRenderState.state.transmissionRenderTarget[ camera.id ] === undefined ) {
1874
1949
 
1950
+ const hasHalfFloatSupport = extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' );
1951
+
1875
1952
  currentRenderState.state.transmissionRenderTarget[ camera.id ] = new WebGLRenderTarget( 1, 1, {
1876
1953
  generateMipmaps: true,
1877
- type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType,
1954
+ type: hasHalfFloatSupport ? HalfFloatType : UnsignedByteType,
1878
1955
  minFilter: LinearMipmapLinearFilter,
1879
- samples: 4,
1956
+ samples: capabilities.samples,
1880
1957
  stencilBuffer: stencil,
1881
1958
  resolveDepthBuffer: false,
1882
1959
  resolveStencilBuffer: false,
@@ -2452,6 +2529,30 @@ class WebGLRenderer {
2452
2529
 
2453
2530
  }
2454
2531
 
2532
+ // Pre-allocate texture units for shadow samplers before setting data textures
2533
+ if ( materialProperties.needsLights ) {
2534
+
2535
+ // Set shadow map uniforms first to ensure they get the first texture units
2536
+ if ( lights.state.directionalShadowMap.length > 0 ) {
2537
+
2538
+ p_uniforms.setValue( _gl, 'directionalShadowMap', lights.state.directionalShadowMap, textures );
2539
+
2540
+ }
2541
+
2542
+ if ( lights.state.spotShadowMap.length > 0 ) {
2543
+
2544
+ p_uniforms.setValue( _gl, 'spotShadowMap', lights.state.spotShadowMap, textures );
2545
+
2546
+ }
2547
+
2548
+ if ( lights.state.pointShadowMap.length > 0 ) {
2549
+
2550
+ p_uniforms.setValue( _gl, 'pointShadowMap', lights.state.pointShadowMap, textures );
2551
+
2552
+ }
2553
+
2554
+ }
2555
+
2455
2556
  // skinning and morph target uniforms must be set even if material didn't change
2456
2557
  // auto-setting of texture unit for bone and morph texture must go before other textures
2457
2558
  // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures
@@ -2714,7 +2815,6 @@ class WebGLRenderer {
2714
2815
  _currentActiveCubeFace = activeCubeFace;
2715
2816
  _currentActiveMipmapLevel = activeMipmapLevel;
2716
2817
 
2717
- let useDefaultFramebuffer = true;
2718
2818
  let framebuffer = null;
2719
2819
  let isCube = false;
2720
2820
  let isRenderTarget3D = false;
@@ -2725,9 +2825,21 @@ class WebGLRenderer {
2725
2825
 
2726
2826
  if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) {
2727
2827
 
2728
- // We need to make sure to rebind the framebuffer.
2729
- state.bindFramebuffer( _gl.FRAMEBUFFER, null );
2730
- useDefaultFramebuffer = false;
2828
+ // Externally-managed framebuffer (e.g. XR)
2829
+ // Bind to the stored framebuffer (may be null for default, or a WebGLFramebuffer)
2830
+ state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
2831
+
2832
+ _currentViewport.copy( renderTarget.viewport );
2833
+ _currentScissor.copy( renderTarget.scissor );
2834
+ _currentScissorTest = renderTarget.scissorTest;
2835
+
2836
+ state.viewport( _currentViewport );
2837
+ state.scissor( _currentScissor );
2838
+ state.setScissorTest( _currentScissorTest );
2839
+
2840
+ _currentMaterialId = - 1;
2841
+
2842
+ return;
2731
2843
 
2732
2844
  } else if ( renderTargetProperties.__webglFramebuffer === undefined ) {
2733
2845
 
@@ -2826,7 +2938,7 @@ class WebGLRenderer {
2826
2938
 
2827
2939
  const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
2828
2940
 
2829
- if ( framebufferBound && useDefaultFramebuffer ) {
2941
+ if ( framebufferBound ) {
2830
2942
 
2831
2943
  state.drawBuffers( renderTarget, framebuffer );
2832
2944
 
@@ -3461,6 +3573,7 @@ class WebGLRenderer {
3461
3573
  * Note that this setting uses `gl_FragDepth` if available which disables the Early Fragment Test optimization and can cause a decrease in performance.
3462
3574
  * @property {boolean} [reversedDepthBuffer=false] Whether to use a reverse depth buffer. Requires the `EXT_clip_control` extension.
3463
3575
  * This is a more faster and accurate version than logarithmic depth buffer.
3576
+ * @property {number} [outputBufferType=UnsignedByteType] Defines the type of the output buffer. Use `HalfFloatType` for HDR rendering with tone mapping and post-processing support.
3464
3577
  **/
3465
3578
 
3466
3579
  /**
@@ -3482,7 +3595,6 @@ class WebGLRenderer {
3482
3595
  * @property {string} precision - The shader precision currently being used by the renderer.
3483
3596
  * @property {boolean} reversedDepthBuffer - `true` if `reversedDepthBuffer` was set to `true` in the constructor
3484
3597
  * and the rendering context supports `EXT_clip_control`.
3485
- * @property {boolean} vertexTextures - `true` if vertex textures can be used.
3486
3598
  **/
3487
3599
 
3488
3600
  /**
@@ -3524,7 +3636,7 @@ class WebGLRenderer {
3524
3636
  * If you do not require dynamic lighting / shadows, you may set this to `false`.
3525
3637
  * @property {boolean} [needsUpdate=false] - When set to `true`, shadow maps in the scene
3526
3638
  * will be updated in the next `render` call.
3527
- * @property {(BasicShadowMap|PCFShadowMap|PCFSoftShadowMap|VSMShadowMap)} [type=PCFShadowMap] - Defines the shadow map type.
3639
+ * @property {(BasicShadowMap|PCFShadowMap|VSMShadowMap)} [type=PCFShadowMap] - Defines the shadow map type.
3528
3640
  **/
3529
3641
 
3530
3642
  export { WebGLRenderer };
@@ -736,6 +736,14 @@ class Backend {
736
736
 
737
737
  }
738
738
 
739
+ /**
740
+ * Delete GPU data associated with a bind group.
741
+ *
742
+ * @abstract
743
+ * @param {BindGroup} bindGroup - The bind group.
744
+ */
745
+ deleteBindGroupData( /*bindGroup*/ ) { }
746
+
739
747
  /**
740
748
  * Frees internal resources.
741
749
  *
@@ -1,6 +1,6 @@
1
1
  import DataMap from './DataMap.js';
2
2
  import Color4 from './Color4.js';
3
- import { vec4, context, normalWorldGeometry, backgroundBlurriness, backgroundIntensity, backgroundRotation, modelViewProjection } from '../../nodes/TSL.js';
3
+ import { vec4, normalWorldGeometry, backgroundBlurriness, backgroundIntensity, backgroundRotation, positionLocal, cameraProjectionMatrix, modelViewMatrix, div } from '../../nodes/TSL.js';
4
4
  import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
5
5
 
6
6
  import { Mesh } from '../../objects/Mesh.js';
@@ -88,13 +88,29 @@ class Background extends DataMap {
88
88
 
89
89
  if ( backgroundMesh === undefined ) {
90
90
 
91
- const backgroundMeshNode = context( vec4( backgroundNode ).mul( backgroundIntensity ), {
91
+ const backgroundMeshNode = vec4( backgroundNode ).mul( backgroundIntensity ).context( {
92
92
  // @TODO: Add Texture2D support using node context
93
93
  getUV: () => backgroundRotation.mul( normalWorldGeometry ),
94
94
  getTextureLevel: () => backgroundBlurriness
95
95
  } );
96
96
 
97
- let viewProj = modelViewProjection;
97
+ // when using orthographic cameras, we must scale the skybox sphere
98
+ // up to exceed the dimensions of the camera's viewing box.
99
+ const isOrtho = cameraProjectionMatrix.element( 3 ).element( 3 ).equal( 1.0 );
100
+
101
+ // calculate the orthographic scale
102
+ // projectionMatrix[1][1] is (1 / top). Invert it to get the height and multiply by 3.0
103
+ // (an arbitrary safety factor) to ensure the skybox is large enough to cover the corners
104
+ // of the rectangular screen
105
+ const orthoScale = div( 1.0, cameraProjectionMatrix.element( 1 ).element( 1 ) ).mul( 3.0 );
106
+
107
+ // compute vertex position
108
+ const modifiedPosition = isOrtho.select( positionLocal.mul( orthoScale ), positionLocal );
109
+
110
+ // By using a w component of 0, the skybox will not translate when the camera moves through the scene
111
+ let viewProj = cameraProjectionMatrix.mul( modelViewMatrix.mul( vec4( modifiedPosition, 0.0 ) ) );
112
+
113
+ // force background to far plane so it does not occlude objects
98
114
  viewProj = viewProj.setZ( viewProj.w );
99
115
 
100
116
  const nodeMaterial = new NodeMaterial();
@@ -113,12 +129,6 @@ class Background extends DataMap {
113
129
  backgroundMesh.frustumCulled = false;
114
130
  backgroundMesh.name = 'Background.mesh';
115
131
 
116
- backgroundMesh.onBeforeRender = function ( renderer, scene, camera ) {
117
-
118
- this.matrixWorld.copyPosition( camera.matrixWorld );
119
-
120
- };
121
-
122
132
  function onBackgroundDispose() {
123
133
 
124
134
  background.removeEventListener( 'dispose', onBackgroundDispose );
@@ -44,6 +44,17 @@ class Binding {
44
44
 
45
45
  }
46
46
 
47
+ /**
48
+ * The shader stages in which the binding's resource is visible.
49
+ *
50
+ * @return {number} The visibility bitmask.
51
+ */
52
+ getVisibility() {
53
+
54
+ return this.visibility;
55
+
56
+ }
57
+
47
58
  /**
48
59
  * Clones the binding.
49
60
  *
@@ -164,6 +164,7 @@ class Bindings extends DataMap {
164
164
 
165
165
  for ( const bindGroup of bindings ) {
166
166
 
167
+ this.backend.deleteBindGroupData( bindGroup );
167
168
  this.delete( bindGroup );
168
169
 
169
170
  }
@@ -181,6 +182,7 @@ class Bindings extends DataMap {
181
182
 
182
183
  for ( const bindGroup of bindings ) {
183
184
 
185
+ this.backend.deleteBindGroupData( bindGroup );
184
186
  this.delete( bindGroup );
185
187
 
186
188
  }
@@ -251,16 +253,14 @@ class Bindings extends DataMap {
251
253
 
252
254
  for ( const binding of bindGroup.bindings ) {
253
255
 
254
- if ( binding.isNodeUniformsGroup ) {
256
+ const updatedGroup = this.nodes.updateGroup( binding );
255
257
 
256
- const updated = this.nodes.updateGroup( binding );
258
+ // every uniforms group is a uniform buffer. So if no update is required,
259
+ // we move one with the next binding. Otherwise the next if block will update the group.
257
260
 
258
- // every uniforms group is a uniform buffer. So if no update is required,
259
- // we move one with the next binding. Otherwise the next if block will update the group.
261
+ if ( updatedGroup === false ) continue;
260
262
 
261
- if ( updated === false ) continue;
262
-
263
- }
263
+ //
264
264
 
265
265
  if ( binding.isStorageBuffer ) {
266
266