mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
Clean up 2d render phases (#12982)
# Objective Currently, the 2d pipeline only has a transparent pass that is used for everything. I want to have separate passes for opaque/alpha mask/transparent meshes just like in 3d. This PR does the basic work to start adding new phases to the 2d pipeline and get the current setup a bit closer to 3d. ## Solution - Use `ViewNode` for `MainTransparentPass2dNode` - Added `Node2d::StartMainPass`, `Node2d::EndMainPass` - Rename everything to clarify that the main pass is currently the transparent pass --- ## Changelog - Added `Node2d::StartMainPass`, `Node2d::EndMainPass` ## Migration Guide If you were using `Node2d::MainPass` to order your own custom render node. You now need to order it relative to `Node2d::StartMainPass` or `Node2d::EndMainPass`.
This commit is contained in:
parent
0dddfa07ab
commit
64e1a7835a
6 changed files with 41 additions and 50 deletions
|
@ -81,7 +81,7 @@ impl Plugin for BloomPlugin {
|
|||
.add_render_graph_node::<ViewNodeRunner<BloomNode>>(Core2d, Node2d::Bloom)
|
||||
.add_render_graph_edges(
|
||||
Core2d,
|
||||
(Node2d::MainPass, Node2d::Bloom, Node2d::Tonemapping),
|
||||
(Node2d::EndMainPass, Node2d::Bloom, Node2d::Tonemapping),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,67 +3,49 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
diagnostic::RecordDiagnostics,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
||||
render_phase::SortedRenderPhase,
|
||||
render_resource::RenderPassDescriptor,
|
||||
renderer::RenderContext,
|
||||
view::{ExtractedView, ViewTarget},
|
||||
view::ViewTarget,
|
||||
};
|
||||
#[cfg(feature = "trace")]
|
||||
use bevy_utils::tracing::info_span;
|
||||
|
||||
pub struct MainPass2dNode {
|
||||
query: QueryState<
|
||||
(
|
||||
&'static ExtractedCamera,
|
||||
&'static SortedRenderPhase<Transparent2d>,
|
||||
&'static ViewTarget,
|
||||
),
|
||||
With<ExtractedView>,
|
||||
>,
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct MainTransparentPass2dNode {}
|
||||
|
||||
impl FromWorld for MainPass2dNode {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
Self {
|
||||
query: world.query_filtered(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ViewNode for MainTransparentPass2dNode {
|
||||
type ViewQuery = (
|
||||
&'static ExtractedCamera,
|
||||
&'static SortedRenderPhase<Transparent2d>,
|
||||
&'static ViewTarget,
|
||||
);
|
||||
|
||||
impl Node for MainPass2dNode {
|
||||
fn update(&mut self, world: &mut World) {
|
||||
self.query.update_archetypes(world);
|
||||
}
|
||||
|
||||
fn run(
|
||||
fn run<'w>(
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, transparent_phase, target): bevy_ecs::query::QueryItem<'w, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let view_entity = graph.view_entity();
|
||||
let Ok((camera, transparent_phase, target)) = self.query.get_manual(world, view_entity)
|
||||
else {
|
||||
// no target
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
{
|
||||
if !transparent_phase.items.is_empty() {
|
||||
#[cfg(feature = "trace")]
|
||||
let _main_pass_2d = info_span!("main_pass_2d").entered();
|
||||
let _main_pass_2d = info_span!("main_transparent_pass_2d").entered();
|
||||
|
||||
let diagnostics = render_context.diagnostic_recorder();
|
||||
|
||||
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
|
||||
label: Some("main_pass_2d"),
|
||||
label: Some("main_transparent_pass_2d"),
|
||||
color_attachments: &[Some(target.get_color_attachment())],
|
||||
depth_stencil_attachment: None,
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
|
||||
let pass_span = diagnostics.pass_span(&mut render_pass, "main_pass_2d");
|
||||
let pass_span = diagnostics.pass_span(&mut render_pass, "main_transparent_pass_2d");
|
||||
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
|
@ -1,5 +1,5 @@
|
|||
mod camera_2d;
|
||||
mod main_pass_2d_node;
|
||||
mod main_transparent_pass_2d_node;
|
||||
|
||||
pub mod graph {
|
||||
use bevy_render::render_graph::{RenderLabel, RenderSubGraph};
|
||||
|
@ -14,7 +14,9 @@ pub mod graph {
|
|||
#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)]
|
||||
pub enum Node2d {
|
||||
MsaaWriteback,
|
||||
MainPass,
|
||||
StartMainPass,
|
||||
MainTransparentPass,
|
||||
EndMainPass,
|
||||
Bloom,
|
||||
Tonemapping,
|
||||
Fxaa,
|
||||
|
@ -27,7 +29,7 @@ pub mod graph {
|
|||
use std::ops::Range;
|
||||
|
||||
pub use camera_2d::*;
|
||||
pub use main_pass_2d_node::*;
|
||||
pub use main_transparent_pass_2d_node::*;
|
||||
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_ecs::prelude::*;
|
||||
|
@ -68,14 +70,21 @@ impl Plugin for Core2dPlugin {
|
|||
|
||||
render_app
|
||||
.add_render_sub_graph(Core2d)
|
||||
.add_render_graph_node::<MainPass2dNode>(Core2d, Node2d::MainPass)
|
||||
.add_render_graph_node::<EmptyNode>(Core2d, Node2d::StartMainPass)
|
||||
.add_render_graph_node::<ViewNodeRunner<MainTransparentPass2dNode>>(
|
||||
Core2d,
|
||||
Node2d::MainTransparentPass,
|
||||
)
|
||||
.add_render_graph_node::<EmptyNode>(Core2d, Node2d::EndMainPass)
|
||||
.add_render_graph_node::<ViewNodeRunner<TonemappingNode>>(Core2d, Node2d::Tonemapping)
|
||||
.add_render_graph_node::<EmptyNode>(Core2d, Node2d::EndMainPassPostProcessing)
|
||||
.add_render_graph_node::<ViewNodeRunner<UpscalingNode>>(Core2d, Node2d::Upscaling)
|
||||
.add_render_graph_edges(
|
||||
Core2d,
|
||||
(
|
||||
Node2d::MainPass,
|
||||
Node2d::StartMainPass,
|
||||
Node2d::MainTransparentPass,
|
||||
Node2d::EndMainPass,
|
||||
Node2d::Tonemapping,
|
||||
Node2d::EndMainPassPostProcessing,
|
||||
Node2d::Upscaling,
|
||||
|
|
|
@ -31,7 +31,7 @@ impl Plugin for MsaaWritebackPlugin {
|
|||
{
|
||||
render_app
|
||||
.add_render_graph_node::<MsaaWritebackNode>(Core2d, Node2d::MsaaWriteback)
|
||||
.add_render_graph_edge(Core2d, Node2d::MsaaWriteback, Node2d::MainPass);
|
||||
.add_render_graph_edge(Core2d, Node2d::MsaaWriteback, Node2d::StartMainPass);
|
||||
}
|
||||
{
|
||||
render_app
|
||||
|
|
|
@ -389,7 +389,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
}
|
||||
|
||||
for (view, visible_entities, tonemapping, dither, mut transparent_phase) in &mut views {
|
||||
let draw_transparent_pbr = transparent_draw_functions.read().id::<DrawMaterial2d<M>>();
|
||||
let draw_transparent_2d = transparent_draw_functions.read().id::<DrawMaterial2d<M>>();
|
||||
|
||||
let mut view_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples())
|
||||
| Mesh2dPipelineKey::from_hdr(view.hdr);
|
||||
|
@ -410,7 +410,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
let Some(mesh_instance) = render_mesh_instances.get_mut(visible_entity) else {
|
||||
continue;
|
||||
};
|
||||
let Some(material2d) = render_materials.get(*material_asset_id) else {
|
||||
let Some(material_2d) = render_materials.get(*material_asset_id) else {
|
||||
continue;
|
||||
};
|
||||
let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else {
|
||||
|
@ -424,7 +424,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
&material2d_pipeline,
|
||||
Material2dKey {
|
||||
mesh_key,
|
||||
bind_group_data: material2d.key.clone(),
|
||||
bind_group_data: material_2d.key.clone(),
|
||||
},
|
||||
&mesh.layout,
|
||||
);
|
||||
|
@ -437,18 +437,18 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
}
|
||||
};
|
||||
|
||||
mesh_instance.material_bind_group_id = material2d.get_bind_group_id();
|
||||
mesh_instance.material_bind_group_id = material_2d.get_bind_group_id();
|
||||
|
||||
let mesh_z = mesh_instance.transforms.transform.translation.z;
|
||||
transparent_phase.add(Transparent2d {
|
||||
entity: *visible_entity,
|
||||
draw_function: draw_transparent_pbr,
|
||||
draw_function: draw_transparent_2d,
|
||||
pipeline: pipeline_id,
|
||||
// NOTE: Back-to-front ordering for transparent with ascending sort means far should have the
|
||||
// lowest sort key and getting closer should increase. As we have
|
||||
// -z in front of the camera, the largest distance is -far with values increasing toward the
|
||||
// camera. As such we can just use mesh_z as the distance
|
||||
sort_key: FloatOrd(mesh_z + material2d.depth_bias),
|
||||
sort_key: FloatOrd(mesh_z + material_2d.depth_bias),
|
||||
// Batching is done in batch_and_prepare_render_phase
|
||||
batch_range: 0..1,
|
||||
extra_index: PhaseItemExtraIndex::NONE,
|
||||
|
|
|
@ -126,7 +126,7 @@ pub fn build_ui_render(app: &mut App) {
|
|||
if let Some(graph_2d) = graph.get_sub_graph_mut(Core2d) {
|
||||
graph_2d.add_sub_graph(SubGraphUi, ui_graph_2d);
|
||||
graph_2d.add_node(NodeUi::UiPass, RunGraphOnViewNode::new(SubGraphUi));
|
||||
graph_2d.add_node_edge(Node2d::MainPass, NodeUi::UiPass);
|
||||
graph_2d.add_node_edge(Node2d::EndMainPass, NodeUi::UiPass);
|
||||
graph_2d.add_node_edge(Node2d::EndMainPassPostProcessing, NodeUi::UiPass);
|
||||
graph_2d.add_node_edge(NodeUi::UiPass, Node2d::Upscaling);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue