Skip to content

Commit

Permalink
Track hdr on ExtractedCamera in order to properly determine when to t…
Browse files Browse the repository at this point in the history
…rigger MSAA writeback.
  • Loading branch information
tychedelia committed May 21, 2024
1 parent 8bdaffc commit d6159c4
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 77 deletions.
6 changes: 5 additions & 1 deletion crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,7 @@ pub struct ExtractedCamera {
pub clear_color: ClearColorConfig,
pub sorted_camera_index_for_target: usize,
pub exposure: f32,
pub hdr: bool,
}

pub fn extract_cameras(
Expand Down Expand Up @@ -902,6 +903,7 @@ pub fn extract_cameras(
exposure: exposure
.map(|e| e.exposure())
.unwrap_or_else(|| Exposure::default().exposure()),
hdr: camera.hdr,
},
ExtractedView {
projection: camera.projection_matrix(),
Expand Down Expand Up @@ -953,6 +955,7 @@ pub struct SortedCamera {
pub entity: Entity,
pub order: isize,
pub target: Option<NormalizedRenderTarget>,
pub hdr: bool,
}

pub fn sort_cameras(
Expand All @@ -965,6 +968,7 @@ pub fn sort_cameras(
entity,
order: camera.order,
target: camera.target.clone(),
hdr: camera.hdr,
});
}
// sort by order and ensure within an order, RenderTargets of the same type are packed together
Expand All @@ -985,7 +989,7 @@ pub fn sort_cameras(
}
}
if let Some(target) = &sorted_camera.target {
let count = target_counts.entry(target.clone()).or_insert(0usize);
let count = target_counts.entry((target.clone(), sorted_camera.hdr)).or_insert(0usize);
let (_, mut camera) = cameras.get_mut(sorted_camera.entity).unwrap();
camera.sorted_camera_index_for_target = *count;
*count += 1;
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/texture/texture_attachment.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::CachedTexture;
use crate::render_resource::{TextureFormat, TextureView};
use bevy_color::LinearRgba;
use bevy_utils::tracing::info;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
Expand Down Expand Up @@ -39,7 +40,6 @@ impl ColorAttachment {
pub fn get_attachment(&self) -> RenderPassColorAttachment {
if let Some(resolve_target) = self.resolve_target.as_ref() {
let first_call = self.is_first_call.fetch_and(false, Ordering::SeqCst);

RenderPassColorAttachment {
view: &resolve_target.default_view,
resolve_target: Some(&self.texture.default_view),
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_render/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use wgpu::{
BufferUsages, Extent3d, RenderPassColorAttachment, RenderPassDepthStencilAttachment, StoreOp,
TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
};
use bevy_utils::tracing::info;

pub const VIEW_TYPE_HANDLE: Handle<Shader> = Handle::weak_from_u128(15421373904451797197);

Expand Down Expand Up @@ -905,6 +906,12 @@ pub fn prepare_view_targets(
main_texture: main_texture.clone(),
};

info!(
"{} Creating view target for camera {:?} with target {:?}",
entity,
camera.order, sampled.as_ref().map(|x| x.default_view.id()),
);

commands.entity(entity).insert(ViewTarget {
main_texture: main_textures.main_texture.clone(),
main_textures,
Expand Down
117 changes: 42 additions & 75 deletions examples/3d/split_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ use std::f32::consts::PI;
use bevy::{
pbr::CascadeShadowConfigBuilder, prelude::*, render::camera::Viewport, window::WindowResized,
};
use bevy::color::palettes::css::{BLACK, BLUE, RED};
use bevy::render::camera::CameraOutputMode;
use bevy::render::render_resource::{BlendComponent, BlendFactor, BlendOperation, BlendState};

fn main() {
App::new()
.add_plugins(DefaultPlugins)
// .insert_resource(Msaa::Off)
.add_systems(Startup, setup)
.add_systems(Update, (set_camera_viewports, button_system))
.run();
Expand Down Expand Up @@ -46,33 +50,56 @@ fn setup(
maximum_distance: 280.0,
..default()
}
.into(),
.into(),
..default()
});

// Cameras and their dedicated UI
for (index, (camera_name, camera_pos)) in [
("Player 1", Vec3::new(0.0, 200.0, -150.0)),
("Player 2", Vec3::new(150.0, 150., 50.0)),
("Player 3", Vec3::new(100.0, 150., -150.0)),
("Player 4", Vec3::new(-100.0, 80., 150.0)),
for (index, (camera_name, camera_pos, hdr)) in [
("Player 1", Vec3::new(0.0, 200.0, -150.0), false),
("Player 2", Vec3::new(150.0, 150., 50.0), true),
("Player 3", Vec3::new(100.0, 150., -150.0), false),
("Player 4", Vec3::new(-100.0, 80., 150.0), true),
]
.iter()
.enumerate()
.iter()
.enumerate()
{
let camera = commands
.spawn((
Camera3dBundle {
transform: Transform::from_translation(*camera_pos)
.looking_at(Vec3::ZERO, Vec3::Y),
camera: Camera {
hdr: *hdr,
// Renders cameras with different priorities to prevent ambiguities
order: index as isize,
// Don't clear after the first camera because the first camera already cleared the entire window
clear_color: if index > 0 {
ClearColorConfig::None
} else {
clear_color: if index == 0 || index == 1 {
ClearColorConfig::default()
} else {
ClearColorConfig::None
},
output_mode: if index == 0 || index == 1 {
CameraOutputMode::Write {
clear_color: ClearColorConfig::Default,
blend_state: Some(BlendState::REPLACE),
}
} else {
CameraOutputMode::Write {
clear_color: ClearColorConfig::None,
blend_state: Some(BlendState {
color: BlendComponent {
src_factor: BlendFactor::SrcAlpha,
dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Max,
},
alpha: BlendComponent{
src_factor: BlendFactor::One,
dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Min,
},
})
}
},
..default()
},
Expand All @@ -83,53 +110,6 @@ fn setup(
},
))
.id();

// Set up UI
commands
.spawn((
TargetCamera(camera),
NodeBundle {
style: Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
padding: UiRect::all(Val::Px(20.)),
..default()
},
..default()
},
))
.with_children(|parent| {
parent.spawn(TextBundle::from_section(
*camera_name,
TextStyle {
font_size: 20.,
..default()
},
));
buttons_panel(parent);
});
}

fn buttons_panel(parent: &mut ChildBuilder) {
parent
.spawn(NodeBundle {
style: Style {
position_type: PositionType::Absolute,
width: Val::Percent(100.),
height: Val::Percent(100.),
display: Display::Flex,
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::SpaceBetween,
align_items: AlignItems::Center,
padding: UiRect::all(Val::Px(20.)),
..default()
},
..default()
})
.with_children(|parent| {
rotate_button(parent, "<", Direction::Left);
rotate_button(parent, ">", Direction::Right);
});
}

fn rotate_button(parent: &mut ChildBuilder, caption: &str, direction: Direction) {
Expand Down Expand Up @@ -199,23 +179,10 @@ fn set_camera_viewports(

#[allow(clippy::type_complexity)]
fn button_system(
interaction_query: Query<
(&Interaction, &TargetCamera, &RotateCamera),
(Changed<Interaction>, With<Button>),
>,
mut camera_query: Query<&mut Transform, With<Camera>>,
mut camera_query: Query<(&Camera, &mut Transform)>,
) {
for (interaction, target_camera, RotateCamera(direction)) in &interaction_query {
if let Interaction::Pressed = *interaction {
// Since TargetCamera propagates to the children, we can use it to find
// which side of the screen the button is on.
if let Ok(mut camera_transform) = camera_query.get_mut(target_camera.entity()) {
let angle = match direction {
Direction::Left => -0.1,
Direction::Right => 0.1,
};
camera_transform.rotate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, angle));
}
}
for (camera, mut camera_transform) in camera_query.iter_mut() {
let angle = if camera.order % 2 == 0 { -0.1 } else { 0.1 };
camera_transform.rotate_around(Vec3::ZERO, Quat::from_axis_angle(Vec3::Y, angle));
}
}

0 comments on commit d6159c4

Please sign in to comment.