From 386aad9dac7c22cabb0f1bbba33d248c40bb0310 Mon Sep 17 00:00:00 2001 From: HampusM Date: Mon, 23 Oct 2023 22:23:25 +0200 Subject: feat(engine): add perspective --- engine/src/lib.rs | 8 +++++++- engine/src/matrix.rs | 9 ++++++++ engine/src/projection.rs | 21 +++++++++++++++++++ engine/src/renderer/mod.rs | 51 +++++++++++++++++++++++++++++++++++++++++----- engine/vertex.glsl | 6 ++++-- 5 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 engine/src/projection.rs (limited to 'engine') diff --git a/engine/src/lib.rs b/engine/src/lib.rs index dbbd407..ee93695 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -9,6 +9,7 @@ use crate::vector::Vec2; mod matrix; mod opengl; +mod projection; mod renderer; mod transform; @@ -93,7 +94,9 @@ impl Engine while !self.window.should_close() { func(self); - crate::renderer::render(self.objects.values()); + let window_size = self.window.size().map_err(Error::GetWindowSizeFailed)?; + + crate::renderer::render(self.objects.values(), &window_size); self.window .swap_buffers() @@ -123,4 +126,7 @@ pub enum Error #[error("Failed to update window")] UpdateWindowFailed(#[source] glfw::Error), + + #[error("Failed to get window size")] + GetWindowSizeFailed(#[source] glfw::Error), } diff --git a/engine/src/matrix.rs b/engine/src/matrix.rs index 7e161f2..c060b59 100644 --- a/engine/src/matrix.rs +++ b/engine/src/matrix.rs @@ -10,6 +10,15 @@ pub struct Matrix impl Matrix { + pub fn new() -> Self + where + Value: Default + Copy, + { + Self { + items: [[Value::default(); ROWS]; COLUMNS], + } + } + /// Sets the value at the specified cell. pub fn set_cell(&mut self, row: usize, column: usize, value: Value) { diff --git a/engine/src/projection.rs b/engine/src/projection.rs new file mode 100644 index 0000000..d5186ba --- /dev/null +++ b/engine/src/projection.rs @@ -0,0 +1,21 @@ +use crate::matrix::Matrix; + +/// Creates a new perspective projection matrix. +#[must_use] +pub fn new_perspective( + fov_radians: f32, + aspect: f32, + far: f32, + near: f32, +) -> Matrix +{ + let mut out = Matrix::new(); + + out.set_cell(0, 0, (1.0 / (fov_radians / 2.0).tan()) / aspect); + out.set_cell(1, 1, 1.0 / (fov_radians / 2.0).tan()); + out.set_cell(2, 2, (near + far) / (near - far)); + out.set_cell(2, 3, (2.0 * near * far) / (near - far)); + out.set_cell(3, 2, -1.0); + + out +} diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs index a02bbc2..d577054 100644 --- a/engine/src/renderer/mod.rs +++ b/engine/src/renderer/mod.rs @@ -4,6 +4,7 @@ use std::process::abort; use cstr::cstr; use glfw::WindowSize; +use crate::matrix::Matrix; use crate::object::Object; use crate::opengl::buffer::{ ArrayKind as ArrayBufferKind, @@ -16,7 +17,8 @@ use crate::opengl::debug::{MessageSeverity, MessageSource, MessageType}; use crate::opengl::shader::Program as ShaderProgram; use crate::opengl::vertex_array::{PrimitiveKind, VertexArray}; use crate::opengl::{clear_buffers, BufferClearMask}; -use crate::vector::Vec2; +use crate::projection::new_perspective; +use crate::vector::{Vec2, Vec3}; use crate::vertex::Vertex; pub fn initialize(window: &glfw::Window) -> Result<(), Error> @@ -99,16 +101,25 @@ fn opengl_debug_message_cb( }; } -pub fn render<'obj>(objects: impl IntoIterator) +pub fn render<'obj>( + objects: impl IntoIterator, + window_size: &WindowSize, +) { clear_buffers(BufferClearMask::COLOR); for obj in objects { obj.renderable().shader_program.activate(); - obj.renderable() - .shader_program - .set_uniform_matrix_4fv(cstr!("transform"), &obj.transform().as_matrix()); + let mut view = Matrix::new_identity(); + + view.translate(&Vec3 { + x: 0.0, + y: 0.0, + z: -3.0, + }); + + apply_transformation_matrices(obj, &view, window_size); obj.renderable().vertex_arr.bind(|vert_arr_curr_bound| { if let Some(index_info) = &obj.renderable().index_info { @@ -203,3 +214,33 @@ pub enum Error #[error("Failed to get window size")] GetWindowSizeFailed(#[source] glfw::Error), } + +fn apply_transformation_matrices( + object: &Object, + view: &Matrix, + window_size: &WindowSize, +) +{ + object + .renderable() + .shader_program + .set_uniform_matrix_4fv(cstr!("model"), &object.transform().as_matrix()); + + object + .renderable() + .shader_program + .set_uniform_matrix_4fv(cstr!("view"), view); + + #[allow(clippy::cast_precision_loss)] + let projection = new_perspective( + 80.0f32.to_radians(), + window_size.width as f32 / window_size.height as f32, + 0.1, + 100.0, + ); + + object + .renderable() + .shader_program + .set_uniform_matrix_4fv(cstr!("projection"), &projection); +} diff --git a/engine/vertex.glsl b/engine/vertex.glsl index db3d612..b0a2a13 100644 --- a/engine/vertex.glsl +++ b/engine/vertex.glsl @@ -4,11 +4,13 @@ layout (location = 1) in vec3 color; out vec3 in_frag_color; -uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; void main() { - gl_Position = transform * vec4(pos, 1.0); + gl_Position = projection * view * model * vec4(pos, 1.0); in_frag_color = color; } -- cgit v1.2.3-18-g5258