forked from 1b-agent/opencadstudio-upstream
perf(scene): hatch LOD — solid-fill substitute + sub-pixel skip (Phase 3.3)
Hatch fills drew the full per-family pattern loop every frame regardless
of zoom. Two LOD tiers, neither of which existed:
* **Shader-side solid substitute.** When the densest line family's
spacing × scale projects to less than 2 px, individual lines blur
into a solid color and the per-fragment family loop is wasted ALU
(and produces moiré). Pass `world_per_pixel` through Uniforms; the
hatch fragment shader now returns `h.color` directly in that case.
* **CPU-side sub-pixel skip.** When the entire hatch AABB projects
to less than 2 px, drop the draw call. Adds `world_aabb` to
HatchGpu plus a per-frame `compute_hatch_lod` pass (mirrors the
existing scissor pass) and `hatch_skip_flags`. The render pass
skips flagged hatches.
Factored a shared `aabb_below_pixel` helper for future LOD callers.
The Uniforms layout is unchanged in size (96 B) — the trailing
`_pad: vec2<f32>` becomes `world_per_pixel: f32, _pad: f32`, so wgsl
modules that don't read the new field keep working with their old
`_pad: vec2<f32>` declarations.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
fbbac423d4
commit
e7675be0bc
5 files changed
+102
-7
No files matched your search
+23
-5
@@ -13,10 +13,11 @@
|
||||
// ── Group 0: frame uniforms (shared) ──────────────────────────────────────
|
||||
|
||||
struct Uniforms {
|
||||
view_proj: mat4x4<f32>,
|
||||
camera_pos: vec4<f32>,
|
||||
viewport_size: vec2<f32>,
|
||||
_pad: vec2<f32>,
|
||||
view_proj: mat4x4<f32>,
|
||||
camera_pos: vec4<f32>,
|
||||
viewport_size: vec2<f32>,
|
||||
world_per_pixel: f32,
|
||||
_pad: f32,
|
||||
}
|
||||
@group(0) @binding(0) var<uniform> u: Uniforms;
|
||||
|
||||
@@ -195,7 +196,24 @@ fn check_family(
|
||||
return mix(h.color, h.color2, t);
|
||||
}
|
||||
|
||||
// 3. Pattern: evaluate each line family.
|
||||
// 3. Pattern: LOD substitution — when the densest family's spacing
|
||||
// projects to less than 2 px, individual lines blur into a solid
|
||||
// fill and the per-family loop just wastes ALU. Return solid color
|
||||
// instead. (Phase 3.3 hatch LOD.)
|
||||
if u.world_per_pixel > 0.0 && f.n_families > 0u {
|
||||
var min_spacing_world: f32 = 1.0e30;
|
||||
for (var i = 0u; i < f.n_families; i++) {
|
||||
let s = abs(f.families[i].perp_step) * h.scale;
|
||||
if s > 0.0 && s < min_spacing_world {
|
||||
min_spacing_world = s;
|
||||
}
|
||||
}
|
||||
if min_spacing_world / u.world_per_pixel < 2.0 {
|
||||
return h.color;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Pattern: evaluate each line family.
|
||||
let cos_off = cos(h.angle_offset);
|
||||
let sin_off = sin(h.angle_offset);
|
||||
for (var i = 0u; i < f.n_families; i++) {
|
||||
|
||||
Reference in new issue
Block a user