AO's gets a weird shading when material is set to Metallic


I’m unsure if this is a bug or not, but I’m having a hard time figuring out why the AO’s look so weird, when I set the material to be fully Metallic.
This is how the materials look in Babylon, notice the weird banding black shading on the 4 fully metallic objects:

This is how the same GLB looks in another model viewer:

Since I’m new, I can’t upload the GLB here, but here is a link to the project file.

Note: I used 3DsMax to export from.

This comes from a special trick our PBR is using called radiance occlusion :

You can disable it in the import callback. Also in your render it is strange AO is impacting metal at all ?

@ Linkitch I’ve recently noticed this same issue and I’m fairly certain it is a bug. I’ve started using AO bake in in my GLTF material pipeline. The AO should only be mixed with the diffuse light. 100% pure metal does reflect any diffuse light as far as I know, so the way it is mixed on metal is wrong. I don’t think there should be any visible AO visible on pure metal at all technically (please correct if wrong).

Interestingly it seems Three.js gets this wrong too but not quite as drastically.

Will you please point me to the right slide in the power point? I can’t find anything explaining ‘radiance occlusion’.

Here is how it looks in Babylon if you disable all the radiance occlusion after loading:

scene.materials.forEach((m) => m.useRadianceOcclusion = false);

Oh that looks more along the lines of what I was expecting, thank you!
Can you elaborate more about the math on the radiance occlusion and why it is enabled by default?

Three.js must be applying some different math in this case because the darkness of the black area in babylon is very aggressive.

I just read the whole power point and it looks like they’re calling their technique “Ambient Specular Occlusion” abbreviated AS? Which seems to combine a non-physical based ambient occlusion and specular occlusion they have defined.

Slide with the final color calculation for anybody who cares:

What I don’t understand is why the effect is so dark in babylonjs sandbox when ultimately the result after the lerp should be multiplied by the AO. I don’t think this is implemented properly, though I can’t fully understand the relation to GLTF AO channel since this power point includes totally different calculation for the Specular Occlusion that would be the factor for interpolation between the ambient occlusion multiplied by the diffuse lighting and the specular light. Can anybody explain why it’s so dark? I haven’t looked at the shader yet (and probably wont before sleeping) but I’m not sure how this effect they’re describing can be achieved with just the AO channel from GLTF.

Final realization:
I can maybe understand why the blacks are so harsh considering it seems this game is using shininess rendering model which I’m not sure repsents metal properties the same way, meaning when they lerp 1.0 shininess diffuse and specular it may not actually be the same as lerping 1.0 metalness since there is probably still some light in diffuse channel. Maybe the intensity of black is the result of the lerp between diffuse(totally black) and specular color, then subsequently being multiplied again by AO mask (aka will end up being twice as black as you probably want). Hopefully whoever wrote the shader can give insight.

@ Linkitch I plan to investigate the shader soon because this is ruining the aesthetic of many products I showcase on the web. Will follow up with the modified fragment shader that just multiplies the AO with the final color if you’re interested. While not physically correct it’s probably closer to what you want since having no AO weight on metals will cause complex metal scenes to look just as bad as they always do.

That sounds great. I would very much appreciate getting ahold of the shader you come up with.

Here is the implementation Babylon.js/pbrIBLFunctions.fx at master · BabylonJS/Babylon.js · GitHub

I d be really grateful if you come up with smthg not having those issues :slight_smile: I can definitely integrate it back in the library.