1use glam::Vec2;
9use wisp::application::Application;
10use wisp::math::Rect;
11use wisp::render::Renderer;
12use wisp::{Color, Fill, Graphics, MaskShape, RenderTexture, Sprite, Stage, Texture};
13
14use crate::story::Story;
15
16pub fn story() -> Story {
17 Story {
18 id: "privacy-blur-rounded",
19 category: "Mask",
20 title: "Rounded privacy blur",
21 milestone: "M-MASK.3 / AUT-21",
22 writeup: include_str!("writeups/privacy_blur_rounded.md"),
23 build,
24 tick: None,
25 }
26}
27
28fn build(app: &Application, stage: &mut Stage) {
29 let format = wgpu::TextureFormat::Rgba8Unorm;
30 let renderer = Renderer::new(app, format).expect("renderer");
31
32 let mut capture_stage = Stage::new();
33
34 let mut bg = Graphics::new();
35 bg.fill(Fill::LinearGradient {
36 start: Vec2::new(-1.0, 1.0),
37 end: Vec2::new(1.0, -1.0),
38 color_a: Color::rgba_u8(80, 130, 210, 255),
39 color_b: Color::rgba_u8(220, 110, 80, 255),
40 });
41 bg.draw_rect(Rect::new(-1.0, -1.0, 2.0, 2.0));
42 let _ = capture_stage.add_child(capture_stage.root(), bg);
43
44 for i in -4i16..=4 {
45 let x = f32::from(i) * 0.2;
46 let mut line = Graphics::new();
47 line.fill(Fill::Solid(Color::rgba_u8(255, 255, 255, 200)));
48 line.draw_rect(Rect::new(x - 0.005, -1.0, 0.01, 2.0));
49 let _ = capture_stage.add_child(capture_stage.root(), line);
50 }
51 for j in -4i16..=4 {
52 let y = f32::from(j) * 0.2;
53 let mut line = Graphics::new();
54 line.fill(Fill::Solid(Color::rgba_u8(255, 255, 255, 200)));
55 line.draw_rect(Rect::new(-1.0, y - 0.005, 2.0, 0.01));
56 let _ = capture_stage.add_child(capture_stage.root(), line);
57 }
58
59 let base_rt = RenderTexture::with_format(app, 256, 256, format);
60 let _ = renderer.render_stage(app, base_rt.view(), Color::BLACK, &capture_stage);
61
62 let output_rt = RenderTexture::with_format(app, 256, 256, format);
63 let region = Rect::new(0.05, -0.45, 0.55, 0.6);
64 let radius = 0.12;
65 renderer.apply_privacy_blur(
66 app,
67 MaskShape::rounded_rect(region, radius),
68 12.0,
69 &base_rt,
70 &output_rt,
71 );
72
73 let bytes = output_rt.read_pixels(app);
74 let result_tex = Texture::from_rgba(app, 256, 256, &bytes);
75
76 let mut shown = Sprite::from_texture(result_tex).with_anchor(Vec2::splat(0.5));
77 shown.container.transform.scale = Vec2::splat(0.9);
78 let _ = stage.add_child(stage.root(), shown);
79
80 let mut outline = Graphics::new();
84 outline.fill(Fill::Solid(Color::rgba_u8(255, 240, 0, 200)));
85 let inner = Rect::new(0.05 * 0.9, -0.45 * 0.9, 0.55 * 0.9, 0.6 * 0.9);
86 let r_scaled = radius * 0.9;
87 let t = 0.008;
88 outline.draw_rect(Rect::new(
90 inner.min.x + r_scaled,
91 inner.min.y + inner.size.y - t,
92 inner.size.x - 2.0 * r_scaled,
93 t,
94 ));
95 outline.draw_rect(Rect::new(
97 inner.min.x + r_scaled,
98 inner.min.y,
99 inner.size.x - 2.0 * r_scaled,
100 t,
101 ));
102 outline.draw_rect(Rect::new(
104 inner.min.x,
105 inner.min.y + r_scaled,
106 t,
107 inner.size.y - 2.0 * r_scaled,
108 ));
109 outline.draw_rect(Rect::new(
111 inner.min.x + inner.size.x - t,
112 inner.min.y + r_scaled,
113 t,
114 inner.size.y - 2.0 * r_scaled,
115 ));
116 let _ = stage.add_child(stage.root(), outline);
117}