From 033870d91e3abfc8752ca472dd8f1d300d77c3b2 Mon Sep 17 00:00:00 2001 From: Chad Brokaw Date: Wed, 22 Feb 2023 20:10:00 -0500 Subject: [PATCH 1/7] Fix brush transforms This fixes an incorrect application of the inverse transform for radial gradients in fine. Also fixes an edge case in `SceneBuilder` where a brush transform is identical to the path transform leading to a corrupt encoding. --- shader/fine.wgsl | 2 +- src/encoding/encoding.rs | 8 +++++++- src/scene.rs | 26 ++++++++++++++------------ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/shader/fine.wgsl b/shader/fine.wgsl index 4cb5a8e3d..5e7a7725f 100644 --- a/shader/fine.wgsl +++ b/shader/fine.wgsl @@ -251,7 +251,7 @@ fn main( for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) { let my_xy = vec2(xy.x + f32(i), xy.y); // TODO: can hoist y, but for now stick to the GLSL version - let xy_xformed = rad.matrx.xz * my_xy.x + rad.matrx.yw * my_xy.y - rad.xlat; + let xy_xformed = rad.matrx.xy * my_xy.x + rad.matrx.zw * my_xy.y - rad.xlat; let ba = dot(xy_xformed, rad.c1); let ca = rad.ra * dot(xy_xformed, xy_xformed); let t = sqrt(ba * ba + ca) - ba - rad.roff; diff --git a/src/encoding/encoding.rs b/src/encoding/encoding.rs index 4d866c2fc..588015c0a 100644 --- a/src/encoding/encoding.rs +++ b/src/encoding/encoding.rs @@ -120,10 +120,16 @@ impl Encoding { } /// Encodes a transform. - pub fn encode_transform(&mut self, transform: Transform) { + /// + /// If the given transform is different from the current one, encodes it an + /// returns true. Otherwise, encodes nothing and returns false. + pub fn encode_transform(&mut self, transform: Transform) -> bool { if self.transforms.last() != Some(&transform) { self.path_tags.push(PathTag::TRANSFORM); self.transforms.push(transform); + true + } else { + false } } diff --git a/src/scene.rs b/src/scene.rs index 3fb7a9670..98d491a5f 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -140,13 +140,14 @@ impl<'a> SceneBuilder<'a> { }); if self.scene.encode_shape(shape, true) { if let Some(brush_transform) = brush_transform { - self.scene - .encode_transform(Transform::from_kurbo(&(transform * brush_transform))); - self.scene.swap_last_path_tags(); - self.scene.encode_brush(brush, 1.0); - } else { - self.scene.encode_brush(brush, 1.0); + if self + .scene + .encode_transform(Transform::from_kurbo(&(transform * brush_transform))) + { + self.scene.swap_last_path_tags(); + } } + self.scene.encode_brush(brush, 1.0); } } @@ -164,13 +165,14 @@ impl<'a> SceneBuilder<'a> { self.scene.encode_linewidth(style.width); if self.scene.encode_shape(shape, false) { if let Some(brush_transform) = brush_transform { - self.scene - .encode_transform(Transform::from_kurbo(&(transform * brush_transform))); - self.scene.swap_last_path_tags(); - self.scene.encode_brush(brush, 1.0); - } else { - self.scene.encode_brush(brush, 1.0); + if self + .scene + .encode_transform(Transform::from_kurbo(&(transform * brush_transform))) + { + self.scene.swap_last_path_tags(); + } } + self.scene.encode_brush(brush, 1.0); } } From 6612b7a8efc54b869cfa0814c12444ef6b7ce8ab Mon Sep 17 00:00:00 2001 From: Chad Brokaw Date: Wed, 22 Feb 2023 21:47:35 -0500 Subject: [PATCH 2/7] From typo in comment --- src/encoding/encoding.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/encoding/encoding.rs b/src/encoding/encoding.rs index 588015c0a..b1d43fc54 100644 --- a/src/encoding/encoding.rs +++ b/src/encoding/encoding.rs @@ -121,7 +121,7 @@ impl Encoding { /// Encodes a transform. /// - /// If the given transform is different from the current one, encodes it an + /// If the given transform is different from the current one, encodes it and /// returns true. Otherwise, encodes nothing and returns false. pub fn encode_transform(&mut self, transform: Transform) -> bool { if self.transforms.last() != Some(&transform) { From c65c19dc4f067d8d09e7cd110546d131d9c10d68 Mon Sep 17 00:00:00 2001 From: Chad Brokaw Date: Wed, 22 Feb 2023 22:32:04 -0500 Subject: [PATCH 3/7] add additional test scene --- examples/scenes/src/test_scenes.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/examples/scenes/src/test_scenes.rs b/examples/scenes/src/test_scenes.rs index 84b622cd6..f268076d8 100644 --- a/examples/scenes/src/test_scenes.rs +++ b/examples/scenes/src/test_scenes.rs @@ -192,14 +192,25 @@ fn brush_transform(sb: &mut SceneBuilder, params: &mut SceneParams) { ]); sb.fill( Fill::NonZero, - Affine::translate((200.0, 200.0)), + Affine::rotate(25f64.to_radians()) * Affine::scale_non_uniform(2.0, 1.0), + &Gradient::new_radial((200.0, 200.0), 80.0).with_stops([ + Color::RED, + Color::GREEN, + Color::BLUE, + ]), + None, + &Rect::from_origin_size((100.0, 100.0), (200.0, 200.0)), + ); + sb.fill( + Fill::NonZero, + Affine::translate((200.0, 600.0)), &linear, Some(around_center(Affine::rotate(th), Point::new(200.0, 100.0))), &Rect::from_origin_size(Point::default(), (400.0, 200.0)), ); sb.stroke( &Stroke::new(40.0), - Affine::translate((800.0, 200.0)), + Affine::translate((800.0, 600.0)), &linear, Some(around_center(Affine::rotate(th), Point::new(200.0, 100.0))), &Rect::from_origin_size(Point::default(), (400.0, 200.0)), From 3c15bff8679b7c32f0d24eaa9a432e207105e2bc Mon Sep 17 00:00:00 2001 From: Chad Brokaw Date: Wed, 22 Feb 2023 23:08:38 -0500 Subject: [PATCH 4/7] Proper inverse of translation components --- shader/draw_leaf.wgsl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shader/draw_leaf.wgsl b/shader/draw_leaf.wgsl index 0c9a72d3b..1d3e6263a 100644 --- a/shader/draw_leaf.wgsl +++ b/shader/draw_leaf.wgsl @@ -151,7 +151,10 @@ fn main( let r1 = bitcast(scene[dd + 6u]); let inv_det = 1.0 / (matrx.x * matrx.w - matrx.y * matrx.z); let inv_mat = inv_det * vec4(matrx.w, -matrx.y, -matrx.z, matrx.x); - var inv_tr = inv_mat.xz * translate.x + inv_mat.yw * translate.y; + var inv_tr = vec2( + inv_det * (matrx.z * translate.y - matrx.w * translate.x), + inv_det * (matrx.y * translate.x - matrx.x * translate.y), + ); inv_tr += p0; let center1 = p1 - p0; let rr = r1 / (r1 - r0); From 1f938e5f498f538c493d8fa6e42ee7d81f5d2eb5 Mon Sep 17 00:00:00 2001 From: Chad Brokaw Date: Wed, 22 Feb 2023 23:18:51 -0500 Subject: [PATCH 5/7] linear algebra refresher --- shader/draw_leaf.wgsl | 2 +- shader/fine.wgsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shader/draw_leaf.wgsl b/shader/draw_leaf.wgsl index 1d3e6263a..be036abbe 100644 --- a/shader/draw_leaf.wgsl +++ b/shader/draw_leaf.wgsl @@ -155,7 +155,7 @@ fn main( inv_det * (matrx.z * translate.y - matrx.w * translate.x), inv_det * (matrx.y * translate.x - matrx.x * translate.y), ); - inv_tr += p0; + inv_tr -= p0; let center1 = p1 - p0; let rr = r1 / (r1 - r0); let ra_inv = rr / (r1 * r1 - dot(center1, center1)); diff --git a/shader/fine.wgsl b/shader/fine.wgsl index 5e7a7725f..e0d885b41 100644 --- a/shader/fine.wgsl +++ b/shader/fine.wgsl @@ -251,7 +251,7 @@ fn main( for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) { let my_xy = vec2(xy.x + f32(i), xy.y); // TODO: can hoist y, but for now stick to the GLSL version - let xy_xformed = rad.matrx.xy * my_xy.x + rad.matrx.zw * my_xy.y - rad.xlat; + let xy_xformed = rad.matrx.xy * my_xy.x + rad.matrx.zw * my_xy.y + rad.xlat; let ba = dot(xy_xformed, rad.c1); let ca = rad.ra * dot(xy_xformed, xy_xformed); let t = sqrt(ba * ba + ca) - ba - rad.roff; From 659ab2ff7e9610b91af5d8d5d4b6fcde195b5917 Mon Sep 17 00:00:00 2001 From: Chad Brokaw Date: Wed, 22 Feb 2023 23:25:45 -0500 Subject: [PATCH 6/7] simplify --- shader/draw_leaf.wgsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shader/draw_leaf.wgsl b/shader/draw_leaf.wgsl index be036abbe..11ef81f5d 100644 --- a/shader/draw_leaf.wgsl +++ b/shader/draw_leaf.wgsl @@ -151,9 +151,9 @@ fn main( let r1 = bitcast(scene[dd + 6u]); let inv_det = 1.0 / (matrx.x * matrx.w - matrx.y * matrx.z); let inv_mat = inv_det * vec4(matrx.w, -matrx.y, -matrx.z, matrx.x); - var inv_tr = vec2( - inv_det * (matrx.z * translate.y - matrx.w * translate.x), - inv_det * (matrx.y * translate.x - matrx.x * translate.y), + var inv_tr = inv_det * vec2( + matrx.z * translate.y - matrx.w * translate.x, + matrx.y * translate.x - matrx.x * translate.y, ); inv_tr -= p0; let center1 = p1 - p0; From f657b88018da1ab0f1f7984754d7cc8f31cf7870 Mon Sep 17 00:00:00 2001 From: Chad Brokaw Date: Thu, 23 Feb 2023 01:19:04 -0500 Subject: [PATCH 7/7] use matrix math! --- shader/draw_leaf.wgsl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/shader/draw_leaf.wgsl b/shader/draw_leaf.wgsl index 11ef81f5d..9183c95e9 100644 --- a/shader/draw_leaf.wgsl +++ b/shader/draw_leaf.wgsl @@ -151,11 +151,7 @@ fn main( let r1 = bitcast(scene[dd + 6u]); let inv_det = 1.0 / (matrx.x * matrx.w - matrx.y * matrx.z); let inv_mat = inv_det * vec4(matrx.w, -matrx.y, -matrx.z, matrx.x); - var inv_tr = inv_det * vec2( - matrx.z * translate.y - matrx.w * translate.x, - matrx.y * translate.x - matrx.x * translate.y, - ); - inv_tr -= p0; + let inv_tr = mat2x2(inv_mat.xy, inv_mat.zw) * -translate - p0; let center1 = p1 - p0; let rr = r1 / (r1 - r0); let ra_inv = rr / (r1 * r1 - dot(center1, center1));