1use glam::Vec2;
9use wisp::application::Application;
10use wisp::math::Rect;
11use wisp::render::Renderer;
12use wisp::{
13 BlurStrength, Color, Fill, Graphics, PrivacyBlur, RenderTexture, Sprite, Stage, Texture,
14};
15
16use crate::story::Story;
17
18pub fn story() -> Story {
19 Story {
20 id: "privacy-blur-strength",
21 category: "Mask",
22 title: "Privacy blur strengths",
23 milestone: "M-MASK.4 / AUT-22",
24 writeup: include_str!("writeups/privacy_blur_strength.md"),
25 build,
26 tick: None,
27 }
28}
29
30fn build(app: &Application, stage: &mut Stage) {
31 let format = wgpu::TextureFormat::Rgba8Unorm;
32 let renderer = Renderer::new(app, format).expect("renderer");
33
34 let base_rt = render_capture(&renderer, app, format);
36
37 let strengths = [
39 (BlurStrength::Soft, Vec2::new(-0.62, 0.0)),
40 (BlurStrength::Medium, Vec2::new(0.0, 0.0)),
41 (BlurStrength::Strong, Vec2::new(0.62, 0.0)),
42 ];
43
44 let region = Rect::new(-1.0, -1.0, 2.0, 2.0);
48
49 for (strength, pos) in strengths {
50 let blur = PrivacyBlur::rect(region).with_strength(strength);
51 let out_rt = RenderTexture::with_format(app, 192, 192, format);
52 renderer.apply_privacy_blur_data(app, &blur, &base_rt, &out_rt);
57 let bytes = out_rt.read_pixels(app);
58 let tex = Texture::from_rgba(app, 192, 192, &bytes);
59 let mut sprite = Sprite::from_texture(tex).with_anchor(Vec2::splat(0.5));
60 sprite.container.transform.position = pos;
61 sprite.container.transform.scale = Vec2::splat(0.28);
62 let _ = stage.add_child(stage.root(), sprite);
63 }
64
65 let label_y = -0.32;
68 let label_h = 0.05;
69 let label_w = 0.32;
70 let labels = [
71 (
72 Vec2::new(-0.62, label_y),
73 Color::rgba_u8(140, 200, 240, 230),
74 ), (Vec2::new(0.0, label_y), Color::rgba_u8(220, 220, 130, 230)), (Vec2::new(0.62, label_y), Color::rgba_u8(240, 130, 130, 230)), ];
78 for (pos, color) in labels {
79 let mut bar = Graphics::new();
80 bar.fill(Fill::Solid(color));
81 bar.draw_rounded_rect(
82 Rect::new(
83 pos.x - label_w * 0.5,
84 pos.y - label_h * 0.5,
85 label_w,
86 label_h,
87 ),
88 0.012,
89 );
90 let _ = stage.add_child(stage.root(), bar);
91 }
92}
93
94fn render_capture(
95 renderer: &Renderer,
96 app: &Application,
97 format: wgpu::TextureFormat,
98) -> RenderTexture {
99 let mut s = Stage::new();
100 let mut bg = Graphics::new();
101 bg.fill(Fill::LinearGradient {
102 start: Vec2::new(-1.0, 1.0),
103 end: Vec2::new(1.0, -1.0),
104 color_a: Color::rgba_u8(80, 130, 210, 255),
105 color_b: Color::rgba_u8(220, 110, 80, 255),
106 });
107 bg.draw_rect(Rect::new(-1.0, -1.0, 2.0, 2.0));
108 let _ = s.add_child(s.root(), bg);
109 for i in -4i16..=4 {
110 let x = f32::from(i) * 0.2;
111 let mut line = Graphics::new();
112 line.fill(Fill::Solid(Color::rgba_u8(255, 255, 255, 200)));
113 line.draw_rect(Rect::new(x - 0.005, -1.0, 0.01, 2.0));
114 let _ = s.add_child(s.root(), line);
115 }
116 for j in -4i16..=4 {
117 let y = f32::from(j) * 0.2;
118 let mut line = Graphics::new();
119 line.fill(Fill::Solid(Color::rgba_u8(255, 255, 255, 200)));
120 line.draw_rect(Rect::new(-1.0, y - 0.005, 2.0, 0.01));
121 let _ = s.add_child(s.root(), line);
122 }
123 let rt = RenderTexture::with_format(app, 192, 192, format);
124 let _ = renderer.render_stage(app, rt.view(), Color::BLACK, &s);
125 rt
126}