Files
OneCAD-Draft/RENDERING_OPTIMIZATION.md
T
Hakan SevenandClaude Opus 4.7 38f9733eb1 docs(rendering): drop completed Phase 2
Phase 2.1/2.2/2.3 landed across the previous commits:
- 727992b quadtree primitive
- 3e87460 Scene::entity_index lazy build
- e43498d wire tessellation uses query_rect
- fcf4d4f mesh draw-time frustum cull
- b70c9f9 hatch + wipeout draw-time frustum cull

What was skipped on purpose:
- Octree-with-Aabb3: meshes only carry XY world_aabb today; the
  pragmatic adaptation is a 4-corner projection test in
  `compute_mesh_lod`. Revisit if a true 3D viewport mode lands.
- Per-mutation incremental quadtree updates: `entity_index_cache` is
  geometry_epoch-keyed and rebuilds lazily on next query. Full
  rebuild is ~50 ms on a 100 k-entity doc — acceptable for occasional
  edits; promote to incremental updates if profiling shows the
  rebuild cost.

Phase 4 (GPU-side culling) remains the next big lever.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 15:03:33 +03:00

2.4 KiB
Raw Blame History

Rendering Optimization Roadmap: Culling & Level of Detail

Background

H7CAD renders all entities every frame regardless of camera position or zoom level. No spatial acceleration, no LOD, no frustum culling. Every wire, hatch, mesh, and image is uploaded and drawn unconditionally. This scales poorly for large drawings (100k+ entities) and dense 3D solids.

Current pipeline order:

  1. Hatch fills → 2. Images → 3. Meshes → 4. Face3D fills → 5. Face3D edges →
  2. Wires → 7. Wipeouts → 8. Selection overlay → 9. MSAA resolve → 10. Blit

Phase 4 — GPU-Side Culling (Advanced)

Goal: Offload culling to the GPU; zero CPU cost for large entity counts.

4.1 Indirect Draw + Compute Cull

Convert per-entity draw calls to indirect draw calls (draw_indirect / draw_indexed_indirect). Run a compute shader pre-pass that tests each entity's AABB against the frustum and writes DrawIndirectArgs only for visible entities.

// cull.wgsl
@compute @workgroup_size(64)
fn cull_entities(@builtin(global_invocation_id) id: vec3<u32>) {
    let entity = entities[id.x];
    if frustum_test(entity.aabb) {
        // atomically append to indirect draw buffer
        let slot = atomicAdd(&draw_count, 1u);
        draw_args[slot] = entity.draw_args;
    }
}

Requires restructuring entity data into GPU-side storage buffers. High complexity; tackle after Phases 1–3 prove insufficient.

4.2 Hierarchical Z-Buffer Occlusion Culling (3D Only)

For dense 3D solid scenes, use a Hi-Z buffer to cull occluded meshes:

  1. Render depth-only pass for large opaque solids.
  2. Downsample depth into mip chain (Hi-Z pyramid).
  3. Compute shader tests each mesh AABB against Hi-Z; skips occluded meshes.

Relevant only for perspective (3D) mode with many overlapping solids.


Implementation Order

Phase 4.1  Indirect draw + GPU cull         high complexity, defer
Phase 4.2  Hi-Z occlusion                   high complexity, 3D only, last

Key Files to Modify

File Change
src/scene/mod.rs Quadtree/octree; LOD epoch tracking
src/scene/pipeline/mod.rs Cull hatch/image entities before upload loops
src/shaders/cull.wgsl New — Phase 4 compute culling shader

Success Metrics

  • Phase 2 target: Pan/zoom frame cost O(visible) not O(total).
  • Phase 4 target: GPU-cull overhead < 0.5 ms for 1M entity scene.