I'm looking to create a 2D "spotlight" effect that allows a spotlight on multiple entities. I.e., as if several sprites were holding torches. For a single entity (one spotlight), I use a technique where I overlay a gradient sprite and have the centerpoint chase that entity. This technique works fine for a single spotlight. Here's a screenshot to illustrate what I'm talking about:

Single Spotlight - Works

Spotlight Effect with one spotlight

The problem I run into is that this technique does not extend to multiple entities. If I overlay another spotlight image I run into several problems. Here's a simulated screenshot:

Multiple Spotlights = Problems

Spotlight Effect with two spotlights

The most obvious problem is the visible corners. This could be solved by making the spotlight image gigantic to cover the whole level, but that doesn't feel right. The second and more intractable problem is that I'm effectively multiplying the darkness with this technique. So each sprite added has the effect of darkening everybody else. Clearly I'm approaching this problem incorrectly.

Any ideas?

Continuing Efforts

There's been some discussion of blending options in the comments. Here's my current thinking. In my single spotlight example above, I use an image file that looks something like this: (I've replaced the transparency with the color green to make it easier to illustrate)

Transparency Approach

As discussed above, the problem is that alpha blending this image with another image is not going to produce the desired effect. Instead it will produce this:

Overlaying two transparency circles

That doesn't strike me as a blending options issue. The problem, it seems to me, is that that sort of image has the transparency mask and image (a black square) built in, when they should be separated.

So instead of a black image with a cut-out transparency built-in, I ought to be using transparency masks that are utilized at run time against the black square. When doing that, I still can't use a traditional white and black transparency mask or it'll run into the same problem. Here's an example, this time the white and black represent white and black:

Transparency Mask

The solution, it seems, would be to apply a transparency mask that itself utilizes transparency. Something like this: (green = transparent)

Transparency Mask with Transparency

That way, multiple transparency masks could be alpha blended together and THEN used as a transparency mask against the black square. Here's an example of two of the transparency masks alpha blended together:

Two Transparency Masks with Transparency

Anyway, that's the approach I'm working on implementing. I'll post results if this works. What I don't know (at present) is if I can use a transparency mask that itself has transparency.

  • \$\begingroup\$ Thinking about it, it seems like I should be moving transparency masks around and applying them to a big black texture. No idea how that would be done though. \$\endgroup\$ Feb 4, 2013 at 19:58
  • 7
    \$\begingroup\$ Not sure how you're creating or applying your gradients, however this could be a blending issue, where if you use the right blending it will work fine. We'd need more info about the textures. \$\endgroup\$
    – dennmat
    Feb 4, 2013 at 21:43
  • \$\begingroup\$ I'm using AndEngine as the framework, and much of the blending is happening behind the scenes, although there is a "setBlendFunction()" available. \$\endgroup\$ Feb 4, 2013 at 22:29
  • \$\begingroup\$ Looking at what you linked to I'd say you probably want the second solution listed at the bottom or the third if that doesn't work. I'm not clear on andEngine, and they didn't seem to have docs, perhaps if you can't find your answer in that thread they may be able to help further, as it seems like they are already playing around with the blending options a lot behind the scenes. \$\endgroup\$
    – dennmat
    Feb 5, 2013 at 4:15
  • \$\begingroup\$ Although that thread seems to be fixing your problem in the first place, do you have the version including that change? \$\endgroup\$
    – dennmat
    Feb 5, 2013 at 4:25

1 Answer 1


Conceptually, the solution to multiple spotlights consists of:

  1. Start with a completely black array to hold lighting values for each pixel in the scene.
    • Zero will represent an area of the image with no light whatsoever.
    • 100% will represent an area which is completely saturated with daylight.
    • If you want to get fancy, you could have a value higher than 100% (say, 200%) represent an area of the image which is oversaturated, and blurs everything into a blinding white blob of pixels. Worry about this later, and simply cap values between 0-100% for the time being.
  2. For each light source either within the screen, or close enough to the edge that its halo would add to the light, add the light values from that light source to your array of light values for the scene pixels.
  3. Use the resulting light-value-array to modify the pixels for your scene such that:
    • Pixels lit by 0% light are black.
    • Pixels lit by 100% light are at their normal colour.
    • Other pixels are a colour part-way between.
    • You seem to already know how to do this step, judging by your screenshots.

The trick is understanding that alpha-blending can do one or more of these steps. Alpha-blending just refers to using an alpha map/image to modify the pixels of an image or texture in a simple way. It also usually means that it's going to be a fast set of functions, or implemented with special hardware commands, to make it fast. You can do it with regular arrays, and normal language commands, but using the special alpha/blending library functions is probably better. ...And won't have bugs. Sometimes this means making the pixels partially transparent, but for your case, this will mean:

  • Adding alpha values to each pixel, to build up the light-value-array from #1.
  • Using the light-value-array from #1 to resolve the final colours for pixels from step #3.

I'd start looking up the documentation for your alpha-blending functions to see what functionality they provide for combining pixels of various kinds. I suspect they will have functions for each of the steps you'll need to perform, but they might be under names which are not obvious.

  • \$\begingroup\$ I'm digging this answer and am going to give it a shot. The idea of a lens-flare/blur for values above 100% is a nice and inspiring bonus as well. Will post updates with lessons learned in the process. Thanks E.T. \$\endgroup\$ Feb 9, 2013 at 3:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .