@woosh/meep-engine 2.164.0 → 2.165.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.
- package/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/core/binary/BitImage2.d.ts +91 -0
- package/src/core/binary/BitImage2.d.ts.map +1 -0
- package/src/core/binary/BitImage2.js +242 -0
- package/src/core/geom/2d/oriented-box/min_area_rect_2d.d.ts +22 -0
- package/src/core/geom/2d/oriented-box/min_area_rect_2d.d.ts.map +1 -0
- package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -0
- package/src/core/geom/2d/packing/skyline.d.ts +116 -0
- package/src/core/geom/2d/packing/skyline.d.ts.map +1 -0
- package/src/core/geom/2d/packing/skyline.js +258 -0
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts +18 -0
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts.map +1 -0
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +86 -0
- package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -0
- package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -0
- package/src/core/geom/3d/atlas/Chart.d.ts +58 -0
- package/src/core/geom/3d/atlas/Chart.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/Chart.js +77 -0
- package/src/core/geom/3d/atlas/REVIEW_02.md +392 -0
- package/src/core/geom/3d/atlas/atlas_bench_lib.d.ts +73 -0
- package/src/core/geom/3d/atlas/atlas_bench_lib.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -0
- package/src/core/geom/3d/atlas/atlas_chart_type.d.ts +17 -0
- package/src/core/geom/3d/atlas/atlas_chart_type.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -0
- package/src/core/geom/3d/atlas/atlas_compute_charts.d.ts +25 -0
- package/src/core/geom/3d/atlas/atlas_compute_charts.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -0
- package/src/core/geom/3d/atlas/atlas_extract_chart.d.ts +17 -0
- package/src/core/geom/3d/atlas/atlas_extract_chart.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -0
- package/src/core/geom/3d/atlas/atlas_generate.d.ts +39 -0
- package/src/core/geom/3d/atlas/atlas_generate.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_generate.js +43 -0
- package/src/core/geom/3d/atlas/atlas_test_fixtures.d.ts +84 -0
- package/src/core/geom/3d/atlas/atlas_test_fixtures.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -0
- package/src/core/geom/3d/atlas/atlas_write_chart_uvs.d.ts +25 -0
- package/src/core/geom/3d/atlas/atlas_write_chart_uvs.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.d.ts +22 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.d.ts +9 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -0
- package/src/core/geom/3d/atlas/data/atlas_build_face_areas.d.ts +9 -0
- package/src/core/geom/3d/atlas/data/atlas_build_face_areas.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -0
- package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.d.ts +27 -0
- package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -0
- package/src/core/geom/3d/atlas/io/bt_loop_uv.d.ts +22 -0
- package/src/core/geom/3d/atlas/io/bt_loop_uv.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/io/bt_loop_uv.js +57 -0
- package/src/core/geom/3d/atlas/pack/ChartPlacement.d.ts +36 -0
- package/src/core/geom/3d/atlas/pack/ChartPlacement.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -0
- package/src/core/geom/3d/atlas/pack/atlas_pack_charts.d.ts +62 -0
- package/src/core/geom/3d/atlas/pack/atlas_pack_charts.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/pack/atlas_pack_charts.js +551 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_param_validity.d.ts +22 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_param_validity.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_param_validity.js +73 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.d.ts +37 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +270 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.d.ts +23 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +224 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.d.ts +14 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.d.ts +22 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -0
- package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.d.ts +20 -0
- package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -0
- package/src/core/geom/3d/atlas/param/fit_plane_basis.d.ts +27 -0
- package/src/core/geom/3d/atlas/param/fit_plane_basis.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -0
- package/src/core/geom/3d/atlas/segment/RegionGraph.d.ts +31 -0
- package/src/core/geom/3d/atlas/segment/RegionGraph.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -0
- package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.d.ts +23 -0
- package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -0
- package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.d.ts +24 -0
- package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -0
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts +27 -0
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +113 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.d.ts +44 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +275 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.d.ts +22 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +199 -0
- package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.d.ts +32 -0
- package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.d.ts.map +1 -0
- package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.d.ts +20 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.d.ts.map +1 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +66 -0
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.d.ts.map +1 -1
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +13 -11
- package/src/core/geom/3d/sphere/sphere_compute_bounding_of_2_spheres.d.ts.map +1 -1
- package/src/core/geom/3d/sphere/sphere_compute_bounding_of_2_spheres.js +4 -3
- package/src/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.d.ts.map +1 -1
- package/src/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.js +4 -3
- package/src/core/geom/3d/topology/simplify/quadratic/Quadric3.d.ts.map +1 -1
- package/src/core/geom/3d/topology/simplify/quadratic/Quadric3.js +4 -3
- package/src/core/geom/3d/topology/simplify/quadratic/apply_border_penalty_to_vertex_quadrics.d.ts.map +1 -1
- package/src/core/geom/3d/topology/simplify/quadratic/apply_border_penalty_to_vertex_quadrics.js +10 -6
- package/src/core/geom/3d/topology/struct/TopoMesh.js +2 -2
- package/src/core/geom/3d/topology/struct/TopoTriangle.d.ts +0 -2
- package/src/core/geom/3d/topology/struct/TopoTriangle.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/TopoTriangle.js +2 -2
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +8 -27
- package/src/core/geom/vec3/v3_cotangent.d.ts +20 -0
- package/src/core/geom/vec3/v3_cotangent.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_cotangent.js +29 -0
- package/src/core/geom/vec3/v3_matrix3_multiply.d.ts +19 -0
- package/src/core/geom/vec3/v3_matrix3_multiply.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -0
- package/src/core/geom/vec3/v3_multiply.d.ts +16 -0
- package/src/core/geom/vec3/v3_multiply.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_multiply.js +19 -0
- package/src/core/math/linalg/cg/cg_solve.d.ts +24 -0
- package/src/core/math/linalg/cg/cg_solve.d.ts.map +1 -0
- package/src/core/math/linalg/cg/cg_solve.js +106 -0
- package/src/core/math/linalg/cg/cg_solve_normal_equations.d.ts +21 -0
- package/src/core/math/linalg/cg/cg_solve_normal_equations.d.ts.map +1 -0
- package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts +19 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -0
- package/src/core/math/linalg/sparse/SparseMatrixCSR.d.ts +50 -0
- package/src/core/math/linalg/sparse/SparseMatrixCSR.d.ts.map +1 -0
- package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -0
- package/src/core/math/linalg/sparse/spm_matvec.d.ts +9 -0
- package/src/core/math/linalg/sparse/spm_matvec.d.ts.map +1 -0
- package/src/core/math/linalg/sparse/spm_matvec.js +22 -0
- package/src/core/math/linalg/sparse/spm_matvec_transpose.d.ts +12 -0
- package/src/core/math/linalg/sparse/spm_matvec_transpose.d.ts.map +1 -0
- package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -0
- package/src/core/math/physics/mie/MIE_PARTICLES_STANDARD_PRECOMPUTED.d.ts +39 -0
- package/src/core/math/physics/mie/MIE_PARTICLES_STANDARD_PRECOMPUTED.js +22 -1
- package/src/core/math/physics/mie/compute_mie_particle_properties_rgb.d.ts.map +1 -1
- package/src/core/math/physics/mie/compute_mie_particle_properties_rgb.js +32 -9
- package/src/core/math/physics/mie/compute_mie_phase.d.ts +2 -3
- package/src/core/math/physics/mie/compute_mie_phase.d.ts.map +1 -1
- package/src/core/math/physics/mie/compute_mie_phase.js +1 -3
- package/src/core/math/physics/mie/lorenz_mie_coefs.d.ts +0 -1
- package/src/core/math/physics/mie/lorenz_mie_coefs.d.ts.map +1 -1
- package/src/core/math/physics/mie/lorenz_mie_coefs.js +0 -7
- package/src/engine/ecs/attachment/TransformAttachmentBinding.js +3 -3
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +2 -2
- package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/Terrain.js +4 -3
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +2 -2
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +9 -8
- package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
- package/src/engine/graphics/GraphicsEngine.js +2 -1
- package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +2 -2
- package/src/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +0 -1
- package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.d.ts.map +1 -1
- package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +8 -7
- package/src/engine/graphics/geometry/MikkT/AvgTSpace.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/AvgTSpace.js +11 -6
- package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +2 -3
- package/src/engine/graphics/geometry/MikkT/CalcTexArea.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/CalcTexArea.js +3 -4
- package/src/engine/graphics/geometry/MikkT/DegenEpilogue.js +4 -4
- package/src/engine/graphics/geometry/MikkT/EvalTspace.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/EvalTspace.js +11 -8
- package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +7 -8
- package/src/engine/graphics/geometry/MikkT/GenerateTSpaces.js +8 -8
- package/src/engine/graphics/geometry/MikkT/InitTriInfo.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/InitTriInfo.js +30 -25
- package/src/engine/graphics/geometry/MikkT/MikkTSpace.js +7 -7
- package/src/engine/graphics/geometry/MikkT/NormalizeSafe.d.ts +0 -1
- package/src/engine/graphics/geometry/MikkT/NormalizeSafe.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/NormalizeSafe.js +6 -4
- package/src/engine/graphics/geometry/MikkT/STSpace.d.ts +0 -2
- package/src/engine/graphics/geometry/MikkT/STSpace.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/STSpace.js +3 -3
- package/src/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.d.ts +0 -2
- package/src/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.d.ts.map +1 -1
- package/src/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.js +0 -1
- package/src/engine/graphics/impostors/octahedral/ImpostorBaker.d.ts +0 -2
- package/src/engine/graphics/impostors/octahedral/ImpostorBaker.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/ImpostorBaker.js +4 -3
- package/src/engine/graphics/impostors/octahedral/grid/HemiOctahedralUvEncoder.js +2 -2
- package/src/engine/graphics/impostors/octahedral/grid/UvEncoder.d.ts +17 -7
- package/src/engine/graphics/impostors/voxel/VoxelImpostorBaker.js +2 -2
- package/src/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +3 -3
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +4 -3
- package/src/engine/graphics/render/forward_plus/LightManager.js +2 -2
- package/src/engine/graphics/render/forward_plus/model/Decal.d.ts +0 -2
- package/src/engine/graphics/render/forward_plus/model/Decal.d.ts.map +1 -1
- package/src/engine/graphics/render/forward_plus/model/Decal.js +3 -3
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +4 -3
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +6 -4
- package/src/engine/graphics/sh3/lightmap/ARTIFACTS_PLAN.md +146 -0
- package/src/engine/graphics/sh3/lightmap/CODE_REVIEW.md +121 -0
- package/src/engine/graphics/sh3/lightmap/LIGHTMAPPER_REVIEW.md +183 -0
- package/src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.d.ts +90 -0
- package/src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.js +678 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_build_geometry.d.ts +32 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_build_geometry.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_build_geometry.js +155 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_denoise.d.ts +49 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_denoise.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_denoise.js +136 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.d.ts +19 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.js +89 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_gather.d.ts +54 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_gather.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_gather.js +168 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_rasterize_triangle.d.ts +30 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_rasterize_triangle.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_rasterize_triangle.js +145 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_seam_fix.d.ts +38 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_seam_fix.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_seam_fix.js +152 -0
- package/src/engine/graphics/sh3/lightmap/prototypeLightmapBaker.d.ts +2 -0
- package/src/engine/graphics/sh3/lightmap/prototypeLightmapBaker.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lightmap/prototypeLightmapBaker.js +186 -0
- package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.d.ts.map +1 -1
- package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +2 -2
- package/src/engine/graphics/sh3/path_tracer/PathTracer.js +2 -2
- package/src/engine/graphics/sh3/path_tracer/prepare_scene_gltf.d.ts.map +1 -1
- package/src/engine/graphics/sh3/path_tracer/prepare_scene_gltf.js +6 -4
- package/src/engine/graphics/sh3/path_tracer/prototypePathTracer.js +3 -3
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.d.ts.map +1 -1
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +5 -4
- package/src/engine/graphics/sh3/sky/hosek/prototype_hosek.js +2 -2
- package/src/engine/input/devices/KeyboardDevice.d.ts +61 -14
- package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
- package/src/engine/input/devices/KeyboardDevice.js +41 -15
- package/src/engine/input/devices/isHTMLElementFocusable.d.ts.map +1 -1
- package/src/engine/input/devices/isHTMLElementFocusable.js +2 -9
- package/src/engine/sound/simulation/prototypeAcousticSolver.js +261 -143
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Lightmap baker — first-principles code review
|
|
2
|
+
|
|
3
|
+
Multi-agent review (6 dimensions × adversarial verification of every finding). 20 raw
|
|
4
|
+
findings → 13 verified-real, 7 dismissed. **No high-severity correctness bugs.** The
|
|
5
|
+
items below are refinements, ordered by impact.
|
|
6
|
+
|
|
7
|
+
## Resolved (this pass)
|
|
8
|
+
|
|
9
|
+
- **Off-surface bias is now a small WORLD-SPACE offset, decoupled from lightmap
|
|
10
|
+
resolution** (`surface_bias × max(1,|coord|)`, default 0.001). A texel-scaled offset
|
|
11
|
+
over-pushes on low-res (clip/leak), under-pushes on dense (acne), and varies per-triangle
|
|
12
|
+
under UV distortion — wrong tool. The texel-footprint **`lightmap_push_sample` relocation
|
|
13
|
+
was removed entirely** (it was built on the same "move by a fraction of a texel" premise);
|
|
14
|
+
buried samples are handled by the confidence mask + dilation. This also dissolves #5, #6
|
|
15
|
+
(push-related) and #10 (the tangent-frame duplication was between gather and push).
|
|
16
|
+
- #1 `ray_batch` now budgets against the adaptive **worst case** (`max(samples_per_texel,
|
|
17
|
+
max_samples)`), so a noisy batch can't blow the per-cycle ray budget.
|
|
18
|
+
- #3 adaptive stop / denoise variance now uses the **unbiased** estimator (÷(n−1)).
|
|
19
|
+
- #4 normal-carry fallback is now **per-triangle** (one bad face no longer drops authored
|
|
20
|
+
normals for the whole mesh).
|
|
21
|
+
- #9 deleted the `lightmap_pack_charts` passthrough; the baker calls `atlas_pack_charts`.
|
|
22
|
+
- #12 fixed the `padding` JSDoc (4). #13 added `lightmap_dilate.spec.js`.
|
|
23
|
+
|
|
24
|
+
Remaining open (low): #7 isotropic world-area scaling, #8 pure-lerp confidence gate,
|
|
25
|
+
#11 job-array preallocation. The notes below are the original review for reference.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Verdict
|
|
30
|
+
|
|
31
|
+
The architecture is sound from first principles:
|
|
32
|
+
- **Light transport** — cosine-importance Monte-Carlo with the arithmetic mean of
|
|
33
|
+
`path_trace` results is the unbiased `E/π` estimator (pdf = cosθ/π). The stored `E/π`
|
|
34
|
+
is correctly reconstructed by three r136's lightmap chunk (`× lightMapIntensity × PI ×
|
|
35
|
+
albedo/PI = texel·albedo`) — valid while the engine stays on the default
|
|
36
|
+
(non-physically-correct) lighting path.
|
|
37
|
+
- **Mixed mode** — indirect-only is genuinely achieved (no direct term; bounced direct
|
|
38
|
+
light at hit surfaces correctly represents indirect).
|
|
39
|
+
- **Geometry/UV** — chart → shared atlas → `uv2`, source-normal carry, conservative
|
|
40
|
+
rasterization, texel-relative bias + push; the baked positions/normals match the
|
|
41
|
+
swapped render geometry.
|
|
42
|
+
- **Post-process** — normal- + variance- + boundary-aware denoise, dilation, normal-aware
|
|
43
|
+
seam-fix. The seam-across-crease and contact-darkening bugs found earlier are addressed.
|
|
44
|
+
|
|
45
|
+
Gap vs the references: we are CPU Monte-Carlo (noisy, mitigated by adaptive sampling +
|
|
46
|
+
denoise) where ands is a noise-free hemicube; missing techniques are bicubic read-time
|
|
47
|
+
filtering (deferred), Phong-tessellated smooth sample position (shadow terminator), and
|
|
48
|
+
stratified/hierarchical-multilevel sampling.
|
|
49
|
+
|
|
50
|
+
## Medium
|
|
51
|
+
|
|
52
|
+
1. **`ray_batch` is budgeted against the minimum sample count, not the adaptive worst
|
|
53
|
+
case** (`bake_lightmap_for_scene.js`, `rays_per_texel = samples_per_texel * …`). Full
|
|
54
|
+
texels can grow to `max_samples` (default 128 = 4× `samples_per_texel`), so a cycle that
|
|
55
|
+
lands on a noisy batch (contacts/edges) can cast ~4× the nominal rays → the frame hitch
|
|
56
|
+
the parameter exists to prevent. *Deliberate trade-off I flagged when adding it; given
|
|
57
|
+
the "no hitches" goal, switch to* `max(samples_per_texel, max_samples) * avg_bounces +
|
|
58
|
+
confidence_probes`.
|
|
59
|
+
|
|
60
|
+
2. **Supersample AA is a single un-stratified origin jitter sharing the RNG stream with
|
|
61
|
+
direction sampling** (`lightmap_gather.js`). Bakery uses a 5×5 stratified tap grid; we
|
|
62
|
+
draw one white-noise origin offset per axis. Higher variance on shadow boundaries than a
|
|
63
|
+
stratified set would give. *Note: stratified directions were previously declined for
|
|
64
|
+
inter-texel coupling; the reconciliation is per-texel-rotated stratification (decorrelated
|
|
65
|
+
per texel), if revisited.*
|
|
66
|
+
|
|
67
|
+
## Low — correctness / robustness
|
|
68
|
+
|
|
69
|
+
3. **Adaptive stop uses population variance (÷n), not sample variance (÷(n−1))**
|
|
70
|
+
(`lightmap_gather.js:132`) → ~3% underestimate at `n≈min_samples`, so the loop can stop a
|
|
71
|
+
touch early and the denoiser sees slightly low variance. Trivial fix; negligible visually.
|
|
72
|
+
4. **Normal-carry fallback is all-or-nothing per mesh** (`lightmap_build_geometry.js`,
|
|
73
|
+
`accumulate_source_normals` returns `false` on the first bad triangle → the whole mesh
|
|
74
|
+
reverts to recomputed geometric normals). One T-junction-split face degrades smooth
|
|
75
|
+
shading everywhere. Fall back **per triangle** instead.
|
|
76
|
+
5. **Supersample jitter is not re-pushed off geometry** (`lightmap_gather.js`): ±0.5-texel
|
|
77
|
+
tangential jitter vs ~0.5-texel normal nudge can place a jittered origin inside adjacent
|
|
78
|
+
geometry near concave edges/curvature → spurious dark first-hit. Couples `supersample`
|
|
79
|
+
with `surface_bias`; at least document, or scale the nudge to dominate.
|
|
80
|
+
6. **`lightmap_push_sample` reuses the original tangent basis across relocation steps** —
|
|
81
|
+
after stepping onto a differently-oriented face the probes stay in the old tangent plane.
|
|
82
|
+
Only matters for deep non-parallel contact pockets; rebuild the basis per step.
|
|
83
|
+
7. **World-area density scaling is isotropic** (`mat4_mean_scale = cbrt(sx·sy·sz)`): under
|
|
84
|
+
anisotropic instance scale, true per-triangle world area depends on orientation. Sum real
|
|
85
|
+
world triangle areas (already computed in the rasterize loop) if anisotropic instances matter.
|
|
86
|
+
8. **Pure-lerp fine texels skip the confidence/backface gate** (`interpolate()` commits
|
|
87
|
+
`coverage=1` unconditionally) — only in `min_sample_fraction = 0` mode (off by default),
|
|
88
|
+
so buried texels could leak there. Document the mode's trade-off or probe before committing.
|
|
89
|
+
|
|
90
|
+
## Low — reuse / efficiency / API / tests
|
|
91
|
+
|
|
92
|
+
9. **`lightmap_pack_charts` is a zero-value passthrough** now that `atlas_pack_charts` is
|
|
93
|
+
mesh-free (`return atlas_pack_charts(charts, options)`). Delete it (+ its spec) and call
|
|
94
|
+
`atlas_pack_charts` directly.
|
|
95
|
+
10. **Tangent-frame construction is duplicated** in `lightmap_gather` and
|
|
96
|
+
`lightmap_push_sample` (same `v3_orthonormal_matrix_from_normal` + two `v3_matrix3_rotate`).
|
|
97
|
+
Extract one helper next to `v3_orthonormal_matrix_from_normal`.
|
|
98
|
+
11. **Job list is built as boxed JS arrays then copied to typed arrays** (`prepare()`:
|
|
99
|
+
`jx/jy/jp/jn/jt`). At 2048² this is millions of boxed pushes + a double-held peak.
|
|
100
|
+
Count-then-preallocate, or write a cursor directly.
|
|
101
|
+
12. **`padding` JSDoc says default 2 but the code is `padding = 4`** — fix the doc. Also the
|
|
102
|
+
24-option surface is large, and the pure-bilinear branch is dead under defaults
|
|
103
|
+
(`min_sample_fraction = 0.25`) — document the mode switch or group the adaptive knobs.
|
|
104
|
+
13. **`lightmap_dilate` has no spec** (every sibling does). Add a small black-box test
|
|
105
|
+
(one-ring growth per pass, hole→neighbour-average, coverage flips to 1).
|
|
106
|
+
|
|
107
|
+
## Notes (accepted / by design)
|
|
108
|
+
|
|
109
|
+
- **Memory** ~137 MB of persistent buffers at 2048² (atlas RGBA-f32 67 MB + normals 50 MB +
|
|
110
|
+
variance 16 MB + coverage 4 MB), +50 MB `world_pos` only under `debug`. Inherent to a dense
|
|
111
|
+
float atlas; fine, worth knowing before raising resolution.
|
|
112
|
+
- **Denoise boundary-aware `alpha`** uses a binary contributing-count, not a weight-sum, so
|
|
113
|
+
near-zero-weight neighbours count as full support — a minor over-count (could weight by Σw).
|
|
114
|
+
- The **MC noise vs hemicube** gap and the **residual low-contrast contact AO gradient**
|
|
115
|
+
(documented in the skipped `lightmap_edge_leak` test) are fundamental to CPU MC + spatial
|
|
116
|
+
denoise; mitigated, not eliminated, by adaptive sampling.
|
|
117
|
+
|
|
118
|
+
## Suggested quick wins
|
|
119
|
+
Safe, low-risk: #3 (unbiased variance), #4 (per-triangle normal fallback), #9 (delete
|
|
120
|
+
passthrough), #10 (dedup tangent helper), #12 (padding doc), #13 (dilate spec). Decision
|
|
121
|
+
needed: #1 (`ray_batch` → worst-case bound) given the no-hitch priority.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Review: ands/lightmapper vs. our lightmap baker
|
|
2
|
+
|
|
3
|
+
Reference: https://github.com/ands/lightmapper (`lightmapper.h`, Andreas Mantler).
|
|
4
|
+
Our code: `engine/graphics/sh3/lightmap/`.
|
|
5
|
+
|
|
6
|
+
Context: we run **mixed mode** — the lightmap stores *indirect + sky only*
|
|
7
|
+
(`lightmap_gather.js` has no direct term); direct light comes from realtime lights.
|
|
8
|
+
|
|
9
|
+
## Status (2026-06): implemented from this review
|
|
10
|
+
|
|
11
|
+
- **Adaptive hierarchical sampling** — `bake_lightmap_for_scene.js` bakes a coarse grid
|
|
12
|
+
(`adaptive_step`), then bilinearly interpolates interior texels whose coarse
|
|
13
|
+
neighbourhood agrees within `interpolation_threshold` and fully path-traces only the
|
|
14
|
+
edges. `adaptive_step = 1` disables. (P0)
|
|
15
|
+
- **Conservative rasterization + clamp-into-triangle** — `lightmap_rasterize_triangle.js`
|
|
16
|
+
`conservative` mode covers edge/sliver texels with a sample clamped onto the triangle. (P1)
|
|
17
|
+
- **Texel-size-relative bias** — the off-surface nudge is `surface_bias × (world size of one
|
|
18
|
+
texel)`, computed per triangle from world-area ÷ uv-area. (P1)
|
|
19
|
+
- **Confidence mask** — `lightmap_gather.js` returns `1 − (fraction of short probes hitting a
|
|
20
|
+
BACK face)`; buried texels (`< valid_threshold`) become holes filled from neighbours.
|
|
21
|
+
Deliberately backface-based, **not** openness-based, so enclosed-but-valid texels (a floor
|
|
22
|
+
in a room) stay confident. (P2)
|
|
23
|
+
- **Variance-driven denoise** — `lightmap_denoise.js` is an edge-stopping filter gated by the
|
|
24
|
+
per-texel Monte-Carlo variance (`lightmap_gather` returns variance-of-the-mean in `out[3]`):
|
|
25
|
+
it blends differences consistent with noise and preserves real gradients. Not a blind blur. (P1)
|
|
26
|
+
- **Doc** — the "direct" term wording is gone from the gather/bake docstrings.
|
|
27
|
+
|
|
28
|
+
Specs: `lightmap_*.spec.js` (rasterize incl. conservative, gather incl. confidence, denoise
|
|
29
|
+
incl. edge-preservation, build_geometry, pack, end-to-end incl. adaptive≈full).
|
|
30
|
+
|
|
31
|
+
### Deliberately NOT done (and why)
|
|
32
|
+
- **Shared stratified directions** — rejected: a fixed direction set shared across texels
|
|
33
|
+
couples samples and shows as structured bias on flats, worst at low sample counts. Each
|
|
34
|
+
texel draws independent random directions; variance is handled by adaptive sampling + the
|
|
35
|
+
variance-driven denoiser instead.
|
|
36
|
+
- **Directional / L1-SH lightmaps** — out of scope: staying within three.js limits (flat RGB).
|
|
37
|
+
- **Progressive multi-bounce (re-bake as emissive)** — deferred: without per-step seam/border
|
|
38
|
+
fixups and a ping-pong buffer it would accumulate noise and leaks.
|
|
39
|
+
- **Web-worker parallelism** — non-goal for now.
|
|
40
|
+
|
|
41
|
+
The remainder of this document is the original analysis.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 1. How the two differ (so we know what ports and what doesn't)
|
|
46
|
+
|
|
47
|
+
| | ands/lightmapper | ours |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| Integrator | GPU **hemicube rasterization**: render the scene into a 5-side hemicube per texel, integrate with a precomputed weight map | CPU **Monte-Carlo path tracing**: N cosine-weighted rays per texel through `PathTracer` |
|
|
50
|
+
| Samples/texel | **1 hemisphere capture** = the whole integral, noise-free per bounce | `samples_per_texel` random rays → stochastic noise (prototype is at **64**) |
|
|
51
|
+
| Multi-bounce | progressive: re-bake feeding the previous lightmap back as emissive | true path bounces inside one gather (`max_bounce`) |
|
|
52
|
+
| UVs | **you bring your own** (suggests xatlas/thekla) | **we generate them** (xatlas charter + shared multi-mesh atlas) |
|
|
53
|
+
| Renderer | needs a live GL context + your scene shaders | headless, renderer-agnostic, unit-testable |
|
|
54
|
+
| Weighting | `cos³θ` per hemicube pixel (Lambert × hemicube foreshortening) | cosine-importance sampling (`getBiasedNormalSample`, power 1) — same radiometry, just via MC |
|
|
55
|
+
| Post | `lmImageDilate` / `lmImageSmooth` / `lmImageDownsample` | `lmImageDilate` equivalent only |
|
|
56
|
+
|
|
57
|
+
**Takeaway:** ands' core advantage is *variance-free capture* and *work-skipping*
|
|
58
|
+
(adaptive interpolation). Almost every ands win lands on our side as either
|
|
59
|
+
**variance reduction** or **work reduction** — both very welcome for a CPU tracer.
|
|
60
|
+
Our advantages (auto-UV, headless, true PT, shared atlas) are things ands does *not* do.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 2. What we already match or beat
|
|
65
|
+
|
|
66
|
+
- **UV generation + shared atlas** — ands explicitly punts UVs to xatlas/thekla; we
|
|
67
|
+
do the unwrap and pack many meshes into one atlas.
|
|
68
|
+
- **Headless / renderer-independent** — our bake needs no GL context and is covered by
|
|
69
|
+
specs; ands requires you to wire your renderer into `lmBegin/lmEnd`.
|
|
70
|
+
- **Correct cosine weighting** — our `getBiasedNormalSample(power=1)` MC estimator is
|
|
71
|
+
the unbiased equivalent of ands' `cos³θ` hemicube weights. No change needed here.
|
|
72
|
+
- **Seam dilation** — `lightmap_dilate.js` ≈ `lmImageDilate`.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 3. Improvements, prioritized
|
|
77
|
+
|
|
78
|
+
### P0 — Adaptive hierarchical sampling (ands `interpolationPasses` / `interpolationThreshold`)
|
|
79
|
+
**ands:** first pass samples only every `1 << interpolationPasses`-th texel; later passes
|
|
80
|
+
fully sample a texel only if a neighbour deviates by more than `interpolationThreshold`,
|
|
81
|
+
otherwise interpolate. Reported **3.3×–10×** speedup at no visible cost.
|
|
82
|
+
|
|
83
|
+
**Ours:** `bake_lightmap_for_scene.js` `cycle()` fully path-traces **every** covered texel.
|
|
84
|
+
|
|
85
|
+
**Why it's our #1:** path tracing per texel is our dominant cost, and in **mixed mode the
|
|
86
|
+
lightmap is indirect-only ⇒ very low frequency ⇒ huge smooth regions** that interpolate
|
|
87
|
+
almost perfectly. This is the single biggest win and it's *more* effective for us than for ands.
|
|
88
|
+
|
|
89
|
+
Sketch: bake on a coarse texel grid, store value+confidence per sampled texel; refine
|
|
90
|
+
(full-sample) only texels whose coarse neighbourhood gradient exceeds a threshold;
|
|
91
|
+
bilinearly fill the rest. Fits our existing job-list/`TaskGroup` cycle model.
|
|
92
|
+
|
|
93
|
+
### P0 — Stratified / jittered hemisphere directions (variance, free win)
|
|
94
|
+
**Ours:** `lightmap_gather.js` draws each direction from raw `random()` → white-noise
|
|
95
|
+
variance, which is exactly why the prototype had to push `samples_per_texel` to 64.
|
|
96
|
+
|
|
97
|
+
**Fix:** we *already ship* `path_tracer/sampling/generate_stratified_samples_2d.js`. Draw
|
|
98
|
+
`Nx×Ny` stratified `(u1,u2)` pairs per texel and map each to a cosine hemisphere direction
|
|
99
|
+
(needs a `getBiasedNormalSample` variant that takes `(u1,u2)` instead of calling `random()`
|
|
100
|
+
internally — trivial refactor). Same sample count, markedly less noise; or same quality at
|
|
101
|
+
far fewer samples. Pair with a per-texel jittered base rotation for inter-texel decorrelation.
|
|
102
|
+
|
|
103
|
+
### P1 — Conservative rasterization + clamp the sample into the triangle
|
|
104
|
+
**ands:** clips the texel quad against the triangle (`lm_convexClip`) and samples the
|
|
105
|
+
**centroid of the clipped polygon** — i.e. every partially-covered texel gets a *valid,
|
|
106
|
+
inside-the-triangle* sample point.
|
|
107
|
+
|
|
108
|
+
**Ours:** `lightmap_rasterize_triangle.js` uses a **texel-center-inside** test
|
|
109
|
+
(`if (wA<0||wB<0||wC<0) continue`). Texels straddling an edge (thin features, chart borders)
|
|
110
|
+
are dropped entirely and left to dilation, and a center that sits just inside an edge can
|
|
111
|
+
sample a near-degenerate spot → leaks/seams.
|
|
112
|
+
|
|
113
|
+
**Fix:** add a conservative coverage mode that, for any texel overlapping the triangle,
|
|
114
|
+
clamps the barycentric sample to the nearest point inside the triangle (or uses the clipped
|
|
115
|
+
centroid). Cuts seam/black-edge artifacts and reduces reliance on dilation. Keep the current
|
|
116
|
+
fast path for interiors.
|
|
117
|
+
|
|
118
|
+
### P1 — Supersample + downsample, and/or a smoothing pass (`lmImageDownsample` / `lmImageSmooth`)
|
|
119
|
+
**ands:** offers `lmImageDownsample` (bake at 2× then box-downsample = cheap AA + denoise)
|
|
120
|
+
and `lmImageSmooth` (3×3 box over valid texels).
|
|
121
|
+
|
|
122
|
+
**Ours:** only dilation. Add a downsample step (bake N× then average) and/or a valid-only
|
|
123
|
+
3×3 smooth before dilation. Especially valuable while we're still MC-noisy. Cheap, isolated,
|
|
124
|
+
high perceived-quality gain.
|
|
125
|
+
|
|
126
|
+
### P1 — Texel-size-relative self-occlusion bias
|
|
127
|
+
**ands:** offsets the camera by `(1+cameraToSurfaceDistanceModifier)·zNear·√2` along the
|
|
128
|
+
interpolated normal; bias is tied to scene/near-plane scale.
|
|
129
|
+
|
|
130
|
+
**Ours:** `surface_bias * max(1,|P|)` in `bake_lightmap_for_scene.js`. Magnitude-relative bias
|
|
131
|
+
over- or under-biases depending on where the geometry sits in world space (peter-panning vs.
|
|
132
|
+
acne). **Better:** derive the bias from the *world size of one lightmap texel* (we know each
|
|
133
|
+
chart's surface-area↔UV-area ratio and the atlas resolution), so the offset scales with local
|
|
134
|
+
texel footprint, not absolute coordinates.
|
|
135
|
+
|
|
136
|
+
### P2 — Validity / confidence mask (ands' alpha-coverage discard)
|
|
137
|
+
**ands:** accumulates per-hemicube solid-angle "validity" in alpha and discards texels with
|
|
138
|
+
< 0.9 coverage (mostly self-occluded / out-of-bounds), then fills them from neighbours.
|
|
139
|
+
**Ours:** no notion of a bad texel. Track a per-texel confidence (fraction of rays that didn't
|
|
140
|
+
immediately self-/back-hit); mark low-confidence texels invalid so dilation fills them from good
|
|
141
|
+
neighbours instead of baking in leaks.
|
|
142
|
+
|
|
143
|
+
### P2 — Progressive multi-bounce via irradiance reuse
|
|
144
|
+
**ands:** extra bounces = re-bake with the previous lightmap as emissive (each pass is 1 bounce).
|
|
145
|
+
**Ours:** N bounces per path per texel — correct but cost ∝ bounces×samples. For *many* bounces,
|
|
146
|
+
a progressive scheme (bake bounce-1, then feed the baked atlas back as an emissive/irradiance
|
|
147
|
+
source so later passes need only 1 bounce) is much cheaper. Low urgency in mixed mode with small
|
|
148
|
+
`max_bounce`, but it's the scalable path.
|
|
149
|
+
|
|
150
|
+
### P2 — Parallelize the bake across Web Workers
|
|
151
|
+
ands gets parallelism for free on the GPU; we're single-threaded. The bake is embarrassingly
|
|
152
|
+
parallel per texel/chart and meep already has worker infrastructure. Biggest raw throughput win
|
|
153
|
+
after adaptive sampling, orthogonal to all of the above.
|
|
154
|
+
|
|
155
|
+
### P3 — Tuning nits
|
|
156
|
+
- For a fixed small `max_bounce`, the path tracer's Russian roulette adds variance; raising
|
|
157
|
+
`min_bounce ≥ max_bounce` (disable RR) gives lower-variance fixed-depth estimates for baking.
|
|
158
|
+
- Bound gather rays with a finite `tMax` (ands' `zFar`) on large scenes.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 4. Mixed-mode specifics
|
|
163
|
+
|
|
164
|
+
- **Indirect-only ⇒ smooth ⇒ adaptive sampling (P0) pays off the most.** Prioritize it.
|
|
165
|
+
- **Directional indirect:** plain RGB indirect ignores per-pixel normals. If normal-mapped
|
|
166
|
+
surfaces should respond to baked indirect, store an **L1 SH / dominant-direction** lightmap
|
|
167
|
+
(Enlighten/Unity "directional") instead of flat irradiance. Bigger feature, but the natural
|
|
168
|
+
next quality step for mixed mode.
|
|
169
|
+
- **Optional AO channel:** a cheap cosine-AO bake alongside indirect is common in mixed setups.
|
|
170
|
+
- **Doc drift:** `lightmap_gather.js` and `bake_lightmap_for_scene.js` docstrings still describe
|
|
171
|
+
a direct-lighting term that's been removed — update them to "indirect + sky (mixed mode)".
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 5. Suggested order of work
|
|
176
|
+
|
|
177
|
+
1. **Stratified hemisphere sampling** (P0, ~hours, pure variance win, primitive already exists).
|
|
178
|
+
2. **Adaptive hierarchical sampling** (P0, biggest speedup, synergizes with indirect-only).
|
|
179
|
+
3. **Conservative raster + sample clamp** (P1, kills edge seams/leaks).
|
|
180
|
+
4. **Downsample/smooth post-pass + texel-relative bias** (P1, quick quality).
|
|
181
|
+
5. **Confidence mask, worker parallelism, directional/AO** (P2+, as needed).
|
|
182
|
+
|
|
183
|
+
Fix the stale docstrings whenever the gather is next touched.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bake a single shared **indirect** lightmap for every {@link ShadedGeometry} in a
|
|
3
|
+
* scene (mixed-mode lighting: direct light stays realtime) using the engine's own
|
|
4
|
+
* UV-atlas charter ({@link atlas_compute_charts} + {@link atlas_pack_charts}) and
|
|
5
|
+
* the {@link PathTracer}.
|
|
6
|
+
*
|
|
7
|
+
* The returned {@link TaskGroup} runs the bake incrementally on an executor: its
|
|
8
|
+
* initializer conditions every mesh (build topology → compute UV charts), packs
|
|
9
|
+
* all charts from all meshes into ONE atlas, swaps each mesh's geometry for a
|
|
10
|
+
* re-charted one carrying a `uv2` lightmap channel, points every material at the
|
|
11
|
+
* shared lightmap texture (initially black), and rasterizes the covered texels
|
|
12
|
+
* conservatively into a bake job list. Subsequent cycles bake the texels and
|
|
13
|
+
* upload the partial result each cycle for a live preview.
|
|
14
|
+
*
|
|
15
|
+
* Quality/perf techniques (see LIGHTMAPPER_REVIEW.md):
|
|
16
|
+
* - **Adaptive sampling** — a coarse grid is fully path-traced first; interior
|
|
17
|
+
* texels whose coarse neighbourhood agrees are bilinearly interpolated, and
|
|
18
|
+
* only edges/discontinuities are fully sampled (`adaptive_step` = 1 disables).
|
|
19
|
+
* - **Conservative rasterization** — edge-overlapping texels get a sample clamped
|
|
20
|
+
* onto the triangle, so thin features and chart borders are covered.
|
|
21
|
+
* - **World-space off-surface bias** — a small fixed world-space nudge (scaled only
|
|
22
|
+
* by coordinate magnitude for float precision), NOT coupled to lightmap resolution.
|
|
23
|
+
* - **Confidence mask** — buried/over-occluded texels are left as holes and filled
|
|
24
|
+
* from good neighbours instead of baking in leaks.
|
|
25
|
+
* - **Variance-guided denoise** — noisy texels blend with consistent neighbours;
|
|
26
|
+
* real gradients are preserved.
|
|
27
|
+
*
|
|
28
|
+
* The lightmap stores cosine-weighted mean radiance (`E / π`, linear); three.js's
|
|
29
|
+
* lightmap path multiplies it back by `π · albedo / π = albedo`, so each surface
|
|
30
|
+
* keeps its colour modulated by the baked indirect light.
|
|
31
|
+
*
|
|
32
|
+
* @param {object} options
|
|
33
|
+
* @param {EntityComponentDataset} options.ecd the scene to bake
|
|
34
|
+
* @param {number} [options.lightmap_resolution] square atlas size in texels (default 2048)
|
|
35
|
+
* @param {number} [options.samples_per_texel] minimum hemisphere gather samples per fully-baked texel (default 32)
|
|
36
|
+
* @param {number} [options.max_samples] adaptive ceiling: noisy texels (contacts/edges) sample up to this (default 128)
|
|
37
|
+
* @param {number} [options.sample_variance_target] relative variance-of-mean to stop adaptive sampling; 0 = fixed count (default 0.02)
|
|
38
|
+
* @param {number} [options.min_bounce] path-tracer roulette start depth (default 2)
|
|
39
|
+
* @param {number} [options.max_bounce] path-tracer maximum depth (default 6)
|
|
40
|
+
* @param {number} [options.padding] atlas gutter texels, also the dilation radius (default 4)
|
|
41
|
+
* @param {number} [options.ray_batch] approximate number of gather/probe rays to cast per
|
|
42
|
+
* executor cycle (default 40000). The per-cycle texel count is derived from this and the
|
|
43
|
+
* per-texel ray cost (samples, bounce depth, confidence probes), so a cycle stays roughly
|
|
44
|
+
* constant work regardless of those — raising `samples_per_texel` shrinks the texel batch
|
|
45
|
+
* instead of lengthening each cycle, keeping the bake from hitching the frame rate.
|
|
46
|
+
* @param {number} [options.light_map_intensity] material lightMapIntensity to set (default 1)
|
|
47
|
+
* @param {number} [options.surface_bias] off-surface nudge as a fraction of the point's world-coordinate
|
|
48
|
+
* magnitude (a small world-space offset, decoupled from lightmap resolution); default 0.001
|
|
49
|
+
* @param {number} [options.adaptive_step] coarse grid spacing in texels; 1 = full sampling everywhere (default 4)
|
|
50
|
+
* @param {number} [options.interpolation_threshold] relative luminance agreement that marks an interior texel "smooth" (default 0.1)
|
|
51
|
+
* @param {number} [options.min_sample_fraction] fraction of `samples_per_texel` spent on smooth texels; 0 = pure bilinear (default 0.25)
|
|
52
|
+
* @param {number} [options.supersample] sub-texel ray-origin jitter as a fraction of a texel (anti-aliasing); 0 disables (default 1)
|
|
53
|
+
* @param {number} [options.confidence_probes] short backface probes per baked texel; 0 disables (default 6)
|
|
54
|
+
* @param {number} [options.inside_probe_texels] backface probe reach in texels (default 4)
|
|
55
|
+
* @param {number} [options.valid_threshold] minimum confidence to keep a texel; below it becomes a hole (default 0.15)
|
|
56
|
+
* @param {boolean} [options.denoise] run the variance-guided denoise pass (default true)
|
|
57
|
+
* @param {number} [options.seam_fix_iterations] UV-seam blend passes; 0 disables (default 4)
|
|
58
|
+
* @param {boolean} [options.debug] also expose per-texel world positions and the
|
|
59
|
+
* pre-dilation baked coverage on `group.lightmap` (extra buffers; default false)
|
|
60
|
+
* @param {function(out:number[], out_offset:number, direction:number[], direction_offset:number):void} [options.background]
|
|
61
|
+
* environment radiance sampler for sky/ambient fill (default {@link make_sky_rtiw})
|
|
62
|
+
* @param {number} [options.seed] PRNG seed for reproducible bakes (default 1)
|
|
63
|
+
* @returns {TaskGroup} a group whose single task performs the bake; it also exposes
|
|
64
|
+
* `.lightmap = { texture, sampler, scene }` for inspection
|
|
65
|
+
*/
|
|
66
|
+
export function bake_lightmap_for_scene({ ecd, lightmap_resolution, samples_per_texel, max_samples, sample_variance_target, min_bounce, max_bounce, padding, ray_batch, light_map_intensity, surface_bias, adaptive_step, interpolation_threshold, min_sample_fraction, supersample, confidence_probes, inside_probe_texels, valid_threshold, denoise, seam_fix_iterations, debug, background, seed, }: {
|
|
67
|
+
ecd: EntityComponentDataset;
|
|
68
|
+
lightmap_resolution?: number;
|
|
69
|
+
samples_per_texel?: number;
|
|
70
|
+
max_samples?: number;
|
|
71
|
+
sample_variance_target?: number;
|
|
72
|
+
min_bounce?: number;
|
|
73
|
+
max_bounce?: number;
|
|
74
|
+
padding?: number;
|
|
75
|
+
ray_batch?: number;
|
|
76
|
+
light_map_intensity?: number;
|
|
77
|
+
surface_bias?: number;
|
|
78
|
+
adaptive_step?: number;
|
|
79
|
+
interpolation_threshold?: number;
|
|
80
|
+
min_sample_fraction?: number;
|
|
81
|
+
supersample?: number;
|
|
82
|
+
confidence_probes?: number;
|
|
83
|
+
inside_probe_texels?: number;
|
|
84
|
+
valid_threshold?: number;
|
|
85
|
+
denoise?: boolean;
|
|
86
|
+
seam_fix_iterations?: number;
|
|
87
|
+
debug?: boolean;
|
|
88
|
+
}): TaskGroup;
|
|
89
|
+
import TaskGroup from "../../../../core/process/task/TaskGroup.js";
|
|
90
|
+
//# sourceMappingURL=bake_lightmap_for_scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bake_lightmap_for_scene.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/sh3/lightmap/bake_lightmap_for_scene.js"],"names":[],"mappings":"AAuEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH;IAjC2C,GAAG;IAClB,mBAAmB,GAApC,MAAM;IACW,iBAAiB,GAAlC,MAAM;IACW,WAAW,GAA5B,MAAM;IACW,sBAAsB,GAAvC,MAAM;IACW,UAAU,GAA3B,MAAM;IACW,UAAU,GAA3B,MAAM;IACW,OAAO,GAAxB,MAAM;IACW,SAAS,GAA1B,MAAM;IAKW,mBAAmB,GAApC,MAAM;IACW,YAAY,GAA7B,MAAM;IAEW,aAAa,GAA9B,MAAM;IACW,uBAAuB,GAAxC,MAAM;IACW,mBAAmB,GAApC,MAAM;IACW,WAAW,GAA5B,MAAM;IACW,iBAAiB,GAAlC,MAAM;IACW,mBAAmB,GAApC,MAAM;IACW,eAAe,GAAhC,MAAM;IACY,OAAO,GAAzB,OAAO;IACU,mBAAmB,GAApC,MAAM;IACY,KAAK,GAAvB,OAAO;IAKL,SAAS,CAgiBrB;sBArpBqB,4CAA4C"}
|