I was wondering how could I improve the looks of a simple tile map to make it look less blocky. I thought about developing an simple ambient occlusion shader, but at the same time I wanted to make it fast enough for mobile development. I wanted to make a method that doesn’t even require the use of OpenGL at all if I don’t want to.
The solution is pre-computed lightmaps which can be just composited over any texture to give it a smoother look even without any additional shading.
To get the desired effect, I had to generate a lightmap for every possible tile layout. Around every floor tile, there are 8 adjacent tiles which might contribute to our fake ambient occlusion. That gives us 256 separate tile configurations, but luckily, many of these are identical by applying simple transformations.
- By adding 90, 180 and 270 degree rotation, it cuts the number right down to 70.
- By adding mirroring and rotating the image by 0, 90, 180 and 270 degrees, it’s down to 51.
- By assuming that a wall to the top and to the left completely seals the top-left corner, regardless whether there is a wall tile to the top-left, it’s down to a nicely manageable 33.
Each layout configuration has a layout ID, which is the 8 adjacent tiles each represented by a bit, giving the 8-bit value between 0 and 255. To keep the rotation of layouts in the lightmap generator simple, the first bit represents the top-left corner, the other bits allocated in clockwise direction. Rotation is always clockwise, mirroring is done horizontally by swapping the following bits: 1-3, 4-8, 5-7.
After evaluating which lightmaps need to be generated, the process is quite simple. Create an image with dimensions three times that of the desired texture, fill the whole area with white and solid fill the wall tiles with the desired shade of gray. Then simply apply gaussian blur over the entire image and extract the middle tile as the finished lightmap texture.
At the end of the process, we have all our unique lightmaps ready to use:
Here’s the rendering of the lightmaps in a simple 2D scene:
For applying it over a texture, you just have to bake the lightmaps into a single texture, and composite them over it, for example by simply multiplying the colours in a pixel shader, the result is the first image in the article.
For more information and the generator code, check out the FakeTileAO project page.