0
\$\begingroup\$

I'd like to start by mentioning that I'm just an amateur programmer of the past 2 years with no formal training and know very little about maximizing the potential of graphics hardware. I can write shaders and manipulate a multi-layered drawing environment, but I've basically stuck to minimalist pixel shaders.

I'm working on putting dynamic point light shadows in my 2d sidescroller, and have had it working to a reasonable degree. Just chucking it in without working on serious optimizations outside of basic culling, I can get 50 lights or so onscreen at once and still hover around 100 fps.

The only issue is that I'm on a very high end machine and would like to target the game at as many platforms I can, low and high end. The way I'm doing shadows involves a lot of masking before I can finally draw the light to my light layer.

Basically, my technique to achieveing such shadows is as follows.

See pics in this album

https://i.sstatic.net/yONK5.jpg

  1. The dark gray represents the background tiles, the light gray represents the foreground tiles, and the yellow represents the shadow-emitting foreground tile.

  2. I'll draw the light using a radial gradient and a color of choice

  3. I'll then exclude light from the mask by drawing some geometry extending through the tile from my point light. I actually don't mask the light yet at this point, but I'm just illustrating the technique in this image

  4. Finally, I'll re-include the foreground layer in my mask, as I only want shadows to collect on the background layer and finally multiply the light with it's mask to the light layer

My question is simple - How can I go about reducing the amount of render target switches I need to do to achieve the following:

a. Draw mask to exclude shadows from the foreground to it's own target once per frame

b. For each light that emits shadows,

-Begin light mask as full white

-Render shadow geometry as transparent with an opaque blendmode to eliminate shadowed areas from the mask

-Render foreground mask back over the light mask to reintroduce light to the foreground

c. Multiply light texture with it's individual mask to the main light layer.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

You can create a polygon that captures everywhere the light can reach. Drawing a light (with shadows) then only requires one draw call and no render target switches.

The basic set-up is:

  • Draw everything than can be lit
  • For each light
    • Compute the polygon of where the light can reach
    • Draw the polygon using additive blending

I've wrote a small article, with a video, about how I implemented it which you can read here

The most important resource I used was this beautiful tutorial with interactive examples.

With this approach I was able to draw hundreds of lights (and smooth hem) at interactive rates.

Another (more sophisticated) example you can look at is this tutorial by one of the XNA MVPs

Disclosure: first article is on my personal blog

\$\endgroup\$

You must log in to answer this question.

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