@woosh/meep-engine 3.60.3 → 3.60.5
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.
- package/CHANGELOG.md +2602 -0
- package/CONTRIBUTING.md +7 -0
- package/MIGRATION_2_TO_3.md +136 -0
- package/SECURITY.md +4 -0
- package/editor/EditorCameraNavigation.d.ts +2 -1
- package/editor/EditorCameraNavigation.d.ts.map +1 -1
- package/editor/EditorCameraNavigation.js +51 -57
- package/editor/ecs/component/editors/ecs/Trail3DEditor.d.ts +3 -0
- package/editor/ecs/component/editors/ecs/Trail3DEditor.d.ts.map +1 -1
- package/editor/ecs/component/editors/ecs/Trail3DEditor.js +6 -0
- package/package.json +6 -2
- package/src/engine/EngineHarness.d.ts +3 -9
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +6 -8
- package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
- package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
- package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
- package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
- package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
- package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +1 -2
- package/src/engine/graphics/ecs/trail3d/TRAIL3D_FADE_LINEAR.d.ts +14 -0
- package/src/engine/graphics/ecs/trail3d/TRAIL3D_FADE_LINEAR.d.ts.map +1 -0
- package/src/engine/graphics/ecs/trail3d/TRAIL3D_FADE_LINEAR.js +22 -0
- package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +19 -3
- package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail3d/Trail3D.js +31 -4
- package/src/engine/graphics/ecs/trail3d/advance_trail.js +1 -1
- package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
- package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/Water.js +8 -0
- package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.d.ts +5 -5
- package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.d.ts.map +1 -1
- package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +6 -6
- package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/WaterSystem.js +731 -734
- package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
- package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
- package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
- package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
- package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
- package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
- package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
- package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
- package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
- package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts +10 -0
- package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts.map +1 -1
- package/src/engine/graphics3/trail/trail_tube_write_geometry.js +13 -1
- package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
- package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
- package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
- package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
- package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
- package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
- package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +2 -2
- package/src/engine/physics/cloth/ecs/cloth_geodesic.js +2 -2
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/playground/probe_clipmap/README.md +1 -0
- package/src/shade/playground/probe_clipmap/index.html +5 -0
- package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
- package/src/shade/playground/probe_clipmap/main.js +16 -2
- package/src/shade/playground/vgeo_scene/README.md +1 -1
- package/src/shade/playground/water_refraction/README.md +5 -6
- package/src/shade/playground/water_refraction/index.html +1 -1
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +7 -5
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts +4 -6
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.js +34 -36
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts +1 -1
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts.map +1 -1
- package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.js +162 -163
- package/src/shade/renderer/atmosphere/compute_mie_absorption.d.ts +1 -1
- package/src/shade/renderer/atmosphere/compute_mie_absorption.js +1 -1
- package/src/shade/renderer/atmosphere/hillaire/ATMOSPHERE_EARTH.js +1 -1
- package/src/shade/renderer/atmosphere/hillaire/ATMOSPHERE_PARAMETERS_STRUCT.js +1 -1
- package/src/shade/renderer/atmosphere/shader_multiscatter_lut.js +164 -164
- package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.js +1 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
- package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +4 -4
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +4 -4
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +2 -1
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +18 -1
- package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.js +2 -2
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_histogram.d.ts +1 -1
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_histogram.js +1 -1
- package/src/shade/renderer/geometry/sdf/chunk_blas_query_band_sdf.d.ts +4 -5
- package/src/shade/renderer/geometry/sdf/chunk_blas_query_band_sdf.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/chunk_blas_query_band_sdf.js +6 -7
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +2 -8
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +5 -5
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +10 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +12 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +22 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +4 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +50 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +6 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +7 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.d.ts +13 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.js +13 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +17 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +20 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resampled.d.ts +18 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resampled.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resampled.js +42 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +5 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +4 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +13 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.d.ts +52 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.js +250 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
- package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
- package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
- package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
- package/src/shade/renderer/light/environment/environment_level_1_blur_plan.d.ts +39 -0
- package/src/shade/renderer/light/environment/environment_level_1_blur_plan.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/environment_level_1_blur_plan.js +119 -0
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts +15 -7
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/execute_filter_environment_map.js +66 -83
- package/src/shade/renderer/light/environment/graph_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/graph_filter_environment_map.js +15 -6
- package/src/shade/renderer/light/environment/shader_blur_environment_map.d.ts +3 -0
- package/src/shade/renderer/light/environment/shader_blur_environment_map.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/shader_blur_environment_map.js +111 -0
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_blurred.d.ts +3 -0
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_blurred.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_blurred.js +128 -0
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.js +0 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.d.ts +7 -0
- package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.js +11 -0
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -3
- package/src/shade/renderer/postprocess/nss/NSS.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/NSS.js +1 -3
- package/src/shade/renderer/postprocess/nss/NSS_NETWORK_SCHEMA.d.ts +5 -6
- package/src/shade/renderer/postprocess/nss/NSS_NETWORK_SCHEMA.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/NSS_NETWORK_SCHEMA.js +9 -10
- package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.js +48 -49
- package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.js +12 -16
- package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.js +246 -246
- package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts +1 -2
- package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.js +34 -35
- package/src/shade/renderer/shader/chunk/atmosphere/C_MIE_SCATTERING_DECLARATION.d.ts +2 -2
- package/src/shade/renderer/shader/chunk/atmosphere/C_MIE_SCATTERING_DECLARATION.js +2 -2
- package/src/shade/renderer/shader/chunk/atmosphere/chunk_compute_extinction.js +1 -1
- package/src/shade/renderer/shader/chunk/atmosphere/hillaire/DENSITY_PROFILE_LAYER_STRUCT.d.ts +1 -1
- package/src/shade/renderer/shader/chunk/atmosphere/hillaire/DENSITY_PROFILE_LAYER_STRUCT.js +1 -1
- package/src/shade/renderer/shader/chunk/brdf/fresnel/chunk_F_Schlick.d.ts +3 -3
- package/src/shade/renderer/shader/chunk/brdf/fresnel/chunk_F_Schlick.js +3 -3
- package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.d.ts +9 -10
- package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.js +9 -10
- package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.d.ts +4 -4
- package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.js +5 -5
- package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.d.ts +1 -2
- package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.js +1 -2
- package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec2.d.ts +14 -1
- package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec2.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec2.js +19 -6
- package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec3.d.ts +10 -1
- package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec3.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec3.js +14 -6
- package/src/shade/renderer/shader/chunk/random/murmur/chunk_murmur3_vec3u.d.ts +1 -1
- package/src/shade/renderer/shader/chunk/random/murmur/chunk_murmur3_vec3u.js +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_DYNAMIC_LOD_BIAS.d.ts +2 -3
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_DYNAMIC_LOD_BIAS.d.ts.map +1 -1
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_DYNAMIC_LOD_BIAS.js +7 -8
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_LOAD_FACTOR.d.ts +1 -1
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_LOAD_FACTOR.js +12 -12
- package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts +2 -2
- package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts.map +1 -1
- package/src/shade/renderer/shadow/vsm/VSMPageManager.js +3 -4
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
- package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
- package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
- package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +22 -13
- package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water_avboit.js +7 -7
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
- package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts +0 -19
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts.map +1 -1
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.js +2 -52
- package/editor/REWORK_PLAN_2026_08.md +0 -692
- package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
- package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
- package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
- package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
- package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
- package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
- package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
- package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
- package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
- package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
- package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
- package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
- package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
- package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
- package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
- package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
- package/src/REVIEW_2026_08_06/adv-core.md +0 -511
- package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
- package/src/REVIEW_2026_08_06/adv-view.md +0 -446
- package/src/REVIEW_2026_08_06/api-core.md +0 -296
- package/src/REVIEW_2026_08_06/api-engine.md +0 -195
- package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
- package/src/REVIEW_2026_08_06/core-binary.md +0 -348
- package/src/REVIEW_2026_08_06/core-collection.md +0 -376
- package/src/REVIEW_2026_08_06/core-math.md +0 -221
- package/src/REVIEW_2026_08_06/core-process.md +0 -266
- package/src/REVIEW_2026_08_06/core-science.md +0 -223
- package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
- package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
- package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
- package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
- package/src/REVIEW_2026_08_06/engine-input.md +0 -197
- package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
- package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
- package/src/REVIEW_2026_08_06/generation.md +0 -176
- package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
- package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
- package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
- package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
- package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
- package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
- package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
- package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
- package/src/REVIEW_2026_08_06/view.md +0 -667
- package/src/REVIEW_2026_08_06.md +0 -610
- package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
- package/src/core/bvh2/bvh3/NOTES.md +0 -2
- package/src/core/bvh8/NOTES.md +0 -63
- package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
- package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
- package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
- package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
- package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
- package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
- package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
- package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
- package/src/core/geom/3d/gjk/NOTES.md +0 -8
- package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
- package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
- package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
- package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
- package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
- package/src/engine/REVIEW_2026_07_03.md +0 -211
- package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
- package/src/engine/control/first-person/DESIGN.md +0 -658
- package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
- package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
- package/src/engine/control/first-person/TODO.md +0 -160
- package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
- package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
- package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
- package/src/engine/ecs/ik/PLAN.md +0 -179
- package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
- package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
- package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
- package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
- package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
- package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
- package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
- package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
- package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
- package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
- package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
- package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
- package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
- package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
- package/src/engine/network/CONGESTION_CONTROL.md +0 -87
- package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
- package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
- package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
- package/src/engine/physics/cloth/PLAN.md +0 -3056
- package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
- package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
- package/src/engine/physics/fluid/solver/NOTES.md +0 -46
- package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
- package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
- package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
- package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
- package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
- package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
- package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
- package/src/format/image/avif/DECISIONS.md +0 -545
- package/src/format/image/jpeg/NOTES.md +0 -3
- package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
- package/src/generation/COORDINATES.md +0 -54
- package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
- package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
- package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
- package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
- package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
- package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
- package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
- package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
- package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
- package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
- package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
- package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
- package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
- package/src/shade/RENDERER_CONTRACT.md +0 -697
- package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
- package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
- package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
- package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
- package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
- package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
- package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
- package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
- package/src/shade/renderer/NOTES.md +0 -78
- package/src/shade/renderer/PLAN.md +0 -8
- package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
- package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
- package/src/shade/renderer/atmosphere/NOTES.md +0 -6
- package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
- package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
- package/src/shade/renderer/camera/orbital/README.md +0 -81
- package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
- package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/index.js +0 -9
- package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
- package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
- package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
- package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
- package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
- package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
- package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -483
- package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
- package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
- package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
- package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
- package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
- package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -536
- package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4225
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
- package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
- package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
- package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
- package/src/shade/renderer/hiz/NOTES.md +0 -3
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
- package/src/shade/renderer/light/cluster/NOTES.md +0 -11
- package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
- package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.d.ts +0 -13
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.d.ts.map +0 -1
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.js +0 -198
- package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
- package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
- package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
- package/src/shade/renderer/particles/DESIGN.md +0 -1011
- package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -283
- package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
- package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
- package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
- package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
- package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
- package/src/shade/renderer/postprocess/nss/NOTES.md +0 -339
- package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
- package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
- package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
- package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
- package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
- package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
- package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
- package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
- package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
- package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
- package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -394
- package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -160
- package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
- package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
- package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
- package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
- package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
- package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
- package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
- package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
- package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
- package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -932
- package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
- package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
- package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
- package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
- package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
- package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
- package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
- package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
- package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
- package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
- package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -4
- package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
- package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
- package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
- package/src/shade/wgsl/NOTES.md +0 -4
- package/src/view/elements/progress/segmented/segment_frame_transform.d.ts +0 -15
- package/src/view/elements/progress/segmented/segment_frame_transform.d.ts.map +0 -1
- package/src/view/elements/progress/segmented/segment_frame_transform.js +0 -69
|
@@ -1,521 +0,0 @@
|
|
|
1
|
-
# Tree LODs at a geometric error, with baked cluster cards (2026-10-27)
|
|
2
|
-
|
|
3
|
-
Follows `REAL_TIME_TREES_BRIEF_2026_10_27.md`. The goal: every preset under `TREE_RENDER_COST_CEILING` at every LOD,
|
|
4
|
-
with LODs that look like the tree, because each one is the tree drawn to an error rather than the finest mesh
|
|
5
|
-
decimated.
|
|
6
|
-
|
|
7
|
-
## What is wrong today
|
|
8
|
-
|
|
9
|
-
- **LODs decimate the finest mesh.** `TreeLODConfig.createDefaultChain` is an authored chain: radial and longitudinal
|
|
10
|
-
scales, a branch-level cut, a radius cut, and a kept fraction of cards scaled up by `keep^-eta`.
|
|
11
|
-
- **The foliage ignores the bark's cuts.** `tree_mesh_build_foliage` decimates cards by golden rank only. It never
|
|
12
|
-
reads `carriers`, `max_branch_level` or `min_branch_radius` (`tree_mesh_build_foliage.js:65-84`).
|
|
13
|
-
- **So coarse LODs show floating leaves.** A coarse LOD keeps single-leaf cards, at their LOD0 positions and LOD0 skin
|
|
14
|
-
joints, around wood that is no longer drawn.
|
|
15
|
-
- **Every LOD carries every joint.** `TreeLODAsset.scene_bundle` builds one `Skin` with the full joint set for every
|
|
16
|
-
LOD. The rig, `skin_info` and `wind_rig` are shared (`generate_tree.js:97-100`).
|
|
17
|
-
- **Joints cost per instance.**
|
|
18
|
-
- Each wind joint is an ECS entity with a GPU transform row and a spring-damper step (`FoliageWindSystem`,
|
|
19
|
-
`shader_foliage_wind_apply.js`).
|
|
20
|
-
- Each skinned instance gets its own geometry clone, re-skinned every frame (`GPUMeshSkinningContext`).
|
|
21
|
-
- So the willow's 40,620 joints cost as much per tree as its triangles do.
|
|
22
|
-
- **Nothing switches LODs at runtime.** `place_tree` takes a fixed `opts.lod` (`place_tree.js:56-66`), and nothing in
|
|
23
|
-
shade or engine selects mesh LODs by screen size.
|
|
24
|
-
|
|
25
|
-
## Measured basis
|
|
26
|
-
|
|
27
|
-
`H:/tmp/probe_error_lod_dp.mjs` on master (seed 1337). Each LOD at error `eps` is estimated as:
|
|
28
|
-
- **Wood:** meshed only where its diameter is at least `eps`.
|
|
29
|
-
- **Spines:** simplified to `eps` (Douglas-Peucker on position and radius).
|
|
30
|
-
- **Rings:** as many sides as keep the chord's sagitta within `eps`.
|
|
31
|
-
- **Cards:** everything below a cut is one 4-triangle card.
|
|
32
|
-
|
|
33
|
-
Triangles per m² of side area; the LOD0 ceiling is 752.6:
|
|
34
|
-
|
|
35
|
-
| preset | eps 1 cm | eps 2 cm | eps 4 cm | eps 8 cm | cuts at 2 cm (median leaves) |
|
|
36
|
-
| :--- | ---: | ---: | ---: | ---: | ---: |
|
|
37
|
-
| oak | 457 | 226 | 150 | 97 | 797 (21) |
|
|
38
|
-
| pine | 2,053 | 661 | 51 | 10 | 4,691 (1) |
|
|
39
|
-
| birch | 3,175 | 856 | 247 | 81 | 3,275 (6) |
|
|
40
|
-
| willow | 3,984 | 1,181 | 340 | 133 | 6,823 (10) |
|
|
41
|
-
| maple | 866 | 439 | 260 | 173 | 2,007 (4) |
|
|
42
|
-
| spruce | 3,812 | 683 | 270 | 80 | 2,389 (16) |
|
|
43
|
-
| shrub | 1,854 | 835 | 279 | 78 | 1,128 (8) |
|
|
44
|
-
|
|
45
|
-
- **Wood stops being the cost once eps reaches 2 cm.** The twig layer, which is most of today's bark, falls under the
|
|
46
|
-
error.
|
|
47
|
-
- **Cuts are the next cost, and they fall slowly.** Twigs grow straight off the boughs, so every twig base is its own
|
|
48
|
-
cut, holding a median of 1 to 21 leaves. On the willow at 2 cm, cards are 27k of its 43k triangles.
|
|
49
|
-
|
|
50
|
-
## Design
|
|
51
|
-
|
|
52
|
-
1. **Each LOD is the tree at an error `eps_k`, in metres.**
|
|
53
|
-
- Wood is meshed where its diameter is at least `eps_k`. Thinner wood is not visible as a tube at that error.
|
|
54
|
-
- A spine keeps the points it needs to stay within `eps_k` in position and radius.
|
|
55
|
-
- A ring has as many sides as keep its chord within `eps_k`. This replaces `radial_segments_min/max`,
|
|
56
|
-
`radial_scale`, `longitudinal_scale`, `max_branch_level` and `min_branch_radius`.
|
|
57
|
-
- Coarser LODs double the error, `eps_k = eps_0 * 2^k`. Each switch then happens at twice the distance, at the same
|
|
58
|
-
error on screen.
|
|
59
|
-
2. **What the wood leaves out becomes cluster cards.**
|
|
60
|
-
- A cut gathers every twig and leaf the simulation grew below it.
|
|
61
|
-
- Each cluster is drawn orthographically from its card's facing, at a texel no coarser than `eps_k / 2`, into albedo,
|
|
62
|
-
alpha, normal and AO tiles.
|
|
63
|
-
- The leaves inside the tiles are the same leaf tiles drawn today (`foliage_tile_raster`); only the card count
|
|
64
|
-
changes, following the wood instead of the leaves.
|
|
65
|
-
- One card per leaf goes (F2).
|
|
66
|
-
3. **A few baked clusters stand for all of them.**
|
|
67
|
-
- The simulation's clusters are siblings grown by the same rules, so each cut uses the nearest of a few baked
|
|
68
|
-
representatives, with the cut's transform and scale.
|
|
69
|
-
- Two clusters are interchangeable when they differ by less than the error.
|
|
70
|
-
4. **The rig runs on each LOD's wood.**
|
|
71
|
-
- `tree_skeleton_assign_skin_joints` runs over the wood each LOD meshes.
|
|
72
|
-
- A cluster card takes its cut's joint and that joint's parent, two influences.
|
|
73
|
-
- No seat meets more than four joints, because twigs on twigs' first segments are no longer meshed.
|
|
74
|
-
5. **The gate goes green.** A spec holds every preset's every LOD under `TREE_RENDER_COST_CEILING`, red before this
|
|
75
|
-
lands and green after.
|
|
76
|
-
|
|
77
|
-
## Reuse map
|
|
78
|
-
|
|
79
|
-
| job | existing code | how it is used |
|
|
80
|
-
| :--- | :--- | :--- |
|
|
81
|
-
| cost measure and ceiling | `analysis/tree_render_cost.js` | the gate, unchanged |
|
|
82
|
-
| wood mesher | `mesh/tree_mesh_build_bark.js` (rings, RMF frames, collars, knots, UVs, skin rings) | kept; only its culling and sample counts move to `eps` |
|
|
83
|
-
| ring skin weights | `mesh/interpolate_ring_skin_weights4.js` | unchanged |
|
|
84
|
-
| leaf drawing | `material/foliage_tile.js` `foliage_tile_raster`, `polygon2_rasterize_coverage`, `material/make_foliage_material.js` (colour model, normal from height, ORM) | the leaves a cluster is drawn from |
|
|
85
|
-
| orthographic CPU raster | `analysis/crown_opacity_measure.js` private `raster_geometry` (edge functions, top-left rule, barycentric UV, bilinear atlas alpha) | extracted to a shared rasterizer, extended to albedo, normal and depth; the crown measure uses the same one |
|
|
86
|
-
| image filters | `engine/graphics/texture/sampler/` (`Sampler2D`, `sampler2d_copy_with_margins`, chamfer distance, `sampler2d_scale_down_*`), `engine/graphics/sh3/grid_dilate_average.js` | gutters, dilation, mips of the cluster tiles |
|
|
87
|
-
| atlas packing | `core/geom/packing/max-rect/MaxRectanglesPacker.js`, `material/compute_foliage_variant_atlas_layout.js` | cluster tiles beside the leaf tiles |
|
|
88
|
-
| card outlines | `material/foliage_atlas_cutout.js` (`foliage_atlas_cutout_fit_tile`: hull fitted to alpha, 6 vertices) and the `CutoutHull` card | cluster cards cut to their tile's alpha, so less overdraw |
|
|
89
|
-
| card geometry and wind data | `mesh/tree_mesh_build_foliage.js` card writers (`CutoutHull`, `CrossCard`, `FoldedVCard`), UV1 flutter and phase, canopy AO | the cluster cards |
|
|
90
|
-
| joint derivation | `skeleton/tree_skeleton_assign_skin_joints.js` (tolerance walk), `animation/build_tree_wind_rig.js` | run per LOD |
|
|
91
|
-
| per-LOD assets | `asset/TreeLODAsset.js` (lazy builders, meshlets, `scene_bundle`, `prefab`) | one skin and one rig per LOD |
|
|
92
|
-
| measures of the look | `analysis/tree_crown_opacity.js` (FIA density and transparency), `analysis/foliage_measure_leaf_area.js` | each LOD's crown is held to its LOD0 density and leaf area |
|
|
93
|
-
|
|
94
|
-
**New code, none of which exists in the engine:**
|
|
95
|
-
- **A polyline simplifier** (Douglas-Peucker over position and radius) in `core/geom/3d`.
|
|
96
|
-
- **The cluster cut and its representatives:**
|
|
97
|
-
- a descriptor per cut;
|
|
98
|
-
- a greedy cover that picks representatives so every cut is within the error of one;
|
|
99
|
-
- the placement transform.
|
|
100
|
-
- `geometry_deduplicate` matches exact congruence and `graph_k_means_cluster` works on graph distances, so neither
|
|
101
|
-
fits.
|
|
102
|
-
- **The cluster bake:** the shared rasterizer writing albedo, normal, depth and AO into tiles.
|
|
103
|
-
|
|
104
|
-
## Forks
|
|
105
|
-
|
|
106
|
-
- **F1. Where a cluster begins.**
|
|
107
|
-
- **(a) Every cut is a cluster.** Simple, but the cluster count falls slowly: the willow has 6,823 at 2 cm.
|
|
108
|
-
- **(b) Cuts along a meshed branch share a card per stretch of it.** The stretch is as long as the cards a cluster
|
|
109
|
-
tile can hold at the LOD's texel. The card count then follows the meshed wood's length over `eps_k`, the way
|
|
110
|
-
SpeedTree's 150-400 cards sit along the boughs.
|
|
111
|
-
- Recommended: (b). It is the only one that keeps falling as `eps` grows.
|
|
112
|
-
- **F2. LOD0's error `eps_0`.**
|
|
113
|
-
- **(a) Each tree's smallest error that fits the ceiling,** found by the generator. The measured values are about
|
|
114
|
-
1-2 cm.
|
|
115
|
-
- **(b) One chosen error for every species.**
|
|
116
|
-
- Recommended: (a). Alex accepted a metric to tune against, and it sizes small and large trees alike.
|
|
117
|
-
- **F3. The rig's tolerance at each LOD.**
|
|
118
|
-
- **(a) `deflection_tolerance` becomes `max(deflection_tolerance, eps_k)`.** A sway error smaller than the shape error
|
|
119
|
-
cannot be seen.
|
|
120
|
-
- **(b) It stays fixed.** Coarse LODs keep every joint their wood still holds.
|
|
121
|
-
- Recommended: (a).
|
|
122
|
-
- **F4. Joints across LODs.**
|
|
123
|
-
- **(a) A coarser LOD's joints are a subset of the finer one's,** chosen by the same walk at the larger tolerance from
|
|
124
|
-
the finer LOD's joints. A switch then keeps the wind state of every joint both LODs share.
|
|
125
|
-
- **(b) Each LOD derives its own.**
|
|
126
|
-
- Recommended: (a). The cost is a constrained walk, about the same code.
|
|
127
|
-
- **F5. Runtime LOD switching.** It is not in this design and no system does it. Without it, a scene uses whichever
|
|
128
|
-
LOD `place_tree` was given.
|
|
129
|
-
- Recommended: its own brief after this lands. Shade has screen-space-error selection only in virtual geometry, which
|
|
130
|
-
is static-only.
|
|
131
|
-
|
|
132
|
-
## Stages, each measured against the cost gate and the look
|
|
133
|
-
|
|
134
|
-
1. **L1: wood at an error.**
|
|
135
|
-
- The bark mesher takes `eps` in place of the authored chain.
|
|
136
|
-
- Reports triangles and joints per LOD, plus LOD0's crown density and leaf area against today's.
|
|
137
|
-
2. **L2: cluster cards.**
|
|
138
|
-
- The cut (F1), the bake, the representatives, the cards.
|
|
139
|
-
- Each LOD's FIA crown density stays within the band at LOD0 (`tree_crown_opacity`), and its leaf area drawn stays
|
|
140
|
-
that of LOD0.
|
|
141
|
-
3. **L3: the rig per LOD** (F3, F4). Joints per m² under the ceiling.
|
|
142
|
-
4. **L4: the gate spec.** Every preset, every LOD, under `TREE_RENDER_COST_CEILING`, red then green.
|
|
143
|
-
`TreeLODConfig`'s authored fields are removed, a hard break.
|
|
144
|
-
|
|
145
|
-
## Risks
|
|
146
|
-
|
|
147
|
-
- **Distant cluster tiles thin out.** Alpha coverage is not preserved across mips anywhere in the engine. A cluster
|
|
148
|
-
card seen from far away loses leaves as plain box-filtered mips thin its alpha. This is measured in L2 with
|
|
149
|
-
`tree_crown_opacity` at coarser pixel sizes; if it shows, coverage-preserving mips are their own fix.
|
|
150
|
-
- **A flat card shows edge-on.** Cluster cards seen along their plane vanish. Crossed or hull cards per cluster cost
|
|
151
|
-
triangles; L2 measures the side density over all views, which `tree_crown_opacity`'s hemi-octahedral frames already
|
|
152
|
-
give.
|
|
153
|
-
- **Cluster wind.** A card moves rigidly with its cut's joints; the flutter attribute (UV1) still animates it. Twig-level
|
|
154
|
-
sway inside a cluster is gone below the LOD's error by design.
|
|
155
|
-
|
|
156
|
-
## L1: wood at an error (built 2026-10-27)
|
|
157
|
-
|
|
158
|
-
Decisions (Alex: the recommended forks): F1 (b) stretches, F2 (a) `eps_0` from the ceiling, F3 (a) the rig's tolerance
|
|
159
|
-
follows `eps`, F4 (a) nested joints, F5 its own brief later.
|
|
160
|
-
|
|
161
|
-
**Built.** `TreeLODConfig.error` replaces the authored chain's bark fields (hard break, with
|
|
162
|
-
`BranchGeneratorConfig.radial_segments_min/max`). A branch is drawn while it is at least `eps` thick and its parent is
|
|
163
|
-
drawn, to where it thins to `eps`. Rings and sides are planned against the surface the mesher draws, measured all round:
|
|
164
|
-
half the error along the branch (`polyline_simplify_by_error`, new in `core/geom/polyline`), half around each ring,
|
|
165
|
-
checked at every chord's middle too. Ring shape (lobes, flutes, ovalization, collars, knots) is one function the plan
|
|
166
|
-
and the vertices share, bit-identical to before at the old sampling. `eps_0` is 1 cm, chosen, until L2 derives it.
|
|
167
|
-
|
|
168
|
-
**Bark triangles, master against L1** (seed 1337):
|
|
169
|
-
|
|
170
|
-
| preset | LOD0 master | LOD0 1 cm | LOD1 master | LOD1 2 cm | LOD2 master | LOD2 4 cm |
|
|
171
|
-
| :--- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
172
|
-
| oak | 69.7k | 29.1k | 3.6k | 12.8k | 0.8k | 6.0k |
|
|
173
|
-
| pine | 556.7k | 119.5k | 14.8k | 20.3k | 0.2k | 0.6k |
|
|
174
|
-
| birch | 295.9k | 49.5k | 5.0k | 10.5k | 0.5k | 2.9k |
|
|
175
|
-
| willow | 422.5k | 132.4k | 5.8k | 30.4k | 0.6k | 7.6k |
|
|
176
|
-
| maple | 58.9k | 26.9k | 3.0k | 10.7k | 0.7k | 4.7k |
|
|
177
|
-
| spruce | 744.7k | 52.3k | 3.5k | 9.0k | 0.6k | 3.1k |
|
|
178
|
-
| palm | 0.8k | 10.9k | 0.4k | 5.5k | 0.3k | 2.6k |
|
|
179
|
-
| shrub | 46.9k | 8.7k | 1.2k | 2.4k | 0.1k | 0.6k |
|
|
180
|
-
|
|
181
|
-
- LOD0 bark falls 2.2-14x on every woody preset. Coarse LODs carry more than master's, which kept only the boughs
|
|
182
|
-
whatever their thickness; at 4 cm a bough is still drawn. The palm's trunk was 3-4 sides authored; its leaf scars
|
|
183
|
-
and flare need 95 rings of 50 sides at 1 cm.
|
|
184
|
-
- Leaf area at LOD0 is unchanged within 0.3%; side crown density drops by at most 0.02 (the thin wood no longer drawn).
|
|
185
|
-
- Generation: the oak's LOD0 bark takes 137 ms against 82 ms, the pine's 793 ms against 288 ms, the palm's 467 ms
|
|
186
|
-
against 5 ms (measuring every candidate ring against every collar and knot).
|
|
187
|
-
|
|
188
|
-
**Measured for L2.** The cost ceilings at LOD1 and LOD2 came from the authored chain's kept fractions (0.54 and 0.13
|
|
189
|
-
of LOD0's). Doubling `eps` does not meet them: the oak's bark alone at 4 cm is 6.0k triangles against the LOD2
|
|
190
|
-
ceiling's 3.0k for the whole tree. Either each LOD's error is derived from its own ceiling (F2 per level), or the
|
|
191
|
-
ceilings follow the error; L2 decides with the cluster cards' cost in hand.
|
|
192
|
-
|
|
193
|
-
**Mutation test.** 6 of 11 mutants killed. Survivors: drawing a child whose parent is not (no child is thicker than
|
|
194
|
-
its parent, an equivalent mutant on real trees); four times the tolerance around a ring (round wood's chord middles
|
|
195
|
-
still bound it; nothing tests shaped rings' accuracy); keeping every candidate ring, and not keeping the weld rings
|
|
196
|
-
(cost and the weld's fade, which no spec measures); a card held 5% inside its ring pair (nothing exposes where a card
|
|
197
|
-
attaches).
|
|
198
|
-
|
|
199
|
-
## L2 measured before building (2026-10-27)
|
|
200
|
-
|
|
201
|
-
`H:/tmp/probe_clusters.mjs` and `probe_clusters_bc.mjs`, master at 588207065, seed 1337. A cut is a subtree the wood at
|
|
202
|
-
an error leaves undrawn, the leaves on drawn wood, or a drawn branch's undrawn tip. A card is estimated at 6 triangles.
|
|
203
|
-
Density is triangles per m^2 of side area; LOD0's ceiling is 752.6.
|
|
204
|
-
|
|
205
|
-
**F1 (b) as stretches within the error of one plane does not merge.** Douglas-Peucker along each drawn branch, with a
|
|
206
|
-
run's error the distance of its leaves and undrawn twigs from their least-squares plane, keeps almost every cut apart:
|
|
207
|
-
a single cut's twig system is already thicker than the error (the oak at 4 cm: 680 cuts, all of them thicker, 680
|
|
208
|
-
cards). So the stretches come out as one card per cut.
|
|
209
|
-
|
|
210
|
-
**Holding every leaf within the error of its card's plane costs too much.** Splitting each cut until every leaf is that
|
|
211
|
-
close to one plane (a billboard cloud, Decoret et al. 2003) needs 12-16 cm of error to meet LOD0's ceiling:
|
|
212
|
-
|
|
213
|
-
| preset | 4 cm | 8 cm | 16 cm |
|
|
214
|
-
| :--- | ---: | ---: | ---: |
|
|
215
|
-
| oak | 18,837 cards, 3,691/m^2 | 8,573, 1,669 | 1,069, 222 |
|
|
216
|
-
| birch | 35,493, 10,265 | 7,988, 2,324 | 1,275, 372 |
|
|
217
|
-
| spruce | 11,419, 3,630 | 2,745, 879 | 716, 231 |
|
|
218
|
-
|
|
219
|
-
At 16 cm only the trunk and the main boughs are drawn as wood.
|
|
220
|
-
|
|
221
|
-
**One card per cut, judged by what it shows** (its depth not held to the error, as SpeedTree's cluster cards are not):
|
|
222
|
-
|
|
223
|
-
| preset | 1 cm | 2 cm | 3 cm | 4 cm | 6 cm | 8 cm | 16 cm |
|
|
224
|
-
| :--- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
225
|
-
| oak | 1,447 | 730 | | 308 | | 172 | 59 |
|
|
226
|
-
| pine | 3,712 | 1,044 | 290 | 79 | 15 | 15 | 0 |
|
|
227
|
-
| birch | 5,225 | 1,427 | | 408 | | 127 | 15 |
|
|
228
|
-
| willow | 7,204 | 1,946 | 932 | 595 | 356 | 230 | 53 |
|
|
229
|
-
| maple | 2,251 | 1,113 | 629 | 494 | 337 | 292 | 82 |
|
|
230
|
-
| spruce | 7,891 | 1,405 | | 502 | | 146 | 59 |
|
|
231
|
-
| shrub | 3,149 | 1,366 | 626 | 440 | 216 | 118 | 11 |
|
|
232
|
-
|
|
233
|
-
LOD0's ceiling is met at 2-4 cm of error (oak 2, pine 3, maple 3, shrub 3, birch and spruce 3-4, willow 4).
|
|
234
|
-
|
|
235
|
-
**The LOD1 and LOD2 ceilings.** Density falls about 2.3x each time the error doubles, not the 4x that one
|
|
236
|
-
triangle per pixel at each LOD's switching distance would need, so ceilings derived per pixel (LOD1 188, LOD2 47 per
|
|
237
|
-
m^2 with doubling) are not met by wood and cards at any error: far trees are an impostor's job (F5). The ceilings
|
|
238
|
-
measured at 6aff5265e (407.6, 97.0) are met if each LOD's error comes from its own ceiling instead of doubling: about
|
|
239
|
-
3-6 cm at LOD1 and 8-16 cm at LOD2.
|
|
240
|
-
|
|
241
|
-
## L2: cluster cards (built 2026-10-27)
|
|
242
|
-
|
|
243
|
-
Decision (Alex, after the measurements above): one card per cut, its depth not held to the error; each LOD's error
|
|
244
|
-
derived from its own ceiling, the ceilings kept.
|
|
245
|
-
|
|
246
|
-
**Built.**
|
|
247
|
-
- `tree_clusters`: one cluster per cut. A leaf on drawn wood joins its branch's nearest cut; a branch with none
|
|
248
|
-
gathers its leaves into one at their mean place. A cluster hangs from its drawn bark point, skinned as that point.
|
|
249
|
-
- `tree_cluster_cards`: a card in the plane its leaves, twigs and hanging point spread in, facing away from the crown.
|
|
250
|
-
- `tree_cluster_bake`: an orthographic CPU bake at a texel equal to the error, 4x4 samples a texel, back to front in
|
|
251
|
-
linear light, through `tri2_rasterize_barycentric` (extracted from the crown opacity measure's raster, which now
|
|
252
|
-
uses it, bit-identical). Leaves are pressed onto the card; twigs are bark bands. The tiles pack into one atlas per
|
|
253
|
-
LOD, each cut to a 6-vertex hull fitted to its alpha.
|
|
254
|
-
- `tree_lod_errors`: each LOD's error, a half-octave apart from 1 cm, the finest that fits its ceiling.
|
|
255
|
-
- The per-leaf foliage (`tree_mesh_build_foliage`, no LOD) is the reference the bakes draw from; no LOD draws it.
|
|
256
|
-
|
|
257
|
-
**The side area is what the tree grew.** `tree_grown_side_area` (wood nodes and every leaf's card) replaces the
|
|
258
|
-
side area of an LOD's drawn mesh, which shrank as the error grew: the search and the gate disagreed on the palm and
|
|
259
|
-
the fern. `TREE_RENDER_COST_CEILING` is re-derived under it at 6aff5265e: 761.2, 412.3, 96.2 triangles and 16.89
|
|
260
|
-
joints per m^2.
|
|
261
|
-
|
|
262
|
-
**How a card shows its leaves**, oak LOD0 FIA crown density from the side and from below (per-leaf .49/.53):
|
|
263
|
-
|
|
264
|
-
| variant | side | below |
|
|
265
|
-
| :--- | ---: | ---: |
|
|
266
|
-
| one card, leaves projected | .42 | .44 |
|
|
267
|
-
| three cards by leaf orientation | .40 | .51 |
|
|
268
|
-
| three cards, leaves pressed | .42 | .53 |
|
|
269
|
-
| **one card, leaves pressed** (built) | **.47** | **.46** |
|
|
270
|
-
|
|
271
|
-
Pressing turns each leaf about where it attaches until it lies in the card's plane, so a card holds the leaf area
|
|
272
|
-
the tree grew whichever way its leaves face (projected, a leaf turned 60 degrees away covers half). Baked normals
|
|
273
|
-
turned the cards' grazing faces white and were flattened; the vertex canopy AO doubled the tiles' and was dropped.
|
|
274
|
-
|
|
275
|
-
**Each preset, seed 1337**: error, triangles, triangles per m^2 (ceiling 761.2 / 412.3 / 96.2), atlas texels:
|
|
276
|
-
|
|
277
|
-
| preset | LOD0 | LOD1 | LOD2 |
|
|
278
|
-
| :--- | :--- | :--- | :--- |
|
|
279
|
-
| oak | 2.0 cm, 16.6k, 565, 556^2 | 4.0 cm, 8.6k, 293, 316^2 | 11.3 cm, 2.1k, 70, 135^2 |
|
|
280
|
-
| pine | 2.8 cm, 9.5k, 218, 787^2 | 2.8 cm, 9.5k, 218, 787^2 | 4.0 cm, 1.9k, 43, 500^2 |
|
|
281
|
-
| birch | 2.8 cm, 8.6k, 444, 528^2 | 4.0 cm, 4.5k, 233, 335^2 | 8.0 cm, 1.4k, 73, 140^2 |
|
|
282
|
-
| willow | 2.8 cm, 25.8k, 724, 1287^2 | 4.0 cm, 14.2k, 397, 842^2 | 11.3 cm, 2.1k, 60, 210^2 |
|
|
283
|
-
| maple | 2.8 cm, 12.9k, 560, 371^2 | 4.0 cm, 9.1k, 396, 270^2 | 16.0 cm, 1.4k, 59, 82^2 |
|
|
284
|
-
| spruce | 2.8 cm, 8.9k, 502, 459^2 | 4.0 cm, 5.6k, 313, 323^2 | 11.3 cm, 1.1k, 61, 117^2 |
|
|
285
|
-
| palm | 1.0 cm, 11.6k, 525, 1572x1536 | 1.4 cm, 8.0k, 363, 1114x1090 | 5.7 cm, 1.7k, 75, 248x241 |
|
|
286
|
-
| shrub | 2.0 cm, 4.4k, 661, 536^2 | 2.8 cm, 2.1k, 312, 364^2 | 5.7 cm, 0.5k, 77, 156^2 |
|
|
287
|
-
| fern | 1.4 cm, 0.3k, 614, 122^2 | 2.0 cm, 0.1k, 292, 89^2 | 11.3 cm, 0.0k, 49, 11x20 |
|
|
288
|
-
|
|
289
|
-
Every preset fits its ceiling's triangles at every LOD (the gate spec, `tree_render_cost.spec`). The willow was
|
|
290
|
-
640k triangles; its LOD0 is 25.8k. The pine's LOD0 already fits LOD1's ceiling, so the two are one.
|
|
291
|
-
|
|
292
|
-
**The look**, FIA crown density side/below at LOD0, LOD1, LOD2, against the per-leaf foliage:
|
|
293
|
-
|
|
294
|
-
| preset | per-leaf | LOD0 | LOD1 | LOD2 |
|
|
295
|
-
| :--- | :--- | :--- | :--- | :--- |
|
|
296
|
-
| oak | .49/.53 | .47/.46 | .45/.46 | .41/.43 |
|
|
297
|
-
| pine | .41/.39 | .30/.35 | .30/.35 | .27/.32 |
|
|
298
|
-
| birch | .52/.77 | .54/.73 | .53/.70 | .49/.66 |
|
|
299
|
-
| willow | .74/.76 | .71/.72 | .71/.70 | .66/.65 |
|
|
300
|
-
| maple | .46/.47 | .44/.40 | .43/.39 | .38/.32 |
|
|
301
|
-
| spruce | .29/.40 | .24/.39 | .23/.39 | .19/.38 |
|
|
302
|
-
| shrub | .68/.71 | .68/.64 | .67/.62 | .60/.56 |
|
|
303
|
-
| palm | | .68/.40 | .68/.40 | .65/.39 |
|
|
304
|
-
| fern | | .59/.14 | .58/.13 | .45/.39 |
|
|
305
|
-
|
|
306
|
-
Generation is 0.3-9.6 s a tree, its three LODs' bakes 0.1-9.1 s; the error search is 0.4-2.5 s of it.
|
|
307
|
-
|
|
308
|
-
**Mutation test.** 13 of 13 killed, three after specs were added for them: the painter's order (where two twigs
|
|
309
|
-
cross, the tile shows the nearer), a tile's empty edge (filtering never reaches the neighbour), and a leaf on drawn
|
|
310
|
-
wood joining its branch's nearest cut.
|
|
311
|
-
|
|
312
|
-
**Measured open items.**
|
|
313
|
-
- **Texture memory has no gate.** At 10 bytes a texel uncompressed (albedo 4, normal 2, ORM 4), LOD0's atlas is
|
|
314
|
-
24.1 MB for the palm and 16.6 MB for the willow, 3.1 MB for the oak. Its 1 cm error is what the palm's ceiling
|
|
315
|
-
allows; the search floor stops it going finer.
|
|
316
|
-
- **Density falls short on the conifers**: the pine's side density is .30 against .41 per-leaf, the spruce's .24
|
|
317
|
-
against .29. The broadleaves are within .03 from the side at LOD0; from below the oak, maple and shrub
|
|
318
|
-
lose .07.
|
|
319
|
-
- **The fern's LOD2 is one card**, flat, so its density from below rises from .14 to .39.
|
|
320
|
-
- **Joints are far over the ceiling** (willow 1,139, birch 779, oak 149 per m^2 against 16.89): L3.
|
|
321
|
-
|
|
322
|
-
## L3: the rig per LOD (built 2026-10-27)
|
|
323
|
-
|
|
324
|
-
Decisions (Alex): F3 (a) the rig's tolerance follows the error, F4 (a) nested joints.
|
|
325
|
-
|
|
326
|
-
**Built.**
|
|
327
|
-
- `tree_skeleton_assign_skin_joints` takes the wood an LOD draws (`options.rings`): its walk runs only over drawn
|
|
328
|
-
branches and places joints no further out than their bark; what the LOD leaves undrawn rides on the drawn wood it
|
|
329
|
-
hangs from, its drag still counted in the joint that carries it. The tolerance is `max(deflection_tolerance, eps)`.
|
|
330
|
-
- `options.within`, the finer LOD's joints: the coarser walk places a joint only where the finer rig has one, the
|
|
331
|
-
first past where its error passes the tolerance. Walked within its own joints, a rig comes back whole.
|
|
332
|
-
- `tree_lod_plan` (was `tree_lod_errors`) searches each LOD's error against the joint ceiling too, F2 (a) read
|
|
333
|
-
whole: the ceiling is triangles and joints. It returns each LOD's rig with its error; each LOD's builders bind it
|
|
334
|
-
(`tree_skeleton_bind_skin_joints`) before meshing, as the bark and the cluster cards read their skinning from the
|
|
335
|
-
nodes. `TreeAsset.skin_info` stays the rig of all the wood as grown, which the leaves as grown are bound to.
|
|
336
|
-
- The gate spec holds every LOD's joints to the ceiling as well as its triangles.
|
|
337
|
-
|
|
338
|
-
**Joints per m^2** (ceiling 16.89), seed 1337: every joint the wood as grown takes at 1 cm, against each LOD's rig.
|
|
339
|
-
|
|
340
|
-
| preset | wood as grown | LOD0 | LOD1 | LOD2 |
|
|
341
|
-
| :--- | ---: | ---: | ---: | ---: |
|
|
342
|
-
| oak | 4,357, 148.6 | 301, 10.3 | 128, 4.4 | 13, 0.4 |
|
|
343
|
-
| pine | 11,576, 266.8 | 175, 4.0 | 175, 4.0 | 24, 0.6 |
|
|
344
|
-
| birch | 15,018, 778.8 | 207, 10.7 | 84, 4.4 | 25, 1.3 |
|
|
345
|
-
| willow | 40,620, 1,138.6 | 293, 8.2 | 293, 8.2 | 26, 0.7 |
|
|
346
|
-
| maple | 1,180, 51.3 | 127, 5.5 | 79, 3.4 | 1, 0.0 |
|
|
347
|
-
| spruce | 8,130, 456.1 | 198, 11.1 | 103, 5.8 | 12, 0.7 |
|
|
348
|
-
| palm | 65, 2.9 | 65, 2.9 | 64, 2.9 | 31, 1.4 |
|
|
349
|
-
| shrub | 4,119, 620.4 | 72, 10.8 | 72, 10.8 | 15, 2.3 |
|
|
350
|
-
| fern | 24, 56.4 | 4, 9.4 | 4, 9.4 | 1, 2.4 |
|
|
351
|
-
|
|
352
|
-
Every preset fits the whole ceiling at every LOD. Rigging the drawn wood at the error is what cuts the joints, 10-60x
|
|
353
|
-
on the woody presets; nesting costs little (nested in a 2.8 cm LOD0, the willow's 4 cm rig took 267 joints, free 293).
|
|
354
|
-
|
|
355
|
-
**Three presets' LOD0 errors rose for their joints.** At the error their triangles allowed, the willow's rig was 20.3
|
|
356
|
-
joints per m^2 (2.8 cm), the shrub's 29.5 (2 cm), the fern's 21.2 (1.4 cm). Their LOD0 errors are now 4 cm, 2.8 cm
|
|
357
|
-
and 2 cm: the willow's LOD0 is 14.2k triangles against 25.8k, its FIA crown density .71/.70 against .71/.72; the
|
|
358
|
-
shrub's .67/.62 against .68/.64; the fern's .58/.13 against .59/.14.
|
|
359
|
-
|
|
360
|
-
**Mutation test.** 13 of 13 killed: the walk over undrawn wood, joints past the drawn bark, `within` ignored, a bind
|
|
361
|
-
without pivots, the species' tolerance kept, joints left out of the search, LODs not nested, each LOD's wind rig taken
|
|
362
|
-
from the wood as grown, the cost counting the wood as grown's joints, the bark or the cards built on whatever rig is
|
|
363
|
-
bound (the cards' after the spec built every LOD's cards before any bark), and a search that never stops when nothing
|
|
364
|
-
is drawn (it hangs: pinned by a tree that fits no ceiling at any error, which is drawn without wood).
|
|
365
|
-
|
|
366
|
-
**Measured open items.**
|
|
367
|
-
- **LOD0 and LOD1 are one** for the pine, the willow, the shrub and the fern: the finest error that fits LOD0's
|
|
368
|
-
ceiling already fits LOD1's, so the chain draws the same tree twice.
|
|
369
|
-
- **Texture memory has no gate** (L2): the palm's LOD0 atlas is 24.1 MB uncompressed; the willow's fell to 7.1 MB
|
|
370
|
-
with its error.
|
|
371
|
-
- Generation is 0.3-8.1 s a tree, its three LODs' builds 0.0-7.4 s.
|
|
372
|
-
|
|
373
|
-
L4 (the gate green) is met: every preset, every LOD, triangles and joints. F5, runtime LOD switching, is its own brief.
|
|
374
|
-
|
|
375
|
-
## Representative cluster tiles (built 2026-10-28)
|
|
376
|
-
|
|
377
|
-
**What was wrong.** L2 baked one tile per cut at a texel equal to the LOD's error, to fit 600-1,100 tiles per LOD into
|
|
378
|
-
memory. An oak leaf, 12.2 cm, was six texels long at LOD0: a blob (Alex's screenshot of the oak at LOD0). The design's
|
|
379
|
-
point 3, a few baked clusters standing for all of them, had been dropped.
|
|
380
|
-
|
|
381
|
-
Decisions (Alex): a few tiles per tree shared by all its LODs, the texel from the leaf, every cut matched to the
|
|
382
|
-
nearest and placed at its own size and turn, the count from a texture-memory ceiling.
|
|
383
|
-
|
|
384
|
-
**Built.**
|
|
385
|
-
- **The leaf's texel** (`FoliageTileLayout.cluster_texel`): the outline's finest feature four texels across, its margin's
|
|
386
|
-
teeth aside (`LeafGeometry.outline`); a needle two across its width, as a stem is. The leaf tile's own texel, which
|
|
387
|
-
draws the teeth, was 10-100x too fine: one oak cut at it is 0.5 MB, one willow cut 56 MB.
|
|
388
|
-
Oak 1.41 mm, shrub 1.20, willow 3.91, maple 8.50, birch 9.38, pine 0.80, spruce 0.50, palm 49.6, fern 25.5.
|
|
389
|
-
- **Coarser LODs** are seen no nearer than where the LOD before is drawn to a pixel, so a representative taken from a
|
|
390
|
-
coarser LOD's cut is baked at that LOD's error, or the leaf's texel if finer; a cut uses only representatives at its
|
|
391
|
-
LOD's texel or finer.
|
|
392
|
-
- **The texture ceiling**, `TREE_RENDER_COST_CEILING.texture_density`: 240,667 bytes per m^2, the shrub's leaf atlas
|
|
393
|
-
at 6aff5265e (every preset's was 640 KiB, so per m^2 the densest is the smallest tree but the fern), derived as the
|
|
394
|
-
other ceilings are. The gate spec holds every preset to it.
|
|
395
|
-
- **How many.** The ceiling alone gave 133 tiles to the birch and 349 to the maple, whose leaves' texels are coarse:
|
|
396
|
-
memory cannot stop variety the eye cannot tell. So the count is the fewest tiles that draw every cut at a size the
|
|
397
|
-
tree's own leaves grow to: a cut magnifies its representative's leaves by their size ratio, and the tree's leaves
|
|
398
|
-
span 0.84-1.16 of their median (10th to 90th percentile of `attachments.scales`), so within that a magnified leaf is
|
|
399
|
-
one the tree grows. Greedy set cover, within the ceiling; among the representatives that draw a cut so, it takes the
|
|
400
|
-
least unlike (leaf coverage, where it hangs). Holding coverage and hang to the leaf spread too left half the oak's
|
|
401
|
-
cuts unmatched at 48 tiles: cut shapes vary far more than leaves.
|
|
402
|
-
- **Placement.** A cut draws its representative on its own plane, as large as it draws (its leaves' cards and its
|
|
403
|
-
twigs' bands: sized by its extent instead, the shrub's LOD0 crown density fell from .67/.62 to .55/.45), hanging
|
|
404
|
-
where it hangs, turned so each runs out from where it hangs the same way.
|
|
405
|
-
- **Pressing per card.** A leaf on cuts of two LODs was pressed twice in place, onto the second card from the first:
|
|
406
|
-
the spruce's atlas came out 16% over its budget. Every card now presses its own copy.
|
|
407
|
-
|
|
408
|
-
**Each preset, seed 1337:** tiles (from LOD0/1/2), the magnification at LOD0 (10th/50th/90th percentile), the atlas.
|
|
409
|
-
|
|
410
|
-
| preset | tiles | LOD0 magnification | atlas | KiB/m^2 (ceiling 235) |
|
|
411
|
-
| :--- | :--- | :--- | ---: | ---: |
|
|
412
|
-
| oak | 11 (8/2/1) | 0.88/1.00/1.12 | 6.11 MiB | 213 |
|
|
413
|
-
| willow | 16 (12/0/4) | 0.89/1.00/1.11 | 5.41 MiB | 155 |
|
|
414
|
-
| birch | 17 (13/1/3) | 0.87/0.99/1.12 | 0.45 MiB | 24 |
|
|
415
|
-
| maple | 15 (10/1/4) | 0.92/1.00/1.10 | 0.29 MiB | 13 |
|
|
416
|
-
| pine | 19 (9/6/4) | 0.87/1.04/1.67 | 9.95 MiB | 235 |
|
|
417
|
-
| spruce | 17 (1/15/1) | 0.44/1.00/2.36 | 4.09 MiB | 235 |
|
|
418
|
-
| shrub | 11 (3/7/1) | 0.90/1.93/3.09 | 1.36 MiB | 210 |
|
|
419
|
-
| palm | 1 (1/0/0) | 0.97/1.07/1.14 | 0.05 MiB | 2 |
|
|
420
|
-
| fern | 3 (2/0/1) | 0.87/1.12/1.23 | 0.02 MiB | 56 |
|
|
421
|
-
|
|
422
|
-
The oak's LOD0 leaves read as lobed oak leaves, the willow's as lanceolate ones, the maple's as palmate ones
|
|
423
|
-
(screenshots at the playground's closest zoom). Triangles and joints are unchanged; the atlas and its LOD0 cards are
|
|
424
|
-
built in 0.0-3.2 s.
|
|
425
|
-
|
|
426
|
-
**The look**, FIA crown density side/below, against one tile per cut (L3):
|
|
427
|
-
|
|
428
|
-
| preset | LOD0 | LOD1 | LOD2 | L3 LOD0 / LOD2 |
|
|
429
|
-
| :--- | :--- | :--- | :--- | :--- |
|
|
430
|
-
| oak | .46/.45 | .45/.45 | .42/.42 | .47/.46 / .41/.43 |
|
|
431
|
-
| willow | .69/.67 | .69/.67 | .65/.63 | .71/.70 / .66/.65 |
|
|
432
|
-
| birch | .52/.74 | .53/.66 | .53/.68 | .54/.73 / .49/.66 |
|
|
433
|
-
| maple | .44/.41 | .43/.39 | .40/.39 | .44/.40 / .38/.32 |
|
|
434
|
-
| pine | .27/.34 | .24/.30 | .28/.36 | .30/.35 / .27/.32 |
|
|
435
|
-
| spruce | .25/.38 | .24/.39 | .23/.43 | .24/.39 / .19/.38 |
|
|
436
|
-
| shrub | .68/.57 | .59/.57 | .49/.43 | .67/.62 / .60/.56 |
|
|
437
|
-
| palm | .65/.37 | .65/.37 | .68/.55 | .68/.40 / .65/.39 |
|
|
438
|
-
| fern | .61/.12 | .61/.12 | .54/.45 | .58/.13 / .45/.39 |
|
|
439
|
-
|
|
440
|
-
**Measured open items.**
|
|
441
|
-
- **The shrub's coarser LODs lose density**: LOD1 .59/.57 and LOD2 .49/.43 against .67/.62 and .60/.56. Its LOD1 is
|
|
442
|
-
drawn to LOD0's error, so its representatives are baked at that error (2.8 cm), coarse against its 9 cm leaves.
|
|
443
|
-
- **The texture ceiling stops the cover first** on the shrub and the conifers, whose cuts at the leaf's texel cost
|
|
444
|
-
more than their budgets: one median shrub cut (54 cm at 1.2 mm) is 2 MB against its 1.4 MB. Their LOD0 cuts are
|
|
445
|
-
magnified past the leaf spread, the shrub's 1.93x at the median and 3.09x at the 90th percentile, the spruce's up
|
|
446
|
-
to 2.36x (one LOD0 tile), the pine's up to 1.67x. The pine's LOD1 loses .06 of density.
|
|
447
|
-
- **Birch twigs are drawn in the bark's colour**, white (`bark_material.primary_color`), since L2.
|
|
448
|
-
- **The palm's leaf `finest` skips its terminal leaflet** (`leaf_geometry`, compound leaves): its outline, which counts
|
|
449
|
-
it, is finer than its finest feature.
|
|
450
|
-
|
|
451
|
-
## The palm's cluster cards (2026-10-28)
|
|
452
|
-
|
|
453
|
-
**What was wrong** (Alex's screenshots of the palm at LOD0): blurred fronds with ragged holes, the cards standing
|
|
454
|
-
upright.
|
|
455
|
-
|
|
456
|
-
- **Upright cards.** A card's plane was fitted to where its leaves attach, its twigs' middles and where it hangs. A
|
|
457
|
-
palm's leaves (each a 1.7 m compound leaf, 9-14 to a frond) attach along a rachis that arches in a vertical plane, so
|
|
458
|
-
every frond's card stood in that plane: 43-90 degrees from horizontal. The crown seen from below was .37 dense
|
|
459
|
-
against .70 drawn leaf by leaf; the fern's .12 against .65. The plane is now fitted to what the card draws, its
|
|
460
|
-
leaves' cards and its twigs' bands each by its area: the palm's cards are 9-89 degrees from horizontal, and its crown
|
|
461
|
-
.59/.69 from the side and below against .62/.70 leaf by leaf (the fern .42/.63 against .47/.65).
|
|
462
|
-
- **Blur.** The legible texel of a compound leaf is its leaflets' outline, the 20 cm leaflet four texels across: 49.6 mm,
|
|
463
|
-
a frond 77 x 65 texels, though the palm spent 0.05 of its 5.1 MiB budget. LOD0 is now drawn at the finest texel the
|
|
464
|
-
ceiling affords for its whole cover: the leaf material's own (`FoliageTileLayout.texel`, the palm's 13.2 mm),
|
|
465
|
-
coarsened by halves while the cover does not fit, never past the legible texel.
|
|
466
|
-
- **Holes.** A frond's tile is its compound leaves pressed onto one plane; the notches between their leaflets show
|
|
467
|
-
through, and at 49.6 mm were ragged blotches. At 13.2 mm they are the notches.
|
|
468
|
-
|
|
469
|
-
**LOD0 texels now:** maple 2.07 mm (was 8.50), birch 4.88 (9.38), palm 13.2 (49.6), fern 13.9 (25.5); the oak's
|
|
470
|
-
1.41, the willow's 3.91, the shrub's 1.20 and the conifers' are where the ceiling held them.
|
|
471
|
-
|
|
472
|
-
**The look**, FIA crown density side/below, against every leaf drawn as its own card:
|
|
473
|
-
|
|
474
|
-
| preset | LOD0 | LOD1 | LOD2 | leaf by leaf |
|
|
475
|
-
| :--- | :--- | :--- | :--- | :--- |
|
|
476
|
-
| oak | .46/.46 | .45/.45 | .42/.42 | .48/.53 |
|
|
477
|
-
| willow | .70/.68 | .70/.68 | .66/.64 | |
|
|
478
|
-
| birch | .52/.72 | .53/.67 | .53/.67 | |
|
|
479
|
-
| maple | .43/.43 | .42/.41 | .40/.40 | |
|
|
480
|
-
| pine | .26/.32 | .25/.28 | .22/.27 | |
|
|
481
|
-
| spruce | .24/.39 | .24/.40 | .22/.40 | |
|
|
482
|
-
| shrub | .67/.60 | .59/.58 | .53/.51 | .67/.70 |
|
|
483
|
-
| palm | .59/.69 | .59/.69 | .57/.67 | .62/.70 |
|
|
484
|
-
| fern | .42/.63 | .42/.63 | .50/.61 | .47/.65 |
|
|
485
|
-
|
|
486
|
-
The palm is drawn with one tile for its 12 fronds (its fronds magnified 0.91-1.06), 0.76 MiB.
|
|
487
|
-
|
|
488
|
-
## Tiles drawn past the leaves' spread (2026-10-28)
|
|
489
|
-
|
|
490
|
-
**What was wrong** (Alex's screenshot of the pine, seed 60557, LOD0 in the playground): thick logs among the
|
|
491
|
-
branches, some thicker than the trunk beside them. They were tiles' twigs, magnified. Where the texture ceiling could
|
|
492
|
-
not hold a cover within the leaves' spread at the legible texel, the choice stopped at legible and drew the cuts no
|
|
493
|
-
tile covered with the least unlike of all, at any size. A pine's LOD0 cuts are whole boughs, 3.5 GB of their own tiles
|
|
494
|
-
at 0.8 mm against a 9.9 MiB ceiling: 86% of its LOD0 cover (by area) was drawn past the spread, magnified up to 10.8x;
|
|
495
|
-
the spruce's up to 15.6x; the shrub's tiles shrunk down to 0.02x. "Up to 1.67x" above was the 90th percentile.
|
|
496
|
-
|
|
497
|
-
**The fix.** No cut is drawn at a size the tree's leaves do not grow to: LOD0's texel keeps halving past the legible
|
|
498
|
-
texel until the cover fits. A blurred leaf is still the tree's leaf; a magnified tile is another tree. The loop ends: a
|
|
499
|
-
cut's size is never under a texel, so at a texel as large as every cut one tile draws them all.
|
|
500
|
-
|
|
501
|
-
**Each preset**, LOD0 texel and FIA crown density side/below per LOD, before / after (seed 1337; 60557 where it differs):
|
|
502
|
-
|
|
503
|
-
| preset | LOD0 texel | LOD0 | LOD1 | LOD2 | atlas |
|
|
504
|
-
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
505
|
-
| oak | 1.41 / 2.83 mm | .46/.46 / same | .45/.45 / same | .42/.42 / same | 824x804 / 502x505 |
|
|
506
|
-
| pine | 0.80 / 6.4 mm | .26/.32 / .26/.31 | .25/.28 / .26/.31 | .22/.27 / .25/.37 | 1038x1005 / 625x650 |
|
|
507
|
-
| spruce | 0.50 / 4.0 mm | .24/.39 / .25/.40 | .24/.40 / .24/.40 | .22/.40 / .22/.38 | 1057x402 / 421x417 |
|
|
508
|
-
| shrub | 1.20 / 4.8 mm (60557: 9.6) | .67/.60 / .64/.58 | .59/.58 / .64/.58 | .53/.51 / .59/.52 | 433x368 / 341x351 |
|
|
509
|
-
|
|
510
|
-
The willow, birch, maple, palm and fern fitted at or before legible and are drawn byte for byte as before.
|
|
511
|
-
The conifers' generation takes 1-2 s longer (single runs on a busy machine); the pine's choice ~5.0 s against
|
|
512
|
-
~3.4 s (paired, 3 runs each).
|
|
513
|
-
|
|
514
|
-
**Measured open items** (independent review):
|
|
515
|
-
- **A cut's wood can be drawn thicker than it grew without magnification.** A cut is matched to a tile by the size of
|
|
516
|
-
its leaf and wood area together, so a few needle shoots on 44 mm of 4 mm twig (pine 60557, LOD0 cut 791) are drawn
|
|
517
|
-
with a tile of the same area that is mostly 1.2 m of bough up to 27.5 mm across. Pine 60557: 58 of 881 LOD0 cuts
|
|
518
|
-
draw more than 3x the wood area they grew (89 before); thickest drawn wood over thickest grown at most 5.3x (20.6x
|
|
519
|
-
before). Maple up to 4.8x, birch 4.2x, oak LOD2 9.6x.
|
|
520
|
-
- **A tile's wood runs off its cut's own wood**: on pine 60557 the angle between them is 10 degrees at the median,
|
|
521
|
-
27 at the 90th percentile, 12-15 cuts over 45 degrees, unchanged by this fix.
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# Real-time trees: what went wrong and the way back (2026-10-27)
|
|
2
|
-
|
|
3
|
-
## What the trees cost, commit by commit
|
|
4
|
-
|
|
5
|
-
Seed 1337, triangles as bark + foliage, measured by generating each preset at each commit.
|
|
6
|
-
|
|
7
|
-
| commit | date | change | oak LOD0 | willow LOD0 | spruce LOD0 | birch LOD0 | most joints |
|
|
8
|
-
| :--- | :--- | :--- | ---: | ---: | ---: | ---: | ---: |
|
|
9
|
-
| 309efebfa | 10-21 | posture and bark | 23k | 38k | 16k | 13k | 32 |
|
|
10
|
-
| 00807d697 | 10-24 | generator graph | 11k | 16k | 11k | 6k | 32 |
|
|
11
|
-
| 3976c5287 | 10-24 | derived wind joints | 11k | 35k | 10k | 6k | 517 |
|
|
12
|
-
| ced837088 | 10-26 | oak twigs as meshed shoots | 83k | 35k | 10k | 6k | 5,703 |
|
|
13
|
-
| 49845ff00 | 10-26 | every species' twigs; crown fills by light | 88k | 637k | 1,108k | 658k | 35,697 |
|
|
14
|
-
| 7d610267e | 10-26 | a card is one leaf | 237k | 1,088k | 1,790k | 838k | 40,466 |
|
|
15
|
-
| 4a3a41928 | 10-27 | S1: pine from the seed | 250k | 1,197k | 1,209k | 615k | 40,620 |
|
|
16
|
-
|
|
17
|
-
Through 10-25 no tree was over 38k triangles at LOD0, and they were real-time. Two changes multiplied the cost:
|
|
18
|
-
|
|
19
|
-
1. **Twigs became meshed branches** (ced837088 for the oak, 49845ff00 for all species). Every shoot is now a tube with its own rings and joints. The bark went from about 8k to 400k–860k triangles, and the joints from hundreds to tens of thousands.
|
|
20
|
-
2. **A card became one leaf** (7d610267e). Foliage went up 3–12×, to 678k triangles on the willow.
|
|
21
|
-
|
|
22
|
-
The LODs share the skeleton. LOD1 and LOD2 drop every branch below level 2 or under 1.5–3.5 cm, which takes away all the twig wood: bark falls to about 3k triangles. But they keep 55% and 28% of the per-leaf cards, scaled up to compensate. So a willow's LOD2 is still 145k triangles, made of single leaves floating where the twigs were. That is why they look bad at any triangle count anyone would ship.
|
|
23
|
-
|
|
24
|
-
## How I got there
|
|
25
|
-
|
|
26
|
-
- **The look was the goal, and I made botany the goal.** On 10-25 Alex said the appearance and flexibility of the generator matter more than real-world accuracy. Each request after that (the oak looks barren, these aren't oak leaves, the crowns look naked) was about the look. I answered each one by modelling more botany, at full resolution, straight into the render mesh.
|
|
27
|
-
- **I had already written down the answer.** `SPEEDTREE_COMPARISON_2026_10_24.md` says individual leaves on thin 3D twigs blow out triangle counts and quad overdraw. It says SpeedTree bakes twig-and-leaf clusters into atlases and places 150–400 cluster cards to show 500k triangles of detail in 3k–8k. Two days later I built the opposite.
|
|
28
|
-
- **The cost was a footnote three times.** "Birch now needs about 45,000 wind joints and 1.1 million triangles" (10-26). "Triangle counts went up ... willow about 1.1M" (10-26). "The pine went from 5k to 85k skeleton nodes and about 700k triangles" (10-27). Each time I listed it under open items and carried on.
|
|
29
|
-
- **I removed the safety net and called it principled.** I raised `max_joints` to 65,536 because the derived count passed the cap. I used "derive counts, no round-number budgets" to justify unbounded counts, when that rule is about deriving the right count, not about never stopping.
|
|
30
|
-
- **I reached for the engine.** When a twig seat on a twig needed six joints, I recommended eight skinning influences. A tree that needs that is the defect.
|
|
31
|
-
|
|
32
|
-
## The way back
|
|
33
|
-
|
|
34
|
-
**The simulation is a generator, not the mesh.** The shoot simulation earns its place: it decides where wood and leaves go, so crowns fill by light without knobs. What it produces should be represented at the detail the screen can show, never drawn shoot for shoot.
|
|
35
|
-
|
|
36
|
-
1. **A cost gate next to the leaf gate.** Triangles per LOD and joints for every preset, per square metre the tree shows from the side, measured on every stage and reported as pass/fail. A regression stops the stage. Built: see the gate below.
|
|
37
|
-
2. **Each LOD is the tree at a geometric error, one knob in world units.**
|
|
38
|
-
- Wood thinner than a LOD's error is not meshed.
|
|
39
|
-
- Rings and spine samples are as many as keep the surface within that error.
|
|
40
|
-
- That is the "physical tolerance" rule applied to geometry, instead of today's authored chain of scales and level cuts.
|
|
41
|
-
3. **What a cut branch carries becomes a cluster card.**
|
|
42
|
-
- The simulated twigs and leaves below a cut are baked orthographically into an atlas tile, using the leaf rasterizer we already have.
|
|
43
|
-
- A handful of representative clusters per species are reused across the crown with each cut's transform, which is how SpeedTree gets 150–400 cards.
|
|
44
|
-
- Leaves stay botanically drawn inside the tiles; the card count follows the wood, not the leaf count.
|
|
45
|
-
4. **The wind rig runs on each LOD's wood.**
|
|
46
|
-
- The tolerance knob is unchanged.
|
|
47
|
-
- Joints follow the meshed branches, so they drop with the twigs.
|
|
48
|
-
- A cluster card takes its cut branch's joint and its parent's, so no seat meets more than four joints.
|
|
49
|
-
5. **Far LOD: an impostor.** `engine/graphics/impostors/octahedral` exists on the older renderer. Whether to port it to shade is its own decision, after 1–4.
|
|
50
|
-
|
|
51
|
-
## Decisions (2026-10-27)
|
|
52
|
-
|
|
53
|
-
- **F1 (Alex: per size, tuned against a metric is fine; mine to choose).** Cost is per square metre a tree shows from the
|
|
54
|
-
side: the mean side area of its drawn envelope (per-slice convex hulls, Cauchy's mean width). A tree twice the size
|
|
55
|
-
may spend four times the triangles. Volume was the other candidate. At the last real-time commits the shrub's density
|
|
56
|
-
per m^2 sits inside the trees' range (423 against 254-753 at 6aff5265e, 371 against 339-585 at 309efebfa), but per
|
|
57
|
-
m^3 it is 2-4 times above them: volume grows faster than what a tree costs to draw. Side area is also what the
|
|
58
|
-
screen pays for.
|
|
59
|
-
- **F2 (Alex: yes).** One card per leaf goes; leaves are drawn inside baked cluster tiles.
|
|
60
|
-
- **F3 (mine).** S2 is parked on `claude/s2-wood-from-leaf-parked` (0efafb11d), with its one failing assertion
|
|
61
|
-
recorded. S3-S6 wait. The plan resumes only for what the look needs, and only within the gate.
|
|
62
|
-
|
|
63
|
-
## The gate (built)
|
|
64
|
-
|
|
65
|
-
`analysis/tree_render_cost.js` measures every LOD's triangles and the joints per m^2 of side area.
|
|
66
|
-
`TREE_RENDER_COST_CEILING` is the densest of the presets at 6aff5265e: 752.6 triangles per m^2 at LOD0 (willow), 407.6
|
|
67
|
-
at LOD1 (willow), 97.0 at LOD2 (shrub), and 17.03 joints per m^2 (shrub).
|
|
68
|
-
|
|
69
|
-
Every preset on master, seed 1337, against the ceiling:
|
|
70
|
-
|
|
71
|
-
| preset | side area | LOD0 | LOD1 | LOD2 | joints |
|
|
72
|
-
| :--- | ---: | ---: | ---: | ---: | ---: |
|
|
73
|
-
| oak | 30.9 m^2 | 250k, 10.7x | 103k, 8.2x | 34k, 11.5x | 4,357, 8.3x |
|
|
74
|
-
| pine | 43.6 m^2 | 641k, 19.5x | 61k, 3.4x | 16k, 3.8x | 11,576, 15.6x |
|
|
75
|
-
| birch | 20.1 m^2 | 615k, 40.7x | 180k, 22.0x | 60k, 30.7x | 15,018, 43.9x |
|
|
76
|
-
| willow | 36.8 m^2 | 1,197k, 43.3x | 432k, 28.8x | 145k, 40.8x | 40,620, 64.9x |
|
|
77
|
-
| maple | 24.8 m^2 | 184k, 9.9x | 72k, 7.1x | 24k, 9.9x | 1,180, 2.8x |
|
|
78
|
-
| spruce | 18.9 m^2 | 1,209k, 84.9x | 259k, 33.5x | 131k, 71.2x | 8,130, 25.2x |
|
|
79
|
-
| palm | 24.8 m^2 | 4k, within | 2k, within | 0.5k, within | 65, within |
|
|
80
|
-
| shrub | 6.6 m^2 | 124k, 24.9x | 44k, 16.2x | 14k, 22.5x | 4,119, 36.6x |
|
|
81
|
-
| fern | 0.42 m^2 | 2k, 6.6x | 0.9k, 5.4x | 0.1k, 2.3x | 24, 3.4x |
|
|
82
|
-
|
|
83
|
-
Every woody preset fails at every LOD, by 2.8x (maple's joints) to 85x (spruce at LOD0). The palm is within. The fern
|
|
84
|
-
already failed at 6aff5265e (7,065 per m^2, a 0.4 m plant of 3.5k triangles). A spec holding every preset under the ceiling
|
|
85
|
-
lands, red then green, with the change that brings them under it.
|
|
86
|
-
|