• 13
• 18
• 19
• 27
• 9

# XNA : A Simple Way To Create Real Water

This topic is 2755 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

This is a simple XNA project that simulates an ocean,
Assuming you're familiar with VertexBuffer,IndexBuffer and other stuff you would need to build a terrain this article should be very straightforward.
The principle is simple! examine this very simple example:

I have 9 vertices forming 4 quads
I also have an array of 9 integers to determine the direction of each vertex : up/down
when first initializing the WaterBody, a random value between -n,n is assigned to the Y component of each vertex. so each vertex should start with a random Y component… The direction of each vertex is also generated randomly!

Now all I have to do ( every Update() Call ) is to move each vertex in its direction ( up or down), if Position.Y<(-n) or Position.Y>n then fix Position.Y and change the direction of the vertex ( if up make it down, if down make it up! pretty simple huh? :) )

If you apply the above to a larger number of vertices ( I used 70×70 in my project ) you’ll have a nice wavy water!
Adding some lighting and texture will make things better.
Adding sound effects will make things even better!

Here’s the final result!

if you download the code you'll find a class called WaterBody which does all the work,you just have to supply it with simple parameters such as width,depth (water body deminsions) , maxWaveHeight , GraphicsDevice and offcourse the texture you want to be mapped on the water
Another constructor is available it takes ( in addition to the first one ) position,rotation and scale...
So you see this class should be easily used in any project,you just have to have a camera class which contains a Projection,View properties..

I know nothing about HLSL, just the standard BasicEffect, but I think some shaders will improve the look of the water remarkably!
I hope this might be of some use for someone somewhere!
If some won needs more detaild explanation don't hesitate to ask [smile]

Check out the demo\project, it contains more features than I mentioned here
Here is the demo
Here is the code

##### Share on other sites
Your up/down movements should at least be in a sine wave!

##### Share on other sites
Quote:
 Original post by BLiTZWiNGYour up/down movements should at least be in a sine wave!

You're right! I don't know why I haven't thought about that!
But even if I use the sine wave I'll still have to store the angle of the vertices in an array right?
Thanks!

##### Share on other sites
Nice effect!

You might try this as well: instead of storing up/down for each vertex, store an int or float that represents phase.

Then, each frame, compute the position of each vertex like so:

for (unsigned int i = 0; i < vertices; ++i){	vertex.y = sinf(time + phase);}time += 0.001f;

This way, the wave motion will be smoother but still retain a random factor (if you randomize phase for each vertex at the beginning of the program, the vertices will be out of sync with each other like in your original version).

Note that you have to increment a float "time" by a small amount each frame to make the vertices move.

##### Share on other sites
Thanks XeonXT!
Another great improvement![smile]

##### Share on other sites
You could also try randomising the amount each point changes each frame. This could be stored as a multiplier created randomly at the start. This should help alleviate the repetition, right now it just cycles between the two same states.

If you're interested in creating accurate wave-like animations then there are plenty of papers out there dealing with a myriad of possibilities like a mix of sine waves, perlin noise and a bunch of other things. I'd recommend you do a bit of research into the field :)

##### Share on other sites
I suggest to learn a bit of shader programming. Changing the y value of each vertex in the shader code will increase the performance enormously, allowing you to increment the number of vertices in your buffer ( more vertices -> better quality)

##### Share on other sites
Quote:
 Original post by b3rs3rkI suggest to learn a bit of shader programming. Changing the y value of each vertex in the shader code will increase the performance enormously, allowing you to increment the number of vertices in your buffer ( more vertices -> better quality)

Hi. It's kinda offtopic but, I'm a little new to vertex shaders and so far I haven't modified geometry on an "individual" basis.

And I just want to ask if this is the right method to do what u said:
1. You send the vertex's original position.
2. You send the current elapsed time.
3. You modify the vertex's final position based on the elapsed time and original position.

Correct?

##### Share on other sites
Quote:
 Original post by cyberlorddanHi. It's kinda offtopic but, I'm a little new to vertex shaders and so far I haven't modified geometry on an "individual" basis.And I just want to ask if this is the right method to do what u said:1. You send the vertex's original position.2. You send the current elapsed time.3. You modify the vertex's final position based on the elapsed time and original position.Correct?

Yeah sounds about right. I believe you only need to send the vertex array over once. After that, every update, you only need to send the elapsed time to the shader. I've only done lighting and post-process shaders in XNA though, not water.

BTW: if game objects need to collide with the water surface, can you still do shader-based water geometry? You have to query the data on the GPU and send it back to the CPU?