From 0418c61db6bb64109981298065312796558bf9bc Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 17 Mar 2026 02:27:13 +0800 Subject: [PATCH] Enhance OpenGLShader with comprehensive shader support --- .../XCEngine/RHI/OpenGL/OpenGLShader.h | 28 +++ engine/src/RHI/OpenGL/OpenGLShader.cpp | 185 +++++++++++++++++- 2 files changed, 209 insertions(+), 4 deletions(-) diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLShader.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLShader.h index ccef092b..64be3edc 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLShader.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLShader.h @@ -2,27 +2,55 @@ #include #include +#include namespace XCEngine { namespace RHI { +enum class ShaderType { + Vertex, + Fragment, + Geometry, + Compute, + TessControl, + TessEvaluation +}; + class OpenGLShader { public: OpenGLShader(); ~OpenGLShader(); bool CompileFromFile(const char* vertexPath, const char* fragmentPath); + bool CompileFromFile(const char* vertexPath, const char* fragmentPath, const char* geometryPath); bool Compile(const char* vertexSource, const char* fragmentSource); + bool Compile(const char* vertexSource, const char* fragmentSource, const char* geometrySource); + bool CompileCompute(const char* computeSource); + bool Compile(const char* source, ShaderType type); void Shutdown(); void Use() const; + void Bind() const { Use(); } + void Unbind() const; + void SetInt(const std::string& name, int value) const; + void SetIntArray(const std::string& name, const int* values, unsigned int count) const; void SetFloat(const std::string& name, float value) const; + void SetFloatArray(const std::string& name, const float* values, unsigned int count) const; + void SetVec2(const std::string& name, float x, float y) const; + void SetVec2(const std::string& name, const float* values) 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 SetVec4(const std::string& name, float x, float y, float z, float w) const; + void SetVec4(const std::string& name, const float* values) const; + void SetMat2(const std::string& name, const float* value) const; + void SetMat3(const std::string& name, const float* value) const; void SetMat4(const std::string& name, const float* value) const; + void SetMat4Array(const std::string& name, const float* values, unsigned int count) const; + int GetUniformLocation(const std::string& name) const; unsigned int GetID() const { return m_program; } + bool IsValid() const { return m_program != 0; } private: unsigned int m_program; diff --git a/engine/src/RHI/OpenGL/OpenGLShader.cpp b/engine/src/RHI/OpenGL/OpenGLShader.cpp index 0da4d1d2..5c1f7129 100644 --- a/engine/src/RHI/OpenGL/OpenGLShader.cpp +++ b/engine/src/RHI/OpenGL/OpenGLShader.cpp @@ -37,18 +37,41 @@ bool OpenGLShader::CompileFromFile(const char* vertexPath, const char* fragmentP return Compile(vertexCode.c_str(), fragmentCode.c_str()); } +bool OpenGLShader::CompileFromFile(const char* vertexPath, const char* fragmentPath, const char* geometryPath) { + std::string vertexCode, fragmentCode, geometryCode; + std::ifstream vShaderFile(vertexPath), fShaderFile(fragmentPath), gShaderFile(geometryPath); + + if (!vShaderFile.is_open() || !fShaderFile.is_open() || !gShaderFile.is_open()) { + return false; + } + + std::stringstream vShaderStream, fShaderStream, gShaderStream; + vShaderStream << vShaderFile.rdbuf(); + fShaderStream << fShaderFile.rdbuf(); + gShaderStream << gShaderFile.rdbuf(); + vShaderFile.close(); + fShaderFile.close(); + gShaderFile.close(); + + vertexCode = vShaderStream.str(); + fragmentCode = fShaderStream.str(); + geometryCode = gShaderStream.str(); + + return Compile(vertexCode.c_str(), fragmentCode.c_str(), geometryCode.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); + glShaderSource(vertex, 1, &vertexSource, nullptr); glCompileShader(vertex); if (!CheckCompileErrors(vertex, "VERTEX")) { return false; } fragment = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragment, 1, &fragmentSource, NULL); + glShaderSource(fragment, 1, &fragmentSource, nullptr); glCompileShader(fragment); if (!CheckCompileErrors(fragment, "FRAGMENT")) { return false; @@ -69,6 +92,116 @@ bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource) return true; } +bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource, const char* geometrySource) { + unsigned int vertex, fragment, geometry; + + vertex = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex, 1, &vertexSource, nullptr); + glCompileShader(vertex); + if (!CheckCompileErrors(vertex, "VERTEX")) { + return false; + } + + fragment = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment, 1, &fragmentSource, nullptr); + glCompileShader(fragment); + if (!CheckCompileErrors(fragment, "FRAGMENT")) { + return false; + } + + geometry = glCreateShader(GL_GEOMETRY_SHADER); + glShaderSource(geometry, 1, &geometrySource, nullptr); + glCompileShader(geometry); + if (!CheckCompileErrors(geometry, "GEOMETRY")) { + return false; + } + + m_program = glCreateProgram(); + glAttachShader(m_program, vertex); + glAttachShader(m_program, fragment); + glAttachShader(m_program, geometry); + glLinkProgram(m_program); + + if (!CheckLinkErrors(m_program)) { + return false; + } + + glDeleteShader(vertex); + glDeleteShader(fragment); + glDeleteShader(geometry); + + return true; +} + +bool OpenGLShader::CompileCompute(const char* computeSource) { + unsigned int compute = glCreateShader(GL_COMPUTE_SHADER); + glShaderSource(compute, 1, &computeSource, nullptr); + glCompileShader(compute); + if (!CheckCompileErrors(compute, "COMPUTE")) { + return false; + } + + m_program = glCreateProgram(); + glAttachShader(m_program, compute); + glLinkProgram(m_program); + + if (!CheckLinkErrors(m_program)) { + return false; + } + + glDeleteShader(compute); + + return true; +} + +bool OpenGLShader::Compile(const char* source, ShaderType type) { + unsigned int shader = 0; + + switch (type) { + case ShaderType::Vertex: + shader = glCreateShader(GL_VERTEX_SHADER); + break; + case ShaderType::Fragment: + shader = glCreateShader(GL_FRAGMENT_SHADER); + break; + case ShaderType::Geometry: + shader = glCreateShader(GL_GEOMETRY_SHADER); + break; + case ShaderType::Compute: + shader = glCreateShader(GL_COMPUTE_SHADER); + break; + case ShaderType::TessControl: + shader = glCreateShader(GL_TESS_CONTROL_SHADER); + break; + case ShaderType::TessEvaluation: + shader = glCreateShader(GL_TESS_EVALUATION_SHADER); + break; + default: + return false; + } + + glShaderSource(shader, 1, &source, nullptr); + glCompileShader(shader); + + const char* typeName[] = { "VERTEX", "FRAGMENT", "GEOMETRY", "COMPUTE", "TESS_CONTROL", "TESS_EVALUATION" }; + if (!CheckCompileErrors(shader, typeName[(int)type])) { + return false; + } + + if (m_program == 0) { + m_program = glCreateProgram(); + } + glAttachShader(m_program, shader); + glLinkProgram(m_program); + + if (!CheckLinkErrors(m_program)) { + return false; + } + + glDeleteShader(shader); + return true; +} + void OpenGLShader::Shutdown() { if (m_program) { glDeleteProgram(m_program); @@ -80,14 +213,34 @@ void OpenGLShader::Use() const { glUseProgram(m_program); } +void OpenGLShader::Unbind() const { + glUseProgram(0); +} + void OpenGLShader::SetInt(const std::string& name, int value) const { glUniform1i(glGetUniformLocation(m_program, name.c_str()), value); } +void OpenGLShader::SetIntArray(const std::string& name, const int* values, unsigned int count) const { + glUniform1iv(glGetUniformLocation(m_program, name.c_str()), count, values); +} + void OpenGLShader::SetFloat(const std::string& name, float value) const { glUniform1f(glGetUniformLocation(m_program, name.c_str()), value); } +void OpenGLShader::SetFloatArray(const std::string& name, const float* values, unsigned int count) const { + glUniform1fv(glGetUniformLocation(m_program, name.c_str()), count, values); +} + +void OpenGLShader::SetVec2(const std::string& name, float x, float y) const { + glUniform2f(glGetUniformLocation(m_program, name.c_str()), x, y); +} + +void OpenGLShader::SetVec2(const std::string& name, const float* values) const { + glUniform2fv(glGetUniformLocation(m_program, name.c_str()), 1, values); +} + void OpenGLShader::SetVec3(const std::string& name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(m_program, name.c_str()), x, y, z); } @@ -96,17 +249,41 @@ void OpenGLShader::SetVec3(const std::string& name, const float* values) const { glUniform3fv(glGetUniformLocation(m_program, name.c_str()), 1, values); } +void OpenGLShader::SetVec4(const std::string& name, float x, float y, float z, float w) const { + glUniform4f(glGetUniformLocation(m_program, name.c_str()), x, y, z, w); +} + +void OpenGLShader::SetVec4(const std::string& name, const float* values) const { + glUniform4fv(glGetUniformLocation(m_program, name.c_str()), 1, values); +} + +void OpenGLShader::SetMat2(const std::string& name, const float* value) const { + glUniformMatrix2fv(glGetUniformLocation(m_program, name.c_str()), 1, GL_FALSE, value); +} + +void OpenGLShader::SetMat3(const std::string& name, const float* value) const { + glUniformMatrix3fv(glGetUniformLocation(m_program, name.c_str()), 1, GL_FALSE, value); +} + void OpenGLShader::SetMat4(const std::string& name, const float* value) const { glUniformMatrix4fv(glGetUniformLocation(m_program, name.c_str()), 1, GL_FALSE, value); } +void OpenGLShader::SetMat4Array(const std::string& name, const float* values, unsigned int count) const { + glUniformMatrix4fv(glGetUniformLocation(m_program, name.c_str()), count, GL_FALSE, values); +} + +int OpenGLShader::GetUniformLocation(const std::string& name) const { + return glGetUniformLocation(m_program, name.c_str()); +} + 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); + glGetShaderInfoLog(shader, 1024, nullptr, infoLog); std::cout << "ERROR::SHADER_COMPILATION_ERROR: " << type << "\n" << infoLog << std::endl; return false; } @@ -119,7 +296,7 @@ bool OpenGLShader::CheckLinkErrors(unsigned int program) { glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { - glGetProgramInfoLog(program, 1024, NULL, infoLog); + glGetProgramInfoLog(program, 1024, nullptr, infoLog); std::cout << "ERROR::PROGRAM_LINKING_ERROR\n" << infoLog << std::endl; return false; }