retrofire_core/render/
prim.rs1use crate::geom::{Edge, Tri, Vertex, Winding};
4use crate::math::{Apply, Mat4x4, Vary, pt3, vary::ZDiv};
5
6use super::{
7 NdcToScreen, Render,
8 clip::ClipVert,
9 raster::{Scanline, ScreenPt, line, tri_fill},
10};
11
12impl<V: Vary> Render<V> for Tri<usize> {
13 type Clip = Tri<ClipVert<V>>;
14 type Clips = [Tri<ClipVert<V>>];
15 type Screen = Tri<Vertex<ScreenPt, V>>;
16
17 fn inline(ixd: Tri<usize>, vs: &[ClipVert<V>]) -> Tri<ClipVert<V>> {
18 Tri(ixd.0.map(|i| vs[i].clone()))
19 }
20
21 fn depth(Tri([a, b, c]): &Self::Clip) -> f32 {
22 (a.pos.z() + b.pos.z() + c.pos.z()) / 3.0
23 }
24
25 fn is_backface(tri: &Self::Screen) -> bool {
26 tri.winding() == Winding::Cw
27 }
28
29 fn to_screen(
30 clip: Tri<ClipVert<V>>,
31 tf: &Mat4x4<NdcToScreen>,
32 ) -> Self::Screen {
33 Tri(to_screen(clip.0, tf))
34 }
35
36 fn rasterize<F: FnMut(Scanline<V>)>(scr: Self::Screen, scanline_fn: F) {
37 tri_fill(scr.0, scanline_fn);
38 }
39}
40
41impl<V: Vary> Render<V> for Edge<usize> {
42 type Clip = Edge<ClipVert<V>>;
43
44 type Clips = [Self::Clip];
45
46 type Screen = Edge<Vertex<ScreenPt, V>>;
47
48 fn inline(Edge(i, j): Edge<usize>, vs: &[ClipVert<V>]) -> Self::Clip {
49 Edge(vs[i].clone(), vs[j].clone())
50 }
51
52 fn to_screen(e: Self::Clip, tf: &Mat4x4<NdcToScreen>) -> Self::Screen {
53 let [a, b] = to_screen([e.0, e.1], tf);
54 Edge(a, b)
55 }
56
57 fn rasterize<F: FnMut(Scanline<V>)>(e: Self::Screen, scanline_fn: F) {
58 line([e.0, e.1], scanline_fn);
59 }
60}
61
62pub fn to_screen<V: ZDiv, const N: usize>(
63 vs: [ClipVert<V>; N],
64 tf: &Mat4x4<NdcToScreen>,
65) -> [Vertex<ScreenPt, V>; N] {
66 vs.map(|v| {
67 let [x, y, _, w] = v.pos.0;
68 let pos = pt3(x, y, 1.0).z_div(w);
81 Vertex {
82 pos: tf.apply(&pos),
84 attrib: v.attrib.z_div(w),
86 }
87 })
88}