mode template for shader, shaderprogram, type aliases

This commit is contained in:
2020-03-09 00:32:12 -04:00
parent e56896db9b
commit 219c3f9e32
2 changed files with 58 additions and 66 deletions

View File

@@ -48,17 +48,17 @@ namespace cgl {
} }
}; };
template<GLenum mode>
class shader { class shader {
protected: protected:
GLuint id{}; GLuint id{};
GLenum mode;
public: public:
shader(GLenum mode) : mode(mode) { shader() {
id = glCreateShader(mode); id = glCreateShader(mode);
} }
shader(GLenum mode, const std::string &src) : shader(mode) { shader(const std::string &src) : shader() {
set_source(src); set_source(src);
if (!compile()) if (!compile())
@@ -68,7 +68,6 @@ namespace cgl {
shader(shader &) = delete; shader(shader &) = delete;
shader(shader &&o) noexcept { shader(shader &&o) noexcept {
mode = o.mode;
id = std::exchange(o.id, 0); id = std::exchange(o.id, 0);
}; };
@@ -80,10 +79,6 @@ namespace cgl {
return id; return id;
} }
[[nodiscard]] GLenum get_mode() const {
return mode;
}
[[nodiscard]] int get(GLenum pname) const { [[nodiscard]] int get(GLenum pname) const {
GLint res; GLint res;
glGetShaderiv(id, pname, &res); glGetShaderiv(id, pname, &res);
@@ -144,11 +139,13 @@ namespace cgl {
return std::string(buffer); return std::string(buffer);
} }
void attach(const shader &sh) { template<GLenum mode>
void attach(const shader<mode> &sh) {
glAttachShader(id, sh); glAttachShader(id, sh);
} }
void detach(const shader &sh) { template<GLenum mode>
void detach(const shader<mode> &sh) {
glDetachShader(id, sh); glDetachShader(id, sh);
} }
@@ -158,17 +155,15 @@ namespace cgl {
} }
}; };
template<GLenum mode>
class shaderprogram : public program { class shaderprogram : public program {
protected:
GLenum mode;
public: public:
shaderprogram(GLenum mode) : program(), mode(mode) { shaderprogram() : program() {
glProgramParameteri(id, GL_PROGRAM_SEPARABLE, GL_TRUE); glProgramParameteri(id, GL_PROGRAM_SEPARABLE, GL_TRUE);
} }
shaderprogram(GLenum mode, const std::string &src) : shaderprogram(mode) { shaderprogram(const std::string &src) : shaderprogram() {
shader sh(mode, src); shader<mode> sh(src);
attach(sh); attach(sh);
@@ -177,14 +172,6 @@ namespace cgl {
detach(sh); detach(sh);
} }
shaderprogram(shaderprogram &&o) noexcept : program(std::move(o)) {
mode = o.mode;
}
[[nodiscard]] GLenum get_mode() const {
return mode;
}
}; };
class pipeline { class pipeline {
@@ -211,29 +198,28 @@ namespace cgl {
return id; return id;
} }
void use_stages(const shaderprogram &pgm) { void use_stages(const shaderprogram<GL_VERTEX_SHADER> &pgm) {
GLbitfield bits; glUseProgramStages(id, GL_VERTEX_SHADER_BIT, pgm);
switch (pgm.get_mode()) {
case GL_VERTEX_SHADER:
bits = GL_VERTEX_SHADER_BIT;
break;
case GL_TESS_CONTROL_SHADER:
bits = GL_TESS_CONTROL_SHADER_BIT;
break;
case GL_TESS_EVALUATION_SHADER:
bits = GL_TESS_EVALUATION_SHADER_BIT;
break;
case GL_GEOMETRY_SHADER:
bits = GL_GEOMETRY_SHADER_BIT;
break;
case GL_FRAGMENT_SHADER:
bits = GL_FRAGMENT_SHADER_BIT;
break;
default:
throw std::domain_error("invalid shaderprogram mode");
} }
glUseProgramStages(id, bits, pgm); void use_stages(const shaderprogram<GL_TESS_CONTROL_SHADER> &pgm) {
glUseProgramStages(id, GL_TESS_CONTROL_SHADER_BIT, pgm);
}
void use_stages(const shaderprogram<GL_TESS_EVALUATION_SHADER> &pgm) {
glUseProgramStages(id, GL_TESS_EVALUATION_SHADER_BIT, pgm);
}
void use_stages(const shaderprogram<GL_GEOMETRY_SHADER> &pgm) {
glUseProgramStages(id, GL_GEOMETRY_SHADER_BIT, pgm);
}
void use_stages(const shaderprogram<GL_FRAGMENT_SHADER> &pgm) {
glUseProgramStages(id, GL_FRAGMENT_SHADER_BIT, pgm);
}
void use_stages(const shaderprogram<GL_COMPUTE_SHADER> &pgm) {
glUseProgramStages(id, GL_COMPUTE_SHADER_BIT, pgm);
} }
[[nodiscard]] int get(GLenum pname) const { [[nodiscard]] int get(GLenum pname) const {
@@ -250,11 +236,17 @@ namespace cgl {
} }
}; };
shader compile_shader(GLenum mode, const std::string &file) { using vert_shader = shader<GL_VERTEX_SHADER>;
return shader(mode, utilReadFile(file)); using tctl_shader = shader<GL_TESS_CONTROL_SHADER>;
} using tevl_shader = shader<GL_TESS_EVALUATION_SHADER>;
using geom_shader = shader<GL_GEOMETRY_SHADER>;
using frag_shader = shader<GL_FRAGMENT_SHADER>;
using comp_shader = shader<GL_COMPUTE_SHADER>;
shaderprogram compile_shaderprogram(GLenum mode, const std::string &file) { using vert_program = shaderprogram<GL_VERTEX_SHADER>;
return shaderprogram(mode, utilReadFile(file)); using tctl_program = shaderprogram<GL_TESS_CONTROL_SHADER>;
} using tevl_program = shaderprogram<GL_TESS_EVALUATION_SHADER>;
using geom_program = shaderprogram<GL_GEOMETRY_SHADER>;
using frag_program = shaderprogram<GL_FRAGMENT_SHADER>;
using comp_program = shaderprogram<GL_COMPUTE_SHADER>;
} }

View File

@@ -81,22 +81,22 @@ void run(GLFWwindow *window) {
// glEnable(GL_CULL_FACE); // glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); glCullFace(GL_BACK);
auto defer = cgl::compile_shaderprogram( auto defer = cgl::vert_program(
GL_VERTEX_SHADER, "shaders/slice/deferred.vs.glsl"); utilReadFile("shaders/slice/deferred.vs.glsl"));
auto direct_ortho = cgl::compile_shaderprogram( auto direct_ortho = cgl::vert_program(
GL_VERTEX_SHADER, "shaders/direct-ortho.vs.glsl"); utilReadFile("shaders/direct-ortho.vs.glsl"));
auto direct_stereo = cgl::compile_shaderprogram( auto direct_stereo = cgl::vert_program(
GL_VERTEX_SHADER, "shaders/direct-stereo.vs.glsl"); utilReadFile("shaders/direct-stereo.vs.glsl"));
auto slice = cgl::compile_shaderprogram( auto slice = cgl::geom_program(
GL_GEOMETRY_SHADER, "shaders/slice/slice.gm.glsl"); utilReadFile("shaders/slice/slice.gm.glsl"));
auto curve_stereo = cgl::compile_shaderprogram( auto curve_stereo = cgl::geom_program(
GL_GEOMETRY_SHADER, "shaders/curve-stereo.gm.glsl"); utilReadFile("shaders/curve-stereo.gm.glsl"));
auto curve_ortho = cgl::compile_shaderprogram( auto curve_ortho = cgl::geom_program(
GL_GEOMETRY_SHADER, "shaders/curve-ortho.gm.glsl"); utilReadFile("shaders/curve-ortho.gm.glsl"));
auto solid = cgl::compile_shaderprogram( auto solid = cgl::frag_program(
GL_FRAGMENT_SHADER, "shaders/solid.fs.glsl"); utilReadFile("shaders/solid.fs.glsl"));
cgl::pipeline proj_pipe; cgl::pipeline proj_pipe;
proj_pipe.use_stages(direct_stereo); proj_pipe.use_stages(direct_stereo);