Skip to content

Commit

Permalink
Split OrthographicProjection::default into 2d & 3d (Adopted) (#15073)
Browse files Browse the repository at this point in the history
Adopted PR from dmlary, all credit to them!
#9915

Original description:

# Objective

The default value for `near` in `OrthographicProjection` should be
different for 2d & 3d.

For 2d using `near = -1000` allows bevy users to build up scenes using
background `z = 0`, and foreground elements `z > 0` similar to css.
However in 3d `near = -1000` results in objects behind the camera being
rendered. Using `near = 0` works for 3d, but forces 2d users to assign
`z <= 0` for rendered elements, putting the background at some arbitrary
negative value.

There is no common value for `near` that doesn't result in a footgun or
usability issue for either 2d or 3d, so they should have separate
values.

There was discussion about other options in the discord
[0](https://discord.com/channels/691052431525675048/1154114310042292325),
but splitting `default()` into `default_2d()` and `default_3d()` seemed
like the lowest cost approach.

Related/past work #9138,
#9214,
#9310,
#9537 (thanks to @Selene-Amanita
for the list)

## Solution

This commit splits `OrthographicProjection::default` into `default_2d`
and `default_3d`.

## Migration Guide

- In initialization of `OrthographicProjection`, change `..default()` to
`..OrthographicProjection::default_2d()` or
`..OrthographicProjection::default_3d()`

Example:
```diff
--- a/examples/3d/orthographic.rs
+++ b/examples/3d/orthographic.rs
@@ -20,7 +20,7 @@ fn setup(
         projection: OrthographicProjection {
             scale: 3.0,
             scaling_mode: ScalingMode::FixedVertical(2.0),
-            ..default()
+            ..OrthographicProjection::default_3d()
         }
         .into(),
         transform: Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
```

---------

Co-authored-by: David M. Lary <dmlary@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
  • Loading branch information
3 people authored Sep 9, 2024
1 parent 8460cfa commit 82e416d
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 20 deletions.
12 changes: 2 additions & 10 deletions crates/bevy_core_pipeline/src/core_2d/camera_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ pub struct Camera2d;
pub struct Camera2dBundle {
pub camera: Camera,
pub camera_render_graph: CameraRenderGraph,
/// Note: default value for `OrthographicProjection.near` is `0.0`
/// which makes objects on the screen plane invisible to 2D camera.
/// `Camera2dBundle::default()` sets `near` to negative value,
/// so be careful when initializing this field manually.
pub projection: OrthographicProjection,
pub visible_entities: VisibleEntities,
pub frustum: Frustum,
Expand All @@ -41,11 +37,7 @@ pub struct Camera2dBundle {

impl Default for Camera2dBundle {
fn default() -> Self {
let projection = OrthographicProjection {
far: 1000.,
near: -1000.,
..Default::default()
};
let projection = OrthographicProjection::default_2d();
let transform = Transform::default();
let frustum = projection.compute_frustum(&GlobalTransform::from(transform));
Self {
Expand Down Expand Up @@ -77,7 +69,7 @@ impl Camera2dBundle {
// the camera's translation by far and use a right handed coordinate system
let projection = OrthographicProjection {
far,
..Default::default()
..OrthographicProjection::default_2d()
};
let transform = Transform::from_xyz(0.0, 0.0, far - 0.1);
let frustum = projection.compute_frustum(&GlobalTransform::from(transform));
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_dev_tools/src/ui_debug_overlay/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn update_debug_camera(
projection: OrthographicProjection {
far: 1000.0,
viewport_origin: Vec2::new(0.0, 0.0),
..default()
..OrthographicProjection::default_3d()
},
camera: Camera {
order: LAYOUT_DEBUG_CAMERA_ORDER,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ fn load_node(
far: orthographic.zfar(),
scaling_mode: ScalingMode::FixedHorizontal(1.0),
scale: xmag,
..Default::default()
..OrthographicProjection::default_3d()
};

Projection::Orthographic(orthographic_projection)
Expand Down
31 changes: 26 additions & 5 deletions crates/bevy_render/src/camera/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ impl Default for PerspectiveProjection {
/// # use bevy_render::camera::{OrthographicProjection, Projection, ScalingMode};
/// let projection = Projection::Orthographic(OrthographicProjection {
/// scaling_mode: ScalingMode::FixedVertical(2.0),
/// ..OrthographicProjection::default()
/// ..OrthographicProjection::default_2d()
/// });
/// ```
#[derive(Debug, Clone, Copy, Reflect, Serialize, Deserialize)]
Expand Down Expand Up @@ -334,11 +334,11 @@ impl DivAssign<f32> for ScalingMode {
/// # use bevy_render::camera::{OrthographicProjection, Projection, ScalingMode};
/// let projection = Projection::Orthographic(OrthographicProjection {
/// scaling_mode: ScalingMode::WindowSize(100.0),
/// ..OrthographicProjection::default()
/// ..OrthographicProjection::default_2d()
/// });
/// ```
#[derive(Component, Debug, Clone, Reflect)]
#[reflect(Component, Default)]
#[reflect(Component)]
pub struct OrthographicProjection {
/// The distance of the near clipping plane in world units.
///
Expand Down Expand Up @@ -479,8 +479,29 @@ impl CameraProjection for OrthographicProjection {
}
}

impl Default for OrthographicProjection {
fn default() -> Self {
impl FromWorld for OrthographicProjection {
fn from_world(_world: &mut World) -> Self {
OrthographicProjection::default_3d()
}
}

impl OrthographicProjection {
/// Returns the default orthographic projection for a 2D context.
///
/// The near plane is set to a negative value so that the camera can still
/// render the scene when using positive z coordinates to order foreground elements.
pub fn default_2d() -> Self {
OrthographicProjection {
near: -1000.0,
..OrthographicProjection::default_3d()
}
}

/// Returns the default orthographic projection for a 3D context.
///
/// The near plane is set to 0.0 so that the camera doesn't render
/// objects that are behind it.
pub fn default_3d() -> Self {
OrthographicProjection {
scale: 1.0,
near: 0.0,
Expand Down
2 changes: 1 addition & 1 deletion examples/3d/orthographic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fn setup(
projection: OrthographicProjection {
// 6 world units per window height.
scaling_mode: ScalingMode::FixedVertical(6.0),
..default()
..OrthographicProjection::default_3d()
}
.into(),
transform: Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
Expand Down
2 changes: 1 addition & 1 deletion examples/3d/pbr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ fn setup(
transform: Transform::from_xyz(0.0, 0.0, 8.0).looking_at(Vec3::default(), Vec3::Y),
projection: OrthographicProjection {
scale: 0.01,
..default()
..OrthographicProjection::default_3d()
}
.into(),
..default()
Expand Down
2 changes: 1 addition & 1 deletion examples/stress_tests/many_lights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ fn setup(
projection: OrthographicProjection {
scale: 20.0,
scaling_mode: ScalingMode::FixedHorizontal(1.0),
..default()
..OrthographicProjection::default_3d()
}
.into(),
..default()
Expand Down

0 comments on commit 82e416d

Please sign in to comment.