1use super::*;
2use crate::{Interpolate, Pipeline, Target};
3use core::marker::PhantomData;
4use vek::*;
5
6pub struct Lines<'a, D> {
8 phantom: PhantomData<&'a D>,
9}
10
11impl<'a, D: Target<Item = f32>> Rasterizer for Lines<'a, D> {
12 type Input = [f32; 3]; type Supplement = Option<&'a mut D>; fn draw<P: Pipeline, T: Target<Item = P::Pixel>>(
16 pipeline: &P,
17 vertices: &[P::Vertex],
18 target: &mut T,
19 mut depth: Self::Supplement,
20 ) {
21 if let Some(depth) = depth.as_ref() {
22 assert_eq!(
23 target.size(),
24 depth.size(),
25 "Target and depth buffers are not similarly sized!"
26 );
27 }
28
29 let size = Vec2::from(target.size());
30 let half_scr = size.map(|e: usize| e as f32 * 0.5);
31 const MIRROR: Vec2<f32> = Vec2 { x: 1.0, y: -1.0 };
32
33 vertices.chunks_exact(2).for_each(|verts| {
34 let (a_hom, a_vs_out) = pipeline.vert(&verts[0]);
36 let (b_hom, b_vs_out) = pipeline.vert(&verts[1]);
37
38 let a = Vec3::new(a_hom[0], a_hom[1], a_hom[2]) / a_hom[3];
40 let b = Vec3::new(b_hom[0], b_hom[1], b_hom[2]) / b_hom[3];
41
42 let a_scr = half_scr * (Vec2::from(a) * MIRROR + 1.0);
44 let b_scr = half_scr * (Vec2::from(b) * MIRROR + 1.0);
45
46 let pa: Vec4<f32> = Vec4::from(a_hom);
47 let pb: Vec4<f32> = Vec4::from(b_hom);
48 let ab: Vec4<f32> = pb - pa;
49
50 let a_px = a_scr.map(|e| e as i32);
51 let b_px = b_scr.map(|e| e as i32);
52
53 let min = Vec2::<i32>::min(a_px, b_px);
54 let max = Vec2::<i32>::max(a_px, b_px);
55
56 if (max.x - min.x) > (max.y - min.y) {
57 let (l_scr, r_scr) = if a_scr.x < b_scr.x {
58 (a_scr, b_scr)
59 } else {
60 (b_scr, a_scr)
61 };
62 let factor = 1.0 / (r_scr.x - l_scr.x);
63 let m = Mat2::new(pa.w, -pa.x, -ab.w, ab.x) / (ab.x * pa.w - pa.x * ab.w);
64
65 for x in l_scr.x as i32..r_scr.x as i32 {
66 let y = l_scr.y + (x as f32 - l_scr.x) * factor * (r_scr.y - l_scr.y);
67
68 if x < 0 || (x as usize) >= size.x || y < 0.0 || (y as usize) >= size.y {
70 continue;
71 }
72
73 let s_hom = m * Vec2::new(2.0 * x as f32 / size.x as f32 - 1.0, 1.0);
75 let s = s_hom.x / s_hom.y;
76 let z_lerped = (pa.z + s * ab.z) * s_hom.y;
77
78 let (x, y) = (x as usize, y as usize);
79
80 if depth.as_ref().map(|depth| z_lerped <= unsafe { depth.get([x, y]) }).unwrap_or(true) {
82 let vs_out_lerped =
84 P::VsOut::lerp2(a_vs_out.clone(), b_vs_out.clone(), 1.0 - s, s);
85
86 unsafe {
87 depth.as_mut().map(|depth| depth.set([x, y], z_lerped));
88 target.set([x, y], pipeline.frag(&vs_out_lerped));
89 }
90 }
91 }
92 } else {
93 let (l_scr, r_scr) = if a_scr.y < b_scr.y {
94 (a_scr, b_scr)
95 } else {
96 (b_scr, a_scr)
97 };
98
99 let factor = 1.0 / (r_scr.y - l_scr.y);
100 let m = Mat2::new(pa.w, -pa.y, -ab.w, ab.y) / (ab.y * pa.w - pa.y * ab.w);
101
102 for y in l_scr.y as i32..r_scr.y as i32 {
103 let x = l_scr.x + (y as f32 - l_scr.y) * factor * (r_scr.x - l_scr.x);
104
105 if x < 0.0 || (x as usize) >= size.x || y < 0 || (y as usize) >= size.y {
107 continue;
108 }
109
110 let s_hom = m * Vec2::new(-2.0 * y as f32 / size.y as f32 + 1.0, 1.0);
112 let s = s_hom.x / s_hom.y;
113 let z_lerped = (pa.z + s * ab.z) * s_hom.y;
114
115 let (x, y) = (x as usize, y as usize);
116
117 if depth.as_ref().map(|depth| z_lerped < unsafe { depth.get([x, y]) }).unwrap_or(true) {
119 let vs_out_lerped =
121 P::VsOut::lerp2(a_vs_out.clone(), b_vs_out.clone(), 1.0 - s, s);
122
123 unsafe {
124 depth.as_mut().map(|depth| depth.set([x, y], z_lerped));
125 target.set([x, y], P::frag(pipeline, &vs_out_lerped));
126 }
127 }
128 }
129 }
130 });
131 }
132}