Error in glTF PBR shader
Description
Currently, mixed materials (e.g. metallic value of 0.5) are not energy conserving and therefore displayed incorrectly. This issue highlights the error in the glTF spec: https://github.com/KhronosGroup/glTF/issues/2386 Here you can see the shader refactoring we had to do in the glTF-Sample-Viewer to fix the issue: https://github.com/KhronosGroup/glTF-Sample-Viewer/pull/556
The issue is clearly visible with the furnace test and mixed materials with iridescence extension (using a premixed F0 has a big impact on the visual output)
Reproduction steps
- Load attached GLBs/HDR
- Compare to glTF-Sample-Viewer output
Furnace test: No spheres should be visible Iridescence: Changes from left to right should be gradual
iridescence_transmission_metallic_white.zip
Code
This is the old incorrect pseudocode
const black = 0
c_diff = lerp(baseColor.rgb, black, metallic)
f0 = lerp(0.04, baseColor.rgb, metallic)
α = roughness^2
F = f0 + (1 - f0) * (1 - abs(VdotH))^5
f_diffuse = (1 - F) * (1 / π) * c_diff
f_specular = F * D(α) * G(α) / (4 * abs(VdotN) * abs(LdotN))
material = f_diffuse + f_specular
Here is the corrected version: https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/Specification.adoc#metal-brdf-and-dielectric-brdf
Babylon.js premixes colorReflectanceF0 and uses it e.g. in iridescence: https://github.com/BabylonJS/Babylon.js/blob/c869b5bcb55a8f0cc8e0c43949cfc2a196445daf/packages/dev/core/src/Shaders/ShadersInclude/pbrBlockReflectivity.fx#L161
Examples
Screenshots from Babylon.js Sandbox:
Screenshots from glTF-Sample-Viewer:
I opened a similar issue for three.js: https://github.com/mrdoob/three.js/issues/31350
We have a fix for it under a flag which was introduced by @MiiBond ? we can not make it the default for back compat purpose
I assume this PR https://github.com/BabylonJS/Babylon.js/pull/16476? Seems like this addresses most of the issues. But as far as I have seen it does not change iridescence.
About iridescence, @Popov72 has worked on a fix in the past which should work with what @MiiBond did.
I tested the assets with legacy energy conservation disabled:
All the spheres now have the same color, so the formula for mixing is correct. They are still brighter than the IBL. That might be a different bug.
The iridescence issue does not seem to be fixed by that option, or do I need to toggle another option as well?
This issue has been automatically staled because it has been inactive for more than 14 days. Please update to "unstale".
@Popov72 will have a look when he ll be fully back :-)
This issue has been automatically staled because it has been inactive for more than 14 days. Please update to "unstale".
cc @Popov72
This will be fixed with the OpenPBR material. Implementation is not yet complete, but if we compare the different results when using a 75% white furnace environment:
Babylon (PBR material):
Babylon (OpenPBR material):
Sample viewer:
We can see we are in the same ballpark with the OpenPBR material as with the sample viewer.
I don't have transmission in OpenPBR yet, so that probably accounts for the remaining difference between Babylon and the glTF Sample Viewer.