diff --git a/vis/CMakeLists.txt b/vis/CMakeLists.txt index 12f2dd9..c1dfe52 100644 --- a/vis/CMakeLists.txt +++ b/vis/CMakeLists.txt @@ -12,3 +12,8 @@ add_executable(vis src/main.cpp) target_include_directories(vis PRIVATE include) target_link_libraries(vis PRIVATE tc glad glm glfw) add_dependencies(vis shaders) + +add_executable(test src/test.cpp) +target_include_directories(test PRIVATE include) +target_link_libraries(test PRIVATE tc glad glm glfw) +add_dependencies(test shaders) diff --git a/vis/include/cgl/render.hpp b/vis/include/cgl/render.hpp index fe8b56c..b115647 100644 --- a/vis/include/cgl/render.hpp +++ b/vis/include/cgl/render.hpp @@ -46,6 +46,12 @@ namespace cgl { void put(const std::vector &data, GLenum usage = GL_STATIC_DRAW) { glNamedBufferData(id, sizeof(T) * data.size(), &data[0], usage); } + + void bound(GLenum target, const std::function &action) const { + glBindBuffer(target, id); + action(); + glBindBuffer(target, 0); + } }; template @@ -248,8 +254,23 @@ namespace cgl { glUseProgramStages(id, GL_COMPUTE_SHADER_BIT, pgm); return *this; } + + void bound(const std::function &action) const { + glBindProgramPipeline(id); + action(); + glBindProgramPipeline(0); + } }; + namespace sh { + using vert = shader; + using tcs = shader; + using tes = shader; + using geom = shader; + using frag = shader; + using comp = shader; + } + namespace pgm { using vert = shaderprogram; using tcs = shaderprogram; @@ -258,4 +279,34 @@ namespace cgl { using frag = shaderprogram; using comp = shaderprogram; } + + class vertexarray { + GLuint id{}; + + public: + vertexarray() { + glCreateVertexArrays(1, &id); + } + + vertexarray(vertexarray &) = delete; + + vertexarray(vertexarray &&o) noexcept { + id = std::exchange(o.id, 0); + } + + ~vertexarray() { + glDeleteVertexArrays(1, &id); + id = 0; + } + + operator GLuint() const { + return id; + } + + void bound(const std::function &action) const { + glBindVertexArray(id); + action(); + glBindVertexArray(0); + } + }; } diff --git a/vis/shaders/test/direct.glsl b/vis/shaders/test/direct.glsl new file mode 100644 index 0000000..5fbc428 --- /dev/null +++ b/vis/shaders/test/direct.glsl @@ -0,0 +1,16 @@ +#version 430 + +layout(std140, binding=0) uniform globals { + mat4 proj; + float time; +}; + +layout(location=0) in vec4 pos; + +out gl_PerVertex{ + vec4 gl_Position; +}; + +void main() { + gl_Position = proj * pos; +} diff --git a/vis/shaders/test/white.glsl b/vis/shaders/test/white.glsl new file mode 100644 index 0000000..24449f9 --- /dev/null +++ b/vis/shaders/test/white.glsl @@ -0,0 +1,15 @@ +#version 430 + +layout(std140, binding=0) uniform globals { + mat4 proj; + float time; +}; + +out vec4 diffuse; + +void main() { + vec3 hue = vec3(time) + vec3(0, 2, 4) * 3.1415 / 6.0; + vec3 rgb = cos(hue) * 0.3 + vec3(0.7); + + diffuse = vec4(rgb, 1); +} diff --git a/vis/src/test.cpp b/vis/src/test.cpp new file mode 100644 index 0000000..825b514 --- /dev/null +++ b/vis/src/test.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include + +#include + +#include + +#include "util.hpp" +#include "mirror.hpp" +#include "geometry.hpp" + +#include + +#ifdef _WIN32 +extern "C" { +__attribute__((unused)) __declspec(dllexport) int NvOptimusEnablement = 0x00000001; +} +#endif + +struct globals { + glm::mat4 proj = glm::identity(); + float time = 0; +}; + +void run(GLFWwindow *window) { + auto direct = cgl::pgm::vert::file("shaders/test/direct.glsl"); + auto white = cgl::pgm::frag::file("shaders/test/white.glsl"); + + auto pipe = cgl::pipeline(); + pipe.stage(direct).stage(white); + + auto vbo = cgl::buffer({ + -0.5, +0.866, 0, 1, + -0.5, -0.866, 0, 1, + +1.0, +0.000, 0, 1, + }); + + auto global_ubo = cgl::buffer(); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, global_ubo); + + auto vao = cgl::vertexarray(); + vao.bound([&]() { + vbo.bound(GL_ARRAY_BUFFER, [&]() { + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, nullptr); + }); + }); + + while (!glfwWindowShouldClose(window)) { + int width, height; + glfwGetFramebufferSize(window, &width, &height); + glViewport(0, 0, width, height); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + auto aspect = (float) width / (float) height; + globals data; + data.time = (float) glfwGetTime(); + data.proj = glm::ortho(-aspect, aspect, -1.0f, 1.0f); + global_ubo.put(data); + + pipe.bound([&]() { + vao.bound([&]() { + glDrawArrays(GL_TRIANGLES, 0, 3); + }); + }); + + glfwSwapBuffers(window); + + 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; +}