bevy/crates/bevy_render/src/camera/projection.rs
Carter Anderson ffecb05a0a Replace old renderer with new renderer (#3312)
This makes the [New Bevy Renderer](#2535) the default (and only) renderer. The new renderer isn't _quite_ ready for the final release yet, but I want as many people as possible to start testing it so we can identify bugs and address feedback prior to release.

The examples are all ported over and operational with a few exceptions:

* I removed a good portion of the examples in the `shader` folder. We still have some work to do in order to make these examples possible / ergonomic / worthwhile: #3120 and "high level shader material plugins" are the big ones. This is a temporary measure.
* Temporarily removed the multiple_windows example: doing this properly in the new renderer will require the upcoming "render targets" changes. Same goes for the render_to_texture example.
* Removed z_sort_debug: entity visibility sort info is no longer available in app logic. we could do this on the "render app" side, but i dont consider it a priority.
2021-12-14 03:58:23 +00:00

176 lines
5.2 KiB
Rust

use super::DepthCalculation;
use bevy_ecs::{component::Component, reflect::ReflectComponent};
use bevy_math::Mat4;
use bevy_reflect::{Reflect, ReflectDeserialize};
use serde::{Deserialize, Serialize};
pub trait CameraProjection {
fn get_projection_matrix(&self) -> Mat4;
fn update(&mut self, width: f32, height: f32);
fn depth_calculation(&self) -> DepthCalculation;
fn far(&self) -> f32;
}
#[derive(Component, Debug, Clone, Reflect)]
#[reflect(Component)]
pub struct PerspectiveProjection {
pub fov: f32,
pub aspect_ratio: f32,
pub near: f32,
pub far: f32,
}
impl CameraProjection for PerspectiveProjection {
fn get_projection_matrix(&self) -> Mat4 {
Mat4::perspective_infinite_reverse_rh(self.fov, self.aspect_ratio, self.near)
}
fn update(&mut self, width: f32, height: f32) {
self.aspect_ratio = width / height;
}
fn depth_calculation(&self) -> DepthCalculation {
DepthCalculation::Distance
}
fn far(&self) -> f32 {
self.far
}
}
impl Default for PerspectiveProjection {
fn default() -> Self {
PerspectiveProjection {
fov: std::f32::consts::PI / 4.0,
near: 0.1,
far: 1000.0,
aspect_ratio: 1.0,
}
}
}
// TODO: make this a component instead of a property
#[derive(Debug, Clone, Reflect, Serialize, Deserialize)]
#[reflect_value(Serialize, Deserialize)]
pub enum WindowOrigin {
Center,
BottomLeft,
}
#[derive(Debug, Clone, Reflect, Serialize, Deserialize)]
#[reflect_value(Serialize, Deserialize)]
pub enum ScalingMode {
/// Manually specify left/right/top/bottom values.
/// Ignore window resizing; the image will stretch.
None,
/// Match the window size. 1 world unit = 1 pixel.
WindowSize,
/// Keep vertical axis constant; resize horizontal with aspect ratio.
FixedVertical,
/// Keep horizontal axis constant; resize vertical with aspect ratio.
FixedHorizontal,
}
#[derive(Component, Debug, Clone, Reflect)]
#[reflect(Component)]
pub struct OrthographicProjection {
pub left: f32,
pub right: f32,
pub bottom: f32,
pub top: f32,
pub near: f32,
pub far: f32,
pub window_origin: WindowOrigin,
pub scaling_mode: ScalingMode,
pub scale: f32,
pub depth_calculation: DepthCalculation,
}
impl CameraProjection for OrthographicProjection {
fn get_projection_matrix(&self) -> Mat4 {
Mat4::orthographic_rh(
self.left * self.scale,
self.right * self.scale,
self.bottom * self.scale,
self.top * self.scale,
// NOTE: near and far are swapped to invert the depth range from [0,1] to [1,0]
// This is for interoperability with pipelines using infinite reverse perspective projections.
self.far,
self.near,
)
}
fn update(&mut self, width: f32, height: f32) {
match (&self.scaling_mode, &self.window_origin) {
(ScalingMode::WindowSize, WindowOrigin::Center) => {
let half_width = width / 2.0;
let half_height = height / 2.0;
self.left = -half_width;
self.right = half_width;
self.top = half_height;
self.bottom = -half_height;
}
(ScalingMode::WindowSize, WindowOrigin::BottomLeft) => {
self.left = 0.0;
self.right = width;
self.top = height;
self.bottom = 0.0;
}
(ScalingMode::FixedVertical, WindowOrigin::Center) => {
let aspect_ratio = width / height;
self.left = -aspect_ratio;
self.right = aspect_ratio;
self.top = 1.0;
self.bottom = -1.0;
}
(ScalingMode::FixedVertical, WindowOrigin::BottomLeft) => {
let aspect_ratio = width / height;
self.left = 0.0;
self.right = aspect_ratio;
self.top = 1.0;
self.bottom = 0.0;
}
(ScalingMode::FixedHorizontal, WindowOrigin::Center) => {
let aspect_ratio = height / width;
self.left = -1.0;
self.right = 1.0;
self.top = aspect_ratio;
self.bottom = -aspect_ratio;
}
(ScalingMode::FixedHorizontal, WindowOrigin::BottomLeft) => {
let aspect_ratio = height / width;
self.left = 0.0;
self.right = 1.0;
self.top = aspect_ratio;
self.bottom = 0.0;
}
(ScalingMode::None, _) => {}
}
}
fn depth_calculation(&self) -> DepthCalculation {
self.depth_calculation
}
fn far(&self) -> f32 {
self.far
}
}
impl Default for OrthographicProjection {
fn default() -> Self {
OrthographicProjection {
left: -1.0,
right: 1.0,
bottom: -1.0,
top: 1.0,
near: 0.0,
far: 1000.0,
window_origin: WindowOrigin::Center,
scaling_mode: ScalingMode::WindowSize,
scale: 1.0,
depth_calculation: DepthCalculation::Distance,
}
}
}