mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 14:10:19 +00:00
Add ClearColor Resource to Pipelined Renderer (#2631)
# Objective - Allow the user to set the clear color when using the pipelined renderer ## Solution - Add a `ClearColor` resource that can be added to the world to configure the clear color ## Remaining Issues Currently the `ClearColor` resource is cloned from the app world to the render world every frame. There are two ways I can think of around this: 1. Figure out why `app_world.is_resource_changed::<ClearColor>()` always returns `true` in the `extract` step and fix it so that we are only updating the resource when it changes 2. Require the users to add the `ClearColor` resource to the render sub-app instead of the parent app. This is currently sub-optimal until we have labled sub-apps, and probably a helper funciton on `App` such as `app.with_sub_app(RenderApp, |app| { ... })`. Even if we had that, I think it would be more than we want the user to have to think about. They shouldn't have to know about the render sub-app I don't think. I think the first option is the best, but I could really use some help figuring out the nuance of why `is_resource_changed` is always returning true in that context.
This commit is contained in:
parent
5fa0b5b498
commit
3faca93f7b
6 changed files with 59 additions and 7 deletions
|
@ -493,6 +493,10 @@ path = "examples/ui/ui.rs"
|
|||
name = "clear_color"
|
||||
path = "examples/window/clear_color.rs"
|
||||
|
||||
[[example]]
|
||||
name = "clear_color_pipelined"
|
||||
path = "examples/window/clear_color_pipelined.rs"
|
||||
|
||||
[[example]]
|
||||
name = "multiple_windows"
|
||||
path = "examples/window/multiple_windows.rs"
|
||||
|
|
|
@ -254,6 +254,7 @@ Example | File | Description
|
|||
Example | File | Description
|
||||
--- | --- | ---
|
||||
`clear_color` | [`window/clear_color.rs`](./window/clear_color.rs) | Creates a solid color window
|
||||
`clear_color_pipelined` | [`window/clear_color_pipelined.rs`](./window/clear_color_pipelined.rs) | Creates a solid color window with the pipelined renderer
|
||||
`multiple_windows` | [`window/multiple_windows.rs`](./window/multiple_windows.rs) | Creates two windows and cameras viewing the same mesh
|
||||
`scale_factor_override` | [`window/scale_factor_override.rs`](./window/scale_factor_override.rs) | Illustrates how to customize the default window settings
|
||||
`window_settings` | [`window/window_settings.rs`](./window/window_settings.rs) | Demonstrates customizing default window settings
|
||||
|
|
25
examples/window/clear_color_pipelined.rs
Normal file
25
examples/window/clear_color_pipelined.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use bevy::{
|
||||
core_pipeline::ClearColor,
|
||||
prelude::*,
|
||||
render2::{camera::OrthographicCameraBundle, color::Color},
|
||||
PipelinedDefaultPlugins,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(ClearColor(Color::rgb(0.5, 0.5, 0.9)))
|
||||
.add_plugins(PipelinedDefaultPlugins)
|
||||
.add_startup_system(setup)
|
||||
.add_system(change_clear_color)
|
||||
.run();
|
||||
}
|
||||
|
||||
fn setup(mut commands: Commands) {
|
||||
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||
}
|
||||
|
||||
fn change_clear_color(input: Res<Input<KeyCode>>, mut clear_color: ResMut<ClearColor>) {
|
||||
if input.just_pressed(KeyCode::Space) {
|
||||
clear_color.0 = Color::PURPLE;
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ use bevy_app::{App, Plugin};
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_render2::{
|
||||
camera::{ActiveCameras, CameraPlugin},
|
||||
color::Color,
|
||||
render_graph::{EmptyNode, RenderGraph, SlotInfo, SlotType},
|
||||
render_phase::{sort_phase_system, RenderPhase},
|
||||
render_resource::{
|
||||
|
@ -19,9 +20,19 @@ use bevy_render2::{
|
|||
renderer::RenderDevice,
|
||||
texture::TextureCache,
|
||||
view::{ExtractedView, ViewPlugin},
|
||||
RenderStage,
|
||||
RenderStage, RenderWorld,
|
||||
};
|
||||
|
||||
/// Resource that configures the clear color
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClearColor(pub Color);
|
||||
|
||||
impl Default for ClearColor {
|
||||
fn default() -> Self {
|
||||
Self(Color::rgb(0.4, 0.4, 0.4))
|
||||
}
|
||||
}
|
||||
|
||||
// Plugins that contribute to the RenderGraph should use the following label conventions:
|
||||
// 1. Graph modules should have a NAME, input module, and node module (where relevant)
|
||||
// 2. The "top level" graph is the plugin module root. Just add things like `pub mod node` directly under the plugin module
|
||||
|
@ -61,8 +72,11 @@ pub struct CorePipelinePlugin;
|
|||
|
||||
impl Plugin for CorePipelinePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_resource::<ClearColor>();
|
||||
|
||||
let render_app = app.sub_app_mut(0);
|
||||
render_app
|
||||
.add_system_to_stage(RenderStage::Extract, extract_clear_color)
|
||||
.add_system_to_stage(RenderStage::Extract, extract_core_pipeline_camera_phases)
|
||||
.add_system_to_stage(RenderStage::Prepare, prepare_core_views_system)
|
||||
.add_system_to_stage(
|
||||
|
@ -154,6 +168,14 @@ pub struct ViewDepthTexture {
|
|||
pub view: TextureView,
|
||||
}
|
||||
|
||||
pub fn extract_clear_color(clear_color: Res<ClearColor>, mut render_world: ResMut<RenderWorld>) {
|
||||
// If the clear color has changed
|
||||
if clear_color.is_changed() {
|
||||
// Update the clear color resource in the render world
|
||||
render_world.insert_resource(clear_color.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_core_pipeline_camera_phases(
|
||||
mut commands: Commands,
|
||||
active_cameras: Res<ActiveCameras>,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::Transparent2dPhase;
|
||||
use crate::{ClearColor, Transparent2dPhase};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_render2::{
|
||||
color::Color,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_phase::{DrawFunctions, RenderPhase, TrackedRenderPass},
|
||||
render_resource::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor},
|
||||
|
@ -43,13 +42,14 @@ impl Node for MainPass2dNode {
|
|||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let color_attachment_texture = graph.get_input_texture(Self::IN_COLOR_ATTACHMENT)?;
|
||||
let clear_color = world.get_resource::<ClearColor>().unwrap();
|
||||
let pass_descriptor = RenderPassDescriptor {
|
||||
label: Some("main_pass_2d"),
|
||||
color_attachments: &[RenderPassColorAttachment {
|
||||
view: color_attachment_texture,
|
||||
resolve_target: None,
|
||||
ops: Operations {
|
||||
load: LoadOp::Clear(Color::rgb(0.4, 0.4, 0.4).into()),
|
||||
load: LoadOp::Clear(clear_color.0.into()),
|
||||
store: true,
|
||||
},
|
||||
}],
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::Transparent3dPhase;
|
||||
use crate::{ClearColor, Transparent3dPhase};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_render2::{
|
||||
color::Color,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_phase::{DrawFunctions, RenderPhase, TrackedRenderPass},
|
||||
render_resource::{
|
||||
|
@ -48,6 +47,7 @@ impl Node for MainPass3dNode {
|
|||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let color_attachment_texture = graph.get_input_texture(Self::IN_COLOR_ATTACHMENT)?;
|
||||
let clear_color = world.get_resource::<ClearColor>().unwrap();
|
||||
let depth_texture = graph.get_input_texture(Self::IN_DEPTH)?;
|
||||
let pass_descriptor = RenderPassDescriptor {
|
||||
label: Some("main_pass_3d"),
|
||||
|
@ -55,7 +55,7 @@ impl Node for MainPass3dNode {
|
|||
view: color_attachment_texture,
|
||||
resolve_target: None,
|
||||
ops: Operations {
|
||||
load: LoadOp::Clear(Color::rgb(0.4, 0.4, 0.4).into()),
|
||||
load: LoadOp::Clear(clear_color.0.into()),
|
||||
store: true,
|
||||
},
|
||||
}],
|
||||
|
|
Loading…
Reference in a new issue