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