Extract common RenderPhase code into render method (#7013)
# Objective All `RenderPhases` follow the same render procedure. The same code is duplicated multiple times across the codebase. ## Solution I simply extracted this code into a method on the `RenderPhase`. This avoids code duplication and makes setting up new `RenderPhases` easier. --- ## Changelog ### Changed You can now set up the rendering code of a `RenderPhase` directly using the `RenderPhase::render` method, instead of implementing it manually in your render graph node.
This commit is contained in:
parent
5566d73d9e
commit
ca85f6c903
@ -6,7 +6,7 @@ use bevy_ecs::prelude::*;
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_phase::{DrawFunctions, RenderPhase, TrackedRenderPass},
|
||||
render_phase::RenderPhase,
|
||||
render_resource::{LoadOp, Operations, RenderPassDescriptor},
|
||||
renderer::RenderContext,
|
||||
view::{ExtractedView, ViewTarget},
|
||||
@ -77,21 +77,13 @@ impl Node for MainPass2dNode {
|
||||
depth_stencil_attachment: None,
|
||||
};
|
||||
|
||||
let draw_functions = world.resource::<DrawFunctions<Transparent2d>>();
|
||||
|
||||
let render_pass = render_context
|
||||
.command_encoder
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
|
||||
let mut draw_functions = draw_functions.write();
|
||||
let mut tracked_pass = TrackedRenderPass::new(render_pass);
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
tracked_pass.set_camera_viewport(viewport);
|
||||
}
|
||||
for item in &transparent_phase.items {
|
||||
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
|
||||
draw_function.draw(world, &mut tracked_pass, view_entity, item);
|
||||
}
|
||||
transparent_phase.render(
|
||||
world,
|
||||
render_context,
|
||||
view_entity,
|
||||
camera.viewport.as_ref(),
|
||||
pass_descriptor,
|
||||
);
|
||||
}
|
||||
|
||||
// WebGL2 quirk: if ending with a render pass with a custom viewport, the viewport isn't
|
||||
|
||||
@ -6,7 +6,7 @@ use bevy_ecs::prelude::*;
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_phase::{DrawFunctions, RenderPhase, TrackedRenderPass},
|
||||
render_phase::RenderPhase,
|
||||
render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor},
|
||||
renderer::RenderContext,
|
||||
view::{ExtractedView, ViewDepthTexture, ViewTarget},
|
||||
@ -95,20 +95,13 @@ impl Node for MainPass3dNode {
|
||||
}),
|
||||
};
|
||||
|
||||
let draw_functions = world.resource::<DrawFunctions<Opaque3d>>();
|
||||
|
||||
let render_pass = render_context
|
||||
.command_encoder
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
let mut draw_functions = draw_functions.write();
|
||||
let mut tracked_pass = TrackedRenderPass::new(render_pass);
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
tracked_pass.set_camera_viewport(viewport);
|
||||
}
|
||||
for item in &opaque_phase.items {
|
||||
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
|
||||
draw_function.draw(world, &mut tracked_pass, view_entity, item);
|
||||
}
|
||||
opaque_phase.render(
|
||||
world,
|
||||
render_context,
|
||||
view_entity,
|
||||
camera.viewport.as_ref(),
|
||||
pass_descriptor,
|
||||
);
|
||||
}
|
||||
|
||||
if !alpha_mask_phase.items.is_empty() {
|
||||
@ -134,20 +127,13 @@ impl Node for MainPass3dNode {
|
||||
}),
|
||||
};
|
||||
|
||||
let draw_functions = world.resource::<DrawFunctions<AlphaMask3d>>();
|
||||
|
||||
let render_pass = render_context
|
||||
.command_encoder
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
let mut draw_functions = draw_functions.write();
|
||||
let mut tracked_pass = TrackedRenderPass::new(render_pass);
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
tracked_pass.set_camera_viewport(viewport);
|
||||
}
|
||||
for item in &alpha_mask_phase.items {
|
||||
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
|
||||
draw_function.draw(world, &mut tracked_pass, view_entity, item);
|
||||
}
|
||||
alpha_mask_phase.render(
|
||||
world,
|
||||
render_context,
|
||||
view_entity,
|
||||
camera.viewport.as_ref(),
|
||||
pass_descriptor,
|
||||
);
|
||||
}
|
||||
|
||||
if !transparent_phase.items.is_empty() {
|
||||
@ -178,20 +164,13 @@ impl Node for MainPass3dNode {
|
||||
}),
|
||||
};
|
||||
|
||||
let draw_functions = world.resource::<DrawFunctions<Transparent3d>>();
|
||||
|
||||
let render_pass = render_context
|
||||
.command_encoder
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
let mut draw_functions = draw_functions.write();
|
||||
let mut tracked_pass = TrackedRenderPass::new(render_pass);
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
tracked_pass.set_camera_viewport(viewport);
|
||||
}
|
||||
for item in &transparent_phase.items {
|
||||
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
|
||||
draw_function.draw(world, &mut tracked_pass, view_entity, item);
|
||||
}
|
||||
transparent_phase.render(
|
||||
world,
|
||||
render_context,
|
||||
view_entity,
|
||||
camera.viewport.as_ref(),
|
||||
pass_descriptor,
|
||||
);
|
||||
}
|
||||
|
||||
// WebGL2 quirk: if ending with a render pass with a custom viewport, the viewport isn't
|
||||
|
||||
@ -1785,16 +1785,7 @@ impl Node for ShadowPassNode {
|
||||
}),
|
||||
};
|
||||
|
||||
let draw_functions = world.resource::<DrawFunctions<Shadow>>();
|
||||
let render_pass = render_context
|
||||
.command_encoder
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
let mut draw_functions = draw_functions.write();
|
||||
let mut tracked_pass = TrackedRenderPass::new(render_pass);
|
||||
for item in &shadow_phase.items {
|
||||
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
|
||||
draw_function.draw(world, &mut tracked_pass, view_light_entity, item);
|
||||
}
|
||||
shadow_phase.render(world, render_context, view_entity, None, pass_descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
mod draw;
|
||||
mod draw_state;
|
||||
|
||||
use bevy_ecs::entity::Entity;
|
||||
pub use draw::*;
|
||||
pub use draw_state::*;
|
||||
use wgpu::RenderPassDescriptor;
|
||||
|
||||
use crate::camera::Viewport;
|
||||
use crate::renderer::RenderContext;
|
||||
use bevy_ecs::prelude::{Component, Query};
|
||||
use bevy_ecs::world::World;
|
||||
|
||||
/// A resource to collect and sort draw requests for specific [`PhaseItems`](PhaseItem).
|
||||
#[derive(Component)]
|
||||
@ -29,6 +34,32 @@ impl<I: PhaseItem> RenderPhase<I> {
|
||||
pub fn sort(&mut self) {
|
||||
I::sort(&mut self.items);
|
||||
}
|
||||
|
||||
pub fn render(
|
||||
&self,
|
||||
world: &World,
|
||||
render_context: &mut RenderContext,
|
||||
view: Entity,
|
||||
viewport: Option<&Viewport>,
|
||||
pass_descriptor: RenderPassDescriptor,
|
||||
) {
|
||||
let render_pass = render_context
|
||||
.command_encoder
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
let mut render_pass = TrackedRenderPass::new(render_pass);
|
||||
|
||||
if let Some(viewport) = viewport {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
}
|
||||
|
||||
let draw_functions = world.resource::<DrawFunctions<I>>();
|
||||
let mut draw_functions = draw_functions.write();
|
||||
|
||||
for item in &self.items {
|
||||
let draw_function = draw_functions.get_mut(item.draw_function()).unwrap();
|
||||
draw_function.draw(world, &mut render_pass, view, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: BatchedPhaseItem> RenderPhase<I> {
|
||||
|
||||
@ -85,18 +85,7 @@ impl Node for UiPassNode {
|
||||
depth_stencil_attachment: None,
|
||||
};
|
||||
|
||||
let draw_functions = world.resource::<DrawFunctions<TransparentUi>>();
|
||||
|
||||
let render_pass = render_context
|
||||
.command_encoder
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
|
||||
let mut draw_functions = draw_functions.write();
|
||||
let mut tracked_pass = TrackedRenderPass::new(render_pass);
|
||||
for item in &transparent_phase.items {
|
||||
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
|
||||
draw_function.draw(world, &mut tracked_pass, view_entity, item);
|
||||
}
|
||||
transparent_phase.render(world, render_context, view_entity, None, pass_descriptor);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user