From d2ba81b0a571d63f52507bcaea54ccde4f044613 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Tue, 29 Aug 2023 20:32:35 +0100 Subject: [PATCH] Support rounded scissor rects --- src/lib.rs | 18 ++++++++++++++++++ src/shader.wgsl | 9 ++++++--- tests/tests.rs | 21 +++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5ab7c38..9a28215 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,6 +58,8 @@ pub(crate) struct Scissor { pub xform: WorldToLocal, pub origin: [f32; 2], pub size: [f32; 2], + pub radius: f32, + pub padding: f32, } impl Scissor { @@ -66,6 +68,8 @@ impl Scissor { xform: WorldToLocal::identity(), origin: [-10000.0, -10000.0], size: [20000.0, 20000.0], + radius: 0.0, + padding: 0.0, } } } @@ -846,6 +850,20 @@ impl Vger { m.xform = xform; m.origin = rect.origin.to_array(); m.size = rect.size.to_array(); + m.radius = 0.0; + } + } + } + + /// Sets the current scissor to a rounded rect. + pub fn rounded_scissor(&mut self, rect: LocalRect, radius: f32) { + if let Some(m) = self.scissor_stack.last_mut() { + *m = Scissor::new(); + if let Some(xform) = self.tx_stack.last().unwrap().inverse() { + m.xform = xform; + m.origin = rect.origin.to_array(); + m.size = rect.size.to_array(); + m.radius = radius; } } } diff --git a/src/shader.wgsl b/src/shader.wgsl index 12cad64..9bf38ba 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -576,6 +576,8 @@ struct Scissor { xform: PackedMat3x2, origin: vec2, size: vec2, + radius: f32, + padding: f32, }; struct Scissors { @@ -591,10 +593,11 @@ fn scissor_mask(scissor: Scissor, p: vec2) -> f32 { let pp = (M * vec3(p, 1.0)).xy; let center = scissor.origin + 0.5 * scissor.size; let size = scissor.size; - if sdBox(pp - center, 0.5 * size, 0.0) < 0.0 { - return 1.0; + let value = 1.0 - sdBox(pp - center, 0.5 * size, scissor.radius); + if scissor.radius > 0.0 { + return value; } else { - return 0.0; + return round(value); } } diff --git a/tests/tests.rs b/tests/tests.rs index a3a4d2c..d598db0 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -433,6 +433,27 @@ fn test_scissor() { assert!(png_not_black(png_name)); } +#[test] +fn test_rounded_scissor() { + let (device, queue) = setup(); + + let mut vger = Vger::new( + device.clone(), + queue.clone(), + wgpu::TextureFormat::Rgba8UnormSrgb, + ); + + vger.begin(512.0, 512.0, 2.0); + + vger.rounded_scissor(euclid::rect(200.0, 200.0, 100.0, 100.0), 20.0); + let cyan = vger.color_paint(Color::WHITE); + vger.fill_rect(euclid::rect(100.0, 100.0, 300.0, 300.0), 10.0, cyan); + + let png_name = "rounded_scissor.png"; + render_test(&mut vger, &device, &queue, png_name, true); + assert!(png_not_black(png_name)); +} + #[test] fn test_scissor_text() { let (device, queue) = setup();