Technical Obstacles in the Use of Water in a 3D Game

I have written some blog posts in the previous incarnation of this web site, but I guess this is my first post for the official 7 Generation Games blog, so I will start off with a brief introduction for those who are not familiar with my role at 7 Generation Games.

I’m the guy that produces the 3D portion of the games we are developing. The games basically switch between textual instructional material, quizzes, movies that instruct or provide narrative bridges between stages of the game, 2D mini-games, and a 3D game that immerses the player in a three-dimensional landscape to explore, solve puzzles and apply lessons learned during the game. Hopefully, the student enjoys all aspects of the game, but the 3D portion provides a special incentive to advance in the game. I produce the final version of the 3D portions; of course, there is plenty of design input from members of our team and we make use of pre-existing assets where we can, but I put together the final version of the 3D world and write the code to implement gameplay.

For the upcoming game “Fish Lake” we had to revisit the way we implement water in the 3D world. In our “Spirit Lake” game, we have a lake and a river, but neither of these play an interesting role in the game itself, but are present only as part of the background scenery. In “Fish Lake,” water will play a much more active role in several parts of the game, and the implementation of water we used before would not begin to cover our requirements. So, I needed to revisit the issue of water.

AnnMaria thought this would be a good topic because it would be an example of how some problems you initially thought would be easy turn out to be difficult and vice versa. I can’t agree with the premise in this case because I never thought any use of water in a 3D game would be easy. It is true that the more I investigated, the more issues came up, but I thought it would be difficult from the start.

As a side note, I should point out that a lot of our game design consists of AnnMaria coming up with ideas and me telling her why it is impossible, inadvisable or impractical. We go back and forth but eventually I have to accept the fact that I can’t keep telling her everything is impossible, so finally I figure out a way to to it.

Water is Hard

…”hard” meaning “difficult” in this case. In a 3D computer generated scene, objects change their appearance based on their position relative to the viewer and the lighting of the scene, but at least the surface of a solid object doesn’t usually change shape from frame to frame. Water is dynamic. If the surface of the water doesn’t move in the scene, it simply won’t convincingly look like water.

Water can be transparent or translucent. So, you can see through it to some extent. It refracts the light from objects underneath the water, and to be really realistic the shape of those objects should appear to waver with the motion of the water.

Water can reflect, so if you put that in, all of the objects surrounding the body of water, as well as the sky itself, influence the appearance of the water surface.

How much of this actually goes into the simulation depends on how much graphic processing power you have and how realistic the water has to be.

For our “Spirit Lake” game, the water was part of the background and it was sufficient to make it an opaque blue surface with ripples that moved. “Fish Lake” will require much more from our water simulation than the background scenery it provided in the previous game. Again we will have a lake and a river, and we will have our player characters:

  • Paddling a canoe in the lake
  • Riding a canoe down a flowing river
  • Spearing fish
  • Bulding a dam

…and other things I’ve probably forgot to put down.

Unity 3D Game Engine

Unity 3D is the platform we are using to implement the 3D portions of the game. It is a game engine & editor that allows me to create the landscape, position the 3D models and program the interactions between the player and the 3D world. When a problem comes up with implementing some feature in the 3D world, Unity 3D provides three major resources:

  1. Unity 3D itself provides solutions to many of the most important and common problems encountered in producing a 3D game.
  2. Unity 3D provides a community forum and wiki where developers can discuss problems encountered and propose solutions.
  3. Unity 3D has an asset store where developers can buy and sell solutions.

Regarding water, Unity provides two built in solutions. There is “simple water” which is what we used in “Spirit Lake”. It gives the general impression of a body of water, but it has many shortcomings. Water can be translucent or transparent, it refracts light, and it can show reflections.

Unity Pro (the non-free version) provides “Pro Water” which corrects many of these deficiencies. It can look pretty realistic, and it has the important property that you can see through it to things under the surface. This is important for us because we need to put fish under the surface, and the player has to be able to see the fish in order to spear them.

There’s Water In My Boat!

Other issues that pop up: a lake or river is created basically by applying the water “texture” to a 3D surface. The surface is placed under the ground but depressions in the ground expose the water surface, thereby creating the lake or river (depending on the shape of the depression).

The problem here is, if you put a boat or canoe into the lake, the surface will cut through the convex boat and appear as water inside the boat.

For a boat with a deck this would not be a problem, because the deck would hide the water surface, But for an open boat like a canoe, the boat would always appear to be full of water.

Play the following movie to see what happens:

Fortunately, a couple of developers had already solved this problem and were kind enough to post the solution on Unity’s wiki. They solved it by writing a special shader.. A shader (to oversimplify) is a piece of code that tells the graphics processor how to render a surface. The surface of the canoe has a shader that tells the processor to use a wood texture to render the canoe surface. The water surface has a (much more complex) shader that tells the processor to make the surface look like water.

At any point in the image, the processor will determine which surface, of all the objects in the scene, is closest to the viewer (i.e. is in front) and will only use the shader of that surface (if the surface is not totally opaque, then it becomes more complicated, but that is the basic idea).

The new shader is applied to a surface that is the shape of the open part of the canoe, and the surface is places at that point, so it will be “in front” of the portion of the water surface that is in the canoe.

This shader tells the processor “just render the surface immediately behind me except for the water surface. If that is encountered, ignore it and render the next surface behind it.”

This is a very simple shader; it is only a couple of lines of code. However, in order to write it, you would have to know how to write a shader, which is not normally considered an elementary topic. I don’t know how to write one, but these fellows did and I used their shader with great results.

Play the following movie to see the fix in action:

At this point I had the basic minimum that we needed to implement the water for “Fish Lake,”  but there were additional issues that needed to be considered to produce a realistic simulation. We could do the game without addressing these issues, but it will look a lot better if we have solutions for them.

The issues are:

  • The water in the river needs to flow. Although this can be done with the build in water simulation in Unity, it doesn’t appear simple to change the direction of flow. This raises issues for our river if we don’t want it to to be completely straight.
  • We will have 3D figures paddling the canoe. In real life, when you move an oar the water, it creates visible waves in the water. If our simulated water doesn’t show a disturbance when the oar is moved, it will look funny.
  • We will have 3D figures thrusting spears into the water to catch fish. Again, if there is no disturbance in the water, it will look funny.

A search for a solution to these problems led me to the Unity Store, where all sorts of assets from 3D models to code libraries can be purchased. One of the water models, called Suimono (here’s a demo video (by the way, AnnMaria tells me Suimono means “water thing” in Japanese)) seemed to  fit the bill.

Watching The River Flow

First of all, it is possible to control the flow of water over a surface by assigning what is known in 3D modeling as a UV map. The UV map can be used to control the direction of water flow.

In order to use this feature, I had to create a surface that represented the shape of the river that I wanted, and then had to assign the appropriate UV map and import that surface into Unity 3D.

The 3D modeling program I use is Blender, and as usually, Blender was able to do the job but it took me a while to figure out how to get Blender to do it. I finally did and now I have a river that flows correctly.

Play the following movie to watch the river flow:

Second, Suimono is specifically designed to make it easy to have the water interact with other objects. This is the main selling point of Suimono. I am still in the midst of doing a proof of concept of this feature as we will use it in the game, but regardless of how that turns out, the face that we can correctly display a flowing river already solves the most important obstacle.