Skip to content

Commit

Permalink
Add support for building infinite projection matrices.
Browse files Browse the repository at this point in the history
Both standard and reverse depth.

The infinite reverse projection matrix is the only one we use, and it is the one with the best precision and the simplest construction. So really the one most everyone should use by default.

Probably should rename the perspective_glu function here also, or maybe (depending on how opionated we want to be) simply remove it? It is only useful in OpenGL due to the -1,1 depth range and it should have a `_rh` suffix to indicate it is right-handed.
  • Loading branch information
repi committed Sep 17, 2019
1 parent 083f6a7 commit 36bf36a
Showing 1 changed file with 29 additions and 46 deletions.
75 changes: 29 additions & 46 deletions src/f32/mat4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,15 @@ impl Mat4 {
}

#[inline]
/// Returns the equivalent of the common pespective function `gluPerspective`.
/// Builds a right-handed perspective projection matrix with [-1,1] depth range.
/// This is the equivalent of the common pespective function `gluPerspective` in OpenGL.
/// See https://www.khronos.org/opengl/wiki/GluPerspective_code
pub fn perspective_glu(fovy: Angle, aspect: f32, nearz: f32, farz: f32) -> Mat4 {
let inv_length = 1.0 / (nearz - farz);
let f = 1.0 / (0.5 * fovy).tan();
let a = f / aspect;
let b = (nearz + farz) * inv_length;
let c = (2.0 * nearz * farz) * inv_length;
pub fn perspective_glu(fov_y: Angle, aspect_ratio: f32, z_near: f32, z_far: f32) -> Mat4 {
let inv_length = 1.0 / (z_near - z_far);
let f = 1.0 / (0.5 * fov_y).tan();
let a = f / aspect_ratio;
let b = (z_near + z_far) * inv_length;
let c = (2.0 * z_near * z_far) * inv_length;
Mat4::new(
Vec4::new(a, 0.0, 0.0, 0.0),
Vec4::new(0.0, f, 0.0, 0.0),
Expand All @@ -431,45 +432,27 @@ impl Mat4 {
)
}

// #[inline]
// pub fn perspective_fov_lh(fovy: Angle, aspect: f32, nearz: f32, farz: f32) -> Self {
// glam_assert!(nearz > 0.0 && farz > 0.0);
// glam_assert!(fovy != Angle::from_radians(0.0));
// glam_assert!(aspect != 0.0);
// glam_assert!(farz != nearz);

// let (sin_fov, cos_fov) = (0.5 * fovy).sin_cos();
// let height = cos_fov / sin_fov;
// let width = height / aspect;
// let range = farz / (farz - nearz);

// Mat4 {
// x_axis: Vec4::new(width, 0.0, 0.0, 0.0),
// y_axis: Vec4::new(0.0, height, 0.0, 0.0),
// z_axis: Vec4::new(0.0, 0.0, range, 1.0),
// w_axis: Vec4::new(0.0, 0.0, -range * nearz, 0.0),
// }
// }

// #[inline]
// pub fn perspective_fov_rh(fovy: Angle, aspect: f32, nearz: f32, farz: f32) -> Self {
// glam_assert!(nearz > 0.0 && farz > 0.0);
// glam_assert!(fovy != Angle::from_radians(0.0));
// glam_assert!(aspect != 0.0);
// glam_assert!(farz != nearz);

// let (sin_fov, cos_fov) = (0.5 * fovy).sin_cos();
// let height = cos_fov / sin_fov;
// let width = height / aspect;
// let range = farz / (nearz - farz);

// Mat4 {
// x_axis: Vec4::new(width, 0.0, 0.0, 0.0),
// y_axis: Vec4::new(0.0, height, 0.0, 0.0),
// z_axis: Vec4::new(0.0, 0.0, range, -1.0),
// w_axis: Vec4::new(0.0, 0.0, range * nearz, 0.0),
// }
// }
/// Build infinite right-handed perspective projection matrix with [0,1] depth range.
pub fn perspective_infinite_rh(fov_y: Angle, aspect_ratio: f32, z_near: f32) -> Mat4 {
let f = 1.0 / (0.5 * fov_y).tan();
Mat4::new(
Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
Vec4::new(0.0, f, 0.0, 0.0),
Vec4::new(0.0, 0.0, -1.0, -1.0),
Vec4::new(0.0, 0.0, -z_near, 0.0),
)
}

/// Build infinite reverse right-handed perspective projection matrix with [0,1] depth range.
pub fn perspective_infinite_reverse_rh(fov_y: Angle, aspect_ratio: f32, z_near: f32) -> Mat4 {
let f = 1.0 / (0.5 * fov_y).tan();
Mat4::new(
Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
Vec4::new(0.0, f, 0.0, 0.0),
Vec4::new(0.0, 0.0, 0.0, -1.0),
Vec4::new(0.0, 0.0, z_near, 0.0),
)
}

#[inline]
pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
Expand Down

0 comments on commit 36bf36a

Please sign in to comment.