Browse Source

noice is generated on GPU

Kajetan Johannes Hammerle 3 years ago
parent
commit
ef132d6d0f
9 changed files with 185 additions and 49 deletions
  1. 33 40
      Game.cpp
  2. 7 2
      Game.h
  3. 78 0
      LayeredFramebuffer.cpp
  4. 25 0
      LayeredFramebuffer.h
  5. 13 2
      Main.cpp
  6. 1 1
      meson.build
  7. 12 0
      resources/noiceFragment.fs
  8. 12 0
      resources/noiceVertex.vs
  9. 4 4
      resources/vertex.vs

+ 33 - 40
Game.cpp

@@ -5,49 +5,40 @@
 #include "MarchingCubes.h"
 #include "gaming-core/utils/Array.h"
 #include "gaming-core/utils/List.h"
-#include "gaming-core/utils/Random.h"
 #include "gaming-core/utils/Utils.h"
 #include "gaming-core/wrapper/GL.h"
 
-static GLuint texture3d;
-static float tData[16][16][16];
-
-Game::Game(Shader& shader, Buttons& buttons, const Size& size)
-    : shader(shader), buttons(buttons), size(size),
-      frustum(60, 0.1f, 1000.0f, size), up(buttons.add(GLFW_KEY_SPACE, "Up")),
+Game::Game(Shader& shader, Shader& noiceShader, LayeredFramebuffer& buffer,
+           Buttons& buttons, const Size& size)
+    : shader(shader), noiceShader(noiceShader), noiceBuffer(buffer),
+      buttons(buttons), size(size), frustum(60, 0.1f, 1000.0f, size),
+      up(buttons.add(GLFW_KEY_SPACE, "Up")),
       down(buttons.add(GLFW_KEY_LEFT_SHIFT, "Down")),
       left(buttons.add(GLFW_KEY_A, "left")),
       right(buttons.add(GLFW_KEY_D, "right")),
       front(buttons.add(GLFW_KEY_W, "front")),
       back(buttons.add(GLFW_KEY_S, "back")) {
-    shader.use();
-
-    Random r(0);
-    for(int x = 0; x < 16; x++) {
-        for(int y = 0; y < 16; y++) {
-            for(int z = 0; z < 16; z++) {
-                float sinX = sinf(M_PI * x / 8.0f);
-                float cosY = cosf(M_PI * y / 8.0f);
-                float cosZ = cosf(M_PI * z / 8.0f);
-                tData[z][x][y] =
-                    (sinX * sinX + cosY * cosY + cosZ * cosZ) * (1.0f / 3.0f);
-            }
-        }
-    }
-
-    glGenTextures(1, &texture3d);
-    glBindTexture(GL_TEXTURE_3D, texture3d);
-    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
-    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
-    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
-    glTexImage3D(GL_TEXTURE_3D, 0, GL_R32F, 16, 16, 16, 0, GL_RED, GL_FLOAT,
-                 tData);
-    glActiveTexture(GL_TEXTURE0);
+    rectangleBuffer.setAttributes(Attributes().addFloat(2));
+    float data[6][2] = {{-1.0f, -1.0f}, {-1.0, 1.0}, {1.0, -1.0},
+                        {1.0f, 1.0f},   {-1.0, 1.0}, {1.0, -1.0}};
+    rectangleBuffer.setStaticData(sizeof(data), data);
+    noiceBuffer.bindTextureTo(0);
 }
 
 void Game::render(float lag) {
+    GL::setViewport(64, 64);
+    noiceShader.use();
+    noiceBuffer.bindAndClear();
+    for(int i = 0; i < 64; i++) {
+        noiceShader.setFloat("layer", i * (1.0f / 63.0f));
+        noiceBuffer.bindLayer(i);
+        rectangleBuffer.draw(6);
+    }
+
+    GL::setViewport(size.width, size.height);
+    shader.use();
+    GL::bindMainFramebuffer();
+    GL::clearFramebuffer();
     Vector3 interPos = Utils::interpolate(oldPosition, position, lag);
     shader.setMatrix("proj", frustum.updateProjection().getValues());
 
@@ -58,28 +49,30 @@ void Game::render(float lag) {
 
     shader.setMatrix("view", m.getValues());
 
-    vertexBuffer.drawPoints(0);
-    glDrawArrays(GL_POINTS, 0, 16 * 16 * 16);
+    noiceBuffer.bindTextureTo(0);
+    emptyBuffer.drawPoints(0);
+    glDrawArrays(GL_POINTS, 0, 64 * 64 * 64);
 }
 
 void Game::tick() {
     oldPosition = position;
+    const float speed = 2.5f;
     if(up.isDown()) {
-        position -= Vector3(0.0f, 0.5f, 0.0f);
+        position -= Vector3(0.0f, speed, 0.0f);
     }
     if(down.isDown()) {
-        position += Vector3(0.0f, 0.5f, 0.0f);
+        position += Vector3(0.0f, speed, 0.0f);
     }
     if(left.isDown()) {
-        position += Vector3(0.5f, 0.0f, 0.0f);
+        position += Vector3(speed, 0.0f, 0.0f);
     }
     if(right.isDown()) {
-        position -= Vector3(0.5f, 0.0f, 0.0f);
+        position -= Vector3(speed, 0.0f, 0.0f);
     }
     if(front.isDown()) {
-        position += Vector3(0.0f, 0.0f, 0.5f);
+        position += Vector3(0.0f, 0.0f, speed);
     }
     if(back.isDown()) {
-        position -= Vector3(0.0f, 0.0f, 0.5f);
+        position -= Vector3(0.0f, 0.0f, speed);
     }
 }

+ 7 - 2
Game.h

@@ -1,6 +1,7 @@
 #ifndef GAME_H
 #define GAME_H
 
+#include "LayeredFramebuffer.h"
 #include "gaming-core/input/Buttons.h"
 #include "gaming-core/math/Frustum.h"
 #include "gaming-core/utils/Size.h"
@@ -9,9 +10,12 @@
 
 class Game final {
     Shader& shader;
+    Shader& noiceShader;
+    LayeredFramebuffer& noiceBuffer;
     Buttons& buttons;
     const Size& size;
-    VertexBuffer vertexBuffer;
+    VertexBuffer rectangleBuffer;
+    VertexBuffer emptyBuffer;
     Frustum frustum;
 
     Button& up;
@@ -24,7 +28,8 @@ class Game final {
     Vector3 position;
 
 public:
-    Game(Shader& shader, Buttons& buttons, const Size& size);
+    Game(Shader& shader, Shader& noiceShader, LayeredFramebuffer& buffer,
+         Buttons& buttons, const Size& size);
 
     void render(float lag);
     void tick();

+ 78 - 0
LayeredFramebuffer.cpp

@@ -0,0 +1,78 @@
+#include <iostream>
+
+#include "LayeredFramebuffer.h"
+
+LayeredFramebuffer::LayeredFramebuffer(int width, int height, int depth)
+    : texture(0), buffer(0) {
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_3D, texture);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
+    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+    glTexImage3D(GL_TEXTURE_3D, 0, GL_R32F, width, height, depth, 0, GL_RED,
+                 GL_FLOAT, nullptr);
+
+    glGenFramebuffers(1, &buffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, buffer);
+
+    GLenum c = GL_COLOR_ATTACHMENT0;
+    glFramebufferTexture3D(GL_FRAMEBUFFER, c, GL_TEXTURE_3D, texture, 0, 0);
+    glDrawBuffers(1, &c);
+}
+
+LayeredFramebuffer::~LayeredFramebuffer() {
+    glDeleteFramebuffers(1, &buffer);
+    glDeleteTextures(1, &texture);
+}
+
+void LayeredFramebuffer::bindAndClear() {
+    glBindFramebuffer(GL_FRAMEBUFFER, buffer);
+    glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void LayeredFramebuffer::bindTextureTo(int unit) const {
+    glActiveTexture(GL_TEXTURE0 + unit);
+    glBindTexture(GL_TEXTURE_3D, texture);
+}
+
+void LayeredFramebuffer::bindLayer(int layer) {
+    glBindFramebuffer(GL_FRAMEBUFFER, buffer);
+    glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D,
+                           texture, 0, layer);
+}
+
+bool LayeredFramebuffer::hasError() const {
+    GLenum error = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if(error == GL_FRAMEBUFFER_COMPLETE) {
+        return false;
+    }
+    switch(error) {
+        case GL_FRAMEBUFFER_UNDEFINED:
+            std::cout << "undefined framebuffer\n";
+            return true;
+        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+            std::cout << "incomplete framebuffer attachment\n";
+            return true;
+        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+            std::cout << "incomplete missing framebuffer attachment\n";
+            return true;
+        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+            std::cout << "incomplete framebuffer draw buffer\n";
+            return true;
+        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+            std::cout << "incomplete framebuffer read buffer\n";
+            return true;
+        case GL_FRAMEBUFFER_UNSUPPORTED:
+            std::cout << "unsupported framebuffer\n";
+            return true;
+        case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+            std::cout << "incomplete framebuffer multisample\n";
+            return true;
+        case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+            std::cout << "incomplete framebuffer layer targets\n";
+            return true;
+    }
+    return "unknown error";
+}

+ 25 - 0
LayeredFramebuffer.h

@@ -0,0 +1,25 @@
+#ifndef LAYERED_FRAMEBUFFER_H
+#define LAYERED_FRAMEBUFFER_H
+
+#include <GL/glew.h>
+
+class LayeredFramebuffer final {
+    GLuint texture;
+    GLuint buffer;
+
+public:
+    LayeredFramebuffer(int width, int height, int depth);
+    ~LayeredFramebuffer();
+    LayeredFramebuffer(const LayeredFramebuffer&) = delete;
+    LayeredFramebuffer(LayeredFramebuffer&&) = delete;
+    LayeredFramebuffer& operator=(const LayeredFramebuffer&) = delete;
+    LayeredFramebuffer& operator=(LayeredFramebuffer&&) = delete;
+
+    void bindAndClear();
+    void bindTextureTo(int unit) const;
+    void bindLayer(int layer);
+
+    bool hasError() const;
+};
+
+#endif

+ 13 - 2
Main.cpp

@@ -1,4 +1,5 @@
 #include "Game.h"
+#include "LayeredFramebuffer.h"
 #include "gaming-core/input/Buttons.h"
 #include "gaming-core/utils/Clock.h"
 #include "gaming-core/wrapper/GL.h"
@@ -34,12 +35,23 @@ int main() {
         return 0;
     }
 
+    Shader noiceShader("resources/noiceVertex.vs",
+                       "resources/noiceFragment.fs");
+    if(noiceShader.hasError()) {
+        return 0;
+    }
+
+    LayeredFramebuffer buffer(64, 64, 64);
+    if(buffer.hasError()) {
+        return 0;
+    }
+
     Buttons buttons(window);
     Clock fps;
 
     window.show();
 
-    Game game(shader, buttons, size);
+    Game game(shader, noiceShader, buffer, buttons, size);
 
     GL::checkAndPrintError("setup error");
     GL::enableDepthTesting();
@@ -51,7 +63,6 @@ int main() {
         updateSize(window, size);
         game.render(static_cast<float>(lag) / nanosPerTick);
         window.swapBuffers();
-        GL::clearFramebuffer();
         lag += fps.update();
         while(lag >= nanosPerTick) {
             lag -= nanosPerTick;

+ 1 - 1
meson.build

@@ -3,9 +3,9 @@ project('spg project', 'cpp')
 sources = ['Main.cpp',
     'Game.cpp',
     'MarchingCubes.cpp',
+    'LayeredFramebuffer.cpp',
     'gaming-core/utils/Size.cpp',
     'gaming-core/utils/Clock.cpp',
-    'gaming-core/utils/Random.cpp',
     'gaming-core/wrapper/GLFW.cpp',
     'gaming-core/wrapper/GL.cpp',
     'gaming-core/wrapper/GLEW.cpp',

+ 12 - 0
resources/noiceFragment.fs

@@ -0,0 +1,12 @@
+#version 430
+
+in vec3 varPosition;
+
+out float noice;
+
+void main(void) {
+    float sinX = sin(varPosition.x * 5.8905);
+    float cosY = cos(varPosition.y * 5.8905);
+    float cosZ = cos(varPosition.z * 5.8905);
+    noice = (sinX * sinX + cosY * cosY + cosZ * cosZ) * (1.0f / 3.0f);
+}

+ 12 - 0
resources/noiceVertex.vs

@@ -0,0 +1,12 @@
+#version 430
+
+layout (location = 0) in vec2 position;
+
+uniform float layer;
+
+out vec3 varPosition;
+
+void main(void) { 
+    gl_Position = vec4(position, layer, 1.0);
+    varPosition = vec3(position, layer);
+}

+ 4 - 4
resources/vertex.vs

@@ -5,13 +5,13 @@ layout (binding = 0) uniform sampler3D samp;
 out vec3 varTexture;
 out int varIndex;
 
-const float step = 1.0 / 15.0;
+const float step = 1.0 / 63.0;
 
 void main(void) { 
     int id = gl_VertexID;
-    int x = id & 0xF;
-    int y = (id >> 4) & 0xF;
-    int z = (id >> 8) & 0xF;
+    int x = id & 0x3F;
+    int y = (id >> 6) & 0x3F;
+    int z = (id >> 12) & 0x3F;
 
     vec3 xyz = vec3(x, y, z);
     gl_Position = vec4(xyz, 1.0);