0
\$\begingroup\$

I know that questions like this have been asked many times, but I have not found one exactly like this yes. I have implemented a top-down grid based world in Monogame, and am starting on the lighting system soon. How I want to do lighting is to have a grid that is 4 times wider and higher, basically splitting each world tile into a 4x4 system of "subtiles". I would like to use a flow like system to spread light across the tiles by reducing the light by a small amount each time. This is kind of the effect I was going for:

https://i.stack.imgur.com/ToHPi.png

The black grid lines are the light grid, and the red lines are the actual tile grid, and the light drop-off is very exaggerated. I plan to render the world by drawing the unlit grid to a separate RenderTarget2D, then rendering the lighting grid to a separate target and overlaying the two.

Basically, my questions are:

  1. What would be the algorithm for a flow style lighting system like this?
  2. Would there be a more efficient way of rendering this?
  3. How would I handle the darkening of the light with colors, reducing the RGB values in each grid, or reducing the alpha in each grid, assuming that I render the light map over the grid using blending?
  4. Even assuming the former are possible, what BlendState would I use for that?
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

A floodfill lighting system should do what you want.

First, set the light value of source tiles to 1, and all other tiles to 0. Next, to propogate the light, use a recursive DFS function to set light values of neighboring tiles to some attenuation of the source light.

So essentially, you would have something like:

void PropogateLight(float sourceLight, int toX, int toY)
{
     if(tiles[toX][toY].Light >= sourceLight) return;

     float newLight = attenuate(sourceLight);

     if(newLight < 0)
     { tiles[toX][toY].Light = 0; return; }

     tiles[toX][toY].Light = newLight;

     PropogateLight(newLight, toX + 1, toY);
     PropogateLight(newLight, toX - 1, toY);
     PropogateLight(newLight, toX, toY + 1);
     PropogateLight(newLight, toX, toY - 1);
}

Once you have the light values set, just do:

spriteBatch.Draw(texture, position, new Color(light, light, light));
\$\endgroup\$
4
  • \$\begingroup\$ Thanks for the response. I'm assuming that this would work just as well if I wanted colored light, I would just replace a blanket light value with something like 'PropogateRLight' or 'PropogateGLight'? Also, I'm assuming here that the 'attenuate' function just decreases the amount of light by a set amount? \$\endgroup\$
    – sm81095
    Jun 24, 2013 at 3:58
  • \$\begingroup\$ Also, since each world tile is split up into 16 smaller lit parts, would it be more efficient to draw all of the unlit tiles, then the light map, and combine the two, or split up each world tile into 16 smaller ones and render using the color setting into a single RenderTarget and not worry about separate render targets? \$\endgroup\$
    – sm81095
    Jun 24, 2013 at 4:02
  • \$\begingroup\$ Correct! You can split the PropogateLight into different channels. The attenuate function would indeed reduce the intensity of the light. Is there any reason for the RenderTargets? Why not just tint it the first time? \$\endgroup\$
    – untitled
    Jun 24, 2013 at 4:13
  • \$\begingroup\$ Alright, thanks for the answer! I'll test this out later today. \$\endgroup\$
    – sm81095
    Jun 24, 2013 at 14:44

You must log in to answer this question.

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