Fake Ambient Occlusion Trick for Games

Written by Ithai

It’s a new year and a fresh start. Time to work on Fly ‘n’ Fight.

The first thing I did was teaching my pilot to shoot booster crates. While working on the crate model and animation, I found a cheap little trick to fake dynamic ambient occlusion for animated objects in games.

I modeled a simple crate in Blender and then hand-painted a wooden-looking texture. To give it a worn, realistic look, I added layered baked ambient occlusion.

Crate with Ambient Occlusion

This looked great when the crate was static - until I animated it.

Animated Crate with Ambient Occlusion

Surely enough, the static ambient occlusion texture does not play well when a model is animated.

Avoid Premature Optimizations?

Having suffered the misery of optimizing Fly ‘n’ Write for mobile and specifically for iPhone4, I decided I need to be a bit more conservative. I didn’t want to overload my 3D pipeline in such an early stage.

I needed a way to dynamically change the object ambient occlusion effect alongside with its animation and I needed this to be cheap.

Texture Alpha channel is your friend

What I came up with was using the texture map alpha channel to store the ambient occlusion layer. When the alpha channel is not used in a model, it’s the perfect place to store extra per-pixel metadata.

Crate Texture with AO in alpha channel

I then modified the GamePlay textured object shader to apply the alpha value as an AO multiplier based on an additional shader parameter.

uniform float u_modulateAO;
...
_baseColor = texture2D(u_diffuseTexture, v_texCoord);
...
gl_FragColor.a = 1.0;
gl_FragColor.rgb *= clamp(_baseColor.a+u_modulateAO,0.0,1.0);

Binding the shader parameter to the animation completed the hack, resulting a fake dynamic ambient occlusion that’s cheap on resources.

float FlyAndFight::getCrateAOFactor() const
{
    return _crate_clip_explode->getAnimationPos();
}

void FlyAndFight::initialize()
{
    ...
    _crate_shader->getParameter("u_modulateAO")->bindValue(this,&FlyAndFight::getCrateAOFactor);
    ...
}

This technique can be used for other effects as well, such as glow, specularity, glitter and the likes.

Fly ‘n’ Fight is now in progress