ADD: Projection, Transformation and ViewMatrix

This commit is contained in:
sebastian 2026-07-29 16:33:14 +02:00
parent 30c9683780
commit 474874d21b
16 changed files with 313 additions and 12 deletions

View File

@ -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
)

View File

@ -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;
}

View File

@ -0,0 +1,54 @@
//
// Created by sebastian on 29.07.26.
//
#include "Camera.h"
#include <glm/gtc/matrix_transform.hpp>
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);
}

View File

@ -0,0 +1,63 @@
//
// Created by sebastian on 29.07.26.
//
#ifndef COLORRACE_CAMERA_H
#define COLORRACE_CAMERA_H
#pragma once
#include <glm/glm.hpp>
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

View File

@ -6,7 +6,7 @@
#define COLORRACE_ENTITY_H
#include <memory>
#include "RawModel.h"
#include "../model/RawModel.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
@ -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<engine::RawModel> m_model;
glm::vec3 m_position;

View File

@ -0,0 +1,5 @@
//
// Created by sebastian on 29.07.26.
//
#include "StaticShader.h"

View File

@ -0,0 +1,44 @@
//
// Created by sebastian on 29.07.26.
//
#ifndef COLORRACE_STATICSHADER_H
#define COLORRACE_STATICSHADER_H
#include <functional>
#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<glm::mat4> transformationMatrix{"transformationMatrix"};
engine::UniformValue<glm::mat4> projectionMatrix{"projectionMatrix"};
engine::UniformValue<glm::mat4> viewMatrix{"viewMatrix"};
};
}
#endif //COLORRACE_STATICSHADER_H

View File

@ -5,6 +5,7 @@
#include "ShaderProgram.h"
#include <glad/glad.h>
#include <fstream>
#include <functional>
#include <sstream>
#include <stdexcept>
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<std::reference_wrapper<Uniform>> uniforms) const {
for (const auto& uniform : uniforms) {
uniform.get().storeUniformLocation(m_programId);
}
glValidateProgram(m_programId);
}
ShaderProgram::~ShaderProgram() {
glDeleteProgram(m_programId);
}

View File

@ -6,11 +6,12 @@
#define COLORRACE_SHADERPROGRAM_H
#include <string>
#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<std::reference_wrapper<Uniform>> uniforms) const;
// Todo: void linkTextureSamplers(std::initializer_list<std::reference_wrapper<UniformSampler>> samplers);
};
}

View File

@ -0,0 +1,20 @@
//
// Created by sebastian on 29.07.26.
//
#include "Uniform.h"
#include <stdexcept>
#include <glad/glad.h>
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;
}

View File

@ -0,0 +1,30 @@
//
// Created by sebastian on 29.07.26.
//
#ifndef COLORRACE_UNIFORM_H
#define COLORRACE_UNIFORM_H
#include <string>
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

View File

@ -0,0 +1,5 @@
//
// Created by sebastian on 29.07.26.
//
#include "UniformValue.h"

View File

@ -0,0 +1,42 @@
//
// Created by sebastian on 29.07.26.
//
#ifndef COLORRACE_UNIFORMVALUE_H
#define COLORRACE_UNIFORMVALUE_H
#include "glad/glad.h"
#include <glm/glm.hpp>
#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<typename T>
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

View File

@ -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();

View File

@ -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<engine::ShaderProgram>("assets/shaders/basic.vert", "assets/shaders/basic.frag");
m_shader = std::make_unique<engine::StaticShader>();
m_camera = std::make_unique<engine::Camera>();
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<engine::Entity>(cubeModel);
}
private:
engine::GLRenderState m_renderState;
std::unique_ptr<engine::ShaderProgram> m_shader;
std::unique_ptr<engine::StaticShader> m_shader;
std::unique_ptr<engine::Entity> m_cubeEntity;
void initTriangle();
std::unique_ptr<engine::Camera> m_camera;
protected:
void onUpdate(float deltaTime) override;
void onRender() override;