I’ve come across a strange issue when using ambient occlusion textures. After working with Unity, I expect the AO texture to simply darken the material where the dark parts of the texture are. However, when using highly reflective materials, especially glossy ones, the AO behaves strangely in Playcanvas. Let’s go over some examples.
Here is a screenshot of a material inside Unity 5. It has black diffuse, white specular, and an AO texture. The only thing that changes is the smoothness value - from 0% on the left to 100% on the right:
Look at the far right image. See how only the darkest parts of the AO texture is visible, and how the lighter parts have faded away? It seems to me that as the glossiness increased, the contrast of the AO texture increased before applying it. This makes the AO look more like completely black, aliased blobs instead of smooth shadows. In addition to being affected by the glossiness value, the AO also seems to be affected by the viewing angle - the AO seems to show up more in grazing angles.
Let’s compare other objects. The same thing is going on here - glossiness at 0 on the left and 100% on the right. Here’s Unity:
I’d like to know if this effect is intentional or not. My bet is that it’s not, and that it calculates AO wrong. To me, AO is unusable on glossy materials if left as is.
PlayCanvas splits AO into diffuse ambient occlusion and specular occlusion (which can be turned on/off separately), what you see with glossy objects is SO.
Ambient occlusion approximates visibility of light, but if diffuse surfaces receive it from many directions (hemisphere), therefore making final lighting look blurred, glossy surfaces have more focused reflection. Multiplying diffuse AO and focused reflection is wrong.
Here’s an example of AO vs SO of different glossiness from mental ray:
Simulating correct behaviour isn’t simple though, as AO should smoothly converge to dark view-dependent reflections, and we don’t have enough information in an AO map.
The solution is hack, similar to what is described here, which is better than nothing: http://research.tri-ace.com/Data/cedec2011_RealtimePBR_Implementation_e.pptx
When using HDR maps, it can look better than AO multiplication, by removing still bright reflections from cavities.
I can understand, though, that in some scenarios you might want just a simple AO multiplication over reflection (because this hack is not perfect). I think it would be nice to be able to switch the way it works.
I see, the SO is supposed to prevent highlights through meshes. Isn’t Unity’s approach doing the same thing, only that it looks better? Where there is shadow in the AO map, the specularity is lessened. It seems to me that it’s the same thing in Playcanvas, only that the contrast in the AO is changed before applying it. Unity’s approach makes materials behave more predictable when changing the parameters.
It took me a while to figure out what I was looking at when seeing the black blobs. I know it is a hack, and not “correct”, but Unity’s approach looks much better. It also does a better job at simulating light falloff inside deep holes, instead of just clamping it to black:
(wireframe on left, Unity in middle, Playcanvas on right)
Of course, an even better solution would be to use screen space reflections or reflection probes. Well, and raytracing, but I don’t think we’re there quite yet
You might have to multiply your specular texture by your AO depending on how good your screen-space AO and self reflection is. Right now more often than not reflections are calculated with “light probes” that don’t provide enough fidelity for self masking and self reflection, so you end up with shiny recesses all around your model. And this is something you have to compensate for with your AO.
Wow this is great, that users can decide for themselves what workflow they want to use. Also, I love the fact that we get updates on-the-fly, instead of having to wait until a new version is released. Thanks a lot!