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:
Jasen Borisov 2021-02-01 01:22:06 +01:00 committed by GitHub
parent 83e30a841a
commit 7d065eeb71
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 7 deletions

View file

@ -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"

View file

@ -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,
}

View file

@ -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,
}
}
}

View file

@ -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);

View file

@ -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(),

View file

@ -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(),

View 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);
}

View file

@ -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