Skip to main content

cvkg_render_gpu/
vertex.rs

1//! Vertex layouts, instance data, and tessellation vertex constructors.
2use lyon::tessellation::{FillVertex, FillVertexConstructor, StrokeVertex, StrokeVertexConstructor};
3
4#[repr(C)]
5#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
6pub struct Vertex {
7    pub position: [f32; 3],
8    pub normal: [f32; 3],
9    pub uv: [f32; 2],
10    pub color: [f32; 4],
11    pub material_id: u32,
12    pub radius: f32,
13    pub slice: [f32; 4],
14    pub logical: [f32; 2],
15    pub size: [f32; 2],
16    pub screen: [f32; 2],
17    pub clip: [f32; 4], // [x, y, width, height]
18    pub translation: [f32; 2],
19    pub scale: [f32; 2],
20    pub rotation: f32,
21    pub tex_index: u32,
22}
23
24/// Per-instance data for instanced rendering.
25/// Stores transform data previously duplicated across all 4 vertices of a quad.
26/// With instancing, 4 vertices + 1 instance draw a quad, reducing vertex bandwidth ~4x.
27#[repr(C)]
28#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
29pub struct InstanceData {
30    pub translation: [f32; 2],
31    pub scale: [f32; 2],
32    pub rotation: f32,
33    pub _pad: f32,
34}
35
36impl Default for InstanceData {
37    fn default() -> Self {
38        Self { translation: [0.0, 0.0], scale: [1.0, 1.0], rotation: 0.0, _pad: 0.0 }
39    }
40}
41
42impl Vertex {
43    const ATTRIBUTES: [wgpu::VertexAttribute; 15] = wgpu::vertex_attr_array![
44        0 => Float32x3, // position
45        1 => Float32x3, // normal
46        2 => Float32x2, // uv
47        3 => Float32x4, // color
48        4 => Uint32,    // mode
49        5 => Float32,   // radius
50        6 => Float32x4, // slice
51        7 => Float32x2, // logical
52        8 => Float32x2, // size
53        9 => Float32x2, // screen
54        10 => Float32x4, // clip
55        11 => Float32x2, // translation
56        12 => Float32x2, // scale
57        13 => Float32,   // rotation
58        14 => Uint32     // tex_index
59    ];
60
61    pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
62        wgpu::VertexBufferLayout {
63            array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
64            step_mode: wgpu::VertexStepMode::Vertex,
65            attributes: &Self::ATTRIBUTES,
66        }
67    }
68}
69
70pub(crate) struct SceneVertexConstructor {
71    pub(crate) color: [f32; 4],
72    pub(crate) translation: [f32; 2],
73    pub(crate) scale: [f32; 2],
74    pub(crate) rotation: f32,
75}
76
77/// Vertex constructor for stroke tessellation -- includes screen and clip for transform.
78pub(crate) struct CustomStrokeVertexConstructor {
79    pub(crate) color: [f32; 4],
80    pub(crate) translation: [f32; 2],
81    pub(crate) scale: [f32; 2],
82    pub(crate) rotation: f32,
83    pub(crate) screen: [f32; 2],
84    pub(crate) clip: [f32; 4],
85}
86
87impl StrokeVertexConstructor<Vertex> for CustomStrokeVertexConstructor {
88    fn new_vertex(&mut self, vertex: StrokeVertex) -> Vertex {
89        let pos = vertex.position();
90        Vertex {
91            position: [pos.x, pos.y, 0.0],
92            normal: [0.0, 0.0, 1.0],
93            uv: [0.0, 0.0],
94            color: self.color,
95            material_id: 0,
96            radius: 0.0,
97            slice: [0.0, 0.0, 0.0, 1.0],
98            logical: [pos.x, pos.y],
99            size: [1.0, 1.0],
100            screen: self.screen,
101            clip: self.clip,
102            translation: self.translation,
103            scale: self.scale,
104            rotation: self.rotation,
105            tex_index: 0,
106        }
107    }
108}
109
110impl FillVertexConstructor<Vertex> for SceneVertexConstructor {
111    fn new_vertex(&mut self, vertex: FillVertex) -> Vertex {
112        Vertex {
113            position: [vertex.position().x, vertex.position().y, 0.0],
114            normal: [0.0, 0.0, 1.0],
115            uv: [0.0, 0.0],
116            color: self.color,
117            material_id: 0,
118            radius: 0.0,
119            slice: [0.0, 0.0, 0.0, 1.0],
120            logical: [vertex.position().x, vertex.position().y],
121            size: [1.0, 1.0],
122            screen: [0.0, 0.0],
123            clip: [-10000.0, -10000.0, 20000.0, 20000.0],
124            translation: self.translation,
125            scale: self.scale,
126            rotation: self.rotation,
127            tex_index: 0,
128        }
129    }
130}
131