Simple 2D lighting effects

Started by
10 comments, last by cakefrost 9 years, 7 months ago

Hi, I am trying to do simple lighting effects (no dynamic shadows, almost like a fog of war). Below is a screenshot of something that looks similar to what I am going for (this is not my game, just something I found from google)

4.png

I am using LPD3DXSPRITE to render things, and am currently running a single pixel shader that isn't doing anything right now. I have found a variety of strategies, from rendering a light map to a different surface (using SetRenderTarget), then converting that to a texture, and then passing that to the pixel shader, and then using that to determine what should be darkened (and potentially by how much).

This sounds pretty straightforward, but I need to learn how to do each of those steps. The problem is, I am having difficulty using the right terms to search. So my questions are:

1. Is this the right approach for something like the above screenshot?

2. If this isn't the right approach, can you please point me in the right direction?

3. If this is the right approach, what things should I be looking up to better understand how to do this?

Thanks in advanced!

Advertisement

I don't know about DirectX, but I know one method I see recommended a lot is to make a screen sized bitmap that has alpha transparency with the circle in the middle and a custom made gradient filling from the edge of the circle to the edge of the bitmap. Then it is a simple matter of drawing it over the top of the sprites being drawn. That is if I'm understanding what you are wanting. There are probably better ways to go about it, but like I said, that is the normal method I see recommended, but I've never done this for a game myself so I can't say from experience.

I should point out this method also assumes you have the camera locked so that the character is always dead center of the screen.

You could draw all your sprites with a non-white color to ID3DXSprite::Draw() which will darken them, then draw the lightmap as another sprite over top of the player sprite and blended with the background. The lightmap doesn't need to be generated with render targets, it could just be a texture you have loaded from a file.

Thank you for the reply, I wasnt clear, but I also meant that these light sources would be in the environment - think a light post or something. I was thinking about doing it the way you described, and determine where in the screen each light is, render the mask as you described, then figure out which areas are not touched by the light, and render a simple mask over it. I suppose that idea doesnt actually sound so bad.

edit: Ah, I know why it would be tough - when multiple lights are on the screen at once, if they overlap, it will be rendered weirdly.

You could draw all your sprites with a non-white color to ID3DXSprite::Draw() which will darken them, then draw the lightmap as another sprite over top of the player sprite and blended with the background. The lightmap doesn't need to be generated with render targets, it could just be a texture you have loaded from a file.

The lights are not constant relative to the player/camera, so I am not sure that would work.

I do exactly that currently, but I if I render something on top of it, the colors look dull/muffled, because I am adding something on top of it.

Thank you for the reply, I wasnt clear, but I also meant that these light sources would be in the environment - think a light post or something. I was thinking about doing it the way you described, and determine where in the screen each light is, render the mask as you described, then figure out which areas are not touched by the light, and render a simple mask over it. I suppose that idea doesnt actually sound so bad.

edit: Ah, I know why it would be tough - when multiple lights are on the screen at once, if they overlap, it will be rendered weirdly.

I have never done lighting based on sprites, but I suspect the correct approach is

  1. Render your scene/screen as if you are not doing lighting
  2. Set an RGB texture the same size as your screen as the render target
  3. Clear the texture/render target to 0/black
  4. Set the blending mode to additive (dest = dest + source, rather than say your "dest = dest * (1-alpha) + source* alpha" for alpha blending)
  5. Render your light gradients (they can be coloured, because "a + b == b + a" order does not matter, overlapping areas just get brighter till you saturate the channel at full brightness)
  6. Put your backbuffer back as the render target
  7. Multiply your backbuffer/scene with the lighting texture (dest = dest * source) which makes unlit areas black (dest = dest * 0) and leaves fully lit areas alone (dest = dest * 1) and everything inbetween, for red, green and blue independently.

I just saw an article about this.

http://gamasutra.com/blogs/OliverFranzke/20140828/224326/Dynamic_2D_Character_Lighting.php

I would think that if the lights stay in the same spot, you could pre-bake the lighting for all the backgrounds and then use the technique in the article for stuff that moves.

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

Glass_Knife: thank you for the link, I will check it out. The lights will not necessarily stay in the same spot (the player might be able to place torches on the ground, or start a fire, I am not entirely sure but I dont want to limit myself). I also am looking to do much simpler lighting, mostly just rendering certain pixels with less color if it is supposed to be darker.

SyncViews: Awesome, this is something I can look into, thanks. From my original research, I remember reading that there is no multiplication blend (step 7), so this sounds like something I'll use the shader for. However, this is basically back to my original problem of not knowing what I need to search. I tried searching for passing textures/buffers to pixel shaders but I am getting a variety of responses, none of which have proven helpful to me. Is there a particular term that this process is called that I can look into?

Net-Gnome had a nice post in his journal about his lighting system using shadow casting. I'd advise you to check it out.

He open sourced his code a while back too, so you can check out how he does it as well.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

I've been working on a method for real time lighting on pixel art. I've put some videos up on YouTube. Latest one here

I haven't written up my method yet as I'm still finishing up some details, but you can see the idea. I do it by offline rendering various normal, material and occlusion maps into my sprite sheet alongside the diffuse colour, then doing similar to a 3D deferred renderer but using the 2D sprites to populate the geometry buffer. It supports dynamic point lights and directional lights so far.

It's a bit similar to the Gamasutra article I guess (though that article hadn't come out when I started working on it.)

Visit http://www.mugsgames.com

Stroids, a retro style mini-game for Windows PC. http://barryskellern.itch.io/stroids

Mugs Games on Twitter: [twitter]MugsGames[/twitter] and Facebook: www.facebook.com/mugsgames

Me on Twitter [twitter]BarrySkellern[/twitter]

This topic is closed to new replies.

Advertisement