mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
Add "depth_load_op" configuration to 3d Cameras (#4904)
# Objective Users should be able to configure depth load operations on cameras. Currently every camera clears depth when it is rendered. But sometimes later passes need to rely on depth from previous passes. ## Solution This adds the `Camera3d::depth_load_op` field with a new `Camera3dDepthLoadOp` value. This is a custom type because Camera3d uses "reverse-z depth" and this helps us record and document that in a discoverable way. It also gives us more control over reflection + other trait impls, whereas `LoadOp` is owned by the `wgpu` crate. ```rust commands.spawn_bundle(Camera3dBundle { camera_3d: Camera3d { depth_load_op: Camera3dDepthLoadOp::Load, ..default() }, ..default() }); ``` ### two_passes example with the "second pass" camera configured to the default (clear depth to 0.0) ![image](https://user-images.githubusercontent.com/2694663/171743172-46d4fdd5-5090-46ea-abe4-1fbc519f6ee8.png) ### two_passes example with the "second pass" camera configured to "load" the depth ![image](https://user-images.githubusercontent.com/2694663/171743323-74dd9a1d-9c25-4883-98dd-38ca0bed8c17.png) --- ## Changelog ### Added * `Camera3d` now has a `depth_load_op` field, which can configure the Camera's main 3d pass depth loading behavior.
This commit is contained in:
parent
cbf032419d
commit
f28b921209
6 changed files with 40 additions and 4 deletions
|
@ -1,18 +1,50 @@
|
|||
use crate::clear_color::ClearColorConfig;
|
||||
use bevy_ecs::{prelude::*, query::QueryItem};
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize};
|
||||
use bevy_render::{
|
||||
camera::{Camera, CameraRenderGraph, Projection},
|
||||
extract_component::ExtractComponent,
|
||||
primitives::Frustum,
|
||||
render_resource::LoadOp,
|
||||
view::VisibleEntities,
|
||||
};
|
||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Component, Default, Reflect, Clone)]
|
||||
/// Configuration for the "main 3d render graph".
|
||||
#[derive(Component, Reflect, Clone, Default)]
|
||||
#[reflect(Component)]
|
||||
pub struct Camera3d {
|
||||
/// The clear color operation to perform for the main 3d pass.
|
||||
pub clear_color: ClearColorConfig,
|
||||
/// The depth clear operation to perform for the main 3d pass.
|
||||
pub depth_load_op: Camera3dDepthLoadOp,
|
||||
}
|
||||
|
||||
/// The depth clear operation to perform for the main 3d pass.
|
||||
#[derive(Reflect, Serialize, Deserialize, Clone, Debug)]
|
||||
#[reflect_value(Serialize, Deserialize)]
|
||||
pub enum Camera3dDepthLoadOp {
|
||||
/// Clear with a specified value.
|
||||
/// Note that 0.0 is the far plane due to bevy's use of reverse-z projections.
|
||||
Clear(f32),
|
||||
/// Load from memory.
|
||||
Load,
|
||||
}
|
||||
|
||||
impl Default for Camera3dDepthLoadOp {
|
||||
fn default() -> Self {
|
||||
Camera3dDepthLoadOp::Clear(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Camera3dDepthLoadOp> for LoadOp<f32> {
|
||||
fn from(config: Camera3dDepthLoadOp) -> Self {
|
||||
match config {
|
||||
Camera3dDepthLoadOp::Clear(x) => LoadOp::Clear(x),
|
||||
Camera3dDepthLoadOp::Load => LoadOp::Load,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractComponent for Camera3d {
|
||||
|
|
|
@ -87,8 +87,8 @@ impl Node for MainPass3dNode {
|
|||
view: &depth.view,
|
||||
// NOTE: The opaque main pass loads the depth buffer and possibly overwrites it
|
||||
depth_ops: Some(Operations {
|
||||
// NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections
|
||||
load: LoadOp::Clear(0.0),
|
||||
// NOTE: 0.0 is the far plane due to bevy's use of reverse-z projections.
|
||||
load: camera_3d.depth_load_op.clone().into(),
|
||||
store: true,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
|
|
|
@ -95,6 +95,7 @@ fn setup(
|
|||
.spawn_bundle(Camera3dBundle {
|
||||
camera_3d: Camera3d {
|
||||
clear_color: ClearColorConfig::Custom(Color::WHITE),
|
||||
..default()
|
||||
},
|
||||
camera: Camera {
|
||||
// render before the "main pass" camera
|
||||
|
|
|
@ -66,6 +66,7 @@ fn setup(
|
|||
camera_3d: Camera3d {
|
||||
// dont clear on the second camera because the first camera already cleared the window
|
||||
clear_color: ClearColorConfig::None,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
|
|
|
@ -49,6 +49,7 @@ fn setup(
|
|||
transform: Transform::from_xyz(10.0, 10., -5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
camera_3d: Camera3d {
|
||||
clear_color: ClearColorConfig::None,
|
||||
..default()
|
||||
},
|
||||
camera: Camera {
|
||||
// renders after / on top of the main camera
|
||||
|
|
|
@ -102,6 +102,7 @@ fn setup(
|
|||
commands.spawn_bundle(Camera3dBundle {
|
||||
camera_3d: Camera3d {
|
||||
clear_color: ClearColorConfig::Custom(Color::WHITE),
|
||||
..default()
|
||||
},
|
||||
camera: Camera {
|
||||
target: RenderTarget::Image(image_handle.clone()),
|
||||
|
|
Loading…
Reference in a new issue