I am experienced with other languages, but not so much with the latest C++ standards. I was wondering if anyone had any tips on how to improve my code or any critique on my implementation. This is not designed to be used as an external or public library and I hope my use of the initializer lists are suitable (unwrapped pointers as they have no owner and aren't copied or stored).
I'm using spdlog
and the Logger
typedef
is a typedef std::shared_ptr<spdlog::logger> Logger;
in another (common) header.
program.cpp
#include <render/program.h>
Program::Program(Logger logger) :
logger(std::move(logger)) {}
Program::operator GLuint() const {
return program_id;
}
void Program::create(std::initializer_list<Shader *> shaders) {
program_id = glCreateProgram();
for (const Shader *shader : shaders) {
glAttachShader(program_id, (GLuint) *shader);
}
glLinkProgram(program_id);
GLint link_status;
glGetProgramiv(program_id, GL_LINK_STATUS, &link_status);
if (!link_status) {
logger->error("Failed to link program");
GLint log_length;
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0) {
GLchar info_log[log_length - 1];
glGetProgramInfoLog(program_id, sizeof(info_log), nullptr, info_log);
logger->error((const char *) info_log);
}
}
for (const Shader *shader : shaders) {
glDetachShader(program_id, (GLuint) *shader);
}
}
void Program::destroy() const {
glDeleteProgram(program_id);
}
void Program::use() const {
glUseProgram(program_id);
}
program.h
#pragma once
#include <engine.h>
#include <render/shader.h>
#include <initializer_list>
class Program {
public:
explicit Program(Logger logger);
explicit operator GLuint() const;
void create(std::initializer_list<Shader *> shaders);
void destroy() const;
void use() const;
private:
const Logger logger;
GLuint program_id;
};
shader.cpp
#include <render/shader.h>
#include <fstream>
Shader::Shader(Logger logger, std::string path) :
logger(std::move(logger)), path(std::move(path)) {}
Shader::operator GLuint() const {
return shader_id;
}
void Shader::create(GLenum type) {
std::ifstream input_stream(path);
if (!input_stream) {
logger->error("Unable to open shader file");
return;
}
std::string source;
char buffer;
source.reserve(120);
while (input_stream.get(buffer)) {
source += buffer;
}
shader_id = glCreateShader(type);
const GLchar *sources[] = {source.c_str()};
glShaderSource(shader_id, 1, sources, nullptr);
glCompileShader(shader_id);
GLint compile_status;
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
if (!compile_status) {
logger->error("Failed to compile shader: {}", path);
GLint log_length;
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0) {
GLchar info_log[log_length - 1];
glGetShaderInfoLog(shader_id, sizeof(info_log), nullptr, info_log);
logger->error((const char *) info_log);
}
}
}
void Shader::destroy() const {
glDeleteShader(shader_id);
}
shader.h
#pragma once
#include <engine.h>
#include <string>
class Shader {
public:
Shader(Logger logger, std::string path);
explicit operator GLuint() const;
void create(GLenum type);
void destroy() const;
private:
const Logger logger;
const std::string path;
GLuint shader_id;
};