From 8ae128e0ee960427878a0fcf1f3acd57dd05ff24 Mon Sep 17 00:00:00 2001 From: sebastian Date: Wed, 29 Jul 2026 13:37:59 +0200 Subject: [PATCH] ADD: Basic Shader and Attribute Infrastructure for OpenGL --- CMakeLists.txt | 4 ++ assets/shaders/basic.frag | 7 ++ assets/shaders/basic.vert.glsl | 6 ++ .../openglWrapper/openglObjects/Attribute.cpp | 55 ++++++++++++++ .../openglWrapper/openglObjects/Attribute.h | 60 ++++++++++++++++ .../openglWrapper/shader/ShaderProgram.cpp | 72 +++++++++++++++++++ .../openglWrapper/shader/ShaderProgram.h | 30 ++++++++ 7 files changed, 234 insertions(+) create mode 100644 assets/shaders/basic.frag create mode 100644 assets/shaders/basic.vert.glsl create mode 100644 engine/src/utils/openglWrapper/openglObjects/Attribute.cpp create mode 100644 engine/src/utils/openglWrapper/openglObjects/Attribute.h create mode 100644 engine/src/utils/openglWrapper/shader/ShaderProgram.cpp create mode 100644 engine/src/utils/openglWrapper/shader/ShaderProgram.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ec999f8..ff71ed8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,8 @@ add_library(Engine STATIC engine/src/utils/openglWrapper/GLStateCache.h engine/src/utils/openglWrapper/GLRenderState.cpp engine/src/utils/openglWrapper/GLRenderState.h + engine/src/utils/openglWrapper/openglObjects/Attribute.cpp + engine/src/utils/openglWrapper/openglObjects/Attribute.h ) target_include_directories(Engine PUBLIC engine/src) target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui) @@ -96,6 +98,8 @@ add_executable(ColorRace game/src/main.cpp game/src/ColorRaceApp.cpp game/src/ColorRaceApp.h + engine/src/utils/openglWrapper/shader/ShaderProgram.cpp + engine/src/utils/openglWrapper/shader/ShaderProgram.h ) target_link_libraries(ColorRace PRIVATE diff --git a/assets/shaders/basic.frag b/assets/shaders/basic.frag new file mode 100644 index 0000000..2050c7a --- /dev/null +++ b/assets/shaders/basic.frag @@ -0,0 +1,7 @@ +#version 460 core + +out vec4 fragColor; + +void main() { + fragColor = vec4(1.0, 0.5, 0.2, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/basic.vert.glsl b/assets/shaders/basic.vert.glsl new file mode 100644 index 0000000..1427b35 --- /dev/null +++ b/assets/shaders/basic.vert.glsl @@ -0,0 +1,6 @@ +#version 460 core +layout(location = 0) in vec3 position; + +void main() { + gl_Position = vec4(position, 1.0); +} \ No newline at end of file diff --git a/engine/src/utils/openglWrapper/openglObjects/Attribute.cpp b/engine/src/utils/openglWrapper/openglObjects/Attribute.cpp new file mode 100644 index 0000000..e5033b8 --- /dev/null +++ b/engine/src/utils/openglWrapper/openglObjects/Attribute.cpp @@ -0,0 +1,55 @@ +// +// Created by sebastian on 29.07.26. +// + +#include "Attribute.h" +#include + +using namespace engine; + +Attribute::Attribute(const unsigned int attributeNumber, const unsigned int dataType, const int componentCount, const bool normalized) + : m_attributeNumber(attributeNumber), m_dataType(dataType), + m_componentCount(componentCount), m_normalized(normalized), + m_bytesPerVertex(calcBytesPerVertex()) {} + +Attribute::Attribute(const unsigned int attributeNumber, const unsigned int dataType, const int componentCount) + : m_attributeNumber(attributeNumber), m_dataType(dataType), + m_componentCount(componentCount), m_normalized(false), + m_bytesPerVertex(calcBytesPerVertex()) {} + +void Attribute::enable(bool enable) const { + if (enable) { + glEnableVertexAttribArray(m_attributeNumber); + } else { + glDisableVertexAttribArray(m_attributeNumber); + } +} + +void Attribute::link(const int offset, const int stride) { + glVertexAttribPointer(m_attributeNumber, m_componentCount, m_dataType, m_normalized, stride, reinterpret_cast(offset)); +} + +int Attribute::calcBytesPerVertex() const { + switch (m_dataType) { + case GL_FLOAT: + case GL_UNSIGNED_INT: + case GL_INT: + return 4 * m_componentCount; + case GL_SHORT: + case GL_UNSIGNED_SHORT: + return 2 * m_componentCount; + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return 1 * m_componentCount; + case GL_UNSIGNED_INT_2_10_10_10_REV: + return 4; // gepackt: 4 Bytes gesamt, unabhängig von componentCount + default: + std::cerr << "Unsupported data type for attribute\n"; + return 0; + } +} + +void IntAttribute::link(int offset, int stride) { + glVertexAttribIPointer(m_attributeNumber, m_componentCount, GL_INT, stride, + reinterpret_cast(offset)); +} diff --git a/engine/src/utils/openglWrapper/openglObjects/Attribute.h b/engine/src/utils/openglWrapper/openglObjects/Attribute.h new file mode 100644 index 0000000..7cad1ad --- /dev/null +++ b/engine/src/utils/openglWrapper/openglObjects/Attribute.h @@ -0,0 +1,60 @@ +// +// Created by sebastian on 29.07.26. +// + +#ifndef COLORRACE_ATTRIBUTE_H +#define COLORRACE_ATTRIBUTE_H +#pragma once +#include + +namespace engine { + class Attribute { + public: + Attribute(unsigned int attributeNumber, unsigned int dataType, int componentCount); + Attribute(unsigned int attributeNumber, unsigned int dataType, int componentCount, bool normalized); + virtual ~Attribute() = default; + + void enable(bool enable) const; + virtual void link(int offset, int stride); + + protected: + unsigned int m_attributeNumber; + unsigned int m_dataType; + int m_componentCount; + bool m_normalized; + int m_bytesPerVertex; + + private: + int calcBytesPerVertex() const; + }; + + class Vec2Attribute : public Attribute { + public: + explicit Vec2Attribute(unsigned int attributeNumber) : Attribute(attributeNumber, GL_FLOAT, 2) {} + }; + + class Vec3Attribute : public Attribute { + public: + explicit Vec3Attribute(unsigned int attributeNumber) : Attribute(attributeNumber, GL_FLOAT, 3) {} + }; + + class ColorAttribute : public Attribute { + public: + explicit ColorAttribute(unsigned int attributeNumber) : Attribute(attributeNumber, GL_UNSIGNED_BYTE, 4, true) {} + }; + + class NormalAttribute : public Attribute { + public: + explicit NormalAttribute(unsigned int attributeNumber) : Attribute(attributeNumber, GL_UNSIGNED_INT_2_10_10_10_REV, 3) {} + }; + + class IntAttribute : public Attribute { + public: + explicit IntAttribute(unsigned int attributeNumber) : Attribute(attributeNumber, GL_INT, 1) {} + + void link(int offset, int stride) override; + }; + +} + +#endif //COLORRACE_ATTRIBUTE_H diff --git a/engine/src/utils/openglWrapper/shader/ShaderProgram.cpp b/engine/src/utils/openglWrapper/shader/ShaderProgram.cpp new file mode 100644 index 0000000..6c3a126 --- /dev/null +++ b/engine/src/utils/openglWrapper/shader/ShaderProgram.cpp @@ -0,0 +1,72 @@ +// +// Created by sebastian on 29.07.26. +// + +#include "ShaderProgram.h" +#include +#include +#include +#include +using namespace engine; + +std::string ShaderProgram::loadSource(const std::string &filePath) { + std::ifstream file(filePath); + if (!file.is_open()) { + throw std::runtime_error("Could not open shader file: " + filePath); + } + std::stringstream buffer; + buffer << file.rdbuf(); + return buffer.str(); +} + +unsigned int ShaderProgram::compileShader(unsigned int type, const std::string &source, const std::string &debugPath) { + unsigned int id = glCreateShader(type); + const char* src = source.c_str(); + glShaderSource(id, 1, &src, nullptr); + glCompileShader(id); + + int success; + glGetShaderiv(id, GL_COMPILE_STATUS, &success); + if (!success) { + char log[512]; + glGetShaderInfoLog(id, 512, nullptr, log); + throw std::runtime_error("Shader compile error (" + debugPath + "): " + log); + } + return id; +} + +ShaderProgram::ShaderProgram(const std::string &vertexShader, const std::string &fragmentShader) { + unsigned int vertexShaderId = compileShader(GL_VERTEX_SHADER, loadSource(vertexShader), vertexShader); + unsigned int fragmentShaderId = compileShader(GL_FRAGMENT_SHADER, loadSource(fragmentShader), fragmentShader); + + m_programId = glCreateProgram(); + glAttachShader(m_programId, vertexShaderId); + glAttachShader(m_programId, fragmentShaderId); + glLinkProgram(m_programId); + + int success; + glGetProgramiv(m_programId, GL_LINK_STATUS, &success); + if (!success) { + char log[512]; + glGetProgramInfoLog(m_programId, 512, nullptr, log); + throw std::runtime_error(std::string("Shader link error: ") + log); + } + + glDetachShader(m_programId, vertexShaderId); + glDetachShader(m_programId, fragmentShaderId); + glDeleteShader(vertexShaderId); + glDeleteShader(fragmentShaderId); +} + +ShaderProgram::~ShaderProgram() { + glDeleteProgram(m_programId); +} + +void ShaderProgram::start() const { + glUseProgram(m_programId); +} + +void ShaderProgram::stop() const { + glUseProgram(0); +} + diff --git a/engine/src/utils/openglWrapper/shader/ShaderProgram.h b/engine/src/utils/openglWrapper/shader/ShaderProgram.h new file mode 100644 index 0000000..891573d --- /dev/null +++ b/engine/src/utils/openglWrapper/shader/ShaderProgram.h @@ -0,0 +1,30 @@ +// +// Created by sebastian on 29.07.26. +// + +#ifndef COLORRACE_SHADERPROGRAM_H +#define COLORRACE_SHADERPROGRAM_H +#include + +namespace engine { + class ShaderProgram { + public: + ShaderProgram(const std::string& vertexShader, const std::string& fragmentShader); + ~ShaderProgram(); + + ShaderProgram(const ShaderProgram&) = delete; + ShaderProgram& operator=(const ShaderProgram&) = delete; + + void start() const; + void stop() const; + + private: + 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); + }; +} + + + +#endif //COLORRACE_SHADERPROGRAM_H