View Full Version : A Revisit to Light Based AO

01 January 2011, 11:00 PM
I started a thread a while ago talking about AO and how it could possibly be set up using lights or rather, use lights to exclude AO. I didn't have time to tie the ends then but now that I do, I was hoping to revisit it. The idea of light based AO is based off a Pigeon Impossible Podcast (#21 I think) video.....


If you open the attached file and render and what should happen is the surface luminance should cause the mib_amb_occlusion node to be constrained to how lit the objects in your scene are. As you move your light's focus, the AO moves with it. Everything else is white. This is EXACTLY what I want EXCEPT for one small thing.......

If you have two objects close to each other or intersecting, the AO on the individual object will look fine but the AO that occurs where the objects meet is screwed up (and you can clearly see this in the example file I posted).

My theory is that the diffuse of the sphere/plane is getting in the way of the AO, as if they are dividing between each other. I've tried a few solutions but no dice, is there a workaround that will remove the artifacts from the AO?

01 January 2011, 12:35 AM
Inverting the blend color color inputs 1 and 2 reveals the problem. If everything were running fine, the light should have shone a flat white color because I specified the area where the light was shining to be white and the rest AO. Instead, there's still some dark there. I tried doing a multitude of different connections and inverses but I still have yet to fix the artifact. Come anyone offer some advice please?

01 January 2011, 02:04 AM
If you connect the surfaceLuminance output directly to the surface shader outColor you can see how the mask will be and there's is the "problem". The diffuse is drive the mask in that way.
You can try contrasting that (i put a contras node set to 1 but with the bias at .001) or maybe you can try using other shading models to drive the mask.

Something that i recommend is to put a clamp node to keep the values between 0 and 1 (i think that if your light has HDR values it can cause problems).

those are really my .0000002 cents. Hope it helps

01 January 2011, 02:45 AM
If by 'light based AO' you mean that practical lights casting on objects should 'illuminate' the objects and thus remove the ambient shadow, then there is another approach to this. It is based on comping passes differently than doing a multiply operand with you AO over your diffuse, because this throws the shadow over everything.

Here's a link to Zap's approach, and in particular you can pay attention to the diagram.

You can integrate this approach by setting up the ambient lighting inside the "ambient" component of your materials, and then breaking off the passes. You can do this using AO shaders, and even create color bleed. For instance create an IBL, put in your env HDR, and set your AO shader mode to 1. Use a blurred env map, no need to have it high res. Your ambient lighting is driven by the AO shader and HRD map, no final gather needed here. Then just set up spots, etc...

Zap's post will then tell you how to properly comp your passes. The comp math should actually work even if you use a separate traditional AO element, as long as you comp if with your diffuse material color first.

01 January 2011, 03:24 AM
Hello, thanks for your replies! Looking over both of your approaches, I may not be fully understanding what you mean but, to make sure, I want to try to reword what I mean by Light-Based AO. When I wrote light-based AO, I meant I wanted to have ambient occlusion bouncing off objects in my scene but only wherever the light was shining. In other words, the rest of the scene is white (so it won't be affected when I multiply the pass in post) but Maya will calculate AO with respect to where a light is shining. If I increase the cone angle, more AO will show. If I move the light around, the AO gets revealed in different areas along with it, etc. That said, I hope to try both of your suggestions soon but I just wanted to throw that out there in case you misunderstood (if not me).

01 January 2011, 06:12 AM
Couldn't you render out a separate pass just for that light, then use that as a mask for an AO layer?

01 January 2011, 10:34 AM
Korinkite and I went through this before, and if you truly want to do it in the same manner as Pidgeon Impossible, you will do it in compositing.

01 January 2011, 11:52 AM
Hello MasonDoran~. I hope you're not offended by the new thread, I did appreciate your suggestions but the thread didn't fully answer answer the thought and I didn't want to bring a dead one up again.

Looks like everyone is saying just mask it in post which is fairly expected. One last question regarding the topic though if I may and then I'll drop it. Is there a way to sample the light intensity of a given point (without surface luminance)? If there's a light with intensity of 17 shining on something for example. Could you sample the object to see where it's 17, where it drops off to 16, 14, 10, etc. to 0? I'm positive this can be done because I thought I saw a forum mention it in passing but I couldn't find it again.


I got the system to work using a condition node instead of a blender. The first term is driven by the surfaceLum, false is the output of a simple white ramp and true is the AO. This outputs the AO as defined by the light source. Only issue is, surface luminance, it seems, only outputs values of 0 or 1. It doesn't account for/if light source drop off or the penumbra angle falloff. And so now my question, again, still stands. I'd like to be able to source the light's intensity values and clamp it to a scale of 0 (dark) to 1 (where the light hits most) which can then be multiplied over the AO before rendering. This will get the falloff. I don't know of a node that can register the light intensity though. I thought surface luminance would work but it doesn't. Could someone please assist? P.S. I can't use the light as a mask in post at this point because of the "problem" that I spoke of before. The mask will not work correctly).

01 January 2011, 04:07 PM
I went back and read the other thread and I'm not quite sure why you're reluctant to use compositing; the node setup just seems really complicated. What is the visual goal (i.e., why the effort invested in this)? Is there a specific advantage to achieving it in-render?

01 January 2011, 04:18 PM
The reason is because, in very large scale scenes, sampling needs to be through the roof to get your AO to look passable in render. Composited or not. The other option is to bake AO but two conditions must be set for large scenes. The first is that your baked AO texture would have to be several gigabytes just to avoid artifacts. If you don't have UVs set up because the scene is massive that's another problem entirely.

I plan to use the coming months to make an animation in a city setting. In these scenes, I'll have very heavy DOF so I know that the audience won't even see much of the AO. So why calculate AO in places where no one will notice the difference?

My plan is to just used raytraced shadows to define the objects in the background and foreground and AO only in certain, key places.

If you render out an AO pass and then mask it, you still have to render the entire AO scene so really, what would be the use in masking at this point? Just use the AO pass without a mask.

It's for a significant increase in render speed with not that much loss of quality. The light-based AO would be very scene specific but, where it can be used, it saves a lot of time.

01 January 2011, 04:51 PM
In that case, wouldn't it be easier to use an AO pass on a separate render layer that only contains geometry that will be seen? That way you're only rendering the AO once, rather than every time you re-render your beauty pass.

01 January 2011, 05:44 PM
In a way, that methodology is kind of what I'm going for. What I assume you suggest is to invert the brights and darks on a mib_amb_occlusion and invert it in post so the background is white and the AO is only black where geometry is shone. Either that or set your background to white when you render out AO. The only way I could explain how what you're suggesting and what I'm talking about is that, although you'd only have to render once, if I move the camera away from the area that you apply AO on somewhere else, you'd need to have a method of having the AO follow it. I figured a great way of exposing/hiding areas of the AO dynamically would be to use a light right in the render but not via masking in post. Hiding/unhiding objects in a separate layer won't create a falloff and the point where the AO ends would probably be too obvious even with heavy blurring applied.

01 January 2011, 07:04 PM
OK I understand what you are trying to do. What I previously posted is not really relevant then.
I couldn't open your scene at work b/c they use maya 2009 here... But I think I understand how your shader setup is. If you have a setup that essentially blends between one white shader and one AO shader based on surface luminance, I can tell your approach is not going to save you much rendering time, either. Occlusion rays will still be evaluated, I'm afraid, in places where is no 'light' or 'focus'. Though they won't show because you are essentially evaluating the final color output after the AO and shader nodes are calculated.

I may be wrong on this, and testing render times would be the ultimate way to see whether this works at all and is worth trying to achieve.

But if you want to save yourself rendering time because you must render a huge cityscape and do a fly through, for instance, here are some suggestions:

Set your AO's max distance to a reasonable value. Occlusion rays stop tracing once max distance is reached. If you leave it to 0, then every object in your scene evaluates every other object to see whether it is within occlusion evaluation. That's when AO passes take a huge amount of time. You must limit what gets evaluated. Then use falloff and spread and color to tweak if your shadows are not to your liking. The smaller your max distance value, the faster the AO will render.

Next, you should try to bake that into multiple textures, arranged based on camera path so that hero buildings get more detailed AO maps. Sorry to break it to you, but in production you sometimes have to create more work for specific situations than you would like. There isn't always a smart trick you can rely on. But don't give up.

Another suggestion is to attach a sampler info, a ramp and a set range node to the Ao samples, that way you can use distance from camera to drive the amount of samples, or better yet, you can use a projected circular ramp to drive samples and max distance on your AO shader. When you move the ramp node in your scene, it will tell the AO shader to send 'long' rays only in the 'focused' area. Where the ramp is black, max distance could be a small nonzero value (as zero means infinite evaluation, which is what you don't want) and then your AO would evaluate really fast. Also you would get the falloff you need, with keyable control. This is in theory, as I don't have the time to test it out for you...

But personally, for a large environment with lots of geometry, I would forego the AO shader and create an ambient shadow using final gather. It actually renders faster...Try the physical suan and sky shader, too...

01 January 2011, 10:31 PM
Thanks for your reply daddyo. In the back of my mind, I had hoped that not to be the case but it's looks like you confirmed it. I will do some render tests later on but I think the idea is closed.

I had some time so I tried out the sample distance that you described but wasn't able to see any significant results although I think another way might work. Oh, also if you plan to use distance to change AO samples, you'll need to round the output because samples only works in integers. I don't know if there's a utility out there that can floor a function but with an expression:

float $float = `getAttr "[your set range utility].[whatever your preferred output is]"`;

float $floorFloat = floor ( $float + 0.5 );

[your ambient occlusion mib texture here].samples = $floorFloat

Your other suggestions as well are extremely helpful and greatly appreciated. Thank you very much for the post and to all others that have been helping me out. I won't pursue the light based shader but you've all left me with a lot to think about!

01 January 2011, 01:36 AM
Yeah if I recall my testing, it seems that the speed of the AO pass is directly proportional to the amount of geometry polys assigned to it. At some point the AO algorithm tallies up surface vertices in the scene and starts shooting rays from them. The more polys, the more calculations. Intrisically, it must shoot rays everywhere without culling faces that are not in camera, because it needs to count them for the AO to do its job. FG based ambient shading seems to be a lot faster in large scenes. Maybe because the FG map first shoots rays to create a map of what is visible to the camera, and contributes lighting based on these points alone.

I once rendered a scene full HD, with 20 million polys (paint fx) in about 10 minutes with FG... AO would have taken much more than that.

Good luck to you!

CGTalk Moderation
01 January 2011, 01:36 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.