Skip to content

Commit 30fe6c4

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

File tree

13 files changed

+827
-305
lines changed

13 files changed

+827
-305
lines changed

assets/shaders/custom_mesh_pass_material.wgsl

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
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+
6+
//forward_io::{Vertex, VertexOutput, FragmentOutput},
7+
8+
// struct OutlineMaterial {
9+
// outline_color: vec4<f32>,
10+
// }
11+
// @group(#{MATERIAL_BIND_GROUP}) @binding(100)
12+
// var<uniform> outline_material: OutlineMaterial;
13+
@group(#{MATERIAL_BIND_GROUP}) @binding(100) var<uniform> outline_color: vec4<f32>;
214

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>;
15+
const OUTLINE_WIDTH = 0.1;
516

617
struct Vertex {
718
@builtin(instance_index) instance_index: u32,
@@ -15,14 +26,18 @@ struct VertexOutput {
1526
@vertex
1627
fn vertex(vertex: Vertex) -> VertexOutput {
1728
var out: VertexOutput;
29+
30+
// This only works when the mesh is at the origin.
31+
let expanded_position = vertex.position * (1 + OUTLINE_WIDTH);
32+
1833
out.clip_position = mesh_position_local_to_clip(
1934
get_world_from_local(vertex.instance_index),
20-
vec4<f32>(vertex.position, 1.0),
35+
vec4<f32>(expanded_position, 1.0),
2136
);
2237
return out;
2338
}
2439

2540
@fragment
2641
fn fragment(input: VertexOutput) -> @location(0) vec4<f32> {
27-
return color;
42+
return outline_color;
2843
}

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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ impl Plugin for Core3dPlugin {
167167
.init_resource::<ViewBinnedRenderPhases<AlphaMask3dDeferred>>()
168168
.init_resource::<ViewSortedRenderPhases<Transmissive3d>>()
169169
.init_resource::<ViewSortedRenderPhases<Transparent3d>>()
170-
.add_systems(ExtractSchedule, extract_core_3d_camera_phases)
171-
.add_systems(ExtractSchedule, extract_camera_prepass_phase)
170+
// .add_systems(ExtractSchedule, extract_core_3d_camera_phases)
171+
// .add_systems(ExtractSchedule, extract_camera_prepass_phase)
172172
.add_systems(
173173
Render,
174174
(

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

crates/bevy_pbr/src/dummy_phase.rs

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ use bevy_core_pipeline::core_3d::{Opaque3dBatchSetKey, Opaque3dBinKey};
44
use bevy_ecs::entity::Entity;
55
use bevy_render::{
66
render_phase::{
7-
BinnedPhaseItem, BinnedRenderPhase, BinnedRenderPhasePlugin, CachedRenderPipelinePhaseItem,
8-
DrawFunctionId, PhaseItem, PhaseItemExtraIndex, ViewBinnedRenderPhases,
7+
BinnedPhaseItem, CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem,
8+
PhaseItemExtraIndex,
99
},
1010
render_resource::CachedRenderPipelineId,
1111
sync_world::MainEntity,
1212
};
1313

14-
use crate::{MeshPass, MeshPipeline, PhaseContext, PhaseItemExt, PhaseItems, RenderPhaseType};
14+
use crate::{
15+
BinnedPhaseFamily, MeshPass, NoExtractCondition, PIEPhase, PhaseContext, PhaseItemExt,
16+
PhaseItems, RenderPhaseType,
17+
};
1518

1619
const DUMMY_PHASE_ERROR: &str = "Dummy phase should never be instantiated.";
1720

@@ -23,11 +26,10 @@ macro_rules! define_dummy_phase {
2326
// Important: It must be empty to ensure it does not match any material.
2427
const PHASE_TYPES: RenderPhaseType = RenderPhaseType::empty();
2528

26-
type RenderPhase = BinnedRenderPhase<Self>;
27-
type RenderPhases = ViewBinnedRenderPhases<Self>;
28-
type PhasePlugin = BinnedRenderPhasePlugin<Self, MeshPipeline>;
29+
type PhaseFamily = BinnedPhaseFamily<Self>;
30+
type ExtractCondition = NoExtractCondition;
2931

30-
fn queue(_render_phase: &mut Self::RenderPhase, _context: &PhaseContext) {
32+
fn queue(_render_phase: &mut PIEPhase<Self>, _context: &PhaseContext) {
3133
panic!("{}", DUMMY_PHASE_ERROR)
3234
}
3335
}
@@ -96,10 +98,10 @@ where
9698
P: MeshPass,
9799
PIE: PhaseItemExt,
98100
{
99-
type Phase1 = PIE;
100-
type Phase2 = DummyPhase2<P>;
101-
type Phase3 = DummyPhase3<P>;
102-
type Phase4 = DummyPhase4<P>;
101+
type PIE1 = PIE;
102+
type PIE2 = DummyPhase2<P>;
103+
type PIE3 = DummyPhase3<P>;
104+
type PIE4 = DummyPhase4<P>;
103105

104106
fn count() -> usize {
105107
1
@@ -111,10 +113,10 @@ where
111113
P: MeshPass,
112114
PIE1: PhaseItemExt,
113115
{
114-
type Phase1 = PIE1;
115-
type Phase2 = DummyPhase2<P>;
116-
type Phase3 = DummyPhase3<P>;
117-
type Phase4 = DummyPhase4<P>;
116+
type PIE1 = PIE1;
117+
type PIE2 = DummyPhase2<P>;
118+
type PIE3 = DummyPhase3<P>;
119+
type PIE4 = DummyPhase4<P>;
118120

119121
fn count() -> usize {
120122
1
@@ -127,10 +129,10 @@ where
127129
PIE1: PhaseItemExt,
128130
PIE2: PhaseItemExt,
129131
{
130-
type Phase1 = PIE1;
131-
type Phase2 = PIE2;
132-
type Phase3 = DummyPhase3<P>;
133-
type Phase4 = DummyPhase4<P>;
132+
type PIE1 = PIE1;
133+
type PIE2 = PIE2;
134+
type PIE3 = DummyPhase3<P>;
135+
type PIE4 = DummyPhase4<P>;
134136

135137
fn count() -> usize {
136138
2
@@ -144,10 +146,10 @@ where
144146
PIE2: PhaseItemExt,
145147
PIE3: PhaseItemExt,
146148
{
147-
type Phase1 = PIE1;
148-
type Phase2 = PIE2;
149-
type Phase3 = PIE3;
150-
type Phase4 = DummyPhase4<P>;
149+
type PIE1 = PIE1;
150+
type PIE2 = PIE2;
151+
type PIE3 = PIE3;
152+
type PIE4 = DummyPhase4<P>;
151153

152154
fn count() -> usize {
153155
3
@@ -162,10 +164,10 @@ where
162164
PIE3: PhaseItemExt,
163165
PIE4: PhaseItemExt,
164166
{
165-
type Phase1 = PIE1;
166-
type Phase2 = PIE2;
167-
type Phase3 = PIE3;
168-
type Phase4 = PIE4;
167+
type PIE1 = PIE1;
168+
type PIE2 = PIE2;
169+
type PIE3 = PIE3;
170+
type PIE4 = PIE4;
169171

170172
fn count() -> usize {
171173
4

crates/bevy_pbr/src/extended_material.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use bevy_render::{
1616
};
1717
use bevy_shader::ShaderRef;
1818

19-
use crate::{Material, MaterialPipeline, MaterialPipelineKey, MeshPipeline, MeshPipelineKey};
19+
use crate::{DeferredPass, MainPass, Material, MaterialPipeline, MaterialPipelineKey, MeshPass, MeshPipeline, MeshPipelineKey, PassId, PassShaders, Prepass, ShaderSet};
2020

2121
pub struct MaterialExtensionPipeline {
2222
pub mesh_pipeline: MeshPipeline,
@@ -25,12 +25,27 @@ pub struct MaterialExtensionPipeline {
2525
pub struct MaterialExtensionKey<E: MaterialExtension> {
2626
pub mesh_key: MeshPipelineKey,
2727
pub bind_group_data: E::Data,
28+
pub pass_id: PassId,
2829
}
2930

3031
/// A subset of the `Material` trait for defining extensions to a base `Material`, such as the builtin `StandardMaterial`.
3132
///
3233
/// A user type implementing the trait should be used as the `E` generic param in an `ExtendedMaterial` struct.
3334
pub trait MaterialExtension: Asset + AsBindGroup + Clone + Sized {
35+
/// Returns this material's shaders for supported passes.
36+
///
37+
/// When the traditional shader method is used, the corresponding pass's shader in the [`PassShaders`] will be ignored.
38+
/// Currently, only [`MainPass`], [`DeferredPass`] and [`Prepass`] are supported out of the box.
39+
fn shaders() -> PassShaders {
40+
let mut pass_shaders = PassShaders::default();
41+
pass_shaders.extend([
42+
(Prepass::id(), ShaderSet::default()),
43+
(DeferredPass::id(), ShaderSet::default()),
44+
(MainPass::id(), ShaderSet::default()),
45+
]);
46+
pass_shaders
47+
}
48+
3449
/// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the base material mesh vertex shader
3550
/// will be used.
3651
fn vertex_shader() -> ShaderRef {
@@ -309,6 +324,10 @@ impl<B: Material, E: MaterialExtension> AsBindGroup for ExtendedMaterial<B, E> {
309324
}
310325

311326
impl<B: Material, E: MaterialExtension> Material for ExtendedMaterial<B, E> {
327+
fn shaders() -> PassShaders {
328+
E::shaders()
329+
}
330+
312331
fn vertex_shader() -> ShaderRef {
313332
match E::vertex_shader() {
314333
ShaderRef::Default => B::vertex_shader(),
@@ -412,6 +431,7 @@ impl<B: Material, E: MaterialExtension> Material for ExtendedMaterial<B, E> {
412431
let base_key = MaterialPipelineKey::<B> {
413432
mesh_key: key.mesh_key,
414433
bind_group_data: key.bind_group_data.base,
434+
pass_id: key.pass_id,
415435
};
416436
B::specialize(pipeline, descriptor, layout, base_key)?;
417437

@@ -425,6 +445,7 @@ impl<B: Material, E: MaterialExtension> Material for ExtendedMaterial<B, E> {
425445
MaterialExtensionKey {
426446
mesh_key: key.mesh_key,
427447
bind_group_data: key.bind_group_data.extension,
448+
pass_id: key.pass_id,
428449
},
429450
)
430451
}

0 commit comments

Comments
 (0)