using raii shaders

This commit is contained in:
2020-03-09 00:00:52 -04:00
parent e069088437
commit 5d030ffe65
2 changed files with 304 additions and 93 deletions

249
vis/include/cgl/render.hpp Normal file
View File

@@ -0,0 +1,249 @@
#pragma once
#include <memory>
#include <glad/glad.h>
namespace cgl {
template<class T>
class buffer {
GLuint id;
public:
buffer() : id(0) {
glCreateBuffers(1, &id);
std::cout << "create " << id << std::endl;
}
buffer(buffer &) = delete;
buffer(buffer &&o) noexcept {
id = std::exchange(o.id, 0);
};
~buffer() {
glDeleteBuffers(1, &id);
id = 0;
}
operator GLuint() const {
return id;
}
};
class shader {
protected:
GLuint id;
GLenum mode;
public:
shader(GLenum mode) : mode(mode), id(0) {
id = glCreateShader(mode);
}
shader(shader &) = delete;
shader(shader &&o) noexcept {
mode = o.mode;
id = std::exchange(o.id, 0);
};
~shader() {
glDeleteShader(id);
}
operator GLuint() const {
return id;
}
[[nodiscard]] GLenum get_mode() const {
return mode;
}
[[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(0) {
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);
}
void attach(const shader &sh) {
glAttachShader(id, sh);
}
void detach(const shader &sh) {
glDetachShader(id, sh);
}
bool link() {
glLinkProgram(id);
return (bool) get(GL_LINK_STATUS);
}
};
class shaderprogram : public program {
protected:
GLenum mode;
public:
shaderprogram(GLenum mode) : program(), mode(mode) {
glProgramParameteri(id, GL_PROGRAM_SEPARABLE, GL_TRUE);
}
shaderprogram(shaderprogram &&o) noexcept : program(std::move(o)) {
mode = o.mode;
}
[[nodiscard]] GLenum get_mode() const {
return mode;
}
};
class pipeline {
protected:
GLuint id;
public:
pipeline() : id(0) {
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) {
GLbitfield bits;
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;
}
glUseProgramStages(id, bits, 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);
}
};
shader compile_shader(GLenum mode, const std::string &src) {
shader res(mode);
res.set_source(src);
if (!res.compile())
throw shader_error(res.get_info_log());
return res;
}
shader compile_shader_file(GLenum mode, const std::string &file) {
return compile_shader(mode, utilReadFile(file));
}
shaderprogram compile_shaderprogram(GLenum mode, const std::string &src) {
shader sh = compile_shader(mode, src);
shaderprogram res(mode);
res.attach(sh);
if (!res.link())
throw shader_error(res.get_info_log());
res.detach(sh);
return res;
}
shaderprogram compile_shaderprogram_file(GLenum mode, const std::string &file) {
return compile_shaderprogram(mode, utilReadFile(file));
}
}

View File

@@ -11,6 +11,8 @@
#include "mirror.hpp"
#include "geometry.hpp"
#include <cgl/render.hpp>
#ifdef _WIN32
extern "C" {
__attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001;
@@ -42,9 +44,6 @@ struct MeshRef {
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, ibo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Primitive<N>) * primitive_count, &mesh.prims[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribIPointer(0, N, GL_INT, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
};
@@ -75,74 +74,34 @@ Matrices build(GLFWwindow *window, float st) {
return Matrices(proj, view);
}
int main(int argc, char *argv[]) {
//region init window
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return EXIT_FAILURE;
}
auto window = glfwCreateWindow(
1920, 1080,
"Coset Visualization",
nullptr, nullptr);
if (!window) {
std::cerr << "Failed to create window" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(0);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
//endregion
std::cout << utilInfo();
void run(GLFWwindow *window) {
glEnable(GL_PROGRAM_POINT_SIZE);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_DEPTH_TEST);
// glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
//region shaders
GLuint slice_pipe;
glCreateProgramPipelines(1, &slice_pipe);
auto defer = cgl::compile_shaderprogram_file(
GL_VERTEX_SHADER, "shaders/slice/deferred.vs.glsl");
auto direct_ortho = cgl::compile_shaderprogram_file(
GL_VERTEX_SHADER, "shaders/direct-ortho.vs.glsl");
auto direct_stereo = cgl::compile_shaderprogram_file(
GL_VERTEX_SHADER, "shaders/direct-stereo.vs.glsl");
GLuint proj_pipe;
glCreateProgramPipelines(1, &proj_pipe);
auto slice = cgl::compile_shaderprogram_file(
GL_GEOMETRY_SHADER, "shaders/slice/slice.gm.glsl");
auto curve_stereo = cgl::compile_shaderprogram_file(
GL_GEOMETRY_SHADER, "shaders/curve-stereo.gm.glsl");
auto curve_ortho = cgl::compile_shaderprogram_file(
GL_GEOMETRY_SHADER, "shaders/curve-ortho.gm.glsl");
GLuint defer, direct_ortho, direct_stereo;
GLuint slice, curve_ortho, curve_stereo;
GLuint solid;
auto solid = cgl::compile_shaderprogram_file(
GL_FRAGMENT_SHADER, "shaders/solid.fs.glsl");
try {
defer = utilCreateShaderProgramFile(GL_VERTEX_SHADER, {"shaders/slice/deferred.vs.glsl"});
direct_ortho = utilCreateShaderProgramFile(GL_VERTEX_SHADER, {"shaders/direct-ortho.vs.glsl"});
direct_stereo = utilCreateShaderProgramFile(GL_VERTEX_SHADER, {"shaders/direct-stereo.vs.glsl"});
slice = utilCreateShaderProgramFile(GL_GEOMETRY_SHADER, {"shaders/slice/slice.gm.glsl"});
curve_stereo = utilCreateShaderProgramFile(GL_GEOMETRY_SHADER, {"shaders/curve-stereo.gm.glsl"});
curve_ortho = utilCreateShaderProgramFile(GL_GEOMETRY_SHADER, {"shaders/curve-ortho.gm.glsl"});
solid = utilCreateShaderProgramFile(GL_FRAGMENT_SHADER, {"shaders/solid.fs.glsl"});
glUseProgramStages(proj_pipe, GL_VERTEX_SHADER_BIT, direct_stereo);
// glUseProgramStages(proj_pipe, GL_GEOMETRY_SHADER_BIT, curve_stereo);
glUseProgramStages(proj_pipe, GL_FRAGMENT_SHADER_BIT, solid);
glUseProgramStages(slice_pipe, GL_VERTEX_SHADER_BIT, defer);
glUseProgramStages(slice_pipe, GL_GEOMETRY_SHADER_BIT, slice);
glUseProgramStages(slice_pipe, GL_FRAGMENT_SHADER_BIT, solid);
} catch (const gl_error &e) {
std::cerr << e.what() << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
//endregion
cgl::pipeline proj_pipe;
proj_pipe.use_stages(direct_stereo);
proj_pipe.use_stages(curve_stereo);
proj_pipe.use_stages(solid);
//region points
auto group = tc::group::H(4);
@@ -167,16 +126,6 @@ int main(int argc, char *argv[]) {
wires.emplace_back(s);
}
const unsigned SLICES_N = 4;
const GLenum SLICES_MODE = GL_POINTS;
std::vector<MeshRef<SLICES_N>> slices;
for (const auto &sg_gens : Combos(g_gens, SLICES_N - 1)) {
const auto s = triangulate<SLICES_N>(group, sg_gens).tile(group, g_gens, sg_gens);
slices.emplace_back(s);
}
//endregion
GLuint vbo;
@@ -206,35 +155,18 @@ int main(int argc, char *argv[]) {
glBufferData(GL_UNIFORM_BUFFER, sizeof(mats), &mats, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
const auto wires_dark = glm::vec3(.3, .3,.3);
glLineWidth(1.5);
const auto wires_dark = glm::vec3(.3, .3, .3);
const auto wires_light = wires_dark;
glBindProgramPipeline(proj_pipe);
for (int i = 0; i < wires.size(); i++) {
const auto &ref = wires[i];
const float f = factor(i, slices.size());
glm::vec3 c = glm::mix(wires_dark, wires_light, f);
glProgramUniform3f(solid, 2, c.r, c.g, c.b);
for (auto ref : wires) {
glProgramUniform3f(solid, 2, 1, 1, 1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ref.ibo);
glDrawElements(WIRE_MODE, ref.index_count, GL_UNSIGNED_INT, nullptr);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
const auto slice_dark = glm::vec3(.5, .3, .7);
const auto slice_light = glm::vec3(.9, .9, .95);
glBindProgramPipeline(slice_pipe);
for (int i = 0; i < slices.size(); i++) {
const auto &ref = slices[i];
const float f = factor(i, slices.size());
glm::vec3 c = glm::mix(slice_dark, slice_light, f);
glProgramUniform3f(solid, 2, c.r, c.g, c.b);
glBindVertexArray(ref.vao);
glDrawArrays(SLICES_MODE, 0, ref.primitive_count);
}
glBindProgramPipeline(0);
glBindVertexArray(0);
@@ -242,6 +174,36 @@ int main(int argc, char *argv[]) {
glfwPollEvents();
}
}
int main(int argc, char *argv[]) {
//region init window
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return EXIT_FAILURE;
}
auto window = glfwCreateWindow(
1920, 1080,
"Coset Visualization",
nullptr, nullptr);
if (!window) {
std::cerr << "Failed to create window" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(1);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
//endregion
std::cout << utilInfo();
run(window);
glfwTerminate();
return EXIT_SUCCESS;