Closed bchirlsbiodigital closed 2 months ago
It looks like some rendering engines clamp roughness value above zero to make sure this doesn't happen and also to avoid computation issues like divide-by-zero errors and arithmetic on subnormal numbers.
The Filament renderer documentation explains it well: https://google.github.io/filament/Filament.html#toc4.8.3.3
For 32-bit floating point numbers, the smallest positive normal number is 2^-126. If you're going to square roughness, then you want to clamp roughness at or above Math.pow(Math.pow(2, -126, 0.25))
(exponent algebra left as an exercise for the reader). For 16-bit half-floats, the smallest positive number is 2^-14.
Part of the problem here is that a "point light" is just an approximation, not a physical object with size. An actual light bulb has a radius and can be seen in a mirror, for example, but a point light is infinitesimal, smaller than microscopic. No one pixel or fragment is perfectly aligned such that its reflection vector directly hits a sub-microscopic object. That's why other engines fudge the minimum roughness. I don't think we need to match that behavior here, though. So, I'll close this for now.
When viewing the MetalRoughSpheres.glb sample with only punctual lights, specular highlights on all the smoothest materials are not shown.
Here is a screenshot with image based lighting disabled. See the left-most column of spheres.
For comparison, here is what it looks like in three.js:
And in Blender (Eevee preview):
I wasn't able to get the exact lighting and view to match in all viewers, but three.js and blender always show those little highlight spots no matter how I adjust the scene.
Not sure what the problem is. I'll keep digging, but I'm hoping someone here can figure it out faster than I can. Thanks!