| ... | ... | @@ -0,0 +1,111 @@ | 
| 1 | +#include <cstddef> | |
| 2 | +#include <string> | |
| 3 | +#include <vector> | |
| 4 | + | |
| 5 | +#include <GL/glew.h> | |
| 6 | +#include <glm/glm.hpp> | |
| 7 | + | |
| 8 | +#include <glfbo3d.hpp> | |
| 9 | +#include <glshader.hpp> | |
| 10 | +#include <gltest.hpp> | |
| 11 | + | |
| 12 | + | |
| 13 | +constexpr auto size = 256; | |
| 14 | +constexpr auto fbo_size_divisor = 2; | |
| 15 | + | |
| 16 | + | |
| 17 | +static void draw(GLuint texture0) | |
| 18 | +{ | |
| 19 | + glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
| 20 | + glViewport(0, 0, size, size); | |
| 21 | + glActiveTexture(GL_TEXTURE0 + 0); | |
| 22 | + glBindTexture(GL_TEXTURE_3D, texture0); | |
| 23 | +    auto draw = Shader({ | |
| 24 | + "draw.vert", | |
| 25 | + "draw.geom", "quad.geom", | |
| 26 | + "draw.frag", | |
| 27 | + }); | |
| 28 | + draw | |
| 29 | + .use() | |
| 30 | +        .uniform("texture0", 0); | |
| 31 | + auto t = 0.0F; | |
| 32 | + gltest_set_time(t); | |
| 33 | + while ((t = gltest_get_time()) < 1) | |
| 34 | +    { | |
| 35 | + draw | |
| 36 | +            .uniform("z", t * 2 - 1, false) | |
| 37 | + .validate(); | |
| 38 | + glDrawArrays(GL_TRIANGLES, 0, 3); | |
| 39 | + gltest_swap_buffers(); | |
| 40 | + } | |
| 41 | +} | |
| 42 | + | |
| 43 | + | |
| 44 | +GLTEST(3, 2, size, size, glfbo3d) | |
| 45 | +{ | |
| 46 | + // Settings. | |
| 47 | +    Shader::root("tests/shaders"); | |
| 48 | + auto fbo_size = glm::ivec3(size / fbo_size_divisor); | |
| 49 | + | |
| 50 | + // Create and bind vertex array. | |
| 51 | +    auto vertex_array = GLuint{}; | |
| 52 | + glGenVertexArrays(1, &vertex_array); | |
| 53 | + glBindVertexArray(vertex_array); | |
| 54 | + | |
| 55 | + // Create texture. | |
| 56 | +    auto texture0 = GLuint{}; | |
| 57 | + glGenTextures(1, &texture0); | |
| 58 | + glBindTexture(GL_TEXTURE_3D, texture0); | |
| 59 | + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 60 | + glTexImage3D( | |
| 61 | + GL_TEXTURE_3D, 0, GL_RGBA32F, | |
| 62 | + fbo_size.x, fbo_size.y, fbo_size.z, 0, | |
| 63 | + GL_RGBA, GL_FLOAT, nullptr | |
| 64 | + ); | |
| 65 | + | |
| 66 | + // Create framebuffer. | |
| 67 | +    auto framebuffer = GLuint{}; | |
| 68 | + glGenFramebuffers(1, &framebuffer); | |
| 69 | + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); | |
| 70 | + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture0, 0); | |
| 71 | + | |
| 72 | + // Set with CPU and draw. | |
| 73 | +    auto data = std::vector<glm::vec4>{}; | |
| 74 | + data.reserve((size_t)(fbo_size.x * fbo_size.y * fbo_size.z)); | |
| 75 | + for (int z = 0; z < fbo_size.z; ++z) | |
| 76 | + for (int y = 0; y < fbo_size.y; ++y) | |
| 77 | + for (int x = 0; x < fbo_size.x; ++x) | |
| 78 | + data.emplace_back( | |
| 79 | + x / (fbo_size.x / 8) % 2 ^ // NOLINT | |
| 80 | + y / (fbo_size.y / 4) % 2 ^ // NOLINT | |
| 81 | + z / (fbo_size.z / 2) % 2 // NOLINT | |
| 82 | + ); | |
| 83 | + glBindTexture(GL_TEXTURE_3D, texture0); | |
| 84 | + glTexSubImage3D( | |
| 85 | + GL_TEXTURE_3D, 0, | |
| 86 | + 0, 0, 0, fbo_size.x, fbo_size.y, fbo_size.z, | |
| 87 | + GL_RGBA, GL_FLOAT, &data[0] | |
| 88 | + ); | |
| 89 | + draw(texture0); | |
| 90 | + | |
| 91 | + // Set with GPU and draw. | |
| 92 | + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); | |
| 93 | + glViewport(0, 0, fbo_size.x, fbo_size.y); | |
| 94 | + auto instance_count = fbo_size.z; | |
| 95 | +    auto set = Shader({ | |
| 96 | + "set.vert", | |
| 97 | + "set.geom", "quad.geom", | |
| 98 | + "set.frag", | |
| 99 | + }); | |
| 100 | + set | |
| 101 | + .use() | |
| 102 | +        .uniform("instance_count", instance_count) | |
| 103 | + .validate(); | |
| 104 | + glDrawArraysInstanced(GL_TRIANGLES, 0, 3, instance_count); | |
| 105 | + draw(texture0); | |
| 106 | + | |
| 107 | + // Delete. | |
| 108 | + glDeleteFramebuffers(1, &framebuffer); | |
| 109 | + glDeleteTextures(1, &texture0); | |
| 110 | + glDeleteVertexArrays(1, &vertex_array); | |
| 111 | +} |