1use glam::Vec2;
8use wisp::application::Application;
9use wisp::render::Renderer;
10use wisp::text::{TextTexturePipeline, WispText, WispTextStyle};
11use wisp::{Color, DropShadowFilter, RenderTexture, Sprite, Stage, Texture, WispFontWeight};
12
13use crate::story::Story;
14
15pub fn story() -> Story {
16 Story {
17 id: "text-shadow-glow",
18 category: "Text",
19 title: "Drop shadow + glow on text",
20 milestone: "M-TEXT.8",
21 writeup: include_str!("writeups/text_shadow_glow.md"),
22 build,
23 tick: None,
24 }
25}
26
27fn build(app: &Application, stage: &mut Stage) {
28 let format = wgpu::TextureFormat::Rgba8Unorm;
29 let renderer = Renderer::new(app, format).expect("renderer");
30 let pipeline = TextTexturePipeline::new(app, wgpu::TextureFormat::Rgba8UnormSrgb);
31 let root = stage.root();
32
33 let backdrop_rt = RenderTexture::with_format(app, 256, 256, format);
36 let _ = renderer.render_stage(
37 app,
38 backdrop_rt.view(),
39 Color::rgba(0.92, 0.93, 0.95, 1.0),
40 &Stage::new(),
41 );
42 let backdrop_bytes = backdrop_rt.read_pixels(app);
43 let backdrop_tex = Texture::from_rgba(app, 256, 256, &backdrop_bytes);
44 let mut backdrop = Sprite::from_texture(backdrop_tex).with_anchor(Vec2::splat(0.5));
45 backdrop.container.transform.scale = Vec2::splat(2.0);
46 let _ = stage.add_child(root, backdrop);
47
48 let text = WispText::new("Glow").with_style(
53 WispTextStyle::default()
54 .with_size(0.50)
55 .with_weight(WispFontWeight::Bold)
56 .with_color(Color::WHITE),
57 );
58 let text_rt_arc = pipeline.render(app, &text, 512, 384);
59 let text_bytes = text_rt_arc.read_pixels(app);
60 let staging = Texture::from_rgba(app, 512, 384, &text_bytes);
65 let input_rt = RenderTexture::with_format(app, 512, 384, format);
66 let mut staging_stage = Stage::new();
67 let mut staging_sprite = Sprite::from_texture(staging.clone()).with_anchor(Vec2::new(0.0, 0.0));
68 staging_sprite.container.transform.position = Vec2::new(-1.0, 1.0);
71 staging_sprite.container.transform.scale = Vec2::new(2.0, -2.0);
72 let _ = staging_stage.add_child(staging_stage.root(), staging_sprite);
73 let _ = renderer.render_stage(app, input_rt.view(), Color::TRANSPARENT, &staging_stage);
74
75 let shadow_rt = RenderTexture::with_format(app, 512, 384, format);
77 renderer.apply_filter(
78 app,
79 &DropShadowFilter {
80 offset: Vec2::new(6.0, 6.0),
81 blur: 5.0,
82 color: Color::rgba(0.0, 0.0, 0.0, 0.6),
83 },
84 &input_rt,
85 &shadow_rt,
86 );
87 let shadow_bytes = shadow_rt.read_pixels(app);
88 let shadow_tex = Texture::from_rgba(app, 512, 384, &shadow_bytes);
89 let mut shadow_sprite = Sprite::from_texture(shadow_tex).with_anchor(Vec2::splat(0.5));
90 shadow_sprite.container.transform.position = Vec2::new(-0.45, 0.20);
91 shadow_sprite.container.transform.scale = Vec2::new(0.9, 0.7);
93 let _ = stage.add_child(root, shadow_sprite);
94
95 let glow_rt = RenderTexture::with_format(app, 512, 384, format);
97 renderer.apply_filter(
98 app,
99 &DropShadowFilter {
100 offset: Vec2::new(0.0, 0.0),
101 blur: 8.0,
102 color: Color::rgba(1.0, 0.80, 0.30, 1.0),
103 },
104 &input_rt,
105 &glow_rt,
106 );
107 let glow_bytes = glow_rt.read_pixels(app);
108 let glow_tex = Texture::from_rgba(app, 512, 384, &glow_bytes);
109 let mut glow_sprite = Sprite::from_texture(glow_tex).with_anchor(Vec2::splat(0.5));
110 glow_sprite.container.transform.position = Vec2::new(0.45, -0.20);
111 glow_sprite.container.transform.scale = Vec2::new(0.9, 0.7);
112 let _ = stage.add_child(root, glow_sprite);
113}