From 82e416dc48f7a76c928ef15dd64b0a2ff858e90c Mon Sep 17 00:00:00 2001 From: Alix Bott Date: Mon, 9 Sep 2024 17:51:28 +0200 Subject: [PATCH] Split OrthographicProjection::default into 2d & 3d (Adopted) (#15073) Adopted PR from dmlary, all credit to them! https://github.com/bevyengine/bevy/pull/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 https://github.com/bevyengine/bevy/issues/9138, https://github.com/bevyengine/bevy/pull/9214, https://github.com/bevyengine/bevy/pull/9310, https://github.com/bevyengine/bevy/pull/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 Co-authored-by: Jan Hohenheim --- .../src/core_2d/camera_2d.rs | 12 ++----- .../src/ui_debug_overlay/mod.rs | 2 +- crates/bevy_gltf/src/loader.rs | 2 +- crates/bevy_render/src/camera/projection.rs | 31 ++++++++++++++++--- examples/3d/orthographic.rs | 2 +- examples/3d/pbr.rs | 2 +- examples/stress_tests/many_lights.rs | 2 +- 7 files changed, 33 insertions(+), 20 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs index 857c2202164ab..b45f668c9943f 100644 --- a/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs +++ b/crates/bevy_core_pipeline/src/core_2d/camera_2d.rs @@ -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, @@ -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 { @@ -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)); diff --git a/crates/bevy_dev_tools/src/ui_debug_overlay/mod.rs b/crates/bevy_dev_tools/src/ui_debug_overlay/mod.rs index 6382cfa9038fb..88af56210a9e3 100644 --- a/crates/bevy_dev_tools/src/ui_debug_overlay/mod.rs +++ b/crates/bevy_dev_tools/src/ui_debug_overlay/mod.rs @@ -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, diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 010e80f659c23..e2c193e110284 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -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) diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 0a6c3ca00afab..2aa5f8acc0d07 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -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)] @@ -334,11 +334,11 @@ impl DivAssign 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. /// @@ -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, diff --git a/examples/3d/orthographic.rs b/examples/3d/orthographic.rs index a56e4f972fefe..f257ab35f8e67 100644 --- a/examples/3d/orthographic.rs +++ b/examples/3d/orthographic.rs @@ -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), diff --git a/examples/3d/pbr.rs b/examples/3d/pbr.rs index 3c7a76211903f..a20adb8edf409 100644 --- a/examples/3d/pbr.rs +++ b/examples/3d/pbr.rs @@ -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() diff --git a/examples/stress_tests/many_lights.rs b/examples/stress_tests/many_lights.rs index 196bea143d8b0..33244a99b9d4a 100644 --- a/examples/stress_tests/many_lights.rs +++ b/examples/stress_tests/many_lights.rs @@ -96,7 +96,7 @@ fn setup( projection: OrthographicProjection { scale: 20.0, scaling_mode: ScalingMode::FixedHorizontal(1.0), - ..default() + ..OrthographicProjection::default_3d() } .into(), ..default()