Skip to main content

astrelis_geometry/
gpu_types.rs

1//! GPU data types for geometry rendering.
2//!
3//! Defines instance data structures for GPU-accelerated rendering.
4
5use astrelis_render::wgpu;
6use bytemuck::{Pod, Zeroable};
7
8/// Instance data for filled geometry.
9///
10/// Each instance represents one filled shape.
11#[repr(C)]
12#[derive(Copy, Clone, Debug, Pod, Zeroable)]
13pub struct FillInstance {
14    /// Transform matrix (2x3 stored as 2x4 for alignment)
15    /// [a, b, c, d, tx, ty, 0, 0]
16    pub transform: [[f32; 4]; 2],
17    /// Fill color (RGBA)
18    pub color: [f32; 4],
19}
20
21impl FillInstance {
22    /// Create a fill instance with position offset and color.
23    pub fn new(offset_x: f32, offset_y: f32, color: [f32; 4]) -> Self {
24        Self {
25            transform: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, offset_x, offset_y]],
26            color,
27        }
28    }
29
30    /// Create a fill instance with full transform.
31    pub fn with_transform(transform: [[f32; 4]; 2], color: [f32; 4]) -> Self {
32        Self { transform, color }
33    }
34
35    /// Get the WGPU vertex buffer layout.
36    pub fn vertex_layout() -> wgpu::VertexBufferLayout<'static> {
37        wgpu::VertexBufferLayout {
38            array_stride: std::mem::size_of::<Self>() as u64,
39            step_mode: wgpu::VertexStepMode::Instance,
40            attributes: &[
41                // transform row 0
42                wgpu::VertexAttribute {
43                    offset: 0,
44                    shader_location: 2,
45                    format: wgpu::VertexFormat::Float32x4,
46                },
47                // transform row 1
48                wgpu::VertexAttribute {
49                    offset: 16,
50                    shader_location: 3,
51                    format: wgpu::VertexFormat::Float32x4,
52                },
53                // color
54                wgpu::VertexAttribute {
55                    offset: 32,
56                    shader_location: 4,
57                    format: wgpu::VertexFormat::Float32x4,
58                },
59            ],
60        }
61    }
62}
63
64/// Instance data for stroked geometry.
65///
66/// Each instance represents one stroked path.
67#[repr(C)]
68#[derive(Copy, Clone, Debug, Pod, Zeroable)]
69pub struct StrokeInstance {
70    /// Transform matrix (2x3 stored as 2x4 for alignment)
71    pub transform: [[f32; 4]; 2],
72    /// Stroke color (RGBA)
73    pub color: [f32; 4],
74    /// Stroke width
75    pub width: f32,
76    /// Padding for alignment
77    pub _padding: [f32; 3],
78}
79
80impl StrokeInstance {
81    /// Create a stroke instance.
82    pub fn new(offset_x: f32, offset_y: f32, color: [f32; 4], width: f32) -> Self {
83        Self {
84            transform: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, offset_x, offset_y]],
85            color,
86            width,
87            _padding: [0.0; 3],
88        }
89    }
90
91    /// Get the WGPU vertex buffer layout.
92    ///
93    /// Note: StrokeVertex uses locations 0-3, so instance attributes start at 4.
94    pub fn vertex_layout() -> wgpu::VertexBufferLayout<'static> {
95        wgpu::VertexBufferLayout {
96            array_stride: std::mem::size_of::<Self>() as u64,
97            step_mode: wgpu::VertexStepMode::Instance,
98            attributes: &[
99                // transform row 0
100                wgpu::VertexAttribute {
101                    offset: 0,
102                    shader_location: 4,
103                    format: wgpu::VertexFormat::Float32x4,
104                },
105                // transform row 1
106                wgpu::VertexAttribute {
107                    offset: 16,
108                    shader_location: 5,
109                    format: wgpu::VertexFormat::Float32x4,
110                },
111                // color
112                wgpu::VertexAttribute {
113                    offset: 32,
114                    shader_location: 6,
115                    format: wgpu::VertexFormat::Float32x4,
116                },
117                // width
118                wgpu::VertexAttribute {
119                    offset: 48,
120                    shader_location: 7,
121                    format: wgpu::VertexFormat::Float32,
122                },
123            ],
124        }
125    }
126}
127
128/// Uniform data for projection matrix.
129#[repr(C)]
130#[derive(Copy, Clone, Debug, Pod, Zeroable)]
131pub struct ProjectionUniform {
132    /// 4x4 projection matrix
133    pub matrix: [[f32; 4]; 4],
134}
135
136impl ProjectionUniform {
137    /// Create an orthographic projection matrix for 2D rendering.
138    pub fn orthographic(width: f32, height: f32) -> Self {
139        Self {
140            matrix: [
141                [2.0 / width, 0.0, 0.0, 0.0],
142                [0.0, -2.0 / height, 0.0, 0.0],
143                [0.0, 0.0, 1.0, 0.0],
144                [-1.0, 1.0, 0.0, 1.0],
145            ],
146        }
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153
154    #[test]
155    fn test_fill_instance_size() {
156        // Should be 48 bytes (2x16 + 16)
157        assert_eq!(std::mem::size_of::<FillInstance>(), 48);
158    }
159
160    #[test]
161    fn test_stroke_instance_size() {
162        // Should be 64 bytes (48 + 16)
163        assert_eq!(std::mem::size_of::<StrokeInstance>(), 64);
164    }
165
166    #[test]
167    fn test_projection_size() {
168        // Should be 64 bytes (4x4 floats)
169        assert_eq!(std::mem::size_of::<ProjectionUniform>(), 64);
170    }
171}