Waterflow
Visualize water in terrain
|
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 }