codersnotes

Shallow water refraction in Super Mario Galaxy June 27th, 2010

I've been playing Super Mario Galaxy 2 over the past few days, and it's fantastic. It's worth a study into how to achieve complex shader effects on the Wii.

For those not familiar with the Wii hardware, it's basically a Pixel Shader 1.1-esque unit, but with a fixed-function vertex pipe. The TEV, as it's known, can be programmed using assembler shaders. (we even wrote an assembler tool to do this at Treyarch).

Anyway, whilst playing I was puzzled by how they did some of their water effects, in particular the refraction. Refraction can sometimes be tricky, as if you're not careful you will pick up things from in front of the water surface and start refracting those instead.

Some poor refraction artifacts. Notice the edges around the barrels bleeding out into the water.

There's three basic methods to work around this. One is to render the underwater stuff to a separate texture, rather than trying to use the backbuffer. This sucks as you have to have more passes. Or you can read in the Z-buffer from the shader, and reject pixels that are in-front of the water surface. This sucks as it increases instruction count a lot, and is not really possible on the Wii either. Or you can sort your objects so you render the water surface before rendering the things in front of it, but this doesn't work if you have objects sticking through the water, and kills any Hi-Z rejection.

But, it turns out in Super Mario Galaxy there is a fourth way. If you watch very very carefully, it turns out the water is in fact not doing the refraction. It is not the water that wobbles, but the ground underneath. This only works if the distance between the water and the ground is small.

Genius.

Levels in SMG2 with shallow water like this, have no artifacts. (this screenshot may be SMG1, but I think it's the same there)

Written by Richard Mitton,

software engineer and travelling wizard.

Follow me on twitter: http://twitter.com/grumpygiant