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}
98
99impl StrokeVertexConstructor<Vertex> for CustomStrokeVertexConstructor {
100    fn new_vertex(&mut self, vertex: StrokeVertex) -> Vertex {
101        let pos = vertex.position();
102        Vertex {
103            position: [pos.x, pos.y, 0.0],
104            normal: [0.0, 0.0, 1.0],
105            uv: [0.0, 0.0],
106            color: self.color,
107            material_id: 0,
108            radius: 0.0,
109            slice: [0.0, 0.0, 0.0, 1.0],
110            logical: [pos.x, pos.y],
111            size: [1.0, 1.0],
112            clip: self.clip,
113            tex_index: 0,
114        }
115    }
116}
117
118impl FillVertexConstructor<Vertex> for SceneVertexConstructor {
119    fn new_vertex(&mut self, vertex: FillVertex) -> Vertex {
120        Vertex {
121            position: [vertex.position().x, vertex.position().y, 0.0],
122            normal: [0.0, 0.0, 1.0],
123            uv: [0.0, 0.0],
124            color: self.color,
125            material_id: 0,
126            radius: 0.0,
127            slice: [0.0, 0.0, 0.0, 1.0],
128            logical: [vertex.position().x, vertex.position().y],
129            size: [1.0, 1.0],
130            clip: [-f32::INFINITY, -f32::INFINITY, f32::INFINITY, f32::INFINITY],
131            tex_index: 0,
132        }
133    }
134}