mirror of
https://github.com/allemangD/toddcox-visualize.git
synced 2025-11-10 03:52:48 -05:00
Add templated wrapper objects
- Shader - Program - Buffer - VertexArray Along with template magic to deduce VertexArray formats - Format, IFormat, LFormat - AutoFormat - Binder - ATTR
This commit is contained in:
@@ -19,7 +19,13 @@ add_custom_command(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res ${CMAKE_CURRENT_BINARY_DIR}/res
|
||||
COMMENT "Copying Resources")
|
||||
|
||||
add_executable(vis src/main.cpp)
|
||||
add_executable(vis
|
||||
src/main.cpp
|
||||
src/gl/debug.hpp
|
||||
src/gl/shader.hpp
|
||||
src/gl/buffer.hpp
|
||||
src/gl/vertexarray.hpp
|
||||
src/gl/types.hpp)
|
||||
target_link_libraries(vis glfw glad imgui eigen nlohmann_json)
|
||||
add_dependencies(vis resources)
|
||||
|
||||
|
||||
48
src/gl/buffer.hpp
Normal file
48
src/gl/buffer.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
template<typename T_>
|
||||
class Buffer {
|
||||
public:
|
||||
using Type = T_;
|
||||
|
||||
private:
|
||||
GLuint id = 0;
|
||||
|
||||
public:
|
||||
Buffer() {
|
||||
glCreateBuffers(1, &id);
|
||||
}
|
||||
|
||||
Buffer(Buffer&& o) noexcept {
|
||||
id = std::exchange(o.id, 0);
|
||||
}
|
||||
|
||||
Buffer(const Buffer&) = delete; // this is doable, but would be slow.
|
||||
|
||||
operator GLuint() const { // NOLINT(google-explicit-constructor)
|
||||
return id;
|
||||
}
|
||||
|
||||
template<typename RandomIt>
|
||||
GLuint upload(RandomIt first, RandomIt last, GLenum mode = GL_STATIC_DRAW) {
|
||||
size_t count = last - first;
|
||||
|
||||
// todo StaticBuffer that uses BufferStorage
|
||||
glNamedBufferData(id, sizeof(Type) * count, nullptr, mode);
|
||||
|
||||
Type* out = (Type*) glMapNamedBuffer(id, GL_WRITE_ONLY);
|
||||
std::copy(first, last, out);
|
||||
glUnmapNamedBuffer(id);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
~Buffer() {
|
||||
// delete silently ignores 0.
|
||||
glDeleteBuffers(1, &id);
|
||||
}
|
||||
};
|
||||
79
src/gl/shader.hpp
Normal file
79
src/gl/shader.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
template<GLenum mode>
|
||||
class Shader {
|
||||
public:
|
||||
private:
|
||||
GLuint id = 0;
|
||||
|
||||
public:
|
||||
explicit Shader(const std::string &src) {
|
||||
id = glCreateShader(mode);
|
||||
|
||||
const char *str = src.c_str();
|
||||
glShaderSource(id, 1, &str, nullptr);
|
||||
glCompileShader(id);
|
||||
|
||||
// todo throw if compile failed
|
||||
}
|
||||
|
||||
explicit Shader(std::ifstream source)
|
||||
: Shader(std::string(
|
||||
std::istreambuf_iterator<char>(source),
|
||||
std::istreambuf_iterator<char>()
|
||||
)) {}
|
||||
|
||||
Shader(const Shader &) = delete;
|
||||
|
||||
Shader(Shader &&o) noexcept {
|
||||
id = std::exchange(o.id, 0);
|
||||
}
|
||||
|
||||
~Shader() {
|
||||
glDeleteShader(id);
|
||||
}
|
||||
|
||||
operator GLuint() const { // NOLINT(google-explicit-constructor)
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
using VertexShader = Shader<GL_VERTEX_SHADER>;
|
||||
using FragmentShader = Shader<GL_FRAGMENT_SHADER>;
|
||||
|
||||
class Program {
|
||||
private:
|
||||
GLuint id = 0;
|
||||
|
||||
public:
|
||||
template<GLenum ...mode>
|
||||
explicit Program(const Shader<mode> &...shader) {
|
||||
id = glCreateProgram();
|
||||
|
||||
(glAttachShader(id, shader), ...);
|
||||
|
||||
glLinkProgram(id);
|
||||
|
||||
// todo throw if link failed
|
||||
}
|
||||
|
||||
Program(const Program &) = delete;
|
||||
|
||||
Program(Program &&o) noexcept {
|
||||
id = std::exchange(o.id, 0);
|
||||
}
|
||||
|
||||
~Program() {
|
||||
glDeleteProgram(id);
|
||||
}
|
||||
|
||||
operator GLuint() const { // NOLINT(google-explicit-constructor)
|
||||
return id;
|
||||
}
|
||||
};
|
||||
113
src/gl/types.hpp
Normal file
113
src/gl/types.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include <Eigen/Eigen>
|
||||
|
||||
template<class T_>
|
||||
struct Buffer;
|
||||
|
||||
template<class ...Fmt_>
|
||||
struct VertexArray;
|
||||
|
||||
|
||||
template<typename ctype, GLenum type, GLint size, GLuint offset = 0, GLboolean norm = GL_FALSE>
|
||||
struct Format {
|
||||
using CType = ctype;
|
||||
static constexpr GLenum Type = type;
|
||||
static constexpr GLint Size = size;
|
||||
static constexpr GLuint Offset = offset;
|
||||
static constexpr GLboolean Norm = norm;
|
||||
|
||||
template<typename ctype_, GLint size_>
|
||||
using As = Format<ctype_, type, size_, offset, norm>;
|
||||
|
||||
static inline constexpr void apply(GLuint vao, GLuint idx) {
|
||||
glEnableVertexArrayAttrib(vao, idx);
|
||||
glVertexArrayAttribFormat(vao, idx, size, type, norm, offset);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ctype, GLenum type, GLint size, GLuint offset = 0>
|
||||
struct IFormat {
|
||||
using CType = ctype;
|
||||
static constexpr GLenum Type = type;
|
||||
static constexpr GLint Size = size;
|
||||
static constexpr GLuint Offset = offset;
|
||||
|
||||
template<typename ctype_, GLint size_>
|
||||
using As = IFormat<ctype_, type, size_, offset>;
|
||||
|
||||
static inline constexpr void apply(GLuint vao, GLuint idx) {
|
||||
glEnableVertexArrayAttrib(vao, idx);
|
||||
glVertexArrayAttribIFormat(vao, idx, size, type, offset);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ctype, GLenum type, GLint size, GLuint offset = 0>
|
||||
struct LFormat {
|
||||
using CType = ctype;
|
||||
static constexpr GLenum Type = type;
|
||||
static constexpr GLint Size = size;
|
||||
static constexpr GLuint Offset = offset;
|
||||
|
||||
template<typename ctype_, GLint size_>
|
||||
using As = LFormat<ctype_, type, size_, offset>;
|
||||
|
||||
static inline constexpr void apply(GLuint vao, GLuint idx) {
|
||||
glEnableVertexArrayAttrib(vao, idx);
|
||||
glVertexArrayAttribLFormat(vao, idx, size, type, offset);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Fmt_>
|
||||
struct AutoFormat {
|
||||
using Fmt = Fmt_;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AutoFormat<double> {
|
||||
using Fmt = LFormat<double, GL_DOUBLE, 1>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AutoFormat<float> {
|
||||
using Fmt = Format<float, GL_FLOAT, 1>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AutoFormat<int> {
|
||||
using Fmt = IFormat<int, GL_INT, 1>;
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
struct AutoFormat<Eigen::Vector<Scalar, Dim>> {
|
||||
static_assert((Dim >= 1) && (Dim <= 4), "Dim must be in range 1-4");
|
||||
|
||||
using Fmt = typename AutoFormat<Scalar>::Fmt::template As<Eigen::Vector<Scalar, Dim>, Dim>;
|
||||
};
|
||||
|
||||
template<typename Fmt_>
|
||||
struct Binder {
|
||||
using CType = typename AutoFormat<Fmt_>::Fmt::CType;
|
||||
|
||||
const GLuint buf;
|
||||
const GLuint offset;
|
||||
const GLuint stride;
|
||||
|
||||
Binder(const Buffer<CType> &buf) // NOLINT(google-explicit-constructor)
|
||||
: buf((GLuint) buf), offset(0), stride(sizeof(CType)) {}
|
||||
|
||||
template<typename CType_>
|
||||
Binder(const Buffer<CType_> &buf, GLuint offset)
|
||||
: buf((GLuint) buf), offset(offset), stride(sizeof(CType_)) {}
|
||||
|
||||
Binder(const Binder<Fmt_> &o)
|
||||
: buf(o.buf), offset(o.offset), stride(o.stride) {}
|
||||
|
||||
inline void bind(GLuint vao, GLuint idx) const {
|
||||
glVertexArrayVertexBuffer(vao, idx, buf, offset, stride);
|
||||
}
|
||||
};
|
||||
|
||||
#define ATTR(buf, field) Binder<decltype(decltype(buf)::Type::field)>(buf, offsetof(decltype(buf)::Type, field))
|
||||
67
src/gl/vertexarray.hpp
Normal file
67
src/gl/vertexarray.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "buffer.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
template<typename ...Fmt_>
|
||||
class VertexArray {
|
||||
public:
|
||||
template<size_t idx>
|
||||
using Fmt = std::tuple_element_t<idx, std::tuple<Fmt_...>>;
|
||||
|
||||
private:
|
||||
GLuint id = 0;
|
||||
|
||||
template<size_t ...idx>
|
||||
inline void formatall(
|
||||
std::integer_sequence<size_t, idx...>
|
||||
) {
|
||||
(AutoFormat<Fmt_>::Fmt::apply(id, idx), ...);
|
||||
}
|
||||
|
||||
template<size_t ...idx>
|
||||
inline void bindall(
|
||||
const Binder<Fmt_> &...buf,
|
||||
std::integer_sequence<size_t, idx...>
|
||||
) {
|
||||
(buf.bind(id, idx), ...);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit VertexArray() {
|
||||
glCreateVertexArrays(1, &id);
|
||||
formatall(std::make_index_sequence<sizeof...(Fmt_)>());
|
||||
}
|
||||
|
||||
explicit VertexArray(const Binder<Fmt_> &...buf)
|
||||
: VertexArray() {
|
||||
bind(buf...);
|
||||
}
|
||||
|
||||
VertexArray(VertexArray &&o) noexcept {
|
||||
id = std::exchange(o.id, 0);
|
||||
}
|
||||
|
||||
VertexArray(const VertexArray &) = delete; // this is doable, but would be slow.
|
||||
|
||||
~VertexArray() {
|
||||
glDeleteVertexArrays(1, &id);
|
||||
}
|
||||
|
||||
operator GLuint() const { // NOLINT(google-explicit-constructor)
|
||||
return id;
|
||||
}
|
||||
|
||||
void bind(const Binder<Fmt_> &...buf) {
|
||||
bindall(buf..., std::make_index_sequence<sizeof...(Fmt_)>());
|
||||
}
|
||||
|
||||
template<size_t idx>
|
||||
void bind(const Binder<Fmt<idx>> &buf) {
|
||||
buf.bind(id, idx);
|
||||
}
|
||||
};
|
||||
189
src/main.cpp
189
src/main.cpp
@@ -6,7 +6,10 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "gldebug.hpp"
|
||||
#include "gl/debug.hpp"
|
||||
#include "gl/buffer.hpp"
|
||||
#include "gl/shader.hpp"
|
||||
#include "gl/vertexarray.hpp"
|
||||
|
||||
#include <ml/meshlib.hpp>
|
||||
#include <ml/meshlib_json.hpp>
|
||||
@@ -123,145 +126,54 @@ void set_style() {
|
||||
int run(GLFWwindow *window, ImGuiContext *context) {
|
||||
State state;
|
||||
|
||||
Buffer<GLuint> ind_buf;
|
||||
Buffer<Eigen::Vector3f> vert_buf;
|
||||
Buffer<Eigen::Vector3f> vert2_buf;
|
||||
|
||||
VertexArray<Eigen::Vector3f> vao(vert_buf);
|
||||
glVertexArrayElementBuffer(vao, ind_buf);
|
||||
|
||||
auto mesh = ml::CubeMesh(0.25f);
|
||||
// auto mesh = ml::read("circle.pak");
|
||||
|
||||
auto dynamic = (ml::DynamicMesh) mesh;
|
||||
auto ind_data = mesh.cells();
|
||||
auto ind_flat = ind_data.reshaped();
|
||||
auto elements = ind_buf.upload(ind_flat.begin(), ind_flat.end(), GL_STATIC_DRAW);
|
||||
|
||||
GLuint vao;
|
||||
glCreateVertexArrays(1, &vao);
|
||||
// todo add <Dim, Rank> to DynamicMesh
|
||||
// need to do weird piping because dynamicmesh returns dynamic-sized matrix, VertexArray requires a static-sized matrix
|
||||
auto vert_data_dyn = mesh.points();
|
||||
Eigen::Ref<Eigen::Matrix3Xf> vert_data(vert_data_dyn);
|
||||
auto vert_flat = vert_data.colwise();
|
||||
vert_buf.upload(vert_flat.begin(), vert_flat.end(), GL_STATIC_DRAW);
|
||||
|
||||
GLuint vbo;
|
||||
glCreateBuffers(1, &vbo);
|
||||
auto mesh2 = ml::CubeMesh(0.5f);
|
||||
auto vert2_data_dyn = mesh2.points();
|
||||
Eigen::Ref<Eigen::Matrix3Xf> vert2_data(vert2_data_dyn);
|
||||
auto vert2_flat = vert2_data.colwise();
|
||||
vert2_buf.upload(vert2_flat.begin(), vert2_flat.end(), GL_STATIC_DRAW);
|
||||
|
||||
constexpr size_t point_scalar_size = sizeof(ml::DynamicMesh::PointsType::Scalar);
|
||||
constexpr size_t cell_scalar_size = sizeof(ml::DynamicMesh::CellsType::Scalar);
|
||||
auto mesh4d = ml::WireCubeMesh(4, 0.33f);
|
||||
|
||||
glNamedBufferData(
|
||||
vbo,
|
||||
(GLsizeiptr) (point_scalar_size * dynamic.points().size()),
|
||||
dynamic.points().data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
glEnableVertexArrayAttrib(vao, 0);
|
||||
glVertexArrayVertexBuffer(vao, 0,
|
||||
vbo, 0,
|
||||
(GLsizeiptr) (point_scalar_size * dynamic.points().rows())
|
||||
);
|
||||
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, 0);
|
||||
Buffer<GLuint> ind4d_buf;
|
||||
Buffer<Eigen::Vector4f> vert4d_buf;
|
||||
VertexArray<Eigen::Vector4f> vao4d(vert4d_buf);
|
||||
glVertexArrayElementBuffer(vao4d, ind4d_buf);
|
||||
|
||||
GLuint ibo;
|
||||
glCreateBuffers(1, &ibo);
|
||||
glGetError();
|
||||
glNamedBufferData(
|
||||
ibo,
|
||||
(GLsizeiptr) (cell_scalar_size * dynamic.cells().size()),
|
||||
dynamic.cells().data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
glVertexArrayElementBuffer(vao, ibo);
|
||||
auto ind4d_data = mesh4d.cells();
|
||||
auto ind4d_flat = ind4d_data.reshaped();
|
||||
auto elements4d = ind4d_buf.upload(ind4d_flat.begin(), ind4d_flat.end(), GL_STATIC_DRAW);
|
||||
|
||||
auto wire_mesh = ml::WireCubeMesh(4, 0.33f);
|
||||
auto wire_dynamic = (ml::DynamicMesh) wire_mesh;
|
||||
auto vert4d_data_dyn = mesh4d.points();
|
||||
Eigen::Ref<Eigen::Matrix4Xf> vert4d_data(vert4d_data_dyn);
|
||||
auto vert4d_flat = vert4d_data.colwise();
|
||||
vert4d_buf.upload(vert4d_flat.begin(), vert4d_flat.end(), GL_STATIC_DRAW);
|
||||
|
||||
GLuint wire_vao;
|
||||
glCreateVertexArrays(1, &wire_vao);
|
||||
VertexShader vs(std::ifstream("res/shaders/main.vert.glsl"));
|
||||
VertexShader vs4d(std::ifstream("res/shaders/4d.vert.glsl"));
|
||||
FragmentShader fs(std::ifstream("res/shaders/main.frag.glsl"));
|
||||
|
||||
GLuint wire_vbo;
|
||||
glCreateBuffers(1, &wire_vbo);
|
||||
|
||||
glNamedBufferData(
|
||||
wire_vbo,
|
||||
(GLsizeiptr) (point_scalar_size * wire_dynamic.points().size()),
|
||||
wire_dynamic.points().data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
glEnableVertexArrayAttrib(wire_vao, 0);
|
||||
glVertexArrayVertexBuffer(wire_vao, 0,
|
||||
wire_vbo, 0,
|
||||
(GLsizeiptr) (point_scalar_size * wire_dynamic.points().rows())
|
||||
);
|
||||
glVertexArrayAttribFormat(wire_vao, 0, 4, GL_FLOAT, GL_FALSE, 0);
|
||||
|
||||
GLuint wire_ibo;
|
||||
glCreateBuffers(1, &wire_ibo);
|
||||
glGetError();
|
||||
glNamedBufferData(
|
||||
wire_ibo,
|
||||
(GLsizeiptr) (cell_scalar_size * wire_dynamic.cells().size()),
|
||||
wire_dynamic.cells().data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
glVertexArrayElementBuffer(wire_vao, wire_ibo);
|
||||
|
||||
std::ifstream vs_file("res/shaders/main.vert.glsl");
|
||||
std::string vs_src(
|
||||
(std::istreambuf_iterator<char>(vs_file)),
|
||||
std::istreambuf_iterator<char>()
|
||||
);
|
||||
vs_file.close();
|
||||
const char *vs_str = vs_src.c_str();
|
||||
|
||||
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vs, 1, &vs_str, nullptr);
|
||||
glCompileShader(vs);
|
||||
|
||||
std::ifstream wire_vs_file("res/shaders/4d.vert.glsl");
|
||||
std::string wire_vs_src(
|
||||
(std::istreambuf_iterator<char>(wire_vs_file)),
|
||||
std::istreambuf_iterator<char>()
|
||||
);
|
||||
wire_vs_file.close();
|
||||
const char *wire_vs_str = wire_vs_src.c_str();
|
||||
|
||||
GLuint wire_vs = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(wire_vs, 1, &wire_vs_str, nullptr);
|
||||
glCompileShader(wire_vs);
|
||||
|
||||
std::ifstream fs_file("res/shaders/main.frag.glsl");
|
||||
std::string fs_src(
|
||||
(std::istreambuf_iterator<char>(fs_file)),
|
||||
std::istreambuf_iterator<char>()
|
||||
);
|
||||
fs_file.close();
|
||||
const char *fs_str = fs_src.c_str();
|
||||
|
||||
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fs, 1, &fs_str, nullptr);
|
||||
glCompileShader(fs);
|
||||
|
||||
GLuint pgm = glCreateProgram();
|
||||
glAttachShader(pgm, vs);
|
||||
glAttachShader(pgm, fs);
|
||||
glLinkProgram(pgm);
|
||||
|
||||
GLuint wire_pgm = glCreateProgram();
|
||||
glAttachShader(wire_pgm, wire_vs);
|
||||
glAttachShader(wire_pgm, fs);
|
||||
glLinkProgram(wire_pgm);
|
||||
|
||||
GLint link_status;
|
||||
glGetProgramiv(pgm, GL_LINK_STATUS, &link_status);
|
||||
if (!link_status) {
|
||||
std::cerr << "Program link failed." << std::endl;
|
||||
GLint vs_comp_status, fs_comp_status;
|
||||
glGetShaderiv(vs, GL_COMPILE_STATUS, &vs_comp_status);
|
||||
glGetShaderiv(fs, GL_COMPILE_STATUS, &fs_comp_status);
|
||||
std::cerr << "vs compiled: " << std::boolalpha << (bool) vs_comp_status << std::endl;
|
||||
std::cerr << "fs compiled: " << std::boolalpha << (bool) fs_comp_status << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
glGetProgramiv(wire_pgm, GL_LINK_STATUS, &link_status);
|
||||
if (!link_status) {
|
||||
std::cerr << "Wire program link failed." << std::endl;
|
||||
GLint vs_comp_status, fs_comp_status;
|
||||
glGetShaderiv(vs, GL_COMPILE_STATUS, &vs_comp_status);
|
||||
glGetShaderiv(fs, GL_COMPILE_STATUS, &fs_comp_status);
|
||||
std::cerr << "vs compiled: " << std::boolalpha << (bool) vs_comp_status << std::endl;
|
||||
std::cerr << "fs compiled: " << std::boolalpha << (bool) fs_comp_status << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
Program pgm(vs, fs);
|
||||
Program pgm4d(vs4d, fs);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
@@ -291,12 +203,12 @@ int run(GLFWwindow *window, ImGuiContext *context) {
|
||||
glUniform1f(1, (GLfloat) glfwGetTime());
|
||||
glUniformMatrix4fv(2, 1, false, proj.data());
|
||||
glUniformMatrix4fv(3, 1, false, state.rot.data());
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei) dynamic.cells().size(), GL_UNSIGNED_INT, nullptr);
|
||||
glDrawElements(GL_TRIANGLES, elements, GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
|
||||
glUseProgram(wire_pgm);
|
||||
glBindVertexArray(wire_vao);
|
||||
glUseProgram(pgm4d);
|
||||
glBindVertexArray(vao4d);
|
||||
glUniform4fv(0, 1, state.wf.data());
|
||||
glUniform1f(1, (GLfloat) glfwGetTime());
|
||||
glUniformMatrix4fv(2, 1, false, proj.data());
|
||||
@@ -320,8 +232,7 @@ int run(GLFWwindow *window, ImGuiContext *context) {
|
||||
}
|
||||
|
||||
glUniform4fv(0, 1, state.wf.data());
|
||||
glDrawElements(GL_LINES, (GLsizei) wire_dynamic.cells().size(), GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
glDrawElements(GL_LINES, elements4d, GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
|
||||
@@ -329,14 +240,6 @@ int run(GLFWwindow *window, ImGuiContext *context) {
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
glDeleteBuffers(1, &vbo);
|
||||
glDeleteBuffers(1, &ibo);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
|
||||
glDeleteBuffers(1, &wire_vbo);
|
||||
glDeleteBuffers(1, &wire_ibo);
|
||||
glDeleteVertexArrays(1, &wire_vao);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user