Waterflow
Visualize water in terrain
src/shallowGPU.cpp
Go to the documentation of this file.
00001 
00002 
00003 
00004 #include "shallowGPU.h"
00005 #include "GL_utilities.h"
00006 #include "Utilities.h"
00007 #include <algorithm>
00008 #include <stdio.h>
00009 #include <valarray>
00010 
00011 #include <iostream>
00012 #include <iomanip>
00013 #include <inttypes.h>
00014 
00015 
00016 bool ShallowGPU::DEBUG = false; 
00017 
00018 void ShallowGPU::cycleBuffer(){
00019     const static GLuint relBuffers[3] = {0,2,4};
00020     cycle = (cycle +1)%3;
00021     bufferOut = relBuffers[cycle];
00022 
00023 }
00024 
00025 void ShallowGPU::floodFill(float* u, int x, int z,float height){
00026 
00027   std::vector<std::vector<int>> queue;
00028 
00029   if (terr->getData()[x +texWidth*z] < height) {
00030     queue.push_back({x, z});
00031   }
00032 
00033 
00034   int temp_x, temp_z;
00035 
00036   /* While queue is not empty, keep processing queue from back to front.
00037   */
00038   while(queue.size() > 0){
00039 
00040     temp_x  = queue.back().at(0);
00041     temp_z = queue.back().at(1);
00042 
00043     queue.pop_back();
00044 
00045     // create the four neighbours clamp to ensure we don't check outside the map.
00046     int temp_x_plus = clip(temp_x+1,0,texWidth-1);
00047     int temp_x_min = clip(temp_x-1,0,texWidth-1);
00048     int temp_z_plus = clip(temp_z+1,0,texHeight-1);
00049     int temp_z_min = clip(temp_z-1,0,texHeight-1);
00050     int offset0 = temp_x + temp_z*texWidth;
00051     if(u[offset0] != height && terr->getData()[offset0] < height){
00052 
00053         //set height at offset0
00054         u[offset0] = height;
00055         //add the four neighbours
00056         queue.push_back({temp_x_plus,temp_z_min});
00057         queue.push_back({temp_x_plus,temp_z_plus});
00058         queue.push_back({temp_x_min,temp_z_min});
00059         queue.push_back({temp_x_min,temp_z_plus});
00060     }
00061   }
00062 }
00063 
00064 int ShallowGPU::clip(int n, int lower, int upper) {
00065     return std::max(lower, std::min(n, upper));
00066 }
00067 
00068 GLfloat ShallowGPU::clipf(GLfloat n, GLfloat lower, GLfloat upper) {
00069     return std::max(lower, std::min(n, upper));
00070 }
00071 
00072 
00073 void ShallowGPU::initGPU() {
00074     if(DEBUG){
00075     texWidth = 20;
00076     texHeight = 20;
00077     }
00078     float* u = new float[texWidth*texHeight];
00079     float* vx = new float[texWidth*texHeight];
00080     float* vy = new float[texWidth*texHeight];
00081     float* f = new float[texWidth*texHeight];
00082     float* emp = new float[texWidth*texHeight];
00083     float* flow = new float[texWidth*texHeight];
00084     std::fill_n(vx,texWidth*texHeight,0.0f);
00085     std::fill_n(vy,texWidth*texHeight,0.0f);
00086     std::fill_n(u,texWidth*texHeight,0.0f);
00087     std::fill_n(f,texWidth*texHeight,0.0f);
00088     std::fill_n(emp,texWidth*texHeight,0.0f);
00089     std::fill_n(flow, texWidth*texHeight, 0.0f);
00090 
00091 
00092     int upper2 = 180;
00093     int lower2 = 70;
00094 
00095     int upper3 = 50;
00096     int lower3 = 0;
00097 
00098 
00099     for (int j = 0; j < texHeight; ++j) {
00100         for (int i = 0; i < texWidth; ++i) {
00101                 f[j*texWidth + i] = 250.0f;
00102 
00103             if( i < 300 && j < 300 ){
00104                 f[j*texWidth +i] = 0.0f;
00105             }
00106 
00107             if( i > 251 && j > 299 && j < 900 && i <299){
00108                 f[j*texWidth +i] = 0.0f;
00109             }
00110 
00111             if( i > 250 && j > 850 && j < 1200 && i < 1500){
00112                 f[j*texWidth +i] = 0.0f;
00113             }
00114 
00115 
00116         }
00117     }
00118 
00119 
00120     for (int j = 0; j < texHeight; ++j) {
00121         for (int i = 0; i < texWidth; ++i) {
00122             u[j*texWidth + i] = 0.0f;
00123             vx[j*texWidth + i] = 0.0f;
00124             vy[j*texWidth + i] = 0.0f;
00125 
00126             if(i < upper2 && i >lower2 && j < upper2 && j > lower2){
00127                 //add interesting data here
00128                 u[j*texWidth + i] = 60.0f;
00129             }
00130 
00131             if (i < upper3 && i >lower3 && j < upper3 && j > lower3) {
00132                 //add interesting data here.
00133                 flow[j*texWidth + i] = 0.25f;
00134             }
00135 
00136         }
00137     }
00138     if(DEBUG){
00139     u[10 + 10 * texWidth] = 5.0f;
00140     }
00141 
00142 
00143     advectWaterProgram = compileComputeShader("src/shaders/advectWaterShader.comp");
00144     addProgram = compileComputeShader("src/shaders/addHeightShader.comp");
00145     advectVelocityXProgram = compileComputeShader("src/shaders/advectVelocityXShader.comp");
00146     advectVelocityYProgram = compileComputeShader("src/shaders/advectVelocityYShader.comp");
00147     updateHeightProgram = compileComputeShader("src/shaders/updateHeightShader.comp");
00148     updateVelocityProgram = compileComputeShader("src/shaders/updateVelocityShader.comp");
00149     //create buffers
00150     glGenBuffers(8, shallowBuffers);
00151     GLint numData = texWidth*texHeight;
00152 
00153     //#warn u is currently total height of terrain, maybe not correct for this impl.
00154 
00155     //Buffer 0, height of water.
00156     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[0]);
00157     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat)* 1 * numData, u, GL_STATIC_DRAW);
00158     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00159     //Buffer 1, height of water pong.
00160     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[1]);
00161     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat)* 1 * numData, u, GL_STATIC_DRAW);
00162     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00163     //Buffer 2, vx
00164     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[2]);
00165     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat)* 1 * numData, vx, GL_STATIC_DRAW);
00166     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00167     //Buffer 3 vx pong
00168     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[3]);
00169     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat)* 1 * numData, vx, GL_STATIC_DRAW);
00170     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00171 
00172     //Buffer 2, vy
00173     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[4]);
00174     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat)* 1 * numData, vy, GL_STATIC_DRAW);
00175     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00176     //Buffer 3 vy pong
00177     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[5]);
00178     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat)* 1 * numData, vy, GL_STATIC_DRAW);
00179     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00180 
00181     //Buffer 4, terrain data.
00182     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[6]);          //use terr->getData() to use terrain
00183     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat) * 1 * numData,f, GL_STATIC_DRAW);
00184     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00185 
00186     //Buffer 8, to renderer
00187     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[7]);
00188     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat) * 1 * numData,emp, GL_STATIC_DRAW);
00189     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00190 
00191     //Buffer 9, constant input
00192     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shallowBuffers[8]);
00193     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat) * 1 * numData, flow, GL_STATIC_DRAW);
00194     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00195 
00196 
00197 
00198     printError("init Compute Error");
00199     printProgramInfoLog(advectWaterProgram, "AdvectWater", NULL, NULL, NULL, NULL);
00200     printError("init Compute Error");
00201     printProgramInfoLog(advectVelocityXProgram, "AdvectX", NULL, NULL, NULL, NULL);
00202     printError("init Compute Error");
00203     printProgramInfoLog(advectVelocityYProgram, "AdvectY", NULL, NULL, NULL, NULL);
00204     printError("init Compute Error");
00205     printProgramInfoLog(addProgram, "Add", NULL, NULL, NULL, NULL);
00206     printError("init Compute Error");
00207     printProgramInfoLog(updateHeightProgram, "Add", NULL, NULL, NULL, NULL);
00208     printError("init Compute Error");
00209     printProgramInfoLog(updateVelocityProgram, "Add", NULL, NULL, NULL, NULL);
00210 
00211 
00212     float dt = 0.05f;
00213 
00214     glUseProgram(advectWaterProgram);
00215     glUniform2i(glGetUniformLocation(advectWaterProgram, "size"), texWidth,texHeight);
00216     glUniform1f(glGetUniformLocation(advectWaterProgram, "dt"), dt);
00217 
00218     glUseProgram(advectVelocityXProgram);
00219     glUniform2i(glGetUniformLocation(advectVelocityXProgram, "size"), texWidth, texHeight);
00220     glUniform1f(glGetUniformLocation(advectWaterProgram, "dt"), dt);
00221 
00222     glUseProgram(advectVelocityYProgram);
00223     glUniform2i(glGetUniformLocation(advectVelocityYProgram, "size"),texWidth, texHeight);
00224     glUniform1f(glGetUniformLocation(advectWaterProgram, "dt"), dt);
00225 
00226     glUseProgram(addProgram);
00227     glUniform2i(glGetUniformLocation(addProgram, "size"),texWidth, texHeight);
00228     glUniform1f(glGetUniformLocation(advectWaterProgram, "dt"), dt);
00229 
00230     glUseProgram(updateHeightProgram);
00231     glUniform2i(glGetUniformLocation(updateHeightProgram, "size"), texWidth,texHeight);
00232     glUniform1f(glGetUniformLocation(advectWaterProgram, "dt"), dt);
00233 
00234     glUseProgram(updateVelocityProgram);
00235     glUniform2i(glGetUniformLocation(updateVelocityProgram, "size"), texWidth, texHeight);
00236     glUniform1f(glGetUniformLocation(advectWaterProgram, "dt"), dt);
00237 
00238     delete u;
00239     delete vx;
00240     delete vy;
00241     delete flow;
00242 }
00243 
00244 void ShallowGPU::initFloodFill(float* u){
00245     for(unsigned int i = 0; i < flood.size(); i++){
00246             floodFill(u, flood.at(i)->x, flood.at(i)->z,flood.at(i)->height);
00247     }
00248 }
00249 
00250 
00251 
00252 void ShallowGPU::runSimGPU(GLfloat dt) {
00253     totTime += dt;
00254     int numPing = 5;
00255     if(DEBUG){
00256         numPing = 500;
00257     }
00258 
00259     //Add this one
00260     glBindBuffersBase(GL_SHADER_STORAGE_BUFFER, 4, 1, &shallowBuffers[0]);
00261     //and this one.
00262     glBindBuffersBase(GL_SHADER_STORAGE_BUFFER, 10, 1, &shallowBuffers[8]);
00263     //write to this one.
00264     glBindBuffersBase(GL_SHADER_STORAGE_BUFFER, 11, 1, &shallowBuffers[1]);
00265     glUseProgram(addProgram);
00266     glDispatchCompute((GLuint)ceil((GLfloat)texWidth / 16.0f), (GLuint)ceil((GLfloat)texHeight / 16.0f), 1);
00267     glFinish();
00268     // Initiate ping ponging.
00269     std::swap(shallowBuffers[0], shallowBuffers[1]);
00270     for (int i = 0; i < numPing; i++) {
00271 
00272         glBindBuffersBase(GL_SHADER_STORAGE_BUFFER, 4, 7, shallowBuffers);
00273 
00274         //select advectWater
00275         glUseProgram(advectWaterProgram);
00276 
00277         glDispatchCompute((GLuint)ceil((GLfloat)texWidth / 16.0f), (GLuint)ceil((GLfloat)texHeight / 16.0f), 1);
00278         glFinish();
00279             if(DEBUG){
00280 
00281             Print(shallowBuffers[1], "HEIGHT AFTER ADVECT WATER", 1);
00282             Print(shallowBuffers[2], "VELX AFTER ADVECT WATER", 1);
00283             Print(shallowBuffers[4], "VELY AFTER ADVECT WATER", 1);
00284             std::getchar();
00285             }
00286         //select velocity advect X
00287         glUseProgram(advectVelocityXProgram);
00288 
00289         glDispatchCompute((GLuint)ceil((GLfloat)texWidth / 16.0f), (GLuint)ceil((GLfloat)texHeight / 16.0f), 1);
00290 
00291         glFinish();
00292 
00293             if(DEBUG){
00294             Print(shallowBuffers[1], "HEIGHT AFTER ADVECTVELX", 1);
00295             Print(shallowBuffers[3], "VELX AFTER ADVECTVELX", 1);
00296             Print(shallowBuffers[4], "VELY AFTER ADVECTVELX", 1);
00297             std::getchar();
00298             }
00299         //select velocity advect Y
00300         glUseProgram(advectVelocityYProgram);
00301 
00302         glDispatchCompute((GLuint)ceil((GLfloat)texWidth / 16.0f), (GLuint)ceil((GLfloat)texHeight / 16.0f), 1);
00303         glFinish();
00304             if(DEBUG){
00305             Print(shallowBuffers[1], "HEIGHT AFTER ADVECT ADVECTVELY", 1);
00306             Print(shallowBuffers[3], "VELX AFTER ADVECT ADVECTVELY", 1);
00307             Print(shallowBuffers[5], "VELY AFTER ADVECT ADVECTVELY", 1);
00308             std::getchar();
00309             }
00310         glUseProgram(updateHeightProgram);
00311 
00312         glDispatchCompute((GLuint)ceil((GLfloat)texWidth / 16.0f), (GLuint)ceil((GLfloat)texHeight / 16.0f), 1);
00313         glFinish();
00314             if(DEBUG){
00315             Print(shallowBuffers[0], "HEIGHT AFTER UPDATE HEIGHT", 1);
00316             Print(shallowBuffers[3], "VELX AFTER UPDATE HEIGHT", 1);
00317             Print(shallowBuffers[5], "VELY AFTER UPDATE HEIGHT", 1);
00318             std::getchar();
00319             }
00320         //
00321 
00322         glUseProgram(updateVelocityProgram);
00323 
00324         glDispatchCompute((GLuint)ceil((GLfloat)texWidth / 16.0f), (GLuint)ceil((GLfloat)texHeight / 16.0f), 1);
00325         glFinish();
00326             if(DEBUG){
00327             Print(shallowBuffers[0], "HEIGHT AFTER UPDATE VELOCITY", 1);
00328             Print(shallowBuffers[2], "VELX AFTER UPDATE VELOCITY", 1);
00329             Print(shallowBuffers[4], "VELY AFTER UPDATE VELOCITY", 1);
00330             std::getchar();
00331 
00332 
00333             Print(shallowBuffers[0], "HEIGHT0 AFTER ALL", 1);
00334             Print(shallowBuffers[2], "VELX0 AFTER ALL", 1);
00335             Print(shallowBuffers[4], "VELY0 AFTER ALL ", 1);
00336             std::getchar();
00337 
00338 
00339             Print(shallowBuffers[1], "HEIGHT1 AFTER ALL", 1);
00340             Print(shallowBuffers[3], "VELX1 AFTER ALL", 1);
00341             Print(shallowBuffers[5], "VELY1 AFTER ALL ", 1);
00342 
00343             }
00344     }
00345 
00346     //Bind input data(to render)
00347     glBindBuffersBase(GL_SHADER_STORAGE_BUFFER,4,1,&shallowBuffers[bufferOut]);
00348     //Bind terrain
00349     glBindBuffersBase(GL_SHADER_STORAGE_BUFFER,10,1,&shallowBuffers[6]);
00350     //bind output
00351     glBindBuffersBase(GL_SHADER_STORAGE_BUFFER,11,1,&shallowBuffers[7]);
00352     glUseProgram(addProgram);
00353     glDispatchCompute((GLuint)ceil((GLfloat)texWidth / 16.0f), (GLuint)ceil((GLfloat)texHeight / 16.0f), 1);
00354     glFinish();
00355     printError("run Sim GPU");
00356 
00357 
00358 }
00359 
00360 void ShallowGPU::Print(GLuint bufferID, std::string msg, int iter) const
00361 {
00362     float * arr = new float[texWidth*texHeight];
00363 
00364     glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferID);
00365     glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLfloat)*texWidth*texHeight, arr);
00366     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00367 
00368     PrintHelper("BEGIN", msg, iter);
00369     for (int j = 0; j < texHeight; j++)
00370     {
00371         for (int i = 0; i < texWidth; i++)
00372         {
00373 
00374             const unsigned int index = i + j*texWidth;
00375             PrintNumber(arr[index]);
00376         }
00377         std::cout << "\n";
00378     }
00379     PrintHelper("END", msg, iter);
00380     std::cout << std::flush;
00381 }
00382 
00383 void ShallowGPU::PrintNumber(float value) const
00384 {
00385     std::cout << std::fixed << std::setw(7) << std::setprecision(3) << value << " ";
00386 }
00387 
00388 void ShallowGPU::PrintHelper(std::string start_end, std::string msg, int iter) const
00389 {
00390     if (iter != -1) {
00391         std::cout << "========== " << start_end << " " << msg << " " << iter << " ==========\n\n";
00392     }
00393     else {
00394         std::cout << "========== " << start_end << " " << msg << " ==========\n\n";
00395     }
00396 }
 All Classes Files Functions Variables Enumerations