#[cfg(not(target_arch = "wasm32"))]
use crate::gfx::raster;
#[derive(Debug, Clone)]
pub struct DrawCall {
pub depth: f32,
pub color: u32,
pub kind: DrawKind,
}
#[derive(Debug, Clone)]
pub enum DrawKind {
Triangle { x0:f32, y0:f32, x1:f32, y1:f32, x2:f32, y2:f32 },
TriangleG { x0:f32, y0:f32, c0:u32, x1:f32, y1:f32, c1:u32, x2:f32, y2:f32, c2:u32, bands:u32 },
Line { x0:f32, y0:f32, x1:f32, y1:f32 },
}
#[derive(Default, Debug)]
pub struct DepthQueue {
calls: Vec<DrawCall>,
}
impl DepthQueue {
pub fn push_triangle(
&mut self, depth: f32, color: u32,
x0:f32, y0:f32, x1:f32, y1:f32, x2:f32, y2:f32,
) {
self.calls.push(DrawCall {
depth, color,
kind: DrawKind::Triangle { x0, y0, x1, y1, x2, y2 },
});
}
#[allow(clippy::too_many_arguments)]
pub fn push_triangle_g(
&mut self, depth: f32,
x0:f32, y0:f32, c0:u32, x1:f32, y1:f32, c1:u32, x2:f32, y2:f32, c2:u32, bands:u32,
) {
self.calls.push(DrawCall {
depth, color: c0,
kind: DrawKind::TriangleG { x0,y0,c0, x1,y1,c1, x2,y2,c2, bands },
});
}
pub fn push_line(
&mut self, depth: f32, color: u32,
x0:f32, y0:f32, x1:f32, y1:f32,
) {
self.calls.push(DrawCall {
depth, color,
kind: DrawKind::Line { x0, y0, x1, y1 },
});
}
#[cfg(not(target_arch = "wasm32"))]
pub fn flush(mut self, buf: &mut Vec<u32>, width: usize, height: usize) {
self.calls.sort_unstable_by(|a, b| {
b.depth.partial_cmp(&a.depth).unwrap_or(std::cmp::Ordering::Equal)
});
for call in &self.calls {
match call.kind {
DrawKind::Triangle { x0, y0, x1, y1, x2, y2 } =>
raster::fill_triangle(buf, width, height, call.color,
x0, y0, x1, y1, x2, y2),
DrawKind::TriangleG { x0,y0,c0, x1,y1,c1, x2,y2,c2, bands } =>
raster::fill_triangle_gouraud(buf, width, height,
x0,y0,c0, x1,y1,c1, x2,y2,c2, bands),
DrawKind::Line { x0, y0, x1, y1 } =>
raster::draw_line(buf, width, height, call.color,
x0, y0, x1, y1),
}
}
}
pub fn is_empty(&self) -> bool { self.calls.is_empty() }
#[cfg(target_arch = "wasm32")]
pub fn flush_to_webgl(mut self, fill_r: f32, fill_g: f32, fill_b: f32, width: usize, height: usize) {
self.calls.sort_unstable_by(|a, b| {
b.depth.partial_cmp(&a.depth).unwrap_or(std::cmp::Ordering::Equal)
});
for call in &self.calls {
match call.kind {
DrawKind::Triangle { x0, y0, x1, y1, x2, y2 } =>
crate::gfx::webgl::push_triangle(call.color, x0, y0, x1, y1, x2, y2, call.depth),
DrawKind::TriangleG { x0,y0,c0, x1,y1,c1, x2,y2,c2, bands:_ } => {
let avg = {
let r=((c0>>16&0xFF)+(c1>>16&0xFF)+(c2>>16&0xFF))/3;
let g=((c0>>8&0xFF)+(c1>>8&0xFF)+(c2>>8&0xFF))/3;
let b=((c0&0xFF)+(c1&0xFF)+(c2&0xFF))/3;
(r<<16)|(g<<8)|b
};
crate::gfx::webgl::push_triangle(avg, x0, y0, x1, y1, x2, y2, call.depth);
}
DrawKind::Line { x0, y0, x1, y1 } =>
crate::gfx::webgl::push_line(call.color, x0, y0, x1, y1, call.depth),
}
}
crate::gfx::webgl::flush(fill_r, fill_g, fill_b, width, height);
}
}