How do I blit a surface RGBA -> RGBA without alpha blending?

Hi,

I’m writing a little game akin to Siedler 3 using sdl. In the game I
have a (relatively) static terrain layer and a dynamic layer for items,
buildings and units that change every frame (well, units run around and
the rest is needed so a unit behind something is ocluded by it).

So what I want to do is render the terrain into a surface (after every
change) once and then on each frame blit the terrain in and draw the
items, buildings and units on top and then flip the result to screen.

My terrain tiles, items, units and buildings are in png files with
transparency and loading them gives me an RGBA surface with SRCALPHA
set. SDL_CreateRGBSurface() with depth=32 also gives me an RGBA surface
with SRCALPHA set and my windows surface also has SRCALPHA set. In fact
I can’t seem to manage to create any surface without SRCALPHA set.

Now the problem is that blitting the terrain tiles into the terrain
surface does alpha blending (as it must) and the resulting pixels all
have an alpha value of 0 (why?). Blitting the terrain tiles to the
window then again does alpha blending showing nothing (alpha=0 -> totaly
transparent).

So how can I tell blit not to do alpha blending? I would prefer having
the rendered terrain in video memory and blitting it there for obvious
reasons. So writing my own memcpy() loop doesn’t sound like a good idea.

MfG
Goswin

SDL 1.2, right? Have you looked at SDL_SetAlpha()? With that, you can
enable or disable alpha blending. You might also benefit from reading my
article on the subject:
http://code.bluedinosaurs.com/articles/blending.html

Jonny DOn Tue, May 1, 2012 at 9:09 AM, Goswin von Brederlow wrote:

Hi,

I’m writing a little game akin to Siedler 3 using sdl. In the game I
have a (relatively) static terrain layer and a dynamic layer for items,
buildings and units that change every frame (well, units run around and
the rest is needed so a unit behind something is ocluded by it).

So what I want to do is render the terrain into a surface (after every
change) once and then on each frame blit the terrain in and draw the
items, buildings and units on top and then flip the result to screen.

My terrain tiles, items, units and buildings are in png files with
transparency and loading them gives me an RGBA surface with SRCALPHA
set. SDL_CreateRGBSurface() with depth=32 also gives me an RGBA surface
with SRCALPHA set and my windows surface also has SRCALPHA set. In fact
I can’t seem to manage to create any surface without SRCALPHA set.

Now the problem is that blitting the terrain tiles into the terrain
surface does alpha blending (as it must) and the resulting pixels all
have an alpha value of 0 (why?). Blitting the terrain tiles to the
window then again does alpha blending showing nothing (alpha=0 -> totaly
transparent).

So how can I tell blit not to do alpha blending? I would prefer having
the rendered terrain in video memory and blitting it there for obvious
reasons. So writing my own memcpy() loop doesn’t sound like a good idea.

MfG
Goswin


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Jonathan Dearborn writes:

SDL 1.2, right? ?Have you looked at SDL_SetAlpha()? ?With that, you can enable
or disable alpha blending. ?You might also benefit from reading my article on
the subject:
http://code.bluedinosaurs.com/articles/blending.html

Jonny D

Yes, SDl 1.2. Thanks, SDL_SetAlpha() is indeed the solution. I still
wonder though why one can’t specify that during creation of a surface.

One more thing though. Is there a way to alpha blend but also blend the
alpha values itself? And by that I mean that it combines the sources
alpha value and color with the destinations alpha value and color to
produce a combined resulting alpha value and color.

Say I have 3 surfaces A, B and C. A is all red, B is all green with 50%
alpha and C is all blue with 50% alpha. Is there a way to blit C to B
and then B to A so that the result is the same as blitting B and C to A
directly?

Use case: I have a basic unit that carries stuff. I also have a bunch of
items it can carry. Both fade to transparent at their border to give
smooth lines on any background. I now want to generate surfaces for
unit-carrying-X for each item so I don’t have to blend them seperately
every time. So I need to blend the item onto the unit but still need the
combined border to fade to transparent.

MfG
Goswin

You can tell SDL_CreateRGBSurface() to not set SDL_SRCALPHA by passing 0 as
the Amask argument. If the bit depth is still 32 bits (or whatever as long
as the masks are right) and the other masks are as usual, then I think you
can technically have an alpha channel without using it until you set the
proper alpha mask.

Compositing RGBA surfaces is not provided through SDL’s function API. You
have to do it yourself or use the blitter from Sprig or SDL_gfx to do it.

Jonny D

SDL supports two types of surface:

  • Alpha channel on the entire surface, created with amask = 0, alpha is
    stored in the global variable SDL_Surface-> format-> alpha, and changes in the
    SDL_SetAlpha call.
  • Alpha channel per pixel, is created when valid amask, the value stored in
    the pixel color, and SDL_SetAlpha call will change the flag SDL_SRCSLPHA.

So, for simple SDL_BLit: RGB -> RGB, RGBA -> RGBA, it works well.

How do I blit a surface RGBA -> RGBA without alpha blending?
Since you’re using RGBA surface, you simply need to manipulate the flag
SDL_SRCSLPHA (use SDL_SetAlpha with flag value).

So, for complex SDL_Blit: RGB->RGBA, RGBA->RGB, it work well only for 32
bpp (sdl_aplha_test attachment).
-------------- next part --------------
A non-text attachment was scrubbed…
Name: sdl_alpha_test.tar.gz
Type: application/x-gzip
Size: 5581 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20120503/941c8302/attachment.bin