1use alloc::vec::Vec;
4use core::borrow::Borrow;
5
6use crate::{
7 geom::{Mesh, Tri, Vertex3},
8 math::{Mat4x4, Vary},
9};
10
11use super::{Clip, Context, NdcToScreen, Render, Shader, Target};
12
13#[derive(Clone, Debug, Default)]
33pub struct Batch<Prim, Vtx, Uni, Shd, Tgt, Ctx> {
34 prims: Vec<Prim>,
35 verts: Vec<Vtx>,
36 uniform: Uni,
37 shader: Shd,
38 viewport: Mat4x4<NdcToScreen>,
39 target: Tgt,
40 ctx: Ctx,
41}
42
43macro_rules! update {
44 ($($upd:ident)+ ; $self:ident $($rest:ident)+) => {{
45 let Self { $($upd: _, )+ $($rest, )+ } = $self;
46 Batch { $($upd, )+ $($rest, )+ }
47 }};
48}
49
50impl Batch<(), (), (), (), (), Context> {
51 pub fn new() -> Self {
52 Self::default()
53 }
54}
55
56impl<Prim, Vtx, Uni, Shd, Tgt, Ctx> Batch<Prim, Vtx, Uni, Shd, Tgt, Ctx> {
57 pub fn primitives<P: Clone>(
61 self,
62 prims: impl AsRef<[P]>,
63 ) -> Batch<P, Vtx, Uni, Shd, Tgt, Ctx> {
64 let prims = prims.as_ref().to_vec();
65 update!(prims; self verts uniform shader viewport target ctx)
66 }
67
68 pub fn vertices<V: Clone>(
73 self,
74 verts: impl AsRef<[V]>,
75 ) -> Batch<Prim, V, Uni, Shd, Tgt, Ctx> {
76 let verts = verts.as_ref().to_vec();
77 update!(verts; self prims uniform shader viewport target ctx)
78 }
79
80 pub fn mesh<A: Clone>(
82 self,
83 mesh: &Mesh<A>,
84 ) -> Batch<Tri<usize>, Vertex3<A>, Uni, Shd, Tgt, Ctx> {
85 let prims = mesh.faces.clone();
86 let verts = mesh.verts.clone();
87 update!(verts prims; self uniform shader viewport target ctx)
88 }
89
90 pub fn uniform<U: Copy>(
92 self,
93 uniform: U,
94 ) -> Batch<Prim, Vtx, U, Shd, Tgt, Ctx> {
95 update!(uniform; self verts prims shader viewport target ctx)
96 }
97
98 pub fn shader<V: Vary, U, S: Shader<Vtx, V, U>>(
100 self,
101 shader: S,
102 ) -> Batch<Prim, Vtx, Uni, S, Tgt, Ctx> {
103 update!(shader; self verts prims uniform viewport target ctx)
104 }
105
106 pub fn viewport(self, viewport: Mat4x4<NdcToScreen>) -> Self {
108 update!(viewport; self verts prims uniform shader target ctx)
109 }
110
111 pub fn target<T>(self, target: T) -> Batch<Prim, Vtx, Uni, Shd, T, Ctx> {
114 update!(target; self verts prims uniform shader viewport ctx)
115 }
116
117 pub fn context(
119 self,
120 ctx: &Context,
121 ) -> Batch<Prim, Vtx, Uni, Shd, Tgt, &Context> {
122 update!(ctx; self verts prims uniform shader viewport target)
123 }
124}
125
126impl<Prim, Vtx, Uni, Shd, Tgt, Ctx> Batch<Prim, Vtx, Uni, Shd, &mut Tgt, Ctx> {
127 #[rustfmt::skip]
129 pub fn render<Var>(&mut self)
130 where
131 Var: Vary,
132 Prim: Render<Var> + Clone,
133 Vtx: Clone,
134 Uni: Copy,
135 [<Prim>::Clip]: Clip<Item= Prim::Clip>,
136 Shd: Shader<Vtx, Var, Uni>,
137 Tgt: Target,
138 Ctx: Borrow<Context>
139 {
140 let Self {
141 prims, verts, shader, uniform, viewport, target, ctx,
142 } = self;
143
144 super::render(
145 prims, verts, shader, *uniform, *viewport, *target,
146 (*ctx).borrow(),
147 );
148 }
149}