Skip to content

Commit

Permalink
Merge pull request #1 from IceSentry/gizmo-node
Browse files Browse the repository at this point in the history
Gizmo render node
  • Loading branch information
tim-blackbird authored Feb 26, 2023
2 parents 95ebbde + ef546ce commit 2f1a35d
Show file tree
Hide file tree
Showing 12 changed files with 464 additions and 48 deletions.
1 change: 1 addition & 0 deletions crates/bevy_core_pipeline/src/core_2d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod graph {
pub const BLOOM: &str = "bloom";
pub const TONEMAPPING: &str = "tonemapping";
pub const FXAA: &str = "fxaa";
pub const GIZMO: &str = "gizmo";
pub const UPSCALING: &str = "upscaling";
pub const END_MAIN_PASS_POST_PROCESSING: &str = "end_main_pass_post_processing";
}
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_core_pipeline/src/core_3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod graph {
pub const BLOOM: &str = "bloom";
pub const TONEMAPPING: &str = "tonemapping";
pub const FXAA: &str = "fxaa";
pub const GIZMO: &str = "gizmo";
pub const UPSCALING: &str = "upscaling";
pub const END_MAIN_PASS_POST_PROCESSING: &str = "end_main_pass_post_processing";
}
Expand Down
104 changes: 104 additions & 0 deletions crates/bevy_core_pipeline/src/gizmo_2d/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use bevy_app::Plugin;
use bevy_ecs::{
prelude::Entity,
query::With,
system::{Commands, Query},
};
use bevy_render::{
prelude::Camera,
render_graph::RenderGraph,
render_phase::{
sort_phase_system, CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem,
RenderPhase,
},
render_resource::*,
Extract, ExtractSchedule, RenderApp,
};
use bevy_utils::FloatOrd;

use crate::core_2d::{self, Camera2d};

use self::node::Gizmo2dNode;

pub mod node;

pub struct Gizmo2dPlugin;

impl Plugin for Gizmo2dPlugin {
fn build(&self, app: &mut bevy_app::App) {
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else { return; };

render_app
.init_resource::<DrawFunctions<GizmoLine2d>>()
.add_system(sort_phase_system::<GizmoLine2d>)
.add_system_to_schedule(ExtractSchedule, extract_gizmo_line_2d_camera_phase);

let gizmo_node = Gizmo2dNode::new(&mut render_app.world);
let mut binding = render_app.world.resource_mut::<RenderGraph>();
let graph = binding.get_sub_graph_mut(core_2d::graph::NAME).unwrap();

graph.add_node(core_2d::graph::node::GIZMO, gizmo_node);
graph.add_slot_edge(
graph.input_node().id,
core_2d::graph::input::VIEW_ENTITY,
core_2d::graph::node::GIZMO,
Gizmo2dNode::IN_VIEW,
);
graph.add_node_edge(
core_2d::graph::node::END_MAIN_PASS_POST_PROCESSING,
core_2d::graph::node::GIZMO,
);
graph.add_node_edge(core_2d::graph::node::GIZMO, core_2d::graph::node::UPSCALING);
}
}

pub struct GizmoLine2d {
pub sort_key: FloatOrd,
pub pipeline: CachedRenderPipelineId,
pub entity: Entity,
pub draw_function: DrawFunctionId,
}

impl PhaseItem for GizmoLine2d {
type SortKey = FloatOrd;

#[inline]
fn entity(&self) -> Entity {
self.entity
}

#[inline]
fn sort_key(&self) -> Self::SortKey {
self.sort_key
}

#[inline]
fn draw_function(&self) -> DrawFunctionId {
self.draw_function
}

#[inline]
fn sort(items: &mut [Self]) {
items.sort_by_key(|item| item.sort_key());
}
}

impl CachedRenderPipelinePhaseItem for GizmoLine2d {
#[inline]
fn cached_pipeline(&self) -> CachedRenderPipelineId {
self.pipeline
}
}

pub fn extract_gizmo_line_2d_camera_phase(
mut commands: Commands,
cameras_2d: Extract<Query<(Entity, &Camera), With<Camera2d>>>,
) {
for (entity, camera) in &cameras_2d {
if camera.is_active {
commands
.get_or_spawn(entity)
.insert(RenderPhase::<GizmoLine2d>::default());
}
}
}
68 changes: 68 additions & 0 deletions crates/bevy_core_pipeline/src/gizmo_2d/node.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use bevy_ecs::prelude::*;
use bevy_render::{
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
render_phase::RenderPhase,
render_resource::{LoadOp, Operations, RenderPassDescriptor},
renderer::RenderContext,
view::{ExtractedView, ViewTarget},
};
#[cfg(feature = "trace")]
use bevy_utils::tracing::info_span;

use super::GizmoLine2d;

pub struct Gizmo2dNode {
view_query:
QueryState<(&'static ViewTarget, &'static RenderPhase<GizmoLine2d>), With<ExtractedView>>,
}

impl Gizmo2dNode {
pub const IN_VIEW: &'static str = "view";

pub fn new(world: &mut World) -> Self {
Self {
view_query: QueryState::new(world),
}
}
}

impl Node for Gizmo2dNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(Self::IN_VIEW, SlotType::Entity)]
}

fn update(&mut self, world: &mut World) {
self.view_query.update_archetypes(world);
}

fn run(
&self,
graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
world: &World,
) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
let Ok((
view_target,
gizmo_phase,
)) = self.view_query.get_manual(world, view_entity) else {
return Ok(());
};
{
#[cfg(feature = "trace")]
let _gizmo_line_2d_pass = info_span!("gizmo_line_2d_pass").entered();

let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
label: Some("gizmo_line_2d"),
color_attachments: &[Some(view_target.get_color_attachment(Operations {
load: LoadOp::Load,
store: true,
}))],
depth_stencil_attachment: None,
});

gizmo_phase.render(&mut render_pass, world, view_entity);
}
Ok(())
}
}
109 changes: 109 additions & 0 deletions crates/bevy_core_pipeline/src/gizmo_3d/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use std::cmp::Reverse;

use bevy_app::Plugin;
use bevy_ecs::{
prelude::Entity,
query::With,
system::{Commands, Query},
};
use bevy_render::{
prelude::Camera,
render_graph::RenderGraph,
render_phase::{
sort_phase_system, CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem,
RenderPhase,
},
render_resource::*,
Extract, ExtractSchedule, RenderApp,
};
use bevy_utils::FloatOrd;
use core_3d::Camera3d;

use crate::core_3d;

use self::node::Gizmo3dNode;

mod node;

pub struct Gizmo3dPlugin;

impl Plugin for Gizmo3dPlugin {
fn build(&self, app: &mut bevy_app::App) {
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else { return; };

render_app
.init_resource::<DrawFunctions<GizmoLine3d>>()
.add_system(sort_phase_system::<GizmoLine3d>)
.add_system_to_schedule(ExtractSchedule, extract_gizmo_line_3d_camera_phase);

let gizmo_node = Gizmo3dNode::new(&mut render_app.world);
let mut binding = render_app.world.resource_mut::<RenderGraph>();
let graph = binding.get_sub_graph_mut(core_3d::graph::NAME).unwrap();

graph.add_node(core_3d::graph::node::GIZMO, gizmo_node);
graph.add_slot_edge(
graph.input_node().id,
core_3d::graph::input::VIEW_ENTITY,
core_3d::graph::node::GIZMO,
Gizmo3dNode::IN_VIEW,
);
graph.add_node_edge(
core_3d::graph::node::END_MAIN_PASS_POST_PROCESSING,
core_3d::graph::node::GIZMO,
);
graph.add_node_edge(core_3d::graph::node::GIZMO, core_3d::graph::node::UPSCALING);
}
}

pub struct GizmoLine3d {
pub distance: f32,
pub pipeline: CachedRenderPipelineId,
pub entity: Entity,
pub draw_function: DrawFunctionId,
}

impl PhaseItem for GizmoLine3d {
// NOTE: Values increase towards the camera. Front-to-back ordering for opaque means we need a descending sort.
type SortKey = Reverse<FloatOrd>;

#[inline]
fn entity(&self) -> Entity {
self.entity
}

#[inline]
fn sort_key(&self) -> Self::SortKey {
Reverse(FloatOrd(self.distance))
}

#[inline]
fn draw_function(&self) -> DrawFunctionId {
self.draw_function
}

#[inline]
fn sort(items: &mut [Self]) {
// Key negated to match reversed SortKey ordering
radsort::sort_by_key(items, |item| -item.distance);
}
}

impl CachedRenderPipelinePhaseItem for GizmoLine3d {
#[inline]
fn cached_pipeline(&self) -> CachedRenderPipelineId {
self.pipeline
}
}

pub fn extract_gizmo_line_3d_camera_phase(
mut commands: Commands,
cameras_3d: Extract<Query<(Entity, &Camera), With<Camera3d>>>,
) {
for (entity, camera) in &cameras_3d {
if camera.is_active {
commands
.get_or_spawn(entity)
.insert(RenderPhase::<GizmoLine3d>::default());
}
}
}
85 changes: 85 additions & 0 deletions crates/bevy_core_pipeline/src/gizmo_3d/node.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use bevy_ecs::prelude::*;
use bevy_render::{
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
render_phase::RenderPhase,
render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor},
renderer::RenderContext,
view::{ExtractedView, ViewDepthTexture, ViewTarget},
};
#[cfg(feature = "trace")]
use bevy_utils::tracing::info_span;

use crate::core_3d::Camera3dDepthLoadOp;

use super::GizmoLine3d;

pub struct Gizmo3dNode {
view_query: QueryState<
(
&'static ViewTarget,
&'static RenderPhase<GizmoLine3d>,
&'static ViewDepthTexture,
),
With<ExtractedView>,
>,
}

impl Gizmo3dNode {
pub const IN_VIEW: &'static str = "view";

pub fn new(world: &mut World) -> Self {
Self {
view_query: QueryState::new(world),
}
}
}

impl Node for Gizmo3dNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(Self::IN_VIEW, SlotType::Entity)]
}

fn update(&mut self, world: &mut World) {
self.view_query.update_archetypes(world);
}

fn run(
&self,
graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
world: &World,
) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
let Ok((
view_target,
gizmo_phase,
depth,
)) = self.view_query.get_manual(world, view_entity) else {
return Ok(());
};

{
#[cfg(feature = "trace")]
let _gizmo_line_3d_pass = info_span!("gizmo_line_3d_pass").entered();

let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
label: Some("gizmo_line_3d"),
color_attachments: &[Some(view_target.get_color_attachment(Operations {
load: LoadOp::Load,
store: true,
}))],
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &depth.view,
depth_ops: Some(Operations {
load: Camera3dDepthLoadOp::Load.into(),
store: false,
}),
stencil_ops: None,
}),
});

gizmo_phase.render(&mut render_pass, world, view_entity);
}
Ok(())
}
}
2 changes: 2 additions & 0 deletions crates/bevy_core_pipeline/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub mod core_2d;
pub mod core_3d;
pub mod fullscreen_vertex_shader;
pub mod fxaa;
pub mod gizmo_2d;
pub mod gizmo_3d;
pub mod prepass;
pub mod tonemapping;
pub mod upscaling;
Expand Down
Loading

0 comments on commit 2f1a35d

Please sign in to comment.