-
-
Notifications
You must be signed in to change notification settings - Fork 22k
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
Prevent very far away point lights from being culled #98641
base: master
Are you sure you want to change the base?
Conversation
I'm not sure about forcing this change on everyone. It's great for space games that want a long view distance, but aren't willing to pay the cost of double precision. But for everyone else its a performance cost for no gain and for engine maintainers its additional complexity and maintenance burden. Our fragment shaders are already instruction bottlenecked. So this would have a very real cost for many games who won't benefit from it. The CPU code is less problematic as there likely won't be any performance regression. |
Yes I'm very aware of the performance bottleneck of fragment shaders, and I get your point. To clarify one thing : this issue prevents anyone from having long ranging lights working in space games and alike, including people using double precision (it doesn't help in shaders). I have a couple of ideas to further reduce the performance cost and maintenance burden :
Will update the PR and see if it looks more acceptable. Feedback appreciated 🙏 |
c3ff473
to
ed704ad
Compare
Can you clarify which max values in meters would start having problems? |
Problems arise when :
To give a comparison |
ed704ad
to
59e0858
Compare
Rebased on top of #94981 |
59e0858
to
930d9f3
Compare
Rebased |
Very far away Omni and Spot lights get culled and can't contribute to the scene's lighting even though their radius is large enough.
This is due to several floating point precision issues this PR resolves :
INFINITY
if one of them is greater thansqrt(MAX_REAL_T_VALUE)
=1.8446744x10^19
with 32 bit floats). Consequently the light's sphere of influence is always considered behind the near plane or beyond the far plane and it gets culled.INFINITY
and the light gets culled against the fade far distance.INFINITY
when they're greater thanSQRT(MAX_FLOAT_VALUE)
. Consequently the light gets a zero attenuation factor and a zero light vector, therefore doesn't affect the fragment.This PR solves
all 3 above issuesissues 1. and 3. (the compatibility renderer is left unchanged) by scaling down the light position in view space by its L1-norm + 1 before getting the length, then scales it back.The scene below is lit by two omni lights positioned behind the camera at approx
x = y = z = 1E30
.FAQ
What about Directional lights ?
There is no such issue for Directional lights, as no distance computation is involved (only the light direction plays a role, and it's a unit vector).
What's the cost of this change in the scene fragment shader ?
Is it really worth it ?
This small tweak unlocks using omni and spot lights in the range [1E19; 1E38] in single precision, speaking of attenuation radius and distance to origin, in addition to the commonly used [0; 1E19] range. This extended range is especially useful in space scenes and other extremely large environments.
Why not just using the double precision build ?
The double precision build can't solve the problem in the scene shader. It would also be a much more resource intensive alternative to solve a simple problem : being able to use the lights across the whole value range of 32 bits floating point, not only the first half of it.
It's not a surprise that rendering very deep scenes raise many numerical precision issues
Absolutely, and this is what I'm into ! I started digging into this rabbit hole a while ago, and also stumbled upon #95944 and #98610 so far. There will be likely more to come