KhronosGroup / glTF-Sample-Viewer

Physically-Based Rendering in glTF 2.0 using WebGL
Apache License 2.0
1.21k stars 229 forks source link

Specular highlights missing on smooth materials #494

Closed bchirlsbiodigital closed 2 months ago

bchirlsbiodigital commented 8 months ago

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.

image

For comparison, here is what it looks like in three.js:

image

And in Blender (Eevee preview):

image

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!

bchirlsbiodigital commented 8 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.

emackey commented 2 months ago

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.