Skip to main content

renderling/ui_slab/
mod.rs

1//! Shared types for the 2D/UI rendering pipeline.
2//!
3//! These types are used by both the CPU (renderling-ui crate) and the GPU
4//! (shader entry points in this crate). They are stored in a GPU slab buffer
5//! and read by the UI vertex and fragment shaders.
6
7use crabslab::{Id, SlabItem};
8use glam::{Mat4, UVec2, Vec2, Vec4};
9
10use crate::atlas::shader::{AtlasDescriptor, AtlasTextureDescriptor};
11
12pub mod shader;
13
14
15/// Identifies what kind of UI element is being rendered.
16///
17/// Used by the fragment shader to select the appropriate SDF / sampling logic.
18#[derive(Clone, Copy, Default, PartialEq, SlabItem, core::fmt::Debug)]
19#[repr(u32)]
20pub enum UiElementType {
21    /// A rectangle (optionally rounded).
22    #[default]
23    Rectangle = 0,
24    /// A circle.
25    Circle = 1,
26    /// An ellipse.
27    Ellipse = 2,
28    /// A textured quad (atlas texture sampling).
29    Image = 3,
30    /// A text glyph quad (glyph atlas sampling).
31    TextGlyph = 4,
32    /// A pre-tessellated path triangle (uses vertex color directly).
33    Path = 5,
34}
35
36impl UiElementType {
37    pub fn from_u32(v: u32) -> Self {
38        match v {
39            0 => Self::Rectangle,
40            1 => Self::Circle,
41            2 => Self::Ellipse,
42            3 => Self::Image,
43            4 => Self::TextGlyph,
44            5 => Self::Path,
45            _ => Self::Rectangle,
46        }
47    }
48}
49
50/// Identifies the type of gradient fill.
51#[derive(Clone, Copy, Default, PartialEq, core::fmt::Debug)]
52#[repr(u32)]
53pub enum GradientType {
54    /// No gradient; use solid fill color.
55    #[default]
56    None = 0,
57    /// Linear gradient from `start` to `end`.
58    Linear = 1,
59    /// Radial gradient from `center` outward.
60    Radial = 2,
61}
62
63impl GradientType {
64    pub fn from_u32(v: u32) -> Self {
65        match v {
66            0 => Self::None,
67            1 => Self::Linear,
68            2 => Self::Radial,
69            _ => Self::None,
70        }
71    }
72}
73
74/// Describes a gradient fill for a UI element.
75///
76/// Stored on the GPU slab.
77#[derive(Clone, Copy, Default, PartialEq, SlabItem, core::fmt::Debug)]
78pub struct GradientDescriptor {
79    /// The type of gradient (None, Linear, Radial).
80    pub gradient_type: u32,
81    /// For linear: start point (in element-local 0..1 space).
82    /// For radial: center point.
83    pub start: Vec2,
84    /// For linear: end point.
85    /// For radial: unused.
86    pub end: Vec2,
87    /// For radial: the radius. For linear: unused.
88    pub radius: f32,
89    /// Color at the start (or center for radial).
90    pub color_start: Vec4,
91    /// Color at the end (or edge for radial).
92    pub color_end: Vec4,
93}
94
95/// Per-vertex data for the 2D/UI pipeline.
96///
97/// This is a lightweight vertex type (32 bytes) compared to the 3D
98/// `Vertex` (~160 bytes).
99#[derive(Clone, Copy, Default, PartialEq, SlabItem, core::fmt::Debug)]
100pub struct UiVertex {
101    /// Screen-space position (x, y).
102    pub position: Vec2,
103    /// UV coordinates (for texture sampling or SDF evaluation).
104    pub uv: Vec2,
105    /// Per-vertex RGBA color.
106    pub color: Vec4,
107}
108
109impl UiVertex {
110    pub fn with_position(mut self, position: impl Into<Vec2>) -> Self {
111        self.position = position.into();
112        self
113    }
114
115    pub fn with_uv(mut self, uv: impl Into<Vec2>) -> Self {
116        self.uv = uv.into();
117        self
118    }
119
120    pub fn with_color(mut self, color: impl Into<Vec4>) -> Self {
121        self.color = color.into();
122        self
123    }
124}
125
126/// Describes a single 2D UI element on the GPU.
127///
128/// This is the per-instance data stored in the GPU slab.
129/// The vertex shader reads this to generate quad corners,
130/// and the fragment shader reads it to evaluate SDF shapes,
131/// gradients, textures, etc.
132#[derive(Clone, Copy, Default, PartialEq, SlabItem, core::fmt::Debug)]
133pub struct UiDrawCallDescriptor {
134    /// The type of element (Rectangle, Circle, Ellipse, Image, TextGlyph,
135    /// Path).
136    pub element_type: UiElementType,
137    /// Position of the element's top-left corner in screen space.
138    pub position: Vec2,
139    /// Size of the element in screen pixels (width, height).
140    pub size: Vec2,
141    /// Per-corner radii for rounded rectangles (top-left, top-right,
142    /// bottom-right, bottom-left).
143    pub corner_radii: Vec4,
144    /// Border width in pixels. 0 means no border.
145    pub border_width: f32,
146    /// Border color (RGBA).
147    pub border_color: Vec4,
148    /// Fill color (RGBA). Used when gradient_type is None.
149    pub fill_color: Vec4,
150    /// Gradient fill descriptor.
151    pub gradient: GradientDescriptor,
152    /// ID of the atlas texture descriptor on the slab.
153    ///
154    /// For `Image` and `TextGlyph` elements: points to an
155    /// `AtlasTextureDescriptor`.
156    /// For `Path` elements: when not `Id::NONE`, points to an
157    /// `AtlasTextureDescriptor` for image-filled paths.
158    /// Set to `Id::NONE` when unused.
159    pub atlas_texture_id: Id<AtlasTextureDescriptor>,
160    /// ID of the atlas descriptor on the slab.
161    ///
162    /// For `Path` elements: repurposed to store the slab offset of
163    /// the first `UiVertex` (via `Id::new(offset)`).
164    /// Set to `Id::NONE` when unused.
165    pub atlas_descriptor_id: Id<AtlasDescriptor>,
166    /// Scissor/clip rectangle (x, y, width, height).
167    /// Reserved for future use — not currently enforced by the shader
168    /// or renderer. Set to (0, 0, viewport_w, viewport_h) by default.
169    pub clip_rect: Vec4,
170    /// Element opacity (0.0 = fully transparent, 1.0 = fully opaque).
171    /// Multiplied with the final alpha.
172    pub opacity: f32,
173    /// Z-depth for sorting (painter's algorithm). Lower values are drawn
174    /// first (further back).
175    pub z: f32,
176}
177
178/// Camera/viewport descriptor for the 2D UI pipeline.
179///
180/// Contains the orthographic projection matrix, viewport dimensions,
181/// and atlas texture dimensions.
182#[derive(Clone, Copy, Default, PartialEq, SlabItem, core::fmt::Debug)]
183pub struct UiViewport {
184    /// Orthographic projection matrix (typically top-left origin, +Y down).
185    pub projection: Mat4,
186    /// Viewport size in pixels.
187    pub size: UVec2,
188    /// Atlas texture size in pixels.
189    pub atlas_size: UVec2,
190}