Skip to content

Projection Improvements #18458

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/light/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy_ecs::{
use bevy_math::{ops, Mat4, Vec3A, Vec4};
use bevy_reflect::prelude::*;
use bevy_render::{
camera::{Camera, CameraProjection, Projection},
camera::{Camera, Projection},
extract_component::ExtractComponent,
extract_resource::ExtractResource,
mesh::Mesh3d,
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use super::{ClearColorConfig, Projection};
use crate::{
batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport},
camera::{CameraProjection, ManualTextureViewHandle, ManualTextureViews},
camera::{ManualTextureViewHandle, ManualTextureViews},
primitives::Frustum,
render_asset::RenderAssets,
render_graph::{InternedRenderSubGraph, RenderSubGraph},
Expand Down Expand Up @@ -659,7 +659,7 @@ impl Camera {
/// To get the coordinates in the render target's viewport dimensions, you should use
/// [`world_to_viewport`](Self::world_to_viewport).
///
/// Returns `None` if the `camera_transform`, the `world_position`, or the projection matrix defined by [`CameraProjection`] contain `NAN`.
/// Returns `None` if the `camera_transform`, the `world_position`, or the projection matrix defined by [`Projection`] contain `NAN`.
///
/// # Panics
///
Expand Down
78 changes: 44 additions & 34 deletions crates/bevy_render/src/camera/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ mod sealed {
/// custom projection.
///
/// The contained dynamic object can be downcast into a static type using [`CustomProjection::get`].
#[derive(Component, Debug, Reflect, Deref, DerefMut)]
#[derive(Debug, Reflect, Deref, DerefMut)]
#[reflect(Default, Clone)]
pub struct CustomProjection {
#[reflect(ignore)]
Expand Down Expand Up @@ -201,6 +201,36 @@ impl CustomProjection {
}
}

// TODO: remove when trait upcasting is stabilized.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trait upcasting is merged into Rust, but not quite released. See rust-lang/rust#65991. Does it make sense to wait until April 3rd? https://releases.rs/docs/1.86.0/

// The deref impl can return `dyn DynCameraProjection`, which can be coerced into
// `dyn CameraProjection` using trait upcasting.
impl CameraProjection for CustomProjection {
#[inline(always)]
fn get_clip_from_view(&self) -> Mat4 {
self.dyn_projection.get_clip_from_view()
}

#[inline(always)]
fn get_clip_from_view_for_sub(&self, sub_view: &super::SubCameraView) -> Mat4 {
self.dyn_projection.get_clip_from_view_for_sub(sub_view)
}

#[inline(always)]
fn update(&mut self, width: f32, height: f32) {
self.dyn_projection.update(width, height);
}

#[inline(always)]
fn far(&self) -> f32 {
self.dyn_projection.far()
}

#[inline(always)]
fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8] {
self.dyn_projection.get_frustum_corners(z_near, z_far)
}
}

/// Component that defines how to compute a [`Camera`]'s projection matrix.
///
/// Common projections, like perspective and orthographic, are provided out of the box to handle the
Expand Down Expand Up @@ -237,7 +267,7 @@ impl Projection {
// that, say, the `Debug` implementation is missing. Wrapping these traits behind a super
// trait or some other indirection will make the errors harder to understand.
//
// For example, we don't use the `DynCameraProjection`` trait bound, because it is not the
// For example, we don't use the `DynCameraProjection` trait bound, because it is not the
// trait the user should be implementing - they only need to worry about implementing
// `CameraProjection`.
P: CameraProjection + Debug + Send + Sync + Clone + 'static,
Expand All @@ -248,44 +278,24 @@ impl Projection {
}
}

impl CameraProjection for Projection {
fn get_clip_from_view(&self) -> Mat4 {
match self {
Projection::Perspective(projection) => projection.get_clip_from_view(),
Projection::Orthographic(projection) => projection.get_clip_from_view(),
Projection::Custom(projection) => projection.get_clip_from_view(),
}
}

fn get_clip_from_view_for_sub(&self, sub_view: &super::SubCameraView) -> Mat4 {
match self {
Projection::Perspective(projection) => projection.get_clip_from_view_for_sub(sub_view),
Projection::Orthographic(projection) => projection.get_clip_from_view_for_sub(sub_view),
Projection::Custom(projection) => projection.get_clip_from_view_for_sub(sub_view),
}
}
impl core::ops::Deref for Projection {
type Target = dyn CameraProjection;

fn update(&mut self, width: f32, height: f32) {
match self {
Projection::Perspective(projection) => projection.update(width, height),
Projection::Orthographic(projection) => projection.update(width, height),
Projection::Custom(projection) => projection.update(width, height),
}
}

fn far(&self) -> f32 {
fn deref(&self) -> &Self::Target {
match self {
Projection::Perspective(projection) => projection.far(),
Projection::Orthographic(projection) => projection.far(),
Projection::Custom(projection) => projection.far(),
Projection::Perspective(projection) => projection,
Projection::Orthographic(projection) => projection,
Projection::Custom(projection) => projection,
}
}
}

fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8] {
impl core::ops::DerefMut for Projection {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Projection::Perspective(projection) => projection.get_frustum_corners(z_near, z_far),
Projection::Orthographic(projection) => projection.get_frustum_corners(z_near, z_far),
Projection::Custom(projection) => projection.get_frustum_corners(z_near, z_far),
Projection::Perspective(projection) => projection,
Projection::Orthographic(projection) => projection,
Projection::Custom(projection) => projection,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/view/visibility/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use smallvec::SmallVec;

use super::NoCpuCulling;
use crate::{
camera::{Camera, CameraProjection, Projection},
camera::{Camera, Projection},
mesh::{Mesh, Mesh3d, MeshAabb},
primitives::{Aabb, Frustum, Sphere},
sync_world::MainEntity,
Expand Down
Loading