So we’ve all probably heard of Viva Pinãta for the XBox 360, which was released fall 2006. It has a quite distinctive and remarkable graphics style; very colorful ofcourse, but also very detailed and rich in stuff happening on the screen. It’s a kids game obviously, and the game itself is not primarily aimed at people like myself who enjoy the virtues of brutality in Gears of War. However, the graphical techniques used in Viva Pinãta game are pretty cool; in fact, the game was nominated for an award for outstanding achievement in visual engineering. The pinãtas have a nice paper-mâché-like fur and the grass is done in a similar style.
So, how is it done? The technique used is commonly called shell rendering, and it is used widely in various games on different platforms. Shadow of the Colossus on PS2 uses it for furifying its colossal creatures, and Super Mario Galaxy on Wii uses it for some of the enemies and for example for the queen bee in the bee world. The trick is to have several additional layers of geometry above your mesh, mapped with a texture that contains random or ordered pixel data (See picture). It’s a cheap method if you compare it to instancing geometry for each fur hair, because now you only have to render the model for each layer of fur. Thats obviously still a conciderable amount of extra polygons if you have a detailed model, but not nearly as much as if you would do it with instanced geometry. Obviously there are some tricks that make it even cheaper. You could for instance take a lower level of detail model to render the fur layers. For grass, you could maybe combine the method with a geometry based LOD technique (like geomipmapping for example) and only render the grass for the terrain that is within certain distance to the viewpoint.
There are also some parameters that you can derive from this method. You can determine:
- The amount of pixels in the fur texture (The density basically)
- The distance between layers. Long hair/grass or short, its all possible. You can even have variations in height by storing the height in the fur texture as the value of a color. Since you have RGB you can store up to 256*256*256 values (you will need the alpha for other things, like a lerp between black and the base texture color for example)
- The displacement of the layers with respect to eachother. You can for example apply gravity or wind making the fur hang or the grass wave. Make the displacement non linear, and the fur/grass will hang in a certain way.
- The amount of layers used. This is useful if the camera is making a low angle with the furred plane, or when the displacement between two layers is too big (and thus gaps emerge between two layers).
- The thickness of the fur hairs. This is done by scaling the texture (mapping it differently) or by means of populating (for example, sample a random position and add pixels for the consequtive two pixels to get a nice row)
There are lots of posibilities by combining the different attributes, some which I can’t even imagine at this time. I would be really interested in the way Rare did the pinãta paper-mâchée fur so neat and tidy for one 🙂 Anyway, here is an example of how grass could look (its a bit coarser than in Viva Pinãta but that can easiliy be adjusted by controlling the thickness parameter):
I made this in XNA with help of Catalin Zima’s fur example on Ziggyware.