# Achieving 2D Lighting for Terraria-Like Game

I'm trying to achieve the fog-of-war lighting style that Terraria and Starbound have. Terraria's lighting system seems to be more blocky/tile based, but Starbound's is a lot more smooth.

The Desired Effect:

Starbound is using a shader to render its lighting, but how it's going about that is quite a mystery to me.

The idea I had on how to achieve the desired effect is the following: Create a texture that is black and somehow calculate the area that is white, storing this in a light map render texture, finally doing an Additive Blend of both the main texture and the light map texture to achieve a similar effect to Starbound's. (However this does not take into account lights in the world, which I also have absolutely no clue how to include in my calculation to the light map render texture)

I say somehow in italics because I have no clue as to how I can create this "Mask" effect in the light map render texture. How I can do calculations necessary to create the mask is beyond me; I don't even know how I can begin to translate the game world's data, relative to the what the camera sees, and update the texture accordingly.

TLDR: How can I achieve lighting similar to that of either Terraria or Starbound in Unity 2D?

• Additive blend won't work. You should multiply. – Ocelot Dec 27 '17 at 3:25

First you draw your color map

Then you draw your light map

And finally you multiply both.

If you want a some sort of secondary lighting in your game, and if your game world uses grid for terrain and/or object placement, then I have a solution for you. This is something like instant radiosity.

First, you find which cells are lit by the light by tracing them from the light source.

Then you place another light sources on lit cells with attenuation of intensity based on a distance from original light. You may also want to blur them a bit (I did). Here's resulting map.

Then multiply with your color map.

Here's pseudocode for the rendering pipeline (don't mind the syntax highlight)

for each light on scene:
if light is on screen:
add light to the drawing queue

draw frame:
render frame color map:
draw each visible tile and object

for each light in queue:
trace secondary lights on visible cells and add them to the drawing queue

render frame light map:
for each light in queue:
move light object to the light position
set light object width and height to the light radius
set light object color to the light color
draw light object
//then we render shadows for solid places
set blending to subtraction
for each visible cell:
if cell is surrounded by other cells from every side:
move light object to the cell
set light width and height to the radius slightly bigger than cell
set light color to white//to subtract any kind of light color
draw light object

set blending to normal
draw color map
set blending to multiplication
draw light map

• This is exactly what I need and definitely help me move over in the write direction, however I'm still stuck on how to procedurally generate the lightmap with that nice radial gradient. I looked online and found very little on the subject in HLSL, any ideas? – BlazeXenon Dec 27 '17 at 22:51
• @BlazeXenon You can use pregenerated texture for the lights. Simply draw them to the lightmap with additive blending. But however, if you want to generate them procedurally, you should have at least basic understanding of what shader is and how programmable rendering pipeline works. Speaking of HLSL - it is not so different from C language. – Ocelot Dec 27 '17 at 23:51
• Yeah, that seems like a good idea however that would only really work for things like torches. Do you have any idea how I can procedurally generate the nice gradient around the blocks themselves? Currently I only have a it rendering the black directly on the tiles themselves which looks really horrible, however with a nice gradient blur around the edges of the tiles, it would look a lot like the desired effect image above. This is what I current have: puu.sh/yPbi0/4fde0796b2.png; The light map is already multiplied to the main camera's color map. I feel like I'm so close... – BlazeXenon Dec 28 '17 at 3:05
• @BlazeXenon First of all, avoid using completely black color as it will cause the black pixels being unlit completely (AnyLightAmount * 0 = 0). To create a gradient you are talking about, just apply the same light with a range approximately of 1.2 (assuming a cell size is 1) for each cell that is surrounded by blocks from every side, only this time with subtraction blending. I don't think you really need a shader for this. – Ocelot Dec 28 '17 at 3:35
• Wouldn't rendering to a texture from anything else besides the GPU be very bad? The Apply() function is very costly and will generally cause huge lag spikes, from my experience at least. I believe the proper way to do this is in a shader, however I have no clue how in one. The idea you posted is perfect however I have no clue how to render to the texture in the CPU without heavy performance dips. Any ideas? – BlazeXenon Dec 28 '17 at 8:25