Skip to content

Commit c92394d

Browse files
committed
Now handling the extraction of ViewRenderPhases; refactored PhaseItemExt; added a derive macro for creating PhaseItem newtypes; fix the example.
1 parent b50dd30 commit c92394d

File tree

16 files changed

+999
-580
lines changed

16 files changed

+999
-580
lines changed

assets/shaders/custom_mesh_pass_material.wgsl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
#import bevy_pbr::mesh_functions::{get_world_from_local, mesh_position_local_to_clip}
1+
#import bevy_pbr::{
2+
mesh_functions::{get_world_from_local, mesh_position_local_to_clip}
3+
}
4+
5+
@group(#{MATERIAL_BIND_GROUP}) @binding(100) var<uniform> outline_color: vec4<f32>;
26

3-
@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<uniform> color: vec4<f32>;
4-
@group(#{MATERIAL_BIND_GROUP}) @binding(1) var<uniform> outline_color: vec4<f32>;
7+
const OUTLINE_WIDTH = 0.1;
58

69
struct Vertex {
710
@builtin(instance_index) instance_index: u32,
@@ -15,14 +18,18 @@ struct VertexOutput {
1518
@vertex
1619
fn vertex(vertex: Vertex) -> VertexOutput {
1720
var out: VertexOutput;
21+
22+
// This only works when the mesh is at the origin.
23+
let expanded_position = vertex.position * (1 + OUTLINE_WIDTH);
24+
1825
out.clip_position = mesh_position_local_to_clip(
1926
get_world_from_local(vertex.instance_index),
20-
vec4<f32>(vertex.position, 1.0),
27+
vec4<f32>(expanded_position, 1.0),
2128
);
2229
return out;
2330
}
2431

2532
@fragment
2633
fn fragment(input: VertexOutput) -> @location(0) vec4<f32> {
27-
return color;
34+
return outline_color;
2835
}

assets/shaders/custom_mesh_pass_outline_material.wgsl

Lines changed: 0 additions & 28 deletions
This file was deleted.

crates/bevy_core_pipeline/src/core_3d/mod.rs

Lines changed: 4 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,11 @@ use core::ops::Range;
7474

7575
use bevy_camera::{Camera, Camera3d, Camera3dDepthLoadOp};
7676
use bevy_render::{
77-
batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport},
7877
camera::CameraRenderGraph,
7978
experimental::occlusion_culling::OcclusionCulling,
8079
mesh::allocator::SlabId,
8180
render_phase::PhaseItemBatchSetKey,
82-
view::{prepare_view_targets, NoIndirectDrawing, RetainedViewEntity},
81+
view::{prepare_view_targets, NoIndirectDrawing},
8382
};
8483
pub use main_opaque_pass_3d_node::*;
8584
pub use main_transparent_pass_3d_node::*;
@@ -90,7 +89,7 @@ use bevy_color::LinearRgba;
9089
use bevy_ecs::prelude::*;
9190
use bevy_image::{BevyDefault, ToExtents};
9291
use bevy_math::FloatOrd;
93-
use bevy_platform::collections::{HashMap, HashSet};
92+
use bevy_platform::collections::HashMap;
9493
use bevy_render::{
9594
camera::ExtractedCamera,
9695
extract_component::ExtractComponentPlugin,
@@ -106,10 +105,10 @@ use bevy_render::{
106105
TextureDimension, TextureFormat, TextureUsages, TextureView,
107106
},
108107
renderer::RenderDevice,
109-
sync_world::{MainEntity, RenderEntity},
108+
sync_world::MainEntity,
110109
texture::{ColorAttachment, TextureCache},
111110
view::{ExtractedView, ViewDepthTexture, ViewTarget},
112-
Extract, ExtractSchedule, Render, RenderApp, RenderSystems,
111+
Render, RenderApp, RenderSystems,
113112
};
114113
use nonmax::NonMaxU32;
115114
use tracing::warn;
@@ -167,8 +166,6 @@ impl Plugin for Core3dPlugin {
167166
.init_resource::<ViewBinnedRenderPhases<AlphaMask3dDeferred>>()
168167
.init_resource::<ViewSortedRenderPhases<Transmissive3d>>()
169168
.init_resource::<ViewSortedRenderPhases<Transparent3d>>()
170-
.add_systems(ExtractSchedule, extract_core_3d_camera_phases)
171-
.add_systems(ExtractSchedule, extract_camera_prepass_phase)
172169
.add_systems(
173170
Render,
174171
(
@@ -616,159 +613,6 @@ impl CachedRenderPipelinePhaseItem for Transparent3d {
616613
}
617614
}
618615

619-
pub fn extract_core_3d_camera_phases(
620-
mut opaque_3d_phases: ResMut<ViewBinnedRenderPhases<Opaque3d>>,
621-
mut alpha_mask_3d_phases: ResMut<ViewBinnedRenderPhases<AlphaMask3d>>,
622-
mut transmissive_3d_phases: ResMut<ViewSortedRenderPhases<Transmissive3d>>,
623-
mut transparent_3d_phases: ResMut<ViewSortedRenderPhases<Transparent3d>>,
624-
cameras_3d: Extract<Query<(Entity, &Camera, Has<NoIndirectDrawing>), With<Camera3d>>>,
625-
mut live_entities: Local<HashSet<RetainedViewEntity>>,
626-
gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
627-
) {
628-
live_entities.clear();
629-
630-
for (main_entity, camera, no_indirect_drawing) in &cameras_3d {
631-
if !camera.is_active {
632-
continue;
633-
}
634-
635-
// If GPU culling is in use, use it (and indirect mode); otherwise, just
636-
// preprocess the meshes.
637-
let gpu_preprocessing_mode = gpu_preprocessing_support.min(if !no_indirect_drawing {
638-
GpuPreprocessingMode::Culling
639-
} else {
640-
GpuPreprocessingMode::PreprocessingOnly
641-
});
642-
643-
// This is the main 3D camera, so use the first subview index (0).
644-
let retained_view_entity = RetainedViewEntity::new(main_entity.into(), None, 0);
645-
646-
opaque_3d_phases.prepare_for_new_frame(retained_view_entity, gpu_preprocessing_mode);
647-
alpha_mask_3d_phases.prepare_for_new_frame(retained_view_entity, gpu_preprocessing_mode);
648-
transmissive_3d_phases.insert_or_clear(retained_view_entity);
649-
transparent_3d_phases.insert_or_clear(retained_view_entity);
650-
651-
live_entities.insert(retained_view_entity);
652-
}
653-
654-
opaque_3d_phases.retain(|view_entity, _| live_entities.contains(view_entity));
655-
alpha_mask_3d_phases.retain(|view_entity, _| live_entities.contains(view_entity));
656-
transmissive_3d_phases.retain(|view_entity, _| live_entities.contains(view_entity));
657-
transparent_3d_phases.retain(|view_entity, _| live_entities.contains(view_entity));
658-
}
659-
660-
// Extract the render phases for the prepass
661-
662-
pub fn extract_camera_prepass_phase(
663-
mut commands: Commands,
664-
mut opaque_3d_prepass_phases: ResMut<ViewBinnedRenderPhases<Opaque3dPrepass>>,
665-
mut alpha_mask_3d_prepass_phases: ResMut<ViewBinnedRenderPhases<AlphaMask3dPrepass>>,
666-
mut opaque_3d_deferred_phases: ResMut<ViewBinnedRenderPhases<Opaque3dDeferred>>,
667-
mut alpha_mask_3d_deferred_phases: ResMut<ViewBinnedRenderPhases<AlphaMask3dDeferred>>,
668-
cameras_3d: Extract<
669-
Query<
670-
(
671-
Entity,
672-
RenderEntity,
673-
&Camera,
674-
Has<NoIndirectDrawing>,
675-
Has<DepthPrepass>,
676-
Has<NormalPrepass>,
677-
Has<MotionVectorPrepass>,
678-
Has<DeferredPrepass>,
679-
),
680-
With<Camera3d>,
681-
>,
682-
>,
683-
mut live_entities: Local<HashSet<RetainedViewEntity>>,
684-
gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
685-
) {
686-
live_entities.clear();
687-
688-
for (
689-
main_entity,
690-
entity,
691-
camera,
692-
no_indirect_drawing,
693-
depth_prepass,
694-
normal_prepass,
695-
motion_vector_prepass,
696-
deferred_prepass,
697-
) in cameras_3d.iter()
698-
{
699-
if !camera.is_active {
700-
continue;
701-
}
702-
703-
// If GPU culling is in use, use it (and indirect mode); otherwise, just
704-
// preprocess the meshes.
705-
let gpu_preprocessing_mode = gpu_preprocessing_support.min(if !no_indirect_drawing {
706-
GpuPreprocessingMode::Culling
707-
} else {
708-
GpuPreprocessingMode::PreprocessingOnly
709-
});
710-
711-
// This is the main 3D camera, so we use the first subview index (0).
712-
let retained_view_entity = RetainedViewEntity::new(main_entity.into(), None, 0);
713-
714-
if depth_prepass || normal_prepass || motion_vector_prepass {
715-
opaque_3d_prepass_phases
716-
.prepare_for_new_frame(retained_view_entity, gpu_preprocessing_mode);
717-
alpha_mask_3d_prepass_phases
718-
.prepare_for_new_frame(retained_view_entity, gpu_preprocessing_mode);
719-
} else {
720-
opaque_3d_prepass_phases.remove(&retained_view_entity);
721-
alpha_mask_3d_prepass_phases.remove(&retained_view_entity);
722-
}
723-
724-
if deferred_prepass {
725-
opaque_3d_deferred_phases
726-
.prepare_for_new_frame(retained_view_entity, gpu_preprocessing_mode);
727-
alpha_mask_3d_deferred_phases
728-
.prepare_for_new_frame(retained_view_entity, gpu_preprocessing_mode);
729-
} else {
730-
opaque_3d_deferred_phases.remove(&retained_view_entity);
731-
alpha_mask_3d_deferred_phases.remove(&retained_view_entity);
732-
}
733-
live_entities.insert(retained_view_entity);
734-
735-
// Add or remove prepasses as appropriate.
736-
737-
let mut camera_commands = commands
738-
.get_entity(entity)
739-
.expect("Camera entity wasn't synced.");
740-
741-
if depth_prepass {
742-
camera_commands.insert(DepthPrepass);
743-
} else {
744-
camera_commands.remove::<DepthPrepass>();
745-
}
746-
747-
if normal_prepass {
748-
camera_commands.insert(NormalPrepass);
749-
} else {
750-
camera_commands.remove::<NormalPrepass>();
751-
}
752-
753-
if motion_vector_prepass {
754-
camera_commands.insert(MotionVectorPrepass);
755-
} else {
756-
camera_commands.remove::<MotionVectorPrepass>();
757-
}
758-
759-
if deferred_prepass {
760-
camera_commands.insert(DeferredPrepass);
761-
} else {
762-
camera_commands.remove::<DeferredPrepass>();
763-
}
764-
}
765-
766-
opaque_3d_prepass_phases.retain(|view_entity, _| live_entities.contains(view_entity));
767-
alpha_mask_3d_prepass_phases.retain(|view_entity, _| live_entities.contains(view_entity));
768-
opaque_3d_deferred_phases.retain(|view_entity, _| live_entities.contains(view_entity));
769-
alpha_mask_3d_deferred_phases.retain(|view_entity, _| live_entities.contains(view_entity));
770-
}
771-
772616
pub fn prepare_core_3d_depth_textures(
773617
mut commands: Commands,
774618
mut texture_cache: ResMut<TextureCache>,

crates/bevy_core_pipeline/src/prepass/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use bevy_asset::UntypedAssetId;
3434
use bevy_ecs::prelude::*;
3535
use bevy_math::Mat4;
3636
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
37+
use bevy_render::extract_component::ExtractComponent;
3738
use bevy_render::mesh::allocator::SlabId;
3839
use bevy_render::render_phase::PhaseItemBatchSetKey;
3940
use bevy_render::sync_world::MainEntity;
@@ -53,27 +54,27 @@ pub const NORMAL_PREPASS_FORMAT: TextureFormat = TextureFormat::Rgb10a2Unorm;
5354
pub const MOTION_VECTOR_PREPASS_FORMAT: TextureFormat = TextureFormat::Rg16Float;
5455

5556
/// If added to a [`bevy_camera::Camera3d`] then depth values will be copied to a separate texture available to the main pass.
56-
#[derive(Component, Default, Reflect, Clone)]
57+
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
5758
#[reflect(Component, Default, Clone)]
5859
pub struct DepthPrepass;
5960

6061
/// If added to a [`bevy_camera::Camera3d`] then vertex world normals will be copied to a separate texture available to the main pass.
6162
/// Normals will have normal map textures already applied.
62-
#[derive(Component, Default, Reflect, Clone)]
63+
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
6364
#[reflect(Component, Default, Clone)]
6465
pub struct NormalPrepass;
6566

6667
/// If added to a [`bevy_camera::Camera3d`] then screen space motion vectors will be copied to a separate texture available to the main pass.
6768
///
6869
/// Motion vectors are stored in the range -1,1, with +x right and +y down.
6970
/// A value of (1.0,1.0) indicates a pixel moved from the top left corner to the bottom right corner of the screen.
70-
#[derive(Component, Default, Reflect, Clone)]
71+
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
7172
#[reflect(Component, Default, Clone)]
7273
pub struct MotionVectorPrepass;
7374

7475
/// If added to a [`bevy_camera::Camera3d`] then deferred materials will be rendered to the deferred gbuffer texture and will be available to subsequent passes.
7576
/// Note the default deferred lighting plugin also requires `DepthPrepass` to work correctly.
76-
#[derive(Component, Default, Reflect)]
77+
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
7778
#[reflect(Component, Default)]
7879
pub struct DeferredPrepass;
7980

0 commit comments

Comments
 (0)