forked from 1b-agent/opencadstudio-upstream
fix(render): draw transparent hatches over the lines behind them
Hatches are drawn before the wires and write depth, so a transparent hatch above lines in draw order still hid them through the depth test. Transparent hatches now go to their own renderer drawn after the wires: the lines behind show through the blend and the lines in front still win the depth test. Fixes #1720 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
088dec4ab6
commit
d1a2e9db64
1 file changed
+27
-3
@@ -136,6 +136,9 @@ pub struct Pipeline {
|
||||
/// Capability-selected hatch renderer. Storage and texture transports are
|
||||
/// private backends behind one upload/LOD/draw lifecycle.
|
||||
hatch_gpu: hatch_gpu::HatchGpu,
|
||||
/// Hatches with transparency, drawn after the wires so the lines behind
|
||||
/// them show through the blend instead of failing the depth test.
|
||||
hatch_translucent_gpu: hatch_gpu::HatchGpu,
|
||||
image_pipeline: wgpu::RenderPipeline,
|
||||
point_cloud_pipeline: wgpu::RenderPipeline,
|
||||
/// SDF text-quad pipeline (Phase 2b): draws per-glyph quads sampling the
|
||||
@@ -1100,6 +1103,14 @@ impl Pipeline {
|
||||
device_caps,
|
||||
force_compat_renderer,
|
||||
);
|
||||
let hatch_translucent_gpu = hatch_gpu::HatchGpu::new(
|
||||
device,
|
||||
format,
|
||||
&frame_bgl,
|
||||
&content_stencil,
|
||||
device_caps,
|
||||
force_compat_renderer,
|
||||
);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if std::env::var_os("RUST_LOG").is_some() {
|
||||
eprintln!(
|
||||
@@ -2339,6 +2350,7 @@ impl Pipeline {
|
||||
gpu_error_epoch: gpu_errors_seen(),
|
||||
wipeout_pipeline,
|
||||
hatch_gpu,
|
||||
hatch_translucent_gpu,
|
||||
image_pipeline,
|
||||
point_cloud_pipeline,
|
||||
text_pipeline,
|
||||
@@ -3429,10 +3441,12 @@ analytic={:.1} regular={:.1} blocks={:.1}",
|
||||
clip_h: u32,
|
||||
) {
|
||||
let perf_started = crate::perf::enabled().then(iced::time::Instant::now);
|
||||
let instance_count = self.hatch_gpu.update_visibility(queue, |aabb| {
|
||||
let visible = |aabb: [f32; 4]| {
|
||||
!aabb_below_pixel(aabb, view_rot, eye, clip_w, clip_h, 2.0)
|
||||
&& !aabb_offscreen(aabb, view_rot, eye, clip_w, clip_h)
|
||||
});
|
||||
};
|
||||
let instance_count = self.hatch_gpu.update_visibility(queue, visible)
|
||||
+ self.hatch_translucent_gpu.update_visibility(queue, visible);
|
||||
if instance_count == 0 {
|
||||
return;
|
||||
}
|
||||
@@ -3786,7 +3800,10 @@ analytic={:.1} regular={:.1} blocks={:.1}",
|
||||
.iter()
|
||||
.filter(|hatch| hatch.boundary.len() >= 3)
|
||||
.count();
|
||||
self.hatch_gpu.upload(device, queue, hatches);
|
||||
let (translucent, opaque): (Vec<HatchModel>, Vec<HatchModel>) =
|
||||
hatches.iter().cloned().partition(|hatch| hatch.color[3] < 0.999);
|
||||
self.hatch_gpu.upload(device, queue, &opaque);
|
||||
self.hatch_translucent_gpu.upload(device, queue, &translucent);
|
||||
if let Some(started) = perf_started {
|
||||
let elapsed_ms = started.elapsed().as_secs_f64() * 1000.0;
|
||||
if elapsed_ms >= 1.0 {
|
||||
@@ -4819,6 +4836,12 @@ analytic={:.1} regular={:.1} blocks={:.1}",
|
||||
}
|
||||
}
|
||||
}
|
||||
// Transparent hatches blend over the lines already drawn; the
|
||||
// lines in front of them still win the depth test.
|
||||
if !self.skip_hatch_frame {
|
||||
self.hatch_translucent_gpu
|
||||
.draw(&mut pass, &self.uniform_bind_group, stencil_ref);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Pass 5c: SDF text quads (drawn over wires) ────────────────────
|
||||
@@ -5311,6 +5334,7 @@ analytic={:.1} regular={:.1} blocks={:.1}",
|
||||
self.gpu_preview_circles.clear();
|
||||
self.gpu_preview_ellipses.clear();
|
||||
self.hatch_gpu.clear();
|
||||
self.hatch_translucent_gpu.clear();
|
||||
self.gpu_wipeouts.clear();
|
||||
self.wipeout_skip_flags.clear();
|
||||
self.gpu_images.clear();
|
||||
|
||||
Reference in new issue
Block a user