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}