Png transparency in testgl.c from sdl package

I’ve slightly modified the testgl.c program that comes with the sdl source to use SDL_image’s IMG_LOAD function instead of SDL_LoadBMP. but when I run it the logocursor has a background and is no longer alpha transparent. You can find the source in the tests folder in the SDL-1.X.XX.tar.gz package.
bellow is a snippet of the relevant code.

void SDL_GL_Enter2DMode()
{
SDL_Surface *screen = SDL_GetVideoSurface();

/* Note, there may be other things you need to change,
depending on how you have your OpenGL state set up.
*/
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);

/* This allows alpha blending of 2D textures with the scene */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glViewport(0, 0, screen->w, screen->h);

glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();

glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glColor4ub(0,0,0,255);
}

GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord)
{
GLuint texture;
int w, h;
SDL_Surface *image;
SDL_Rect area;
Uint32 saved_flags;
Uint8 saved_alpha;

/* Use the surface width and height expanded to powers of 2 /
w = power_of_two(surface->w);
h = power_of_two(surface->h);
texcoord[0] = 0.0f; /
Min X /
texcoord[1] = 0.0f; /
Min Y /
texcoord[2] = (GLfloat)surface->w / w; /
Max X /
texcoord[3] = (GLfloat)surface->h / h; /
Max Y */

image = SDL_CreateRGBSurface(
SDL_SWSURFACE,
w, h,
32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);
if ( image == NULL ) {
return 0;
}

/* Save the alpha blending attributes */
saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
saved_alpha = surface->format->alpha;
if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
SDL_SetAlpha(surface, 0, 0);
}

/* Copy the surface into the GL texture image */
area.x = 0;
area.y = 0;
area.w = surface->w;
area.h = surface->h;
SDL_BlitSurface(surface, &area, image, &area);

/* Restore the alpha blending attributes */
if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
SDL_SetAlpha(surface, saved_flags, saved_alpha);
//SDL_SetAlpha(surface, 0, SDL_ALPHA_TRANSPARENT);
}

/* Create an OpenGL texture for the image /
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
w, h,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
image->pixels);
SDL_FreeSurface(image); /
No longer needed */

return texture;
}

void DrawLogoCursor(void)
{
static GLfloat texMinX, texMinY;
static GLfloat texMaxX, texMaxY;
static int w, h;
int x, y;

if ( ! cursor_texture ) {
SDL_Surface *image;
GLfloat texcoord[4];

/* Load the image (could use SDL_image library here) */
image = IMG_Load(LOGO_FILE);
if ( image == NULL ) {
return;
}
w = image->w;
h = image->h;

/* Convert the image into an OpenGL texture */
cursor_texture = SDL_GL_LoadTexture(image, texcoord);

/* Make texture coordinates easy to understand */
texMinX = texcoord[0];
texMinY = texcoord[1];
texMaxX = texcoord[2];
texMaxY = texcoord[3];

/* We don’t need the original image anymore */
SDL_FreeSurface(image);

/* Make sure that the texture conversion is okay */
if ( ! cursor_texture ) {
return;
}
}

/* Move the image around */
SDL_GetMouseState(&x, &y);
x -= w/2;
y -= h/2;

/* Show the image on the screen */
SDL_GL_Enter2DMode();
glBindTexture(GL_TEXTURE_2D, cursor_texture);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(texMinX, texMinY); glVertex2i(x, y );
glTexCoord2f(texMaxX, texMinY); glVertex2i(x+w, y );
glTexCoord2f(texMinX, texMaxY); glVertex2i(x, y+h);
glTexCoord2f(texMaxX, texMaxY); glVertex2i(x+w, y+h);
glEnd();
SDL_GL_Leave2DMode();
}

Anyone able to help? Also when I set glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); to GL_ONE,GL_ONE the background is blended out, but when objects pass over each other they are semi-transparent. Been stuck on this problem for two months now!

Read this:
http://glprogramming.com/red/chapter06.html

Tells you all you need to know about opengl blending.On Sun, Dec 12, 2010 at 5:56 PM, image28 wrote:

Anyone able to help? Also when I set
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); to GL_ONE,GL_ONE the
background is blended out, but when objects pass over each other they are
semi-transparent. Been stuck on this problem for two months now!


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

I think the blending is setup right because when I use the original testgl.c code which loads a RGB bmp file and converts it to a alpha surface it is blended perfectly, but when I switched the SDL_LoadBMP with IMG_Load and the file from a RGB bitmap to a RGBA png file the blending stopped working. I got the RGBA pixels and printed there values and they were correct, 0 for transparent area, 255 for solid areas. and lower values for the partly visible colours.

changing the line glColor4ub(0,0,0,255); to glColor4ub(0,0,0,128); makes all images 50% transparent. for some reason it is using the colour setting from that line instead of the individual pixels colour in the texture.

Maybe you should remove that line entirely.On Sun, Dec 12, 2010 at 10:13 PM, image28 wrote:

changing the line glColor4ub(0,0,0,255); to glColor4ub(0,0,0,128); makes all
images 50% transparent. for some reason it is using the colour setting from
that line instead of the individual pixels colour in the texture.


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

I haven’t spotted anything obvious in the code you posted earlier. It seems
like it should work, provided there actually is an alpha channel i the loaded
image.

The glColor*() call shouldn’t have anything to do with it. Whatever values you
set for color and alpha that way are only going to scale whatever comes from
the texture, so 0 means “always zero” and 255 means “use texel data as is.”

BTW, restoring the alpha attributes of the new SDL surface shouldn’t matter
either, as OpenGL only ever sees the raw pixel data. Unless you RLE the
surface, the attributes will only affect the SDL_Surface struct; not the
actual pixel data.

I would suggest somehow verifying the surface/texture data along the way.
Print out the values of the alpha channel, to verify that there actually is
anything but opaque pixels in the surface uploaded. An OpenGL debugger
(gDEBugger or similar) might give some hints as well.On Monday 13 December 2010, at 04.13.37, “image28” wrote:

changing the line glColor4ub(0,0,0,255); to glColor4ub(0,0,0,128); makes
all images 50% transparent. for some reason it is using the colour setting
from that line instead of the individual pixels colour in the texture.


//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://consulting.olofson.net http://olofsonarcade.com |
’---------------------------------------------------------------------’

Tried gDEBugger. The texture viewer loaded the textures correctly with alpha values, other than that I havent worked out how to use it properly yet, setup some watches for the state of GL_BLEND which it said it was disabled while the program was running, which is probaly correct because it would only be enabled for a split second to perform the drawing.

Just a quick thought–GL_DECAL means to replace the primitive color
with the texture color, which may mean it also disables blending. I
use GL_MODULATE exclusively (then just set color to 1.0, 1.0, 1.0 when
I want to display the texture as-is).

Hope the helps,

John

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

becomes

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);On Mon, Dec 13, 2010 at 2:09 PM, image28 wrote:

Tried gDEBugger. The texture viewer loaded the textures correctly with alpha
values, other than that I havent worked out how to use it properly yet,
setup some watches for the state of GL_BLEND which it said it was disabled
while the program was running, which is probaly correct because it would
only be enabled for a split second to perform the drawing.


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

Thanks you, Thank you, Thank you… That worked perfectly… :smiley:

Merry Christmas :smiley: