A vertex occlusion baking guide

Published November 26, 2014
Advertisement
'allo

Finally got around to add an ambient occlusion baker to the pipeline.

I'm baking it all to vertex maps, as these give generally good results and avoid the hassle and memory demands of having to assign unique texture space to every triangle in a mesh. Meaning I could no longer use the render-to-texture-only routines provided by Modo. Also, lots of instanced meshes (grass, trees, etc.) don't exist until mesh compilation time, which caused them to be excluded from any in-modeller performed ray tests. And then I don't like having to bake all that gpu stuff by hand, so this was always going to be automated one day. smile.png

Occlusion testing itself is pretty straightforward, but here are some findings specific to creating per-vertex maps:

- Don't only evaluate rays at vertex positions, but sample from various points over the surface of the vertex' neighboring triangles - this avoids local undersampling of the surrounding geometry. Worse case example: most of a vertex' connecting face area may actually be un-occluded, but if the vertex itself is occluded by some small object, all rays fired from its position will be too and the vertex will show up completely dark. Multisampling smooths out such deficiencies.

occlusionbake1.png

- Use a series of sample positions combined with a series of ray directions that spread out evenly over respectively a triangle's area and a halfsphere - precomputed Poisson distributions work well. It's not too relevant which point fires which ray; triangles tend to be small compared to their environment, which keeps rays from converging too much once they fan out into the scene.

occlusionbake2.png

- Once you have a bunch of per-triangel occlusion values, you'll need to weld them together to form per-vertex values. Normals are usually welded based on some angle threshold and my first idea was to use a similar threshold, but specific to occlusion values. Turns out it's better to have them weld along with the normal angles: if the normals weld, the occlusion values weld too (or any weight/color map value really). What this really means is that you use any lighting discontinuities caused by unwelded triangle normals as an excuse to keep more triangle-specific occlusion data around as well (not averaging at the vertex will result in higher graphical fidelity), but only then, as to avoid a too-faceted look. It also results in the least amount of duplicated vertices needed in a vertex buffer.

render021.png
14 likes 7 comments

Comments

riuthamus

I wish i could grab you up! The stuff you are doing is amazing.

November 26, 2014 03:05 PM
ongamex92

So basically something similar to spherical harmonics?

November 27, 2014 11:53 PM
eppo

thanks Riu!

@imoogiBG: this is much simpler than that. SH techniques try to compress all low-frequency environmental detail - this is just a single term that represents how much light on average can reach a vertex.

November 28, 2014 09:39 AM
TheChubu

I wish i could grab you up!

If_you_know_what_I_mean..png

November 30, 2014 07:37 AM
alek314??

Nice screen shot!

Here are some questions:

What about instancing? Like i have 10 trees and each of them would have different occlusion data, how do you manage to put them into one draw call?

And the dark part between glass blade, are they made by ssao?

December 02, 2014 09:56 AM
Althar

Impressive - would you be able to share with us a screenshot of the AO on its own?

December 02, 2014 11:24 PM
eppo

@alek314??: For every face in every instance I bake the average occlusion into a (shared) vertex map.
Then every instance gets an additional occlusion term which is its own average (for all its faces) divided by the total average of all instances. This works pretty well because occlusion conditions between different instances tend to be fairly identical - they have the same self-occlusion, trees have foliage growing in the same places and they all have an occluding ground-plane of some sorts.

As for the darkening underneath grass patches: I've set the same texture that's used to modulate grass-growth as an

multiplier for occlusion.

no texturing, ambient diffuse + spec only: link

December 05, 2014 10:17 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement