diff --git a/main/include/util.h b/main/include/util.h index 29d6df0..70da194 100644 --- a/main/include/util.h +++ b/main/include/util.h @@ -5,14 +5,109 @@ #ifndef HOPF_FIBRATION_UTIL_H #define HOPF_FIBRATION_UTIL_H -#include +#include -void hello() { - printf("Hello there.\n"); -} +#include +#include +#include +#include -void general() { - printf("General Kenobi.\n"); +namespace util { + template + void bufferData(GLenum target, std::vector data, GLenum usage) { + glBufferData(target, data.size() * sizeof(T), &data.front(), usage); + } + + template + void bufferData(GLenum target, T &data, GLenum usage) { + glBufferData(target, sizeof(T), &data, usage); + } + + std::string readFile(const std::string &path) { + std::ifstream file(path); + if (!file) return std::string(); + + file.ignore(std::numeric_limits::max()); + auto size = file.gcount(); + + if (size > 0x10000) return std::string(); + + file.clear(); + file.seekg(0, std::ios_base::beg); + + std::stringstream sstr; + sstr << file.rdbuf(); + file.close(); + + return sstr.str(); + } + + void shaderFiles(GLuint shader, std::vector &paths) { + std::vector strs; + std::vector c_strs; + + for (const auto &path : paths) strs.push_back(readFile(path)); + for (const auto &str:strs) c_strs.push_back(str.c_str()); + + glShaderSource(shader, (GLsizei) c_strs.size(), &c_strs.front(), nullptr); + } + + std::string shaderInfoLog(GLuint shader) { + GLint log_len; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len); + char log[log_len]; + glGetShaderInfoLog(shader, log_len, nullptr, log); + return std::string(log); + } + + std::string programInfoLog(GLuint program) { + GLint log_len; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len); + char log[log_len]; + glGetProgramInfoLog(program, log_len, nullptr, log); + return std::string(log); + } + + GLuint buildShader(GLenum kind, const std::string &name, std::vector paths) { + GLuint shader = glCreateShader(kind); + shaderFiles(shader, paths); + + glCompileShader(shader); + + GLint comp; + glGetShaderiv(shader, GL_COMPILE_STATUS, &comp); + if (!comp) { + std::string log = shaderInfoLog(shader); + fprintf(stderr, "SHADER ERROR (%s):\n%s", name.c_str(), log.c_str()); + glDeleteShader(shader); + return 0; + } + + return shader; + } + + GLuint buildProgram(bool separable, const std::string &name, std::vector shaders) { + GLuint program = glCreateProgram(); + + if (separable) + glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE); + + for (GLuint shader : shaders) + glAttachShader(program, shader); + + glLinkProgram(program); + + GLint link; + glGetProgramiv(program, GL_LINK_STATUS, &link); + if (!link) { + std::string log = programInfoLog(program); + fprintf(stderr, "PROGRAM ERROR (%s):\n%s", name.c_str(), log.c_str()); + glDeleteProgram(program); + return 0; + } + + return program; + } } #endif //HOPF_FIBRATION_UTIL_H diff --git a/main/shaders/main.frag b/main/shaders/main.frag new file mode 100644 index 0000000..234034d --- /dev/null +++ b/main/shaders/main.frag @@ -0,0 +1,7 @@ +#version 440 + +out vec4 color; + +void main() { + color = vec4(1); +} \ No newline at end of file diff --git a/main/shaders/main.vert b/main/shaders/main.vert index e69de29..6eca279 100644 --- a/main/shaders/main.vert +++ b/main/shaders/main.vert @@ -0,0 +1,7 @@ +#version 440 + +in vec4 iPos; + +void main(){ + gl_Position = vec4(iPos.xyz, 1); +} \ No newline at end of file diff --git a/main/src/main.cpp b/main/src/main.cpp index 8249cd9..fca5219 100644 --- a/main/src/main.cpp +++ b/main/src/main.cpp @@ -5,25 +5,124 @@ #include #include +#define GLM_FORCE_SWIZZLE +#define GLM_ENABLE_EXPERIMENTAL + +#include +#include + #include +#include #include +#include + +#include "util.h" + +#define RES_MAJOR 128 +#define RES_MINOR 8 + +#define PI (float) (M_PI) struct State { - void deinit(GLFWwindow *window) { + GLuint vao{}; + GLuint vbo{}; + GLuint ibo{}; + GLuint prog{}; + + std::vector verts{}; + std::vector inds{}; + + void add_ring(float xi, float eta) { + std::vector _verts; + std::vector _inds; + + for (int i = 0; i < RES_MAJOR; ++i) { + auto nu = 4 * PI * i / RES_MAJOR; + + auto v = glm::vec4( // todo find parameterization given quaternion + cos((nu + xi) / 2) * sin(eta), + sin((nu + xi) / 2) * sin(eta), + cos((nu - xi) / 2) * cos(eta), + sin((nu - xi) / 2) * cos(eta) + ); + + _verts.emplace_back(v.xzy() / (1.f - v.w), 1); + } + + _inds.push_back(0); + for (unsigned i = 1; i < RES_MAJOR; ++i) { + _inds.push_back(i); + _inds.push_back(i); + } + _inds.push_back(0); + + auto offset = (unsigned) verts.size(); + + for (auto v: _verts) + verts.push_back(v); + for (auto i : _inds) + inds.push_back(offset + i); } - void init(GLFWwindow *window) { + void init(GLFWwindow *window) { + GLuint vs = util::buildShader(GL_VERTEX_SHADER, "vs", {"shaders/main.vert"}); + GLuint fs = util::buildShader(GL_FRAGMENT_SHADER, "fs", {"shaders/main.frag"}); + prog = util::buildProgram(false, "prog", {vs, fs}); + + for (int i = 0; i < 32; ++i) { + for (int j = 0; j <= 4; ++j) { + float xi = 2 * PI * i / 32; + float eta = PI / 2 * j / 4; + add_ring(xi, eta); + } + } + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + util::bufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenBuffers(1, &ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + util::bufferData(GL_ELEMENT_ARRAY_BUFFER, inds, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + GLint pos = glGetAttribLocation(prog, "iPos"); + if (pos >= 0) { + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glVertexAttribPointer((GLuint) pos, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), nullptr); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + glBindVertexArray(0); } void render(GLFWwindow *window, float dt, int frame) { + int w, h; + glfwGetFramebufferSize(window, &w, &h); + glViewport(0, 0, w, h); + glClear(GL_COLOR_BUFFER_BIT); + + glBindVertexArray(vao); + glUseProgram(prog); + glDrawElements(GL_LINES, (GLsizei) inds.size(), GL_UNSIGNED_INT, 0); + + glfwSwapBuffers(window); } void update(GLFWwindow *window, float dt, int frame) { } + + void deinit(GLFWwindow *window) { + + } }; void run(State *state, const std::string &title) {