From 474874d21b651430f6314790affcf84a724dd1d1 Mon Sep 17 00:00:00 2001 From: sebastian Date: Wed, 29 Jul 2026 16:33:14 +0200 Subject: [PATCH] ADD: Projection, Transformation and ViewMatrix --- CMakeLists.txt | 12 +++- assets/shaders/basic.vert | 7 ++- engine/src/renderer/entities/Camera.cpp | 54 ++++++++++++++++ engine/src/renderer/entities/Camera.h | 63 +++++++++++++++++++ .../renderer/{model => entities}/Entity.cpp | 0 .../src/renderer/{model => entities}/Entity.h | 6 +- engine/src/renderer/shader/StaticShader.cpp | 5 ++ engine/src/renderer/shader/StaticShader.h | 44 +++++++++++++ .../openglWrapper/shader/ShaderProgram.cpp | 8 +++ .../openglWrapper/shader/ShaderProgram.h | 9 ++- .../utils/openglWrapper/shader/Uniform.cpp | 20 ++++++ .../src/utils/openglWrapper/shader/Uniform.h | 30 +++++++++ .../openglWrapper/shader/UniformValue.cpp | 5 ++ .../utils/openglWrapper/shader/UniformValue.h | 42 +++++++++++++ game/src/ColorRaceApp.cpp | 5 +- game/src/ColorRaceApp.h | 15 +++-- 16 files changed, 313 insertions(+), 12 deletions(-) create mode 100644 engine/src/renderer/entities/Camera.cpp create mode 100644 engine/src/renderer/entities/Camera.h rename engine/src/renderer/{model => entities}/Entity.cpp (100%) rename engine/src/renderer/{model => entities}/Entity.h (82%) create mode 100644 engine/src/renderer/shader/StaticShader.cpp create mode 100644 engine/src/renderer/shader/StaticShader.h create mode 100644 engine/src/utils/openglWrapper/shader/Uniform.cpp create mode 100644 engine/src/utils/openglWrapper/shader/Uniform.h create mode 100644 engine/src/utils/openglWrapper/shader/UniformValue.cpp create mode 100644 engine/src/utils/openglWrapper/shader/UniformValue.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 114e36f..f49df64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,10 @@ add_library(Engine STATIC engine/src/utils/openglWrapper/shader/ShaderProgram.h engine/src/renderer/primitives/CubeFactory.cpp engine/src/renderer/primitives/CubeFactory.h + engine/src/utils/openglWrapper/shader/Uniform.cpp + engine/src/utils/openglWrapper/shader/Uniform.h + engine/src/utils/openglWrapper/shader/UniformValue.cpp + engine/src/utils/openglWrapper/shader/UniformValue.h ) target_include_directories(Engine PUBLIC engine/src) target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui) @@ -108,8 +112,12 @@ add_executable(ColorRace game/src/ColorRaceApp.h engine/src/renderer/model/RawModel.cpp engine/src/renderer/model/RawModel.h - engine/src/renderer/model/Entity.cpp - engine/src/renderer/model/Entity.h + engine/src/renderer/entities/Entity.cpp + engine/src/renderer/entities/Entity.h + engine/src/renderer/shader/StaticShader.cpp + engine/src/renderer/shader/StaticShader.h + engine/src/renderer/entities/Camera.cpp + engine/src/renderer/entities/Camera.h ) diff --git a/assets/shaders/basic.vert b/assets/shaders/basic.vert index 1427b35..9717514 100644 --- a/assets/shaders/basic.vert +++ b/assets/shaders/basic.vert @@ -1,6 +1,11 @@ #version 460 core layout(location = 0) in vec3 position; +uniform mat4 transformationMatrix; +uniform mat4 projectionMatrix; +uniform mat4 viewMatrix; + void main() { - gl_Position = vec4(position, 1.0); + vec4 worldPosition = transformationMatrix * vec4(position, 1.0f); + gl_Position = projectionMatrix * viewMatrix * worldPosition; } \ No newline at end of file diff --git a/engine/src/renderer/entities/Camera.cpp b/engine/src/renderer/entities/Camera.cpp new file mode 100644 index 0000000..8aea57e --- /dev/null +++ b/engine/src/renderer/entities/Camera.cpp @@ -0,0 +1,54 @@ +// +// Created by sebastian on 29.07.26. +// + +#include "Camera.h" +#include +glm::vec3 engine::Camera::getForward() const { + // Yaw um Y-Achse, Pitch um lokale X-Achse — Standard-FPS-Konvention + glm::vec3 forward; + forward.x = std::cos(glm::radians(m_pitch)) * std::sin(glm::radians(m_yaw)); + forward.y = std::sin(glm::radians(m_pitch)); + forward.z = -std::cos(glm::radians(m_pitch)) * std::cos(glm::radians(m_yaw)); + return glm::normalize(forward); +} + +glm::vec3 engine::Camera::getRight() const { + return glm::normalize(glm::cross(getForward(), glm::vec3(0.0f, 1.0f, 0.0f))); +} + +glm::vec3 engine::Camera::getUp() const { + return glm::normalize(glm::cross(getRight(), getForward())); +} + +void engine::Camera::moveRelative(const glm::vec3 &direction, float speed, float deltaTime) { + glm::vec3 worldOffset = getRight() * direction.x + getUp() * direction.y + getForward() * direction.z; + + if (worldOffset != glm::vec3(0.0f)) { + worldOffset = glm::normalize(worldOffset); + } + + m_position += worldOffset * speed * deltaTime; +} + +void engine::Camera::moveWorld(const glm::vec3 &offset) { + m_position += offset; +} + +glm::mat4 engine::Camera::getViewMatrix() const { + glm::vec3 forward = getForward(); + glm::vec3 up = getUp(); + + glm::mat4 view = glm::lookAt(m_position, m_position + forward, up); + + // Roll: Rotation um die Blickachse, nachträglich im View-Space angewendet + if (m_roll != 0.0f) { + view = glm::rotate(glm::mat4(1.0f), glm::radians(m_roll), glm::vec3(0.0f, 0.0f, 1.0f)) * view; + } + + return view; +} + +glm::mat4 engine::Camera::getProjectionMatrix() const { + return glm::perspective(m_fovY, m_aspect, m_near, m_far); +} diff --git a/engine/src/renderer/entities/Camera.h b/engine/src/renderer/entities/Camera.h new file mode 100644 index 0000000..2be7736 --- /dev/null +++ b/engine/src/renderer/entities/Camera.h @@ -0,0 +1,63 @@ +// +// Created by sebastian on 29.07.26. +// + +#ifndef COLORRACE_CAMERA_H +#define COLORRACE_CAMERA_H +#pragma once +#include +namespace engine { + class Camera { + private: + glm::vec3 m_position{0.0f, 5.0f, 0.0f}; + float m_pitch = 0.0f; + float m_yaw = 0.0f; + float m_roll = 0.0f; + + float m_fovY = glm::radians(60.0f); + float m_aspect = 16.0f / 9.0f; + float m_near = 0.1f; + float m_far = 1000.0f; + + + public: + Camera() = default; + + // Bewegung relativ zur aktuellen Blickrichtung der Kamera (z.B. aus WASD-Input). + // direction.x = rechts/links, direction.y = hoch/runter, direction.z = vorwärts/rückwärts + void moveRelative(const glm::vec3& direction, float speed, float deltaTime); + + // Direkte Bewegung im World-Space (z.B. für Cutscenes, Freikamera per Maus-Drag) + void moveWorld(const glm::vec3& offset); + + void setPosition(const glm::vec3& position) { m_position = position; } + [[nodiscard]] const glm::vec3& getPosition() const { return m_position; } + + void setPitch(float pitch) { m_pitch = pitch; } + void setYaw(float yaw) { m_yaw = yaw; } + void setRoll(float roll) { m_roll = roll; } + [[nodiscard]] float getPitch() const { return m_pitch; } + [[nodiscard]] float getYaw() const { return m_yaw; } + [[nodiscard]] float getRoll() const { return m_roll; } + + [[nodiscard]] glm::vec3 getForward() const; + [[nodiscard]] glm::vec3 getRight() const; + [[nodiscard]] glm::vec3 getUp() const; + + [[nodiscard]] glm::mat4 getViewMatrix() const; + + void setFovY(float fovYRadians) { m_fovY = fovYRadians; } + void setAspectRatio(float aspect) { m_aspect = aspect; } + void setNearFar(float near, float far) { m_near = near; m_far = far; } + + [[nodiscard]] float getFovY() const { return m_fovY; } + [[nodiscard]] float getAspectRatio() const { return m_aspect; } + [[nodiscard]] float getNear() const { return m_near; } + [[nodiscard]] float getFar() const { return m_far; } + + [[nodiscard]] glm::mat4 getProjectionMatrix() const; + }; +} + + +#endif //COLORRACE_CAMERA_H diff --git a/engine/src/renderer/model/Entity.cpp b/engine/src/renderer/entities/Entity.cpp similarity index 100% rename from engine/src/renderer/model/Entity.cpp rename to engine/src/renderer/entities/Entity.cpp diff --git a/engine/src/renderer/model/Entity.h b/engine/src/renderer/entities/Entity.h similarity index 82% rename from engine/src/renderer/model/Entity.h rename to engine/src/renderer/entities/Entity.h index bef029e..a01c416 100644 --- a/engine/src/renderer/model/Entity.h +++ b/engine/src/renderer/entities/Entity.h @@ -6,7 +6,7 @@ #define COLORRACE_ENTITY_H #include -#include "RawModel.h" +#include "../model/RawModel.h" #include #include @@ -29,6 +29,10 @@ namespace engine { glm::mat4 getModelMatrix() const; RawModel& getModel() const { return *m_model; } + void increasePosition(glm::vec3 offset) { m_position += offset; } + void increaseRotation(glm::vec3 offset) { m_rotation += offset; } + void increaseScale(glm::vec3 offset) { m_scale += offset; } + private: std::shared_ptr m_model; glm::vec3 m_position; diff --git a/engine/src/renderer/shader/StaticShader.cpp b/engine/src/renderer/shader/StaticShader.cpp new file mode 100644 index 0000000..a2f75ab --- /dev/null +++ b/engine/src/renderer/shader/StaticShader.cpp @@ -0,0 +1,5 @@ +// +// Created by sebastian on 29.07.26. +// + +#include "StaticShader.h" diff --git a/engine/src/renderer/shader/StaticShader.h b/engine/src/renderer/shader/StaticShader.h new file mode 100644 index 0000000..3e2c3a2 --- /dev/null +++ b/engine/src/renderer/shader/StaticShader.h @@ -0,0 +1,44 @@ +// +// Created by sebastian on 29.07.26. +// + +#ifndef COLORRACE_STATICSHADER_H +#define COLORRACE_STATICSHADER_H +#include + +#include "utils/openglWrapper/shader/ShaderProgram.h" +#include "utils/openglWrapper/shader/UniformValue.h" + + +namespace engine { + class StaticShader : public ShaderProgram { + public: + StaticShader() : ShaderProgram("assets/shaders/basic.vert", "assets/shaders/basic.frag") { + storeAllUniformLocations({ + std::ref(transformationMatrix), + std::ref(projectionMatrix), + std::ref(viewMatrix) + }); + }; + + void loadTransformationMatrix(const glm::mat4& matrix) { + transformationMatrix.load(matrix); + } + + void loadProjectionMatrix(const glm::mat4& matrix) { + projectionMatrix.load(matrix); + } + + void loadViewMatrix(const glm::mat4& matrix) { + viewMatrix.load(matrix); + } + private: + engine::UniformValue transformationMatrix{"transformationMatrix"}; + engine::UniformValue projectionMatrix{"projectionMatrix"}; + engine::UniformValue viewMatrix{"viewMatrix"}; + + }; +} + + +#endif //COLORRACE_STATICSHADER_H diff --git a/engine/src/utils/openglWrapper/shader/ShaderProgram.cpp b/engine/src/utils/openglWrapper/shader/ShaderProgram.cpp index 6c3a126..73fd9d9 100644 --- a/engine/src/utils/openglWrapper/shader/ShaderProgram.cpp +++ b/engine/src/utils/openglWrapper/shader/ShaderProgram.cpp @@ -5,6 +5,7 @@ #include "ShaderProgram.h" #include #include +#include #include #include using namespace engine; @@ -58,6 +59,13 @@ ShaderProgram::ShaderProgram(const std::string &vertexShader, const std::string glDeleteShader(fragmentShaderId); } +void ShaderProgram::storeAllUniformLocations(const std::initializer_list> uniforms) const { + for (const auto& uniform : uniforms) { + uniform.get().storeUniformLocation(m_programId); + } + glValidateProgram(m_programId); +} + ShaderProgram::~ShaderProgram() { glDeleteProgram(m_programId); } diff --git a/engine/src/utils/openglWrapper/shader/ShaderProgram.h b/engine/src/utils/openglWrapper/shader/ShaderProgram.h index 891573d..f4229ba 100644 --- a/engine/src/utils/openglWrapper/shader/ShaderProgram.h +++ b/engine/src/utils/openglWrapper/shader/ShaderProgram.h @@ -6,11 +6,12 @@ #define COLORRACE_SHADERPROGRAM_H #include +#include "Uniform.h" + namespace engine { class ShaderProgram { public: - ShaderProgram(const std::string& vertexShader, const std::string& fragmentShader); - ~ShaderProgram(); + virtual ~ShaderProgram(); ShaderProgram(const ShaderProgram&) = delete; ShaderProgram& operator=(const ShaderProgram&) = delete; @@ -22,6 +23,10 @@ namespace engine { unsigned int m_programId; static std::string loadSource(const std::string& filePath); static unsigned int compileShader(unsigned int type, const std::string& source, const std::string& debugPath); + protected: + ShaderProgram(const std::string& vertexShader, const std::string& fragmentShader); + void storeAllUniformLocations(std::initializer_list> uniforms) const; + // Todo: void linkTextureSamplers(std::initializer_list> samplers); }; } diff --git a/engine/src/utils/openglWrapper/shader/Uniform.cpp b/engine/src/utils/openglWrapper/shader/Uniform.cpp new file mode 100644 index 0000000..bf53ac9 --- /dev/null +++ b/engine/src/utils/openglWrapper/shader/Uniform.cpp @@ -0,0 +1,20 @@ +// +// Created by sebastian on 29.07.26. +// + +#include "Uniform.h" + +#include +#include +void engine::Uniform::storeUniformLocation(unsigned int programID) { + m_location = glGetUniformLocation(programID, m_name.c_str()); + if (m_location == -1) { + throw std::runtime_error("Uniform " + m_name + " not found!"); + } + m_locationSet = true; +} + +int engine::Uniform::getLocation() const { + if (!m_locationSet) throw std::runtime_error("Uniform location not set!"); + return m_location; +} diff --git a/engine/src/utils/openglWrapper/shader/Uniform.h b/engine/src/utils/openglWrapper/shader/Uniform.h new file mode 100644 index 0000000..5b370d5 --- /dev/null +++ b/engine/src/utils/openglWrapper/shader/Uniform.h @@ -0,0 +1,30 @@ +// +// Created by sebastian on 29.07.26. +// + +#ifndef COLORRACE_UNIFORM_H +#define COLORRACE_UNIFORM_H +#include + + +namespace engine { + class Uniform { + public: + explicit Uniform(std::string name) : m_name(std::move(name)) {} + virtual ~Uniform() = default; + + Uniform(const Uniform&) = delete; + Uniform& operator=(const Uniform&) = delete; + + void storeUniformLocation(unsigned int programID); + protected: + int getLocation() const; + private: + std::string m_name; + int m_location = -1; + bool m_locationSet = false; + }; +} + + +#endif //COLORRACE_UNIFORM_H diff --git a/engine/src/utils/openglWrapper/shader/UniformValue.cpp b/engine/src/utils/openglWrapper/shader/UniformValue.cpp new file mode 100644 index 0000000..ca20795 --- /dev/null +++ b/engine/src/utils/openglWrapper/shader/UniformValue.cpp @@ -0,0 +1,5 @@ +// +// Created by sebastian on 29.07.26. +// + +#include "UniformValue.h" diff --git a/engine/src/utils/openglWrapper/shader/UniformValue.h b/engine/src/utils/openglWrapper/shader/UniformValue.h new file mode 100644 index 0000000..55226d3 --- /dev/null +++ b/engine/src/utils/openglWrapper/shader/UniformValue.h @@ -0,0 +1,42 @@ +// +// Created by sebastian on 29.07.26. +// + +#ifndef COLORRACE_UNIFORMVALUE_H +#define COLORRACE_UNIFORMVALUE_H +#include "glad/glad.h" +#include + +#include "Uniform.h" + +namespace engine::detail { + inline void glUniformLoad(int loc, float v) { glUniform1f(loc, v); } + inline void glUniformLoad(int loc, int v) { glUniform1i(loc, v); } + inline void glUniformLoad(int loc, bool v) { glUniform1i(loc, v ? 1 : 0); } + inline void glUniformLoad(int loc, const glm::vec2& v) { glUniform2f(loc, v.x, v.y); } + inline void glUniformLoad(int loc, const glm::vec3& v) { glUniform3f(loc, v.x, v.y, v.z); } + inline void glUniformLoad(int loc, const glm::vec4& v) { glUniform4f(loc, v.x, v.y, v.z, v.w); } + inline void glUniformLoad(int loc, const glm::mat4& m) { glUniformMatrix4fv(loc, 1, GL_FALSE, &m[0][0]); } +} + +namespace engine { + template + class UniformValue : public Uniform { + public: + explicit UniformValue(std::string name) : Uniform(std::move(name)) {} + + void load(const T& value) { + if (m_used && m_currentValue == value) { + return; + } + detail::glUniformLoad(getLocation(), value); + m_currentValue = value; + m_used = true; + } + private: + T m_currentValue{}; + bool m_used = false; + }; +} + +#endif //COLORRACE_UNIFORMVALUE_H diff --git a/game/src/ColorRaceApp.cpp b/game/src/ColorRaceApp.cpp index 726552c..c3bcdcb 100644 --- a/game/src/ColorRaceApp.cpp +++ b/game/src/ColorRaceApp.cpp @@ -10,13 +10,16 @@ void ColorRaceApp::onUpdate(float deltaTime) { - + m_cubeEntity->increaseRotation(glm::vec3(0, 1, 0)); } void ColorRaceApp::onRender() { m_renderState.apply(); m_shader->start(); + m_shader->loadTransformationMatrix(m_cubeEntity->getModelMatrix()); + m_shader->loadViewMatrix(m_camera->getViewMatrix()); + m_shader->loadProjectionMatrix(m_camera->getProjectionMatrix()); m_cubeEntity->getModel().bind(); m_cubeEntity->getModel().draw(); m_cubeEntity->getModel().unbind(); diff --git a/game/src/ColorRaceApp.h b/game/src/ColorRaceApp.h index 3ffd42e..53f7a04 100644 --- a/game/src/ColorRaceApp.h +++ b/game/src/ColorRaceApp.h @@ -5,8 +5,10 @@ #ifndef COLORRACE_COLORRACEAPP_H #define COLORRACE_COLORRACEAPP_H #include "core/Application.h" -#include "renderer/model/Entity.h" +#include "../../engine/src/renderer/entities/Entity.h" +#include "renderer/entities/Camera.h" #include "renderer/primitives/CubeFactory.h" +#include "renderer/shader/StaticShader.h" #include "utils/openglWrapper/GLRenderState.h" #include "utils/openglWrapper/openglObjects/Vao.h" #include "utils/openglWrapper/shader/ShaderProgram.h" @@ -29,17 +31,20 @@ public: m_renderState.depthTesting = false; m_renderState.backfaceCulling = false; - m_shader = std::make_unique("assets/shaders/basic.vert", "assets/shaders/basic.frag"); + m_shader = std::make_unique(); + m_camera = std::make_unique(); + m_camera->setPosition({0.0f, 0.0f, 5.0f}); + m_camera->setYaw(0.0f); + m_camera->setPitch(0.0f); auto cubeModel = engine::CubeFactory::createCube(); m_cubeEntity = std::make_unique(cubeModel); } private: engine::GLRenderState m_renderState; - std::unique_ptr m_shader; + std::unique_ptr m_shader; std::unique_ptr m_cubeEntity; - - void initTriangle(); + std::unique_ptr m_camera; protected: void onUpdate(float deltaTime) override; void onRender() override;