#include "MetaCoreRender/MetaCoreShaderProgram.h" #include #include 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 logBuffer(static_cast((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 logBuffer(static_cast((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