How to implement wave equation?

Started by
1 comment, last by EarthBanana 7 years, 9 months ago

I'm using OpenGL, GLFW and GLEW to create a simulation of water waves for a school project.

When I use the old vertex shader without the function, the grid renders as expected, but with the new shader it shows a blank grey background.
I created a grid in the xz-plane and created a shader to manipulate the grid based on an equation I found from some resources I found online are at the end:

Here are the relevant snippets of code:

Rendering code


while(!glfwWindowShouldClose(window))
    {
        // Set frame time
        GLfloat currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // Check and call events

        glfwPollEvents();
        Do_Movement();

        // Clear the colorbuffer
        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Draw objects
        shader.Use();

        //Set Uniforms
        GLint locTime = glGetUniformLocation(shader.Program, "time");
        if (locTime != -1)
            glUniform1f(locTime, (float)glfwGetTime());

        GLint locWLength = glGetUniformLocation(shader.Program, "wavelength");
        if (locWLength != -1)
            glUniform1f(locWLength, 1.0f);

        GLint locPeak = glGetUniformLocation(shader.Program, "peak");
        if (locPeak != -1)
            glUniform1f(locPeak, 3.0f);



        glm::mat4 model;
        glm::mat4 view = camera.GetViewMatrix();
        glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
        glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

        // Grid
        glBindVertexArray(planeVAO);
        glBindTexture(GL_TEXTURE_2D, floorTexture);
        model = glm::mat4();
        glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
        //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glDrawElements(GL_LINES, 3*grid.Indices.size(), GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);                

        // Swap the buffers
        glfwSwapBuffers(window);

    }

Vertex Shader


#version 430 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;

out vec2 TexCoords;

const float pi = 3.14159265;


uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

uniform float wavelength;
uniform float peak;
uniform float time;

void main()
{
    float a = position.x;
    float b = peak - 1.0f;
    float k = (2.0f * pi) / wavelength;
    float c = sqrt(9.81f/k);

    float wave_dx = (exp(k * b)/ k) * sin(k * (a + c * time));
    float wave_dy = (-exp(k * b)/ k) * cos(k * (a + c * time));    

    gl_Position = projection * view * model * vec4( (position.x + wave_dx), (position.y + wave_dy), position.z, 1.0f);
    TexCoords = texCoords;

}

oldVertex Shader


 
#version 430 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;

out vec2 TexCoords;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
    TexCoords = texCoords;
}

Here is the correct static output:

[attachment=32470:output_4.png]

[attachment=32471:realOutput.png]

This is where I got my equation/ implementation.

" title="External link">

https://en.wikipedia.org/wiki/Trochoidal_wave#description_of_classical_trochoidal_wave

Thanks in advance!

Advertisement

Hmm i'd test the equation first in a simpler way (Calculate on CPU or use glBegin/glEnd).

Make sure the values are right.

A lot of things could be wrong here - including compile/link errors with the shaders - if not then likely your equations are producing huge delta values.

I would start with a simple traveling wave in a single direction - assuming your water is in x y plane then just vary z according to time and either x/y - expand from there.

new_z = position.z * A * sin( 2 * pi * f * time - beta * position.x) // varying according to x

where A is the amplitude, f is the frequency in hertz, and beta is 2 * pi * f / phase_velocity. Most emag wave equations would assume a phase velocity of the speed of light, but I would chose a more sane and visible phase velocity.

If you want the wave to travel across your water in the x direction at 1 unit per second for example and you want the wave to complete an up/down cycle once per second: f = 1, beta = 2 * pi * f / phase_velocity = 2 * pi

which lands you at

new_z = position.z * A * sin(2 * pi * (time - position.x) )

You could adjust A, starting very small, until you see noticeable waves going in the x direction across the water. Start adding to get to the other wave equations from there.

This topic is closed to new replies.

Advertisement