summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2023-10-23 22:23:25 +0200
committerHampusM <hampus@hampusmat.com>2023-10-23 22:23:25 +0200
commit386aad9dac7c22cabb0f1bbba33d248c40bb0310 (patch)
tree1f4379ab50ffc85e9ad511b9fe9e9dd8a7f8c321
parentfee2320189d6e758748a939c56d539043cbffde6 (diff)
feat(engine): add perspective
-rw-r--r--engine/src/lib.rs8
-rw-r--r--engine/src/matrix.rs9
-rw-r--r--engine/src/projection.rs21
-rw-r--r--engine/src/renderer/mod.rs51
-rw-r--r--engine/vertex.glsl6
5 files changed, 87 insertions, 8 deletions
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<Value, const ROWS: usize, const COLUMNS: usize>
impl<Value, const ROWS: usize, const COLUMNS: usize> Matrix<Value, ROWS, COLUMNS>
{
+ 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<f32, 4, 4>
+{
+ 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<Item = &'obj Object>)
+pub fn render<'obj>(
+ objects: impl IntoIterator<Item = &'obj Object>,
+ 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<f32, 4, 4>,
+ 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;
}