1
\$\begingroup\$

I have a LWJGL project and ran into a problem with a vertex shader I wrote. In my scene I am rendering a map whose ground consists of rectangular tiles. On top of that there are other objects (I used tiny white balls here). Here is a screenshot of my scene:

screenshot of my scene http://110.imagebam.com/download/0-Ktu6XjdWSMpKytTr3Trg/34736/347358711/scene_static.jpg

You can also click here to see the image.

Each of the four larger rectangles at the bottom is one huge quad drawn in one piece. Every one of them contains four coordinates (the corners: top-left, top-right, bottom-right, bottom-left). Their interior is filled with a texture.

The small white balls on top are single game objects each drawn by itself. Note that I aligned them with the vertical edges of the underlying rectangles.

I used the following vertex shader to render the scene:

/* default shader */
#version 120    

void main()
{
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}   

Now imagine the scene getting covered with water. I modified the shader adding a little water effect:

/* water shader */
#version 120    

uniform float amplitude;
uniform float phase;

void main()
{
    gl_TexCoord[0] = gl_MultiTexCoord0;

    // transform x
    vec4 a_position = gl_Vertex;        
    a_position.x = a_position.x + amplitude * sin(phase + a_position.x);

    gl_Position = gl_ModelViewProjectionMatrix * a_position;
}

An animated image of my scene can be found here or here.

You can see that the borders of the rectangles keep aligned with the white balls on top of them. However, vertices inside the rectangles (I marked the most distinct areas red) suffer a displacement relative to the white balls. In the last rectangle you can even see the balls cross the white line in the middle.


I need the interior of my textured rectangles to be transformed exactly like the white balls on top and move uniformly when being animated by my shader. Please let me know if my problem is clear and if any other information is needed.

Thank you very much for your help. Greetings Xoric

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

From your original equation

a_position.x = a_position.x + amplitude * sin(phase + a_position.x);

We'll just be taking at look at the sin portion as this is where this effect comes from

sin(phase + a_position.x);

Let's look at the sin function over a half of a period for different positions (phase is in degrees)

Position 1 - a_position.x = 0
sin(0 + 0) = 0
sin(45 + 0) = .707
sin(90 + 0) = 1
sin(135 + 0) = .707
sin(180 + 0) = 0

Position 2 - a_position.x = 1
sin(0 + 1) = 0.0175
sin(45 + 1) = .719
sin(90 + 1) = 0.9998
sin(135 + 1) = .695
sin(180 + 1) = -0.0175

Position 3 - a_position.x = 2
sin(0 + 2) = 0.0349
sin(45 + 2) = .731
sin(90 + 2) = 0.9993
sin(135 + 2) = .682
sin(180 + 2) = -0.0349

With each increment of the a_position.x we're almost slowly changing the phase that the sin function is actually using. This is what gives you that expanding and contracting water effect. The problem with this is that it is also what's causing the alignment issues between your quad and the rest of the balls.

Your quads are defined by their vertices which are aligned by the balls. Because the vertices are at different positions their phase is different and so move out of phase from each other causing the quad to grow and shrink. The actual midpoint of the quad can be calculated using the two vertices and simplified to just the sin portion to get

sin(phase + pos1) + sin(phase + pos2) / 2

Where if you wanted the middle to match up, it'd have to be equal to the ball closest to that which would have an equation which simplifies to its sin portion of

sin(phase + posBallMiddle)

The first one is dependent upon two positions, not just one like the second equation. The only way you'd get it to line up is if the vertices were one or more periods apart. This means a solution is limited by what you can change elsewhere (lining up the objects with the quad through other means, making sure to keep the rectangles are a certain width based on your period, or something else). Otherwise, you'd need a different equation to model your water.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks a lot Coburn. Your answer was all I could hope for. I thought about your suggestions and came to the conclusion that restricting the rectangles' size is not a valid option in my project. So I am going to have a look around and maybe find a different water shader implementation. For now I "solved" the problem by decreasing the amplitude in my shader and I'm also considering decreasing the size of my ground tiles. Thanks again for your great explanation. \$\endgroup\$
    – xoric
    Aug 26, 2014 at 19:39
  • \$\begingroup\$ Glad to help :D \$\endgroup\$
    – Cobertos
    Aug 26, 2014 at 23:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .