First pass at PBO
authorLuke Lau <luke_lau@icloud.com>
Mon, 13 Apr 2020 13:23:44 +0000 (14:23 +0100)
committerLuke Lau <luke_lau@icloud.com>
Mon, 13 Apr 2020 13:23:44 +0000 (14:23 +0100)
Turned off because its actually a bit slower

clouds.cpp
program.cpp
program.hpp
simulation.cpp
simulation.h

index 3ed3b10c91cc32a10509483bcb653b6a2f35468f..f6c0083837e15611cc628e5316e3c55fd63cd4d5 100644 (file)
@@ -7,6 +7,7 @@
 #include <cmath>
 #include <cstdio>
 #include <cstdlib>
+#include <chrono>
 #include <glm/ext.hpp>
 #include <glm/glm.hpp>
 #include <sys/stat.h>
 
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
 
-enum Mode {
-  render,
-  debugContDist,
-  debugColor,
-  debugProbExt,
-  debugProbAct
-};
+enum Mode { render, debugContDist, debugColor, debugProbExt, debugProbAct };
 Mode curMode = render;
 
 using namespace std;
@@ -68,7 +63,7 @@ void precalculateBillboardTextures() {
         float r = distance(vec2(i, j), vec2(16, 16)) / 16;
         float density = (float)d / NQ;
         data[i + j * 32] =
-            1 - (density * 0.7 * (metaballField(r) / normalizationFactor));
+            1 - (3 * density * 0.7 * (metaballField(r) / normalizationFactor));
       }
     }
 
@@ -82,7 +77,6 @@ void precalculateBillboardTextures() {
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 32, 32, 0, GL_RED, GL_FLOAT, data);
     glGenerateMipmap(GL_TEXTURE_2D); // required, otherwise texture is blank
 
-
     fprintf(stderr, "\r%i out of %i densities calculated%s", d + 1, NQ,
             d == NQ - 1 ? "\n" : "");
   }
@@ -115,9 +109,7 @@ void calculateMetaballs() {
   for (int i = 0; i < CLOUD_DIM_X; i++) {
     for (int j = 0; j < CLOUD_DIM_Y; j++) {
       for (int k = 0; k < CLOUD_DIM_Z; k++) {
-        Metaball m = {
-            vec3(i, j, k) * vec3(cloudScale),
-            {i, j, k} };
+        Metaball m = {vec3(i, j, k) * vec3(cloudScale), {i, j, k}};
         /* m.pos = (m.pos * vec3(2)) - (cloudScale / 2); */
         m.pos -= vec3(CLOUD_DIM_X, CLOUD_DIM_Y, CLOUD_DIM_Z) * cloudScale / 2.f;
         m.d = cs.q[i][j][k];
@@ -127,20 +119,22 @@ void calculateMetaballs() {
     }
   }
   /* for (int z = 0; z < CLOUD_DIM_Z; z++) */
-  /*   metaballs[32 * CLOUD_DIM_Y * CLOUD_DIM_Z + 32 * CLOUD_DIM_Z + z].d = 1; */
+  /*   metaballs[32 * CLOUD_DIM_Y * CLOUD_DIM_Z + 32 * CLOUD_DIM_Z + z].d = 1;
+   */
 }
 
 vec3 sunPos = {0, 10, 0}, sunDir = {0, -1, 0};
-size_t sunColorIdx = 0;
-std::array<vec4, 2> sunColors = {
-  vec4(1,1,1,1),
-  vec4(0.988,0.309,0.677,1)
-};
-vec3 camPos = {0, 0, -5}, viewPos = {0, 0, 0};
+size_t envColorIdx = 0;
+// First color is sun color, second is sky color
+std::array<std::array<vec4, 2>, 3> envColors{
+    {{vec4(1, 1, 1, 1), vec4(0.9, 1, 1, 1)},
+     {vec4(0.939, 0.632, 0.815, 1), vec4(0.9, 1, 1, 1)},
+     {vec4(0.999, 0.999, 0.519, 1), vec4(0.981, 0.667, 0.118, 1)}}};
+vec3 camPos = {0, 0, -3}, viewPos = {0, 0, 0};
 mat4 proj; // projection matrix
 mat4 view; // view matrix
 float znear = 0.001, zfar = 1000;
-float width = 600, height = 400;
+float width = 512, height = 512;
 float aspect = width / height;
 
 void setProjectionAndViewUniforms(GLuint progId) {
@@ -166,7 +160,11 @@ mat4 faceView(mat4 m) {
   return m;
 }
 
-GLuint attenuationTex;
+#ifdef PBO
+const int numPbos = 64;
+GLuint pboBufs[numPbos];
+GLbyte sink[1000 * 1000 * 4];
+#endif
 
 void shadeClouds() {
   glDisable(GL_DEPTH_TEST);
@@ -185,16 +183,16 @@ void shadeClouds() {
   GLuint modelLoc = glGetUniformLocation(bbProg, "model");
   glUniform1i(glGetUniformLocation(bbProg, "debug"), 0);
 
-  /* GLuint pboBuf; */
-  /* glGenBuffers(1, &pboBuf); */
-  /* glBindBuffer(GL_PIXEL_PACK_BUFFER, pboBuf); */
-
   /* glViewport(0, 0, shadeWidth, shadeHeight); */
 
+#ifdef PBO
+  int pboIdx = 0;
+#endif
 
+  auto begin_time = std::chrono::system_clock::now();
   size_t i = 0;
   for (auto &k : metaballs) {
-    fprintf(stderr, "\rShading cloud %lu/%lu...", i++, metaballs.size());
+    fprintf(stderr, "\rShading metaball %lu/%lu...", i++, metaballs.size());
     // place the billboard at the center of k
     mat4 model = translate(mat4(1), k.pos);
 
@@ -225,22 +223,47 @@ void shadeClouds() {
     // 1. First get position in opengl screen space: from [-1,1]
     // 2. Normalize to [0,1]
     // 3. Multiply by (width * height)
-    vec2 screenPos =
+    ivec2 screenPos =
         ((vec2(proj * view * model * vec4(0, 0, 0, 1)) + vec2(1)) / vec2(2)) *
         vec2(width, height);
     vec4 pixel;
+
+#ifndef PBO
     // TODO: This is a huge bottleneck
-    glReadPixels(screenPos.x, screenPos.y, 1, 1, GL_RGBA, GL_FLOAT,
-                 value_ptr(pixel));
+    glReadPixels(screenPos.x, screenPos.y, 1, 1, GL_RGBA, GL_FLOAT, &pixel);
+#else
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, pboBufs[pboIdx]);
+    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
+                 NULL);
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, pboBufs[(pboIdx + 1) % numPbos]);
+    GLuint offset = screenPos.x * 4 + screenPos.y * (int)width * 4;
+    ivec4 *src = (ivec4 *)glMapBufferRange(GL_PIXEL_PACK_BUFFER, offset, 4, GL_MAP_READ_BIT);
+    checkError();
+    if (src) {
+      ivec4 t = src[(int)screenPos.x + (int)screenPos.y * (int)width];
+      pixel = vec4(t) / vec4(255.f);
+    }
+    glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+
+    pboIdx = (pboIdx + 1) % numPbos;
+
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+#endif
     
     // Multiply the pixel value by the sunlight color.
-    pixel *= sunColors[sunColorIdx % sunColors.size()];
+    pixel *= envColors[envColorIdx][0];
 
     // Store the color into an array C[k] as the color of the billboard.
     k.col = pixel;
   }
   fprintf(stderr, "\n");
 
+  auto elapsed = std::chrono::system_clock::now() - begin_time;
+  double elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double> >(elapsed).count();
+  fprintf(stderr, "time with pbo: %f\n", elapsed_seconds);
+
   saveFBO();
   checkError();
   /* glViewport(0, 0, width, height); */
@@ -253,7 +276,8 @@ void renderObject() {
   mat4 model = translate(mat4(1), sunPos);
   /* model = lookAt(sunPos, sunPos + sunDir, {0, 1, 0}) * model; */
   model = translate(scale(translate(model, -sunPos), vec3(0.3)), sunPos);
-  glUniformMatrix4fv(glGetUniformLocation(sunProg, "model"), 1, GL_FALSE, glm::value_ptr(model));
+  glUniformMatrix4fv(glGetUniformLocation(sunProg, "model"), 1, GL_FALSE,
+                     glm::value_ptr(model));
   glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
 }
 
@@ -273,7 +297,8 @@ void renderClouds() {
   glBlendFunc(GL_ONE, GL_SRC_ALPHA);
 
   /* glBlendColor(1.f,1.f,1.f,1.f); */
-  /* glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_SRC_ALPHA); */
+  /* glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_SRC_ALPHA);
+   */
 
   glActiveTexture(GL_TEXTURE0);
   glUniform1i(glGetUniformLocation(bbProg, "tex"), 0);
@@ -304,12 +329,16 @@ void renderClouds() {
     // Don't modulate it -- blend it
     glUniform1i(glGetUniformLocation(bbProg, "modulate"), 0);
 
-    glUniform1f(glGetUniformLocation(bbProg, "debugColor"), curMode == debugColor);
+    glUniform1f(glGetUniformLocation(bbProg, "debugColor"),
+                curMode == debugColor);
     if (curMode != render) {
       float debugVal = 0;
-      if (curMode == debugContDist) debugVal = k.d;
-      else if (curMode == debugProbAct) debugVal = cs.p_act[k.coords.x][k.coords.y][k.coords.z];
-      else if (curMode == debugProbExt) debugVal = cs.p_ext[k.coords.x][k.coords.y][k.coords.z];
+      if (curMode == debugContDist)
+        debugVal = k.d;
+      else if (curMode == debugProbAct)
+        debugVal = cs.p_act[k.coords.x][k.coords.y][k.coords.z] / P_ACT;
+      else if (curMode == debugProbExt)
+        debugVal = cs.p_ext[k.coords.x][k.coords.y][k.coords.z] / P_EXT;
       glUniform1f(glGetUniformLocation(bbProg, "debugVal"), debugVal);
       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
       model = scale(model, vec3(0.2));
@@ -344,7 +373,9 @@ void display() {
   glUseProgram(bbProg);
   setProjectionAndViewUniforms(bbProg);
 
-  glClearColor(0.83, 1, 1, 1); // background color
+  vec4 skyColor = envColors[envColorIdx][1];
+  glClearColor(skyColor.r, skyColor.g, skyColor.b,
+               skyColor.a); // background color
   glClear(GL_COLOR_BUFFER_BIT);
   renderObject(); // render things that aren't clouds
   renderClouds();
@@ -390,7 +421,7 @@ void keyboard(unsigned char key, int x, int y) {
     needsRedisplay = true;
   }
   if (key == 's') {
-    sunColorIdx++;
+    envColorIdx = (envColorIdx + 1) % envColors.size();
     needsRedisplay = true;
     needsReshading = true;
   }
@@ -424,7 +455,7 @@ void passiveMotion(int x, int y) {
 
 int main(int argc, char **argv) {
   glutInit(&argc, argv);
-  glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB |
+  glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA |
                       GLUT_3_2_CORE_PROFILE);
   glutInitWindowSize(width, height);
   glutCreateWindow("Clouds");
@@ -466,14 +497,21 @@ int main(int argc, char **argv) {
   initClouds(&cs);
   calculateMetaballs();
 
-  glGenTextures(1, &attenuationTex);
-
   glutKeyboardFunc(keyboard);
   glutMotionFunc(motion);
   glutPassiveMotionFunc(passiveMotion);
   glutTimerFunc(16, timer, 0);
 
-  // set up billboard prog
+#ifdef PBO
+  // setup PBOs for buffering readPixels
+  glGenBuffers(numPbos, pboBufs);
+  for (int i = 0; i < numPbos; i++) {
+    glBindBuffer(GL_PIXEL_PACK_BUFFER, pboBufs[i]);
+    glBufferData(GL_PIXEL_PACK_BUFFER, width * height * 4, NULL,
+                 GL_DYNAMIC_READ);
+  }
+  glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+#endif
 
   glutMainLoop();
 
index 2275dcb416bed7740725f0a170a7a16610f795a1..deb068bf7ea9c3bd374e43c35eb9aff507f9f357 100644 (file)
@@ -3,6 +3,8 @@
 #include <sstream>
 #include <iostream>
 
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
 using namespace std;
 
 void attachShader(GLuint progId, string filePath, GLenum type) {
index 3fa88791b1d871ba355306036246aca5e852fe67..ae3eb3f8c14c9ca433462c88007be5513799a55f 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef PROGRAM_HPP
 #define PROGRAM_HPP
 #include <string>
-#include <GL/glew.h>
+#include <GLUT/glut.h>
 class Program {
        public:
                Program(const std::string vert, const std::string frag);
index 4e107e72670a2d86452d0383fcdf8563c786ce4a..33b58de92c21f03d3e39a7310e33ad20a386dcc7 100644 (file)
@@ -15,17 +15,13 @@ inline void set(float x[CLOUD_DIM_X][CLOUD_DIM_Y][CLOUD_DIM_Z], int i, int j, in
   x[i][j][k] = y;
 }
 
-#define P_EXT 0.1
-#define P_HUM 0.1 
-#define P_ACT 0.001
-
 void initClouds(Clouds *cs) {
   for (int i = 0; i < CLOUD_DIM_X; i++) {
     for (int j = 0; j < CLOUD_DIM_Y; j++) {
       for (int k = 0; k < CLOUD_DIM_Z; k++) {
         cs->act[i][j][k] = randf() < 0.01;
         cs->cld[i][j][k] = false;
-        cs->hum[i][j][k] = randf() < 0.1;
+        cs->hum[i][j][k] = randf() < 0.01;
         cs->p_ext[i][j][k] = 0.f;
         cs->p_hum[i][j][k] = 0.f;
         cs->p_act[i][j][k] = 0.f;
@@ -46,7 +42,7 @@ void initClouds(Clouds *cs) {
     cs->vz[k] = floor(randf() * 3);
 
   // generate ellipsoids of probability
-  const int numEllipsoids = CLOUD_DIM_X * CLOUD_DIM_Y * CLOUD_DIM_Z * 0.002;
+  const int numEllipsoids = CLOUD_DIM_X * CLOUD_DIM_Y * CLOUD_DIM_Z * 0.001;
   for (int n = 0; n < numEllipsoids; n++) {
     const float maxSize = 8, minSize = 4;
     float delta = maxSize - minSize;
index ef53425e5a8b99db86def28805b6ce886d9b3a93..1985ee3662fb6af8eec728d2a21d48ba6fb9dcb7 100644 (file)
@@ -1,9 +1,15 @@
 #define CLOUD_DIM_X 64
 #define CLOUD_DIM_Y 16
 #define CLOUD_DIM_Z 64
+
 /* #define CLOUD_DIM_X 16 */
 /* #define CLOUD_DIM_Y 16 */
 /* #define CLOUD_DIM_Z 16 */
+
+#define P_EXT 0.1
+#define P_HUM 0.1 
+#define P_ACT 0.001
+
 struct Clouds {
   // TODO: make more efficient
   bool hum[CLOUD_DIM_X][CLOUD_DIM_Y][CLOUD_DIM_Z];