Skip to main content

cvkg_render_gpu/api/
shapes.rs

1use crate::renderer::GpuRenderer;
2use crate::types::DrawCall;
3use crate::vertex::{CustomStrokeVertexConstructor, InstanceData, Vertex};
4use cvkg_core::Renderer;
5use lyon::tessellation::{BuffersBuilder, StrokeOptions, StrokeTessellator, VertexBuffers};
6use std::hash::Hasher;
7
8impl GpuRenderer {
9    /// Inherent method: stroke a lyon path using wgpu.
10    pub fn stroke_path_impl(&mut self, path: &lyon::path::Path, color: [f32; 4], stroke_width: f32) {
11        let c = self.apply_opacity(color);
12        let base_vertex_idx = self.vertices.len() as u32;
13        let base_index_idx = self.indices.len() as u32;
14        
15        let path_hash = {
16            let mut h = std::collections::hash_map::DefaultHasher::new();
17            let num_elements = path.iter().count();
18            std::hash::Hash::hash(&num_elements, &mut h);
19            std::hash::Hash::hash(&stroke_width.to_bits(), &mut h);
20            h.finish()
21        };
22
23        let (vert_count, idx_count) = match self.path_geometry_cache.get(&path_hash) {
24            Some((cached_verts, cached_indices)) => {
25                self.vertices.extend_from_slice(cached_verts);
26                for idx in cached_indices {
27                    self.indices.push(base_vertex_idx + *idx);
28                }
29                (cached_verts.len(), cached_indices.len())
30            }
31            None => {
32                let mut tessellator = StrokeTessellator::new();
33                let mut buffers: VertexBuffers<Vertex, u32> = VertexBuffers::new();
34                let result = tessellator.tessellate_path(
35                    path,
36                    &StrokeOptions::default().with_line_width(stroke_width),
37                    &mut BuffersBuilder::new(
38                        &mut buffers,
39                        CustomStrokeVertexConstructor {
40                            color: c,
41                            clip: [0.0, 0.0, 0.0, 0.0],
42                            path_length: 1.0,
43                        },
44                    ),
45                );
46                if let Err(e) = result {
47                    log::warn!("Failed to tessellate stroke path: {:?}", e);
48                    return;
49                }
50                let vert_count = buffers.vertices.len();
51                let idx_count = buffers.indices.len();
52                let cached_verts = buffers.vertices.clone();
53                let cached_indices = buffers.indices.clone();
54                self.path_geometry_cache
55                    .put(path_hash, (cached_verts, cached_indices));
56                self.vertices.extend(buffers.vertices);
57                for idx in &buffers.indices {
58                    self.indices.push(base_vertex_idx + *idx);
59                }
60                (vert_count, idx_count)
61            }
62        };
63
64        let material = self.current_material();
65        let tid = self.get_texture_id("__mega_heim");
66
67        if self.draw_calls.last().is_none()
68            || self.current_texture_id != tid
69            || self.draw_calls.last().unwrap().scissor_rect != self.clip_stack.last().copied()
70            || self.draw_calls.last().unwrap().material != material
71        {
72            self.current_texture_id = tid;
73            let (translation, scale, rotation, _, _) = self.current_transform();
74            self.instance_data.push(InstanceData {
75                translation,
76                scale,
77                rotation,
78                blur_radius: 0.0,
79                ior_override: 0.0,
80                glass_intensity: 1.0,
81            });
82            self.draw_calls.push(DrawCall {
83                target_id: None,
84                texture_id: tid,
85                scissor_rect: self.clip_stack.last().copied(),
86                index_start: base_index_idx,
87                index_count: idx_count as u32,
88                instance_count: 1,
89                material,
90                instance_start: (self.instance_data.len() - 1) as u32,
91                draw_order: 0,
92            });
93        } else {
94            if let Some(last) = self.draw_calls.last_mut() {
95                last.index_count += idx_count as u32;
96            }
97        }
98    }
99}