wisp_storybook/stories/
s_path_mask.rs1use glam::Vec2;
8use wisp::application::Application;
9use wisp::math::Rect;
10use wisp::render::Renderer;
11use wisp::{Color, Fill, Graphics, RenderTexture, Sprite, Stage, Texture};
12use crate::story::Story;
16
17pub fn story() -> Story {
18 Story {
19 id: "path-mask",
20 category: "Mask",
21 title: "Freehand path mask",
22 milestone: "M-MASK.10 / AUT-35",
23 writeup: include_str!("writeups/path_mask.md"),
24 build,
25 tick: None,
26 }
27}
28
29fn build(app: &Application, stage: &mut Stage) {
30 let format = wgpu::TextureFormat::Rgba8Unorm;
31 let renderer = Renderer::new(app, format).expect("renderer");
32
33 let frame_rt = render_textured_frame(&renderer, app, format);
34 let star = star_polygon();
35
36 let cutout = RenderTexture::with_format(app, 256, 256, format);
38 renderer.apply_path_clip(app, &star, &frame_rt, &cutout);
39 let cb = cutout.read_pixels(app);
40 let ct = Texture::from_rgba(app, 256, 256, &cb);
41 let mut left = Sprite::from_texture(ct).with_anchor(Vec2::splat(0.5));
42 left.container.transform.position = Vec2::new(-0.45, 0.0);
43 left.container.transform.scale = Vec2::splat(0.4);
44 let _ = stage.add_child(stage.root(), left);
45
46 let redacted = RenderTexture::with_format(app, 256, 256, format);
49 renderer.apply_solid_redaction_path(
50 app,
51 &star,
52 Color::rgba_u8(20, 20, 20, 255),
53 &frame_rt,
54 &redacted,
55 );
56 let rb = redacted.read_pixels(app);
57 let rt = Texture::from_rgba(app, 256, 256, &rb);
58 let mut right = Sprite::from_texture(rt).with_anchor(Vec2::splat(0.5));
59 right.container.transform.position = Vec2::new(0.45, 0.0);
60 right.container.transform.scale = Vec2::splat(0.4);
61 let _ = stage.add_child(stage.root(), right);
62}
63
64fn star_polygon() -> Vec<Vec2> {
65 let mut pts = Vec::with_capacity(10);
66 for i in 0i16..10 {
67 let r = if i % 2 == 0 { 0.85 } else { 0.35 };
68 let theta = f32::from(i) * std::f32::consts::PI / 5.0 - std::f32::consts::FRAC_PI_2;
69 pts.push(Vec2::new(theta.cos() * r, theta.sin() * r));
70 }
71 pts
72}
73
74fn render_textured_frame(
75 renderer: &Renderer,
76 app: &Application,
77 format: wgpu::TextureFormat,
78) -> RenderTexture {
79 let mut s = Stage::new();
80 let mut tone = Graphics::new();
81 tone.fill(Fill::LinearGradient {
82 start: Vec2::new(-1.0, 1.0),
83 end: Vec2::new(1.0, -1.0),
84 color_a: Color::rgba_u8(255, 195, 150, 255),
85 color_b: Color::rgba_u8(150, 100, 80, 255),
86 });
87 tone.draw_rect(Rect::new(-1.0, -1.0, 2.0, 2.0));
88 let _ = s.add_child(s.root(), tone);
89 for i in -3i16..=3 {
90 let x = f32::from(i) * 0.25;
91 let mut line = Graphics::new();
92 line.fill(Fill::Solid(Color::rgba_u8(255, 255, 255, 180)));
93 line.draw_rect(Rect::new(x - 0.01, -1.0, 0.02, 2.0));
94 let _ = s.add_child(s.root(), line);
95 }
96 for j in -3i16..=3 {
97 let y = f32::from(j) * 0.25;
98 let mut line = Graphics::new();
99 line.fill(Fill::Solid(Color::rgba_u8(255, 255, 255, 180)));
100 line.draw_rect(Rect::new(-1.0, y - 0.01, 2.0, 0.02));
101 let _ = s.add_child(s.root(), line);
102 }
103 let rt = RenderTexture::with_format(app, 256, 256, format);
104 let _ = renderer.render_stage(app, rt.view(), Color::TRANSPARENT, &s);
105 rt
106}