Skip to main content

custom_shader/
custom_shader.rs

1//! custom_shader — exercises the custom-shader escape hatch.
2//!
3//! Produces the same bundle artifacts as `settings` (SVG, tree dump,
4//! draw-ops text, shader manifest, lint) for a tree that paints three
5//! buttons via a registered custom WGSL shader (`gradient.wgsl`). The
6//! SVG fallback emits dashed-magenta placeholders for those buttons —
7//! that's the documented behavior for `ShaderHandle::Custom`. The wgpu
8//! PNG shows the actual gradient pixels.
9//!
10//! Inspection of `out/custom_shader.shader_manifest.txt` is the point —
11//! it lists `custom::gradient` alongside the stock shaders, with the
12//! per-instance uniforms each binding sets.
13//!
14//! Run: `cargo run -p aetna-core --example custom_shader`
15
16use aetna_core::prelude::*;
17
18/// Helper: a button-shaped El whose surface paint is the registered
19/// `gradient` shader instead of stock::rounded_rect. The shader's vec_a
20/// slot is read as the top color, vec_b as the bottom, vec_c.x as the
21/// corner radius.
22fn gradient_button(label: &str, top: Color, bottom: Color, radius: f32) -> El {
23    button(label).text_color(tokens::PRIMARY_FOREGROUND).shader(
24        ShaderBinding::custom("gradient")
25            .color("vec_a", top)
26            .color("vec_b", bottom)
27            .f32("vec_c", radius),
28    )
29}
30
31fn fixture() -> El {
32    column([
33        h1("Custom shader demo"),
34        paragraph(
35            "Three buttons below paint via a registered custom shader \
36             (gradient.wgsl). The right-hand button is a stock rounded_rect \
37             for contrast.",
38        )
39        .muted(),
40        titled_card(
41            "gradient.wgsl — vertical linear gradient",
42            [row([
43                gradient_button(
44                    "Sunrise",
45                    Color::rgb(255, 200, 90),
46                    Color::rgb(245, 95, 110),
47                    tokens::RADIUS_MD,
48                ),
49                gradient_button(
50                    "Ocean",
51                    Color::rgb(120, 200, 255),
52                    Color::rgb(40, 90, 200),
53                    tokens::RADIUS_MD,
54                ),
55                gradient_button(
56                    "Forest",
57                    Color::rgb(180, 230, 140),
58                    Color::rgb(40, 110, 80),
59                    tokens::RADIUS_MD,
60                ),
61                spacer(),
62                button("Stock").secondary(),
63            ])
64            .gap(tokens::SPACE_3)],
65        ),
66    ])
67    .gap(tokens::SPACE_4)
68    .padding(tokens::SPACE_7)
69}
70
71fn main() -> std::io::Result<()> {
72    let mut root = fixture();
73
74    let viewport = Rect::new(0.0, 0.0, 720.0, 360.0);
75    let bundle = render_bundle(&mut root, viewport);
76
77    let out_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("out");
78    let written = write_bundle(&bundle, &out_dir, "custom_shader")?;
79    for p in &written {
80        println!("wrote {}", p.display());
81    }
82
83    if !bundle.lint.findings.is_empty() {
84        eprintln!("\nlint findings ({}):", bundle.lint.findings.len());
85        eprint!("{}", bundle.lint.text());
86    }
87
88    Ok(())
89}