Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specular distribution function must be normalized/clamped for physically correct values #557

Open
rsahlin opened this issue Jul 16, 2024 · 1 comment

Comments

@rsahlin
Copy link

rsahlin commented Jul 16, 2024

In order for the glTF sample viewer to be physically correct the specular normal distribution factor - D_GGX in the shader - must be clamped to [0.0- 1.0]
This factor, which is a means to provide a 'made up' specular lobe in the absens of a light solid angle, is used together with the light intensity.
It follows simple logic that any factor that is used in calculations together with light intensity must be within the 0 - 1 range.
Otherwise light is magically removed or added.

In the sample-viewer, this means that the return value from the D_GGX function MUST be clamped in the [0.0 - 1.0] range.

The output can be checked to see if it follows the Fresnel power law for unpolarized light.
This states that the reflectivity and transmission factor is calculated at the interface between the media using index of refraction, at normal incidence this is:
Reflectivityfactor = (IOR1 - IOR2) / (IOR1 + IOR2) ^2
For the default glTF air to material interface this becomes:
Reflectivityfactor = (1.5 - 1.0) / (1.5 + 1.0) ^2 = 0.04

This means that specular light makes up 0.04 of the incoming light at normal incidence and transmitted light makes up the remaining 0.96.
0.04 + 0.96 = 1.0

Attached is the fresnel test model and reference image.
The test model has a 1 * 1 meter material facing the camera, the material is perfectly smooth with a basecolor of [0,0,0] just to isolate the specular factor.
A directional light is placed so that light falls straight onto the surface, at normal incidence.
Light intensity is 1000 meaning that the sampleviewer exposure setting must be set to 0.001

Below image is correct output - the reflectiv intensity shows up as sRGB [0.22,0.22,0.22] - converted to linear light this equals to [0.04,0.04, 0.04] which is the correct result

image
fresneltest.zip

This is the output from sampleviewer - it clearly shows that the specular contribution is massively inflated - this is because the D_GGX function must be limited to 1.0

image

@UX3D-haertl
Copy link
Contributor

We can definetly clamp the value anyways, but I can not reproduce the bright lobe in sample viewer.
This is probably because of the other issue you mentioned about 0 roughness, but even with a small roughness value the light is not really visible for me (even with intensity 1). I tried some values and could not find any which showed a too bright light.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants