MetaCore/Source/MetaCoreRender/Private/MetaCoreShaderProgram.cpp
2026-03-20 10:39:34 +08:00

111 lines
3.3 KiB
C++

#include "MetaCoreRender/MetaCoreShaderProgram.h"
#include <glad/glad.h>
#include <vector>
namespace MetaCore {
namespace {
bool MetaCoreCompileShader(unsigned int shaderHandle, const std::string& source, std::string& outError) {
const char* rawSource = source.c_str();
glShaderSource(shaderHandle, 1, &rawSource, nullptr);
glCompileShader(shaderHandle);
int compileStatus = 0;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus == GL_TRUE) {
return true;
}
int logLength = 0;
glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> logBuffer(static_cast<std::size_t>((logLength > 1) ? logLength : 1), '\0');
glGetShaderInfoLog(shaderHandle, logLength, nullptr, logBuffer.data());
outError.assign(logBuffer.data());
return false;
}
} // namespace
MetaCoreShaderProgram::~MetaCoreShaderProgram() {
Shutdown();
}
bool MetaCoreShaderProgram::BuildFromSource(const std::string& vertexSource, const std::string& fragmentSource, std::string& outError) {
Shutdown();
const unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
const unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
if (!MetaCoreCompileShader(vertexShader, vertexSource, outError)) {
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return false;
}
if (!MetaCoreCompileShader(fragmentShader, fragmentSource, outError)) {
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return false;
}
ProgramHandle_ = glCreateProgram();
glAttachShader(ProgramHandle_, vertexShader);
glAttachShader(ProgramHandle_, fragmentShader);
glLinkProgram(ProgramHandle_);
int linkStatus = 0;
glGetProgramiv(ProgramHandle_, GL_LINK_STATUS, &linkStatus);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
if (linkStatus == GL_TRUE) {
return true;
}
int logLength = 0;
glGetProgramiv(ProgramHandle_, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> logBuffer(static_cast<std::size_t>((logLength > 1) ? logLength : 1), '\0');
glGetProgramInfoLog(ProgramHandle_, logLength, nullptr, logBuffer.data());
outError.assign(logBuffer.data());
glDeleteProgram(ProgramHandle_);
ProgramHandle_ = 0;
return false;
}
void MetaCoreShaderProgram::Shutdown() {
if (ProgramHandle_ != 0) {
glDeleteProgram(ProgramHandle_);
ProgramHandle_ = 0;
}
}
void MetaCoreShaderProgram::Bind() const {
glUseProgram(ProgramHandle_);
}
unsigned int MetaCoreShaderProgram::GetNativeHandle() const {
return ProgramHandle_;
}
void MetaCoreShaderProgram::SetMatrix4(const char* name, const glm::mat4& value) const {
const int location = glGetUniformLocation(ProgramHandle_, name);
glUniformMatrix4fv(location, 1, GL_FALSE, &value[0][0]);
}
void MetaCoreShaderProgram::SetVector3(const char* name, const glm::vec3& value) const {
const int location = glGetUniformLocation(ProgramHandle_, name);
glUniform3fv(location, 1, &value[0]);
}
void MetaCoreShaderProgram::SetFloat(const char* name, float value) const {
const int location = glGetUniformLocation(ProgramHandle_, name);
glUniform1f(location, value);
}
} // namespace MetaCore