retrofire_core/render/
target.rs1use crate::math::vary::Vary;
8use crate::util::buf::AsMutSlice2;
9
10use super::{
11 ctx::Context, raster::Scanline, shader::FragmentShader, stats::Throughput,
12};
13
14pub trait Target {
16 fn rasterize<V, Fs>(
20 &mut self,
21 scanline: Scanline<V>,
22 frag_shader: &Fs,
23 ctx: &Context,
24 ) -> Throughput
25 where
26 V: Vary,
27 Fs: FragmentShader<V>;
28}
29
30#[derive(Clone)]
32pub struct Framebuf<Col, Dep> {
33 pub color_buf: Col,
34 pub depth_buf: Dep,
35}
36
37impl<Col, Dep> Target for Framebuf<Col, Dep>
38where
39 Col: AsMutSlice2<u32>,
40 Dep: AsMutSlice2<f32>,
41{
42 fn rasterize<V, Fs>(
44 &mut self,
45 mut sl: Scanline<V>,
46 fs: &Fs,
47 ctx: &Context,
48 ) -> Throughput
49 where
50 V: Vary,
51 Fs: FragmentShader<V>,
52 {
53 let x0 = sl.xs.start;
54 let x1 = sl.xs.end.max(x0);
55 let cbuf_span = &mut self.color_buf.as_mut_slice2()[sl.y][x0..x1];
56 let zbuf_span = &mut self.depth_buf.as_mut_slice2()[sl.y][x0..x1];
57
58 let mut io = Throughput { i: x1 - x0, o: 0 };
59
60 sl.fragments()
61 .zip(cbuf_span)
62 .zip(zbuf_span)
63 .for_each(|((frag, curr_col), curr_z)| {
64 let new_z = frag.pos.z();
65
66 if ctx.depth_test(new_z, *curr_z) {
67 if let Some(new_col) = fs.shade_fragment(frag) {
68 if ctx.color_write {
69 io.o += 1;
70 *curr_col = new_col.to_argb_u32();
72 }
73 if ctx.depth_write {
74 *curr_z = new_z;
75 }
76 }
77 }
78 });
79 io
80 }
81}
82
83impl<Buf: AsMutSlice2<u32>> Target for Buf {
84 fn rasterize<V, Fs>(
87 &mut self,
88 mut sl: Scanline<V>,
89 fs: &Fs,
90 ctx: &Context,
91 ) -> Throughput
92 where
93 V: Vary,
94 Fs: FragmentShader<V>,
95 {
96 let x0 = sl.xs.start;
97 let x1 = sl.xs.end.max(x0);
98 let mut io = Throughput { i: x1 - x0, o: 0 };
99 let cbuf_span = &mut self.as_mut_slice2()[sl.y][x0..x1];
100
101 sl.fragments()
102 .zip(cbuf_span)
103 .for_each(|(frag, c)| {
104 if let Some(color) = fs.shade_fragment(frag) {
105 if ctx.color_write {
106 io.o += 1;
107 *c = color.to_argb_u32();
108 }
109 }
110 });
111 io
112 }
113}