Files
XCEngine/engine/src/RHI/OpenGL/OpenGLShader.cpp
ssdfasd 3196261e9b fix(RHI): 添加 OpenGL 源文件到 CMakeLists 并修复编译错误
- 添加 OpenGL RHI 所有源文件到 engine/CMakeLists.txt
- 修复 OpenGLPipelineState 结构体重定义问题
- 修复 BufferDesc/TextureDesc/ShaderCompileDesc API 不匹配
- 添加 OpenGLShader 缺少的基类纯虚函数实现
- 修复 HashMap 迭代器支持和 ResourceManager API 调用
2026-03-18 03:37:34 +08:00

313 lines
9.1 KiB
C++

#define GLFW_INCLUDE_NONE
#include "XCEngine/RHI/OpenGL/OpenGLShader.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <fstream>
#include <sstream>
#include <iostream>
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::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, 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;
}
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;
}
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;
}
bool OpenGLShader::CompileFromFile(const wchar_t* filePath, const char* entryPoint, const char* target) {
std::wstring ws(filePath);
std::string path(ws.begin(), ws.end());
return CompileFromFile(path.c_str(), nullptr);
}
bool OpenGLShader::Compile(const void* sourceData, size_t sourceSize, const char* entryPoint, const char* target) {
if (!sourceData || sourceSize == 0) {
return false;
}
return Compile(static_cast<const char*>(sourceData), ShaderType::Fragment);
}
void OpenGLShader::Shutdown() {
if (m_program) {
glDeleteProgram(m_program);
m_program = 0;
}
}
void OpenGLShader::Use() const {
glUseProgram(m_program);
}
void OpenGLShader::Unbind() {
glUseProgram(0);
}
void OpenGLShader::SetInt(const char* name, int value) {
glUniform1i(glGetUniformLocation(m_program, name), value);
}
void OpenGLShader::SetIntArray(const char* name, const int* values, unsigned int count) {
glUniform1iv(glGetUniformLocation(m_program, name), count, values);
}
void OpenGLShader::SetFloat(const char* name, float value) {
glUniform1f(glGetUniformLocation(m_program, name), value);
}
void OpenGLShader::SetFloatArray(const char* name, const float* values, unsigned int count) {
glUniform1fv(glGetUniformLocation(m_program, name), count, values);
}
void OpenGLShader::SetVec3(const char* name, float x, float y, float z) {
glUniform3f(glGetUniformLocation(m_program, name), x, y, z);
}
void OpenGLShader::SetVec3(const char* name, const float* values) {
glUniform3fv(glGetUniformLocation(m_program, name), 1, values);
}
void OpenGLShader::SetVec4(const char* name, float x, float y, float z, float w) {
glUniform4f(glGetUniformLocation(m_program, name), x, y, z, w);
}
void OpenGLShader::SetVec4(const char* name, const float* values) {
glUniform4fv(glGetUniformLocation(m_program, name), 1, values);
}
void OpenGLShader::SetMat2(const char* name, const float* value) {
glUniformMatrix2fv(glGetUniformLocation(m_program, name), 1, GL_FALSE, value);
}
void OpenGLShader::SetMat3(const char* name, const float* value) {
glUniformMatrix3fv(glGetUniformLocation(m_program, name), 1, GL_FALSE, value);
}
void OpenGLShader::SetMat4(const char* name, const float* value) {
glUniformMatrix4fv(glGetUniformLocation(m_program, name), 1, GL_FALSE, value);
}
void OpenGLShader::SetMat4Array(const char* name, const float* values, unsigned int count) {
glUniformMatrix4fv(glGetUniformLocation(m_program, name), count, GL_FALSE, values);
}
int OpenGLShader::GetUniformLocation(const char* name) const {
return glGetUniformLocation(m_program, name);
}
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, nullptr, 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, nullptr, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR\n" << infoLog << std::endl;
return false;
}
return true;
}
} // namespace RHI
} // namespace XCEngine