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 "mirror.hpp"
|
||||||
#include "geometry.hpp"
|
#include "geometry.hpp"
|
||||||
|
|
||||||
|
#include <cgl/render.hpp>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001;
|
__attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001;
|
||||||
@@ -42,9 +44,6 @@ struct MeshRef {
|
|||||||
glBindVertexArray(vao);
|
glBindVertexArray(vao);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, ibo);
|
glBindBuffer(GL_ARRAY_BUFFER, ibo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(Primitive<N>) * primitive_count, &mesh.prims[0], GL_STATIC_DRAW);
|
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);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -75,74 +74,34 @@ Matrices build(GLFWwindow *window, float st) {
|
|||||||
return Matrices(proj, view);
|
return Matrices(proj, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
void run(GLFWwindow *window) {
|
||||||
//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();
|
|
||||||
|
|
||||||
glEnable(GL_PROGRAM_POINT_SIZE);
|
glEnable(GL_PROGRAM_POINT_SIZE);
|
||||||
glEnable(GL_POINT_SMOOTH);
|
glEnable(GL_POINT_SMOOTH);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
// glEnable(GL_CULL_FACE);
|
// glEnable(GL_CULL_FACE);
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
|
|
||||||
//region shaders
|
auto defer = cgl::compile_shaderprogram_file(
|
||||||
GLuint slice_pipe;
|
GL_VERTEX_SHADER, "shaders/slice/deferred.vs.glsl");
|
||||||
glCreateProgramPipelines(1, &slice_pipe);
|
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;
|
auto slice = cgl::compile_shaderprogram_file(
|
||||||
glCreateProgramPipelines(1, &proj_pipe);
|
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;
|
auto solid = cgl::compile_shaderprogram_file(
|
||||||
GLuint slice, curve_ortho, curve_stereo;
|
GL_FRAGMENT_SHADER, "shaders/solid.fs.glsl");
|
||||||
GLuint solid;
|
|
||||||
|
|
||||||
try {
|
cgl::pipeline proj_pipe;
|
||||||
defer = utilCreateShaderProgramFile(GL_VERTEX_SHADER, {"shaders/slice/deferred.vs.glsl"});
|
proj_pipe.use_stages(direct_stereo);
|
||||||
direct_ortho = utilCreateShaderProgramFile(GL_VERTEX_SHADER, {"shaders/direct-ortho.vs.glsl"});
|
proj_pipe.use_stages(curve_stereo);
|
||||||
direct_stereo = utilCreateShaderProgramFile(GL_VERTEX_SHADER, {"shaders/direct-stereo.vs.glsl"});
|
proj_pipe.use_stages(solid);
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
//region points
|
//region points
|
||||||
auto group = tc::group::H(4);
|
auto group = tc::group::H(4);
|
||||||
@@ -167,16 +126,6 @@ int main(int argc, char *argv[]) {
|
|||||||
wires.emplace_back(s);
|
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
|
//endregion
|
||||||
|
|
||||||
GLuint vbo;
|
GLuint vbo;
|
||||||
@@ -206,35 +155,18 @@ int main(int argc, char *argv[]) {
|
|||||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(mats), &mats, GL_STATIC_DRAW);
|
glBufferData(GL_UNIFORM_BUFFER, sizeof(mats), &mats, GL_STATIC_DRAW);
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
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;
|
const auto wires_light = wires_dark;
|
||||||
glBindProgramPipeline(proj_pipe);
|
glBindProgramPipeline(proj_pipe);
|
||||||
for (int i = 0; i < wires.size(); i++) {
|
for (auto ref : wires) {
|
||||||
const auto &ref = wires[i];
|
glProgramUniform3f(solid, 2, 1, 1, 1);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ref.ibo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ref.ibo);
|
||||||
glDrawElements(WIRE_MODE, ref.index_count, GL_UNSIGNED_INT, nullptr);
|
glDrawElements(WIRE_MODE, ref.index_count, GL_UNSIGNED_INT, nullptr);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
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);
|
glBindProgramPipeline(0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
@@ -242,6 +174,36 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
glfwPollEvents();
|
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();
|
glfwTerminate();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|||||||
Reference in New Issue
Block a user