Alpha Blending of Geometric Shapes

Hello, I’m new to SDL but not to programming. I’ve been reading all about SDL’s alpha blending capabilities for the last couple of days but still have some questions/issues. Most of the information I have found deals with blitting surfaces onto each other and I’m not doing that. I’m using SDL_gfx to draw simple primitives (pixels, circles, lines, rects, etc.). I’m using the alpha aware calls for these SDL_gfx functions.

The big picture is that I want to draw random circles (for example) into the full screen window (with a black background) and I would like to have later drawn circles which overlap previously drawn circles be semi transparent so you can see what they are covering. This functionality will be part of a particle system I’ve been developing.

I’m trying to determine what setup I need to do to make this happen. My questions are:

  1. Do I need to set SDL_SRCALPHA during video mode setup ? If so, why?

  2. Do I need a call to SDL_SetAlpha on my display surface ? If so, why?

  3. If I call SDL_SetAlpha what value for alpha do I need to pass for the window’s surface?

When I call the SDL_gfx function for drawing a circle I pass it a color that was created with SDL_MapRGBA(surface->format, red, green, blue, alpha) with alpha < 255.

Sometimes I get circles without blending, sometimes the screen remains blank and sometimes I see some blending depending upon the various parameters I use. Usually I could use the process of elimination to figure this out but there are so many variables involved there are to many permutations. If I can get a mental picture of how this process should work I can eliminate the guess work.

One final SDL_gfx related questions. When I have seen blending kinda work it seems like the process is iterative. That is it paints the filled circles multiple times. Is this normal ?

Any help you can provide would be appreciated.

Thank You

Regarding your SDL_gfx issues, what versions (SDL & SDL_gfx) are you
using? What platform is your code running on?

For SDL2 you should use SDL2_gfx.

It is possible that there are still bugs, so please open a ticket and
attach some simple repro code if you found an issue (i.e. the paint
multiple times problem you seem to have).On 6/9/2013 11:02 AM, craiglindley wrote:

Hello, I’m new to SDL but not to programming. I’ve been reading all
about SDL’s alpha blending capabilities for the last couple of days
but still have some questions/issues. Most of the information I have
found deals with blitting surfaces onto each other and I’m not doing
that. I’m using SDL_gfx to draw simple primitives (pixels, circles,
lines, rects, etc.). I’m using the alpha aware calls for these SDL_gfx
functions.

The big picture is that I want to draw random circles (for example)
into the full screen window (with a black background) and I would like
to have later drawn circles which overlap previously drawn circles be
semi transparent so you can see what they are covering. This
functionality will be part of a particle system I’ve been developing.

I’m trying to determine what setup I need to do to make this happen.
My questions are:

  1. Do I need to set SDL_SRCALPHA during video mode setup ? If so, why?

  2. Do I need a call to SDL_SetAlpha on my display surface ? If so, why?

  3. If I call SDL_SetAlpha what value for alpha do I need to pass for
    the window’s surface?

When I call the SDL_gfx function for drawing a circle I pass it a
color that was created with SDL_MapRGBA(surface->format, red, green,
blue, alpha) with alpha < 255.

Sometimes I get circles without blending, sometimes the screen remains
blank and sometimes I see some blending depending upon the various
parameters I use. Usually I could use the process of elimination to
figure this out but there are so many variables involved there are to
many permutations. If I can get a mental picture of how this process
should work I can eliminate the guess work.

One final SDL_gfx related questions. When I have seen blending kinda
work it seems like the process is iterative. That is it paints the
filled circles multiple times. Is this normal ?

Any help you can provide would be appreciated.

Thank You


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

Sorry I guess I should have mentioned the versions in the post.

For SDL it is 1.2.15
For SDL_gfx its 2.0.24

OK I found some more things out.

First, when I create my 32 bit display surface with SDL_SetVideoMode I get a surface without an alpha channel. If I inspect the alpha mask and alpha shift values for this surface they are both zero. So when I map a SDL_mapRGBA color in association with this display surface and then convert it back to RGBA via GetRGBA its alpha value is set to 0xFF regardless of its original value.

The next thing I did was to call SDL_DisplayFormatAlpha on the surface I created above and am attempting to use that for the rendering of circle. After this call if I map and get an RGBA color I get back exactly what I put in. Progress I think.

With this change I can see my code is now calling the _putPixelAlpha code in SDL_gfx as a result of trying to draw an alpha blended circle. This to is good news. Unfortunately, my display remains blank.

If I put print statements into the _putPixelAlpha function I can see the code is writing values like ca17161c to the display memory with ca being the alpha portion of the color, so the pixel should not be transparent.

Any ideas on why my screen remains blank? I’m using a SW surface (for speed) and am doing an SDL_UpdateRect with my surface with x=y=w=h=0 to update the complete surface after I draw my circle.

I have the feeling that the new surface created by calling SDL_DisplayFormatAlpha is divorced from the display.

Is there some other way of creating a display surface that has a alpha channel by default? Or is there a way to associate the new surface with the display?

Thanks again for looking at this post.

Craig Lindley

OK, I figured things out and I wanted to post the code for others who may be interested. What I had to do was
to create a separate renderSurface with an alpha channel (from the displaySurface) and draw the circles onto that instead of directly on the displaySurface. After drawing a circle I blit the renderSurface to the displaySurface and things display correctly without any repainting.

I didn’t have to do anything special with the displaySurface.

Code:

/*

  • Raspberry Pi Test Program for alpha blending of circles*
  • Craig Lindley
    */

#include <stdbool.h>
#include “SDL.h”
#include “…/SDL_gfx/SDL_gfxPrimitives.h”

#define SDL_ERROR -1

// Define the attributes of the display screen
#define SCREEN_WIDTH 1366
#define SCREEN_HEIGHT 768
#define MINX 0
#define MAXX (SCREEN_WIDTH - 1)
#define MIDX (SCREEN_WIDTH / 2)
#define MINY 0
#define MAXY (SCREEN_HEIGHT - 1)
#define MIDY (SCREEN_HEIGHT / 2)

#define SCREEN_BBP 32
#define SCREEN_SURFACE SDL_SWSURFACE
#define SCREEN_FULLSCREEN true

int randomInt0toN(int n) {

return (random() % n);

}

int randomIntNtoM(int n, int m) {

int diff = m - n;
return randomInt0toN(diff) + n;

}

int main (void) {

SDL_Surface *displaySurface;
SDL_Surface *renderSurface;

// Initialize defaults and Video subsystems only
    if ((SDL_Init(SDL_INIT_VIDEO) == SDL_ERROR)) {
        fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError());
        exit(-1);
    }
    // If we get here, SDL initialized

    // Clean up on exit
    atexit(SDL_Quit);

    // Initialize display screen to constants above
    uint32_t flags = SCREEN_SURFACE;
    if (SCREEN_FULLSCREEN) {
        flags |= SDL_FULLSCREEN;
    }
    // Create the display surface
displaySurface  = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BBP, flags);
    if (displaySurface == NULL) {
        fprintf(stderr, "Couldn't set requested video mode: %s\n", SDL_GetError());
        exit(-1);
    }

    // Create a render surface with an alpha channel
    renderSurface = SDL_DisplayFormatAlpha(displaySurface);

// Turn the cursor off
SDL_ShowCursor(SDL_DISABLE);

int i;
for (i = 0; i < 100; i++) {
    
    uint8_t red = randomInt0toN(256);
        uint8_t green = randomInt0toN(256);
        uint8_t blue = randomInt0toN(256);
        uint8_t alpha = randomIntNtoM(32, 256);

        int radius = randomIntNtoM(40, SCREEN_HEIGHT / 10);

        // Make sure to keep the circle's coordinates in bounds
        int x = randomInt0toN(SCREEN_WIDTH);
        while (((x - radius) < 1) || ((x + radius) > SCREEN_WIDTH - 1))
            x = randomInt0toN(SCREEN_WIDTH);

        int y = randomInt0toN(SCREEN_HEIGHT);
        while (((y - radius) < 1) || ((y + radius) > SCREEN_HEIGHT - 1))
            y = randomInt0toN(SCREEN_HEIGHT);

        // Draw some filled circles
        filledCircleRGBA(renderSurface, x, y, radius, red, green, blue, alpha);

    // Blit the render surface to the display surface
    SDL_BlitSurface(renderSurface, NULL, displaySurface, NULL);

    // Update all of the display surface
    SDL_UpdateRect(displaySurface, 0, 0, 0, 0);

    // Do short delay
        SDL_Delay(10);
    }
SDL_Delay(2000);

}

[/code]