diff --git a/CMakeLists.txt b/CMakeLists.txt index a9b3af8..0028c7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(main) +project(hopf) set(CMAKE_CXX_STANDARD 17) diff --git a/main/shaders/main.frag b/main/shaders/main.frag index 234034d..d2e268c 100644 --- a/main/shaders/main.frag +++ b/main/shaders/main.frag @@ -1,7 +1,17 @@ #version 440 +#define PI 3.14159 + +in vec4 pos; +in vec4 pos4; +in vec4 pos3; + out vec4 color; void main() { - color = vec4(1); + float light = -pos3.y / 10 + .5; + + vec3 col = vec3(1); + + color = vec4(col * light, 1); } \ No newline at end of file diff --git a/main/shaders/main.geom b/main/shaders/main.geom index 78bda9b..cede560 100644 --- a/main/shaders/main.geom +++ b/main/shaders/main.geom @@ -1,31 +1,47 @@ #version 440 -#define CIRCLE_RES 256 +#define CIRCLE_RES 64 #define PI 3.14159 layout(points) in; layout(line_strip, max_vertices=CIRCLE_RES) out; +layout(binding=1) uniform Matrices { + mat4 proj; + mat4 model; +}; + in float xi_[]; in float eta_[]; -layout(binding=1) uniform Matrices { - mat4 proj; -}; +out vec4 pos; +out vec4 pos4; +out vec4 pos3; void main(){ for(int k = 0; k <= CIRCLE_RES; k++) { - vec2 xi = vec2(xi_[0], 4 * PI * k / CIRCLE_RES); + vec2 xi = vec2(xi_[0], 4 * PI * k / (CIRCLE_RES - 1)); float eta = eta_[0]; + // todo parameterize the projected circle so there aren't jagged edges. + // should be smooth at <=32 segments, not just 128+ float x = cos((xi.y + xi.x) / 2) * sin(eta); float y = sin((xi.y + xi.x) / 2) * sin(eta); float z = cos((xi.y - xi.x) / 2) * cos(eta); float w = sin((xi.y - xi.x) / 2) * cos(eta); - vec4 pos = vec4(x / (1 - w), y / (1 - w), z / (1 - w), 1); + pos = vec4(x, y, z, w); + pos4 = model * pos; + pos3 = vec4(pos4.xyz / (1 - pos4.w), 1); + gl_Position = proj * pos3; + + if (length(gl_Position) > 4) { + EndPrimitive(); + continue; + } - gl_Position = proj * pos; EmitVertex(); } + + EndPrimitive(); } \ No newline at end of file diff --git a/main/src/main.cpp b/main/src/main.cpp index 6d2b899..6a3562d 100644 --- a/main/src/main.cpp +++ b/main/src/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #define PI 3.14159f @@ -107,8 +108,12 @@ namespace util { } struct HopfCircle { - float xi; - float eta; + float xi; // longitude + float eta; // latitude + + HopfCircle(float xi, float eta) : xi(xi), eta(eta) {} + + HopfCircle() : HopfCircle(0, 0) {} }; struct State { @@ -120,30 +125,36 @@ struct State { std::vector circles{}; - explicit State(GLFWwindow *window) { + float t = 0; + + void regen() { + circles.clear(); + const int N = 32; - for (int k = 0; k < N; ++k) { - circles.push_back({2 * PI * k / N, 0.025}); - circles.push_back({2 * PI * k / N, PI / 2 - 0.025}); + const int M = 4; + const float PAD = 0.0125; - circles.push_back({2 * PI * k / N, 0.3f}); - circles.push_back({2 * PI * k / N, 0.4f}); - circles.push_back({2 * PI * k / N, 0.5f}); - - circles.push_back({2 * PI * k / N, 1.1f}); - circles.push_back({2 * PI * k / N, 1.2f}); - circles.push_back({2 * PI * k / N, 1.3f}); + for (int k = 0; k <= N; ++k) { + for (int j = 0; j <= M; ++j) { + float xi = 2 * PI * k / N; + float eta = (PI / 2 - 2 * PAD) * j / M + PAD; + circles.emplace_back(xi, eta); + } } + glBindBuffer(GL_ARRAY_BUFFER, vbo); + util::bufferData(GL_ARRAY_BUFFER, circles, GL_STREAM_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + explicit State(GLFWwindow *window) { printf("vendor: %s\nrenderer: %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER)); glGenBuffers(1, &vbo); glGenBuffers(1, &ubo); glGenVertexArrays(1, &vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - util::bufferData(GL_ARRAY_BUFFER, circles, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + regen(); glBindBufferBase(GL_UNIFORM_BUFFER, ubo_bp, ubo); @@ -180,12 +191,25 @@ struct State { glfwGetFramebufferSize(window, &w, &h); auto ar = (float) w / h; + t += dt; + + float c = std::cos(t / 8); + float s = std::sin(t / 8); + + float c_ = std::cos(3.f / 8); + float s_ = std::sin(3.f / 8); + glBindBuffer(GL_UNIFORM_BUFFER, ubo); util::bufferData(GL_UNIFORM_BUFFER, { 1.f / 4 / ar, 0, 0, 0, 0, 0, 1.f / 10, 0, 0, 1.f / 4, 0, 0, - 0, 0, 0, 1 + 0, 0, 0, 1, + + c, 0, 0, s, + 0, c_, s_, 0, + 0, -s_, c_, 0, + -s, 0, 0, c }, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } @@ -195,12 +219,13 @@ struct State { glfwGetFramebufferSize(window, &w, &h); glViewport(0, 0, w, h); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(prog); glBindVertexArray(vao); + glEnable(GL_DEPTH_TEST); glPointSize(5); - glLineWidth(3); + glLineWidth(5); glDrawArrays(GL_POINTS, 0, (unsigned) circles.size()); glBindVertexArray(0); glUseProgram(0);