@@ -5,16 +5,17 @@ pub mod primitive;
55pub mod transform;
66
77use bevy:: {
8- camera:: visibility:: RenderLayers , ecs:: system:: SystemParam , math:: Affine3A , prelude:: * ,
8+ camera:: visibility:: RenderLayers ,
9+ ecs:: system:: SystemParam ,
10+ math:: { Affine3A , Mat4 , Vec4 } ,
11+ prelude:: * ,
912} ;
1013use command:: { CommandBuffer , DrawCommand } ;
1114use material:: MaterialKey ;
1215use primitive:: { TessellationMode , empty_mesh} ;
1316use transform:: TransformStack ;
1417
15- use crate :: {
16- Flush , geometry:: Geometry , graphics:: SurfaceSize , image:: Image , render:: primitive:: rect,
17- } ;
18+ use crate :: { Flush , geometry:: Geometry , image:: Image , render:: primitive:: rect} ;
1819
1920#[ derive( Component ) ]
2021#[ relationship( relationship_target = TransientMeshes ) ]
@@ -94,16 +95,26 @@ pub fn flush_draw_commands(
9495 & mut CommandBuffer ,
9596 & mut RenderState ,
9697 & RenderLayers ,
97- & SurfaceSize ,
98+ & Projection ,
99+ & Transform ,
98100 ) ,
99101 With < Flush > ,
100102 > ,
101103 p_images : Query < & Image > ,
102104 p_geometries : Query < & Geometry > ,
103105) {
104- for ( graphics_entity, mut cmd_buffer, mut state, render_layers, SurfaceSize ( width, height) ) in
105- graphics. iter_mut ( )
106+ for (
107+ graphics_entity,
108+ mut cmd_buffer,
109+ mut state,
110+ render_layers,
111+ projection,
112+ camera_transform,
113+ ) in graphics. iter_mut ( )
106114 {
115+ let clip_from_view = projection. get_clip_from_view ( ) ;
116+ let view_from_world = camera_transform. to_matrix ( ) . inverse ( ) ;
117+ let world_from_clip = ( clip_from_view * view_from_world) . inverse ( ) ;
107118 let draw_commands = std:: mem:: take ( & mut cmd_buffer. commands ) ;
108119 let mut batch = BatchState :: new ( graphics_entity, render_layers. clone ( ) ) ;
109120
@@ -143,18 +154,26 @@ pub fn flush_draw_commands(
143154 } ) ;
144155 }
145156 DrawCommand :: BackgroundColor ( color) => {
146- add_fill ( & mut res, & mut batch, & state, |mesh, _| {
147- rect (
148- mesh,
149- 0.0 ,
150- 0.0 ,
151- * width as f32 ,
152- * height as f32 ,
153- [ 0.0 ; 4 ] ,
154- color,
155- TessellationMode :: Fill ,
156- )
157- } ) ;
157+ flush_batch ( & mut res, & mut batch) ;
158+
159+ let mesh = create_ndc_background_quad ( world_from_clip, color, false ) ;
160+ let mesh_handle = res. meshes . add ( mesh) ;
161+
162+ let material_key = MaterialKey {
163+ transparent : color. alpha ( ) < 1.0 ,
164+ background_image : None ,
165+ } ;
166+ let material_handle = res. materials . add ( material_key. to_material ( ) ) ;
167+
168+ res. commands . spawn ( (
169+ Mesh3d ( mesh_handle) ,
170+ MeshMaterial3d ( material_handle) ,
171+ BelongsToGraphics ( batch. graphics_entity ) ,
172+ Transform :: IDENTITY ,
173+ batch. render_layers . clone ( ) ,
174+ ) ) ;
175+
176+ batch. draw_index += 1 ;
158177 }
159178 DrawCommand :: BackgroundImage ( entity) => {
160179 let Some ( p_image) = p_images. get ( entity) . ok ( ) else {
@@ -164,28 +183,24 @@ pub fn flush_draw_commands(
164183
165184 flush_batch ( & mut res, & mut batch) ;
166185
186+ let mesh = create_ndc_background_quad ( world_from_clip, Color :: WHITE , true ) ;
187+ let mesh_handle = res. meshes . add ( mesh) ;
188+
167189 let material_key = MaterialKey {
168190 transparent : false ,
169191 background_image : Some ( p_image. handle . clone ( ) ) ,
170192 } ;
193+ let material_handle = res. materials . add ( material_key. to_material ( ) ) ;
171194
172- batch. material_key = Some ( material_key) ;
173- batch. current_mesh = Some ( empty_mesh ( ) ) ;
174-
175- if let Some ( ref mut mesh) = batch. current_mesh {
176- rect (
177- mesh,
178- 0.0 ,
179- 0.0 ,
180- * width as f32 ,
181- * height as f32 ,
182- [ 0.0 ; 4 ] ,
183- Color :: WHITE ,
184- TessellationMode :: Fill ,
185- )
186- }
195+ res. commands . spawn ( (
196+ Mesh3d ( mesh_handle) ,
197+ MeshMaterial3d ( material_handle) ,
198+ BelongsToGraphics ( batch. graphics_entity ) ,
199+ Transform :: IDENTITY ,
200+ batch. render_layers . clone ( ) ,
201+ ) ) ;
187202
188- flush_batch ( & mut res , & mut batch ) ;
203+ batch . draw_index += 1 ;
189204 }
190205 DrawCommand :: PushMatrix => state. transform . push ( ) ,
191206 DrawCommand :: PopMatrix => state. transform . pop ( ) ,
@@ -348,3 +363,51 @@ fn flush_batch(res: &mut RenderResources, batch: &mut BatchState) {
348363 }
349364 batch. material_key = None ;
350365}
366+
367+ /// Creates a fullscreen quad by transforming NDC fullscreen by inverse of the clip-from-world matrix
368+ /// so that when the vertex shader applies clip_from_world, the vertices end up correctly back in
369+ /// NDC space.
370+ fn create_ndc_background_quad ( world_from_clip : Mat4 , color : Color , with_uvs : bool ) -> Mesh {
371+ use bevy:: asset:: RenderAssetUsages ;
372+ use bevy:: mesh:: { Indices , PrimitiveTopology } ;
373+
374+ let ndc_z = 0.001 ; // near far plane (bevy uses reverse-z)
375+ let ndc_corners = [
376+ Vec4 :: new ( -1.0 , -1.0 , ndc_z, 1.0 ) , // bl
377+ Vec4 :: new ( 1.0 , -1.0 , ndc_z, 1.0 ) , // br
378+ Vec4 :: new ( 1.0 , 1.0 , ndc_z, 1.0 ) , // tr
379+ Vec4 :: new ( -1.0 , 1.0 , ndc_z, 1.0 ) , // tl
380+ ] ;
381+
382+ let world_positions: Vec < [ f32 ; 3 ] > = ndc_corners
383+ . iter ( )
384+ . map ( |ndc| {
385+ let world = world_from_clip * * ndc;
386+ [ world. x / world. w , world. y / world. w , world. z / world. w ]
387+ } )
388+ . collect ( ) ;
389+
390+ let uvs: Vec < [ f32 ; 2 ] > = vec ! [
391+ [ 0.0 , 1.0 ] , // bl
392+ [ 1.0 , 1.0 ] , // br
393+ [ 1.0 , 0.0 ] , // tr
394+ [ 0.0 , 0.0 ] , // tl
395+ ] ;
396+
397+ let color_array: [ f32 ; 4 ] = color. to_linear ( ) . to_f32_array ( ) ;
398+ let colors: Vec < [ f32 ; 4 ] > = vec ! [ color_array; 4 ] ;
399+
400+ // two tris
401+ let indices: Vec < u32 > = vec ! [ 0 , 1 , 2 , 0 , 2 , 3 ] ;
402+
403+ let mut mesh = Mesh :: new ( PrimitiveTopology :: TriangleList , RenderAssetUsages :: default ( ) ) ;
404+
405+ mesh. insert_attribute ( Mesh :: ATTRIBUTE_POSITION , world_positions) ;
406+ mesh. insert_attribute ( Mesh :: ATTRIBUTE_COLOR , colors) ;
407+ if with_uvs {
408+ mesh. insert_attribute ( Mesh :: ATTRIBUTE_UV_0 , uvs) ;
409+ }
410+ mesh. insert_indices ( Indices :: U32 ( indices) ) ;
411+
412+ mesh
413+ }
0 commit comments