Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Camera Driven Rendering #4745

Closed
wants to merge 17 commits into from
Closed
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
5 changes: 5 additions & 0 deletions crates/bevy_core_pipeline/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ trace = []
# bevy
bevy_app = { path = "../bevy_app", version = "0.8.0-dev" }
bevy_asset = { path = "../bevy_asset", version = "0.8.0-dev" }
bevy_derive = { path = "../bevy_derive", version = "0.8.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.8.0-dev" }
bevy_reflect = { path = "../bevy_reflect", version = "0.8.0-dev" }
bevy_render = { path = "../bevy_render", version = "0.8.0-dev" }
bevy_transform = { path = "../bevy_transform", version = "0.8.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }

serde = { version = "1", features = ["derive"] }

32 changes: 32 additions & 0 deletions crates/bevy_core_pipeline/src/clear_color.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::prelude::*;
use bevy_reflect::{Reflect, ReflectDeserialize};
use bevy_render::{color::Color, extract_resource::ExtractResource};
use serde::{Deserialize, Serialize};

#[derive(Reflect, Serialize, Deserialize, Clone, Debug)]
#[reflect_value(Serialize, Deserialize)]
pub enum ClearColorConfig {
Default,
Custom(Color),
None,
}

impl Default for ClearColorConfig {
fn default() -> Self {
ClearColorConfig::Default
}
}

/// When used as a resource, sets the color that is used to clear the screen between frames.
///
/// This color appears as the "background" color for simple apps, when
/// there are portions of the screen with nothing rendered.
#[derive(Component, Clone, Debug, Deref, DerefMut, ExtractResource)]
pub struct ClearColor(pub Color);

impl Default for ClearColor {
fn default() -> Self {
Self(Color::rgb(0.4, 0.4, 0.4))
}
}
128 changes: 0 additions & 128 deletions crates/bevy_core_pipeline/src/clear_pass.rs

This file was deleted.

20 changes: 0 additions & 20 deletions crates/bevy_core_pipeline/src/clear_pass_driver.rs

This file was deleted.

82 changes: 82 additions & 0 deletions crates/bevy_core_pipeline/src/core_2d/camera_2d.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use crate::clear_color::ClearColorConfig;
use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_reflect::Reflect;
use bevy_render::{
camera::{
Camera, CameraProjection, CameraRenderGraph, DepthCalculation, OrthographicProjection,
},
extract_component::ExtractComponent,
primitives::Frustum,
view::VisibleEntities,
};
use bevy_transform::prelude::{GlobalTransform, Transform};

#[derive(Component, Default, Reflect, Clone)]
#[reflect(Component)]
pub struct Camera2d {
pub clear_color: ClearColorConfig,
}

impl ExtractComponent for Camera2d {
type Query = &'static Self;
type Filter = With<Camera>;

fn extract_component(item: QueryItem<Self::Query>) -> Self {
item.clone()
}
}

#[derive(Bundle)]
pub struct Camera2dBundle {
pub camera: Camera,
pub camera_render_graph: CameraRenderGraph,
pub projection: OrthographicProjection,
pub visible_entities: VisibleEntities,
pub frustum: Frustum,
pub transform: Transform,
pub global_transform: GlobalTransform,
pub camera_2d: Camera2d,
}

impl Default for Camera2dBundle {
fn default() -> Self {
Self::new_with_far(1000.0)
}
}

impl Camera2dBundle {
/// Create an orthographic projection camera with a custom Z position.
///
/// The camera is placed at `Z=far-0.1`, looking toward the world origin `(0,0,0)`.
/// Its orthographic projection extends from `0.0` to `-far` in camera view space,
/// corresponding to `Z=far-0.1` (closest to camera) to `Z=-0.1` (furthest away from
/// camera) in world space.
cart marked this conversation as resolved.
Show resolved Hide resolved
pub fn new_with_far(far: f32) -> Self {
// we want 0 to be "closest" and +far to be "farthest" in 2d, so we offset
// the camera's translation by far and use a right handed coordinate system
let projection = OrthographicProjection {
far,
depth_calculation: DepthCalculation::ZDifference,
..Default::default()
};
let transform = Transform::from_xyz(0.0, 0.0, far - 0.1);
let view_projection =
projection.get_projection_matrix() * transform.compute_matrix().inverse();
let frustum = Frustum::from_view_projection(
&view_projection,
&transform.translation,
&transform.back(),
projection.far(),
);
Self {
camera_render_graph: CameraRenderGraph::new(crate::core_2d::graph::NAME),
projection,
visible_entities: VisibleEntities::default(),
frustum,
transform,
global_transform: Default::default(),
camera: Camera::default(),
camera_2d: Camera2d::default(),
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::Transparent2d;
use crate::{
clear_color::{ClearColor, ClearColorConfig},
core_2d::{camera_2d::Camera2d, Transparent2d},
};
use bevy_ecs::prelude::*;
use bevy_render::{
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
Expand All @@ -9,16 +12,22 @@ use bevy_render::{
};

pub struct MainPass2dNode {
query:
QueryState<(&'static RenderPhase<Transparent2d>, &'static ViewTarget), With<ExtractedView>>,
query: QueryState<
(
&'static RenderPhase<Transparent2d>,
&'static ViewTarget,
&'static Camera2d,
),
With<ExtractedView>,
>,
}

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

pub fn new(world: &mut World) -> Self {
Self {
query: QueryState::new(world),
query: world.query_filtered(),
}
}
}
Expand All @@ -39,20 +48,24 @@ impl Node for MainPass2dNode {
world: &World,
) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
// If there is no view entity, do not try to process the render phase for the view
let (transparent_phase, target) = match self.query.get_manual(world, view_entity) {
Ok(it) => it,
_ => return Ok(()),
};

if transparent_phase.items.is_empty() {
return Ok(());
}
let (transparent_phase, target, camera_2d) =
if let Ok(result) = self.query.get_manual(world, view_entity) {
result
} else {
// no target
return Ok(());
};

let pass_descriptor = RenderPassDescriptor {
label: Some("main_pass_2d"),
color_attachments: &[target.get_color_attachment(Operations {
load: LoadOp::Load,
load: match camera_2d.clear_color {
ClearColorConfig::Default => {
LoadOp::Clear(world.resource::<ClearColor>().0.into())
}
ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()),
ClearColorConfig::None => LoadOp::Load,
},
store: true,
})],
depth_stencil_attachment: None,
Expand Down
Loading