1
\$\begingroup\$

I'm trying to achieve multiple lights shadows. Currently my program works using only 1 spotlight as a light source that produces shadows. Well... I want to involve multiple lights to give a more realistic effect to my scene.

However, I'm facing a scenario which is a little bit unclear for me:

  1. The steps I follow to create shadows is

    a) Create FBO

    b) Render scene from light's perspective using a depth texture attached to my FBO

    c) Render the scene normally, using my texture from my FBO as a shadowmap texture in order to be able to sample it and creating finally shadows.

  2. The steps I follow to create multiple shadows is

    a) Create FBO1 and FBO2

    b) Render scene from 1st light's perspective using a depth texture attached to my FBO1

    c) Render the scene normally, using my texture from my FBO1 as a shadowmap texture in order to be able to sample it and creating finally shadows.

    d) Render scene from 2nd light's perspective using a depth texture attached to my FBO2

    e) Render the scene normally, using my texture from my FBO2 as a shadowmap texture in order to be able to sample it and creating finally shadows.

Now, the step 1) is pretty clear, works fine. When I manage to implement step 2), something happens: the shadows rendered will be the shadows of my last light (depending the order I call rendering methods). So in this case I get shadows only from my 2nd light.

If I reverse the order of calls (this order: a -> d -> e -> b -> c) and render first in my second FBO and then in my first FBO I get the shadows from my first light source. So basically I conclude: my shadows are not working simultaneously.

Is this the correct approach? (I've seen a solution which uses in fragment shader an array of shadowMaps, an array of lightSpace coordinates so this involves multiple uniforms... what do you think about this?)

Thanks

\$\endgroup\$
  • \$\begingroup\$ Does your current engine have forward or deferred shading? \$\endgroup\$ – transistor09 Nov 8 '15 at 7:59
  • \$\begingroup\$ @transistor09 hm.. no. should that be a reason for not working? \$\endgroup\$ – Shmwel Nov 8 '15 at 14:24
  • \$\begingroup\$ Well, it probably is either forward or deferred. This is important to provide a correct answer. \$\endgroup\$ – transistor09 Nov 8 '15 at 14:41
3
+50
\$\begingroup\$

Are you using blending between your rendering passes?

It sounds like your rendering loop is going something like this:

  1. Fill first explicitly defined shadow map
  2. Render scene fully using the first light
  3. Fill second explicitly defined shadow map
  4. Re-render scene fully once again but using second light

Under that situation, the result of step 4 will essentially overlap the results of step 2. If multiple lights (& shadows) are desired, you need to enable blending (glEnable(GL_BLEND);) between rendering passes.

If blending doesn't solve the problem, perhaps the issue is related to you not properly defining which texture should be used when rendering (ie not passing the correct texture handle).


The solution of using multiple shadow maps in a single fragment shader assumes that you are using a single shader to handle all of your lighting calculations. Under this situation, it would be possible to do the following:

  1. Fill first explicitly defined shadow map
  2. Fill second explicitly defined shadow map
  3. Render scene fully

But one problem with this is that you have to always pre-define in your shader code the maximum amount of lights and shadows you want to use. This is incredibly restrictive.

A solution to this is to implement a deferred shading system. Instead of having a single shader program, you define one for every type of shading situation you need (like one for spot lights, one for point lights, etc), and then instead of shading the entire scene multiple times only the stuff on the screen gets shaded.

This alleviates the problem of having arrays of shadows and lights per shader, since a shader will now only contain everything a single light needs.

\$\endgroup\$
  • \$\begingroup\$ Hm.. doesn't work event activating GL_BLEND. Shall I use some GL_BLEND_FUNC? And regarding texture handling, there are no issues with linking it to the correct shadow map sampler (that's is a fact because the shadow for a light is rendered.. and I guess there is nothing wrong with it) \$\endgroup\$ – Shmwel Oct 25 '15 at 19:01
  • 1
    \$\begingroup\$ Blend func specifies how the pixels a draw call will react with any pixels that were already present from the last draw call. The default is to sum the 2 together, which is what is wanted in this case. \$\endgroup\$ – Yattabyte Oct 25 '15 at 19:04
  • \$\begingroup\$ Well, unfortunately it doesn't work with glBend activated :( \$\endgroup\$ – Shmwel Oct 29 '15 at 17:50
  • \$\begingroup\$ @Shmwel Have you tried glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)? \$\endgroup\$ – John Apr 30 at 1:10

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.