OpenGL Ocean Simulation

edited December 2015 in GLSL / Shaders
PImage ground;
//This is the final PShape
PShape surface;
PShader texShader;

PShape[][] test;

//Width and length of the ocean vertex matrix
int w,l;

//This timer is used to generate random wave ripples 
int timer;

//This is the height matrix for each vertex
float[][] elevation;

boolean[][] flag;

void setup() {  
  frameRate(30);

  timer = 0;

  size(800, 800, P3D);  
  ground = loadImage("ocean.jpg");

  w = 200;
  l = 200;

  elevation = new float[w][l];
  flag = new boolean[w][l];

  test = new PShape[w-1][l-1];

  for(int i = 0; i < w; i++)
  {
    for(int j = 0; j < l; j++)
    {
      //Initial vertex elevation value
      elevation[i][j] = random(-1,1);
      flag[i][j] = true;
    }
  }

  surface = createSurface(w, l, 200, ground);
  texShader = loadShader("texfrag.glsl", "texvert.glsl");
}

void draw() {   
  background(0);

  //Calculate movements of each vertex and wave
  runOcean();

  //Write vertex positions to the PShape
  updateShape();

  shader(texShader);  

  //Move to appropriate positions
  translate((width-200)/2, (height-200)/2,350);  
  rotateX(PI/2.75);

  shape(surface); 
}

//This function creates a PShape using the points from elevation[][]
PShape createSurface(int w, int d, int detail, PImage tex) {

  textureMode(NORMAL);
  PShape sh = createShape(GROUP);

  sh.beginShape();
  sh.noStroke();

  for(int i = 0; i < detail-1; i++)
  {
    for(int j = 0; j < detail-1; j++)
    {
      PShape tmp = createShape();
      tmp.beginShape(QUAD);
      tmp.noStroke();
      tmp.texture(ground);      
      tmp.vertex(i*(w/detail),j*(d/detail),elevation[i][j],float(i)/detail,float(j)/detail);
      tmp.vertex((i+1)*(w/detail),j*(d/detail),elevation[i+1][j],float(i+1)/detail,float(j)/detail);
      tmp.vertex((i+1)*(w/detail),(j+1)*(d/detail),elevation[i+1][j+1],float(i+1)/detail,float(j+1)/detail);
      tmp.vertex(i*(w/detail),(j+1)*(d/detail),elevation[i][j+1],float(i)/detail,float(j+1)/detail);
      tmp.endShape();

      sh.addChild(tmp);
    }
  }
  return sh;
}

//Calculate movements of each vertex and wave
void runOcean()
{
  //This is for the ordinary random movement which is there
  //even when there are no waves
  for(int i = 0; i < w; i++)
  {
    for(int j = 0; j < l; j++)
    { 
      if(!flag[i][j])
       {
          elevation[i][j] =random(-.5,0.5);
          elevation[i][j] = constrain(elevation[i][j],-2,2);
          flag[i][j] = true;
       }
       if(flag[i][j])
       {
         flag[i][j] = false;
       }
    }
  }
}

//This writes the points from elevation[][] to the vertices of 'surface'
void updateShape()
{
  for(int i = 0; i < w - 1; i++)
  {
    for(int j = 0; j < l - 1; j++)
    {       
      PVector v  = surface.getChild(i + j*(w-1)).getVertex(0);
      surface.getChild(i + j*(w-1)).setVertex(0,v.x,v.y,elevation[i][j]);
      v  = surface.getChild(i + j*(w-1)).getVertex(1);
      surface.getChild(i + j*(w-1)).setVertex(1,v.x,v.y,elevation[i+1][j]);
      v  = surface.getChild(i + j*(w-1)).getVertex(2);
      surface.getChild(i + j*(w-1)).setVertex(2,v.x,v.y,elevation[i+1][j+1]);
      v  = surface.getChild(i + j*(w-1)).getVertex(3);
      surface.getChild(i + j*(w-1)).setVertex(3,v.x,v.y,elevation[i][j+1]);
    }
  }
}

Answers

  • edited December 2015

    Hi people, the code above is an Opengl simulation of the surface of the ocean. The way it works is, I have a matrix of points representing the polygon vertices. Each time a change occurs, the vertices of the PShape 'surface' are replaced by the points from the aforementioned matrix.

    I'm seeing a lot of black spaces when the code runs, can someone be kind enough to take a look and see if there is a problem with my algorithm somewhere?

  • Answer ✓

    Ok, solved it, it was extremelyyy stuuupiddd. In case anyone is curious, in updateShape(), when setting each vertex, you cannot use v.x and v.y (these are floats), you need to use terms based on i and j. Not sure why but somehow when converting int to float, something goes wrong. See example below:

    surface.getChild(i + j*(w-1)).setVertex(3,i,j-1,elevation[i][j+1]);

Sign In or Register to comment.