Skip to main content

cvkg_render_gpu/
vertex.rs

1//! Vertex layouts, instance data, and tessellation vertex constructors.
2use lyon::tessellation::{
3    FillVertex, FillVertexConstructor, StrokeVertex, StrokeVertexConstructor,
4};
5
6#[repr(C)]
7#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
8pub struct Vertex {
9    pub position: [f32; 3],
10    pub normal: [f32; 3],
11    pub uv: [f32; 2],
12    pub color: [f32; 4],
13    pub material_id: u32,
14    pub radius: f32,
15    pub slice: [f32; 4],
16    pub logical: [f32; 2],
17    pub size: [f32; 2],
18    pub clip: [f32; 4], // [x, y, width, height]
19    pub tex_index: u32,
20}
21
22/// Per-instance data for instanced rendering.
23/// Stores transform data previously duplicated across all vertices of a path/quad.
24#[repr(C)]
25#[derive(Copy, Clone, Debug, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
26pub struct InstanceData {
27    pub translation: [f32; 2],
28    pub scale: [f32; 2],
29    pub rotation: f32,
30    pub blur_radius: f32,
31    /// Per-instance Index of Refraction (IOR) override for custom glass thickness refraction.
32    pub ior_override: f32,
33    /// Per-instance glass effect intensity (0.0 = frosted/minimal, 1.0 = full refraction+specular).
34    pub glass_intensity: f32,
35}
36
37/// Per-instance data for 3D instanced rendering.
38/// Stores a 3×4 model matrix (4th row implied [0,0,0,1]), material overrides,
39/// and UV transform (scale + offset).
40#[repr(C)]
41#[derive(Copy, Clone, Debug, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
42pub struct InstanceData3D {
43    pub model_row0: [f32; 4],
44    pub model_row1: [f32; 4],
45    pub model_row2: [f32; 4],
46    pub material_overrides: [f32; 4],
47    pub uv_scale: [f32; 2],
48    pub uv_offset: [f32; 2],
49}
50
51impl Default for InstanceData3D {
52    fn default() -> Self {
53        Self {
54            model_row0: [1.0, 0.0, 0.0, 0.0],
55            model_row1: [0.0, 1.0, 0.0, 0.0],
56            model_row2: [0.0, 0.0, 1.0, 0.0],
57            material_overrides: [0.0, 0.0, 1.0, 0.0],
58            uv_scale: [1.0, 1.0],
59            uv_offset: [0.0, 0.0],
60        }
61    }
62}
63
64impl InstanceData3D {
65    const ATTRIBUTES: [wgpu::VertexAttribute; 6] = wgpu::vertex_attr_array![
66        16 => Float32x4,
67        17 => Float32x4,
68        18 => Float32x4,
69        19 => Float32x4,
70        20 => Float32x2,
71        21 => Float32x2,
72    ];
73
74    pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
75        wgpu::VertexBufferLayout {
76            array_stride: std::mem::size_of::<InstanceData3D>() as wgpu::BufferAddress,
77            step_mode: wgpu::VertexStepMode::Instance,
78            attributes: &Self::ATTRIBUTES,
79        }
80    }
81}
82
83impl Default for InstanceData {
84    fn default() -> Self {
85        Self {
86            translation: [0.0, 0.0],
87            scale: [1.0, 1.0],
88            rotation: 0.0,
89            blur_radius: 0.0,
90            ior_override: 0.0,
91            glass_intensity: 1.0,
92        }
93    }
94}
95
96impl InstanceData {
97    const ATTRIBUTES: [wgpu::VertexAttribute; 5] = wgpu::vertex_attr_array![
98        11 => Float32x2, // translation
99        12 => Float32x2, // scale
100        13 => Float32,   // rotation
101        14 => Float32,   // blur_radius
102        15 => Float32x2, // ior_override + glass_intensity
103    ];
104
105    pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
106        wgpu::VertexBufferLayout {
107            array_stride: std::mem::size_of::<InstanceData>() as wgpu::BufferAddress,
108            step_mode: wgpu::VertexStepMode::Instance,
109            attributes: &Self::ATTRIBUTES,
110        }
111    }
112}
113
114impl Vertex {
115    const ATTRIBUTES: [wgpu::VertexAttribute; 11] = wgpu::vertex_attr_array![
116        0 => Float32x3, // position
117        1 => Float32x3, // normal
118        2 => Float32x2, // uv
119        3 => Float32x4, // color
120        4 => Uint32,    // mode
121        5 => Float32,   // radius
122        6 => Float32x4, // slice
123        7 => Float32x2, // logical
124        8 => Float32x2, // size
125        9 => Float32x4, // clip
126        10 => Uint32,   // tex_index
127    ];
128
129    pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
130        wgpu::VertexBufferLayout {
131            array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
132            step_mode: wgpu::VertexStepMode::Vertex,
133            attributes: &Self::ATTRIBUTES,
134        }
135    }
136}
137
138pub(crate) struct SceneVertexConstructor {
139    pub(crate) color: [f32; 4],
140}
141
142/// Vertex constructor for stroke tessellation -- includes clip for transform.
143pub(crate) struct CustomStrokeVertexConstructor {
144    pub(crate) color: [f32; 4],
145    pub(crate) clip: [f32; 4],
146    pub(crate) path_length: f32,
147}
148
149impl StrokeVertexConstructor<Vertex> for CustomStrokeVertexConstructor {
150    fn new_vertex(&mut self, vertex: StrokeVertex) -> Vertex {
151        let pos = vertex.position();
152        Vertex {
153            position: [pos.x, pos.y, 0.0],
154            normal: [0.0, 0.0, 1.0],
155            uv: [vertex.advancement(), self.path_length],
156            color: self.color,
157            material_id: 0,
158            radius: 0.0,
159            slice: [0.0, 0.0, 0.0, 1.0],
160            logical: [pos.x, pos.y],
161            size: [1.0, 1.0],
162            clip: self.clip,
163            tex_index: 0,
164        }
165    }
166}
167
168impl FillVertexConstructor<Vertex> for SceneVertexConstructor {
169    fn new_vertex(&mut self, vertex: FillVertex) -> Vertex {
170        Vertex {
171            position: [vertex.position().x, vertex.position().y, 0.0],
172            normal: [0.0, 0.0, 1.0],
173            uv: [0.0, 0.0],
174            color: self.color,
175            material_id: 0,
176            radius: 0.0,
177            slice: [0.0, 0.0, 0.0, 1.0],
178            logical: [vertex.position().x, vertex.position().y],
179            size: [1.0, 1.0],
180            clip: [-f32::INFINITY, -f32::INFINITY, f32::INFINITY, f32::INFINITY],
181            tex_index: 0,
182        }
183    }
184}