Thursday, 28 June 2012

Engine Design - Water (Ocean)

Now, once I had a terrain object I thought it would be great to get a water model to go with it. I thought I would just use the terrain class and modify it so that it was flat. I then needed a shader to do my water effect, and being new to all this 3D stuff and HLSL, did not have the skills to write my own, so I had a mooch on line and found NVIDIA's Ocean shader, with a few tweaks I got it working with my engine.
I am going to give you the whole class at the end along with the modified shader. What I will do now is show the effects of various parameter setting's.

Basic Water
Here is a basic implementation of the class

As you can see, in the picture above, I am reflecting the surrounding skybox and the bumpmap is also applied. The wave amplitude and frequency are set to 0 so you cant see any waves in this example.

RCWater water = new RCWater("Content/Textures/SkyBox/HazyMind/cubeMap", "Content/Textures/Terrain/waves2", "water");
water.Width = 128;
water.Height = 128;
water.WaveFrequency = .0f;
water.WaveAmplitude = 0f;
water.DeepWaterColor = Color.Navy.ToVector4();
water.ShallowWaterColor = Color.DarkSeaGreen.ToVector4();
water.ReflectionColor = Color.DarkGray.ToVector4();
water.ReflectionAmount = 0.7f;
water.Position = new Vector3(0, -1, 0);
water.AnimationSpeed = .05f;
game.Scene.AddObject(water, "water");

This is the bumpmap I am using to ripple the surface of the water

If I remove the bump map from the render this is the effect

Kinda takes the depth out of the water doesn't it.

You can manage the bump height with the BumpMapHeight parameter
water.BumpMapHeight = 0.1f;

The initial picture above uses the default BumpMapHeight of 0.1 the best range is from 0 to 2, so here are both those extremes

With a BumpMapHeight of 0, the water renders like still water, no ripples at all.

With a BumpMapHeight of 2, the water renders like a raging river

OK, I will now set the BumpMapHeight back to default and start creating some waves.

As you can see this is a nice wave effect, this was done by setting the wave amplitude to 1 and the frequency to .1

water.WaveFrequency = .1f;
water.WaveAmplitude = 1f;

Lets see what this looks like now with the maximum recommended BumpMapHeight of 2

Now that just makes me feel a little sea sick...

Water Color
All the examples so far have been setting the DeepWaterColor to Navy, ShallowWaterColor to DarkSeaGreen and the ReflectionColor to DarkGrey, but as you guessed you can alter these colors too.
So with the following parameter settings

water.DeepWaterColor = Color.Red.ToVector4();
water.ShallowWaterColor = Color.Gold.ToVector4();
water.ReflectionColor = Color.Black.ToVector4();

You get this effect (keeping the frequency and bump height map as before)

Just to clarify the DeepWaterColor and the ShallowWaterColor parameters. In the next image I have set the parameters like this

water.WaveFrequency = .0f;
water.WaveAmplitude = 0f;
water.DeepWaterColor = Color.Gold.ToVector4();
water.ShallowWaterColor = Color.Red.ToVector4();
water.ReflectionColor = Color.DarkGray.ToVector4();

Giving this result

You can see the water closest to the camera is Gold colored where the water in the distance is Red, this gives that deep ocean effect.

"HALO" sparkle effect
In the origional shader you could either have this effect on or off, this is now switchable via the sparkle parameter.

water.Sparkle = true;

Sparkle On

Sparkle Off

Transparent Water
So what if you want to be able to see the fish swimming in your Ocean? Well you can do this by simply setting the AlphaBlendColor parameter like this

water.DeepWaterColor = Color.Navy.ToVector4();
water.ShallowWaterColor = Color.DarkSeaGreen.ToVector4();
water.ReflectionColor = Color.DarkGray.ToVector4();
water.AlphaBlendColor = Color.White;

So here is the ocean rendered without the AlphaBlendColor parameter being set and then with it set as in the code snippet above.

You still get all the lovely reflection and bump effects, they are just now rendered against a transparent mesh.

This is a very configurable shader and coupled with my RCWater class is easily accessible. As you can see in the images above it can be used in a variety of ways and I have only really touched on the possible parameter variations. However, this shader is GPU heavy, but then I am running it on my laptop which is not exactly designed for high performance 3D rendering.

[Code and shader would be here, but can't post, see old post for this]

So my next post will be on my Fire class and it's shader.

Posted Mon, Oct 15 2007 3:52 PM by Charles Humphrey | Add post to favorites | Add blog to favorites
Filed under: Randomchaos 3D Engine, Water, XNA 1.0 [Edit Tags]

No comments:

Post a Comment