#include "cbt/opengl/shader.hpp" #include #include #include "fmt/std.h" namespace cbt::opengl { shader::shader() {} shader::~shader() { if (m_id) { glDeleteProgram(m_id); } } shader::shader(shader&& other) noexcept : m_id(other.m_id) { other.m_id = 0; } shader& shader::operator=(shader&& other) noexcept { if (this != &other) { if (m_id) { glDeleteProgram(m_id); } m_id = other.m_id; other.m_id = 0; } return *this; } auto shader::compile_vertex(char const* source) -> bool { auto vert = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vert, 1, &source, nullptr); glCompileShader(vert); GLint success; glGetShaderiv(vert, GL_COMPILE_STATUS, &success); if (!success) { GLchar info[512]; glGetShaderInfoLog(vert, 512, nullptr, info); fmt::print("Vertex shader compile error:\n{}\n", info); glDeleteShader(vert); return false; } if (m_id) { glDeleteProgram(m_id); } m_id = glCreateProgram(); glAttachShader(m_id, vert); glDeleteShader(vert); return true; } auto shader::compile_fragment(char const* source) -> bool { auto frag = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(frag, 1, &source, nullptr); glCompileShader(frag); GLint success; glGetShaderiv(frag, GL_COMPILE_STATUS, &success); if (!success) { GLchar info[512]; glGetShaderInfoLog(frag, 512, nullptr, info); fmt::print("Fragment shader compile error:\n{}\n", info); glDeleteShader(frag); return false; } glAttachShader(m_id, frag); glDeleteShader(frag); return true; } auto shader::link() -> bool { glLinkProgram(m_id); GLint success; glGetProgramiv(m_id, GL_LINK_STATUS, &success); if (!success) { GLchar info[512]; glGetProgramInfoLog(m_id, 512, nullptr, info); fmt::print("Shader link error:\n{}\n", info); glDeleteProgram(m_id); m_id = 0; return false; } return true; } auto shader::use() const -> void { glUseProgram(m_id); } auto shader::unuse() const -> void { glUseProgram(0); } auto shader::id() const -> GLuint { return m_id; } auto shader::valid() const -> bool { return m_id != 0; } }