#include "shader.h" #include #include #include "assets_manager.h" #include "logger.h" void Shader::destroy() { if (m_program != 0) { glDeleteProgram(m_program); } } bool Shader::load(const std::string &vertexFilename, const std::string &fragmentFilename) { // Read source from assets std::vector vsSourceRaw = AssetsManager::ReadAll(vertexFilename); std::vector fsSourceRaw = AssetsManager::ReadAll(fragmentFilename); if (vsSourceRaw.empty() || fsSourceRaw.empty()) { Logger::Log("Failed to read shader files from assets"); return false; } // Null-terminate the source strings std::string vsSource(vsSourceRaw.begin(), vsSourceRaw.end()); std::string fsSource(fsSourceRaw.begin(), fsSourceRaw.end()); GLuint vertexShader = compile(GL_VERTEX_SHADER, vsSource.c_str()); if (!vertexShader) return false; GLuint fragmentShader = compile(GL_FRAGMENT_SHADER, fsSource.c_str()); if (!fragmentShader) { glDeleteShader(vertexShader); return false; } m_program = glCreateProgram(); glAttachShader(m_program, vertexShader); glAttachShader(m_program, fragmentShader); glLinkProgram(m_program); // Check for link errors GLint linked; glGetProgramiv(m_program, GL_LINK_STATUS, &linked); if (!linked) { GLint infoLen = 0; glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { std::vector infoLog(infoLen); glGetProgramInfoLog(m_program, infoLen, nullptr, infoLog.data()); Logger::Log(std::format("Error linking program: {}", infoLog.data())); } glDeleteProgram(m_program); m_program = 0; } // Shaders can be deleted after linking glDeleteShader(vertexShader); glDeleteShader(fragmentShader); return (m_program != 0); } void Shader::use() const { if (m_program) glUseProgram(m_program); } GLint Shader::getUniformLocation(const char *name) const { return glGetUniformLocation(m_program, name); } GLint Shader::getAttribLocation(const char *name) const { return glGetAttribLocation(m_program, name); } GLuint Shader::compile(GLenum type, const char *source) { GLuint shader = glCreateShader(type); glShaderSource(shader, 1, &source, nullptr); glCompileShader(shader); GLint compiled; glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { GLint infoLen = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { std::vector infoLog(infoLen); glGetShaderInfoLog(shader, infoLen, nullptr, infoLog.data()); Logger::Log(std::format("Error compiling shader type {}: {}", type, infoLog.data())); } glDeleteShader(shader); return 0; } return shader; }