I will just write a quick article on this week’s work: creating the appearance of waterfalls and water/lakes which are not the main sea.
Indeed, I want a world with various (floating) islands and some waterfalls. Maybe you noticed it, but there is already water in the video game. I previously worked on the main sea of the world, and it wasn’t that easy to set up a look that I found OK. I finally chose to have a purely reflective water. The big problem is that displaying the main sea is quite computationally expensive.
If I want to add other water planes (for example a lake on an island) or waterfalls, I can’t use the exact same approach because it will seriously slow down the game. Plus, for a simple plane, computing the reflection is “quite” straight-forward, but for complex shapes (a waterfall), the computations are more difficult and the graphical pipeline of the GPU is not well suited for such a task. So I have to use a work around if I don’t want to spend days developing an incredibly complex material that nobody will notice anyway.
I finally choose a combination of various classical techniques used in video game/real-time applications…
I – Environment(cube) map
An environment map is some kind of “spherical” texture (actually it’s computed from the faces of a cube) that is applied on a mesh according to its normals. The idea is to “fake” the reflection of the environment on the object.
Technically, it is possible to compute such a normal map in real-time to obtain a “true” reflection of the environment. However, as usual, this is quite GPU-heavy (you have to make 6 renders of the scene to create the real-time reflection texture). Furthermore, even with real-time computed reflections, the mapping itselft is still a fake one, which won’t fool the careful viewer’s eye.
Thus, I choose to use a pre-computed environment map: I simply use the cube map of the sky (see this post for more details).
II – Moving normal maps to create waves
Then, to break the perfect flatness of the water, I add 2 normal maps that moves at 2 different speeds. It creates a nice effect of moving waves. By the way, it’s the same trick that is used to create the waves on the main sea material.
III – Moving foam texture
This one is a simple classical moving texture added on top of the moving waves. To keep consistency with the rendering of the main sea, I use pure white for the foam, and I play with the alpha channel to modulate the visual impact.
IV – Distortion of the foam texture
Because I want the foam not to be straight on this moving water, I add distortion to it by altering the texture coordinates with a noise texture (actually, this is the wave normal map with a different scale and speed).
V – Day time aware material
VI – Tweaking and particles
The final difficulty is adjusting all the material parameters of this “fake” water, to match most closely the main sea water. Because the algorithms behind the rendering of these 2 water styles are different, it’s strictly impossible, but I have to minimize the visual gap.
As you can see on the above screenshots, for lake and other “sleeping” water planes, the differences with the main sea water can be obvious according to the camera viewing direction. But for the moment, I can’t do better.
Maybe, later, I’ll modify the main water rendering shader to make it structurally closer to the fake water one, so that it can be easier to have a similar look (without losing real reflection on the main water of course). Or maybe I’ll find anoter way to have real-time reflections on lakes too without hurting too much the GPU (I already tried… but failed… for now).
For waterfalls however, this fake water is quite OK, I guess because all waterfalls have the same material. By the way, I must add particles to create the splashing waters.
So, that’s all for today! I hope this detailed water material post was interesting for you…
And, I didn’t talk about it in this post, but I made a loooot of bug fixes thanks to all of you guys who tested the last demo. Thanks for your amazing feedback! I plan to release a new demo with lots of major fixes at the end of the week, so that new testers can find new bugs 😉
See you! Peace!