@unikia/upe-renderer 0.186.110 → 0.187.11

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 (506) hide show
  1. package/README.md +5 -7
  2. package/UPSTREAM.md +4 -4
  3. package/build/three.core.js +853 -277
  4. package/build/three.module.js +1098 -1280
  5. package/build/three.tsl.js +41938 -686
  6. package/build/three.webgpu.js +10604 -49055
  7. package/build/three.webgpu.nodes.js +9249 -5788
  8. package/examples/jsm/Addons.js +2 -0
  9. package/examples/jsm/animation/CCDIKSolver.js +17 -5
  10. package/examples/jsm/controls/FirstPersonControls.js +1 -1
  11. package/examples/jsm/controls/OrbitControls.js +27 -14
  12. package/examples/jsm/csm/CSMShader.js +74 -3
  13. package/examples/jsm/curves/CurveExtras.js +4 -4
  14. package/examples/jsm/curves/NURBSCurve.js +14 -0
  15. package/examples/jsm/exporters/EXRExporter.js +673 -16
  16. package/examples/jsm/exporters/GLTFExporter.js +4 -4
  17. package/examples/jsm/exporters/KTX2Exporter.js +1 -1
  18. package/examples/jsm/exporters/OBJExporter.js +48 -5
  19. package/examples/jsm/exporters/PLYExporter.js +22 -11
  20. package/examples/jsm/generators/CityGenerator.js +3 -2
  21. package/examples/jsm/generators/city/SkyscraperGenerator.js +63 -21
  22. package/examples/jsm/gpgpu/BitonicSort.js +30 -23
  23. package/examples/jsm/helpers/VertexTangentsHelper.js +1 -1
  24. package/examples/jsm/inspector/Extension.js +1 -1
  25. package/examples/jsm/inspector/Inspector.js +6 -46
  26. package/examples/jsm/inspector/RendererInspector.js +43 -8
  27. package/examples/jsm/inspector/Storage.js +49 -0
  28. package/examples/jsm/inspector/extensions/color-grading/ColorGrading.js +32 -27
  29. package/examples/jsm/inspector/tabs/Parameters.js +5 -1
  30. package/examples/jsm/inspector/tabs/Performance.js +22 -7
  31. package/examples/jsm/inspector/tabs/Settings.js +1 -1
  32. package/examples/jsm/inspector/tabs/Timeline.js +83 -7
  33. package/examples/jsm/inspector/tabs/Viewer.js +25 -10
  34. package/examples/jsm/inspector/ui/Profiler.js +1 -1
  35. package/examples/jsm/inspector/ui/Style.js +21 -53
  36. package/examples/jsm/inspector/ui/Values.js +28 -3
  37. package/examples/jsm/libs/fflate.module.js +83 -56
  38. package/examples/jsm/libs/mikktspace.README.md +27 -0
  39. package/examples/jsm/libs/mikktspace.module.js +721 -109
  40. package/examples/jsm/lighting/ClusteredLighting.js +100 -2
  41. package/examples/jsm/lighting/LightMapper.js +295 -0
  42. package/examples/jsm/lighting/LightProbeGrid.js +242 -139
  43. package/examples/jsm/lighting/LightProbeGridWebGL.js +30 -14
  44. package/examples/jsm/lighting/vxgi/VXGIConeTracer.js +54 -5
  45. package/examples/jsm/lighting/vxgi/VXGIIrradiance.js +43 -0
  46. package/examples/jsm/lighting/vxgi/VXGINode.js +13 -56
  47. package/examples/jsm/lighting/vxgi/VXGISceneCollector.js +316 -1
  48. package/examples/jsm/lighting/vxgi/VXGIVolume.js +69 -59
  49. package/examples/jsm/lights/SunLight.js +9 -4
  50. package/examples/jsm/lights/SunLightNode.js +3 -3
  51. package/examples/jsm/lines/LineMaterial.js +26 -10
  52. package/examples/jsm/loaders/3DMLoader.js +10 -1
  53. package/examples/jsm/loaders/3MFLoader.js +5 -1
  54. package/examples/jsm/loaders/AMFLoader.js +2 -0
  55. package/examples/jsm/loaders/BVHLoader.js +2 -0
  56. package/examples/jsm/loaders/ColladaLoader.js +8 -0
  57. package/examples/jsm/loaders/DDSLoader.js +1 -1
  58. package/examples/jsm/loaders/DRACOLoader.js +5 -1
  59. package/examples/jsm/loaders/EXRLoader.js +120 -104
  60. package/examples/jsm/loaders/FBXLoader.js +4 -0
  61. package/examples/jsm/loaders/FontLoader.js +2 -0
  62. package/examples/jsm/loaders/GCodeLoader.js +5 -9
  63. package/examples/jsm/loaders/GLTFLoader.js +112 -31
  64. package/examples/jsm/loaders/GaussianSplatPLYLoader.js +2 -0
  65. package/examples/jsm/loaders/HDRCubeTextureLoader.js +3 -0
  66. package/examples/jsm/loaders/IESLoader.js +46 -12
  67. package/examples/jsm/loaders/JXLLoader.js +159 -0
  68. package/examples/jsm/loaders/KMZLoader.js +6 -0
  69. package/examples/jsm/loaders/KSPLATLoader.js +2 -0
  70. package/examples/jsm/loaders/KTX2Loader.js +49 -4
  71. package/examples/jsm/loaders/KTXLoader.js +5 -3
  72. package/examples/jsm/loaders/LDrawLoader.js +15 -22
  73. package/examples/jsm/loaders/LUT3dlLoader.js +5 -1
  74. package/examples/jsm/loaders/LUTCubeLoader.js +6 -2
  75. package/examples/jsm/loaders/LUTImageLoader.js +2 -0
  76. package/examples/jsm/loaders/LWOLoader.js +6 -0
  77. package/examples/jsm/loaders/MD2Loader.js +2 -0
  78. package/examples/jsm/loaders/MDDLoader.js +4 -0
  79. package/examples/jsm/loaders/MTLLoader.js +8 -0
  80. package/examples/jsm/loaders/MaterialXLoader.js +57 -5
  81. package/examples/jsm/loaders/NRRDLoader.js +4 -2
  82. package/examples/jsm/loaders/OBJLoader.js +10 -4
  83. package/examples/jsm/loaders/PCDLoader.js +6 -2
  84. package/examples/jsm/loaders/PDBLoader.js +5 -3
  85. package/examples/jsm/loaders/PLYLoader.js +39 -15
  86. package/examples/jsm/loaders/PVRLoader.js +2 -2
  87. package/examples/jsm/loaders/SPLATLoader.js +2 -0
  88. package/examples/jsm/loaders/SPZLoader.js +2 -0
  89. package/examples/jsm/loaders/STLLoader.js +3 -1
  90. package/examples/jsm/loaders/SVGLoader.js +27 -49
  91. package/examples/jsm/loaders/TDSLoader.js +4 -0
  92. package/examples/jsm/loaders/TGALoader.js +6 -5
  93. package/examples/jsm/loaders/TTFLoader.js +2 -0
  94. package/examples/jsm/loaders/USDLoader.js +14 -0
  95. package/examples/jsm/loaders/UltraHDRLoader.js +2 -0
  96. package/examples/jsm/loaders/VOXLoader.js +3 -0
  97. package/examples/jsm/loaders/VRMLLoader.js +4 -0
  98. package/examples/jsm/loaders/VTKLoader.js +2 -0
  99. package/examples/jsm/loaders/XYZLoader.js +2 -0
  100. package/examples/jsm/loaders/collada/ColladaComposer.js +15 -8
  101. package/examples/jsm/loaders/materialx/MaterialXDocument.js +610 -138
  102. package/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js +12 -95
  103. package/examples/jsm/loaders/materialx/MaterialXLog.js +4 -0
  104. package/examples/jsm/loaders/materialx/MaterialXNodeDefs.js +99 -0
  105. package/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js +760 -1
  106. package/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js +222 -372
  107. package/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js +163 -259
  108. package/examples/jsm/loaders/materialx/MaterialXUtils.js +25 -0
  109. package/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js +161 -159
  110. package/examples/jsm/loaders/usd/USDAParser.js +56 -47
  111. package/examples/jsm/loaders/usd/USDComposer.js +25 -30
  112. package/examples/jsm/math/ColorConverter.js +7 -3
  113. package/examples/jsm/math/Lut.js +2 -2
  114. package/examples/jsm/math/OBB.js +3 -3
  115. package/examples/jsm/math/Octree.js +20 -17
  116. package/examples/jsm/objects/GaussianSplat.js +5 -4
  117. package/examples/jsm/objects/Reflector.js +5 -0
  118. package/examples/jsm/objects/SkyMesh.js +14 -7
  119. package/examples/jsm/objects/Water2Mesh.js +2 -2
  120. package/examples/jsm/physics/RapierPhysics.js +2 -2
  121. package/examples/jsm/pipelines/MeshletDrawingPipeline.js +5571 -0
  122. package/examples/jsm/pipelines/VisibilityBufferDrawingPipeline.js +954 -0
  123. package/examples/jsm/postprocessing/BokehPass.js +1 -1
  124. package/examples/jsm/postprocessing/GTAOPass.js +26 -18
  125. package/examples/jsm/renderers/SVGRenderer.js +3 -2
  126. package/examples/jsm/shaders/GTAOShader.js +7 -4
  127. package/examples/jsm/shaders/PoissonDenoiseShader.js +1 -10
  128. package/examples/jsm/tsl/WebGLNodesHandler.js +21 -9
  129. package/examples/jsm/tsl/display/AfterImageNode.js +3 -3
  130. package/examples/jsm/tsl/display/BilateralBlurNode.js +3 -3
  131. package/examples/jsm/tsl/display/BloomNode.js +3 -3
  132. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +8 -19
  133. package/examples/jsm/tsl/display/DenoiseNode.js +5 -5
  134. package/examples/jsm/tsl/display/DepthOfFieldNode.js +3 -3
  135. package/examples/jsm/tsl/display/DotScreenNode.js +3 -3
  136. package/examples/jsm/tsl/display/FSR1Node.js +3 -3
  137. package/examples/jsm/tsl/display/FXAANode.js +3 -10
  138. package/examples/jsm/tsl/display/FilmNode.js +3 -3
  139. package/examples/jsm/tsl/display/GTAONode.js +33 -25
  140. package/examples/jsm/tsl/display/GaussianBlurNode.js +3 -3
  141. package/examples/jsm/tsl/display/GodraysNode.js +5 -19
  142. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +8 -4
  143. package/examples/jsm/tsl/display/LensflareNode.js +3 -3
  144. package/examples/jsm/tsl/display/Lut3DNode.js +3 -3
  145. package/examples/jsm/tsl/display/OITPassNode.js +0 -11
  146. package/examples/jsm/tsl/display/OutlineNode.js +107 -5
  147. package/examples/jsm/tsl/display/PixelationPassNode.js +85 -193
  148. package/examples/jsm/tsl/display/RGBShiftNode.js +3 -3
  149. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +23 -126
  150. package/examples/jsm/tsl/display/SMAANode.js +3 -3
  151. package/examples/jsm/tsl/display/SSAONode.js +6 -20
  152. package/examples/jsm/tsl/display/SSGINode.js +36 -29
  153. package/examples/jsm/tsl/display/SSRNode.js +135 -63
  154. package/examples/jsm/tsl/display/SSSNode.js +6 -20
  155. package/examples/jsm/tsl/display/SharpenNode.js +3 -3
  156. package/examples/jsm/tsl/display/SobelOperatorNode.js +3 -3
  157. package/examples/jsm/tsl/display/TAAUNode.js +10 -42
  158. package/examples/jsm/tsl/display/TRAANode.js +11 -43
  159. package/examples/jsm/tsl/display/TemporalReprojectNode.js +42 -47
  160. package/examples/jsm/tsl/display/TransitionNode.js +3 -3
  161. package/examples/jsm/tsl/display/lensDirt.js +30 -0
  162. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +482 -121
  163. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +41 -140
  164. package/examples/jsm/tsl/lighting/LightProbeGridNode.js +72 -25
  165. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +6 -0
  166. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +6 -0
  167. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +6 -0
  168. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +6 -0
  169. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +6 -0
  170. package/examples/jsm/tsl/shadows/TileShadowNode.js +102 -14
  171. package/examples/jsm/tsl/utils/Raymarching.js +1 -1
  172. package/examples/jsm/tsl/utils/SoftParticles.js +5 -12
  173. package/examples/jsm/tsl/utils/SpecularHelpers.js +47 -70
  174. package/examples/jsm/tsl/utils/TAAUtils.js +6 -17
  175. package/examples/jsm/utils/BufferGeometryUtils.js +110 -88
  176. package/examples/jsm/utils/MeshletGeometryUtils.js +417 -0
  177. package/examples/jsm/utils/SceneOptimizer.js +2 -1
  178. package/examples/jsm/utils/SceneUtils.js +1 -1
  179. package/examples/jsm/utils/unwrapUVs.js +865 -0
  180. package/examples/jsm/webxr/XREstimatedLight.js +11 -4
  181. package/package.json +3 -3
  182. package/src/Three.TSL.js +2 -683
  183. package/src/Three.WebGPU.Nodes.js +2 -1
  184. package/src/Three.WebGPU.js +2 -1
  185. package/src/animation/AnimationAction.js +1 -1
  186. package/src/animation/AnimationUtils.js +1 -3
  187. package/src/animation/KeyframeTrack.js +19 -0
  188. package/src/cameras/ArrayCamera.js +12 -0
  189. package/src/cameras/CubeCamera.js +3 -3
  190. package/src/constants.js +1 -9
  191. package/src/core/BufferAttribute.js +57 -21
  192. package/src/core/BufferGeometry.js +5 -13
  193. package/src/core/Clock.js +1 -1
  194. package/src/core/InterleavedBuffer.js +28 -18
  195. package/src/core/InterleavedBufferAttribute.js +54 -20
  196. package/src/core/Object3D.js +19 -9
  197. package/src/core/Raycaster.js +2 -0
  198. package/src/core/RenderTarget.js +11 -5
  199. package/src/core/UniformsGroup.js +7 -3
  200. package/src/extras/PMREMGenerator.js +392 -685
  201. package/src/extras/core/Curve.js +4 -0
  202. package/src/extras/core/CurvePath.js +13 -0
  203. package/src/extras/core/ShapePath.js +1 -1
  204. package/src/geometries/EdgesGeometry.js +12 -10
  205. package/src/geometries/LatheGeometry.js +2 -0
  206. package/src/helpers/PolarGridHelper.js +1 -1
  207. package/src/lights/Light.js +11 -0
  208. package/src/lights/LightProbe.js +2 -0
  209. package/src/lights/LightShadow.js +2 -0
  210. package/src/loaders/AnimationLoader.js +2 -0
  211. package/src/loaders/AudioLoader.js +2 -0
  212. package/src/loaders/BufferGeometryLoader.js +2 -0
  213. package/src/loaders/CompressedTextureLoader.js +2 -0
  214. package/src/loaders/CubeTextureLoader.js +2 -0
  215. package/src/loaders/DataTextureLoader.js +2 -0
  216. package/src/loaders/FileLoader.js +2 -0
  217. package/src/loaders/ImageBitmapLoader.js +3 -1
  218. package/src/loaders/ImageLoader.js +1 -0
  219. package/src/loaders/Loader.js +47 -0
  220. package/src/loaders/MaterialLoader.js +2 -0
  221. package/src/loaders/ObjectLoader.js +27 -8
  222. package/src/loaders/TextureLoader.js +5 -3
  223. package/src/loaders/nodes/NodeLoader.js +2 -0
  224. package/src/materials/Material.js +21 -2
  225. package/src/materials/MeshDepthMaterial.js +1 -1
  226. package/src/materials/MeshDistanceMaterial.js +1 -1
  227. package/src/materials/MeshLambertMaterial.js +1 -1
  228. package/src/materials/MeshMatcapMaterial.js +1 -1
  229. package/src/materials/MeshNormalMaterial.js +1 -1
  230. package/src/materials/MeshPhongMaterial.js +1 -1
  231. package/src/materials/MeshPhysicalMaterial.js +90 -11
  232. package/src/materials/MeshStandardMaterial.js +1 -1
  233. package/src/materials/MeshToonMaterial.js +1 -1
  234. package/src/materials/nodes/Line2NodeMaterial.js +32 -10
  235. package/src/materials/nodes/MeshLambertNodeMaterial.js +13 -0
  236. package/src/materials/nodes/MeshPhongNodeMaterial.js +13 -0
  237. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +40 -5
  238. package/src/materials/nodes/MeshToonNodeMaterial.js +13 -0
  239. package/src/materials/nodes/NodeMaterial.js +36 -16
  240. package/src/materials/nodes/NodeMaterialInstance.js +193 -0
  241. package/src/materials/nodes/NodeMaterials.js +1 -0
  242. package/src/materials/nodes/PointsNodeMaterial.js +1 -1
  243. package/src/materials/nodes/SpriteNodeMaterial.js +3 -3
  244. package/src/materials/nodes/manager/NodeMaterialObserver.js +191 -22
  245. package/src/math/Box3.js +2 -2
  246. package/src/math/Color.js +8 -8
  247. package/src/math/ColorManagement.js +2 -21
  248. package/src/math/FrustumArray.js +12 -0
  249. package/src/math/Interpolant.js +1 -1
  250. package/src/math/Line3.js +2 -4
  251. package/src/math/MathUtils.js +33 -46
  252. package/src/math/Matrix2.js +1 -1
  253. package/src/math/Matrix3.js +1 -1
  254. package/src/math/Matrix4.js +1 -1
  255. package/src/math/Triangle.js +2 -1
  256. package/src/math/Vector2.js +1 -1
  257. package/src/math/Vector3.js +1 -1
  258. package/src/math/Vector4.js +1 -1
  259. package/src/nodes/Nodes.js +1 -0
  260. package/src/nodes/TSL.js +2 -0
  261. package/src/nodes/accessors/Arrays.js +1 -1
  262. package/src/nodes/accessors/Batch.js +29 -23
  263. package/src/nodes/accessors/BufferAttributeNode.js +21 -1
  264. package/src/nodes/accessors/BuiltinNode.js +6 -0
  265. package/src/nodes/accessors/Camera.js +100 -93
  266. package/src/nodes/accessors/ClippingNode.js +17 -6
  267. package/src/nodes/accessors/CubeTextureNode.js +12 -24
  268. package/src/nodes/accessors/Instance.js +198 -160
  269. package/src/nodes/accessors/Lights.js +19 -6
  270. package/src/nodes/accessors/MaterialNode.js +33 -4
  271. package/src/nodes/accessors/Morph.js +81 -22
  272. package/src/nodes/accessors/Normal.js +0 -42
  273. package/src/nodes/accessors/Object3DNode.js +6 -0
  274. package/src/nodes/accessors/PointUVNode.js +6 -0
  275. package/src/nodes/accessors/ReferenceAttributeNode.js +279 -0
  276. package/src/nodes/accessors/ReferenceBaseNode.js +6 -0
  277. package/src/nodes/accessors/ReferenceNode.js +6 -0
  278. package/src/nodes/accessors/Skinning.js +57 -52
  279. package/src/nodes/accessors/StorageBufferNode.js +3 -12
  280. package/src/nodes/accessors/TextureBicubic.js +30 -27
  281. package/src/nodes/accessors/TextureNode.js +164 -78
  282. package/src/nodes/accessors/TextureSizeNode.js +6 -0
  283. package/src/nodes/accessors/UniformArrayNode.js +8 -15
  284. package/src/nodes/accessors/VelocityNode.js +13 -8
  285. package/src/nodes/code/CodeNode.js +6 -0
  286. package/src/nodes/code/ExpressionNode.js +6 -0
  287. package/src/nodes/code/FunctionCallNode.js +3 -3
  288. package/src/nodes/code/FunctionNode.js +15 -13
  289. package/src/nodes/core/ArrayNode.js +3 -3
  290. package/src/nodes/core/AssignNode.js +10 -9
  291. package/src/nodes/core/AttributeNode.js +39 -0
  292. package/src/nodes/core/BypassNode.js +6 -0
  293. package/src/nodes/core/ConstNode.js +31 -1
  294. package/src/nodes/core/ContextNode.js +11 -6
  295. package/src/nodes/core/IndexNode.js +6 -0
  296. package/src/nodes/core/InputNode.js +6 -0
  297. package/src/nodes/core/InspectorNode.js +17 -31
  298. package/src/nodes/core/IsolateNode.js +8 -0
  299. package/src/nodes/core/Node.js +367 -67
  300. package/src/nodes/core/NodeBuilder.js +664 -222
  301. package/src/nodes/core/NodeUtils.js +25 -0
  302. package/src/nodes/core/NodeVar.js +10 -1
  303. package/src/nodes/core/OutputStructNode.js +6 -0
  304. package/src/nodes/core/OverrideContextNode.js +38 -37
  305. package/src/nodes/core/PropertyNode.js +14 -0
  306. package/src/nodes/core/StackNode.js +33 -21
  307. package/src/nodes/core/StructNode.js +6 -0
  308. package/src/nodes/core/StructTypeNode.js +6 -0
  309. package/src/nodes/core/SubBuildNode.js +8 -0
  310. package/src/nodes/core/TempNode.js +10 -35
  311. package/src/nodes/core/UniformGroupNode.js +6 -0
  312. package/src/nodes/core/VarNode.js +43 -135
  313. package/src/nodes/core/VaryingNode.js +33 -2
  314. package/src/nodes/display/BlendModes.js +5 -40
  315. package/src/nodes/display/BumpMapNode.js +17 -7
  316. package/src/nodes/display/ColorAdjustment.js +22 -10
  317. package/src/nodes/display/ColorSpaceFunctions.js +2 -14
  318. package/src/nodes/display/ColorSpaceNode.js +3 -3
  319. package/src/nodes/display/FrontFacingNode.js +6 -0
  320. package/src/nodes/display/NormalMapNode.js +3 -3
  321. package/src/nodes/display/PassNode.js +75 -16
  322. package/src/nodes/display/RenderOutputNode.js +22 -5
  323. package/src/nodes/display/ScreenNode.js +6 -0
  324. package/src/nodes/display/ToneMappingFunctions.js +9 -51
  325. package/src/nodes/display/ToneMappingNode.js +3 -3
  326. package/src/nodes/display/ToonOutlinePassNode.js +66 -2
  327. package/src/nodes/display/ViewportDepthNode.js +34 -4
  328. package/src/nodes/functions/BSDF/BRDF_EON.js +65 -0
  329. package/src/nodes/functions/BSDF/BRDF_GGX.js +5 -3
  330. package/src/nodes/functions/BSDF/BRDF_Sheen.js +2 -16
  331. package/src/nodes/functions/BSDF/D_GGX.js +1 -8
  332. package/src/nodes/functions/BSDF/D_GGX_Anisotropic.js +7 -10
  333. package/src/nodes/functions/BSDF/LTC.js +20 -47
  334. package/src/nodes/functions/BSDF/Schlick_to_F0.js +1 -9
  335. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +1 -9
  336. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +10 -13
  337. package/src/nodes/functions/PhysicalLightingModel.js +84 -51
  338. package/src/nodes/functions/VolumetricLightingModel.js +1 -1
  339. package/src/nodes/functions/material/getAlphaHashThreshold.js +3 -9
  340. package/src/nodes/functions/material/getParallaxCorrectNormal.js +10 -11
  341. package/src/nodes/functions/material/getRoughness.js +3 -1
  342. package/src/nodes/geometry/RangeNode.js +52 -69
  343. package/src/nodes/gpgpu/AtomicFunctionNode.js +11 -6
  344. package/src/nodes/gpgpu/BarrierNode.js +6 -0
  345. package/src/nodes/gpgpu/ComputeBuiltinNode.js +6 -0
  346. package/src/nodes/gpgpu/ComputeNode.js +6 -0
  347. package/src/nodes/gpgpu/SubgroupFunctionNode.js +38 -29
  348. package/src/nodes/gpgpu/WorkgroupInfoNode.js +6 -0
  349. package/src/nodes/lighting/AnalyticLightNode.js +7 -14
  350. package/src/nodes/lighting/BasicEnvironmentNode.js +5 -1
  351. package/src/nodes/lighting/EnvironmentNode.js +58 -8
  352. package/src/nodes/lighting/IESSpotLightNode.js +19 -4
  353. package/src/nodes/lighting/LightProbeNode.js +2 -1
  354. package/src/nodes/lighting/LightUtils.js +2 -2
  355. package/src/nodes/lighting/LightingNode.js +6 -0
  356. package/src/nodes/lighting/LightsNode.js +26 -32
  357. package/src/nodes/lighting/PointShadowNode.js +92 -48
  358. package/src/nodes/lighting/ProjectorLightNode.js +1 -1
  359. package/src/nodes/lighting/RectAreaLightNode.js +13 -14
  360. package/src/nodes/lighting/ShadowBaseNode.js +9 -17
  361. package/src/nodes/lighting/ShadowFilterNode.js +26 -3
  362. package/src/nodes/lighting/ShadowNode.js +13 -11
  363. package/src/nodes/materialx/MaterialXColor.js +2 -14
  364. package/src/nodes/materialx/MaterialXColorTransform.js +1 -7
  365. package/src/nodes/materialx/MaterialXNodes.js +8 -11
  366. package/src/nodes/materialx/MaterialXNoise.js +195 -454
  367. package/src/nodes/math/BitcastNode.js +5 -5
  368. package/src/nodes/math/BitcountNode.js +18 -46
  369. package/src/nodes/math/ConditionalNode.js +92 -22
  370. package/src/nodes/math/Hash.js +1 -1
  371. package/src/nodes/math/MathNode.js +86 -64
  372. package/src/nodes/math/MathUtils.js +2 -2
  373. package/src/nodes/math/OperatorNode.js +42 -59
  374. package/src/nodes/math/PackFloatNode.js +9 -9
  375. package/src/nodes/math/Packed4x8IntegerNode.js +20 -52
  376. package/src/nodes/math/TriNoise3D.js +3 -23
  377. package/src/nodes/math/UnpackFloatNode.js +9 -9
  378. package/src/nodes/pmrem/PMREMNode.js +38 -75
  379. package/src/nodes/pmrem/PMREMUtils.js +108 -272
  380. package/src/nodes/procedural/Checker.js +1 -1
  381. package/src/nodes/tsl/TSLCore.js +199 -74
  382. package/src/nodes/utils/ArrayElementNode.js +19 -1
  383. package/src/nodes/utils/CubeMapNode.js +3 -3
  384. package/src/nodes/utils/DebugNode.js +2 -2
  385. package/src/nodes/utils/EventNode.js +6 -0
  386. package/src/nodes/utils/FlipNode.js +3 -3
  387. package/src/nodes/utils/FunctionOverloadingNode.js +7 -1
  388. package/src/nodes/utils/JoinNode.js +3 -3
  389. package/src/nodes/utils/LoopNode.js +14 -9
  390. package/src/nodes/utils/MemberNode.js +18 -0
  391. package/src/nodes/utils/PostProcessingUtils.js +20 -25
  392. package/src/nodes/utils/RTTNode.js +2 -0
  393. package/src/nodes/utils/ReflectorNode.js +24 -0
  394. package/src/nodes/utils/RotateNode.js +3 -3
  395. package/src/nodes/utils/SampleNode.js +6 -0
  396. package/src/nodes/utils/SetNode.js +3 -3
  397. package/src/nodes/utils/SplitNode.js +6 -0
  398. package/src/nodes/utils/UVUtils.js +2 -2
  399. package/src/objects/BatchedMesh.js +146 -15
  400. package/src/objects/InstancedMesh.js +12 -4
  401. package/src/objects/Line.js +20 -0
  402. package/src/objects/Mesh.js +8 -0
  403. package/src/objects/Points.js +20 -0
  404. package/src/objects/Skeleton.js +26 -0
  405. package/src/objects/SkinnedMesh.js +3 -3
  406. package/src/objects/Sprite.js +10 -0
  407. package/src/renderers/WebGLRenderer.js +104 -70
  408. package/src/renderers/common/Animation.js +5 -1
  409. package/src/renderers/common/Attributes.js +67 -57
  410. package/src/renderers/common/Backend.js +78 -3
  411. package/src/renderers/common/BindGroup.js +11 -0
  412. package/src/renderers/common/Binding.js +0 -11
  413. package/src/renderers/common/Bindings.js +116 -10
  414. package/src/renderers/common/Buffer.js +1 -1
  415. package/src/renderers/common/ClippingContext.js +12 -1
  416. package/src/renderers/common/ComputePipeline.js +17 -1
  417. package/src/renderers/common/DirectRenderPipeline.js +7 -3
  418. package/src/renderers/common/Geometries.js +170 -132
  419. package/src/renderers/common/Info.js +1 -1
  420. package/src/renderers/common/InspectorBase.js +5 -5
  421. package/src/renderers/common/Lighting.js +59 -0
  422. package/src/renderers/common/Pipelines.js +26 -12
  423. package/src/renderers/common/ProgrammableStage.js +1 -17
  424. package/src/renderers/common/RenderContext.js +21 -0
  425. package/src/renderers/common/RenderContexts.js +13 -4
  426. package/src/renderers/common/RenderObject.js +111 -35
  427. package/src/renderers/common/RenderObjects.js +37 -19
  428. package/src/renderers/common/Renderer.js +537 -295
  429. package/src/renderers/common/RendererUtils.js +15 -0
  430. package/src/renderers/common/StandardDrawingPipeline.js +343 -0
  431. package/src/renderers/common/Storage3DTexture.js +11 -0
  432. package/src/renderers/common/StorageArrayTexture.js +10 -0
  433. package/src/renderers/common/StorageTexture.js +0 -9
  434. package/src/renderers/common/Textures.js +144 -37
  435. package/src/renderers/common/UniformsGroup.js +19 -0
  436. package/src/renderers/common/XRManager.js +10 -91
  437. package/src/renderers/common/extras/PMREMGenerator.js +298 -576
  438. package/src/renderers/common/nodes/NodeBuilderState.js +7 -5
  439. package/src/renderers/common/nodes/NodeLibrary.js +11 -35
  440. package/src/renderers/common/nodes/NodeManager.js +80 -31
  441. package/src/renderers/common/nodes/NodeSampledTexture.js +14 -0
  442. package/src/renderers/common/nodes/NodeSampler.js +14 -0
  443. package/src/renderers/common/nodes/NodeStorageBuffer.js +1 -1
  444. package/src/renderers/common/nodes/NodeUniformBuffer.js +1 -14
  445. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +13 -4
  446. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +8 -8
  447. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +23 -11
  448. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +21 -2
  449. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +1 -1
  450. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +18 -2
  451. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +104 -7
  452. package/src/renderers/shaders/ShaderChunk/morphcolor_vertex.glsl.js +11 -2
  453. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +36 -20
  454. package/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js +5 -0
  455. package/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js +6 -0
  456. package/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js +5 -0
  457. package/src/renderers/shaders/ShaderChunk.js +0 -2
  458. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +4 -18
  459. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -1
  460. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
  461. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +8 -1
  462. package/src/renderers/shaders/ShaderLib.js +3 -0
  463. package/src/renderers/shaders/UniformsLib.js +4 -5
  464. package/src/renderers/webgl/WebGLBackground.js +3 -3
  465. package/src/renderers/webgl/WebGLBindingStates.js +4 -2
  466. package/src/renderers/webgl/WebGLCapabilities.js +7 -1
  467. package/src/renderers/webgl/WebGLEnvironments.js +2 -2
  468. package/src/renderers/webgl/WebGLGeometries.js +42 -14
  469. package/src/renderers/webgl/WebGLMaterials.js +15 -2
  470. package/src/renderers/webgl/WebGLOutput.js +37 -1
  471. package/src/renderers/webgl/WebGLProgram.js +13 -54
  472. package/src/renderers/webgl/WebGLPrograms.js +22 -8
  473. package/src/renderers/webgl/WebGLRenderStates.js +11 -8
  474. package/src/renderers/webgl/WebGLShadowMap.js +6 -4
  475. package/src/renderers/webgl/WebGLState.js +10 -6
  476. package/src/renderers/webgl/WebGLTextures.js +129 -77
  477. package/src/renderers/webgl/WebGLUniforms.js +44 -6
  478. package/src/renderers/webgl/WebGLUniformsGroups.js +75 -69
  479. package/src/renderers/webgl-fallback/WebGLBackend.js +206 -278
  480. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +154 -20
  481. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +45 -42
  482. package/src/renderers/webgl-fallback/utils/WebGLState.js +29 -4
  483. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +129 -49
  484. package/src/renderers/webgl-fallback/utils/WebGLVertexArrayUtils.js +346 -0
  485. package/src/renderers/webgpu/WebGPUBackend.js +140 -82
  486. package/src/renderers/webgpu/WebGPURenderer.js +1 -1
  487. package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +10 -10
  488. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +10 -10
  489. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +135 -60
  490. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +128 -55
  491. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
  492. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +15 -12
  493. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +55 -19
  494. package/src/renderers/webgpu/utils/WebGPUUtils.js +20 -3
  495. package/src/renderers/webxr/WebXRController.js +3 -3
  496. package/src/renderers/webxr/WebXRManager.js +5 -90
  497. package/src/scenes/Scene.js +4 -4
  498. package/src/textures/CompressedTexture.js +2 -2
  499. package/src/textures/DepthTexture.js +2 -2
  500. package/src/textures/FramebufferTexture.js +11 -0
  501. package/src/textures/Texture.js +29 -1
  502. package/src/textures/TextureSource.js +1 -1
  503. package/src/upe.js +1 -1
  504. package/src/utils.js +4 -4
  505. package/examples/jsm/libs/surfaceNet.js +0 -201
  506. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +0 -186
@@ -0,0 +1,954 @@
1
+ import {
2
+ StorageBufferAttribute,
3
+ IndirectStorageBufferAttribute,
4
+ Mesh,
5
+ BoxGeometry,
6
+ BufferGeometry,
7
+ Float32BufferAttribute
8
+ } from 'three/webgpu';
9
+
10
+ import {
11
+ Fn, If, Loop, vec2, vec3, vec4, mat3, uint, float, int, min, max, floor, sqrt, select, struct, transformNormal,
12
+ storage, uniform, instanceIndex, vertexIndex, screenCoordinate, varyingProperty,
13
+ positionGeometry, cameraViewMatrix, cameraProjectionMatrix, normalize, context, overrideNodes,
14
+ positionLocal, positionWorld, positionWorldDirection, positionView, positionViewDirection,
15
+ normalLocal, normalViewGeometry, normalWorldGeometry, tangentViewFrame, bitangentViewFrame, modelWorldMatrix, modelViewMatrix, modelPosition, atomicMax, atomicAdd, atomicStore, atomicLoad
16
+ } from 'three/tsl';
17
+
18
+ import { MeshletDrawingPipeline, MeshletBatch, cacheAttributes, createDebugMaterial, createDrawMaterial, createOcclusion } from './MeshletDrawingPipeline.js';
19
+ import { MESHLET_SIZE } from '../utils/MeshletGeometryUtils.js';
20
+
21
+ // visibility buffer packing — the depth occupies the bits above each payload
22
+
23
+ const TRIANGLE_INDEX_BITS = 16;
24
+ const INSTANCE_INDEX_BITS = 17;
25
+ const TRIANGLE_INDEX_MASK = 2 ** TRIANGLE_INDEX_BITS - 1;
26
+ const INSTANCE_INDEX_MASK = 2 ** INSTANCE_INDEX_BITS - 1;
27
+ const DEPTH_TRI_MAX = 2 ** ( 32 - TRIANGLE_INDEX_BITS ) - 1;
28
+ const DEPTH_INST_MAX = 2 ** ( 32 - INSTANCE_INDEX_BITS ) - 1;
29
+
30
+ const MAX_TRIANGLES = TRIANGLE_INDEX_MASK + 1;
31
+ const MAX_INSTANCES = INSTANCE_INDEX_MASK + 1;
32
+
33
+ // the large triangles of one batch drawn by the hardware rasterizer per frame, limited by the vertices of the pulled geometry
34
+
35
+ const MAX_HW_TRIANGLES = 65536;
36
+
37
+ let _resolveGeometry = null;
38
+ let _fullscreenGeometry = null;
39
+
40
+ // the corners of a triangle deformed by the position node of the material, see deformTriangle()
41
+
42
+ const DeformedTriangle = /*@__PURE__*/ struct( { positions: 'mat3', normals: 'mat3' }, 'DeformedTriangle' );
43
+
44
+ const edgeFunction = /*@__PURE__*/ Fn( ( [ a, b, c ] ) => {
45
+
46
+ return c.y.sub( a.y ).mul( b.x.sub( a.x ) ).sub( c.x.sub( a.x ).mul( b.y.sub( a.y ) ) );
47
+
48
+ } );
49
+
50
+ /**
51
+ * Returns the positions and the normals of the corners of a triangle deformed by the position node of the material, in
52
+ * the space of the object: the node is evaluated per corner with the position, the normal and the attributes of the
53
+ * vertex, and the position and the normal transformed by the instance matrix, like the regular instancing of node
54
+ * materials. The normal assigned to `normalLocal` by the position node is the normal of the corner.
55
+ *
56
+ * @private
57
+ * @param {Node<vec3>} positionNode - The position node of the material.
58
+ * @param {Object} vertex - The functions reading the position, the normal and the attributes of a vertex.
59
+ * @param {Array<Node<uint>>} corners - The addresses of the vertices of the corners.
60
+ * @param {Node<mat4>} instanceMatrix - The instance matrix, identity for objects which are not instanced meshes.
61
+ * @param {Node<uint>} instance - The instance index of the material.
62
+ * @return {Node} The deformed positions and normals, one column per corner, see DeformedTriangle.
63
+ */
64
+ function deformTriangle( positionNode, { position, normal, vertexUv, hasAttribute, attribute }, corners, instanceMatrix, instance ) {
65
+
66
+ return Fn( () => {
67
+
68
+ const address = uint( 0 ).toVar();
69
+ const cornerNormal = vec3( 0 ).toVar();
70
+ const positions = [ vec3( 0 ).toVar(), vec3( 0 ).toVar(), vec3( 0 ).toVar() ];
71
+ const normals = [ vec3( 0 ).toVar(), vec3( 0 ).toVar(), vec3( 0 ).toVar() ];
72
+
73
+ const geometryPosition = position( address );
74
+ const geometryNormal = normal( address );
75
+
76
+ const getAttribute = cacheAttributes( ( name ) => {
77
+
78
+ if ( name === 'position' ) return geometryPosition;
79
+ if ( name === 'normal' ) return geometryNormal;
80
+ if ( name === 'uv' ) return vertexUv( address );
81
+
82
+ return hasAttribute( name ) ? attribute( name, address ) : null;
83
+
84
+ } );
85
+
86
+ const deformed = context( positionNode.overrideNodes( [
87
+ [ positionLocal, instanceMatrix.mul( vec4( geometryPosition, 1.0 ) ).xyz ],
88
+ [ normalLocal, cornerNormal ],
89
+ [ instanceIndex, instance ]
90
+ ] ), { getAttribute } );
91
+
92
+ // the node is built once, in the loop over the corners
93
+
94
+ Loop( { start: 0, end: 3, type: 'int' }, ( { i } ) => {
95
+
96
+ address.assign( select( i.equal( 0 ), corners[ 0 ], select( i.equal( 1 ), corners[ 1 ], corners[ 2 ] ) ) );
97
+ cornerNormal.assign( transformNormal( geometryNormal, instanceMatrix ) );
98
+
99
+ const value = vec3( deformed ).toVar();
100
+
101
+ If( i.equal( 0 ), () => {
102
+
103
+ positions[ 0 ].assign( value );
104
+ normals[ 0 ].assign( cornerNormal );
105
+
106
+ } ).ElseIf( i.equal( 1 ), () => {
107
+
108
+ positions[ 1 ].assign( value );
109
+ normals[ 1 ].assign( cornerNormal );
110
+
111
+ } ).Else( () => {
112
+
113
+ positions[ 2 ].assign( value );
114
+ normals[ 2 ].assign( cornerNormal );
115
+
116
+ } );
117
+
118
+ } );
119
+
120
+ return DeformedTriangle( mat3( positions[ 0 ], positions[ 1 ], positions[ 2 ] ), mat3( normals[ 0 ], normals[ 1 ], normals[ 2 ] ) );
121
+
122
+ } )();
123
+
124
+ }
125
+
126
+ /**
127
+ * Returns a context which feeds the surface of the merged object covering the current fragment into
128
+ * the material graph: position and normal in local, world and view space, the model matrices and the
129
+ * first uv channel. The nodes of the material evaluate the merged object instead of the drawing mesh.
130
+ * If a uv gradient is given, textures sampled with the first uv channel use it instead of the hardware
131
+ * derivatives, which are invalid if neighbor fragments belong to other triangles. The same applies to
132
+ * the tangent frame of normal maps without precomputed tangents. Other attributes of the geometry are
133
+ * provided by the given attribute function. The surface only exists in the fragment stage, so the nodes
134
+ * are overridden in the fragment stage and the varyings derived from them are evaluated there as well.
135
+ *
136
+ * @private
137
+ * @param {Object} surface - The reconstructed surface.
138
+ * @return {ContextNode} The context node.
139
+ */
140
+ function createSurfaceContext( { localPosition, localNormal, worldPosition, worldNormal, uv, uvGradient = null, tangentFrame = null, matrixWorld, attribute } ) {
141
+
142
+ const viewPosition = cameraViewMatrix.mul( vec4( worldPosition, 1.0 ) ).xyz;
143
+
144
+ const overrides = [
145
+ [ positionLocal, localPosition ],
146
+ [ positionWorld, worldPosition ],
147
+ [ positionWorldDirection, normalize( matrixWorld.mul( vec4( localPosition, 0.0 ) ).xyz ) ],
148
+ [ positionView, viewPosition ],
149
+ [ positionViewDirection, viewPosition.negate().normalize() ],
150
+ [ normalLocal, normalize( localNormal ) ],
151
+ [ normalWorldGeometry, normalize( worldNormal ) ],
152
+ [ normalViewGeometry, cameraViewMatrix.mul( vec4( worldNormal, 0.0 ) ).xyz.normalize() ],
153
+ [ modelWorldMatrix, matrixWorld ],
154
+ [ modelViewMatrix, cameraViewMatrix.mul( matrixWorld ) ],
155
+ [ modelPosition, matrixWorld.mul( vec4( 0.0, 0.0, 0.0, 1.0 ) ).xyz ]
156
+ ];
157
+
158
+ if ( tangentFrame !== null ) overrides.push( [ tangentViewFrame, tangentFrame[ 0 ] ], [ bitangentViewFrame, tangentFrame[ 1 ] ] );
159
+
160
+ return overrideNodes( overrides, context( {
161
+ getAttribute: cacheAttributes( ( name ) => name === 'uv' ? uv : attribute( name ) ),
162
+ getTextureGradient: uvGradient !== null ? () => uvGradient : null
163
+ } ), 'fragment' );
164
+
165
+ }
166
+
167
+ /**
168
+ * Creates the visibility buffers of a view, shared by all batches of a render list, and the compute
169
+ * node clearing them. The instances of all batches share one index range, each batch owns a slice.
170
+ *
171
+ * @private
172
+ * @param {number} width - The width of the view in pixels.
173
+ * @param {number} height - The height of the view in pixels.
174
+ * @return {Object} The view.
175
+ */
176
+ function createView( width, height ) {
177
+
178
+ const pixels = width * height;
179
+
180
+ // depth(16) | triangle(16) and depth(15) | instance(17)
181
+
182
+ const screenTriAttribute = new StorageBufferAttribute( new Uint32Array( pixels ), 1 );
183
+ const screenInstAttribute = new StorageBufferAttribute( new Uint32Array( pixels ), 1 );
184
+
185
+ const screenTriAtomic = storage( screenTriAttribute, 'uint', pixels ).toAtomic();
186
+ const screenInstAtomic = storage( screenInstAttribute, 'uint', pixels ).toAtomic();
187
+
188
+ const computeClear = Fn( () => {
189
+
190
+ atomicStore( screenTriAtomic.element( instanceIndex ), uint( 0 ) );
191
+ atomicStore( screenInstAtomic.element( instanceIndex ), uint( 0 ) );
192
+
193
+ } )().compute( pixels, [ 256 ] ).setName( 'VisibilityBufferDrawingPipeline Clear' );
194
+
195
+ return {
196
+ width,
197
+ height,
198
+ screenTriAtomic,
199
+ screenTriRead: storage( screenTriAttribute, 'uint', pixels ).toReadOnly(),
200
+ screenInstAtomic,
201
+ screenInstRead: storage( screenInstAttribute, 'uint', pixels ).toReadOnly(),
202
+ computeClear,
203
+ dispose() {
204
+
205
+ computeClear.dispose();
206
+ screenTriAttribute.dispose();
207
+ screenInstAttribute.dispose();
208
+
209
+ }
210
+ };
211
+
212
+ }
213
+
214
+
215
+ /**
216
+ * A batch drawing the visible clusters into a visibility buffer: a compute shader rasterizes the small
217
+ * triangles in software and queues the large ones for the hardware rasterizer. A resolve draws the bounding
218
+ * box of each object and shades the fragments whose visible triangle belongs to the object.
219
+ *
220
+ * @private
221
+ * @augments MeshletBatch
222
+ */
223
+ class VisibilityBufferBatch extends MeshletBatch {
224
+
225
+ /**
226
+ * Creates the software rasterizer, the hardware path of the large triangles and the resolve.
227
+ *
228
+ * @param {Object} shared - The nodes and resources of the batch.
229
+ */
230
+ setupDraw( shared ) {
231
+
232
+ const {
233
+ createAttribute, clusters, material, renderer, receiveShadow, debug,
234
+ position, normal, vertexUv, hasAttribute, attribute, indexBuffer, instanceWorld, instanceMvp, objectWorld, instanceLocal, instanceData,
235
+ workQueue, workQueueCountRead, maxWorkItems, projScreenMatrix, viewSize
236
+ } = shared;
237
+
238
+ // the position node of the material is evaluated per corner of the triangles by the software rasterizer and by the
239
+ // resolve. the world matrices of the culling approximate the deformation, the real ones are the matrices of the
240
+ // objects. the instance index of the material is the index of the instance in its instanced mesh
241
+
242
+ const deformed = this.deformed;
243
+ const vertex = { position, normal, vertexUv, hasAttribute, attribute };
244
+ const stride = this.instanceDataStride;
245
+
246
+ const deformCorners = ( corners, instId ) => deformTriangle( material.positionNode, vertex, corners, instanceLocal.element( instId ), uint( instanceData.element( instId.mul( stride ) ).x ) );
247
+
248
+ // the batches of the visibility buffer draw one geometry, the triangles of the visibility buffer are indexed
249
+ // from the first triangle of the geometry in the geometry pool
250
+
251
+ const triangleBase = this.triangleBase = uniform( this.pool.add( clusters ), 'uint' );
252
+
253
+ this.maxRasterSize = uniform( 8, 'int' );
254
+
255
+ // the slice of the instance index range of the view owned by this batch
256
+
257
+ this.instanceOffset = uniform( 0, 'uint' );
258
+
259
+ const { maxRasterSize, instanceOffset } = this;
260
+
261
+ // visibility buffers shared by all batches of the view
262
+
263
+ const { screenTriAtomic, screenTriRead, screenInstAtomic, screenInstRead } = this.view;
264
+
265
+ const dispatchAttribute = createAttribute( new Uint32Array( 3 ), 3, IndirectStorageBufferAttribute );
266
+ const dispatchBuffer = storage( dispatchAttribute, 'uint', 3 );
267
+
268
+ // the software rasterizer sends large triangles to the hardware queue, the counter followed by [ instance, triangle ] pairs
269
+
270
+ const hwQueueAttribute = createAttribute( new Uint32Array( 1 + MAX_HW_TRIANGLES * 2 ), 1 );
271
+ const hwQueueAtomic = storage( hwQueueAttribute, 'uint', 1 + MAX_HW_TRIANGLES * 2 ).toAtomic();
272
+ const hwQueueRead = storage( hwQueueAttribute, 'uint', 1 + MAX_HW_TRIANGLES * 2 ).toReadOnly();
273
+
274
+ const hwDrawAttribute = createAttribute( new Uint32Array( 4 ), 4, IndirectStorageBufferAttribute );
275
+ const hwDrawBuffer = storage( hwDrawAttribute, 'uint', 4 );
276
+
277
+ const computeHWReset = Fn( () => {
278
+
279
+ atomicStore( hwQueueAtomic.element( 0 ), uint( 0 ) );
280
+
281
+ } )().compute( 1 ).setName( 'VisibilityBufferDrawingPipeline Reset' );
282
+
283
+ // indirect dispatch arguments, split into 2D if exceeding 65535 workgroups
284
+
285
+ const computeDispatch = Fn( () => {
286
+
287
+ const workgroups = min( workQueueCountRead.element( 0 ), maxWorkItems );
288
+ const maxDimension = uint( 65535 );
289
+
290
+ dispatchBuffer.element( 0 ).assign( min( workgroups, maxDimension ) );
291
+ dispatchBuffer.element( 1 ).assign( workgroups.add( maxDimension ).sub( 1 ).div( maxDimension ) );
292
+ dispatchBuffer.element( 2 ).assign( 1 );
293
+
294
+ } )().compute( 1 ).setName( 'VisibilityBufferDrawingPipeline Dispatch' );
295
+
296
+ // software rasterizer — one thread per triangle of a cluster
297
+
298
+ const computeRasterize = Fn( () => {
299
+
300
+ const totalThreads = min( workQueueCountRead.element( 0 ), maxWorkItems ).mul( MESHLET_SIZE );
301
+
302
+ If( instanceIndex.lessThan( totalThreads ), () => {
303
+
304
+ const workItem = workQueue.element( instanceIndex.div( MESHLET_SIZE ) );
305
+ const instId = workItem.x;
306
+ const lodTriangleStart = workItem.y;
307
+ const lodNumTriangles = workItem.z;
308
+ const chunk = workItem.w;
309
+
310
+ const lodTriangle = chunk.mul( MESHLET_SIZE ).add( instanceIndex.mod( MESHLET_SIZE ) );
311
+
312
+ If( lodTriangle.lessThan( lodNumTriangles ), () => {
313
+
314
+ const megaTriangleIndex = lodTriangleStart.add( lodTriangle );
315
+ const indexOffset = megaTriangleIndex.mul( 3 );
316
+
317
+ const corners = [ indexBuffer.element( indexOffset ), indexBuffer.element( indexOffset.add( 1 ) ), indexBuffer.element( indexOffset.add( 2 ) ) ];
318
+
319
+ let p0, p1, p2;
320
+
321
+ if ( deformed === true ) {
322
+
323
+ const deformedPositions = deformCorners( corners, instId ).get( 'positions' );
324
+ const mvp = projScreenMatrix.mul( objectWorld.element( instId ) ).toVar();
325
+
326
+ p0 = mvp.mul( vec4( deformedPositions.element( 0 ), 1.0 ) );
327
+ p1 = mvp.mul( vec4( deformedPositions.element( 1 ), 1.0 ) );
328
+ p2 = mvp.mul( vec4( deformedPositions.element( 2 ), 1.0 ) );
329
+
330
+ } else {
331
+
332
+ const mvp = instanceMvp.element( instId );
333
+
334
+ p0 = mvp.mul( vec4( position( corners[ 0 ] ), 1.0 ) );
335
+ p1 = mvp.mul( vec4( position( corners[ 1 ] ), 1.0 ) );
336
+ p2 = mvp.mul( vec4( position( corners[ 2 ] ), 1.0 ) );
337
+
338
+ }
339
+
340
+ const enqueueHardware = () => {
341
+
342
+ const hwCount = atomicAdd( hwQueueAtomic.element( 0 ), 1 );
343
+
344
+ If( hwCount.lessThan( MAX_HW_TRIANGLES ), () => {
345
+
346
+ const slot = hwCount.mul( 2 ).add( 1 );
347
+
348
+ atomicStore( hwQueueAtomic.element( slot ), instId );
349
+ atomicStore( hwQueueAtomic.element( slot.add( 1 ) ), megaTriangleIndex );
350
+
351
+ } );
352
+
353
+ };
354
+
355
+ // triangles crossing the near plane need clipping, so they go to the hardware rasterizer
356
+
357
+ If( p0.w.greaterThan( 0.0 ).and( p1.w.greaterThan( 0.0 ) ).and( p2.w.greaterThan( 0.0 ) ), () => {
358
+
359
+ const ndc0 = p0.xyz.div( p0.w );
360
+ const ndc1 = p1.xyz.div( p1.w );
361
+ const ndc2 = p2.xyz.div( p2.w );
362
+
363
+ // back-face culling
364
+
365
+ If( edgeFunction( ndc0, ndc1, ndc2 ).greaterThan( 0.0 ), () => {
366
+
367
+ const ndcMinX = min( ndc0.x, min( ndc1.x, ndc2.x ) );
368
+ const ndcMaxX = max( ndc0.x, max( ndc1.x, ndc2.x ) );
369
+ const ndcMinY = min( ndc0.y, min( ndc1.y, ndc2.y ) );
370
+ const ndcMaxY = max( ndc0.y, max( ndc1.y, ndc2.y ) );
371
+
372
+ If( ndcMaxX.greaterThan( - 1.0 ).and( ndcMinX.lessThan( 1.0 ) ).and( ndcMaxY.greaterThan( - 1.0 ) ).and( ndcMinY.lessThan( 1.0 ) ), () => {
373
+
374
+ const w = viewSize.x;
375
+ const h = viewSize.y;
376
+
377
+ const s0 = ndc0.xy.add( 1.0 ).mul( 0.5 ).mul( vec2( w, h ) );
378
+ const s1 = ndc1.xy.add( 1.0 ).mul( 0.5 ).mul( vec2( w, h ) );
379
+ const s2 = ndc2.xy.add( 1.0 ).mul( 0.5 ).mul( vec2( w, h ) );
380
+
381
+ const startX = int( floor( max( 0.0, min( s0.x, min( s1.x, s2.x ) ) ) ) );
382
+ const endX = int( floor( min( w.sub( 1.0 ), max( s0.x, max( s1.x, s2.x ) ) ) ) );
383
+ const startY = int( floor( max( 0.0, min( s0.y, min( s1.y, s2.y ) ) ) ) );
384
+ const endY = int( floor( min( h.sub( 1.0 ), max( s0.y, max( s1.y, s2.y ) ) ) ) );
385
+
386
+ // only small triangles are rasterized in software, the others go to the hardware queue
387
+
388
+ If( startX.lessThanEqual( endX ).and( startY.lessThanEqual( endY ) ).and( endX.sub( startX ).lessThanEqual( maxRasterSize ) ).and( endY.sub( startY ).lessThanEqual( maxRasterSize ) ), () => {
389
+
390
+ const area = edgeFunction( s0, s1, s2 );
391
+
392
+ const stepX_w0 = s1.y.sub( s2.y );
393
+ const stepY_w0 = s2.x.sub( s1.x );
394
+ const stepX_w1 = s2.y.sub( s0.y );
395
+ const stepY_w1 = s0.x.sub( s2.x );
396
+ const stepX_w2 = s0.y.sub( s1.y );
397
+ const stepY_w2 = s1.x.sub( s0.x );
398
+
399
+ // top-left rule for watertight edges
400
+
401
+ const bias0 = stepX_w0.lessThan( 0.0 ).or( stepX_w0.equal( 0.0 ).and( stepY_w0.greaterThan( 0.0 ) ) ).select( 0.0, - 1e-5 );
402
+ const bias1 = stepX_w1.lessThan( 0.0 ).or( stepX_w1.equal( 0.0 ).and( stepY_w1.greaterThan( 0.0 ) ) ).select( 0.0, - 1e-5 );
403
+ const bias2 = stepX_w2.lessThan( 0.0 ).or( stepX_w2.equal( 0.0 ).and( stepY_w2.greaterThan( 0.0 ) ) ).select( 0.0, - 1e-5 );
404
+
405
+ const pStart = vec2( float( startX ).add( 0.5 ), float( startY ).add( 0.5 ) );
406
+
407
+ const row_w0 = edgeFunction( s1, s2, pStart ).add( bias0 ).toVar();
408
+ const row_w1 = edgeFunction( s2, s0, pStart ).add( bias1 ).toVar();
409
+ const row_w2 = edgeFunction( s0, s1, pStart ).add( bias2 ).toVar();
410
+
411
+ // incremental depth
412
+
413
+ const row_z = row_w0.div( area ).mul( ndc0.z ).add( row_w1.div( area ).mul( ndc1.z ) ).add( row_w2.div( area ).mul( ndc2.z ) ).toVar();
414
+
415
+ const stepX_z = stepX_w0.div( area ).mul( ndc0.z ).add( stepX_w1.div( area ).mul( ndc1.z ) ).add( stepX_w2.div( area ).mul( ndc2.z ) );
416
+ const stepY_z = stepY_w0.div( area ).mul( ndc0.z ).add( stepY_w1.div( area ).mul( ndc1.z ) ).add( stepY_w2.div( area ).mul( ndc2.z ) );
417
+
418
+ Loop( { name: 'y', type: 'int', start: startY, end: endY, condition: '<=' }, ( { y } ) => {
419
+
420
+ const w0 = row_w0.toVar();
421
+ const w1 = row_w1.toVar();
422
+ const w2 = row_w2.toVar();
423
+ const z = row_z.toVar();
424
+
425
+ Loop( { name: 'x', type: 'int', start: startX, end: endX, condition: '<=' }, ( { x } ) => {
426
+
427
+ If( w0.greaterThanEqual( 0.0 ).and( w1.greaterThanEqual( 0.0 ) ).and( w2.greaterThanEqual( 0.0 ) ).and( z.greaterThanEqual( 0.0 ) ).and( z.lessThanEqual( 1.0 ) ), () => {
428
+
429
+ // depth with a fourth-root distribution, packed above each payload
430
+
431
+ const zEncoded = sqrt( sqrt( float( 1.0 ).sub( z ) ) );
432
+ const depthTri = uint( zEncoded.mul( DEPTH_TRI_MAX ) );
433
+ const depthInst = uint( zEncoded.mul( DEPTH_INST_MAX ) );
434
+
435
+ const pixelIndex = uint( y ).mul( uint( w ) ).add( uint( x ) );
436
+
437
+ // the depth occupies the high bits, so atomicMax resolves the depth test and the payload together
438
+
439
+ If( depthTri.greaterThanEqual( atomicLoad( screenTriAtomic.element( pixelIndex ) ).shiftRight( TRIANGLE_INDEX_BITS ) ), () => {
440
+
441
+ atomicMax( screenTriAtomic.element( pixelIndex ), depthTri.shiftLeft( TRIANGLE_INDEX_BITS ).bitOr( megaTriangleIndex.sub( triangleBase ).bitAnd( TRIANGLE_INDEX_MASK ) ) );
442
+ atomicMax( screenInstAtomic.element( pixelIndex ), depthInst.shiftLeft( INSTANCE_INDEX_BITS ).bitOr( instanceOffset.add( instId ) ) );
443
+
444
+ } );
445
+
446
+ } );
447
+
448
+ w0.addAssign( stepX_w0 );
449
+ w1.addAssign( stepX_w1 );
450
+ w2.addAssign( stepX_w2 );
451
+ z.addAssign( stepX_z );
452
+
453
+ } );
454
+
455
+ row_w0.addAssign( stepY_w0 );
456
+ row_w1.addAssign( stepY_w1 );
457
+ row_w2.addAssign( stepY_w2 );
458
+ row_z.addAssign( stepY_z );
459
+
460
+ } );
461
+
462
+ } ).ElseIf( startX.lessThanEqual( endX ).and( startY.lessThanEqual( endY ) ), enqueueHardware );
463
+
464
+ } );
465
+
466
+ } );
467
+
468
+ } ).ElseIf( p0.w.greaterThan( 0.0 ).or( p1.w.greaterThan( 0.0 ) ).or( p2.w.greaterThan( 0.0 ) ), enqueueHardware );
469
+
470
+ } );
471
+
472
+ } );
473
+
474
+ } )().compute( dispatchAttribute ).setName( 'VisibilityBufferDrawingPipeline Rasterize' );
475
+
476
+ // indirect draw arguments of the hardware path
477
+
478
+ const computeHWArgs = Fn( () => {
479
+
480
+ hwDrawBuffer.element( 0 ).assign( min( atomicLoad( hwQueueAtomic.element( 0 ) ), uint( MAX_HW_TRIANGLES ) ).mul( 3 ) );
481
+ hwDrawBuffer.element( 1 ).assign( uint( 1 ) );
482
+ hwDrawBuffer.element( 2 ).assign( uint( 0 ) );
483
+ hwDrawBuffer.element( 3 ).assign( uint( 0 ) );
484
+
485
+ } )().compute( 1 ).setName( 'VisibilityBufferDrawingPipeline HW Args' );
486
+
487
+
488
+ this.computeNodes.push( computeHWReset, computeDispatch, computeRasterize, computeHWArgs );
489
+
490
+ // hardware path — the large triangles queued by the software rasterizer
491
+
492
+ const slot = vertexIndex.div( 3 ).mul( 2 ).add( 1 );
493
+
494
+ this.hwMesh = this.createPulledMesh( hwDrawAttribute, {
495
+ instance: hwQueueRead.element( slot ),
496
+ triangle: hwQueueRead.element( slot.add( 1 ) ),
497
+ corner: vertexIndex.mod( 3 )
498
+ }, shared );
499
+
500
+ // resolve — shades the visibility buffer through the material graph
501
+
502
+ // the resolve draws the bounding box of each object, so every fragment is only shaded by the box of
503
+ // the object visible in it — a fullscreen resolve would run the material for the whole screen per batch.
504
+ // the back faces cover the object even if the camera is inside its box. the winding of the box is
505
+ // reversed instead of using BackSide, which would negate the normals of the material.
506
+
507
+ if ( _resolveGeometry === null ) {
508
+
509
+ _resolveGeometry = new BoxGeometry();
510
+
511
+ const index = _resolveGeometry.index;
512
+
513
+ for ( let i = 0; i < index.count; i += 3 ) {
514
+
515
+ const b = index.getX( i + 1 );
516
+
517
+ index.setX( i + 1, index.getX( i + 2 ) );
518
+ index.setX( i + 2, b );
519
+
520
+ }
521
+
522
+ }
523
+
524
+ const vResolveInstance = varyingProperty( 'uint', 'vVisibilityBufferInstance' );
525
+
526
+ const boxMin = uniform( clusters.boundingBox.min.clone() );
527
+ const boxSize = uniform( clusters.boundingBox.max.clone().sub( clusters.boundingBox.min ) );
528
+
529
+ const resolveVertex = Fn( () => {
530
+
531
+ vResolveInstance.assign( instanceIndex );
532
+
533
+ if ( deformed === true ) {
534
+
535
+ // the box of the deformed positions: the world matrix of the culling approximates the deformation, the box
536
+ // grows by the margin of the deformation. deformations which can't be bounded are resolved fullscreen
537
+
538
+ const bounds = this.culling.instanceBounds.element( this.rangeNodes.dataOffset.add( instanceIndex ) );
539
+ const margin = bounds.x.div( bounds.w.abs() );
540
+ const boxPosition = positionGeometry.add( 0.5 ).mul( boxSize.add( margin.mul( 2 ) ) ).add( boxMin.sub( margin ) );
541
+ const clipPosition = cameraProjectionMatrix.mul( cameraViewMatrix ).mul( instanceWorld.element( instanceIndex ) ).mul( vec4( boxPosition, 1.0 ) );
542
+
543
+ return select( this.unbounded.greaterThan( 0 ), vec4( 0 ), clipPosition );
544
+
545
+ }
546
+
547
+ const boxPosition = positionGeometry.add( 0.5 ).mul( boxSize ).add( boxMin );
548
+
549
+ return cameraProjectionMatrix.mul( cameraViewMatrix ).mul( instanceWorld.element( instanceIndex ) ).mul( vec4( boxPosition, 1.0 ) );
550
+
551
+ } )();
552
+
553
+ // the rasterizer addresses the screen bottom-up, screenCoordinate is top-down
554
+
555
+ const flippedY = viewSize.y.sub( screenCoordinate.y );
556
+ const pixelIndex = uint( flippedY ).mul( uint( viewSize.x ) ).add( uint( screenCoordinate.x ) );
557
+
558
+ const packedTri = screenTriRead.element( pixelIndex );
559
+ const megaTriangleIndex = packedTri.bitAnd( TRIANGLE_INDEX_MASK ).add( triangleBase );
560
+ // the fragment is shaded if the object visible in it is the object of the box
561
+
562
+ const globalInstance = screenInstRead.element( pixelIndex ).bitAnd( INSTANCE_INDEX_MASK );
563
+ const ownedByBox = globalInstance.equal( instanceOffset.add( vResolveInstance ) );
564
+ const instId = globalInstance.sub( instanceOffset );
565
+
566
+ // the fullscreen resolve shades the fragments of all objects of the batch
567
+
568
+ this.resolveCount = uniform( 0, 'uint' );
569
+
570
+ const ownedByBatch = instId.lessThan( this.resolveCount );
571
+
572
+ const i0 = indexBuffer.element( megaTriangleIndex.mul( 3 ) );
573
+ const i1 = indexBuffer.element( megaTriangleIndex.mul( 3 ).add( 1 ) );
574
+ const i2 = indexBuffer.element( megaTriangleIndex.mul( 3 ).add( 2 ) );
575
+
576
+ let matrixWorld, l0, l1, l2, n0, n1, n2;
577
+
578
+ if ( deformed === true ) {
579
+
580
+ const deformedTriangle = deformCorners( [ i0, i1, i2 ], instId );
581
+ const deformedPositions = deformedTriangle.get( 'positions' );
582
+ const deformedNormals = deformedTriangle.get( 'normals' );
583
+
584
+ matrixWorld = objectWorld.element( instId );
585
+
586
+ l0 = deformedPositions.element( 0 );
587
+ l1 = deformedPositions.element( 1 );
588
+ l2 = deformedPositions.element( 2 );
589
+
590
+ n0 = deformedNormals.element( 0 );
591
+ n1 = deformedNormals.element( 1 );
592
+ n2 = deformedNormals.element( 2 );
593
+
594
+ } else {
595
+
596
+ matrixWorld = instanceWorld.element( instId );
597
+
598
+ l0 = position( i0 );
599
+ l1 = position( i1 );
600
+ l2 = position( i2 );
601
+
602
+ n0 = normal( i0 );
603
+ n1 = normal( i1 );
604
+ n2 = normal( i2 );
605
+
606
+ }
607
+
608
+ const p0 = projScreenMatrix.mul( matrixWorld ).mul( vec4( l0, 1.0 ) );
609
+ const p1 = projScreenMatrix.mul( matrixWorld ).mul( vec4( l1, 1.0 ) );
610
+ const p2 = projScreenMatrix.mul( matrixWorld ).mul( vec4( l2, 1.0 ) );
611
+
612
+ const screenScale = vec2( viewSize.x, viewSize.y );
613
+ const s0 = p0.xy.div( p0.w ).add( 1.0 ).mul( 0.5 ).mul( screenScale );
614
+ const s1 = p1.xy.div( p1.w ).add( 1.0 ).mul( 0.5 ).mul( screenScale );
615
+ const s2 = p2.xy.div( p2.w ).add( 1.0 ).mul( 0.5 ).mul( screenScale );
616
+
617
+ const p = vec2( screenCoordinate.x, flippedY );
618
+
619
+ // perspective correct barycentrics from the edge functions weighted by the inverse clip w
620
+
621
+ const e0 = edgeFunction( s1, s2, p );
622
+ const e1 = edgeFunction( s2, s0, p );
623
+ const e2 = edgeFunction( s0, s1, p );
624
+
625
+ const q0 = float( 1.0 ).div( p0.w );
626
+ const q1 = float( 1.0 ).div( p1.w );
627
+ const q2 = float( 1.0 ).div( p2.w );
628
+
629
+ const sum = e0.mul( q0 ).add( e1.mul( q1 ) ).add( e2.mul( q2 ) );
630
+ const safeSum = sum.equal( 0.0 ).select( 1.0, sum );
631
+
632
+ const interpolate = ( a0, a1, a2 ) => a0.mul( e0.mul( q0 ) ).add( a1.mul( e1.mul( q1 ) ) ).add( a2.mul( e2.mul( q2 ) ) ).div( safeSum );
633
+
634
+ // analytic screen-space derivatives, neighbor fragments can belong to other triangles —
635
+ // the derivatives of the edge functions along the screen x and y axes, with the same
636
+ // orientation as the hardware derivatives
637
+
638
+ const dx = ( a0, a1, a2, value ) => derivative( a0, a1, a2, value, s2.y.sub( s1.y ), s0.y.sub( s2.y ), s1.y.sub( s0.y ) );
639
+ const dy = ( a0, a1, a2, value ) => derivative( a0, a1, a2, value, s1.x.sub( s2.x ), s2.x.sub( s0.x ), s0.x.sub( s1.x ) );
640
+
641
+ const derivative = ( a0, a1, a2, value, d0, d1, d2 ) => d0.mul( q0 ).mul( a0.sub( value ) ).add( d1.mul( q1 ).mul( a1.sub( value ) ) ).add( d2.mul( q2 ).mul( a2.sub( value ) ) ).div( safeSum );
642
+
643
+ const uv0 = vertexUv( i0 );
644
+ const uv1 = vertexUv( i1 );
645
+ const uv2 = vertexUv( i2 );
646
+
647
+ const uv = interpolate( uv0, uv1, uv2 );
648
+ const uvDx = dx( uv0, uv1, uv2, uv );
649
+ const uvDy = dy( uv0, uv1, uv2, uv );
650
+
651
+ const localPosition = interpolate( l0, l1, l2 );
652
+ const localNormal = interpolate( n0, n1, n2 );
653
+ const worldPosition = matrixWorld.mul( vec4( localPosition, 1.0 ) ).xyz;
654
+ const worldNormal = matrixWorld.mul( vec4( localNormal, 0.0 ) ).xyz;
655
+
656
+ // tangent frame of normal maps from the analytic derivatives, see TangentUtils
657
+
658
+ const modelView = cameraViewMatrix.mul( matrixWorld );
659
+
660
+ const v0 = modelView.mul( vec4( l0, 1.0 ) ).xyz;
661
+ const v1 = modelView.mul( vec4( l1, 1.0 ) ).xyz;
662
+ const v2 = modelView.mul( vec4( l2, 1.0 ) ).xyz;
663
+
664
+ const viewPosition = interpolate( v0, v1, v2 );
665
+ const viewNormal = cameraViewMatrix.mul( vec4( worldNormal, 0.0 ) ).xyz.normalize();
666
+
667
+ const q1perp = dy( v0, v1, v2, viewPosition ).cross( viewNormal );
668
+ const q0perp = viewNormal.cross( dx( v0, v1, v2, viewPosition ) );
669
+
670
+ const tangent = q1perp.mul( uvDx.x ).add( q0perp.mul( uvDy.x ) );
671
+ const bitangent = q1perp.mul( uvDx.y ).add( q0perp.mul( uvDy.y ) );
672
+
673
+ const det = tangent.dot( tangent ).max( bitangent.dot( bitangent ) );
674
+ const frameScale = det.equal( 0.0 ).select( 0.0, det.inverseSqrt() );
675
+
676
+ // depth from the high bits with the fourth-root distribution reversed, zero means not covered
677
+
678
+ const depthTri = packedTri.shiftRight( TRIANGLE_INDEX_BITS );
679
+ const depthEncoded = float( depthTri ).div( DEPTH_TRI_MAX );
680
+ const depthSquared = depthEncoded.mul( depthEncoded );
681
+
682
+ const createResolveMaterial = ( vertexNode, owned ) => {
683
+
684
+ let resolveMaterial;
685
+
686
+ if ( debug === true ) {
687
+
688
+ resolveMaterial = createDebugMaterial( megaTriangleIndex.div( MESHLET_SIZE ), instId );
689
+
690
+ } else {
691
+
692
+ resolveMaterial = createDrawMaterial( material, renderer );
693
+ resolveMaterial.positionNode = null;
694
+ resolveMaterial.receivedShadowPositionNode = worldPosition;
695
+ resolveMaterial.contextNode = createSurfaceContext( {
696
+ localPosition,
697
+ localNormal,
698
+ worldPosition,
699
+ worldNormal,
700
+ uv,
701
+ uvGradient: [ uvDx, uvDy ],
702
+ tangentFrame: [ tangent.mul( frameScale ), bitangent.mul( frameScale ) ],
703
+ matrixWorld,
704
+ attribute: ( name ) => {
705
+
706
+ return hasAttribute( name ) ? interpolate( attribute( name, i0 ), attribute( name, i1 ), attribute( name, i2 ) ) : null;
707
+
708
+ }
709
+ } );
710
+
711
+ }
712
+
713
+ resolveMaterial.vertexNode = vertexNode;
714
+ resolveMaterial.depthNode = float( 1.0 ).sub( depthSquared.mul( depthSquared ) );
715
+ resolveMaterial.maskNode = depthTri.notEqual( uint( 0 ) ).and( owned );
716
+
717
+ return resolveMaterial;
718
+
719
+ };
720
+
721
+ this.resolveMesh = new Mesh( _resolveGeometry, createResolveMaterial( resolveVertex, ownedByBox ) );
722
+ this.resolveMesh.frustumCulled = false;
723
+ this.resolveMesh.receiveShadow = receiveShadow;
724
+
725
+ this.meshes.push( this.resolveMesh, this.hwMesh );
726
+
727
+ // deformations which can't be bounded are resolved by one fullscreen triangle instead of the boxes
728
+
729
+ if ( deformed === true ) {
730
+
731
+ if ( _fullscreenGeometry === null ) {
732
+
733
+ _fullscreenGeometry = new BufferGeometry();
734
+ _fullscreenGeometry.setAttribute( 'position', new Float32BufferAttribute( [ - 1, - 1, 0, 3, - 1, 0, - 1, 3, 0 ], 3 ) );
735
+
736
+ }
737
+
738
+ const fullscreenVertex = select( this.unbounded.greaterThan( 0 ), vec4( positionGeometry.xy, 0.0, 1.0 ), vec4( 0 ) );
739
+
740
+ this.fullscreenMesh = new Mesh( _fullscreenGeometry, createResolveMaterial( fullscreenVertex, ownedByBatch ) );
741
+ this.fullscreenMesh.frustumCulled = false;
742
+ this.fullscreenMesh.receiveShadow = receiveShadow;
743
+
744
+ this.meshes.push( this.fullscreenMesh );
745
+
746
+ }
747
+
748
+ }
749
+
750
+ update( ...parameters ) {
751
+
752
+ super.update( ...parameters );
753
+
754
+ // Compaction can move this geometry without rebuilding its batch.
755
+
756
+ this.triangleBase.value = this.pool.add( this.clusters );
757
+
758
+ const pipeline = parameters[ 1 ];
759
+
760
+ this.maxRasterSize.value = pipeline.maxRasterSize;
761
+ this.resolveCount.value = this.count;
762
+
763
+ }
764
+
765
+ }
766
+
767
+ /**
768
+ * A meshlet drawing pipeline with a hybrid rasterizer. Like {@link MeshletDrawingPipeline}, compute shaders select the
769
+ * level of detail and cull objects and clusters, but the visible clusters are rasterized into a visibility
770
+ * buffer: small triangles in software by a compute shader, large triangles by the hardware rasterizer. A
771
+ * resolve pass shades the visibility buffer with the material of the meshes: its node graph is evaluated on
772
+ * the reconstructed surface (position, normal, model matrices and the attributes of the geometry) with
773
+ * analytic derivatives, so custom nodes, lights, shadows and the environment work as usual and the meshes
774
+ * depth test against other objects.
775
+ *
776
+ * The visibility buffer stores the triangle in 16 bits, so only the levels of detail whose triangles fit
777
+ * into this range are used. Geometries whose most detailed level doesn't fit are drawn by the hardware
778
+ * pipeline of {@link MeshletDrawingPipeline}. The resolve only writes the color, so render calls with MRT, like the
779
+ * velocity of TRAA, draw all clusters with the hardware pipeline. The position node of the material is evaluated
780
+ * per corner of the triangles by the software rasterizer and by the resolve.
781
+ *
782
+ * ```js
783
+ * renderer.drawingPipeline = new VisibilityBufferDrawingPipeline();
784
+ * ```
785
+ *
786
+ * This class is experimental and its interface might change.
787
+ *
788
+ * @augments MeshletDrawingPipeline
789
+ */
790
+ class VisibilityBufferDrawingPipeline extends MeshletDrawingPipeline {
791
+
792
+ /**
793
+ * Constructs a new visibility buffer drawing pipeline.
794
+ *
795
+ * @param {Object} [parameters] - The configuration parameter.
796
+ * @param {number} [parameters.lodThreshold=1] - The projected error in pixels below which a simpler level of detail is selected.
797
+ * @param {number} [parameters.shadowLodThreshold=1] - The projected error in shadow map texels below which a simpler level of detail is selected for shadow casters.
798
+ * @param {number} [parameters.maxRasterSize=8] - The maximum screen-space size in pixels of triangles rasterized in software.
799
+ * @param {boolean} [parameters.debug=false] - Whether the clusters should be shown with a flat color each instead of the material.
800
+ * @param {boolean} [parameters.occlusionCulling=true] - Whether the clusters hidden by other clusters should be culled.
801
+ */
802
+ constructor( { lodThreshold, shadowLodThreshold, maxRasterSize = 8, debug, occlusionCulling } = {} ) {
803
+
804
+ super( { lodThreshold, shadowLodThreshold, debug, occlusionCulling } );
805
+
806
+ this._hardware = false;
807
+
808
+ /**
809
+ * The maximum screen-space size in pixels of triangles rasterized in software.
810
+ * Larger triangles are drawn by the hardware rasterizer. The software rasterizer
811
+ * loops over the pixels of a triangle in one thread, so it only pays off for small
812
+ * triangles.
813
+ *
814
+ * @type {number}
815
+ * @default 8
816
+ */
817
+ this.maxRasterSize = maxRasterSize;
818
+
819
+ }
820
+
821
+ /**
822
+ * The maximum number of objects per render list, limited by the instance index of the visibility buffer.
823
+ *
824
+ * @type {number}
825
+ * @readonly
826
+ */
827
+ get maxInstances() {
828
+
829
+ return MAX_INSTANCES;
830
+
831
+ }
832
+
833
+ updateView( record, width, height ) {
834
+
835
+ // shadow passes are drawn by the hardware rasterizer of the base pipeline
836
+
837
+ if ( this._shadowPass === true ) return null;
838
+
839
+ // the resolve only writes the color and the software rasterizer doesn't apply the deformation of the render call:
840
+ // render calls with MRT or deformed positions draw all clusters with the hardware rasterizer
841
+
842
+ const hardware = this.renderer.getMRT() !== null || this._boundsNode !== null;
843
+
844
+ if ( record.view !== null && record.view.hardware !== hardware ) {
845
+
846
+ record.view.dispose();
847
+ record.view = null;
848
+
849
+ }
850
+
851
+ this._hardware = hardware;
852
+
853
+ return super.updateView( record, width, height );
854
+
855
+ }
856
+
857
+ _isSupportedMaterial( material ) {
858
+
859
+ // the software rasterizer doesn't discard fragments
860
+
861
+ // the resolve doesn't write the MRT outputs of the material
862
+
863
+ if ( material.isNodeMaterial === true && ( ( material.maskNode !== null && material.maskNode !== undefined ) || ( material.mrtNode !== null && material.mrtNode !== undefined ) ) ) return false;
864
+
865
+ return super._isSupportedMaterial( material );
866
+
867
+ }
868
+
869
+ _canMergeLevels() {
870
+
871
+ // the resolve shades a batch with one material, the levels of LOD objects are drawn as separate objects
872
+
873
+ return false;
874
+
875
+ }
876
+
877
+ _usesDepthPrepass() {
878
+
879
+ // the resolve shades every pixel once, the large triangles of the hardware path are drawn directly
880
+
881
+ return false;
882
+
883
+ }
884
+
885
+ createView( width, height, occlusion ) {
886
+
887
+ if ( this._hardware === true ) {
888
+
889
+ const view = super.createView( width, height, occlusion );
890
+
891
+ if ( view !== null ) view.hardware = true;
892
+
893
+ return view;
894
+
895
+ }
896
+
897
+ const view = createView( width, height );
898
+ view.hardware = false;
899
+ const disposeBuffers = view.dispose;
900
+
901
+ view.occlusion = occlusion === true ? createOcclusion( width, height ) : null;
902
+ view.dispose = () => {
903
+
904
+ disposeBuffers();
905
+
906
+ if ( view.occlusion !== null ) view.occlusion.dispose();
907
+
908
+ };
909
+
910
+ return view;
911
+
912
+ }
913
+
914
+ /**
915
+ * The batches of the software rasterizer index the triangles of one geometry, each geometry has its own batches.
916
+ *
917
+ * @param {Object} clusters - The cluster data of the geometry.
918
+ * @return {Object} The key.
919
+ */
920
+ _getBatchKey( clusters ) {
921
+
922
+ return clusters;
923
+
924
+ }
925
+
926
+ createBatch( entry, capacity, view, culling ) {
927
+
928
+ // the levels of detail whose triangles fit into the triangle index of the visibility buffer,
929
+ // the levels are ordered from the most detailed one
930
+
931
+ // the instances of instanced meshes are drawn as objects, their world matrices are computed on the GPU. the resolve
932
+ // doesn't read the instanced attributes of the geometry and the instance colors, these instanced meshes are drawn by the hardware rasterizer
933
+
934
+ // the software rasterizer doesn't evaluate the alpha of alpha-tested materials
935
+
936
+ if ( this._shadowPass === true || ( entry.instanced === true && ( entry.clusters.instancedAttributes.length > 0 || entry.instanceColor === true ) ) || entry.material.alphaTest > 0 || view === null || view.hardware === true ) return super.createBatch( entry, capacity, view, culling );
937
+
938
+ const lodTriangleEnds = entry.clusters.lodTriangleEnds;
939
+
940
+ let lodCount = 0;
941
+
942
+ while ( lodCount < lodTriangleEnds.length && lodTriangleEnds[ lodCount ] <= MAX_TRIANGLES ) lodCount ++;
943
+
944
+ if ( lodCount === 0 ) return super.createBatch( entry, capacity, view, culling );
945
+
946
+ const source = entry.source !== null ? entry.source.batch : null;
947
+
948
+ return new VisibilityBufferBatch( entry.clusters, entry.material, entry.receiveShadow, capacity, this.renderer, culling, { debug: this.debug, lodCount, view, instanced: entry.instanced, source, queueBudget: entry.queueBudget, maxChunks: entry.maxChunks, pool: this._geometryPool } );
949
+
950
+ }
951
+
952
+ }
953
+
954
+ export { VisibilityBufferDrawingPipeline };