#pragma once #include #include namespace cgl { template class buffer { GLuint id{}; public: buffer() { glCreateBuffers(1, &id); } buffer(const T &data, GLenum usage = GL_STATIC_DRAW) : buffer() { put(data, usage); } buffer(const std::vector &data, GLenum usage = GL_STATIC_DRAW) : buffer() { put(data, usage); } buffer(buffer &) = delete; buffer(buffer &&o) noexcept { id = std::exchange(o.id, 0); }; ~buffer() { glDeleteBuffers(1, &id); id = 0; } operator GLuint() const { return id; } void put(const T &data, GLenum usage = GL_STATIC_DRAW) { glNamedBufferData(id, sizeof(T), &data, usage); } void put(const std::vector &data, GLenum usage = GL_STATIC_DRAW) { glNamedBufferData(id, sizeof(T) * data.size(), &data[0], usage); } }; template class shader { protected: GLuint id{}; public: shader() { id = glCreateShader(mode); } shader(const std::string &src) : shader() { set_source(src); if (!compile()) throw shader_error(get_info_log()); } static shader file(const std::string &name) { return shader(utilReadFile(name)); } shader(shader &) = delete; shader(shader &&o) noexcept { id = std::exchange(o.id, 0); }; ~shader() { glDeleteShader(id); } operator GLuint() const { return id; } [[nodiscard]] int get(GLenum pname) const { GLint res; glGetShaderiv(id, pname, &res); return (int) res; } [[nodiscard]] std::string get_info_log() const { auto len = (size_t) get(GL_INFO_LOG_LENGTH); char buffer[len]; glGetShaderInfoLog(id, len, nullptr, buffer); return std::string(buffer); } void set_source(const std::string &src) { const char *c_src = src.c_str(); glShaderSource(id, 1, &c_src, nullptr); } bool compile() { glCompileShader(id); return (bool) get(GL_COMPILE_STATUS); } }; class program { protected: GLuint id{}; public: program() { id = glCreateProgram(); } program(program &) = delete; program(program &&o) noexcept { id = std::exchange(o.id, 0); }; ~program() { glDeleteProgram(id); } operator GLuint() const { return id; } [[nodiscard]] int get(GLenum pname) const { GLint res; glGetProgramiv(id, pname, &res); return (int) res; } [[nodiscard]] std::string get_info_log() const { auto len = (size_t) get(GL_INFO_LOG_LENGTH); char buffer[len]; glGetProgramInfoLog(id, len, nullptr, buffer); return std::string(buffer); } template void attach(const shader &sh) { glAttachShader(id, sh); } template void detach(const shader &sh) { glDetachShader(id, sh); } bool link() { glLinkProgram(id); return (bool) get(GL_LINK_STATUS); } }; template class shaderprogram : public program { public: shaderprogram() : program() { glProgramParameteri(id, GL_PROGRAM_SEPARABLE, GL_TRUE); } shaderprogram(const std::string &src) : shaderprogram() { shader sh(src); attach(sh); if (!link()) throw shader_error(get_info_log()); detach(sh); } static shaderprogram file(const std::string &name) { return shaderprogram(utilReadFile(name)); } }; class pipeline { protected: GLuint id{}; public: pipeline() { glCreateProgramPipelines(1, &id); } pipeline(pipeline &) = delete; pipeline(pipeline &&o) noexcept { id = std::exchange(o.id, 0); } ~pipeline() { glDeleteProgramPipelines(1, &id); id = 0; } operator GLuint() const { return id; } void use_stages(const shaderprogram &pgm) { glUseProgramStages(id, GL_VERTEX_SHADER_BIT, pgm); } void use_stages(const shaderprogram &pgm) { glUseProgramStages(id, GL_TESS_CONTROL_SHADER_BIT, pgm); } void use_stages(const shaderprogram &pgm) { glUseProgramStages(id, GL_TESS_EVALUATION_SHADER_BIT, pgm); } void use_stages(const shaderprogram &pgm) { glUseProgramStages(id, GL_GEOMETRY_SHADER_BIT, pgm); } void use_stages(const shaderprogram &pgm) { glUseProgramStages(id, GL_FRAGMENT_SHADER_BIT, pgm); } void use_stages(const shaderprogram &pgm) { glUseProgramStages(id, GL_COMPUTE_SHADER_BIT, pgm); } [[nodiscard]] int get(GLenum pname) const { GLint res; glGetProgramPipelineiv(id, pname, &res); return (int) res; } [[nodiscard]] std::string get_info_log() const { auto len = (size_t) get(GL_INFO_LOG_LENGTH); char buffer[len]; glGetProgramPipelineInfoLog(id, len, nullptr, buffer); return std::string(buffer); } }; namespace pgm { using vert = shaderprogram; using tcs = shaderprogram; using tes = shaderprogram; using geom = shaderprogram; using frag = shaderprogram; using comp = shaderprogram; } }