Advertisement

Problem with Gerstner waves in vertex shader

Started by March 27, 2019 02:05 AM
5 comments, last by Alex Gomez Cortes 5 years, 10 months ago

Hello everyone!

I am working in a openGL framework lately, and I found a problem when implementing Gerstner waves. The problem is that when I calculate the waves through the CPU, it works really good, but when i copy and paste the code to the vertex shader(with some changes, uniforms, etc) the waves become weird af.

I am going to post some pictures so you can get a better idea about what is going on.

 

CPU waves: 

olas_cpu.PNG.5aeabb4f85970ab39f9f6a9ac5cc4187.PNG

 

GPU waves: 

570815670_Capturaolas.thumb.PNG.adae8eb48ad7e0e736d0850d63bb877f.PNG

 

Code comparison:

2080527730_comparacioncodigo.thumb.PNG.f2be0a81e8a0b29c283b18923962f404.PNG

k->wave direction w-> frequency A-> amplitude of the wave   L-> distance between crests

 

If someone knows what is going on, please tell me.

Thank you in advance!

Hola Alex,

First, I would recommend getting familiar with a GPU debugger, my favourite one being RenderDoc. It allows you to debug the execution of shaders on individual vertices or pixels. 

I had a quick look at your shader code. You are modifying all components of pos, including w and that might explain the error. In theory you should modify the xz components with the horizontal displacement formula, y the component with the vertical formula (assuming y points vertically in your world space), and leave w to 1. k should be a 2D normalized vector, not a vec4, and the wave phase should be given by dot(k, in_Position.xz) + offset.  

I have worked on waves simulation for many years so please let me know if you have any questions related to it.

 

Advertisement

I had a quick look at your code, but the first thing you have to know is that the vertex shader works per vertex whereas doing it on the CPU you have vision over all vertices.

olas seems to become the L uniform in your shader. Do you update L for every vertex as it seems it should from your CPU version ? olas is an array, so L might remain an array (thus removing the need to update the uniform for every vertex). Then to know which vertex is currently processed, you can use gl_VertexID and access it threw L[gl_VertexID] for example.

Also note that uniforms have limitations in their size (this is important if your grid is big and you use array of uniforms as I suggested).

If you don't want to use array of uniforms and if olas is constant, then use olas as a vertex attribute.

Advertisement
10 hours ago, Reitano said:

Hola Alex,

First, I would recommend getting familiar with a GPU debugger, my favourite one being RenderDoc. It allows you to debug the execution of shaders on individual vertices or pixels. 

I had a quick look at your shader code. You are modifying all components of pos, including w and that might explain the error. In theory you should modify the xz components with the horizontal displacement formula, y the component with the vertical formula (assuming y points vertically in your world space), and leave w to 1. k should be a 2D normalized vector, not a vec4, and the wave phase should be given by dot(k, in_Position.xz) + offset.  

I have worked on waves simulation for many years so please let me know if you have any questions related to it.

 

@Reitano  Thanks for your answer!

The problem was what you said, I was multiplying the w component.

But I have two questions:

Why should the vector k be 2D? If I want to make a wave that moves along z axis I can't then.

What is the offset of the wave? 

Thank you!

9 hours ago, _Silence_ said:

I had a quick look at your code, but the first thing you have to know is that the vertex shader works per vertex whereas doing it on the CPU you have vision over all vertices.

olas seems to become the L uniform in your shader. Do you update L for every vertex as it seems it should from your CPU version ? olas is an array, so L might remain an array (thus removing the need to update the uniform for every vertex). Then to know which vertex is currently processed, you can use gl_VertexID and access it threw L[gl_VertexID] for example.

Also note that uniforms have limitations in their size (this is important if your grid is big and you use array of uniforms as I suggested).

If you don't want to use array of uniforms and if olas is constant, then use olas as a vertex attribute.

@_Silence_ First of all thanks for your answer!

olas is not the L uniform. L, k, w, speed, A are the attributes of the waves, so what I do is: when I call the draw function, I make a foor loop where in every iteration i pass to the shader olas.w, olas.k, etc. as uniforms.

I'll read about passing arrays to the shader because right now only the last wave is being rendered, the previous no, so I think I can pass several arrays (one array of w components, another one of L components, etc) and iterate inside the vertex shader applying the formulas with the right variables.

 

Thank you very much!

Where do you use temp_vertices array in shader??? Seems you use the same index so either pass another attribute to vertex shader with this temp array (if its static - if not youll have to update this buffer..)

5 hours ago, _WeirdCat_ said:

Where do you use temp_vertices array in shader??? Seems you use the same index so either pass another attribute to vertex shader with this temp array (if its static - if not youll have to update this buffer..)

@_WeirdCat_ Hello and thanks for your reply!

 

I dont need temp_vertices in the shader. When I calculate the waves through the cpu I need temp_vertices[] because I need to know the difference between the initial position and the new position after applying the formulas. As you can see, vertices[] is being modified every frame, so every frame I need to reset it with temp_vertices[] (it has the initial positions) in order to recalculate the difference between points again.

In the shader, I dont need temp_vertices[] because vertices[] is not being modified, I just pass vertices[] to the shader and it acts like temp_vertices[] and pos acts as vertices[].

Thanks for your reply!

This topic is closed to new replies.

Advertisement