Normal Maps are great, but there are many more ways to improve the visual quality of 3D objects. For the Rocket Commander game we are happy with a little parallax mapping and some cool post screen shaders. If you are more ambitious about your game you probably want to implement glass shaders, reflection effects, cool water shaders, and more. This section gives a small overview about possible shaders you could write for your XNA graphics engine. There are many more examples available online or in the many shader books out there. Good examples are the Nvidia homepage, www.shadertech.com, the GPU Gems (by Nvidia), or Game Programming Gems books (by Charles River Media), or Shader X book series (by Charles River Media, edited by Wolfgang Engel). There is a lot that can be learned from these books, but in the end you will probably end up writing your shader code unless you find someone that does it for you.
Parallax mapping is sometimes also called offset mapping because the points are remapped, but usually offset mapping means that the original parallax mapping effect is taken to another level by going through several height layers in the pixel shader. Another popular name for offset mapping is steep parallax mapping, which was shown in a paper from Morgan McGuire and Max McGuire in April, 2005. The game F.E.A.R. is a prominent example of this technique. It uses parallax mapping with maybe two or three height layers, but the results are fine-tuned and look pretty good.
The steep parallax mapping approach is a little more complex and usually takes 20 or more height steps until it looks really good. The advantage is that you can also calculate self-shadowing (see Figure 7-22), which looks really amazing if you consider that all of this happens in the pixel shader, there is no actual 3D geometry, and it is all faked.
The major problem with this technique is the high cost associated with it. Not only will you spend a lot of time implementing this technique and trying to get it right, but more importantly it will cost an insane amount of Pixel Shader power to execute. The shader is about 20 times slower than a normal parallax mapping shader, and though it is possible to create cool looking scenes in demos with very few polygons, in a real game you will need a lot more than just one cool effect. Maybe it will be an option in the future to improve existing games or allow really high-end graphics hardware to make the game look even better.
Simulating glass is not that easy, at least if you try to get it right. The main problem with glass is that it does two things: it reflects the side of the world you are on and it refracts the world behind the glass. Reflection means that light from the viewer side of the glass is reflected like on a mirror and will be seen by the viewer, including himself if he stands in front of the glass and the lighting conditions are correct. Refraction means that the world behind the glass (for example, if you are looking outside through a window) is distorted a bit depending on the glass thickness, the structure, and even the color of the glass. This is especially true if you have a glass surface with a structure on it (like glass on the bathroom window).
To make things even more complicated glass does not always behave the same way. Viewing it from the top gives you other reflection values for reflection than viewing the glass from the side, which usually gives you a better reflection. If the lighting conditions are poor or the glass is dirty it might not be so reflective at all, and so on. There are many more options that could be considered.
Because you don’t have a lifetime to get it right and you just want it to work you usually leave out everything that is not really important and are still left with some cool looking effects (see Figure 7-23). You can find more information about the cars and the shaders in the last part of this book.
For glass you can get away with implementing a simple reflection shader, which reflects the sky cube box (see the next chapter for more information about the sky) on the glass. For more shiny metal surfaces or mirrors, just reflecting the sky might not be sufficient. You may have to think about reflecting the world around certain objects for more realistic effects. This is neither easy nor fast because for a complete reflection around a simple 3D object you would have to render a reflection cube map to show the world in every direction from that reflective material. In Direct3D 10 it is possible to render this in one step, but you still need a fast graphics card for this kind of dynamic update for materials in your engine. In DirectX 9 or XNA it will probably be too slow in most cases because you have to render the scene six times for every cube direction just for one materials reflective cube map.
Reflection can be a little bit simpler when you just reflect the world on a planar surface like a mirror. Now you only have to render the world mirrored on this surface once and you are good to go for your reflection effects. This technique is also used for many water shaders and it can look really cool, especially if you don’t just reflect the sky, but also the objects and effects of the world. Additionally, water has many effects (reflection, refraction, water color, water animation, waves, and so on), which can take a lot of time to fine-tune, but it can also be a lot of fun playing around with water shaders (see Figure 7-24).