Implementing different AO algo(GTAO) with GLSL

Did someone tried implementing different GLSL ambient occlusion algorithms in TD?

I found Ground truth-based ambient occlusion( (which considered to be a gold standard) implementation and adapted it to TD, but getting some funny results.

Would love to get some GLSL guru to take a look.

GTAO-AmbientOcclusionGLSLShader.toe (8.8 KB)


+1 this looks super nice. I’m not familiar with it but will take a look at the doc soon when I have some time.

Hi @vacuumhack, I’m taking a look at this code, and I haven’t fully absorbed everything going on yet but wanted to share a few errors and fixes I’ve found.

So in this area of the shader, you are creating the variable tc_original from sampling the color channels of the render.

void main()
	vec2 tc_original = texture(sTD2DInputs[0],;
	// Depth of the current pixel
	float dhere = textureLod(sTD2DInputs[1], tc_original, 0.0).x;
	// Vector from camera to the current pixel's position
	vec3 ray = GetCameraVec(tc_original) * dhere;
	const float normalSampleDist = 1.0;

I think this variable is meant to be the UV coordinates. Not sure what tc stands for, but regardless when I assign to it, get rid of the color render input to the top, put the depth render there, and change all references of sTD2DInputs[1] to sTD2DInputs[0] I get this:

This seems more like AO, but there’s a few problems. First, there is an invisible plane cutting things off. This is the depth channel, it shouldn’t be 8 bit ever, you almost always more range of values than that. After I changed it to 16 bit depth with out changing anything else, got this:

There’s still some weird stuff going on that I haven’t figured out yet.

Whats’ up with that shadow along the bottom of the image? it was in both images, but changing depth fixed the outline around the edge. Maybe an artifact of this type of AO? maybe too high of a AO distance? Does this method require calculating AO past the normal edges of the render, so that the problem areas can be cropped or something later? I’ve heard of screen space algo’s requiring this.

Also, when you zoom in there’s a weird halo around the geometry? This gets WAY worse when the depth mode is set to 32 bit instead of 16 bit, so it seems related to the contrast. Perhaps this AO method requires a backplane of the scene ? Not sure. Curious if you have insights here:

Lastly (I think haha) There is obviously some intentional (I think?) dithering going on here, maybe to reduce the per frame load, which is spread out over time in some kind of feedback network? I assume you are saving that step for last but wanted to point it out none the less.

I’ll see what else I can find, but wanted to share those findings so far. I’m very interested in a better AO for TD as well that isn’t a resource hog. Nice work so far!

GTAO-AmbientOcclusionGLSLShader-LucasEdit.2.toe (8.9 KB)

Ok so I also noticed that if I rendered out the reconstructed normal there were some significant artifacts:

I improved these somewhat by setting depth to 32 bit instead of 16.

Ah but now I see where the strong halo was coming from @ 32 bit depth. there are a bunch of NAN pixels around the edges. If you can fix the NAN pixels, this solution is pretty decent.

Still though, normal reconstruction suffers at the edges of objects, where the neighboring pixel is really far or really close.

I’ve read of some better ways to recreate normals that do a very fine job visually, but to make it optimized, needs to be done on a compute shader. Can read more here:

Anyways, to keep it simple for now and focus on getting the whole thing working I just piped in the rendered world space normals in and sampling from the second input.

Anyways, got to this point:

Will jump back in here if I get any further.
GTAO-AmbientOcclusionGLSLShader-LucasEdit.4.toe (9.4 KB)


In the original shader it was:

The normalized coordinates of the current pixel, range 0.0 … 1.0

This is great findings man, thanks for all the improvements.

1 Like

Ok a bit more tinkering and progress.

Referencing these two gists:

If anyone wants to take a stab at implementing that temporal denoising compute shader that’d be awesome :sweat_smile: I’m not even sure it’s possible to do in TD, given the barriers and all the other fancy stuff.

GTAO-AmbientOcclusionGLSLShader-LucasEdit.19.toe (12.6 KB)

1 Like

I definitely have gotten sucked into this problem. I have made more progress :upside_down_face:

So, the temporal denoising mentioned earlier is a way of spreading out the cost of the shader across many frames. To make it look good, it’s actually more complicated than just averaging the last X number of frames.

Essentially, there’s a 2 level deep nested for loop in the AO shader, and the idea is to take the deeper for loop out, and iterate over that across frames, not within a frame.

SSAO types generally have a DIRECTIONS attribute, and a NUMSTEPS attribute, both of which are used to determine how many loops are done. Increasing either of these makes quality go up in one of two ways, and they are expensive.

I found a simpler temporal denoiser here which looks way doable but I haven’t taken a stab at implementing it yet.

Right now I’m just trying to fix bugs and get it looking right, and I think it’s ALMOST there. There’s an annoying dark thin fringe around GTAO’s objects silhouette. Not sure what that’s about, maybe it’s normal.

Below you can see a comparison between TD’s SSAO top, and the GTAO version below. They are slightly different, but both have what I think are roughly comparable settings. Both are just as expensive more or less. However GTAO looks infinitely better, especially at lower quality settings.

GTAO at the moment does not have any optimizations spatial or temporal. So, it’s just brute force calculating full AO every frame.

GTAO is also softer. I personally like this, but if you need it to be more contrasty like SSAO just use a level top + gamma of .455 and it gets pretty close to the TD version. Could also do this in the shader to save a bit of gpu mem/cpu cycles etc.

btw, be sure to click the expand arrows on that image, or you won’t see all of it.

GTAO-AmbientOcclusionGLSLShader-LucasEdit.20.toe (12.8 KB)


@lucasm you are legend, man. This results are astonishing. :heart_eyes: :fire:

Glad it’s useful :slight_smile: TD needs a refresher on the AO solution IMO, been in the back of my mind for a while. There’s some other decent ones but they are heavy too. hopefully some temporal denoising will make things a lot faster.

There’s some really great material in this guys repo:

highly recommend digging around there. I was able to open and run from visual studio with out any issues as well, so very easy to try things out natively there too.

Here’s a componentized version of the Asylum GTAO. Still feel there’s some improvements to make, and certainly optimizations but it’s quite usable if you turn down the settings. Also, this ao seems to have a directional component to it. Not sure if that’s by design… or something done wrong.

Here’s a donut where you can see what I mean. the bottom is darkened even though there’s nothing down there:

Asylum_GTAO.tox (13.7 KB)

Huh? Interesting, I will take a look later.
Thanks for the work, Lucas.