mirror of
https://github.com/bevyengine/bevy
synced 2024-11-30 08:30:24 +00:00
Split Transmissive3d
into a separate pass
This commit is contained in:
parent
fb490297e9
commit
3bc0a018cd
6 changed files with 193 additions and 25 deletions
|
@ -0,0 +1,106 @@
|
||||||
|
use super::ViewTransmissionTexture;
|
||||||
|
use crate::core_3d::Transmissive3d;
|
||||||
|
use bevy_ecs::prelude::*;
|
||||||
|
use bevy_render::{
|
||||||
|
camera::ExtractedCamera,
|
||||||
|
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||||
|
render_phase::RenderPhase,
|
||||||
|
render_resource::{
|
||||||
|
Extent3d, LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor,
|
||||||
|
},
|
||||||
|
renderer::RenderContext,
|
||||||
|
view::{ExtractedView, ViewDepthTexture, ViewTarget},
|
||||||
|
};
|
||||||
|
#[cfg(feature = "trace")]
|
||||||
|
use bevy_utils::tracing::info_span;
|
||||||
|
|
||||||
|
/// A [`Node`] that runs the [`Transmissive3d`] [`RenderPhase`].
|
||||||
|
pub struct MainTransmissivePass3dNode {
|
||||||
|
query: QueryState<
|
||||||
|
(
|
||||||
|
&'static ExtractedCamera,
|
||||||
|
&'static RenderPhase<Transmissive3d>,
|
||||||
|
&'static ViewTarget,
|
||||||
|
&'static ViewTransmissionTexture,
|
||||||
|
&'static ViewDepthTexture,
|
||||||
|
),
|
||||||
|
With<ExtractedView>,
|
||||||
|
>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWorld for MainTransmissivePass3dNode {
|
||||||
|
fn from_world(world: &mut World) -> Self {
|
||||||
|
Self {
|
||||||
|
query: world.query_filtered(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node for MainTransmissivePass3dNode {
|
||||||
|
fn update(&mut self, world: &mut World) {
|
||||||
|
self.query.update_archetypes(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
graph: &mut RenderGraphContext,
|
||||||
|
render_context: &mut RenderContext,
|
||||||
|
world: &World,
|
||||||
|
) -> Result<(), NodeRunError> {
|
||||||
|
let view_entity = graph.view_entity();
|
||||||
|
let Ok((
|
||||||
|
camera,
|
||||||
|
transmissive_phase,
|
||||||
|
target,
|
||||||
|
transmission,
|
||||||
|
depth,
|
||||||
|
)) = self.query.get_manual(world, view_entity) else {
|
||||||
|
// No window
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let physical_target_size = camera.physical_target_size.unwrap();
|
||||||
|
render_context.command_encoder().copy_texture_to_texture(
|
||||||
|
target.main_texture().as_image_copy(),
|
||||||
|
transmission.texture.as_image_copy(),
|
||||||
|
Extent3d {
|
||||||
|
width: physical_target_size.x,
|
||||||
|
height: physical_target_size.y,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if !transmissive_phase.items.is_empty() {
|
||||||
|
// Run the transmissive pass, sorted back-to-front
|
||||||
|
// NOTE: Scoped to drop the mutable borrow of render_context
|
||||||
|
#[cfg(feature = "trace")]
|
||||||
|
let _main_transmissive_pass_3d_span = info_span!("main_transmissive_pass_3d").entered();
|
||||||
|
|
||||||
|
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
|
||||||
|
label: Some("main_transmissive_pass_3d"),
|
||||||
|
// NOTE: The transmissive pass loads the color buffer as well as overwriting it where appropriate.
|
||||||
|
color_attachments: &[Some(target.get_color_attachment(Operations {
|
||||||
|
load: LoadOp::Load,
|
||||||
|
store: true,
|
||||||
|
}))],
|
||||||
|
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
|
||||||
|
view: &depth.view,
|
||||||
|
// NOTE: The transmissive main pass loads the depth buffer and possibly overwrites it
|
||||||
|
depth_ops: Some(Operations {
|
||||||
|
load: LoadOp::Load,
|
||||||
|
store: true,
|
||||||
|
}),
|
||||||
|
stencil_ops: None,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(viewport) = camera.viewport.as_ref() {
|
||||||
|
render_pass.set_camera_viewport(viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
transmissive_phase.render(&mut render_pass, world, view_entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,10 @@
|
||||||
use super::ViewTransmissionTexture;
|
|
||||||
use crate::core_3d::Transparent3d;
|
use crate::core_3d::Transparent3d;
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::ExtractedCamera,
|
camera::ExtractedCamera,
|
||||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||||
render_phase::RenderPhase,
|
render_phase::RenderPhase,
|
||||||
render_resource::{
|
render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor},
|
||||||
Extent3d, LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor,
|
|
||||||
},
|
|
||||||
renderer::RenderContext,
|
renderer::RenderContext,
|
||||||
view::{ExtractedView, ViewDepthTexture, ViewTarget},
|
view::{ExtractedView, ViewDepthTexture, ViewTarget},
|
||||||
};
|
};
|
||||||
|
@ -21,7 +18,6 @@ pub struct MainTransparentPass3dNode {
|
||||||
&'static ExtractedCamera,
|
&'static ExtractedCamera,
|
||||||
&'static RenderPhase<Transparent3d>,
|
&'static RenderPhase<Transparent3d>,
|
||||||
&'static ViewTarget,
|
&'static ViewTarget,
|
||||||
&'static ViewTransmissionTexture,
|
|
||||||
&'static ViewDepthTexture,
|
&'static ViewDepthTexture,
|
||||||
),
|
),
|
||||||
With<ExtractedView>,
|
With<ExtractedView>,
|
||||||
|
@ -52,24 +48,12 @@ impl Node for MainTransparentPass3dNode {
|
||||||
camera,
|
camera,
|
||||||
transparent_phase,
|
transparent_phase,
|
||||||
target,
|
target,
|
||||||
transmission,
|
|
||||||
depth,
|
depth,
|
||||||
)) = self.query.get_manual(world, view_entity) else {
|
)) = self.query.get_manual(world, view_entity) else {
|
||||||
// No window
|
// No window
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let physical_target_size = camera.physical_target_size.unwrap();
|
|
||||||
render_context.command_encoder().copy_texture_to_texture(
|
|
||||||
target.main_texture().as_image_copy(),
|
|
||||||
transmission.texture.as_image_copy(),
|
|
||||||
Extent3d {
|
|
||||||
width: physical_target_size.x,
|
|
||||||
height: physical_target_size.y,
|
|
||||||
depth_or_array_layers: 1,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if !transparent_phase.items.is_empty() {
|
if !transparent_phase.items.is_empty() {
|
||||||
// Run the transparent pass, sorted back-to-front
|
// Run the transparent pass, sorted back-to-front
|
||||||
// NOTE: Scoped to drop the mutable borrow of render_context
|
// NOTE: Scoped to drop the mutable borrow of render_context
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
mod camera_3d;
|
mod camera_3d;
|
||||||
mod main_opaque_pass_3d_node;
|
mod main_opaque_pass_3d_node;
|
||||||
|
mod main_transmissive_pass_3d_node;
|
||||||
mod main_transparent_pass_3d_node;
|
mod main_transparent_pass_3d_node;
|
||||||
|
|
||||||
pub mod graph {
|
pub mod graph {
|
||||||
|
@ -12,6 +13,7 @@ pub mod graph {
|
||||||
pub const PREPASS: &str = "prepass";
|
pub const PREPASS: &str = "prepass";
|
||||||
pub const START_MAIN_PASS: &str = "start_main_pass";
|
pub const START_MAIN_PASS: &str = "start_main_pass";
|
||||||
pub const MAIN_OPAQUE_PASS: &str = "main_opaque_pass";
|
pub const MAIN_OPAQUE_PASS: &str = "main_opaque_pass";
|
||||||
|
pub const MAIN_TRANSMISSIVE_PASS: &str = "main_transmissive_pass";
|
||||||
pub const MAIN_TRANSPARENT_PASS: &str = "main_transparent_pass";
|
pub const MAIN_TRANSPARENT_PASS: &str = "main_transparent_pass";
|
||||||
pub const END_MAIN_PASS: &str = "end_main_pass";
|
pub const END_MAIN_PASS: &str = "end_main_pass";
|
||||||
pub const BLOOM: &str = "bloom";
|
pub const BLOOM: &str = "bloom";
|
||||||
|
@ -53,6 +55,7 @@ use bevy_render::{
|
||||||
use bevy_utils::{FloatOrd, HashMap};
|
use bevy_utils::{FloatOrd, HashMap};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
core_3d::main_transmissive_pass_3d_node::MainTransmissivePass3dNode,
|
||||||
prepass::{node::PrepassNode, DepthPrepass},
|
prepass::{node::PrepassNode, DepthPrepass},
|
||||||
skybox::SkyboxPlugin,
|
skybox::SkyboxPlugin,
|
||||||
tonemapping::TonemappingNode,
|
tonemapping::TonemappingNode,
|
||||||
|
@ -76,6 +79,7 @@ impl Plugin for Core3dPlugin {
|
||||||
render_app
|
render_app
|
||||||
.init_resource::<DrawFunctions<Opaque3d>>()
|
.init_resource::<DrawFunctions<Opaque3d>>()
|
||||||
.init_resource::<DrawFunctions<AlphaMask3d>>()
|
.init_resource::<DrawFunctions<AlphaMask3d>>()
|
||||||
|
.init_resource::<DrawFunctions<Transmissive3d>>()
|
||||||
.init_resource::<DrawFunctions<Transparent3d>>()
|
.init_resource::<DrawFunctions<Transparent3d>>()
|
||||||
.add_systems(ExtractSchedule, extract_core_3d_camera_phases)
|
.add_systems(ExtractSchedule, extract_core_3d_camera_phases)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
|
@ -89,6 +93,7 @@ impl Plugin for Core3dPlugin {
|
||||||
.after(bevy_render::view::prepare_windows),
|
.after(bevy_render::view::prepare_windows),
|
||||||
sort_phase_system::<Opaque3d>.in_set(RenderSet::PhaseSort),
|
sort_phase_system::<Opaque3d>.in_set(RenderSet::PhaseSort),
|
||||||
sort_phase_system::<AlphaMask3d>.in_set(RenderSet::PhaseSort),
|
sort_phase_system::<AlphaMask3d>.in_set(RenderSet::PhaseSort),
|
||||||
|
sort_phase_system::<Transmissive3d>.in_set(RenderSet::PhaseSort),
|
||||||
sort_phase_system::<Transparent3d>.in_set(RenderSet::PhaseSort),
|
sort_phase_system::<Transparent3d>.in_set(RenderSet::PhaseSort),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -99,6 +104,7 @@ impl Plugin for Core3dPlugin {
|
||||||
.add_render_graph_node::<PrepassNode>(CORE_3D, PREPASS)
|
.add_render_graph_node::<PrepassNode>(CORE_3D, PREPASS)
|
||||||
.add_render_graph_node::<EmptyNode>(CORE_3D, START_MAIN_PASS)
|
.add_render_graph_node::<EmptyNode>(CORE_3D, START_MAIN_PASS)
|
||||||
.add_render_graph_node::<MainOpaquePass3dNode>(CORE_3D, MAIN_OPAQUE_PASS)
|
.add_render_graph_node::<MainOpaquePass3dNode>(CORE_3D, MAIN_OPAQUE_PASS)
|
||||||
|
.add_render_graph_node::<MainTransmissivePass3dNode>(CORE_3D, MAIN_TRANSMISSIVE_PASS)
|
||||||
.add_render_graph_node::<MainTransparentPass3dNode>(CORE_3D, MAIN_TRANSPARENT_PASS)
|
.add_render_graph_node::<MainTransparentPass3dNode>(CORE_3D, MAIN_TRANSPARENT_PASS)
|
||||||
.add_render_graph_node::<EmptyNode>(CORE_3D, END_MAIN_PASS)
|
.add_render_graph_node::<EmptyNode>(CORE_3D, END_MAIN_PASS)
|
||||||
.add_render_graph_node::<TonemappingNode>(CORE_3D, TONEMAPPING)
|
.add_render_graph_node::<TonemappingNode>(CORE_3D, TONEMAPPING)
|
||||||
|
@ -110,6 +116,7 @@ impl Plugin for Core3dPlugin {
|
||||||
PREPASS,
|
PREPASS,
|
||||||
START_MAIN_PASS,
|
START_MAIN_PASS,
|
||||||
MAIN_OPAQUE_PASS,
|
MAIN_OPAQUE_PASS,
|
||||||
|
MAIN_TRANSMISSIVE_PASS,
|
||||||
MAIN_TRANSPARENT_PASS,
|
MAIN_TRANSPARENT_PASS,
|
||||||
END_MAIN_PASS,
|
END_MAIN_PASS,
|
||||||
TONEMAPPING,
|
TONEMAPPING,
|
||||||
|
@ -200,6 +207,45 @@ impl CachedRenderPipelinePhaseItem for AlphaMask3d {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Transmissive3d {
|
||||||
|
pub distance: f32,
|
||||||
|
pub pipeline: CachedRenderPipelineId,
|
||||||
|
pub entity: Entity,
|
||||||
|
pub draw_function: DrawFunctionId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhaseItem for Transmissive3d {
|
||||||
|
// NOTE: Values increase towards the camera. Back-to-front ordering for transmissive means we need an ascending sort.
|
||||||
|
type SortKey = FloatOrd;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn entity(&self) -> Entity {
|
||||||
|
self.entity
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sort_key(&self) -> Self::SortKey {
|
||||||
|
FloatOrd(self.distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn draw_function(&self) -> DrawFunctionId {
|
||||||
|
self.draw_function
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sort(items: &mut [Self]) {
|
||||||
|
radsort::sort_by_key(items, |item| item.distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CachedRenderPipelinePhaseItem for Transmissive3d {
|
||||||
|
#[inline]
|
||||||
|
fn cached_pipeline(&self) -> CachedRenderPipelineId {
|
||||||
|
self.pipeline
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Transparent3d {
|
pub struct Transparent3d {
|
||||||
pub distance: f32,
|
pub distance: f32,
|
||||||
pub pipeline: CachedRenderPipelineId,
|
pub pipeline: CachedRenderPipelineId,
|
||||||
|
@ -248,6 +294,7 @@ pub fn extract_core_3d_camera_phases(
|
||||||
commands.get_or_spawn(entity).insert((
|
commands.get_or_spawn(entity).insert((
|
||||||
RenderPhase::<Opaque3d>::default(),
|
RenderPhase::<Opaque3d>::default(),
|
||||||
RenderPhase::<AlphaMask3d>::default(),
|
RenderPhase::<AlphaMask3d>::default(),
|
||||||
|
RenderPhase::<Transmissive3d>::default(),
|
||||||
RenderPhase::<Transparent3d>::default(),
|
RenderPhase::<Transparent3d>::default(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -264,6 +311,7 @@ pub fn prepare_core_3d_depth_textures(
|
||||||
(
|
(
|
||||||
With<RenderPhase<Opaque3d>>,
|
With<RenderPhase<Opaque3d>>,
|
||||||
With<RenderPhase<AlphaMask3d>>,
|
With<RenderPhase<AlphaMask3d>>,
|
||||||
|
With<RenderPhase<Transmissive3d>>,
|
||||||
With<RenderPhase<Transparent3d>>,
|
With<RenderPhase<Transparent3d>>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
|
@ -330,6 +378,7 @@ pub fn prepare_core_3d_transmission_textures(
|
||||||
(
|
(
|
||||||
With<RenderPhase<Opaque3d>>,
|
With<RenderPhase<Opaque3d>>,
|
||||||
With<RenderPhase<AlphaMask3d>>,
|
With<RenderPhase<AlphaMask3d>>,
|
||||||
|
With<RenderPhase<Transmissive3d>>,
|
||||||
With<RenderPhase<Transparent3d>>,
|
With<RenderPhase<Transparent3d>>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle};
|
use bevy_asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle};
|
||||||
use bevy_core_pipeline::{
|
use bevy_core_pipeline::{
|
||||||
core_3d::{AlphaMask3d, Opaque3d, Transparent3d},
|
core_3d::{AlphaMask3d, Opaque3d, Transmissive3d, Transparent3d},
|
||||||
prepass::NormalPrepass,
|
prepass::NormalPrepass,
|
||||||
tonemapping::{DebandDither, Tonemapping},
|
tonemapping::{DebandDither, Tonemapping},
|
||||||
};
|
};
|
||||||
|
@ -133,6 +133,13 @@ pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'stat
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Returns whether or not the material has light transmission properties. Transmissive materials use the color
|
||||||
|
/// output from the [`Opaque3d`] pass as an input and therefore must run in a separate [`Transmissive3d`] pass.
|
||||||
|
fn transmissive(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns this material's prepass vertex shader. If [`ShaderRef::Default`] is returned, the default prepass vertex shader
|
/// Returns this material's prepass vertex shader. If [`ShaderRef::Default`] is returned, the default prepass vertex shader
|
||||||
/// will be used.
|
/// will be used.
|
||||||
fn prepass_vertex_shader() -> ShaderRef {
|
fn prepass_vertex_shader() -> ShaderRef {
|
||||||
|
@ -193,6 +200,7 @@ where
|
||||||
render_app
|
render_app
|
||||||
.init_resource::<DrawFunctions<Shadow>>()
|
.init_resource::<DrawFunctions<Shadow>>()
|
||||||
.add_render_command::<Shadow, DrawPrepass<M>>()
|
.add_render_command::<Shadow, DrawPrepass<M>>()
|
||||||
|
.add_render_command::<Transmissive3d, DrawMaterial<M>>()
|
||||||
.add_render_command::<Transparent3d, DrawMaterial<M>>()
|
.add_render_command::<Transparent3d, DrawMaterial<M>>()
|
||||||
.add_render_command::<Opaque3d, DrawMaterial<M>>()
|
.add_render_command::<Opaque3d, DrawMaterial<M>>()
|
||||||
.add_render_command::<AlphaMask3d, DrawMaterial<M>>()
|
.add_render_command::<AlphaMask3d, DrawMaterial<M>>()
|
||||||
|
@ -366,6 +374,7 @@ impl<P: PhaseItem, M: Material, const I: usize> RenderCommand<P> for SetMaterial
|
||||||
pub fn queue_material_meshes<M: Material>(
|
pub fn queue_material_meshes<M: Material>(
|
||||||
opaque_draw_functions: Res<DrawFunctions<Opaque3d>>,
|
opaque_draw_functions: Res<DrawFunctions<Opaque3d>>,
|
||||||
alpha_mask_draw_functions: Res<DrawFunctions<AlphaMask3d>>,
|
alpha_mask_draw_functions: Res<DrawFunctions<AlphaMask3d>>,
|
||||||
|
transmissive_draw_functions: Res<DrawFunctions<Transmissive3d>>,
|
||||||
transparent_draw_functions: Res<DrawFunctions<Transparent3d>>,
|
transparent_draw_functions: Res<DrawFunctions<Transparent3d>>,
|
||||||
material_pipeline: Res<MaterialPipeline<M>>,
|
material_pipeline: Res<MaterialPipeline<M>>,
|
||||||
mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipeline<M>>>,
|
mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipeline<M>>>,
|
||||||
|
@ -384,6 +393,7 @@ pub fn queue_material_meshes<M: Material>(
|
||||||
Option<&NormalPrepass>,
|
Option<&NormalPrepass>,
|
||||||
&mut RenderPhase<Opaque3d>,
|
&mut RenderPhase<Opaque3d>,
|
||||||
&mut RenderPhase<AlphaMask3d>,
|
&mut RenderPhase<AlphaMask3d>,
|
||||||
|
&mut RenderPhase<Transmissive3d>,
|
||||||
&mut RenderPhase<Transparent3d>,
|
&mut RenderPhase<Transparent3d>,
|
||||||
)>,
|
)>,
|
||||||
) where
|
) where
|
||||||
|
@ -398,11 +408,13 @@ pub fn queue_material_meshes<M: Material>(
|
||||||
normal_prepass,
|
normal_prepass,
|
||||||
mut opaque_phase,
|
mut opaque_phase,
|
||||||
mut alpha_mask_phase,
|
mut alpha_mask_phase,
|
||||||
|
mut transmissive_phase,
|
||||||
mut transparent_phase,
|
mut transparent_phase,
|
||||||
) in &mut views
|
) in &mut views
|
||||||
{
|
{
|
||||||
let draw_opaque_pbr = opaque_draw_functions.read().id::<DrawMaterial<M>>();
|
let draw_opaque_pbr = opaque_draw_functions.read().id::<DrawMaterial<M>>();
|
||||||
let draw_alpha_mask_pbr = alpha_mask_draw_functions.read().id::<DrawMaterial<M>>();
|
let draw_alpha_mask_pbr = alpha_mask_draw_functions.read().id::<DrawMaterial<M>>();
|
||||||
|
let draw_transmissive_pbr = transmissive_draw_functions.read().id::<DrawMaterial<M>>();
|
||||||
let draw_transparent_pbr = transparent_draw_functions.read().id::<DrawMaterial<M>>();
|
let draw_transparent_pbr = transparent_draw_functions.read().id::<DrawMaterial<M>>();
|
||||||
|
|
||||||
let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
|
let mut view_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
|
||||||
|
@ -491,12 +503,21 @@ pub fn queue_material_meshes<M: Material>(
|
||||||
+ material.properties.depth_bias;
|
+ material.properties.depth_bias;
|
||||||
match material.properties.alpha_mode {
|
match material.properties.alpha_mode {
|
||||||
AlphaMode::Opaque => {
|
AlphaMode::Opaque => {
|
||||||
opaque_phase.add(Opaque3d {
|
if material.properties.transmissive {
|
||||||
entity: *visible_entity,
|
transmissive_phase.add(Transmissive3d {
|
||||||
draw_function: draw_opaque_pbr,
|
entity: *visible_entity,
|
||||||
pipeline: pipeline_id,
|
draw_function: draw_transmissive_pbr,
|
||||||
distance,
|
pipeline: pipeline_id,
|
||||||
});
|
distance,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
opaque_phase.add(Opaque3d {
|
||||||
|
entity: *visible_entity,
|
||||||
|
draw_function: draw_opaque_pbr,
|
||||||
|
pipeline: pipeline_id,
|
||||||
|
distance,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AlphaMode::Mask(_) => {
|
AlphaMode::Mask(_) => {
|
||||||
alpha_mask_phase.add(AlphaMask3d {
|
alpha_mask_phase.add(AlphaMask3d {
|
||||||
|
@ -532,6 +553,9 @@ pub struct MaterialProperties {
|
||||||
/// for meshes with equal depth, to avoid z-fighting.
|
/// for meshes with equal depth, to avoid z-fighting.
|
||||||
/// The bias is in depth-texture units so large values may be needed to overcome small depth differences.
|
/// The bias is in depth-texture units so large values may be needed to overcome small depth differences.
|
||||||
pub depth_bias: f32,
|
pub depth_bias: f32,
|
||||||
|
/// Whether or not the material has light transmission properties. Transmissive materials use the color
|
||||||
|
/// output from the [`Opaque3d`] pass as an input and therefore must run in a separate [`Transmissive3d`] pass.
|
||||||
|
pub transmissive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data prepared for a [`Material`] instance.
|
/// Data prepared for a [`Material`] instance.
|
||||||
|
@ -685,6 +709,7 @@ fn prepare_material<M: Material>(
|
||||||
properties: MaterialProperties {
|
properties: MaterialProperties {
|
||||||
alpha_mode: material.alpha_mode(),
|
alpha_mode: material.alpha_mode(),
|
||||||
depth_bias: material.depth_bias(),
|
depth_bias: material.depth_bias(),
|
||||||
|
transmissive: material.transmissive(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -530,4 +530,9 @@ impl Material for StandardMaterial {
|
||||||
fn depth_bias(&self) -> f32 {
|
fn depth_bias(&self) -> f32 {
|
||||||
self.depth_bias
|
self.depth_bias
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transmissive(&self) -> bool {
|
||||||
|
self.transmission > 0.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,6 @@ fn setup(
|
||||||
thickness: 1.0,
|
thickness: 1.0,
|
||||||
ior: 1.5,
|
ior: 1.5,
|
||||||
perceptual_roughness: 0.12,
|
perceptual_roughness: 0.12,
|
||||||
alpha_mode: AlphaMode::Blend,
|
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
transform: Transform::from_xyz(1.0, 0.0, 0.0),
|
transform: Transform::from_xyz(1.0, 0.0, 0.0),
|
||||||
|
|
Loading…
Reference in a new issue