@@ -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,20 @@ 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
106+ for ( graphics_entity, mut cmd_buffer, mut state, render_layers, projection , camera_transform ) in
105107 graphics. iter_mut ( )
106108 {
109+ let clip_from_view = projection. get_clip_from_view ( ) ;
110+ let view_from_world = camera_transform. to_matrix ( ) . inverse ( ) ;
111+ let world_from_clip = ( clip_from_view * view_from_world) . inverse ( ) ;
107112 let draw_commands = std:: mem:: take ( & mut cmd_buffer. commands ) ;
108113 let mut batch = BatchState :: new ( graphics_entity, render_layers. clone ( ) ) ;
109114
@@ -143,18 +148,26 @@ pub fn flush_draw_commands(
143148 } ) ;
144149 }
145150 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- } ) ;
151+ flush_batch ( & mut res, & mut batch) ;
152+
153+ let mesh = create_ndc_background_quad ( world_from_clip, color, false ) ;
154+ let mesh_handle = res. meshes . add ( mesh) ;
155+
156+ let material_key = MaterialKey {
157+ transparent : color. alpha ( ) < 1.0 ,
158+ background_image : None ,
159+ } ;
160+ let material_handle = res. materials . add ( material_key. to_material ( ) ) ;
161+
162+ res. commands . spawn ( (
163+ Mesh3d ( mesh_handle) ,
164+ MeshMaterial3d ( material_handle) ,
165+ BelongsToGraphics ( batch. graphics_entity ) ,
166+ Transform :: IDENTITY ,
167+ batch. render_layers . clone ( ) ,
168+ ) ) ;
169+
170+ batch. draw_index += 1 ;
158171 }
159172 DrawCommand :: BackgroundImage ( entity) => {
160173 let Some ( p_image) = p_images. get ( entity) . ok ( ) else {
@@ -164,28 +177,24 @@ pub fn flush_draw_commands(
164177
165178 flush_batch ( & mut res, & mut batch) ;
166179
180+ let mesh = create_ndc_background_quad ( world_from_clip, Color :: WHITE , true ) ;
181+ let mesh_handle = res. meshes . add ( mesh) ;
182+
167183 let material_key = MaterialKey {
168184 transparent : false ,
169185 background_image : Some ( p_image. handle . clone ( ) ) ,
170186 } ;
187+ let material_handle = res. materials . add ( material_key. to_material ( ) ) ;
171188
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- }
189+ res. commands . spawn ( (
190+ Mesh3d ( mesh_handle) ,
191+ MeshMaterial3d ( material_handle) ,
192+ BelongsToGraphics ( batch. graphics_entity ) ,
193+ Transform :: IDENTITY ,
194+ batch. render_layers . clone ( ) ,
195+ ) ) ;
187196
188- flush_batch ( & mut res , & mut batch ) ;
197+ batch . draw_index += 1 ;
189198 }
190199 DrawCommand :: PushMatrix => state. transform . push ( ) ,
191200 DrawCommand :: PopMatrix => state. transform . pop ( ) ,
@@ -348,3 +357,54 @@ fn flush_batch(res: &mut RenderResources, batch: &mut BatchState) {
348357 }
349358 batch. material_key = None ;
350359}
360+
361+ /// Creates a fullscreen quad by transforming NDC fullscreen by inverse of the clip-from-world matrix
362+ /// so that when the vertex shader applies clip_from_world, the vertices end up correctly back in
363+ /// NDC space.
364+ fn create_ndc_background_quad ( world_from_clip : Mat4 , color : Color , with_uvs : bool ) -> Mesh {
365+ use bevy:: asset:: RenderAssetUsages ;
366+ use bevy:: mesh:: { Indices , PrimitiveTopology } ;
367+
368+ let ndc_z = 0.001 ; // near far plane (bevy uses reverse-z)
369+ let ndc_corners = [
370+ Vec4 :: new ( -1.0 , -1.0 , ndc_z, 1.0 ) , // bl
371+ Vec4 :: new ( 1.0 , -1.0 , ndc_z, 1.0 ) , // br
372+ Vec4 :: new ( 1.0 , 1.0 , ndc_z, 1.0 ) , // tr
373+ Vec4 :: new ( -1.0 , 1.0 , ndc_z, 1.0 ) , // tl
374+ ] ;
375+
376+ let world_positions: Vec < [ f32 ; 3 ] > = ndc_corners
377+ . iter ( )
378+ . map ( |ndc| {
379+ let world = world_from_clip * * ndc;
380+ [ world. x / world. w , world. y / world. w , world. z / world. w ]
381+ } )
382+ . collect ( ) ;
383+
384+ let uvs: Vec < [ f32 ; 2 ] > = vec ! [
385+ [ 0.0 , 1.0 ] , // bl
386+ [ 1.0 , 1.0 ] , // br
387+ [ 1.0 , 0.0 ] , // tr
388+ [ 0.0 , 0.0 ] , // tl
389+ ] ;
390+
391+ let color_array: [ f32 ; 4 ] = color. to_linear ( ) . to_f32_array ( ) ;
392+ let colors: Vec < [ f32 ; 4 ] > = vec ! [ color_array; 4 ] ;
393+
394+ // two tris
395+ let indices: Vec < u32 > = vec ! [ 0 , 1 , 2 , 0 , 2 , 3 ] ;
396+
397+ let mut mesh = Mesh :: new (
398+ PrimitiveTopology :: TriangleList ,
399+ RenderAssetUsages :: default ( ) ,
400+ ) ;
401+
402+ mesh. insert_attribute ( Mesh :: ATTRIBUTE_POSITION , world_positions) ;
403+ mesh. insert_attribute ( Mesh :: ATTRIBUTE_COLOR , colors) ;
404+ if with_uvs {
405+ mesh. insert_attribute ( Mesh :: ATTRIBUTE_UV_0 , uvs) ;
406+ }
407+ mesh. insert_indices ( Indices :: U32 ( indices) ) ;
408+
409+ mesh
410+ }
0 commit comments