OK. So this is “cool” enough to share.
I was thinking last night about ways to improve the visuals of larger object in a game scenario, such as architectural details or even entire buildings.
One thing in particular that I lack for these types of structures is ambient occlusion.
For models that use a single texture that is non-tiling- adding ambient occlusion is no problem at all. We can just multiply an ambient occlusion texture onto the color texture. Standard stuff, easy peasy.
But what if we have a side or the facade of a building? Which also happens to use tiling textures or even multiple textures for a single model?
This is where per vertex ambient occlusion is a valid option.
Before I go on any further I’d like to address an obvious question.
Why don’t I use screen space ambient occlusion?
The answer is simple: I don’t really like it.
Let me elaborate: In almost every game I’ve seen it used it looks pretty terrible.
I feel it requires way too much maintenance and tweaking to really be worth it. I like the concept, and future real time ambient occlusion techniques will surely be better. But for right now, I’ll stick to manual approaches like the one I’ll be talking about.
So. Per vertex ambient occlusion.
This should be no mystery to anyone who is familiar with the terms by themselves.
Basically what it is, however, is a set of data that’s stored for every vertex of a model, containing a brightness or color shift for that vertex.
We can then modulate the color of a shaded pixel on a model by this value.
With this simple approach, we can get cheap and fairly accurate ambient occlusion for any model.
A while back I wrote a simple ambient occlusion generator that worked on a per texel basis.
I remember that that approach was slow and was sorely limited by the texturing of the model that was being processed.
Think about it, these are the exact points I bring up in the beginning of this post.
We can’t have tiling textures and we can’t have shared parts of the texture.
Anyway. The knowledge I gained back then was enough to let me work this thing out without thinking twice.
There’s of course the drawback of tessellation. This approach does not go over well with very low-polygon models.
The data per vertex gets interpolated across faces, which means a huge triangle will get severely darkened if only one of its vertices is occluded.
This is not a real problem since my engine isn’t that hampered by triangle count, we can easily cram some extra triangles on there without trouble.
As with any ambient occlusion we get better results the more samples we use. More samples means we get a wider range of shading for any given vertex. We therefore get smoother results.
There’s also the possibility of blurring the shading across vertices to smooth things out even further if necessary.
Here’s a thing without anything special. It’s not very exciting and it’s hard to tell what’s what.
And here’s the same thing but with a simple ambient occlusion term. It’s easier to tell what shape this thing actually has.
Now, I’m aware that the results aren’t that appealing. But as I mentioned above, there are several things one can do to make the results more pleasant.
It’s also important to remember that cases like this won’t often happen in a game where there’s something that only has an entirely flat texture applied. Textures mask a lot of errors in shading and is in this case a very useful thing. We can in many cases just ignore processing the data further.
But blurring the result is definitely a step up when it comes to this. And that is the next thing I will get into. I’ll also make sure to get some more exciting models to show off, that thing above isn’t very appealing, is it?
Back to it. 🙂