• Register

This member has provided no bio about themself...

RSS My Blogs

Ambient Occlusion

Ambient occlusion (AO) is a powerful tool when it comes to making games visually appealing. Especially for indies, since you can give plain and simple geometry (like Avorion's) a great sense of depth and make it look more three-dimensional.

For those of you who don't know what ambient occlusion is exactly and how your game can benefit from it, have a look at the following screenshot:

Ambient Occlusion On / Off

This is an animation of a space station with and without ambient occlusion. It's easy to see that one of the scenes looks "better". You get an impression of depth, of plasticity. Ambient occlusion basically means that objects that are near each other "steal" light from each other, so they appear darker.

To calculate ambient occlusion, from each point on your model, you shoot n (random) rays (here 64) with a fixed length in a semisphere formation and check whether you hit other geometry.

aoskizzew

The more rays intersect with other geometry, the darker the point in space. There are more sophisticated approaches that take into account the distance of the intersection point to the ray origin, but in our case we'll just say we hit or we miss. We didn't necessarily need a physically correct approach, we only want something that looks decent.

AO Techniques and our Problem

There are various techniques for achieving ambient occlusion:

Usually you can do it in your 3D editor and bake it into textures like lightmaps, but then it won't work when your scene changes. In Avorion, players build their own ships or get them blown apart, so models change all the time and the texture atlas would have to be huge for decent quality.

Then there's SSAO (screen space ambient occlusion). It basically calculates ambient occlusion each frame based on what you see and the depth of your current screen image. SSAO didn't work either, because it largely depends on your current viewport and I wanted dark parts of spaceships to always be dark. Since SSAO is view-based the occlusion tends to change when you move your camera around.

Minecraft does ambient occlusion by stepping one or more blocks in each grid direction, to find out how many blocks there are and calculates a corresponding occlusion. But I can't step in any grid directions because in Avorion there is no grid.

The Solution

Since Avorion allows arbitrarily scaled blocks, there is no way to predict what shape the model is going to have. Plus the model changes all the time when players extend their ships or get them blown apart. So how do we solve this?

I found that the best way to solve this dilemma was vertex-based ambient occlusion. This way it's baked directly into the model and won't change when the camera moves. The great thing about vertex-based ambient occlusion is that you don't have to apply a blur to the result. Instead, the "blur" comes for free via the interpolations the GPU does between vertices!

That means now we'll be shooting rays from each vertex into the model. In order to get the ray intersections fast we used the bounding volume hierarchies that we had already from our collision model. This way every ray cast has a complexity of O(logn), which is pretty much the best we can get. And we needed the bounding volume hierarchy anyways for collision, so there were no additional costs here.

I did a first take on vertex-based occlusion and it turned out better than I had expected:

first

In this picture I'm using 64 samples per vertex, counting only hits and misses. It shoots fixed length rays depending on the normal of the vertex. 64 samples had the best tradeoff between performance and quality, above 64 there was nearly no difference in the result, but the performance hit got remarkable.

You can see several artifacts of the vertex-based SSAO model on the right side, where the grey block fades from grey to pitch black, and also in the middle of the space ship where there are blocks that are entirely black. That's be cause the vertices of these blocks are actually inside other blocks, so all sampled rays hit and the occlusion is black.

And there was another problem: Blocks can have any size. Even super large block sides only have 4 vertices to shadow, so if you place a small block in the middle of a large block side, it won't have any shadows because its 4 vertices are simply too far away from any geometry that could cast a shadow.

Screenshot271

Okay, how do we solve that? Well, we have to increase the resolution of the models. So: Tesselation! Since we needed the tesselation in the model to calculate the ambient occlusion, and some of our target hardware doesn't have tesselation shaders, we couldn't use a shader. Instead I wrote a quick algorithm that tesselates the sides of the of the blocks like this:

tesselation

Then we generate the ambient occlusion for the tesselated model based on the previous approach:

tesselatedocclusion

Looks pretty good already! You can see that there are dark areas on the big cube around the small cube and the quality around the intersections between the small and the big block is a lot higher. There's even a dark area on the top side of the big cube where the main part of the space ship is.

You can also still see the artifacts of the pitch-black vertices, but it's already a lot better and we finally settled for this approach, since we thought it looked good enough.

Then we one last problem: The ambient occlusion algorithm used random ray directions to collect the samples. Every time a user adds a block to a ship, the ambient occlusion would slightly change and create irritating flickering. We solved this by creating a predefined array of 64 fixed ray directions, so there is no more randomness going on.

Vertex-Based Lighting

The best part about this approach: You can use it backwards for vertex-based local ship lighting! We cast rays from light blocks towards all vertices on other blocks to achieve a sweet local ship light effect.

Screenshot260

Performance

The calculations for the ships in the pictures took less than half a second with -O3 on gcc. This includes tesselation, ambient occlusion with 64 samples per vertex and lighting calculations. While for these smaller ships it was blazingly fast, stations with thousands of big blocks can easily take 10 - 15 seconds to compute.

But we never had any illusions about the performance of large stations, so we moved the AO calculations into a separate thread. Now, when as the player gets near a station, the AO calculations are started, and while they're running the plain model is rendered.

Wrap Up

Alright, that's it! I'm sure there are plenty who know already about this stuff, but I still hope some of you guys learned something new today.

Cheers

- Koonschi

Koonschi's Twitter

Avorion Website

Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account:

X

Latest posts from @koonschi

Great news everyone! After performing well, #Avorion Patch 2.3.1 is now live on the default branch for everyone! It… T.co

Jan 19 2023

More news! We've made some updates to the #Avorion roadmap for 2023, check it out here: Avorion.fandom.com

Dec 23 2022

Very happy to announce that we've pushed more #Avorion performance improvements (especially loading screens, wooo!)… T.co

Dec 21 2022

We just set an #Avorion hotfix patch live that fixes a crash and some issues with fighters: Size 0 fighters as well… T.co

Nov 24 2022

After performing well on the beta branch, #Avorion patch 2.3 is now live! Improvements to rifts, rift missions, fig… T.co

Nov 22 2022

We've set a new #Avorion patch live on the beta branch! DLC modding & Steam achievements, new maintenance command,… T.co

Nov 8 2022

RT @PhilomenaSchwab: Hi I'm Philomena and I spent the past 3 years of my life making a weird game where you build a city on the back of… T.co

Sep 8 2022

RT @SimoRoth: Game Developer Searches: "Kill tweens efficiently" "Removing bones from parents" "Moving rigid bodies" "Problems s… T.co

Sep 8 2022

Feels so weird how some huge changes that take hours of investigating, refactoring, fixing, testing, and monitoring… T.co

Sep 8 2022

New #Avorion hotfix now live on the default branch, fixing some issues with rift missions crashing when starting an… T.co

Sep 8 2022