#include "shader.h" #include #include #include #include "../lib/glew/GL/glew.h" #include "../lib/glfw/glfw3.h" #include "logger.h" #include "vertex.h" Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath) { const uint32_t vshader = compile_shader(GL_VERTEX_SHADER, vertexPath); const uint32_t fshader = compile_shader(GL_FRAGMENT_SHADER, fragmentPath); if (vshader == 0 || fshader == 0) { program_id_ = 0; return; } program_id_ = glCreateProgram(); glAttachShader(program_id_, vshader); glAttachShader(program_id_, fshader); glLinkProgram(program_id_); // Error handling int ret; glGetProgramiv(program_id_, GL_LINK_STATUS, &ret); if (ret == GL_FALSE) { char buffer[1024]; glGetProgramInfoLog(program_id_, sizeof(buffer), nullptr, buffer); error_ = buffer; glDeleteProgram(program_id_); program_id_ = 0; } glDeleteShader(vshader); glDeleteShader(fshader); } void Shader::use() const { if (program_id_ != 0) glUseProgram(program_id_); } void Shader::setup_attribs() const { int loc = glGetAttribLocation(program_id_, "vpos"); if (loc != -1) { glEnableVertexAttribArray(loc); glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, position))); } loc = glGetAttribLocation(program_id_, "vcolor"); if (loc != -1) { glEnableVertexAttribArray(loc); glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, color))); } } int Shader::uniform_location(const char* key) const { return glGetUniformLocation(program_id_, key); } void Shader::set_int(int loc, int value) { if (loc != -1) glUniform1i(loc, value); } void Shader::set_float(int loc, float value) { if (loc != -1) glUniform1f(loc, value); } void Shader::set_vec3(int loc, const glm::vec3& value) { if (loc != -1) glUniform3fv(loc, 1, &value[0]); } void Shader::set_vec4(int loc, const glm::vec4& value) { if (loc != -1) glUniform4fv(loc, 1, &value[0]); } void Shader::set_mat4(int loc, const glm::mat4& value) { if (loc != -1) glUniformMatrix4fv(loc, 1, GL_FALSE, &value[0][0]); } std::string Shader::read_shader_file(const std::string& filename) { std::ifstream file(filename); if (!file) { error_ = "Failed to open shader file: " + filename; Logger::error(sstr("Failed to open shader file: ", filename)); return std::string{0}; } std::stringstream buffer; buffer << file.rdbuf(); return buffer.str(); } uint32_t Shader::compile_shader(uint32_t type, const std::string& source_path) { const char* shader_type_name = (type == GL_VERTEX_SHADER) ? "vertex" : "fragment"; std::string source = read_shader_file(source_path); if (source.empty()) return 0; Logger::info( sstr("Compiling ", shader_type_name, " shader: ", source_path)); const uint32_t shader = glCreateShader(type); const char* shader_code = source.c_str(); glShaderSource(shader, 1, &shader_code, nullptr); glCompileShader(shader); // Error handling int ret; glGetShaderiv(shader, GL_COMPILE_STATUS, &ret); if (ret == GL_FALSE) { char buffer[1024]; glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer); error_ = buffer; Logger::error( sstr("Shader compilation failed (", shader_type_name, "): ", buffer)); glDeleteShader(shader); return 0; } Logger::info(sstr(shader_type_name, " shader compiled successfully")); return shader; }