1
\$\begingroup\$

I would like to render an OpenGL scene with an arbitrary number of point lights (at least 1024) with shadows enabled.

My current method of rendering shadowmaps, however, cannot do this.

Let me explain

There are only 32 textures you can pass to a fragment at a time.

I am using 31 of those 32 textures for shadowmaps at the moment.

pseudocode for my main code...

setShader("DepthBufferPointLight", -1); //the int is actually numlights, used for deciding whether or not to recompile a finalpass shader. Irrelevant in this stage and set to -1 for debugging purposes.
FBO fBO* = CreateFBOs[6 * numLights]
for (int j = 0; j < 6; j++)
for (int i = 0; i < 6; i++)
{
 setRenderTarget(fBO[i]);
 setupCameraforLight(j,i); //Move the camera to the right position
 renderSceneDepth(); //Textures aren't even rendered for this
}
setRenderTargetDefault();
setShader("FinalPass", numLights); //The shader dynamically recompiles for final pass calls if the number of lights has changed, because it will need to change how many uniform struct lights there are.
setLightTextureUnits(fBO, 6, numLights); //glActiveTexture calls and glBindTexture calls
renderSceneFinalPass(); //Textures and uniforms are all set up for this, also does the lights

and then in the shader pipeline I do my calculations using the shadowmaps. My pseudocode is rough but you get the picture.

(SIDE NOTE: the dynamic recompiling is actually really simple and only changes one line of the shader, and I'm going to deprecate and remove the function once I figure out how uniform variable arrays work...)

my code breaks after numlights*6 is greater than 31.

Is there a better way to do this?

my ultimate goal is to render an arbitrarily high number of point lights using shadow mapping

\$\endgroup\$
2
\$\begingroup\$

Do you hit this limit when you do the light-pass or main render-pass?

With so many lightsources, I assume that your shadowmap resolution is very low?

The thing I would try first is to put all the shadowmaps in a shared large texture, like an atlas.

E.g, in a 8192x8192 texture, you could tile 16384 shadowmaps of 64x64 texels each.

In your main shader, you would simply calculate a texel offset for each of the shadowmaps.

That said, 1024 lightsources seems very high. Because you need to render the shadowmaps (views from the lightsource) for each of them. That would mean at least 1024 render passes over your scene. Or in your case even more, as your light sources seem to be omnidirectinal, as you render 6 views per light?

Maybe I make different assumptions on shadowmaps than you do. The way I do shadow maps, is to render the scene twice.

First I render the scene from the point of view of the light source, storing depths in a depth texture.

Second I render the scene from the point of view of the camera, using the shadowmap previously generated.

With 1024 lights, I would expect that your first pass needs to be done far too many times?

\$\endgroup\$
  • \$\begingroup\$ The first pass is depth buffering. You describe exactly what I do perfectly. \$\endgroup\$ – Geklmintendon't of Awesome Jan 12 '18 at 23:19
  • \$\begingroup\$ I believe I have solved this problem though, and while it still requires a buttload of depth buffering passes, I can now do infinite lights. \$\endgroup\$ – Geklmintendon't of Awesome Jan 12 '18 at 23:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.