1#[cfg(not(target_arch = "wasm32"))]
12use crate::gfx::raster;
13
14#[derive(Debug, Clone)]
16pub struct DrawCall {
17 pub depth: f32,
19 pub color: u32,
21 pub kind: DrawKind,
22}
23
24#[derive(Debug, Clone)]
25pub enum DrawKind {
26 Triangle { x0:f32, y0:f32, x1:f32, y1:f32, x2:f32, y2:f32 },
27 TriangleG { x0:f32, y0:f32, c0:u32, x1:f32, y1:f32, c1:u32, x2:f32, y2:f32, c2:u32, bands:u32 },
29 Line { x0:f32, y0:f32, x1:f32, y1:f32 },
30}
31
32#[derive(Default, Debug)]
34pub struct DepthQueue {
35 calls: Vec<DrawCall>,
36}
37
38impl DepthQueue {
39 pub fn push_triangle(
41 &mut self, depth: f32, color: u32,
42 x0:f32, y0:f32, x1:f32, y1:f32, x2:f32, y2:f32,
43 ) {
44 self.calls.push(DrawCall {
45 depth, color,
46 kind: DrawKind::Triangle { x0, y0, x1, y1, x2, y2 },
47 });
48 }
49
50 #[allow(clippy::too_many_arguments)]
52 pub fn push_triangle_g(
53 &mut self, depth: f32,
54 x0:f32, y0:f32, c0:u32, x1:f32, y1:f32, c1:u32, x2:f32, y2:f32, c2:u32, bands:u32,
55 ) {
56 self.calls.push(DrawCall {
57 depth, color: c0,
58 kind: DrawKind::TriangleG { x0,y0,c0, x1,y1,c1, x2,y2,c2, bands },
59 });
60 }
61
62 pub fn push_line(
64 &mut self, depth: f32, color: u32,
65 x0:f32, y0:f32, x1:f32, y1:f32,
66 ) {
67 self.calls.push(DrawCall {
68 depth, color,
69 kind: DrawKind::Line { x0, y0, x1, y1 },
70 });
71 }
72
73 #[cfg(not(target_arch = "wasm32"))]
76 pub fn flush(mut self, buf: &mut Vec<u32>, width: usize, height: usize) {
77 self.calls.sort_unstable_by(|a, b| {
79 b.depth.partial_cmp(&a.depth).unwrap_or(std::cmp::Ordering::Equal)
80 });
81 for call in &self.calls {
82 match call.kind {
83 DrawKind::Triangle { x0, y0, x1, y1, x2, y2 } =>
84 raster::fill_triangle(buf, width, height, call.color,
85 x0, y0, x1, y1, x2, y2),
86 DrawKind::TriangleG { x0,y0,c0, x1,y1,c1, x2,y2,c2, bands } =>
87 raster::fill_triangle_gouraud(buf, width, height,
88 x0,y0,c0, x1,y1,c1, x2,y2,c2, bands),
89 DrawKind::Line { x0, y0, x1, y1 } =>
90 raster::draw_line(buf, width, height, call.color,
91 x0, y0, x1, y1),
92 }
93 }
94 }
96
97 pub fn is_empty(&self) -> bool { self.calls.is_empty() }
98
99 #[cfg(target_arch = "wasm32")]
102 pub fn flush_to_webgl(mut self, fill_r: f32, fill_g: f32, fill_b: f32, width: usize, height: usize) {
103 self.calls.sort_unstable_by(|a, b| {
105 b.depth.partial_cmp(&a.depth).unwrap_or(std::cmp::Ordering::Equal)
106 });
107 for call in &self.calls {
108 match call.kind {
109 DrawKind::Triangle { x0, y0, x1, y1, x2, y2 } =>
110 crate::gfx::webgl::push_triangle(call.color, x0, y0, x1, y1, x2, y2, call.depth),
111 DrawKind::TriangleG { x0,y0,c0, x1,y1,c1, x2,y2,c2, bands:_ } => {
112 let avg = {
114 let r=((c0>>16&0xFF)+(c1>>16&0xFF)+(c2>>16&0xFF))/3;
115 let g=((c0>>8&0xFF)+(c1>>8&0xFF)+(c2>>8&0xFF))/3;
116 let b=((c0&0xFF)+(c1&0xFF)+(c2&0xFF))/3;
117 (r<<16)|(g<<8)|b
118 };
119 crate::gfx::webgl::push_triangle(avg, x0, y0, x1, y1, x2, y2, call.depth);
120 }
121 DrawKind::Line { x0, y0, x1, y1 } =>
122 crate::gfx::webgl::push_line(call.color, x0, y0, x1, y1, call.depth),
123 }
124 }
125 crate::gfx::webgl::flush(fill_r, fill_g, fill_b, width, height);
126 }
127}