Skip to content

Commit

Permalink
Add "depth_load_op" configuration to 3d Cameras (bevyengine#4904)
Browse files Browse the repository at this point in the history
# 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.
  • Loading branch information
cart authored and james7132 committed Oct 28, 2022
1 parent ea6118c commit 9990ab0
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 4 deletions.
36 changes: 34 additions & 2 deletions crates/bevy_core_pipeline/src/core_3d/camera_3d.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_core_pipeline/src/core_3d/main_pass_3d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions examples/3d/render_to_texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions examples/3d/split_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
Expand Down
1 change: 1 addition & 0 deletions examples/3d/two_passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions examples/shader/post_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down

0 comments on commit 9990ab0

Please sign in to comment.