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}
34
35impl Default for InstanceData {
36    fn default() -> Self {
37        Self {
38            translation: [0.0, 0.0],
39            scale: [1.0, 1.0],
40            rotation: 0.0,
41            blur_radius: 0.0,
42            ior_override: 0.0,
43        }
44    }
45}
46
47impl InstanceData {
48    const ATTRIBUTES: [wgpu::VertexAttribute; 5] = wgpu::vertex_attr_array![
49        11 => Float32x2, // translation
50        12 => Float32x2, // scale
51        13 => Float32,   // rotation
52        14 => Float32,   // blur_radius
53        15 => Float32,   // ior_override
54    ];
55
56    pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
57        wgpu::VertexBufferLayout {
58            array_stride: std::mem::size_of::<InstanceData>() as wgpu::BufferAddress,
59            step_mode: wgpu::VertexStepMode::Instance,
60            attributes: &Self::ATTRIBUTES,
61        }
62    }
63}
64
65impl Vertex {
66    const ATTRIBUTES: [wgpu::VertexAttribute; 11] = wgpu::vertex_attr_array![
67        0 => Float32x3, // position
68        1 => Float32x3, // normal
69        2 => Float32x2, // uv
70        3 => Float32x4, // color
71        4 => Uint32,    // mode
72        5 => Float32,   // radius
73        6 => Float32x4, // slice
74        7 => Float32x2, // logical
75        8 => Float32x2, // size
76        9 => Float32x4, // clip
77        10 => Uint32,   // tex_index
78    ];
79
80    pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
81        wgpu::VertexBufferLayout {
82            array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
83            step_mode: wgpu::VertexStepMode::Vertex,
84            attributes: &Self::ATTRIBUTES,
85        }
86    }
87}
88
89pub(crate) struct SceneVertexConstructor {
90    pub(crate) color: [f32; 4],
91}
92
93/// Vertex constructor for stroke tessellation -- includes clip for transform.
94pub(crate) struct CustomStrokeVertexConstructor {
95    pub(crate) color: [f32; 4],
96    pub(crate) clip: [f32; 4],
97    pub(crate) path_length: f32,
98}
99
100impl StrokeVertexConstructor<Vertex> for CustomStrokeVertexConstructor {
101    fn new_vertex(&mut self, vertex: StrokeVertex) -> Vertex {
102        let pos = vertex.position();
103        Vertex {
104            position: [pos.x, pos.y, 0.0],
105            normal: [0.0, 0.0, 1.0],
106            uv: [vertex.advancement(), self.path_length],
107            color: self.color,
108            material_id: 0,
109            radius: 0.0,
110            slice: [0.0, 0.0, 0.0, 1.0],
111            logical: [pos.x, pos.y],
112            size: [1.0, 1.0],
113            clip: self.clip,
114            tex_index: 0,
115        }
116    }
117}
118
119impl FillVertexConstructor<Vertex> for SceneVertexConstructor {
120    fn new_vertex(&mut self, vertex: FillVertex) -> Vertex {
121        Vertex {
122            position: [vertex.position().x, vertex.position().y, 0.0],
123            normal: [0.0, 0.0, 1.0],
124            uv: [0.0, 0.0],
125            color: self.color,
126            material_id: 0,
127            radius: 0.0,
128            slice: [0.0, 0.0, 0.0, 1.0],
129            logical: [vertex.position().x, vertex.position().y],
130            size: [1.0, 1.0],
131            clip: [-f32::INFINITY, -f32::INFINITY, f32::INFINITY, f32::INFINITY],
132            tex_index: 0,
133        }
134    }
135}