Thursday, February 23, 2017

lighting - Can I achieve a torchlight effect (lighter area around a light source) in a 2D game?


I am thinking of writing myself a simple 2D game. It will not shine with perfect graphics or gameplay at first, but I'd consider it my first step in PC game development. So, imagine such simple sprite-based 2D game (like Heroes IV or Startcraft BroodWar).



I want the gameplay to support day/night with the according lighting changes and at the same time it will be madness to have to create sprites for every lighting nuance. So, I decided adding a semi-transparent layer on top of other objects will be enough.


The issue with this solution is if I have a light source object in the game (like the hero wearing a torch, or a burning building), there must be a lighter area around it, right? Since I am putting my semi-transparent layer over everything, how would you suggest to achive the torchligt visual effect I want? Maybe redraw that layer adding 'gaps' or differently colored areas based on the lighting effect?



Answer



I don't know what you're programming in, but this is how I handled it in XNA:



  1. On the draw call, a List object is created/cleared.

  2. During the tile draw loop, each tile is checked to see if it has any Lights associated with it. If it does, the Light objects are appended to the List.

  3. The tiles are drawn onto their own RenderTarget2D.

  4. After the tile loop, the list of Lights is iterated through and drawn on their own RenderTarget2D using a texture I made that looks like this:
    Light Texture (Note: I used the R, G and B values here but you should probably use the alpha channel in your actual texture.)


  5. Using a custom shader, I render the tile surface to the screen and pass in the lighting surface as a parameter which gets sampled for the "darkness" value at each pixel.




Now, there's a few things to note:

Regarding Point 4:


I actually have two custom shaders, one to draw the lights to the lighting render target (step 4) and another to draw the tile render target to the screen using the lighting render target (step 5).
The shader used at point 4 allows me to add (what I call) a "luminosity" value. This value is a float that gets multiplied against each pixel in the texture before it's added to the render target so that I can essentially make lights brighter or darker.
At this point, I also take into account the light's "scale" value which means that I can have large or small lights using only one texture.


Regarding Point 5:


Think of the lighting render target as essentially having a value for each pixel from 0 (black) to 1 (white). The shader essentially multiplies that value against the RGB values for a pixel in the tile render target to make the final drawn image.



I also have some more code here where I pass in (to the shader) a value to be used as the day/night overlay colour. This is also multiplied into the RGB values and included in the lighting render target calculations.




Now, this won't allow you to do things like block light from going around objects and whatnot but, at least for my purposes, it's simple and works well.

I've written more detailed blog posts here and here which may help you. I don't have time right now, but if you want I can go into more detail here on gamedev.


Oh, and here's a look at it in my map editor:enter image description here


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...