@@ -10,6 +10,9 @@ pub mod graph {
10
10
pub mod node {
11
11
pub const MSAA_WRITEBACK : & str = "msaa_writeback" ;
12
12
pub const PREPASS : & str = "prepass" ;
13
+ pub const DEFERRED_PREPASS : & str = "deferred_prepass" ;
14
+ pub const COPY_DEFERRED_LIGHTING_ID : & str = "copy_deferred_lighting_id" ;
15
+ pub const END_PREPASSES : & str = "end_prepasses" ;
13
16
pub const START_MAIN_PASS : & str = "start_main_pass" ;
14
17
pub const MAIN_OPAQUE_PASS : & str = "main_opaque_pass" ;
15
18
pub const MAIN_TRANSPARENT_PASS : & str = "main_transparent_pass" ;
@@ -24,13 +27,16 @@ pub mod graph {
24
27
}
25
28
pub const CORE_3D : & str = graph:: NAME ;
26
29
30
+ // PERF: vulkan docs recommend using 24 bit depth for better performance
31
+ pub const CORE_3D_DEPTH_FORMAT : TextureFormat = TextureFormat :: Depth32Float ;
32
+
27
33
use std:: { cmp:: Reverse , ops:: Range } ;
28
34
29
35
pub use camera_3d:: * ;
30
36
pub use main_opaque_pass_3d_node:: * ;
31
37
pub use main_transparent_pass_3d_node:: * ;
32
38
33
- use bevy_app:: { App , Plugin } ;
39
+ use bevy_app:: { App , Plugin , PostUpdate } ;
34
40
use bevy_ecs:: prelude:: * ;
35
41
use bevy_render:: {
36
42
camera:: { Camera , ExtractedCamera } ,
@@ -50,12 +56,17 @@ use bevy_render::{
50
56
view:: ViewDepthTexture ,
51
57
Extract , ExtractSchedule , Render , RenderApp , RenderSet ,
52
58
} ;
53
- use bevy_utils:: { nonmax:: NonMaxU32 , FloatOrd , HashMap } ;
59
+ use bevy_utils:: { nonmax:: NonMaxU32 , tracing :: warn , FloatOrd , HashMap } ;
54
60
55
61
use crate :: {
62
+ deferred:: {
63
+ copy_lighting_id:: CopyDeferredLightingIdNode , node:: DeferredGBufferPrepassNode ,
64
+ AlphaMask3dDeferred , Opaque3dDeferred , DEFERRED_LIGHTING_PASS_ID_FORMAT ,
65
+ DEFERRED_PREPASS_FORMAT ,
66
+ } ,
56
67
prepass:: {
57
- node:: PrepassNode , AlphaMask3dPrepass , DepthPrepass , MotionVectorPrepass , NormalPrepass ,
58
- Opaque3dPrepass , ViewPrepassTextures , DEPTH_PREPASS_FORMAT , MOTION_VECTOR_PREPASS_FORMAT ,
68
+ node:: PrepassNode , AlphaMask3dPrepass , DeferredPrepass , DepthPrepass , MotionVectorPrepass ,
69
+ NormalPrepass , Opaque3dPrepass , ViewPrepassTextures , MOTION_VECTOR_PREPASS_FORMAT ,
59
70
NORMAL_PREPASS_FORMAT ,
60
71
} ,
61
72
skybox:: SkyboxPlugin ,
@@ -69,7 +80,8 @@ impl Plugin for Core3dPlugin {
69
80
fn build ( & self , app : & mut App ) {
70
81
app. register_type :: < Camera3d > ( )
71
82
. register_type :: < Camera3dDepthLoadOp > ( )
72
- . add_plugins ( ( SkyboxPlugin , ExtractComponentPlugin :: < Camera3d > :: default ( ) ) ) ;
83
+ . add_plugins ( ( SkyboxPlugin , ExtractComponentPlugin :: < Camera3d > :: default ( ) ) )
84
+ . add_systems ( PostUpdate , check_msaa) ;
73
85
74
86
let render_app = match app. get_sub_app_mut ( RenderApp ) {
75
87
Ok ( render_app) => render_app,
@@ -82,6 +94,8 @@ impl Plugin for Core3dPlugin {
82
94
. init_resource :: < DrawFunctions < Transparent3d > > ( )
83
95
. init_resource :: < DrawFunctions < Opaque3dPrepass > > ( )
84
96
. init_resource :: < DrawFunctions < AlphaMask3dPrepass > > ( )
97
+ . init_resource :: < DrawFunctions < Opaque3dDeferred > > ( )
98
+ . init_resource :: < DrawFunctions < AlphaMask3dDeferred > > ( )
85
99
. add_systems ( ExtractSchedule , extract_core_3d_camera_phases)
86
100
. add_systems ( ExtractSchedule , extract_camera_prepass_phase)
87
101
. add_systems (
@@ -92,6 +106,8 @@ impl Plugin for Core3dPlugin {
92
106
sort_phase_system :: < Transparent3d > . in_set ( RenderSet :: PhaseSort ) ,
93
107
sort_phase_system :: < Opaque3dPrepass > . in_set ( RenderSet :: PhaseSort ) ,
94
108
sort_phase_system :: < AlphaMask3dPrepass > . in_set ( RenderSet :: PhaseSort ) ,
109
+ sort_phase_system :: < Opaque3dDeferred > . in_set ( RenderSet :: PhaseSort ) ,
110
+ sort_phase_system :: < AlphaMask3dDeferred > . in_set ( RenderSet :: PhaseSort ) ,
95
111
prepare_core_3d_depth_textures. in_set ( RenderSet :: PrepareResources ) ,
96
112
prepare_prepass_textures. in_set ( RenderSet :: PrepareResources ) ,
97
113
) ,
@@ -101,6 +117,15 @@ impl Plugin for Core3dPlugin {
101
117
render_app
102
118
. add_render_sub_graph ( CORE_3D )
103
119
. add_render_graph_node :: < ViewNodeRunner < PrepassNode > > ( CORE_3D , PREPASS )
120
+ . add_render_graph_node :: < ViewNodeRunner < DeferredGBufferPrepassNode > > (
121
+ CORE_3D ,
122
+ DEFERRED_PREPASS ,
123
+ )
124
+ . add_render_graph_node :: < ViewNodeRunner < CopyDeferredLightingIdNode > > (
125
+ CORE_3D ,
126
+ COPY_DEFERRED_LIGHTING_ID ,
127
+ )
128
+ . add_render_graph_node :: < EmptyNode > ( CORE_3D , END_PREPASSES )
104
129
. add_render_graph_node :: < EmptyNode > ( CORE_3D , START_MAIN_PASS )
105
130
. add_render_graph_node :: < ViewNodeRunner < MainOpaquePass3dNode > > (
106
131
CORE_3D ,
@@ -118,6 +143,9 @@ impl Plugin for Core3dPlugin {
118
143
CORE_3D ,
119
144
& [
120
145
PREPASS ,
146
+ DEFERRED_PREPASS ,
147
+ COPY_DEFERRED_LIGHTING_ID ,
148
+ END_PREPASSES ,
121
149
START_MAIN_PASS ,
122
150
MAIN_OPAQUE_PASS ,
123
151
MAIN_TRANSPARENT_PASS ,
@@ -341,12 +369,14 @@ pub fn extract_camera_prepass_phase(
341
369
Option < & DepthPrepass > ,
342
370
Option < & NormalPrepass > ,
343
371
Option < & MotionVectorPrepass > ,
372
+ Option < & DeferredPrepass > ,
344
373
) ,
345
374
With < Camera3d > ,
346
375
> ,
347
376
> ,
348
377
) {
349
- for ( entity, camera, depth_prepass, normal_prepass, motion_vector_prepass) in cameras_3d. iter ( )
378
+ for ( entity, camera, depth_prepass, normal_prepass, motion_vector_prepass, deferred_prepass) in
379
+ cameras_3d. iter ( )
350
380
{
351
381
if camera. is_active {
352
382
let mut entity = commands. get_or_spawn ( entity) ;
@@ -361,6 +391,13 @@ pub fn extract_camera_prepass_phase(
361
391
) ) ;
362
392
}
363
393
394
+ if deferred_prepass. is_some ( ) {
395
+ entity. insert ( (
396
+ RenderPhase :: < Opaque3dDeferred > :: default ( ) ,
397
+ RenderPhase :: < AlphaMask3dDeferred > :: default ( ) ,
398
+ ) ) ;
399
+ }
400
+
364
401
if depth_prepass. is_some ( ) {
365
402
entity. insert ( DepthPrepass ) ;
366
403
}
@@ -370,6 +407,9 @@ pub fn extract_camera_prepass_phase(
370
407
if motion_vector_prepass. is_some ( ) {
371
408
entity. insert ( MotionVectorPrepass ) ;
372
409
}
410
+ if deferred_prepass. is_some ( ) {
411
+ entity. insert ( DeferredPrepass ) ;
412
+ }
373
413
}
374
414
}
375
415
}
@@ -428,8 +468,7 @@ pub fn prepare_core_3d_depth_textures(
428
468
mip_level_count : 1 ,
429
469
sample_count : msaa. samples ( ) ,
430
470
dimension : TextureDimension :: D2 ,
431
- // PERF: vulkan docs recommend using 24 bit depth for better performance
432
- format : TextureFormat :: Depth32Float ,
471
+ format : CORE_3D_DEPTH_FORMAT ,
433
472
usage,
434
473
view_formats : & [ ] ,
435
474
} ;
@@ -445,6 +484,22 @@ pub fn prepare_core_3d_depth_textures(
445
484
}
446
485
}
447
486
487
+ // Disable MSAA and warn if using deferred rendering
488
+ pub fn check_msaa (
489
+ mut msaa : ResMut < Msaa > ,
490
+ deferred_views : Query < Entity , ( With < Camera > , With < DeferredPrepass > ) > ,
491
+ ) {
492
+ if !deferred_views. is_empty ( ) {
493
+ match * msaa {
494
+ Msaa :: Off => ( ) ,
495
+ _ => {
496
+ warn ! ( "MSAA is incompatible with deferred rendering and has been disabled." ) ;
497
+ * msaa = Msaa :: Off ;
498
+ }
499
+ } ;
500
+ }
501
+ }
502
+
448
503
// Prepares the textures used by the prepass
449
504
pub fn prepare_prepass_textures (
450
505
mut commands : Commands ,
@@ -458,6 +513,7 @@ pub fn prepare_prepass_textures(
458
513
Option < & DepthPrepass > ,
459
514
Option < & NormalPrepass > ,
460
515
Option < & MotionVectorPrepass > ,
516
+ Option < & DeferredPrepass > ,
461
517
) ,
462
518
(
463
519
With < RenderPhase < Opaque3dPrepass > > ,
@@ -467,8 +523,12 @@ pub fn prepare_prepass_textures(
467
523
) {
468
524
let mut depth_textures = HashMap :: default ( ) ;
469
525
let mut normal_textures = HashMap :: default ( ) ;
526
+ let mut deferred_textures = HashMap :: default ( ) ;
527
+ let mut deferred_lighting_id_textures = HashMap :: default ( ) ;
470
528
let mut motion_vectors_textures = HashMap :: default ( ) ;
471
- for ( entity, camera, depth_prepass, normal_prepass, motion_vector_prepass) in & views_3d {
529
+ for ( entity, camera, depth_prepass, normal_prepass, motion_vector_prepass, deferred_prepass) in
530
+ & views_3d
531
+ {
472
532
let Some ( physical_target_size) = camera. physical_target_size else {
473
533
continue ;
474
534
} ;
@@ -489,7 +549,7 @@ pub fn prepare_prepass_textures(
489
549
mip_level_count : 1 ,
490
550
sample_count : msaa. samples ( ) ,
491
551
dimension : TextureDimension :: D2 ,
492
- format : DEPTH_PREPASS_FORMAT ,
552
+ format : CORE_3D_DEPTH_FORMAT ,
493
553
usage : TextureUsages :: COPY_DST
494
554
| TextureUsages :: RENDER_ATTACHMENT
495
555
| TextureUsages :: TEXTURE_BINDING ,
@@ -544,10 +604,56 @@ pub fn prepare_prepass_textures(
544
604
. clone ( )
545
605
} ) ;
546
606
607
+ let cached_deferred_texture = deferred_prepass. is_some ( ) . then ( || {
608
+ deferred_textures
609
+ . entry ( camera. target . clone ( ) )
610
+ . or_insert_with ( || {
611
+ texture_cache. get (
612
+ & render_device,
613
+ TextureDescriptor {
614
+ label : Some ( "prepass_deferred_texture" ) ,
615
+ size,
616
+ mip_level_count : 1 ,
617
+ sample_count : 1 ,
618
+ dimension : TextureDimension :: D2 ,
619
+ format : DEFERRED_PREPASS_FORMAT ,
620
+ usage : TextureUsages :: RENDER_ATTACHMENT
621
+ | TextureUsages :: TEXTURE_BINDING ,
622
+ view_formats : & [ ] ,
623
+ } ,
624
+ )
625
+ } )
626
+ . clone ( )
627
+ } ) ;
628
+
629
+ let deferred_lighting_pass_id_texture = deferred_prepass. is_some ( ) . then ( || {
630
+ deferred_lighting_id_textures
631
+ . entry ( camera. target . clone ( ) )
632
+ . or_insert_with ( || {
633
+ texture_cache. get (
634
+ & render_device,
635
+ TextureDescriptor {
636
+ label : Some ( "deferred_lighting_pass_id_texture" ) ,
637
+ size,
638
+ mip_level_count : 1 ,
639
+ sample_count : 1 ,
640
+ dimension : TextureDimension :: D2 ,
641
+ format : DEFERRED_LIGHTING_PASS_ID_FORMAT ,
642
+ usage : TextureUsages :: RENDER_ATTACHMENT
643
+ | TextureUsages :: TEXTURE_BINDING ,
644
+ view_formats : & [ ] ,
645
+ } ,
646
+ )
647
+ } )
648
+ . clone ( )
649
+ } ) ;
650
+
547
651
commands. entity ( entity) . insert ( ViewPrepassTextures {
548
652
depth : cached_depth_texture,
549
653
normal : cached_normals_texture,
550
654
motion_vectors : cached_motion_vectors_texture,
655
+ deferred : cached_deferred_texture,
656
+ deferred_lighting_pass_id : deferred_lighting_pass_id_texture,
551
657
size,
552
658
} ) ;
553
659
}
0 commit comments