How to add thousands of lights to your renderer and not die in the process
zyanidelab.com
zyanidelab.com
LOL, solid advice. Early openGl only allowed 8 lights in a lighting pass. So if you had a bunch of lights, you'd have to find the closest ones and just use those. One technique I liked was the index deferred lights, which at the time could run on older hardware that didn't have use of floating point buffers: https://mynameismjp.wordpress.com/2012/03/31/light-indexed-d...
The fixed function pipeline api only does one thing one way with a lot of limitations while the shader pipeline can basically do anything (doesn’t even have to be rendering a 3D scene) as long as it’s fast enough for your purpose.
...that sounds like software vs hardware though?
Lighting used to run as a fixed (hardware) function and now it runs via a shader (software) function.
I’d be really curious to hear how easy it was to adapt the Q3 engine for this!
I also suspect that in most situations you can cache most results. Cast one shadow ray at a light selected randomly distributed based on intensity (thus if half the light that could hit a pixel comes from one source that light gets picked half the time) and a cache of the other answers. Sit still and it will be basically perfect, the more you move the more error there will be but there will also be less ability to notice that error.
I've also been curious about using Z-buffer techniques to determine visibility. Render a frame off screen, "color" it with the distance to the pixel. An object is visible if this frame shows it in the color corresponding to it's distance.
Efficiently determining visibility, even approximate visibility, is what makes rendering such a tough problem in the first place. Naturally, many ideas have been gathered in this space. Shadow maps for light sources act as caches of discretely sampled visibility information per light source. Their sampled nature makes them highly problematic in practice. Many workarounds for shortcomings have been found over the years, but it's like building a jenga tower on a shaky foundation.
Similarly, you can reasonably estimate shadowing from objects in a local area around a pixel by doing screen space tracing, that is, walking the projected line towards the light source in the depth buffer and see if any fragment in that line has a depth close enough to your ray at that pixel). Again, this is dealing with sampled and incomplete information (e.g. any shadow caster occluded from view or off screen is missed). But this method is often used on top of other methods to ensure that contact shadows are accurate.
There are many other approaches that try to precompute or cache visibiliy or lighting information in one way or another. The big problem they all run up against is that the data needs to be sampled somehow and the memory requirements start to explode with increasing sampling resolution.
As far as I understood the article the method works like this:
- per pixel estimate which lights contribute
- from those lights pick a random one and store how much it contributes
- give priority to lights that contribute the most
- the next frame uses the data of the previous frame
- neighboring pixels are used to remove noise
I wonder how useful this is for fast moving games. Wouldn't this be very noisy?
Or doing all this light pass at a lower resolution and then upscaling it & denoising at the same time
The unbiased thing would be to use all the lights, but use some kind of weighted random sampling where you pick nearby lights most of the time, but occasionally you pick one that's far away and give it's results a higher weight to counteract that it's not chosen very often.
In a lot of contexts, though, I can agree that the pragmatic choice might be just to cull the number of lights you have to deal with by defining them to have a maximum range, and if you store them in an acceleration structure it'll be easy to query just the ones that matter.
Agreed. A wide area light can be handled, but 1000 far away lights my system would ignore but they might actually be better modeled as ambient. Bit hey, I was ray tracing a maze with hundreds of lights at 10-20 fps on a CPU ;-)