From 170df5506b5a32bfbbfee729111ec80a58c99196 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Mon, 16 Mar 2026 16:09:09 +0800 Subject: [PATCH] Add OpenGLShader class - Created OpenGLShader class for shader compilation - Supports compiling from file or source code - Provides uniform setting methods (SetInt, SetFloat, SetVec3, SetMat4) - Integrated with GLAD for OpenGL function loading --- tests/OpenGL/CMakeLists.txt | 1 + tests/OpenGL/OpenGLShader.cpp | 130 ++++++++++++++++++++++++++++++++++ tests/OpenGL/OpenGLShader.h | 34 +++++++++ 3 files changed, 165 insertions(+) create mode 100644 tests/OpenGL/OpenGLShader.cpp create mode 100644 tests/OpenGL/OpenGLShader.h diff --git a/tests/OpenGL/CMakeLists.txt b/tests/OpenGL/CMakeLists.txt index aa34c046..7f8624ba 100644 --- a/tests/OpenGL/CMakeLists.txt +++ b/tests/OpenGL/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable( XCRender main.cpp OpenGLDevice.cpp + OpenGLShader.cpp ./package/src/glad.c ) diff --git a/tests/OpenGL/OpenGLShader.cpp b/tests/OpenGL/OpenGLShader.cpp new file mode 100644 index 00000000..92301158 --- /dev/null +++ b/tests/OpenGL/OpenGLShader.cpp @@ -0,0 +1,130 @@ +#define GLFW_INCLUDE_NONE +#include "OpenGLShader.h" +#include +#include +#include +#include +#include + +namespace XCEngine { +namespace RHI { + +OpenGLShader::OpenGLShader() + : m_program(0) { +} + +OpenGLShader::~OpenGLShader() { + Shutdown(); +} + +bool OpenGLShader::CompileFromFile(const char* vertexPath, const char* fragmentPath) { + std::string vertexCode, fragmentCode; + std::ifstream vShaderFile(vertexPath), fShaderFile(fragmentPath); + + if (!vShaderFile.is_open() || !fShaderFile.is_open()) { + return false; + } + + std::stringstream vShaderStream, fShaderStream; + vShaderStream << vShaderFile.rdbuf(); + fShaderStream << fShaderFile.rdbuf(); + vShaderFile.close(); + fShaderFile.close(); + + vertexCode = vShaderStream.str(); + fragmentCode = fShaderStream.str(); + + return Compile(vertexCode.c_str(), fragmentCode.c_str()); +} + +bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource) { + unsigned int vertex, fragment; + + vertex = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex, 1, &vertexSource, NULL); + glCompileShader(vertex); + if (!CheckCompileErrors(vertex, "VERTEX")) { + return false; + } + + fragment = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment, 1, &fragmentSource, NULL); + glCompileShader(fragment); + if (!CheckCompileErrors(fragment, "FRAGMENT")) { + return false; + } + + m_program = glCreateProgram(); + glAttachShader(m_program, vertex); + glAttachShader(m_program, fragment); + glLinkProgram(m_program); + + if (!CheckLinkErrors(m_program)) { + return false; + } + + glDeleteShader(vertex); + glDeleteShader(fragment); + + return true; +} + +void OpenGLShader::Shutdown() { + if (m_program) { + glDeleteProgram(m_program); + m_program = 0; + } +} + +void OpenGLShader::Use() const { + glUseProgram(m_program); +} + +void OpenGLShader::SetInt(const std::string& name, int value) const { + glUniform1i(glGetUniformLocation(m_program, name.c_str()), value); +} + +void OpenGLShader::SetFloat(const std::string& name, float value) const { + glUniform1f(glGetUniformLocation(m_program, name.c_str()), value); +} + +void OpenGLShader::SetVec3(const std::string& name, float x, float y, float z) const { + glUniform3f(glGetUniformLocation(m_program, name.c_str()), x, y, z); +} + +void OpenGLShader::SetVec3(const std::string& name, const float* values) const { + glUniform3fv(glGetUniformLocation(m_program, name.c_str()), 1, values); +} + +void OpenGLShader::SetMat4(const std::string& name, const float* value) const { + glUniformMatrix4fv(glGetUniformLocation(m_program, name.c_str()), 1, GL_FALSE, value); +} + +bool OpenGLShader::CheckCompileErrors(unsigned int shader, const char* type) { + int success; + char infoLog[1024]; + + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(shader, 1024, NULL, infoLog); + std::cout << "ERROR::SHADER_COMPILATION_ERROR: " << type << "\n" << infoLog << std::endl; + return false; + } + return true; +} + +bool OpenGLShader::CheckLinkErrors(unsigned int program) { + int success; + char infoLog[1024]; + + glGetProgramiv(program, GL_LINK_STATUS, &success); + if (!success) { + glGetProgramInfoLog(program, 1024, NULL, infoLog); + std::cout << "ERROR::PROGRAM_LINKING_ERROR\n" << infoLog << std::endl; + return false; + } + return true; +} + +} // namespace RHI +} // namespace XCEngine diff --git a/tests/OpenGL/OpenGLShader.h b/tests/OpenGL/OpenGLShader.h new file mode 100644 index 00000000..ccef092b --- /dev/null +++ b/tests/OpenGL/OpenGLShader.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include + +namespace XCEngine { +namespace RHI { + +class OpenGLShader { +public: + OpenGLShader(); + ~OpenGLShader(); + + bool CompileFromFile(const char* vertexPath, const char* fragmentPath); + bool Compile(const char* vertexSource, const char* fragmentSource); + void Shutdown(); + + void Use() const; + void SetInt(const std::string& name, int value) const; + void SetFloat(const std::string& name, float value) const; + void SetVec3(const std::string& name, float x, float y, float z) const; + void SetVec3(const std::string& name, const float* values) const; + void SetMat4(const std::string& name, const float* value) const; + + unsigned int GetID() const { return m_program; } + +private: + unsigned int m_program; + bool CheckCompileErrors(unsigned int shader, const char* type); + bool CheckLinkErrors(unsigned int program); +}; + +} // namespace RHI +} // namespace XCEngine