7

I'm developing a 2D game in SDL 2.0 and I'm having am trouble with my lighting system. I want to fill the screen with fog and create a transparent circle around the player (lower-left). I know how to make a dark room with a tinted light using SDL_BLENDMODE_MOD (lower-right), but I cannot make the fog. I have tried layering multiple textures over the screen with every combination of SDL_SetRenderDrawBlendMode() and SDL_SetTextureBlendMode() I can think of.

image

I have searched and found solutions on StackOverflow like this, but they use SDL surfaces and pre-made light images. I am going to be dynamically changing the shape and size of my input image (upper-right) so I need something more flexible.

Solution 1: Instead of a white circle and black background, I use a black circle and navy background. I then blend this using screen blending and get my fog (I've tested this in an image editor to get the lower-left image). Unfortunately, SDL does not have a SDL_BLENDMODE_SCREEN.

Solution 2: Create a semitransparent fog layer and punch a fully-transparent hole in it. Unfortunately, I don't know how to overwrite a texture with a transparent hole. I have tried setting my drawing mode to SDL_BLENDMODE_NONE and drawing a fully-transparent circle, but it only creates fully-opaque ones. The documentation says I can replace the destination alpha but that doesn't seem to work...

Community
  • 1
  • 1
DragonDePlatino
  • 159
  • 1
  • 10
  • I just ran into this issue too. If you're using `sdl2-gfx` to draw the circle, it explicitly **changes** the blending mode to be `SDL_BLENDMODE_ALPHABLEND`, and completely ignores the blending mode you set. The (awful) solution here is to draw without alpha, and then use a custom blending mode via `SDL_ComposeCustomBlendMode` to merge the light layer down. – Sandy Maguire Apr 09 '22 at 04:44

1 Answers1

0

(The following is a series of suggestions, not a definitive answer. If you can use shaders, your answer is a one-liner fragment shader. Other than that, I don't know a simple solution that gives exactly what you want.)

Firstly, you probably need to generate (or store) your "mask" image in the alpha channel of the texture (instead of the color channels) for it to have any effect in alpha-blending.

And I suggest using an inverted alpha value in the mask texture: setting the circle (or whatever shape) around the player to zero, and filling the fog parts with a "fog value" near 255 (or 1.0, if you are using real numbers.) This lets you prevent anything from getting drawn in the clear circle in the middle.

Now, if you have filled the entire mask texture with a solid "fog color" (probably no need to make a shape or anything,) taking care not to disturb the alpha channel, set your SDL_SetTextureBlendMode() to SDL_BLENDMODE_BLEND and do a SDL_RenderCopy(), you will achieve something like what you want. Specially if you have set a bright "fog color" (not value, color) in the mask texture, e.g. like the cyan in your sample images. It will not exactly match your "screen blend mode", but you can get close.

And you can experiment with SDL_BLENDMODE_ADD as well. It might even give you better results (for a foggy effect.)

In any case, to reiterate, in your fog mask texture (which is the "source" in all your blendings,) you set a solid fog color, and set the alpha channel to a solid fog value, and then paint the clear area around the player in the alpha channel only, using a value of zero.

yzt
  • 8,873
  • 1
  • 35
  • 44
  • How do I store an image in the alpha value of a texture? I know how to RenderCopy() one texture over another, but I do not know how to access the alpha channel of a texture. – DragonDePlatino May 29 '16 at 05:18