Water Shader with OpenGL

A Water Shader with OpenGL

#OpenGL#C#Projects#Bachelor's Studies#University Studies
In a module in my bachelor's degree, there was an animation project where we had to render a short video with OpenGL. I decided to delve into procedural geometry and raymarching to create a water shader.

Implementation

Raymarching

The entire video is generated using raymarching:

float ray(vec3 ro, vec3 rd, out vec4 col, bool flip){
    float t = 0.;
    float eps = 0.001;
    uint steps = 100;
    while(steps>0 && t<FAR_PLANE){
        vec3 p = ro + t*rd;
        float dist = sdTest(p, col, flip);

        if (dist<eps){
            break;
        }

        t += dist;
        steps --;
    }

    if (t>= FAR_PLANE){
        t = -1.0;
    }

    return t;
   }

   

Procedural Geometry

Signed distance functions (SDFs) are used to describe the geometry. A simple example is the SDF for a cube:

float quader(vec3 p, vec3 b){
    vec3 value = abs(p)-b;


    if(value.x<0.){
        value.x = 0.;
    }

    if(value.y<0.){
        value.y = 0.;
    }

    if(value.z<0.){
        value.z = 0.;
    }

    return length(value);
}
I called this SDF recursively to create complex structures. This way, I generated an abstract representation of a boat.
float recursiveCube(vec3 pos, float edge){
    float ret = 10000;

    vec3 cPos = pos;
    float cEdge = edge;
    ret = cube(pos, edge);
    for(int i=0; i<10; i++){
        float mainCube = cube(cPos, cEdge);

        float sideoffset = cEdge+cEdge*0.75;
        cPos = cPos-vec3(0,sideoffset,0);
        cEdge = cEdge*0.75;
        float smallCube = cube(cPos, cEdge);



        ret = min(mainCube, min(smallCube, ret));
    }
    return ret;

}

Waves

Then I combined the surfaces of the cube with a function to make the cubes wavy. These are Gerstner waves:

vec3 gerstner(vec3 position, float wave_height , float wave_length, float speed, vec2 direction){
    vec2 d = normalize(direction);
    float k = M_PI*2.0f / wave_length;
    float f = k * (dot(position.xz, d)-uTime*speed);

    float y = wave_height*sin(f);
    float x = wave_height * cos(f) * d.x;
    float z = d.y* wave_height*sin(f);

    vec3 wave = vec3(x, y, z);
    return wave;
}

Miscellaneous

For decoration, I placed a few cacti on the strange boat, which are supposed to look like masts. I also defined a simple data structure to store the individual objects in my scene, so I could color and move the objects individually.

Result

The (in my opinion, somewhat presentable given the tight timeframe) result is the following video:

Comments

Feel free to leave your opinion or questions in the comment section below.