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 Viewports #4898

Closed
wants to merge 12 commits into from
12 changes: 8 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ path = "examples/2d/texture_atlas.rs"
name = "3d_scene"
path = "examples/3d/3d_scene.rs"

[[example]]
name = "3d_shapes"
path = "examples/3d/shapes.rs"

[[example]]
name = "lighting"
path = "examples/3d/lighting.rs"
Expand Down Expand Up @@ -208,10 +212,6 @@ path = "examples/3d/render_to_texture.rs"
name = "shadow_biases"
path = "examples/3d/shadow_biases.rs"

[[example]]
name = "3d_shapes"
path = "examples/3d/shapes.rs"

[[example]]
name = "shadow_caster_receiver"
path = "examples/3d/shadow_caster_receiver.rs"
Expand All @@ -220,6 +220,10 @@ path = "examples/3d/shadow_caster_receiver.rs"
name = "spherical_area_lights"
path = "examples/3d/spherical_area_lights.rs"

[[example]]
name = "split_screen"
path = "examples/3d/split_screen.rs"

[[example]]
name = "texture"
path = "examples/3d/texture.rs"
Expand Down
7 changes: 6 additions & 1 deletion crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
};
use bevy_ecs::prelude::*;
use bevy_render::{
camera::ExtractedCamera,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
render_phase::{DrawFunctions, RenderPhase, TrackedRenderPass},
render_resource::{LoadOp, Operations, RenderPassDescriptor},
Expand All @@ -14,6 +15,7 @@ use bevy_render::{
pub struct MainPass2dNode {
query: QueryState<
(
&'static ExtractedCamera,
&'static RenderPhase<Transparent2d>,
&'static ViewTarget,
&'static Camera2d,
Expand Down Expand Up @@ -48,7 +50,7 @@ impl Node for MainPass2dNode {
world: &World,
) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
let (transparent_phase, target, camera_2d) =
let (camera, transparent_phase, target, camera_2d) =
if let Ok(result) = self.query.get_manual(world, view_entity) {
result
} else {
Expand Down Expand Up @@ -79,6 +81,9 @@ impl Node for MainPass2dNode {

let mut draw_functions = draw_functions.write();
let mut tracked_pass = TrackedRenderPass::new(render_pass);
if let Some(viewport) = camera.viewport.as_ref() {
tracked_pass.set_camera_viewport(viewport);
}
for item in &transparent_phase.items {
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
draw_function.draw(world, &mut tracked_pass, view_entity, item);
Expand Down
13 changes: 12 additions & 1 deletion crates/bevy_core_pipeline/src/core_3d/main_pass_3d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
};
use bevy_ecs::prelude::*;
use bevy_render::{
camera::ExtractedCamera,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
render_phase::{DrawFunctions, RenderPhase, TrackedRenderPass},
render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor},
Expand All @@ -16,6 +17,7 @@ use bevy_utils::tracing::info_span;
pub struct MainPass3dNode {
query: QueryState<
(
&'static ExtractedCamera,
&'static RenderPhase<Opaque3d>,
&'static RenderPhase<AlphaMask3d>,
&'static RenderPhase<Transparent3d>,
Expand Down Expand Up @@ -53,7 +55,7 @@ impl Node for MainPass3dNode {
world: &World,
) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
let (opaque_phase, alpha_mask_phase, transparent_phase, camera_3d, target, depth) =
let (camera, opaque_phase, alpha_mask_phase, transparent_phase, camera_3d, target, depth) =
match self.query.get_manual(world, view_entity) {
Ok(query) => query,
Err(_) => {
Expand Down Expand Up @@ -100,6 +102,9 @@ impl Node for MainPass3dNode {
.begin_render_pass(&pass_descriptor);
let mut draw_functions = draw_functions.write();
let mut tracked_pass = TrackedRenderPass::new(render_pass);
if let Some(viewport) = camera.viewport.as_ref() {
tracked_pass.set_camera_viewport(viewport);
}
for item in &opaque_phase.items {
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
draw_function.draw(world, &mut tracked_pass, view_entity, item);
Expand Down Expand Up @@ -136,6 +141,9 @@ impl Node for MainPass3dNode {
.begin_render_pass(&pass_descriptor);
let mut draw_functions = draw_functions.write();
let mut tracked_pass = TrackedRenderPass::new(render_pass);
if let Some(viewport) = camera.viewport.as_ref() {
tracked_pass.set_camera_viewport(viewport);
}
for item in &alpha_mask_phase.items {
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
draw_function.draw(world, &mut tracked_pass, view_entity, item);
Expand Down Expand Up @@ -177,6 +185,9 @@ impl Node for MainPass3dNode {
.begin_render_pass(&pass_descriptor);
let mut draw_functions = draw_functions.write();
let mut tracked_pass = TrackedRenderPass::new(render_pass);
if let Some(viewport) = camera.viewport.as_ref() {
tracked_pass.set_camera_viewport(viewport);
}
for item in &transparent_phase.items {
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
draw_function.draw(world, &mut tracked_pass, view_entity, item);
Expand Down
67 changes: 32 additions & 35 deletions crates/bevy_core_pipeline/src/core_3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use bevy_render::{
},
renderer::RenderDevice,
texture::TextureCache,
view::{ExtractedView, ViewDepthTexture},
view::ViewDepthTexture,
RenderApp, RenderStage,
};
use bevy_utils::{FloatOrd, HashMap};
Expand All @@ -53,7 +53,7 @@ impl Plugin for Core3dPlugin {
.init_resource::<DrawFunctions<AlphaMask3d>>()
.init_resource::<DrawFunctions<Transparent3d>>()
.add_system_to_stage(RenderStage::Extract, extract_core_3d_camera_phases)
.add_system_to_stage(RenderStage::Prepare, prepare_core_3d_views_system)
.add_system_to_stage(RenderStage::Prepare, prepare_core_3d_cameras_system)
.add_system_to_stage(RenderStage::PhaseSort, sort_phase_system::<Opaque3d>)
.add_system_to_stage(RenderStage::PhaseSort, sort_phase_system::<AlphaMask3d>)
.add_system_to_stage(RenderStage::PhaseSort, sort_phase_system::<Transparent3d>);
Expand Down Expand Up @@ -199,13 +199,13 @@ pub fn extract_core_3d_camera_phases(
}
}

pub fn prepare_core_3d_views_system(
pub fn prepare_core_3d_cameras_system(
mut commands: Commands,
mut texture_cache: ResMut<TextureCache>,
msaa: Res<Msaa>,
render_device: Res<RenderDevice>,
views_3d: Query<
cart marked this conversation as resolved.
Show resolved Hide resolved
(Entity, &ExtractedView, Option<&ExtractedCamera>),
(Entity, &ExtractedCamera),
(
With<RenderPhase<Opaque3d>>,
With<RenderPhase<AlphaMask3d>>,
Expand All @@ -214,37 +214,34 @@ pub fn prepare_core_3d_views_system(
>,
) {
let mut textures = HashMap::default();
for (entity, view, camera) in views_3d.iter() {
let mut get_cached_texture = || {
texture_cache.get(
&render_device,
TextureDescriptor {
label: Some("view_depth_texture"),
size: Extent3d {
depth_or_array_layers: 1,
width: view.width as u32,
height: view.height as u32,
},
mip_level_count: 1,
sample_count: msaa.samples,
dimension: TextureDimension::D2,
format: TextureFormat::Depth32Float, /* PERF: vulkan docs recommend using 24
* bit depth for better performance */
usage: TextureUsages::RENDER_ATTACHMENT,
},
)
};
let cached_texture = if let Some(camera) = camera {
textures
for (entity, camera) in views_3d.iter() {
if let Some(physical_target_size) = camera.physical_target_size {
let cached_texture = textures
.entry(camera.target.clone())
.or_insert_with(get_cached_texture)
.clone()
} else {
get_cached_texture()
};
commands.entity(entity).insert(ViewDepthTexture {
texture: cached_texture.texture,
view: cached_texture.default_view,
});
.or_insert_with(|| {
texture_cache.get(
&render_device,
TextureDescriptor {
label: Some("view_depth_texture"),
size: Extent3d {
depth_or_array_layers: 1,
width: physical_target_size.x,
height: physical_target_size.y,
},
mip_level_count: 1,
sample_count: msaa.samples,
dimension: TextureDimension::D2,
format: TextureFormat::Depth32Float, /* PERF: vulkan docs recommend using 24
* bit depth for better performance */
usage: TextureUsages::RENDER_ATTACHMENT,
},
)
})
.clone();
commands.entity(entity).insert(ViewDepthTexture {
texture: cached_texture.texture,
view: cached_texture.default_view,
});
}
}
}
14 changes: 7 additions & 7 deletions crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ pub(crate) fn assign_lights_to_clusters(
continue;
}

let screen_size = if let Some(screen_size) = camera.physical_target_size {
let screen_size = if let Some(screen_size) = camera.physical_viewport_size() {
screen_size
} else {
clusters.clear();
Expand All @@ -747,7 +747,7 @@ pub(crate) fn assign_lights_to_clusters(

let view_transform = camera_transform.compute_matrix();
let inverse_view_transform = view_transform.inverse();
let is_orthographic = camera.projection_matrix.w_axis.w == 1.0;
let is_orthographic = camera.projection_matrix().w_axis.w == 1.0;

let far_z = match config.far_z_mode() {
ClusterFarZMode::MaxLightRange => {
Expand All @@ -772,7 +772,7 @@ pub(crate) fn assign_lights_to_clusters(
// 3,2 = r * far and 2,2 = r where r = 1.0 / (far - near)
// rearranging r = 1.0 / (far - near), r * (far - near) = 1.0, r * far - 1.0 = r * near, near = (r * far - 1.0) / r
// = (3,2 - 1.0) / 2,2
(camera.projection_matrix.w_axis.z - 1.0) / camera.projection_matrix.z_axis.z
(camera.projection_matrix().w_axis.z - 1.0) / camera.projection_matrix().z_axis.z
}
(false, 1) => config.first_slice_depth().max(far_z),
_ => config.first_slice_depth(),
Expand Down Expand Up @@ -804,7 +804,7 @@ pub(crate) fn assign_lights_to_clusters(
// it can overestimate more significantly when light ranges are only partially in view
let (light_aabb_min, light_aabb_max) = cluster_space_light_aabb(
inverse_view_transform,
camera.projection_matrix,
camera.projection_matrix(),
&light_sphere,
);

Expand Down Expand Up @@ -871,7 +871,7 @@ pub(crate) fn assign_lights_to_clusters(
clusters.dimensions.x * clusters.dimensions.y * clusters.dimensions.z <= 4096
);

let inverse_projection = camera.projection_matrix.inverse();
let inverse_projection = camera.projection_matrix().inverse();

for lights in &mut clusters.lights {
lights.entities.clear();
Expand Down Expand Up @@ -958,7 +958,7 @@ pub(crate) fn assign_lights_to_clusters(
let (light_aabb_xy_ndc_z_view_min, light_aabb_xy_ndc_z_view_max) =
cluster_space_light_aabb(
inverse_view_transform,
camera.projection_matrix,
camera.projection_matrix(),
&light_sphere,
);

Expand Down Expand Up @@ -991,7 +991,7 @@ pub(crate) fn assign_lights_to_clusters(
radius: light_sphere.radius,
};
let light_center_clip =
camera.projection_matrix * view_light_sphere.center.extend(1.0);
camera.projection_matrix() * view_light_sphere.center.extend(1.0);
let light_center_ndc = light_center_clip.xyz() / light_center_clip.w;
let cluster_coordinates = ndc_position_to_cluster(
clusters.dimensions,
Expand Down
Loading