mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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
8 changed files with 89 additions and 7 deletions
|
@ -121,6 +121,10 @@ path = "examples/3d/load_gltf.rs"
|
|||
name = "msaa"
|
||||
path = "examples/3d/msaa.rs"
|
||||
|
||||
[[example]]
|
||||
name = "orthographic"
|
||||
path = "examples/3d/orthographic.rs"
|
||||
|
||||
[[example]]
|
||||
name = "parenting"
|
||||
path = "examples/3d/parenting.rs"
|
||||
|
|
|
@ -2,9 +2,10 @@ use super::CameraProjection;
|
|||
use bevy_app::prelude::EventReader;
|
||||
use bevy_ecs::{Added, Component, Entity, Query, QuerySet, Res};
|
||||
use bevy_math::{Mat4, Vec2, Vec3};
|
||||
use bevy_reflect::{Reflect, ReflectComponent};
|
||||
use bevy_reflect::{Reflect, ReflectComponent, ReflectDeserialize};
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Debug, Reflect)]
|
||||
#[reflect(Component)]
|
||||
|
@ -17,9 +18,12 @@ pub struct Camera {
|
|||
pub depth_calculation: DepthCalculation,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, Copy, Reflect, Serialize, Deserialize)]
|
||||
#[reflect_value(Serialize, Deserialize)]
|
||||
pub enum DepthCalculation {
|
||||
/// Pythagorean distance; works everywhere, more expensive to compute.
|
||||
Distance,
|
||||
/// Optimization for 2D; assuming the camera points towards -Z.
|
||||
ZDifference,
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ pub struct OrthographicProjection {
|
|||
pub window_origin: WindowOrigin,
|
||||
pub scaling_mode: ScalingMode,
|
||||
pub scale: f32,
|
||||
pub depth_calculation: DepthCalculation,
|
||||
}
|
||||
|
||||
impl CameraProjection for OrthographicProjection {
|
||||
|
@ -140,7 +141,7 @@ impl CameraProjection for OrthographicProjection {
|
|||
}
|
||||
|
||||
fn depth_calculation(&self) -> DepthCalculation {
|
||||
DepthCalculation::ZDifference
|
||||
self.depth_calculation
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,6 +157,7 @@ impl Default for OrthographicProjection {
|
|||
window_origin: WindowOrigin::Center,
|
||||
scaling_mode: ScalingMode::WindowSize,
|
||||
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
|
||||
FloatOrd(match camera.depth_calculation {
|
||||
DepthCalculation::ZDifference => camera_position.z - position.z,
|
||||
DepthCalculation::Distance => (camera_position - position).length(),
|
||||
DepthCalculation::Distance => (camera_position - position).length_squared(),
|
||||
})
|
||||
} else {
|
||||
let order = FloatOrd(no_transform_order);
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use crate::{
|
||||
camera::{Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities},
|
||||
camera::{
|
||||
Camera, DepthCalculation, OrthographicProjection, PerspectiveProjection, ScalingMode,
|
||||
VisibleEntities,
|
||||
},
|
||||
pipeline::RenderPipelines,
|
||||
prelude::Visible,
|
||||
render_graph::base,
|
||||
|
@ -92,6 +95,7 @@ impl OrthographicCameraBundle {
|
|||
},
|
||||
orthographic_projection: OrthographicProjection {
|
||||
far,
|
||||
depth_calculation: DepthCalculation::ZDifference,
|
||||
..Default::default()
|
||||
},
|
||||
visible_entities: Default::default(),
|
||||
|
@ -106,7 +110,11 @@ impl OrthographicCameraBundle {
|
|||
name: Some(base::camera::CAMERA_3D.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
orthographic_projection: Default::default(),
|
||||
orthographic_projection: OrthographicProjection {
|
||||
scaling_mode: ScalingMode::FixedVertical,
|
||||
depth_calculation: DepthCalculation::Distance,
|
||||
..Default::default()
|
||||
},
|
||||
visible_entities: Default::default(),
|
||||
transform: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
use bevy_asset::Handle;
|
||||
use bevy_ecs::Bundle;
|
||||
use bevy_render::{
|
||||
camera::{Camera, OrthographicProjection, VisibleEntities, WindowOrigin},
|
||||
camera::{Camera, DepthCalculation, OrthographicProjection, VisibleEntities, WindowOrigin},
|
||||
draw::Draw,
|
||||
mesh::Mesh,
|
||||
pipeline::{RenderPipeline, RenderPipelines},
|
||||
|
@ -185,6 +185,7 @@ impl Default for UiCameraBundle {
|
|||
orthographic_projection: OrthographicProjection {
|
||||
far,
|
||||
window_origin: WindowOrigin::BottomLeft,
|
||||
depth_calculation: DepthCalculation::ZDifference,
|
||||
..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
|
||||
`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
|
||||
`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
|
||||
`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
|
||||
|
|
Loading…
Reference in a new issue