summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-01-19 22:35:49 +0100
committerHampusM <hampus@hampusmat.com>2025-01-19 23:04:30 +0100
commite2c15f3f2fb6a67d615322020a78bf334621b16c (patch)
tree8a0d081574ac9376092b817332452284d18d551f /engine
parent9b4b46438eca26faca9809646dc1631ddcafd64e (diff)
feat(engine): add orthographic projection support
Diffstat (limited to 'engine')
-rw-r--r--engine/src/data_types/dimens.rs11
-rw-r--r--engine/src/projection.rs111
-rw-r--r--engine/src/renderer/opengl.rs23
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
}