mirror of
https://github.com/allemangD/toddcox-visualize.git
synced 2025-11-10 12:02:47 -05:00
using raii shaders
This commit is contained in:
249
vis/include/cgl/render.hpp
Normal file
249
vis/include/cgl/render.hpp
Normal 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));
|
||||
}
|
||||
}
|
||||
148
vis/src/main.cpp
148
vis/src/main.cpp
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user