summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-10-04 01:18:19 +0200
committerMel <einebeere@gmail.com>2022-10-04 01:18:19 +0200
commit0631fb666d2a28a6eb9b8d1578675699b41a5de6 (patch)
tree1db9b88d9c11074864f6959d32960eb6c54d3c4b /src
parent75f3941579c756655fc7d4d29e7b92b6eae436b7 (diff)
downloadmeowcraft-0631fb666d2a28a6eb9b8d1578675699b41a5de6.tar.zst
meowcraft-0631fb666d2a28a6eb9b8d1578675699b41a5de6.zip
Cube Rendering
Diffstat (limited to 'src')
-rw-r--r--src/Camera.cpp29
-rw-r--r--src/Camera.hpp25
-rw-r--r--src/Math/MVP.cpp82
-rw-r--r--src/Math/MVP.hpp11
-rw-r--r--src/Math/Math.hpp3
-rw-r--r--src/Math/Matrix.hpp46
-rw-r--r--src/Math/Rotation.hpp31
-rw-r--r--src/Math/Vector.hpp29
-rw-r--r--src/Shader/ShaderProgram.cpp10
-rw-r--r--src/Shader/ShaderProgram.hpp10
-rw-r--r--src/Shader/Uniform.cpp14
-rw-r--r--src/Shader/Uniform.hpp23
-rw-r--r--src/Shader/fragment.glsl5
-rw-r--r--src/Shader/vertex.glsl6
-rw-r--r--src/Window.cpp4
-rw-r--r--src/Window.hpp3
-rw-r--r--src/main.cpp76
17 files changed, 385 insertions, 22 deletions
diff --git a/src/Camera.cpp b/src/Camera.cpp
new file mode 100644
index 0000000..5bb9aa2
--- /dev/null
+++ b/src/Camera.cpp
@@ -0,0 +1,29 @@
+#include "Camera.hpp"
+
+namespace MC {
+
+Vector<3> Camera::position() {
+ return m_position;
+}
+
+void Camera::set_position(Vector<3> position) {
+ m_position = position;
+}
+
+void Camera::move(Vector<3> vector) {
+ m_position = m_position + vector;
+}
+
+Rotation Camera::angles() {
+ return m_angles;
+}
+
+void Camera::set_angles(Rotation angles) {
+ m_angles = angles;
+}
+
+void Camera::rotate(Rotation by) {
+ m_angles = m_angles + by;
+}
+
+}
diff --git a/src/Camera.hpp b/src/Camera.hpp
new file mode 100644
index 0000000..decba87
--- /dev/null
+++ b/src/Camera.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Math/Math.hpp"
+#include "Math/Rotation.hpp"
+
+namespace MC {
+
+class Camera {
+public:
+ Camera() = default;
+
+ Vector<3> position();
+ void set_position(Vector<3> position);
+ void move(Vector<3> by);
+
+ Rotation angles();
+ void set_angles(Rotation angles);
+ void rotate(Rotation by);
+
+private:
+ Vector<3> m_position = {};
+ Rotation m_angles = {};
+};
+
+} \ No newline at end of file
diff --git a/src/Math/MVP.cpp b/src/Math/MVP.cpp
new file mode 100644
index 0000000..37675b4
--- /dev/null
+++ b/src/Math/MVP.cpp
@@ -0,0 +1,82 @@
+#include <cmath>
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+#include <glm/gtc/type_ptr.hpp>
+#include <glm/gtx/string_cast.hpp>
+#include "MVP.hpp"
+#include "Math.hpp"
+
+namespace Math::MVP {
+
+Matrix<4, 4> transformation_matrix(Vector<3> position) {
+ return {
+ 1.0f, 0.0f, 0.0f, position.x(),
+ 0.0f, 1.0f, 0.0f, position.y(),
+ 0.0f, 0.0f, 1.0f, position.z(),
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+}
+
+Matrix<4, 4> rotation_matrix(Rotation angles) {
+ auto c = angles.vector.apply(cos);
+ auto s = angles.vector.apply(sin);
+
+ Matrix<4, 4> rotation_x{
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, c.x(), -s.x(), 0.0f,
+ 0.0f, s.x(), c.x(), 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ };
+
+ Matrix<4, 4> rotation_y{
+ c.y(), 0.0f, s.y(), 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ -s.y(), 0.0f, c.y(), 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ };
+
+ Matrix<4, 4> rotation_z{
+ c.z(), -s.z(), 0.0f, 0.0f,
+ s.z(), c.z(), 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ };
+
+ return rotation_x * rotation_y * rotation_z;
+}
+
+Matrix<4, 4> model(Vector<3> position, Rotation angles) {
+ auto transformation = transformation_matrix(position);
+ auto rotation = rotation_matrix(angles);
+
+ return transformation * rotation;
+}
+
+Matrix<4, 4> view(Vector<3> position, Rotation angles) {
+ auto transformation = transformation_matrix(position);
+ auto rotation = rotation_matrix(angles);
+
+ return transformation * rotation;
+}
+
+Matrix<4, 4> projection(float aspect, float fov, float near, float far) {
+ auto fov_radians = (fov * M_PI) / 180.0f;
+
+ float x_scale = 1.0f / (tan(fov_radians / 2.0f) * aspect);
+ float y_scale = 1.0f / tan(fov_radians / 2.0f);
+
+ float frustum_length = far - near;
+ float z_near = -(far + near) / frustum_length;
+ float z_far = -(2 * far * near) / frustum_length;
+
+ Matrix<4, 4> projection{
+ x_scale, 0.0f, 0.0f, 0.0f,
+ 0.0f, y_scale, 0.0f, 0.0f,
+ 0.0f, 0.0f, z_near, z_far,
+ 0.0f, 0.0f, -1.0f, 0.0f,
+ };
+
+ return projection;
+}
+
+}
diff --git a/src/Math/MVP.hpp b/src/Math/MVP.hpp
new file mode 100644
index 0000000..c3fb64f
--- /dev/null
+++ b/src/Math/MVP.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Math.hpp"
+
+namespace Math::MVP {
+
+Matrix<4, 4> model(Vector<3> position, Rotation angles);
+Matrix<4, 4> view(Vector<3> position, Rotation angles);
+Matrix<4, 4> projection(float aspect, float fov, float near, float far);
+
+}
diff --git a/src/Math/Math.hpp b/src/Math/Math.hpp
index 8204728..b8b61a1 100644
--- a/src/Math/Math.hpp
+++ b/src/Math/Math.hpp
@@ -1,4 +1,5 @@
#pragma once
#include "Vector.hpp"
-#include "Matrix.hpp" \ No newline at end of file
+#include "Matrix.hpp"
+#include "Rotation.hpp" \ No newline at end of file
diff --git a/src/Math/Matrix.hpp b/src/Math/Matrix.hpp
index adc34a9..9a6b7e6 100644
--- a/src/Math/Matrix.hpp
+++ b/src/Math/Matrix.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <sstream>
-#include <stddef.h>
+#include <cstddef>
#include <iostream>
template <size_t R, size_t C, typename T = float>
@@ -9,8 +9,24 @@ struct Matrix {
public:
Matrix<R, C, T>() : elements{} {};
+ Matrix<R, C, T>(T scalar) {
+ std::fill(elements, elements + R * C, scalar);
+ };
+
template<typename ...Args>
- explicit Matrix<R, C, T>(Args... args): elements{ args... } {};
+ Matrix<R, C, T>(Args... args): elements{ args... } {};
+
+ Matrix<R, C, T>(T values[R * C]) {
+ std::copy(values, values + R * C, elements);
+ };
+
+ static Matrix<R, R, T> identity() {
+ Matrix<R, R, T> result{};
+ for (int i = 0; i < R; i++) {
+ result(i, i) = 1;
+ }
+ return result;
+ }
Vector<C, T> row(size_t index) {
return { &elements[index * C] };
@@ -24,6 +40,22 @@ public:
return result;
}
+ Matrix<R, C, T> operator+(Matrix<R, C, T> other) {
+ Matrix<R, C, T> result{};
+ for (int i = 0; i < R * C; i++) {
+ result.elements[i] = elements[i] + other.elements[i];
+ }
+ return result;
+ }
+
+ Matrix<R, C, T> operator*(float scalar) {
+ Matrix<R, C, T> result{};
+ for (int i = 0; i < R * C; i++) {
+ result.elements[i] = elements[i] * scalar;
+ }
+ return result;
+ }
+
template<size_t N>
Matrix<R, N, T> operator*(Matrix<C, N, T> other) {
Matrix<R, N, T> result{};
@@ -34,16 +66,18 @@ public:
auto dot = r * c;
- std::cout << x << ", " << y << ": "
- << "(" << r.string() << ", " << c.string() << ")"
- << dot << std::endl;
-
result(x, y) = dot;
}
}
return result;
}
+ Vector<R, T> operator*(Vector<R, T> vector) {
+ Matrix<R, 1, T> matrix(vector.elements);
+ matrix = this->operator*(matrix);
+ return { matrix.elements };
+ }
+
auto& operator()(size_t x, size_t y) {
return elements[y * C + x];
}
diff --git a/src/Math/Rotation.hpp b/src/Math/Rotation.hpp
new file mode 100644
index 0000000..334ede2
--- /dev/null
+++ b/src/Math/Rotation.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <cmath>
+#include "Vector.hpp"
+
+struct Rotation {
+public:
+ Rotation() : vector{} {};
+
+ Rotation(Vector<3> vector) : vector{ wrap(vector) } {};
+
+ Rotation(float angles[3]) : Rotation(angles[0], angles[1], angles[2]) {};
+
+ Rotation(float x, float y, float z) {
+ vector = wrap({ x, y, z });
+ };
+
+ Rotation operator+(Rotation other) const {
+ return wrap(vector + other.vector);
+ }
+
+ std::string string() const {
+ return vector.string();
+ }
+
+ static Vector<3> wrap(Vector<3> v) {
+ return v.apply([=](float a) -> float { return fmod(a, 360.0f); });
+ }
+
+ Vector<3> vector;
+}; \ No newline at end of file
diff --git a/src/Math/Vector.hpp b/src/Math/Vector.hpp
index 0145b58..2e97217 100644
--- a/src/Math/Vector.hpp
+++ b/src/Math/Vector.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <stddef.h>
+#include <cstddef>
#include <sstream>
#include <iostream>
#include <iterator>
@@ -17,10 +17,35 @@ public:
std::copy(values, values + S, elements);
};
+ Vector<S, T>(Vector<S - 1, T> vector, T scalar) {
+ std::copy(vector.elements, vector.elements + S - 1, elements);
+ elements[S - 1] = scalar;
+ }
+
+ Vector<S, T> apply(T f(T)) {
+ return apply(static_cast<std::function<T(T)>>(f));
+ }
+
+ Vector<S, T> apply(std::function<T(T)> f) {
+ Vector<S, T> result{};
+ for (int i = 0; i < S; i++) {
+ result[i] = f(elements[i]);
+ }
+ return result;
+ }
+
T& operator[](size_t index) {
return elements[index];
}
+ Vector<S, T> operator+(Vector<S, T> other) const {
+ Vector<S, T> result{};
+ for (int i = 0; i < S; i++) {
+ result[i] = elements[i] + other[i];
+ }
+ return result;
+ }
+
Vector<S, T> operator*(T scalar) const {
Vector<S, T> result;
for (size_t index; index < S; index++) {
@@ -57,7 +82,7 @@ public:
return elements[3];
}
- std::string string() {
+ std::string string() const {
std::stringstream str{};
str << "[ ";
diff --git a/src/Shader/ShaderProgram.cpp b/src/Shader/ShaderProgram.cpp
index 854b1bf..4d0b684 100644
--- a/src/Shader/ShaderProgram.cpp
+++ b/src/Shader/ShaderProgram.cpp
@@ -29,4 +29,14 @@ void ShaderProgram::bind() const {
glUseProgram(m_program);
}
+Uniform ShaderProgram::uniform(const std::string& name) const {
+ auto index = glGetUniformLocation(m_program, name.c_str());
+
+ return {name, static_cast<uint32_t>(index)};
+}
+
+uint32_t ShaderProgram::get() const {
+ return m_program;
+}
+
}
diff --git a/src/Shader/ShaderProgram.hpp b/src/Shader/ShaderProgram.hpp
index 800e3ff..857dc2f 100644
--- a/src/Shader/ShaderProgram.hpp
+++ b/src/Shader/ShaderProgram.hpp
@@ -1,6 +1,10 @@
#pragma once
+#include <string>
+#include <vector>
#include "Shader.hpp"
+#include "../Math/Math.hpp"
+#include "Uniform.hpp"
namespace MC {
@@ -8,9 +12,11 @@ class ShaderProgram {
public:
ShaderProgram(Shader fragment, Shader vertex);
- void bind() const;
+ uint32_t get() const;
+
+ Uniform uniform(const std::string& name) const;
- uint32_t get();
+ void bind() const;
private:
uint32_t m_program;
diff --git a/src/Shader/Uniform.cpp b/src/Shader/Uniform.cpp
new file mode 100644
index 0000000..71b7633
--- /dev/null
+++ b/src/Shader/Uniform.cpp
@@ -0,0 +1,14 @@
+#include <GL/glew.h>
+#include "Uniform.hpp"
+
+namespace MC {
+
+void Uniform::set(Matrix<4, 4> value) const {
+ glUniformMatrix4fv(m_index, 1, GL_TRUE, value.elements);
+}
+
+void Uniform::set(Vector<3> value) const {
+ glUniform3f(m_index, value.x(), value.y(), value.z());
+}
+
+}
diff --git a/src/Shader/Uniform.hpp b/src/Shader/Uniform.hpp
new file mode 100644
index 0000000..58cdc28
--- /dev/null
+++ b/src/Shader/Uniform.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include "../Math/Math.hpp"
+
+namespace MC {
+
+class Uniform {
+public:
+ Uniform(std::string name, uint32_t index)
+ : m_name(std::move(name)), m_index(index) {};
+
+ void set(Matrix<4, 4> value) const;
+ void set(Vector<3> value) const;
+
+private:
+ std::string m_name;
+ uint32_t m_index;
+};
+
+}
diff --git a/src/Shader/fragment.glsl b/src/Shader/fragment.glsl
index 017a2c8..ba5ed93 100644
--- a/src/Shader/fragment.glsl
+++ b/src/Shader/fragment.glsl
@@ -2,7 +2,6 @@
out vec4 color;
-void main()
-{
- color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
+void main() {
+ color = vec4(0.2f, 0.6f, 0.6f, 1.0f); // #339999
} \ No newline at end of file
diff --git a/src/Shader/vertex.glsl b/src/Shader/vertex.glsl
index 8b1bbbd..e7b9e3d 100644
--- a/src/Shader/vertex.glsl
+++ b/src/Shader/vertex.glsl
@@ -1,7 +1,11 @@
#version 330 core
+uniform mat4 model_matrix;
+uniform mat4 view_matrix;
+uniform mat4 projection_matrix;
+
in vec3 position;
void main() {
- gl_Position = vec4(position.x, position.y, position.z, 1.0);
+ gl_Position = projection_matrix * view_matrix * model_matrix * vec4(position, 1.0);
} \ No newline at end of file
diff --git a/src/Window.cpp b/src/Window.cpp
index 54d70f9..413cd47 100644
--- a/src/Window.cpp
+++ b/src/Window.cpp
@@ -43,4 +43,8 @@ void Window::start_frame() {
glfwPollEvents();
}
+void Window::on_size_change(void (callback)(GLFWwindow*, int, int)) {
+ glfwSetFramebufferSizeCallback(m_window, static_cast<GLFWframebuffersizefun>(callback));
+}
+
} \ No newline at end of file
diff --git a/src/Window.hpp b/src/Window.hpp
index acd39fe..5a2b640 100644
--- a/src/Window.hpp
+++ b/src/Window.hpp
@@ -12,6 +12,8 @@ public:
GLFWwindow* get();
+ void on_size_change(void (* callback)(GLFWwindow*, int, int));
+
void close();
void start_frame();
@@ -19,6 +21,7 @@ public:
bool should_close();
private:
GLFWwindow* m_window;
+
};
} \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 0893849..16eda51 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,19 +1,27 @@
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
+#include <cmath>
+#include <cstdint>
#include "Window.hpp"
#include "Mesh.hpp"
+#include "Camera.hpp"
#include "Binder.hpp"
+#include "Math/MVP.hpp"
#include "Shader/ShaderProgram.hpp"
#define APP_NAME "Meowcraft"
#define WINDOW_WIDTH 1000
#define WINDOW_HEIGHT 800
+#define ASPECT static_cast<float>(WINDOW_WIDTH) / WINDOW_HEIGHT
+
+#define FOV 45
void run();
void render(MC::BindableMesh&);
+void process_input(MC::Window&, MC::Camera&);
void setup_gl();
void fix_macos_render(MC::Window&);
@@ -37,18 +45,45 @@ void run() {
setup_gl();
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
+ window.on_size_change([](GLFWwindow* window, int w, int h) {
+ glViewport(0, 0, w, h);
+ });
MC::Mesh shape({
- {-0.5f, -0.5f, 0.0f}, {0.5f, -0.5f, 0.0f},
- {-0.5f, 0.5f, 0.0f}, {0.5f, 0.5f, 0.0f},
- }, {0, 1, 2, 3, 2, 1});
+ {-0.5f, -0.5f, 0.5f},
+ {0.5f, -0.5f, 0.5f},
+ {0.5f, 0.5f, 0.5f},
+ {-0.5f, 0.5f, 0.5f},
+
+ {-0.5f, -0.5f, -0.5f},
+ {0.5f, -0.5f, -0.5f},
+ {0.5f, 0.5f, -0.5f},
+ {-0.5f, 0.5f, -0.5f}
+ }, {
+ 0, 1, 2, 2, 3, 0,
+ 1, 5, 6, 6, 2, 1,
+ 7, 6, 5, 5, 4, 7,
+ 4, 0, 3, 3, 7, 4,
+ 4, 5, 1, 1, 0, 4,
+ 3, 2, 6, 6, 7, 3
+ });
auto mesh = MC::Binder::load(shape);
- auto mesh = MC::Binder::load(quad);
+ MC::Camera camera{};
+ camera.set_position({0.0f, 0.0f, -3.0f});
MC::ShaderProgram program(MC::Shader::create_fragment(), MC::Shader::create_vertex());
+
+ auto model_uniform = program.uniform("model_matrix");
+ auto view_uniform = program.uniform("view_matrix");
+ auto projection_uniform = program.uniform("projection_matrix");
+
program.bind();
+ auto projection = Math::MVP::projection(ASPECT, FOV, 0.1f, 100.0f);
+ projection_uniform.set(projection);
+
+ uint64_t time = 0;
while (!window.should_close()) {
window.start_frame();
@@ -57,11 +92,19 @@ void run() {
fix_macos_render(window);
#endif
- if (window.key(GLFW_KEY_ESCAPE, GLFW_PRESS)) {
- window.close();
- }
+ process_input(window, camera);
+
+ program.bind();
+
+ auto angle = fmod(time / 10.0f, 360.0f);
+ auto model = Math::MVP::model({0.0f, 0.0f, 0.0f}, {angle, angle, 0.0f});
+ model_uniform.set(model);
+
+ auto view = Math::MVP::view(camera.position(), camera.angles());
+ view_uniform.set(view);
render(mesh);
+ time++;
}
}
@@ -74,6 +117,25 @@ void render(MC::BindableMesh& mesh) {
mesh.unbind();
}
+void process_input(MC::Window& window, MC::Camera& camera) {
+ if (window.key(GLFW_KEY_ESCAPE, GLFW_PRESS)) {
+ window.close();
+ }
+
+ auto key = [&](int key) -> float { return window.key(key, GLFW_PRESS); };
+
+ float forward = key(GLFW_KEY_W) - key(GLFW_KEY_S);
+ float side = key(GLFW_KEY_D) - key(GLFW_KEY_A);
+
+ float vertical = key(GLFW_KEY_UP) - key(GLFW_KEY_DOWN);
+ float horizontal = key(GLFW_KEY_LEFT) - key(GLFW_KEY_RIGHT);
+
+ auto speed = 0.05f;
+
+ camera.move({side * speed, forward * speed, 0.0f});
+ camera.rotate({vertical * speed, horizontal * speed, 0.0f});
+}
+
void setup_gl() {
GLenum error;
if ((error = glewInit()) != GLEW_OK) {