@@ -85,8 +85,17 @@ impl<S, Vtx, Var, Uni> Shader<Vtx, Var, Uni> for S where
8585{
8686}
8787
88- pub fn render_lines < Vtx : Clone , Var : Lerp + Vary , Uni : Copy , Shd > (
89- lines : impl AsRef < [ [ usize ; 2 ] ] > ,
88+ fn start_stats ( prims : usize , verts : usize ) -> Stats {
89+ let mut s = Stats :: start ( ) ;
90+ s. calls = 1.0 ;
91+ s. prims . i = prims;
92+ s. verts . i = verts;
93+ s
94+ }
95+
96+ /// Renders the given triangles into `target`.
97+ pub fn render < Vtx : Clone , Var : Lerp + Vary , Uni : Copy , Shd > (
98+ tris : impl AsRef < [ Tri < usize > ] > ,
9099 verts : impl AsRef < [ Vtx ] > ,
91100 shader : & Shd ,
92101 uniform : Uni ,
@@ -96,67 +105,58 @@ pub fn render_lines<Vtx: Clone, Var: Lerp + Vary, Uni: Copy, Shd>(
96105) where
97106 Shd : Shader < Vtx , Var , Uni > ,
98107{
108+ let tris = tris. as_ref ( ) ;
99109 let verts = verts. as_ref ( ) ;
100- let lines = lines. as_ref ( ) ;
101- let mut stats = Stats :: start ( ) ;
102110
103- stats. calls = 1.0 ;
104- stats. prims . i += lines. len ( ) ;
105- stats. verts . i += verts. len ( ) ;
111+ let mut stats = start_stats ( tris. len ( ) , verts. len ( ) ) ;
106112
107113 // Vertex shader: transform vertices to clip space
108- let verts: Vec < _ > = verts
109- . iter ( )
110- // TODO Pass vertex as ref to shader
111- . cloned ( )
112- . map ( |v| shader. shade_vertex ( v, uniform) )
113- . map ( ClipVert :: new)
114- . collect ( ) ;
114+ let verts = transform ( verts, shader, uniform) ;
115115
116116 // Map triangle vertex indices to actual vertices
117- let lines: Vec < _ > = lines
117+ // TODO This needlessly collects soon-to-be-culled triangles
118+ let tris: Vec < _ > = tris
118119 . iter ( )
119- . map ( |vs| vs. map ( |i| verts[ i] . clone ( ) ) )
120+ . map ( |Tri ( vs ) | Tri ( vs. map ( |i| verts[ i] . clone ( ) ) ) )
120121 . collect ( ) ;
121122
122123 // Clip against the view frustum
123124 let mut clipped = vec ! [ ] ;
124- view_frustum:: clip ( & lines [ ..] , & mut clipped) ;
125+ view_frustum:: clip ( & tris [ ..] , & mut clipped) ;
125126
126- for vs in clipped {
127+ // Optional depth sorting for use case such as transparency
128+ if let Some ( d) = ctx. depth_sort {
129+ depth_sort ( & mut clipped, d) ;
130+ }
131+
132+ for Tri ( vs) in clipped {
127133 // Transform to screen space
128- let vs = vs. map ( |v| {
129- let [ x, y, _, w] = v. pos . 0 ;
130- // Perspective division (projection to the real plane)
131- //
132- // We use the screen-space z coordinate to store the reciprocal
133- // of the original view-space depth. The interpolated reciprocal
134- // is used in fragment processing for depth testing (larger values
135- // are closer) and for perspective correction of the varyings.
136- let pos = vec3 ( x, y, 1.0 ) . z_div ( w) ;
137- Vertex {
138- // Viewport transform
139- pos : to_screen. apply ( & pos) . to_pt ( ) ,
140- // Perspective correction
141- attrib : v. attrib . z_div ( w) ,
142- }
143- } ) ;
134+ let vs = project ( vs, to_screen) ;
135+
136+ // Back/frontface culling
137+ //
138+ // TODO This could also be done earlier, before or as part of clipping
139+ match ctx. face_cull {
140+ Some ( FaceCull :: Back ) if is_backface ( & vs) => continue ,
141+ Some ( FaceCull :: Front ) if !is_backface ( & vs) => continue ,
142+ _ => { }
143+ }
144144
145145 // Log output stats after culling
146146 stats. prims . o += 1 ;
147147 stats. verts . o += 3 ;
148148
149149 // Fragment shader and rasterization
150- line ( vs, |scanline| {
150+ tri_fill ( vs, |scanline| {
151151 // Convert to fragments and shade
152152 stats. frags += target. rasterize ( scanline, uniform, shader, ctx) ;
153153 } ) ;
154154 }
155155 * ctx. stats . borrow_mut ( ) += stats. finish ( ) ;
156156}
157- /// Renders the given triangles into `target`.
158- pub fn render < Vtx : Clone , Var : Lerp + Vary , Uni : Copy , Shd > (
159- tris : impl AsRef < [ Tri < usize > ] > ,
157+
158+ pub fn render_lines < Vtx : Clone , Var : Lerp + Vary , Uni : Copy , Shd > (
159+ lines : impl AsRef < [ [ usize ; 2 ] ] > ,
160160 verts : impl AsRef < [ Vtx ] > ,
161161 shader : & Shd ,
162162 uniform : Uni ,
@@ -166,83 +166,84 @@ pub fn render<Vtx: Clone, Var: Lerp + Vary, Uni: Copy, Shd>(
166166) where
167167 Shd : Shader < Vtx , Var , Uni > ,
168168{
169+ let lines = lines. as_ref ( ) ;
169170 let verts = verts. as_ref ( ) ;
170- let tris = tris. as_ref ( ) ;
171- let mut stats = Stats :: start ( ) ;
172171
173- stats. calls = 1.0 ;
174- stats. prims . i += tris. len ( ) ;
175- stats. verts . i += verts. len ( ) ;
172+ let mut stats = start_stats ( lines. len ( ) , verts. len ( ) ) ;
176173
177174 // Vertex shader: transform vertices to clip space
178- let verts: Vec < _ > = verts
179- . iter ( )
180- // TODO Pass vertex as ref to shader
181- . cloned ( )
182- . map ( |v| shader. shade_vertex ( v, uniform) )
183- . map ( ClipVert :: new)
184- . collect ( ) ;
175+ let verts = transform ( verts, shader, uniform) ;
185176
186- // Map triangle vertex indices to actual vertices
187- let tris : Vec < _ > = tris
177+ // Map vertex indices to actual vertices
178+ let lines : Vec < _ > = lines
188179 . iter ( )
189- . map ( |Tri ( vs ) | Tri ( vs. map ( |i| verts[ i] . clone ( ) ) ) )
180+ . map ( |vs| vs. map ( |i| verts[ i] . clone ( ) ) )
190181 . collect ( ) ;
191182
192183 // Clip against the view frustum
193184 let mut clipped = vec ! [ ] ;
194- view_frustum:: clip ( & tris[ ..] , & mut clipped) ;
195-
196- // Optional depth sorting for use case such as transparency
197- if let Some ( d) = ctx. depth_sort {
198- depth_sort ( & mut clipped, d) ;
199- }
185+ view_frustum:: clip ( & lines[ ..] , & mut clipped) ;
200186
201- for Tri ( vs ) in clipped {
187+ for vs in clipped {
202188 // Transform to screen space
203- let vs = vs. map ( |v| {
204- let [ x, y, _, w] = v. pos . 0 ;
205- // Perspective division (projection to the real plane)
206- //
207- // We use the screen-space z coordinate to store the reciprocal
208- // of the original view-space depth. The interpolated reciprocal
209- // is used in fragment processing for depth testing (larger values
210- // are closer) and for perspective correction of the varyings.
211- let pos = vec3 ( x, y, 1.0 ) . z_div ( w) ;
212- Vertex {
213- // Viewport transform
214- pos : to_screen. apply ( & pos) . to_pt ( ) ,
215- // Perspective correction
216- attrib : v. attrib . z_div ( w) ,
217- }
218- } ) ;
219-
220- // Back/frontface culling
221- //
222- // TODO This could also be done earlier, before or as part of clipping
223- match ctx. face_cull {
224- Some ( FaceCull :: Back ) if is_backface ( & vs) => continue ,
225- Some ( FaceCull :: Front ) if !is_backface ( & vs) => continue ,
226- _ => { }
227- }
189+ let vs = project ( vs, to_screen) ;
228190
229191 // Log output stats after culling
230192 stats. prims . o += 1 ;
231193 stats. verts . o += 3 ;
232194
233195 // Fragment shader and rasterization
234- tri_fill ( vs, |scanline| {
196+ line ( vs, |scanline| {
235197 // Convert to fragments and shade
236198 stats. frags += target. rasterize ( scanline, uniform, shader, ctx) ;
237199 } ) ;
238200 }
239201 * ctx. stats . borrow_mut ( ) += stats. finish ( ) ;
240202}
241203
204+ fn transform < ' a , I , S , U , V , A > ( verts : I , shd : & S , uni : U ) -> Vec < ClipVert < A > >
205+ where
206+ I : IntoIterator < Item = & ' a V > ,
207+ S : VertexShader < V , U , Output = Vertex < ProjVec4 , A > > ,
208+ U : Copy ,
209+ V : Clone + ' a ,
210+ {
211+ verts
212+ . into_iter ( )
213+ . cloned ( )
214+ // TODO Pass vertex as ref to shader
215+ . map ( |v| shd. shade_vertex ( v, uni) )
216+ . map ( ClipVert :: new)
217+ . collect ( )
218+ }
219+
220+ fn project < A : ZDiv , const N : usize > (
221+ vs : [ ClipVert < A > ; N ] ,
222+ to_screen : Mat4x4 < NdcToScreen > ,
223+ ) -> [ Vertex < ScreenPt , A > ; N ] {
224+ vs. map ( |v| {
225+ let [ x, y, _, w] = v. pos . 0 ;
226+ // Perspective division (projection to the real plane)
227+ //
228+ // We use the screen-space z coordinate to store the reciprocal
229+ // of the original view-space depth. The interpolated reciprocal
230+ // is used in fragment processing for depth testing (larger values
231+ // are closer) and for perspective correction of the varyings.
232+ let pos = vec3 ( x, y, 1.0 ) . z_div ( w) ;
233+ Vertex {
234+ // Viewport transform
235+ pos : to_screen. apply ( & pos) . to_pt ( ) ,
236+ // Perspective correction
237+ attrib : v. attrib . z_div ( w) ,
238+ }
239+ } )
240+ }
241+
242+ /// Sorts triangles by depth.
242243fn depth_sort < A > ( tris : & mut [ Tri < ClipVert < A > > ] , d : DepthSort ) {
243- tris. sort_unstable_by ( |t , u | {
244- let z = t . 0 [ 0 ] . pos . z ( ) + t . 0 [ 1 ] . pos . z ( ) + t . 0 [ 2 ] . pos . z ( ) ;
245- let w = u . 0 [ 0 ] . pos . z ( ) + u . 0 [ 1 ] . pos . z ( ) + u . 0 [ 2 ] . pos . z ( ) ;
244+ tris. sort_unstable_by ( |Tri ( vs ) , Tri ( us ) | {
245+ let z = vs [ 0 ] . pos . z ( ) + vs [ 1 ] . pos . z ( ) + vs [ 2 ] . pos . z ( ) ;
246+ let w = us [ 0 ] . pos . z ( ) + us [ 1 ] . pos . z ( ) + us [ 2 ] . pos . z ( ) ;
246247 if d == DepthSort :: FrontToBack {
247248 z. total_cmp ( & w)
248249 } else {
0 commit comments