@woosh/meep-engine 3.42.0 → 3.44.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 (345) hide show
  1. package/editor/prototypeEditorShell.d.ts.map +1 -1
  2. package/editor/prototypeEditorShell.js +4 -2
  3. package/package.json +91 -96
  4. package/src/engine/Clock.d.ts +15 -0
  5. package/src/engine/Clock.d.ts.map +1 -1
  6. package/src/engine/Clock.js +29 -5
  7. package/src/engine/Engine.d.ts.map +1 -1
  8. package/src/engine/Engine.js +11 -19
  9. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts +57 -0
  10. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts.map +1 -0
  11. package/src/engine/graphics/ecs/mesh-v2/MeshSkin.js +84 -0
  12. package/src/engine/graphics3/AnimationGraphSystem.d.ts +23 -13
  13. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  14. package/src/engine/graphics3/AnimationGraphSystem.js +61 -64
  15. package/src/engine/graphics3/AnimationSystem.d.ts +24 -15
  16. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  17. package/src/engine/graphics3/AnimationSystem.js +67 -61
  18. package/src/engine/graphics3/MeshSkinSystem.d.ts +56 -0
  19. package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -0
  20. package/src/engine/graphics3/MeshSkinSystem.js +317 -0
  21. package/src/engine/graphics3/MeshSystem.d.ts +15 -35
  22. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  23. package/src/engine/graphics3/MeshSystem.js +21 -298
  24. package/src/engine/graphics3/RowChains.d.ts +76 -0
  25. package/src/engine/graphics3/RowChains.d.ts.map +1 -0
  26. package/src/engine/graphics3/RowChains.js +347 -0
  27. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +6 -0
  28. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  29. package/src/engine/graphics3/ShadedGeometrySystem.js +329 -309
  30. package/src/engine/graphics3/animation/AnimationClips.d.ts +56 -0
  31. package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -0
  32. package/src/engine/graphics3/animation/AnimationClips.js +79 -0
  33. package/src/engine/graphics3/animation/ClipListPlayer.d.ts +13 -14
  34. package/src/engine/graphics3/animation/ClipListPlayer.d.ts.map +1 -1
  35. package/src/engine/graphics3/animation/ClipListPlayer.js +262 -263
  36. package/src/engine/graphics3/animation/write_clip_playback.d.ts +3 -3
  37. package/src/engine/graphics3/animation/write_clip_playback.js +4 -4
  38. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +5 -0
  39. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  40. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +80 -75
  41. package/src/engine/graphics3/prefab/PrefabInstance.d.ts +4 -24
  42. package/src/engine/graphics3/prefab/PrefabInstance.d.ts.map +1 -1
  43. package/src/engine/graphics3/prefab/PrefabInstance.js +60 -80
  44. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts +16 -3
  45. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
  46. package/src/engine/graphics3/prefab/prefab_instantiate.js +49 -12
  47. package/src/engine/graphics3/prefab/prefab_place.d.ts +31 -17
  48. package/src/engine/graphics3/prefab/prefab_place.d.ts.map +1 -1
  49. package/src/engine/graphics3/prefab/prefab_place.js +175 -130
  50. package/src/engine/graphics3/register_clips.d.ts +64 -0
  51. package/src/engine/graphics3/register_clips.d.ts.map +1 -0
  52. package/src/engine/graphics3/register_clips.js +114 -0
  53. package/src/engine/physics/cloth/MEASUREMENTS.md +795 -0
  54. package/src/engine/physics/cloth/PLAN.md +339 -9
  55. package/src/engine/physics/cloth/build/ClothProxy.d.ts +113 -61
  56. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -1
  57. package/src/engine/physics/cloth/build/ClothProxy.js +142 -77
  58. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +22 -0
  59. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -0
  60. package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +75 -0
  61. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +43 -30
  62. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
  63. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +357 -284
  64. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts +62 -0
  65. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -0
  66. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +280 -0
  67. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +1 -1
  68. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +1 -1
  69. package/src/engine/physics/cloth/ecs/Cloth.d.ts +17 -9
  70. package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -1
  71. package/src/engine/physics/cloth/ecs/Cloth.js +220 -212
  72. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +6 -0
  73. package/src/engine/physics/cloth/ecs/ClothHold.d.ts +91 -0
  74. package/src/engine/physics/cloth/ecs/ClothHold.d.ts.map +1 -0
  75. package/src/engine/physics/cloth/ecs/ClothHold.js +103 -0
  76. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +254 -48
  77. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  78. package/src/engine/physics/cloth/ecs/ClothInstance.js +277 -47
  79. package/src/engine/physics/cloth/ecs/ClothPin.d.ts +73 -0
  80. package/src/engine/physics/cloth/ecs/ClothPin.d.ts.map +1 -0
  81. package/src/engine/physics/cloth/ecs/ClothPin.js +92 -0
  82. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts +36 -0
  83. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts.map +1 -0
  84. package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.js +61 -0
  85. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +23 -17
  86. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -1
  87. package/src/engine/physics/cloth/ecs/ClothRig.js +29 -27
  88. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +12 -14
  89. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  90. package/src/engine/physics/cloth/ecs/ClothSystem.js +20 -15
  91. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +57 -36
  92. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  93. package/src/engine/physics/cloth/ecs/ClothWorld.js +816 -179
  94. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +12 -13
  95. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
  96. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +20 -14
  97. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +63 -11
  98. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  99. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +321 -84
  100. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +9 -7
  101. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  102. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +9 -7
  103. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +3 -3
  104. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +30 -30
  105. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +37 -0
  106. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -0
  107. package/src/engine/physics/cloth/ecs/cloth_geodesic.js +142 -0
  108. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts +97 -0
  109. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -0
  110. package/src/engine/physics/cloth/ecs/cloth_holds.js +608 -0
  111. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +2 -2
  112. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
  113. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +160 -9
  114. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +17 -22
  115. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  116. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +55 -117
  117. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -6
  118. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  119. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +44 -15
  120. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +5 -0
  121. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  122. package/src/engine/physics/cloth/ecs/cloth_write_back.js +60 -16
  123. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -1
  124. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +65 -58
  125. package/src/engine/physics/cloth/playground/collide_main.js +1 -1
  126. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -1
  127. package/src/engine/physics/cloth/playground/garment_build.js +17 -5
  128. package/src/engine/physics/cloth/playground/garment_main.js +1 -1
  129. package/src/engine/physics/cloth/playground/rig_build.d.ts.map +1 -1
  130. package/src/engine/physics/cloth/playground/rig_build.js +302 -296
  131. package/src/engine/physics/cloth/solver/ClothState.d.ts +45 -7
  132. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  133. package/src/engine/physics/cloth/solver/ClothState.js +63 -7
  134. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +6 -1
  135. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  136. package/src/engine/physics/cloth/solver/cloth_contact_find.js +7 -2
  137. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts +114 -0
  138. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -0
  139. package/src/engine/physics/cloth/solver/cloth_hold_line.js +362 -0
  140. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +6 -2
  141. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
  142. package/src/engine/physics/cloth/solver/cloth_self_find.js +13 -13
  143. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +24 -12
  144. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  145. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +24 -12
  146. package/src/engine/physics/cloth/solver/cloth_step.d.ts +16 -0
  147. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  148. package/src/engine/physics/cloth/solver/cloth_step.js +183 -20
  149. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +1 -0
  150. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
  151. package/src/engine/physics/cloth/solver/cloth_step_instance.js +10 -3
  152. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts +1 -1
  153. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts.map +1 -1
  154. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.js +353 -346
  155. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +7 -5
  156. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
  157. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +7 -5
  158. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +9 -9
  159. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
  160. package/src/engine/physics/cloth/wind/cloth_sample_air.js +26 -26
  161. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  162. package/src/engine/simulation/Ticker.d.ts +13 -0
  163. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  164. package/src/engine/simulation/Ticker.js +43 -8
  165. package/src/shade/RENDERER_CONTRACT.md +8 -2
  166. package/src/shade/playground/mesh_row_ceiling/main.js +2 -1
  167. package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
  168. package/src/shade/playground/skinned_blas_refit/main.js +11 -19
  169. package/src/shade/playground/skinned_blas_refit/place_character.d.ts +6 -3
  170. package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -1
  171. package/src/shade/playground/skinned_blas_refit/place_character.js +90 -90
  172. package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -1
  173. package/src/shade/playground/skinned_mesh_soup/main.js +502 -509
  174. package/src/shade/playground/texture_encode/README.md +129 -109
  175. package/src/shade/playground/texture_encode/main.js +1430 -1430
  176. package/src/shade/playground/vgeo_runtime/README.md +5 -4
  177. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  178. package/src/shade/renderer/Renderer.js +6 -5
  179. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +45 -14
  180. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  181. package/src/shade/renderer/animation/GPUAnimationManager.js +316 -64
  182. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +5 -0
  183. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  184. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -1
  185. package/src/shade/renderer/atmosphere/GPUSky.d.ts +12 -0
  186. package/src/shade/renderer/atmosphere/GPUSky.d.ts.map +1 -1
  187. package/src/shade/renderer/atmosphere/GPUSky.js +162 -147
  188. package/src/shade/renderer/geometry/BoxGeometry.d.ts +1 -11
  189. package/src/shade/renderer/geometry/BoxGeometry.d.ts.map +1 -1
  190. package/src/shade/renderer/geometry/BoxGeometry.js +6 -13
  191. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts +19 -0
  192. package/src/shade/renderer/geometry/CapsuleGeometry.d.ts.map +1 -0
  193. package/src/shade/renderer/geometry/CapsuleGeometry.js +24 -0
  194. package/src/shade/renderer/geometry/ConeGeometry.d.ts +20 -0
  195. package/src/shade/renderer/geometry/ConeGeometry.d.ts.map +1 -0
  196. package/src/shade/renderer/geometry/ConeGeometry.js +33 -0
  197. package/src/shade/renderer/geometry/CylinderGeometry.d.ts +21 -0
  198. package/src/shade/renderer/geometry/CylinderGeometry.d.ts.map +1 -0
  199. package/src/shade/renderer/geometry/CylinderGeometry.js +35 -0
  200. package/src/shade/renderer/geometry/PlaneGeometry.d.ts +17 -0
  201. package/src/shade/renderer/geometry/PlaneGeometry.d.ts.map +1 -0
  202. package/src/shade/renderer/geometry/PlaneGeometry.js +22 -0
  203. package/src/shade/renderer/geometry/TorusGeometry.d.ts +18 -0
  204. package/src/shade/renderer/geometry/TorusGeometry.d.ts.map +1 -0
  205. package/src/shade/renderer/geometry/TorusGeometry.js +23 -0
  206. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts +21 -0
  207. package/src/shade/renderer/geometry/UVSphereGeometry.d.ts.map +1 -0
  208. package/src/shade/renderer/geometry/UVSphereGeometry.js +34 -0
  209. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts +19 -0
  210. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts.map +1 -0
  211. package/src/shade/renderer/geometry/primitives/make_capsule_geometry.js +205 -0
  212. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts +21 -0
  213. package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts.map +1 -0
  214. package/src/shade/renderer/geometry/primitives/make_cone_geometry.js +36 -0
  215. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts +1 -1
  216. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts.map +1 -1
  217. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +44 -9
  218. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts +20 -0
  219. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts.map +1 -0
  220. package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.js +190 -0
  221. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  222. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +7 -2
  223. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +26 -8
  224. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
  225. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +56 -39
  226. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts +7 -0
  227. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts.map +1 -1
  228. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js +46 -4
  229. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.d.ts.map +1 -1
  230. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.js +4 -2
  231. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +2 -2
  232. package/src/shade/renderer/gpu_primitive/sort/defs.js +79 -79
  233. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +1 -1
  234. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  235. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +7 -3
  236. package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.d.ts.map +1 -1
  237. package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +10 -3
  238. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  239. package/src/shade/renderer/particles/DESIGN.md +13 -9
  240. package/src/shade/renderer/particles/GPUParticleSystem.js +1 -1
  241. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +4 -3
  242. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
  243. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +200 -194
  244. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  245. package/src/shade/renderer/particles/graph_particles.js +6 -2
  246. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +1 -1
  247. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +1 -1
  248. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -1
  249. package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +334 -329
  250. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  251. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  252. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +7 -2
  253. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
  254. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +16 -4
  255. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +3 -2
  256. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
  257. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +3 -2
  258. package/src/shade/renderer/scene/GPUSceneContext.d.ts +9 -1
  259. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  260. package/src/shade/renderer/scene/GPUSceneContext.js +23 -1
  261. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +2444 -2345
  262. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts.map +1 -1
  263. package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.js +312 -310
  264. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts +3 -3
  265. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts.map +1 -1
  266. package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.js +383 -375
  267. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts.map +1 -1
  268. package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.js +349 -346
  269. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts +58 -0
  270. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts.map +1 -0
  271. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.js +536 -0
  272. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts +21 -7
  273. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts.map +1 -1
  274. package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.js +291 -327
  275. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts +25 -0
  276. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts.map +1 -0
  277. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.js +99 -0
  278. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts +5 -3
  279. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts.map +1 -1
  280. package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.js +47 -71
  281. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts +10 -0
  282. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts.map +1 -0
  283. package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.js +50 -0
  284. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts +4 -5
  285. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts.map +1 -1
  286. package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.js +7 -8
  287. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +4 -1
  288. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  289. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +74 -3
  290. package/src/shade/renderer/volumetrics/NOTES.md +1023 -957
  291. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts +5 -4
  292. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts.map +1 -1
  293. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.js +5 -4
  294. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.d.ts +1 -1
  295. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.js +1 -1
  296. package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.d.ts +1 -1
  297. package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.js +1 -1
  298. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts +41 -0
  299. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts.map +1 -0
  300. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.js +112 -0
  301. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +9 -23
  302. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  303. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +18 -126
  304. package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.d.ts +22 -0
  305. package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.d.ts.map +1 -0
  306. package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.js +228 -0
  307. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
  308. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +0 -53
  309. package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
  310. package/src/shade/renderer/water/chunk_water_transport.js +7 -5
  311. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
  312. package/src/shade/renderer/water/medium/GPUWaterBodies.js +8 -2
  313. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts +3 -2
  314. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
  315. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +3 -2
  316. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  317. package/src/shade/renderer/water/shader_water.js +3 -1
  318. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -1
  319. package/src/shade/renderer/water/surface/GPUWaterSurface.js +3 -1
  320. package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts +4 -3
  321. package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts.map +1 -1
  322. package/src/shade/renderer/water/surface/chunk_water_surface_sample.js +17 -7
  323. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
  324. package/src/shade/renderer/water/surface/graph_water_tessellation.js +11 -4
  325. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
  326. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +93 -30
  327. package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.d.ts.map +1 -1
  328. package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.js +13 -5
  329. package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts +29 -8
  330. package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts.map +1 -1
  331. package/src/shade/renderer/water/surface/particles/chunk_water_particle.js +155 -30
  332. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts +6 -1
  333. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts.map +1 -1
  334. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.js +157 -39
  335. package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts +91 -21
  336. package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts.map +1 -1
  337. package/src/shade/renderer/water/surface/particles/shader_water_particles.js +442 -70
  338. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +11 -3
  339. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  340. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +3 -0
  341. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  342. package/src/shade/wgsl/validate_wgsl_source.js +74 -3
  343. package/src/engine/graphics3/register_instance_animation.d.ts +0 -114
  344. package/src/engine/graphics3/register_instance_animation.d.ts.map +0 -1
  345. package/src/engine/graphics3/register_instance_animation.js +0 -201
@@ -1,375 +1,383 @@
1
- import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
2
- import { chunk_bc1_pack_block } from "./chunk_bc1_pack_block.js";
3
-
4
- /**
5
- * Encode sixteen RGB texels as one BC1 block, four-colour mode.
6
- *
7
- * **The line through colour space is the whole problem**, and it is the problem BC7 inherits with
8
- * more precision and BC6H with a different domain — which is why it is written once here as the
9
- * shape the later encoders build on. A BC1 block is two 5:6:5 colours and every texel at one of
10
- * four points on the segment between them, so the fit is: find the line, place its ends, then find
11
- * the pair of *representable* ends that the decoder's own palette makes best.
12
- *
13
- * 1. **The principal axis**, by four rounds of power iteration on the block's covariance, seeded
14
- * with the bounding box's diagonal — `stb_dxt`'s choice, kept by betsy and `rgbcx`. Castaño
15
- * notes the iteration "is very sensitive to the initial approximation"; the diagonal is the
16
- * seed that already points the right way for the blocks that matter.
17
- * 2. **The ends, then least squares.** The extreme projections on the axis start the line; two
18
- * rounds of assigning each texel its nearest of the four real palette points and re-solving
19
- * both ends by the normal equations — the same solve as `fit_endpoints.js`, with the weights
20
- * `0, 1/3, 2/3, 1` shared across the three channels — move it to where the texels are.
21
- * 3. **Quantisation, then a search in 5:6:5.** The rounded pair is a starting point and not an
22
- * answer, because five- and six-bit ends are coarse enough that the best representable pair is
23
- * not the rounding of the best real one — §9.11 measured that at up to 1.3 dB for the transcoder.
24
- * So each of the six stored components is stepped up and down in turn, twice over, keeping any
25
- * step that lowers the block's error against the decoder's palette: coordinate descent, twelve
26
- * scores a round, no branch that depends on the content for how long it runs.
27
- *
28
- * A **flat block** is the case every table-driven encoder special-cases, because a single colour
29
- * rounds to 5:6:5 with an error of up to four levels while a pair of ends whose one-third mix lands
30
- * on the colour is exact to a level. The mix is searched per channel over the ends' neighbours,
31
- * which is what `stb_dxt`'s optimal-match tables hold, computed rather than stored.
32
- *
33
- * The three-colour mode is never written: its fourth index is transparent black, and a block that
34
- * decodes to a hole on a device sampling `bc1-rgba-unorm` is not a lower-quality block, it is a
35
- * different picture. Alpha in the source is ignored; a caller with a cut-out wants BC7.
36
- *
37
- * The values are given in `[0, 1]` and fitted in `[0, 255]`, where the palette arithmetic is the
38
- * decoder's: ends expanded from 5:6:5 by bit replication, interior points at exact thirds,
39
- * truncated.
40
- *
41
- * @type {CodeChunk}
42
- */
43
- export const chunk_bc1_encode_block = CodeChunk.from(
44
- //language=WGSL
45
- `
46
- // a colour quantised to 5:6:5 — each channel rounded to its bit count, as the format stores it
47
- fn bc1_quantise(color: vec3<f32>) -> vec3<i32> {
48
- let scaled = round(clamp(color, vec3<f32>(0.0), vec3<f32>(255.0)) * vec3<f32>(31.0, 63.0, 31.0) / 255.0);
49
-
50
- return vec3<i32>(scaled);
51
- }
52
-
53
- // the eight-bit colour a 5:6:5 colour decodes to, by the bit replication hardware uses
54
- fn bc1_expand(q: vec3<i32>) -> vec3<f32> {
55
- return vec3<f32>(
56
- f32((q.x << 3) | (q.x >> 2)),
57
- f32((q.y << 2) | (q.y >> 4)),
58
- f32((q.z << 3) | (q.z >> 2))
59
- );
60
- }
61
-
62
- fn bc1_pack_565(q: vec3<i32>) -> u32 {
63
- return (u32(q.x) << 11u) | (u32(q.y) << 5u) | u32(q.z);
64
- }
65
-
66
- // the four-colour palette's entry, as the decoder builds it: the ends, then thirds, truncated
67
- fn bc1_palette_entry(c0: vec3<f32>, c1: vec3<f32>, index: u32) -> vec3<f32> {
68
- if (index == 0u) {
69
- return c0;
70
- }
71
-
72
- if (index == 1u) {
73
- return c1;
74
- }
75
-
76
- if (index == 2u) {
77
- return floor((2.0 * c0 + c1) / 3.0);
78
- }
79
-
80
- return floor((c0 + 2.0 * c1) / 3.0);
81
- }
82
-
83
- // the palette entry nearest a colour, and its squared distance
84
- fn bc1_nearest(c0: vec3<f32>, c1: vec3<f32>, color: vec3<f32>) -> vec2<f32> {
85
- var best = 0.0;
86
- var best_distance = 1e30;
87
-
88
- for (var index = 0u; index < 4u; index++) {
89
- let delta = bc1_palette_entry(c0, c1, index) - color;
90
- let distance = dot(delta, delta);
91
-
92
- if (distance < best_distance) {
93
- best_distance = distance;
94
- best = f32(index);
95
- }
96
- }
97
-
98
- return vec2<f32>(best, best_distance);
99
- }
100
-
101
- // the block's squared error against a quantised pair, in the mode their order selects; only the
102
- // four-colour mode is ever wanted, so an equal or inverted pair scores as unusable
103
- fn bc1_score(texels: array<vec3<f32>, 16>, q0: vec3<i32>, q1: vec3<i32>) -> f32 {
104
- if (bc1_pack_565(q0) <= bc1_pack_565(q1)) {
105
- return 1e30;
106
- }
107
-
108
- let c0 = bc1_expand(q0);
109
- let c1 = bc1_expand(q1);
110
-
111
- var error = 0.0;
112
-
113
- for (var i = 0u; i < 16u; i++) {
114
- error += bc1_nearest(c0, c1, texels[i]).y;
115
- }
116
-
117
- return error;
118
- }
119
-
120
- // the ends that best reproduce the texels at the palette points they are nearest to on a real line:
121
- // the two-by-two normal equations, shared across the channels because the weights are
122
- fn bc1_refine(texels: array<vec3<f32>, 16>, e0: vec3<f32>, e1: vec3<f32>) -> array<vec3<f32>, 2> {
123
- var aa = 0.0;
124
- var ab = 0.0;
125
- var bb = 0.0;
126
- var ap = vec3<f32>(0.0);
127
- var bp = vec3<f32>(0.0);
128
-
129
- for (var i = 0u; i < 16u; i++) {
130
- // nearest of the four real points, by distance rather than by projection: the two are not
131
- // the same thing once the ends have moved off the axis the texels were projected on
132
- var best_weight = 0.0;
133
- var best_distance = 1e30;
134
-
135
- for (var step = 0u; step < 4u; step++) {
136
- let weight = f32(step) / 3.0;
137
- let delta = mix(e0, e1, weight) - texels[i];
138
- let distance = dot(delta, delta);
139
-
140
- if (distance < best_distance) {
141
- best_distance = distance;
142
- best_weight = weight;
143
- }
144
- }
145
-
146
- let b = best_weight;
147
- let a = 1.0 - b;
148
-
149
- aa += a * a;
150
- ab += a * b;
151
- bb += b * b;
152
- ap += a * texels[i];
153
- bp += b * texels[i];
154
- }
155
-
156
- let determinant = aa * bb - ab * ab;
157
-
158
- var out: array<vec3<f32>, 2>;
159
-
160
- // singular when every texel took the same point; the line is as good as it gets
161
- if (abs(determinant) < 1e-6) {
162
- out[0] = e0;
163
- out[1] = e1;
164
-
165
- return out;
166
- }
167
-
168
- out[0] = (bb * ap - ab * bp) / determinant;
169
- out[1] = (aa * bp - ab * ap) / determinant;
170
-
171
- return out;
172
- }
173
-
174
- // a vector with one component replaced — built rather than assigned into a copy, so the same code
175
- // means the same thing on a device, where a copy is a value, and in the emulator, where it is not
176
- fn bc1_with_component(v: vec3<i32>, channel: i32, value: i32) -> vec3<i32> {
177
- return vec3<i32>(
178
- select(v.x, value, channel == 0),
179
- select(v.y, value, channel == 1),
180
- select(v.z, value, channel == 2)
181
- );
182
- }
183
-
184
- // a flat block: per channel, the pair of stored values whose one-third mix lands nearest the colour,
185
- // which beats rounding the colour itself by up to three levels
186
- fn bc1_encode_flat(color: vec3<f32>) -> vec2<u32> {
187
- let bits = vec3<i32>(31, 63, 31);
188
- let centre = bc1_quantise(color);
189
-
190
- var q0 = centre;
191
- var q1 = centre;
192
-
193
- for (var channel = 0; channel < 3; channel++) {
194
- var best_distance = 1e30;
195
-
196
- for (var da = -1; da <= 1; da++) {
197
- for (var db = -1; db <= 1; db++) {
198
- let a = clamp(centre[channel] + da, 0, bits[channel]);
199
- let b = clamp(centre[channel] + db, 0, bits[channel]);
200
-
201
- let qa = bc1_with_component(centre, channel, a);
202
- let qb = bc1_with_component(centre, channel, b);
203
-
204
- let mixed = floor((2.0 * bc1_expand(qa)[channel] + bc1_expand(qb)[channel]) / 3.0);
205
- let distance = abs(mixed - color[channel]);
206
-
207
- if (distance < best_distance) {
208
- best_distance = distance;
209
- q0 = bc1_with_component(q0, channel, a);
210
- q1 = bc1_with_component(q1, channel, b);
211
- }
212
- }
213
- }
214
- }
215
-
216
- let first = bc1_pack_565(q0);
217
- let second = bc1_pack_565(q1);
218
-
219
- var indices: array<u32, 16>;
220
-
221
- // the mix was searched as two thirds of q0 and one of q1, which is index 2 with q0 first; with
222
- // the pair the other way round it is index 3; and equal ends are the three-colour mode, whose
223
- // index 0 is the colour itself
224
- let index = select(select(3u, 2u, first > second), 0u, first == second);
225
-
226
- for (var i = 0u; i < 16u; i++) {
227
- indices[i] = index;
228
- }
229
-
230
- if (first >= second) {
231
- return bc1_pack_block(first, second, indices);
232
- }
233
-
234
- return bc1_pack_block(second, first, indices);
235
- }
236
-
237
- fn bc1_encode_block(texels: array<vec3<f32>, 16>) -> vec2<u32> {
238
- var scaled: array<vec3<f32>, 16>;
239
-
240
- var low = vec3<f32>(255.0);
241
- var high = vec3<f32>(0.0);
242
- var mean = vec3<f32>(0.0);
243
-
244
- for (var i = 0u; i < 16u; i++) {
245
- let v = clamp(texels[i], vec3<f32>(0.0), vec3<f32>(1.0)) * 255.0;
246
-
247
- scaled[i] = v;
248
- low = min(low, v);
249
- high = max(high, v);
250
- mean += v;
251
- }
252
-
253
- mean = mean / 16.0;
254
-
255
- let extent = high - low;
256
-
257
- if (max(extent.x, max(extent.y, extent.z)) < 0.5) {
258
- return bc1_encode_flat(mean);
259
- }
260
-
261
- // the covariance's six distinct terms
262
- var cov = array<f32, 6>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
263
-
264
- for (var i = 0u; i < 16u; i++) {
265
- let d = scaled[i] - mean;
266
-
267
- cov[0] += d.x * d.x;
268
- cov[1] += d.x * d.y;
269
- cov[2] += d.x * d.z;
270
- cov[3] += d.y * d.y;
271
- cov[4] += d.y * d.z;
272
- cov[5] += d.z * d.z;
273
- }
274
-
275
- // power iteration from the box diagonal, which is never zero here
276
- var axis = extent;
277
-
278
- for (var iteration = 0u; iteration < 4u; iteration++) {
279
- let next = vec3<f32>(
280
- cov[0] * axis.x + cov[1] * axis.y + cov[2] * axis.z,
281
- cov[1] * axis.x + cov[3] * axis.y + cov[4] * axis.z,
282
- cov[2] * axis.x + cov[4] * axis.y + cov[5] * axis.z
283
- );
284
-
285
- let magnitude = length(next);
286
-
287
- // a degenerate covariance leaves the diagonal in charge
288
- if (magnitude < 1e-3) {
289
- break;
290
- }
291
-
292
- axis = next / magnitude;
293
- }
294
-
295
- axis = normalize(axis);
296
-
297
- var t_min = 1e30;
298
- var t_max = -1e30;
299
-
300
- for (var i = 0u; i < 16u; i++) {
301
- let t = dot(scaled[i] - mean, axis);
302
-
303
- t_min = min(t_min, t);
304
- t_max = max(t_max, t);
305
- }
306
-
307
- var e0 = mean + axis * t_min;
308
- var e1 = mean + axis * t_max;
309
-
310
- for (var round = 0u; round < 2u; round++) {
311
- let refined = bc1_refine(scaled, e0, e1);
312
-
313
- e0 = clamp(refined[0], vec3<f32>(0.0), vec3<f32>(255.0));
314
- e1 = clamp(refined[1], vec3<f32>(0.0), vec3<f32>(255.0));
315
- }
316
-
317
- var q0 = bc1_quantise(e0);
318
- var q1 = bc1_quantise(e1);
319
-
320
- // four-colour mode wants the first end greater; a pair that rounded together is a flat block
321
- if (bc1_pack_565(q0) < bc1_pack_565(q1)) {
322
- let swap = q0;
323
-
324
- q0 = q1;
325
- q1 = swap;
326
- }
327
-
328
- if (bc1_pack_565(q0) == bc1_pack_565(q1)) {
329
- return bc1_encode_flat(mean);
330
- }
331
-
332
- var best = bc1_score(scaled, q0, q1);
333
-
334
- // coordinate descent over the six stored components, twice
335
- let bits = vec3<i32>(31, 63, 31);
336
-
337
- for (var round = 0u; round < 2u; round++) {
338
- for (var component = 0; component < 6; component++) {
339
- let channel = component % 3;
340
-
341
- for (var direction = -1; direction <= 1; direction += 2) {
342
- var c0 = q0;
343
- var c1 = q1;
344
-
345
- if (component < 3) {
346
- c0 = bc1_with_component(q0, channel, clamp(q0[channel] + direction, 0, bits[channel]));
347
- } else {
348
- c1 = bc1_with_component(q1, channel, clamp(q1[channel] + direction, 0, bits[channel]));
349
- }
350
-
351
- let error = bc1_score(scaled, c0, c1);
352
-
353
- if (error < best) {
354
- best = error;
355
- q0 = c0;
356
- q1 = c1;
357
- }
358
- }
359
- }
360
- }
361
-
362
- let c0 = bc1_expand(q0);
363
- let c1 = bc1_expand(q1);
364
-
365
- var indices: array<u32, 16>;
366
-
367
- for (var i = 0u; i < 16u; i++) {
368
- indices[i] = u32(bc1_nearest(c0, c1, scaled[i]).x);
369
- }
370
-
371
- return bc1_pack_block(bc1_pack_565(q0), bc1_pack_565(q1), indices);
372
- }
373
- `, [
374
- chunk_bc1_pack_block,
375
- ]);
1
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
2
+ import { chunk_bc1_pack_block } from "./chunk_bc1_pack_block.js";
3
+
4
+ /**
5
+ * Encode sixteen RGB texels as one BC1 block, four-colour mode.
6
+ *
7
+ * **The line through colour space is the whole problem**, and it is the problem BC7 inherits with
8
+ * more precision and BC6H with a different domain — which is why it is written once here as the
9
+ * shape the later encoders build on. A BC1 block is two 5:6:5 colours and every texel at one of
10
+ * four points on the segment between them, so the fit is: find the line, place its ends, then find
11
+ * the pair of *representable* ends that the decoder's own palette makes best.
12
+ *
13
+ * 1. **The principal axis**, by four rounds of power iteration on the block's covariance, seeded
14
+ * with the bounding box's diagonal — `stb_dxt`'s choice, kept by betsy and `rgbcx`. Castaño
15
+ * notes the iteration "is very sensitive to the initial approximation"; the diagonal is the
16
+ * seed that already points the right way for the blocks that matter.
17
+ * 2. **The ends, then least squares.** The extreme projections on the axis start the line; two
18
+ * rounds of assigning each texel its nearest of the four real palette points and re-solving
19
+ * both ends by the normal equations — the same solve as `fit_endpoints.js`, with the weights
20
+ * `0, 1/3, 2/3, 1` shared across the three channels — move it to where the texels are.
21
+ * 3. **Quantisation, then a search in 5:6:5.** The rounded pair is a starting point and not an
22
+ * answer, because five- and six-bit ends are coarse enough that the best representable pair is
23
+ * not the rounding of the best real one — §9.11 measured that at up to 1.3 dB for the transcoder.
24
+ * So each of the six stored components is stepped up and down in turn, keeping any step that
25
+ * lowers the block's error against the decoder's palette: one round of coordinate descent,
26
+ * twelve scores, no branch that depends on the content for how long it runs.
27
+ *
28
+ * A **flat block** is the case every table-driven encoder special-cases, because a single colour
29
+ * rounds to 5:6:5 with an error of up to four levels while a pair of ends whose one-third mix lands
30
+ * on the colour is exact to a level. The mix is searched per channel over the ends' neighbours,
31
+ * which is what `stb_dxt`'s optimal-match tables hold, computed rather than stored.
32
+ *
33
+ * The three-colour mode is never written: its fourth index is transparent black, and a block that
34
+ * decodes to a hole on a device sampling `bc1-rgba-unorm` is not a lower-quality block, it is a
35
+ * different picture. Alpha in the source is ignored; a caller with a cut-out wants BC7.
36
+ *
37
+ * The values are given in `[0, 1]` and fitted in `[0, 255]`, where the palette arithmetic is the
38
+ * decoder's: ends expanded from 5:6:5 by bit replication, interior points at exact thirds,
39
+ * truncated.
40
+ *
41
+ * @type {CodeChunk}
42
+ */
43
+ export const chunk_bc1_encode_block = CodeChunk.from(
44
+ //language=WGSL
45
+ `
46
+ // a colour quantised to 5:6:5 — each channel rounded to its bit count, as the format stores it
47
+ fn bc1_quantise(color: vec3<f32>) -> vec3<i32> {
48
+ let scaled = round(clamp(color, vec3<f32>(0.0), vec3<f32>(255.0)) * vec3<f32>(31.0, 63.0, 31.0) / 255.0);
49
+
50
+ return vec3<i32>(scaled);
51
+ }
52
+
53
+ // the eight-bit colour a 5:6:5 colour decodes to, by the bit replication hardware uses
54
+ fn bc1_expand(q: vec3<i32>) -> vec3<f32> {
55
+ return vec3<f32>(
56
+ f32((q.x << 3) | (q.x >> 2)),
57
+ f32((q.y << 2) | (q.y >> 4)),
58
+ f32((q.z << 3) | (q.z >> 2))
59
+ );
60
+ }
61
+
62
+ fn bc1_pack_565(q: vec3<i32>) -> u32 {
63
+ return (u32(q.x) << 11u) | (u32(q.y) << 5u) | u32(q.z);
64
+ }
65
+
66
+ // the four-colour palette's entry, as the decoder builds it: the ends, then thirds, truncated
67
+ fn bc1_palette_entry(c0: vec3<f32>, c1: vec3<f32>, index: u32) -> vec3<f32> {
68
+ if (index == 0u) {
69
+ return c0;
70
+ }
71
+
72
+ if (index == 1u) {
73
+ return c1;
74
+ }
75
+
76
+ if (index == 2u) {
77
+ return floor((2.0 * c0 + c1) / 3.0);
78
+ }
79
+
80
+ return floor((c0 + 2.0 * c1) / 3.0);
81
+ }
82
+
83
+ // the palette entry nearest a colour, and its squared distance
84
+ fn bc1_nearest(c0: vec3<f32>, c1: vec3<f32>, color: vec3<f32>) -> vec2<f32> {
85
+ var best = 0.0;
86
+ var best_distance = 1e30;
87
+
88
+ for (var index = 0u; index < 4u; index++) {
89
+ let delta = bc1_palette_entry(c0, c1, index) - color;
90
+ let distance = dot(delta, delta);
91
+
92
+ if (distance < best_distance) {
93
+ best_distance = distance;
94
+ best = f32(index);
95
+ }
96
+ }
97
+
98
+ return vec2<f32>(best, best_distance);
99
+ }
100
+
101
+ // the block's squared error against a quantised pair, in the mode their order selects; only the
102
+ // four-colour mode is ever wanted, so an equal or inverted pair scores as unusable. The palette is
103
+ // built once and each texel takes the least of its four distances — the same sum as asking
104
+ // bc1_nearest per texel, which rebuilt the palette sixteen times and made the encoder 2.5x slower
105
+ fn bc1_score(texels: array<vec3<f32>, 16>, q0: vec3<i32>, q1: vec3<i32>) -> f32 {
106
+ if (bc1_pack_565(q0) <= bc1_pack_565(q1)) {
107
+ return 1e30;
108
+ }
109
+
110
+ let c0 = bc1_expand(q0);
111
+ let c1 = bc1_expand(q1);
112
+ let c2 = bc1_palette_entry(c0, c1, 2u);
113
+ let c3 = bc1_palette_entry(c0, c1, 3u);
114
+
115
+ var error = 0.0;
116
+
117
+ for (var i = 0u; i < 16u; i++) {
118
+ let d0 = c0 - texels[i];
119
+ let d1 = c1 - texels[i];
120
+ let d2 = c2 - texels[i];
121
+ let d3 = c3 - texels[i];
122
+
123
+ error += min(min(dot(d0, d0), dot(d1, d1)), min(dot(d2, d2), dot(d3, d3)));
124
+ }
125
+
126
+ return error;
127
+ }
128
+
129
+ // the ends that best reproduce the texels at the palette points they are nearest to on a real line:
130
+ // the two-by-two normal equations, shared across the channels because the weights are
131
+ fn bc1_refine(texels: array<vec3<f32>, 16>, e0: vec3<f32>, e1: vec3<f32>) -> array<vec3<f32>, 2> {
132
+ var aa = 0.0;
133
+ var ab = 0.0;
134
+ var bb = 0.0;
135
+ var ap = vec3<f32>(0.0);
136
+ var bp = vec3<f32>(0.0);
137
+
138
+ for (var i = 0u; i < 16u; i++) {
139
+ // nearest of the four real points, by distance rather than by projection: the two are not
140
+ // the same thing once the ends have moved off the axis the texels were projected on
141
+ var best_weight = 0.0;
142
+ var best_distance = 1e30;
143
+
144
+ for (var step = 0u; step < 4u; step++) {
145
+ let weight = f32(step) / 3.0;
146
+ let delta = mix(e0, e1, weight) - texels[i];
147
+ let distance = dot(delta, delta);
148
+
149
+ if (distance < best_distance) {
150
+ best_distance = distance;
151
+ best_weight = weight;
152
+ }
153
+ }
154
+
155
+ let b = best_weight;
156
+ let a = 1.0 - b;
157
+
158
+ aa += a * a;
159
+ ab += a * b;
160
+ bb += b * b;
161
+ ap += a * texels[i];
162
+ bp += b * texels[i];
163
+ }
164
+
165
+ let determinant = aa * bb - ab * ab;
166
+
167
+ var out: array<vec3<f32>, 2>;
168
+
169
+ // singular when every texel took the same point; the line is as good as it gets
170
+ if (abs(determinant) < 1e-6) {
171
+ out[0] = e0;
172
+ out[1] = e1;
173
+
174
+ return out;
175
+ }
176
+
177
+ out[0] = (bb * ap - ab * bp) / determinant;
178
+ out[1] = (aa * bp - ab * ap) / determinant;
179
+
180
+ return out;
181
+ }
182
+
183
+ // a vector with one component replaced — built rather than assigned into a copy, so the same code
184
+ // means the same thing on a device, where a copy is a value, and in the emulator, where it is not
185
+ fn bc1_with_component(v: vec3<i32>, channel: i32, value: i32) -> vec3<i32> {
186
+ return vec3<i32>(
187
+ select(v.x, value, channel == 0),
188
+ select(v.y, value, channel == 1),
189
+ select(v.z, value, channel == 2)
190
+ );
191
+ }
192
+
193
+ // a flat block: per channel, the pair of stored values whose one-third mix lands nearest the colour,
194
+ // which beats rounding the colour itself by up to three levels
195
+ fn bc1_encode_flat(color: vec3<f32>) -> vec2<u32> {
196
+ let bits = vec3<i32>(31, 63, 31);
197
+ let centre = bc1_quantise(color);
198
+
199
+ var q0 = centre;
200
+ var q1 = centre;
201
+
202
+ for (var channel = 0; channel < 3; channel++) {
203
+ var best_distance = 1e30;
204
+
205
+ for (var da = -1; da <= 1; da++) {
206
+ for (var db = -1; db <= 1; db++) {
207
+ let a = clamp(centre[channel] + da, 0, bits[channel]);
208
+ let b = clamp(centre[channel] + db, 0, bits[channel]);
209
+
210
+ let qa = bc1_with_component(centre, channel, a);
211
+ let qb = bc1_with_component(centre, channel, b);
212
+
213
+ let mixed = floor((2.0 * bc1_expand(qa)[channel] + bc1_expand(qb)[channel]) / 3.0);
214
+ let distance = abs(mixed - color[channel]);
215
+
216
+ if (distance < best_distance) {
217
+ best_distance = distance;
218
+ q0 = bc1_with_component(q0, channel, a);
219
+ q1 = bc1_with_component(q1, channel, b);
220
+ }
221
+ }
222
+ }
223
+ }
224
+
225
+ let first = bc1_pack_565(q0);
226
+ let second = bc1_pack_565(q1);
227
+
228
+ var indices: array<u32, 16>;
229
+
230
+ // the mix was searched as two thirds of q0 and one of q1, which is index 2 with q0 first; with
231
+ // the pair the other way round it is index 3; and equal ends are the three-colour mode, whose
232
+ // index 0 is the colour itself
233
+ let index = select(select(3u, 2u, first > second), 0u, first == second);
234
+
235
+ for (var i = 0u; i < 16u; i++) {
236
+ indices[i] = index;
237
+ }
238
+
239
+ if (first >= second) {
240
+ return bc1_pack_block(first, second, indices);
241
+ }
242
+
243
+ return bc1_pack_block(second, first, indices);
244
+ }
245
+
246
+ fn bc1_encode_block(texels: array<vec3<f32>, 16>) -> vec2<u32> {
247
+ var scaled: array<vec3<f32>, 16>;
248
+
249
+ var low = vec3<f32>(255.0);
250
+ var high = vec3<f32>(0.0);
251
+ var mean = vec3<f32>(0.0);
252
+
253
+ for (var i = 0u; i < 16u; i++) {
254
+ let v = clamp(texels[i], vec3<f32>(0.0), vec3<f32>(1.0)) * 255.0;
255
+
256
+ scaled[i] = v;
257
+ low = min(low, v);
258
+ high = max(high, v);
259
+ mean += v;
260
+ }
261
+
262
+ mean = mean / 16.0;
263
+
264
+ let extent = high - low;
265
+
266
+ if (max(extent.x, max(extent.y, extent.z)) < 0.5) {
267
+ return bc1_encode_flat(mean);
268
+ }
269
+
270
+ // the covariance's six distinct terms
271
+ var cov = array<f32, 6>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
272
+
273
+ for (var i = 0u; i < 16u; i++) {
274
+ let d = scaled[i] - mean;
275
+
276
+ cov[0] += d.x * d.x;
277
+ cov[1] += d.x * d.y;
278
+ cov[2] += d.x * d.z;
279
+ cov[3] += d.y * d.y;
280
+ cov[4] += d.y * d.z;
281
+ cov[5] += d.z * d.z;
282
+ }
283
+
284
+ // power iteration from the box diagonal, which is never zero here
285
+ var axis = extent;
286
+
287
+ for (var iteration = 0u; iteration < 4u; iteration++) {
288
+ let next = vec3<f32>(
289
+ cov[0] * axis.x + cov[1] * axis.y + cov[2] * axis.z,
290
+ cov[1] * axis.x + cov[3] * axis.y + cov[4] * axis.z,
291
+ cov[2] * axis.x + cov[4] * axis.y + cov[5] * axis.z
292
+ );
293
+
294
+ let magnitude = length(next);
295
+
296
+ // a degenerate covariance leaves the diagonal in charge
297
+ if (magnitude < 1e-3) {
298
+ break;
299
+ }
300
+
301
+ axis = next / magnitude;
302
+ }
303
+
304
+ axis = normalize(axis);
305
+
306
+ var t_min = 1e30;
307
+ var t_max = -1e30;
308
+
309
+ for (var i = 0u; i < 16u; i++) {
310
+ let t = dot(scaled[i] - mean, axis);
311
+
312
+ t_min = min(t_min, t);
313
+ t_max = max(t_max, t);
314
+ }
315
+
316
+ var e0 = mean + axis * t_min;
317
+ var e1 = mean + axis * t_max;
318
+
319
+ for (var round = 0u; round < 2u; round++) {
320
+ let refined = bc1_refine(scaled, e0, e1);
321
+
322
+ e0 = clamp(refined[0], vec3<f32>(0.0), vec3<f32>(255.0));
323
+ e1 = clamp(refined[1], vec3<f32>(0.0), vec3<f32>(255.0));
324
+ }
325
+
326
+ var q0 = bc1_quantise(e0);
327
+ var q1 = bc1_quantise(e1);
328
+
329
+ // four-colour mode wants the first end greater; a pair that rounded together is a flat block
330
+ if (bc1_pack_565(q0) < bc1_pack_565(q1)) {
331
+ let swap = q0;
332
+
333
+ q0 = q1;
334
+ q1 = swap;
335
+ }
336
+
337
+ if (bc1_pack_565(q0) == bc1_pack_565(q1)) {
338
+ return bc1_encode_flat(mean);
339
+ }
340
+
341
+ var best = bc1_score(scaled, q0, q1);
342
+
343
+ // coordinate descent over the six stored components, once: a second round was measured at
344
+ // 0.04 dB over twenty photographs for 43% more time (plan §9.20)
345
+ let bits = vec3<i32>(31, 63, 31);
346
+
347
+ for (var component = 0; component < 6; component++) {
348
+ let channel = component % 3;
349
+
350
+ for (var direction = -1; direction <= 1; direction += 2) {
351
+ var c0 = q0;
352
+ var c1 = q1;
353
+
354
+ if (component < 3) {
355
+ c0 = bc1_with_component(q0, channel, clamp(q0[channel] + direction, 0, bits[channel]));
356
+ } else {
357
+ c1 = bc1_with_component(q1, channel, clamp(q1[channel] + direction, 0, bits[channel]));
358
+ }
359
+
360
+ let error = bc1_score(scaled, c0, c1);
361
+
362
+ if (error < best) {
363
+ best = error;
364
+ q0 = c0;
365
+ q1 = c1;
366
+ }
367
+ }
368
+ }
369
+
370
+ let c0 = bc1_expand(q0);
371
+ let c1 = bc1_expand(q1);
372
+
373
+ var indices: array<u32, 16>;
374
+
375
+ for (var i = 0u; i < 16u; i++) {
376
+ indices[i] = u32(bc1_nearest(c0, c1, scaled[i]).x);
377
+ }
378
+
379
+ return bc1_pack_block(bc1_pack_565(q0), bc1_pack_565(q1), indices);
380
+ }
381
+ `, [
382
+ chunk_bc1_pack_block,
383
+ ]);