Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4877,3 +4877,14 @@ name = "Pan Camera"
description = "Example Pan-Camera Styled Camera Controller for 2D scenes"
category = "Camera"
wasm = true

[[example]]
name = "custom_mesh_pass"
path = "examples/shader_advanced/custom_mesh_pass.rs"
doc-scrape-examples = true

[package.metadata.example.custom_mesh_pass]
name = "Custom Mesh Pass"
description = "Example Pan-Camera Styled Camera Controller for 2D scenes"
category = "Shaders"
wasm = true
28 changes: 28 additions & 0 deletions assets/shaders/custom_mesh_pass_material.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#import bevy_pbr::mesh_functions::{get_world_from_local, mesh_position_local_to_clip}

@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<uniform> color: vec4<f32>;
@group(#{MATERIAL_BIND_GROUP}) @binding(1) var<uniform> outline_color: vec4<f32>;

struct Vertex {
@builtin(instance_index) instance_index: u32,
@location(0) position: vec3<f32>,
};

struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
};

@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = mesh_position_local_to_clip(
get_world_from_local(vertex.instance_index),
vec4<f32>(vertex.position, 1.0),
);
return out;
}

@fragment
fn fragment(input: VertexOutput) -> @location(0) vec4<f32> {
return color;
}
28 changes: 28 additions & 0 deletions assets/shaders/custom_mesh_pass_outline_material.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#import bevy_pbr::mesh_functions::{get_world_from_local, mesh_position_local_to_clip}

@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<uniform> color: vec4<f32>;
@group(#{MATERIAL_BIND_GROUP}) @binding(1) var<uniform> outline_color: vec4<f32>;

struct Vertex {
@builtin(instance_index) instance_index: u32,
@location(0) position: vec3<f32>,
};

struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
};

@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = mesh_position_local_to_clip(
get_world_from_local(vertex.instance_index),
vec4<f32>(vertex.position, 1.0),
);
return out;
}

@fragment
fn fragment(input: VertexOutput) -> @location(0) vec4<f32> {
return outline_color;
}
2 changes: 1 addition & 1 deletion crates/bevy_mesh/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ bitflags! {
/// downward. The PBR mesh pipeline key bits start from the lowest bit and
/// go upward. This allows the PBR bits in the downstream crate `bevy_pbr`
/// to coexist in the same field without any shifts.
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct BaseMeshPipelineKey: u64 {
const MORPH_TARGETS = 1 << (u64::BITS - 1);
}
Expand Down
173 changes: 173 additions & 0 deletions crates/bevy_pbr/src/dummy_phase.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
use core::{marker::PhantomData, ops::Range};

use bevy_core_pipeline::core_3d::{Opaque3dBatchSetKey, Opaque3dBinKey};
use bevy_ecs::entity::Entity;
use bevy_render::{
render_phase::{
BinnedPhaseItem, BinnedRenderPhase, BinnedRenderPhasePlugin, CachedRenderPipelinePhaseItem,
DrawFunctionId, PhaseItem, PhaseItemExtraIndex, ViewBinnedRenderPhases,
},
render_resource::CachedRenderPipelineId,
sync_world::MainEntity,
};

use crate::{MeshPass, MeshPipeline, PhaseContext, PhaseItemExt, PhaseItems, RenderPhaseType};

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

macro_rules! define_dummy_phase {
($name:ident) => {
pub struct $name<P>(PhantomData<P>);

impl<P: MeshPass> PhaseItemExt for $name<P> {
// Important: It must be empty to ensure it does not match any material.
const PHASE_TYPES: RenderPhaseType = RenderPhaseType::empty();

type RenderPhase = BinnedRenderPhase<Self>;
type RenderPhases = ViewBinnedRenderPhases<Self>;
type PhasePlugin = BinnedRenderPhasePlugin<Self, MeshPipeline>;

fn queue(_render_phase: &mut Self::RenderPhase, _context: &PhaseContext) {
panic!("{}", DUMMY_PHASE_ERROR)
}
}

impl<P: MeshPass> PhaseItem for $name<P> {
fn entity(&self) -> Entity {
panic!("{}", DUMMY_PHASE_ERROR)
}

fn main_entity(&self) -> MainEntity {
panic!("{}", DUMMY_PHASE_ERROR)
}

fn draw_function(&self) -> DrawFunctionId {
panic!("{}", DUMMY_PHASE_ERROR)
}

fn batch_range(&self) -> &Range<u32> {
panic!("{}", DUMMY_PHASE_ERROR)
}

fn batch_range_mut(&mut self) -> &mut Range<u32> {
panic!("{}", DUMMY_PHASE_ERROR)
}

fn extra_index(&self) -> PhaseItemExtraIndex {
panic!("{}", DUMMY_PHASE_ERROR)
}

fn batch_range_and_extra_index_mut(
&mut self,
) -> (&mut Range<u32>, &mut PhaseItemExtraIndex) {
panic!("{}", DUMMY_PHASE_ERROR)
}
}

impl<P: MeshPass> BinnedPhaseItem for $name<P> {
type BatchSetKey = Opaque3dBatchSetKey;
type BinKey = Opaque3dBinKey;

fn new(
_batch_set_key: Self::BatchSetKey,
_bin_key: Self::BinKey,
_representative_entity: (Entity, MainEntity),
_batch_range: Range<u32>,
_extra_index: PhaseItemExtraIndex,
) -> Self {
panic!("{}", DUMMY_PHASE_ERROR)
}
}

impl<P: MeshPass> CachedRenderPipelinePhaseItem for $name<P> {
fn cached_pipeline(&self) -> CachedRenderPipelineId {
panic!("{}", DUMMY_PHASE_ERROR)
}
}
};
}

define_dummy_phase!(DummyPhase2);
define_dummy_phase!(DummyPhase3);
define_dummy_phase!(DummyPhase4);

impl<P, PIE> PhaseItems<P> for PIE
where
P: MeshPass,
PIE: PhaseItemExt,
{
type Phase1 = PIE;
type Phase2 = DummyPhase2<P>;
type Phase3 = DummyPhase3<P>;
type Phase4 = DummyPhase4<P>;

fn count() -> usize {
1
}
}

impl<P, PIE1> PhaseItems<P> for (PIE1,)
where
P: MeshPass,
PIE1: PhaseItemExt,
{
type Phase1 = PIE1;
type Phase2 = DummyPhase2<P>;
type Phase3 = DummyPhase3<P>;
type Phase4 = DummyPhase4<P>;

fn count() -> usize {
1
}
}

impl<P, PIE1, PIE2> PhaseItems<P> for (PIE1, PIE2)
where
P: MeshPass,
PIE1: PhaseItemExt,
PIE2: PhaseItemExt,
{
type Phase1 = PIE1;
type Phase2 = PIE2;
type Phase3 = DummyPhase3<P>;
type Phase4 = DummyPhase4<P>;

fn count() -> usize {
2
}
}

impl<P, PIE1, PIE2, PIE3> PhaseItems<P> for (PIE1, PIE2, PIE3)
where
P: MeshPass,
PIE1: PhaseItemExt,
PIE2: PhaseItemExt,
PIE3: PhaseItemExt,
{
type Phase1 = PIE1;
type Phase2 = PIE2;
type Phase3 = PIE3;
type Phase4 = DummyPhase4<P>;

fn count() -> usize {
3
}
}

impl<P, PIE1, PIE2, PIE3, PIE4> PhaseItems<P> for (PIE1, PIE2, PIE3, PIE4)
where
P: MeshPass,
PIE1: PhaseItemExt,
PIE2: PhaseItemExt,
PIE3: PhaseItemExt,
PIE4: PhaseItemExt,
{
type Phase1 = PIE1;
type Phase2 = PIE2;
type Phase3 = PIE3;
type Phase4 = PIE4;

fn count() -> usize {
4
}
}
6 changes: 4 additions & 2 deletions crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ mod components;
pub mod decal;
pub mod deferred;
pub mod diagnostic;
mod dummy_phase;
mod extended_material;
mod fog;
mod light_probe;
mod lightmap;
mod main_pass;
mod material;
mod material_bind_groups;
mod medium;
Expand Down Expand Up @@ -61,6 +63,7 @@ pub use extended_material::*;
pub use fog::*;
pub use light_probe::*;
pub use lightmap::*;
pub use main_pass::*;
pub use material::*;
pub use material_bind_groups::*;
pub use medium::*;
Expand Down Expand Up @@ -222,7 +225,7 @@ impl Plugin for PbrPlugin {
use_gpu_instance_buffer_builder: self.use_gpu_instance_buffer_builder,
debug_flags: self.debug_flags,
},
MaterialsPlugin {
MainPassPlugin {
debug_flags: self.debug_flags,
},
MaterialPlugin::<StandardMaterial> {
Expand Down Expand Up @@ -327,7 +330,6 @@ impl Plugin for PbrPlugin {
extract_ambient_light_resource,
extract_ambient_light,
extract_shadow_filtering_method,
late_sweep_material_instances,
),
)
.add_systems(
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/lightmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ pub struct Lightmap {
///
/// There is one of these per visible lightmapped mesh instance.
#[derive(Debug)]
pub(crate) struct RenderLightmap {
pub struct RenderLightmap {
/// The rectangle within the lightmap texture that the UVs are relative to.
///
/// The top left coordinate is the `min` part of the rect, and the bottom
Expand All @@ -130,7 +130,7 @@ pub(crate) struct RenderLightmap {
pub(crate) slot_index: LightmapSlotIndex,

// Whether or not bicubic sampling should be used for this lightmap.
pub(crate) bicubic_sampling: bool,
pub bicubic_sampling: bool,
}

/// Stores data for all lightmaps in the render world.
Expand Down
Loading
Loading