diff options
author | HampusM <hampus@hampusmat.com> | 2025-01-19 22:35:49 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-01-19 23:04:30 +0100 |
commit | e2c15f3f2fb6a67d615322020a78bf334621b16c (patch) | |
tree | 8a0d081574ac9376092b817332452284d18d551f /engine | |
parent | 9b4b46438eca26faca9809646dc1631ddcafd64e (diff) |
feat(engine): add orthographic projection support
Diffstat (limited to 'engine')
-rw-r--r-- | engine/src/data_types/dimens.rs | 11 | ||||
-rw-r--r-- | engine/src/projection.rs | 111 | ||||
-rw-r--r-- | engine/src/renderer/opengl.rs | 23 |
3 files changed, 114 insertions, 31 deletions
diff --git a/engine/src/data_types/dimens.rs b/engine/src/data_types/dimens.rs index b395627..5002436 100644 --- a/engine/src/data_types/dimens.rs +++ b/engine/src/data_types/dimens.rs @@ -1,7 +1,16 @@ -/// Dimensions. +/// 2D dimensions. #[derive(Debug, Clone, Copy)] pub struct Dimens<Value> { pub width: Value, pub height: Value, } + +/// 3D dimensions. +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] +pub struct Dimens3<Value> +{ + pub width: Value, + pub height: Value, + pub depth: Value, +} diff --git a/engine/src/projection.rs b/engine/src/projection.rs index aa84a9f..ecbe297 100644 --- a/engine/src/projection.rs +++ b/engine/src/projection.rs @@ -1,10 +1,14 @@ +use crate::data_types::dimens::Dimens3; use crate::matrix::Matrix; +use crate::util::builder; +use crate::vector::Vec3; #[derive(Debug)] #[non_exhaustive] pub enum Projection { Perspective(Perspective), + Orthographic(Orthographic), } /// Perspective projection parameters. @@ -16,6 +20,22 @@ pub struct Perspective pub near: f32, } +impl Perspective +{ + pub fn to_matrix(&self, aspect: f32) -> Matrix<f32, 4, 4> + { + let mut out = Matrix::new(); + + out.set_cell(0, 0, (1.0 / (self.fov_radians / 2.0).tan()) / aspect); + out.set_cell(1, 1, 1.0 / (self.fov_radians / 2.0).tan()); + out.set_cell(2, 2, (self.near + self.far) / (self.near - self.far)); + out.set_cell(2, 3, (2.0 * self.near * self.far) / (self.near - self.far)); + out.set_cell(3, 2, -1.0); + + out + } +} + impl Default for Perspective { fn default() -> Self @@ -28,30 +48,83 @@ impl Default for Perspective } } -pub(crate) fn new_perspective_matrix( - perspective: &Perspective, - aspect: f32, -) -> Matrix<f32, 4, 4> +builder! { +#[builder(name = OrthographicBuilder, derives=(Debug, Clone))] +#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[non_exhaustive] +pub struct Orthographic { - let mut out = Matrix::new(); + pub size: Dimens3<f32>, +} +} + +impl Orthographic +{ + pub fn builder() -> OrthographicBuilder + { + OrthographicBuilder::default() + } + + /// Creates a orthographic projection matrix using right-handed coordinates. + pub fn to_matrix_rh( + &self, + center_pos: &Vec3<f32>, + clip_volume: ClipVolume, + ) -> Matrix<f32, 4, 4> + { + let mut result = Matrix::<f32, 4, 4>::new(); + + let left = center_pos.x - (self.size.width / 2.0); + let right = center_pos.x + (self.size.width / 2.0); + let bottom = center_pos.y - (self.size.height / 2.0); + let top = center_pos.y + (self.size.height / 2.0); + let near = center_pos.z - (self.size.depth / 2.0); + let far = center_pos.z + (self.size.depth / 2.0); - out.set_cell(0, 0, (1.0 / (perspective.fov_radians / 2.0).tan()) / aspect); + match clip_volume { + ClipVolume::NegOneToOne => { + result.set_cell(0, 0, 2.0 / (right - left)); + result.set_cell(1, 1, 2.0 / (top - bottom)); + result.set_cell(2, 2, -2.0 / (far - near)); + result.set_cell(0, 3, -(right + left) / (right - left)); + result.set_cell(1, 3, -(top + bottom) / (top - bottom)); + result.set_cell(2, 3, -(far + near) / (far - near)); + result.set_cell(3, 3, 1.0); + } + } - out.set_cell(1, 1, 1.0 / (perspective.fov_radians / 2.0).tan()); + result + } +} - out.set_cell( - 2, - 2, - (perspective.near + perspective.far) / (perspective.near - perspective.far), - ); +impl Default for Orthographic +{ + fn default() -> Self + { + Self { + size: Dimens3 { + width: 10.0, + height: 7.0, + depth: 10.0, + }, + } + } +} - out.set_cell( - 2, - 3, - (2.0 * perspective.near * perspective.far) / (perspective.near - perspective.far), - ); +impl Default for OrthographicBuilder +{ + fn default() -> Self + { + let orthographic = Orthographic::default(); - out.set_cell(3, 2, -1.0); + OrthographicBuilder { size: orthographic.size } + } +} - out +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum ClipVolume +{ + /// -1 to +1. This is the OpenGL clip volume definition. + NegOneToOne, } diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index 7220ddc..f48dcc0 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -61,7 +61,7 @@ use crate::opengl::{ Capability, ContextFlags, }; -use crate::projection::{new_perspective_matrix, Projection}; +use crate::projection::{ClipVolume, Projection}; use crate::texture::{Id as TextureId, Texture}; use crate::transform::{Position, Scale}; use crate::util::NeverDrop; @@ -469,19 +469,20 @@ fn apply_transformation_matrices( gl_shader_program .set_uniform_matrix_4fv(c"model", &create_transformation_matrix(transformation)); - let view = create_view(camera, camera_pos); + let view_matrix = create_view_matrix(camera, &camera_pos.position); - gl_shader_program.set_uniform_matrix_4fv(c"view", &view); + gl_shader_program.set_uniform_matrix_4fv(c"view", &view_matrix); #[allow(clippy::cast_precision_loss)] - let projection = match &camera.projection { - Projection::Perspective(perspective) => new_perspective_matrix( - perspective, - window_size.width as f32 / window_size.height as f32, - ), + let proj_matrix = match &camera.projection { + Projection::Perspective(perspective_proj) => perspective_proj + .to_matrix(window_size.width as f32 / window_size.height as f32), + Projection::Orthographic(orthographic_proj) => { + orthographic_proj.to_matrix_rh(&camera_pos.position, ClipVolume::NegOneToOne) + } }; - gl_shader_program.set_uniform_matrix_4fv(c"projection", &projection); + gl_shader_program.set_uniform_matrix_4fv(c"projection", &proj_matrix); } fn apply_light<PointLightHolder>( @@ -694,11 +695,11 @@ fn create_light_uniform_name( } } -fn create_view(camera: &Camera, camera_pos: &Position) -> Matrix<f32, 4, 4> +fn create_view_matrix(camera: &Camera, camera_pos: &Vec3<f32>) -> Matrix<f32, 4, 4> { let mut view = Matrix::new(); - view.look_at(&camera_pos.position, &camera.target, &camera.global_up); + view.look_at(&camera_pos, &camera.target, &camera.global_up); view } |