mirage_engine/shader_values.rs
1//! The values a style's or a post effect's WGSL reads, and the WGSL struct
2//! it reads them through.
3//!
4//! `#[derive(ShaderValues)]` over a struct writes both: the WGSL that
5//! declares them, and the bytes laid out where that WGSL reads each
6//! field. The WGSL struct takes the Rust type's own name, each field takes
7//! its own name, and the fields keep the order they were written in; what
8//! padding the shader's own layout calls for is the derive's, not the
9//! game's.
10//!
11//! | Rust | WGSL |
12//! |-------------|---------------|
13//! | `f32` | `f32` |
14//! | `u32` | `u32` |
15//! | `Vec2` | `vec2<f32>` |
16//! | `Vec3` | `vec3<f32>` |
17//! | `Vec4` | `vec4<f32>` |
18//! | `Mat4` | `mat4x4<f32>` |
19//! | [`Color`](crate::Color) | `vec4<f32>`, linear red, green, blue and alpha |
20//!
21//! A field of any other type does not compile. A type with no fields reads
22//! no values and binds none.
23//!
24//! ```
25//! use mirage_engine::prelude::*;
26//!
27//! #[derive(Default, ShaderValues)]
28//! struct Water {
29//! wave: f32,
30//! tint: Color,
31//! }
32//! ```
33//!
34//! declares `struct Water { wave: f32, tint: vec4<f32> }`, which a style
35//! reads as `style` and an effect as `effect`. [`Default`] is derived here
36//! because a [`SurfaceStyle`](crate::SurfaceStyle) requires it — a frame
37//! that passes a style no values draws with the default of every field —
38//! where a [`PostEffect`](crate::PostEffect) does not, since an effect no
39//! frame submits never runs.
40
41use crate::holds::Sealed;
42
43/// The values one style's or one post effect's WGSL reads. Written by
44/// [`ShaderValues`](macro@crate::ShaderValues) on a struct of `f32`, `u32`,
45/// `Vec2`, `Vec3`, `Vec4`, `Mat4` and [`Color`](crate::Color) fields.
46///
47/// A style's code reads them as `style` and an effect's as `effect`. A type
48/// that reads no values has no fields, and binds none.
49pub trait ShaderValues: Sealed + 'static {
50 /// Name of the WGSL struct these values are read through.
51 #[doc(hidden)]
52 const TYPE: &'static str;
53
54 /// The WGSL declaring that struct; empty where the type has no fields.
55 #[doc(hidden)]
56 const DECLARATION: &'static str;
57
58 /// Lays the values out where the shader reads each of them.
59 #[doc(hidden)]
60 fn write(&self, into: &mut Vec<u8>);
61
62 /// The WGSL declaring these values and binding them at `group` under
63 /// `name`; empty where the type has no fields.
64 #[doc(hidden)]
65 fn bound(group: u32, name: &str) -> String
66 where
67 Self: Sized,
68 {
69 if Self::DECLARATION.is_empty() {
70 return String::new();
71 }
72 format!(
73 "{}\n@group({group}) @binding(0) var<uniform> {name}: {};\n\n",
74 Self::DECLARATION,
75 Self::TYPE
76 )
77 }
78}