3D OrthographicProjection improvements + new example (#1361)
* use `length_squared` for visible entities * ortho projection 2d/3d different depth calculation * use ScalingMode::FixedVertical for 3d ortho * new example: 3d orthographic
This commit is contained in:
parent
83e30a841a
commit
7d065eeb71
@ -121,6 +121,10 @@ path = "examples/3d/load_gltf.rs"
|
|||||||
name = "msaa"
|
name = "msaa"
|
||||||
path = "examples/3d/msaa.rs"
|
path = "examples/3d/msaa.rs"
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "orthographic"
|
||||||
|
path = "examples/3d/orthographic.rs"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "parenting"
|
name = "parenting"
|
||||||
path = "examples/3d/parenting.rs"
|
path = "examples/3d/parenting.rs"
|
||||||
|
@ -2,9 +2,10 @@ use super::CameraProjection;
|
|||||||
use bevy_app::prelude::EventReader;
|
use bevy_app::prelude::EventReader;
|
||||||
use bevy_ecs::{Added, Component, Entity, Query, QuerySet, Res};
|
use bevy_ecs::{Added, Component, Entity, Query, QuerySet, Res};
|
||||||
use bevy_math::{Mat4, Vec2, Vec3};
|
use bevy_math::{Mat4, Vec2, Vec3};
|
||||||
use bevy_reflect::{Reflect, ReflectComponent};
|
use bevy_reflect::{Reflect, ReflectComponent, ReflectDeserialize};
|
||||||
use bevy_transform::components::GlobalTransform;
|
use bevy_transform::components::GlobalTransform;
|
||||||
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
|
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Default, Debug, Reflect)]
|
#[derive(Default, Debug, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
@ -17,9 +18,12 @@ pub struct Camera {
|
|||||||
pub depth_calculation: DepthCalculation,
|
pub depth_calculation: DepthCalculation,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy, Reflect, Serialize, Deserialize)]
|
||||||
|
#[reflect_value(Serialize, Deserialize)]
|
||||||
pub enum DepthCalculation {
|
pub enum DepthCalculation {
|
||||||
|
/// Pythagorean distance; works everywhere, more expensive to compute.
|
||||||
Distance,
|
Distance,
|
||||||
|
/// Optimization for 2D; assuming the camera points towards -Z.
|
||||||
ZDifference,
|
ZDifference,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ pub struct OrthographicProjection {
|
|||||||
pub window_origin: WindowOrigin,
|
pub window_origin: WindowOrigin,
|
||||||
pub scaling_mode: ScalingMode,
|
pub scaling_mode: ScalingMode,
|
||||||
pub scale: f32,
|
pub scale: f32,
|
||||||
|
pub depth_calculation: DepthCalculation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CameraProjection for OrthographicProjection {
|
impl CameraProjection for OrthographicProjection {
|
||||||
@ -140,7 +141,7 @@ impl CameraProjection for OrthographicProjection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn depth_calculation(&self) -> DepthCalculation {
|
fn depth_calculation(&self) -> DepthCalculation {
|
||||||
DepthCalculation::ZDifference
|
self.depth_calculation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +157,7 @@ impl Default for OrthographicProjection {
|
|||||||
window_origin: WindowOrigin::Center,
|
window_origin: WindowOrigin::Center,
|
||||||
scaling_mode: ScalingMode::WindowSize,
|
scaling_mode: ScalingMode::WindowSize,
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
|
depth_calculation: DepthCalculation::Distance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,7 +231,7 @@ pub fn visible_entities_system(
|
|||||||
// smaller distances are sorted to lower indices by using the distance from the camera
|
// smaller distances are sorted to lower indices by using the distance from the camera
|
||||||
FloatOrd(match camera.depth_calculation {
|
FloatOrd(match camera.depth_calculation {
|
||||||
DepthCalculation::ZDifference => camera_position.z - position.z,
|
DepthCalculation::ZDifference => camera_position.z - position.z,
|
||||||
DepthCalculation::Distance => (camera_position - position).length(),
|
DepthCalculation::Distance => (camera_position - position).length_squared(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let order = FloatOrd(no_transform_order);
|
let order = FloatOrd(no_transform_order);
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
camera::{Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities},
|
camera::{
|
||||||
|
Camera, DepthCalculation, OrthographicProjection, PerspectiveProjection, ScalingMode,
|
||||||
|
VisibleEntities,
|
||||||
|
},
|
||||||
pipeline::RenderPipelines,
|
pipeline::RenderPipelines,
|
||||||
prelude::Visible,
|
prelude::Visible,
|
||||||
render_graph::base,
|
render_graph::base,
|
||||||
@ -92,6 +95,7 @@ impl OrthographicCameraBundle {
|
|||||||
},
|
},
|
||||||
orthographic_projection: OrthographicProjection {
|
orthographic_projection: OrthographicProjection {
|
||||||
far,
|
far,
|
||||||
|
depth_calculation: DepthCalculation::ZDifference,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
visible_entities: Default::default(),
|
visible_entities: Default::default(),
|
||||||
@ -106,7 +110,11 @@ impl OrthographicCameraBundle {
|
|||||||
name: Some(base::camera::CAMERA_3D.to_string()),
|
name: Some(base::camera::CAMERA_3D.to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
orthographic_projection: Default::default(),
|
orthographic_projection: OrthographicProjection {
|
||||||
|
scaling_mode: ScalingMode::FixedVertical,
|
||||||
|
depth_calculation: DepthCalculation::Distance,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
visible_entities: Default::default(),
|
visible_entities: Default::default(),
|
||||||
transform: Default::default(),
|
transform: Default::default(),
|
||||||
global_transform: Default::default(),
|
global_transform: Default::default(),
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_ecs::Bundle;
|
use bevy_ecs::Bundle;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::{Camera, OrthographicProjection, VisibleEntities, WindowOrigin},
|
camera::{Camera, DepthCalculation, OrthographicProjection, VisibleEntities, WindowOrigin},
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
mesh::Mesh,
|
mesh::Mesh,
|
||||||
pipeline::{RenderPipeline, RenderPipelines},
|
pipeline::{RenderPipeline, RenderPipelines},
|
||||||
@ -185,6 +185,7 @@ impl Default for UiCameraBundle {
|
|||||||
orthographic_projection: OrthographicProjection {
|
orthographic_projection: OrthographicProjection {
|
||||||
far,
|
far,
|
||||||
window_origin: WindowOrigin::BottomLeft,
|
window_origin: WindowOrigin::BottomLeft,
|
||||||
|
depth_calculation: DepthCalculation::ZDifference,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
visible_entities: Default::default(),
|
visible_entities: Default::default(),
|
||||||
|
62
examples/3d/orthographic.rs
Normal file
62
examples/3d/orthographic.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::build()
|
||||||
|
.insert_resource(Msaa { samples: 4 })
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_startup_system(setup.system())
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set up a simple 3D scene
|
||||||
|
fn setup(
|
||||||
|
commands: &mut Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
// set up the camera
|
||||||
|
let mut camera = OrthographicCameraBundle::new_3d();
|
||||||
|
camera.orthographic_projection.scale = 3.0;
|
||||||
|
camera.transform = Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::zero(), Vec3::unit_y());
|
||||||
|
|
||||||
|
// add entities to the world
|
||||||
|
commands
|
||||||
|
// plane
|
||||||
|
.spawn(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// cubes
|
||||||
|
.spawn(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||||
|
transform: Transform::from_xyz(1.5, 0.5, 1.5),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.spawn(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||||
|
transform: Transform::from_xyz(1.5, 0.5, -1.5),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.spawn(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||||
|
transform: Transform::from_xyz(-1.5, 0.5, 1.5),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.spawn(PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
|
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
|
||||||
|
transform: Transform::from_xyz(-1.5, 0.5, -1.5),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// light
|
||||||
|
.spawn(LightBundle {
|
||||||
|
transform: Transform::from_xyz(3.0, 8.0, 5.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// camera
|
||||||
|
.spawn(camera);
|
||||||
|
}
|
@ -71,6 +71,7 @@ Example | File | Description
|
|||||||
`3d_scene` | [`3d/3d_scene.rs`](./3d/3d_scene.rs) | Simple 3D scene with basic shapes and lighting
|
`3d_scene` | [`3d/3d_scene.rs`](./3d/3d_scene.rs) | Simple 3D scene with basic shapes and lighting
|
||||||
`load_gltf` | [`3d/load_gltf.rs`](./3d/load_gltf.rs) | Loads and renders a gltf file as a scene
|
`load_gltf` | [`3d/load_gltf.rs`](./3d/load_gltf.rs) | Loads and renders a gltf file as a scene
|
||||||
`msaa` | [`3d/msaa.rs`](./3d/msaa.rs) | Configures MSAA (Multi-Sample Anti-Aliasing) for smoother edges
|
`msaa` | [`3d/msaa.rs`](./3d/msaa.rs) | Configures MSAA (Multi-Sample Anti-Aliasing) for smoother edges
|
||||||
|
`orthographic` | [`3d/orthographic.rs`](./3d/orthographic.rs) | Shows how to create a 3D orthographic view (for isometric-look games or CAD applications)
|
||||||
`parenting` | [`3d/parenting.rs`](./3d/parenting.rs) | Demonstrates parent->child relationships and relative transformations
|
`parenting` | [`3d/parenting.rs`](./3d/parenting.rs) | Demonstrates parent->child relationships and relative transformations
|
||||||
`spawner` | [`3d/spawner.rs`](./3d/spawner.rs) | Renders a large number of cubes with changing position and material
|
`spawner` | [`3d/spawner.rs`](./3d/spawner.rs) | Renders a large number of cubes with changing position and material
|
||||||
`texture` | [`3d/texture.rs`](./3d/texture.rs) | Shows configuration of texture materials
|
`texture` | [`3d/texture.rs`](./3d/texture.rs) | Shows configuration of texture materials
|
||||||
|
Loading…
Reference in New Issue
Block a user