Water
We’ve now used 2 of the effects of the TVGraphicsEffects class. But there are some other cool effects that we can use. The next effect is one of the coolest effects in my opinion, since I’ve always wanted to know how they make water in a 3D world. So we’re going to make a water surface with a cube spinning above the water, a floor beneath the water, and of course a sky (which you won’t see probably, but the effects are noticable).

What do we need?
- Of course we need a couple meshes. We need a cube, a lightmark, a sky, a water surface and the floor.
- Then we need a TV_PLANE. This is not an airplane or anything alike. A plane basicly is a virtual surface with a normal that’s pointing perpendicular to it. If you want to get a better explanation, you should take a look at this: wiki
- We need something really strange as well right now. It’s called a DUDV texture. DUDV is an abbreviation for Distort U Distort V. U and V are the x and y axis on a texture, so the UV coordinates define a point on the texture. The DUDV texture will distort it a bit, so there can be waves on the water. Of course we also need an integer to keep track of the texture ID.
- To make water, we need to know what water really does and what the most important phenomenons are. The 2 most important things you see when you look at water are reflections and refractions. Everyone knows what a reflection is, just look in a mirror. But not everyone knows what a refraction is. You can see refractions when you have a straw in your glass of water. You’ll see that the straw looks different underwater than above the water. Under the water surface it seems that it’s a bit displaced in comparison with the upper part. This is called refraction (see: refraction). We’ll need 2 render surfaces for these 2 effects to render to. They are called Refraction and Reflection.
How do we set things up?
- First of all, we’ll load our sky mesh. In this case we’re using a *.tvm file that contains a sphere. When we load the sphere however, it’s way to small to be a sky. That’s why the following line is in there:
This scales the mesh 2000 times in every direction, so it will stay a sphere. You know the rest of the setup of the mesh, but I’ll post the code here anyway.
Sky.LoadTVM("..\\..\\..\\..\\common\\sky.tvm", true, true);
Sky.SetMaterial(0, -1);
Sky.SetScale(2000, 2000, 2000);
Sky.SetLightingMode(CONST_TV_LIGHTINGMODE.TV_LIGHTING_NONE, 0, 1);
- Now we’re going to load the DUDV texture. This is done slighly different from normal textures. The loading of the DUDV texture looks like this:
The first 3 parameters are the same as the ones from the normal texture loading, but after that, it’s different. The fourth parameter defines the amplitude of the DUDV texture. A higher amplitude means more distortion, a lower amplitude means less distortion. The last parameter is a boolean that defines whether it should use mipmapping or not. I won’t go into depth about mip mapping right now. If you do want to find out more about this subject, take a look at this: wiki
- We’re going to make a water surface right now. This water surface is just a simple mesh. It’s made by this code:
Water.AddFloor(IDDUDV, -400, -400, 400, 400, -10, 16, 16, false);
As you see, we’re using Water.AddFloor(). We’ve never used that before, so I’ll try to explain it a bit.
The first parameter is the texture that’s applied to the water surface.
The next four parameters define the position and size of the floor. The first 2 of those are the first point in the xz plane, the second 2 are the second point in the xz plane. So you define 2 points in the XZ plane and it will create a floor from the one to the other point.
The next parameter defines the height of the floor. You could think that this would set the thickness of the floor, but that’s not true. It’s the distance between the xz plane and the floor. So it’s basically the y value of the whole floor.
The next 2 parameters define the number of times that the texture is displayed on the floor. In this case the texture is tiled 16 times across the floor.
The last parameter defines of the floor should be a new group in the mesh. This can be useful if you want to apply a new texture to the floor/watersurface later on in your program.
- We want our floor (the one below the water surface) to have the same textures as our cube. That’s why we make 2 temporary integers with this code:
int IDCubeNormal = Cube.GetTextureEx((int)CONST_TV_LAYER.TV_LAYER_NORMALMAP, -1);
This code is fairly easy. The Cube.GetTexture(-1) gets the texture from the cube, the other line gets the texture on the normalmap layer of the cube.
- Now we want to create our floor and apply the textures to it. The code is pretty straight forward. You’ve used it all already, except for one line, which i will explain:
Floor.AddFloor(IDDUDV, -400, -400, 400, 400, -20, 60, 60, false);
Floor.SetTexture(IDCubeDiffuse, -1);
Floor.SetTextureEx((int)CONST_TV_LAYER.TV_LAYER_NORMALMAP, IDCubeNormal, -1);
Floor.SetMaterial(IDMat, -1);
Floor.ComputeNormals();
Floor.SetLightingMode(CONST_TV_LIGHTINGMODE.TV_LIGHTING_BUMPMAPPING_TANGENTSPACE, 0, 1);
You’ve probably never seen Floor.ComputeNormals(). What this command does is calculate the normals of the vertices of the floor. This is necessary since we don’t know how the normals are placed while creating the floor. They all need to point upward, so we make the mesh calculate that all on its own.
- Now we create the two render surfaces. You’ve seen this before:
Refract = Scene.CreateRenderSurface(512, 512, true, CONST_TV_RENDERSURFACEFORMAT.TV_TEXTUREFORMAT_A8R8G8B8, "refract target");
- We still didn’t make the TV_PLANE yet. So that’s what we’re doing right now. It’s not too hard to understand. TV_PLANE is a struct, so you don’t need to instantiate it. We set the settings this way:
Plane.Dist = 10;
This means the normal of the plane is pointing upward (in the direction (0,1,0)). The Plane.Dist setting allows us to move the plane in the direction of the normal. In this case, the plane will be at y=10.
- Now we’ve come to the real part of making the water work. We need to set everything up in the TVGraphicsEffect class. This is done by the following code:
FX.SetWaterReflectionColor(Water, new TV_COLOR(0.6f, 0.4f, 1, 1), new TV_COLOR(0.6f, 0.8f, 1, 1), 0.25f);
The first method defines respectively the water mesh, the reflect render surface, the refract render surface, the style of the water (you should keep this 0 for the best effect) and the plane that defines the water surface.
The second method defines the color of respectively the reflection and the refraction. The last parameter is for the fresnel settings. To learn more about this, visit: frensel diffraction
How do we render this?
That’s it, the settings are finally done. Now lets render it!
- In UpdateScene() we’re rendering everything to both the reflect and the refract render surface. You’ve seen this before.
Sky.Render();
Floor.Render();
Cube.Render();
LightMark.Render();
Reflect.EndRender();
Refract.StartRender(true);
Sky.Render();
Floor.Render();
Cube.Render();
LightMark.Render();
Refract.EndRender();
- Only thing we need to do is render everything in the normal render loop, because the TVGraphicsEffect makes sure the water surface looks like a water surface if you render to the reflect and refract render surfaces correctly.
- That’s it, we’ve made some water with reflections and refractions!
Things you can add/change yourself
- You can’t see the sky sphere in the water that well, so i suggest removing the scaling of the mesh, or setting it at around 20, so you’ll be able to see what it actually is.
- Try messing around with the amplitude of the DUDV texture to see what happens to the waves.
- Try removing and adding meshes to the reflect and refract surfaces to see if it works like you think it does.
Hey there,
first of all, your tutorials are great! They really help me a lot. But could you please be so kind and add some texture examples of textures? For example you just tell me to add this dudv texture. I have no idea what it should look like. There are more examples. Maybe you could just add low detailed texture examples of all textures you use.
Greetings from Skellods Team in Germany
PS: keep up your good work!
Thanks for the feedback! I’ll look in to putting all the textures here as well. You know you can download the whole tutorial pack by clicking the truevision3d button on top of the page (3rd button)?
About the dudv texture, it’s explained here: http://www.gametutorials.com/Articles/RealisticWater.htm
Scroll down to find the part about the dudv texture.