# Transparency help [Solved, I've been stupid]

This topic is 4254 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I am making a 2D sprite based game, but the sprites already have a background. Like this: ++++++++++++++++++ ++++++xxxxxx++++++ +++++xxxxxxxx+++++ +++++++xxxx+++++++ ++++++++xx++++++++ ++++++++++++++++++ I hope you get the point(my ASCII art sucks!) In the diagram(?) above, '+' represents brown color and 'x' is my character. Naturally, with this, im bound to a brown blackground. Is there a way to make this brown backroung transparent so that im left only with the character and can see anything this image is placed onto.(ummmm.... like the character walking on water, flying through clouds...). Pleaseeeee help me out. Please. [Edited by - horizon981 on July 4, 2006 10:56:08 AM]

##### Share on other sites
If you're using OpenGL then it could turn out to be quite easy depending on how you load your sprites. All you have to do is convert your images to RGBA (if they aren't already in this format), switch from brown to transparent (=> alpha A = 0 whereas in other cases A = MAX) and enable alpha testing. Alpha testing is in a way color keying (which is what you want), where texels that "fail the alpha test" are rejected and not drawn on the framebuffer. Look for glEnable( GL_ALPHA_TEST ) and glAlphaFunc().

On the other hand, there is another way which is possible in OpenGL (but not in DirectX). In the old days, transparency could be achieved by using a mask and a combination of bit operations. But you'd have to use black instead of brown though. Plus, alpha testing and blending are the way to go. Masking is more or less depreciated (if you forget about stencil masking for a second).

##### Share on other sites
Quote:
 Original post by horizon981I am making a 2D sprite based game, but the sprites already have a background. Like this:++++++++++++++++++++++++xxxxxx+++++++++++xxxxxxxx++++++++++++xxxx+++++++++++++++xx++++++++++++++++++++++++++I hope you get the point(my ASCII art sucks!)In the diagram(?) above, '+' represents brown color and 'x' is my character.Naturally, with this, im bound to a brown blackground. Is there a way to make this brown backroung transparent so that im left only with the character and can see anything this image is placed onto.(ummmm.... like the character walking on water, flying through clouds...).Pleaseeeee help me out. Please.

What is requried is the use of the alpha channel to "mask" the background parts of the image. You have 2 options:

a) Load the image into your art program, add an alpha channel and convert the brown pixels to alpha. (You need an image format that supports alpha, eg tga).

b) If the image loader is your own, after you are done reading pixel data, copy it to a RGBA / BGRA array, and set
alpha = (r == brown_color.r && g == brown_color.g && b == brown_color.b) ? 0 : 255;
where alpha is an unsigned byte.

Before rendering the sprite:
glAlphaFunc(GL_GREATER, 0.5);glEnable(GL_ALPHA_TEST);draw_sprite();

/edit: Believe me, I opened this page and was looking at other things, I'm not that slow! [lol]

##### Share on other sites
Will it work with bmp files?

##### Share on other sites
Quote:
 Original post by horizon981Will it work with bmp files?

As long as they are 32bit and not 24bit.

##### Share on other sites
Problem No. 2: The "paint" program in windows allows only 24 bit bitmaps. Is there another way to get 32 bit bitmaps?

##### Share on other sites
Quote:
 Original post by horizon981Problem No. 2: The "paint" program in windows allows only 24 bit bitmaps. Is there another way to get 32 bit bitmaps?How about RAW files?

RAW files are just another file format. You should use .tga or .dds files. Both support 32bit. I am assuming you are using your own code to load the textures? If not you should look into a texture loading library or look into Phantoms texture loader class he is working on... nehe has a tutorial on .tga loading. HTH

##### Share on other sites
I remember having read there is a way to do that with blending and glTexEnv. If I am correct, this way it doesn't matter how the image is being loaded. Do you know how to do that?

##### Share on other sites
not to go off topic, too much, but if you are making a 2d sprite based game, you could use allegro and then manually set the mask color to whatever you want. allegro assumes it is pink automatically, but you can change that.

##### Share on other sites
Quote:
 Original post by horizon981I remember having read there is a way to do that with blending and glTexEnv. If I am correct, this way it doesn't matter how the image is being loaded. Do you know how to do that?

Your textures need an alpha channel. There are a few image loader libraries out there. I use SDL+SDL_image for OGL output and texture loading.
Then DOWNLOAD GIMP and draw your sprites. When you've done this, select the parts of your image you want to be trasparent, and delete them. Then save the image as TGA (that can keep an alpha channel).
That is how I suggest you to do.

##### Share on other sites
Okay, after many tutorials and references, I am convinced that Alpha Channel is a far better option than Masking. Could anyone recommend a free program to convert 24 bit BMP files to 32 bit TGA files?

##### Share on other sites
oh, i realize that you are using opengl. i was just suggesting allegro because it fits 2d games very well. however, it obviously is fairly limited in what it can do at times. i was just suggesting it because it does the masking automatically.

however, if you used allegrogl (i think that is what it is called) you might be able to use that functionality with opengl too. not sure, haven't looked into it myself.

: you edited while i was posting. :D

##### Share on other sites
Quote:
 Original post by horizon981Okay, after many tutorials and references, I am convinced that Alpha Channel is a far better option than Masking. Could anyone recommend a free program to convert 24 bit BMP files to 32 bit TGA files?

Quote:
 Original post by cignox1DOWNLOAD GIMP and draw your sprites. When you've done this, select the parts of your image you want to be trasparent, and delete them. Then save the image as TGA (that can keep an alpha channel).

;)

##### Share on other sites
I download GIMP(nice one), opened the bitmap image, chose 'select by color'->selected brown background->Cut. The background was replaced by a checkerboard, which i'll take as a transparent one.Added an alpha channel.Then, I saved it as .TGA file.

Have I done anything wrong till now? Is this the way to do it?
If yes, i'll procced to TGA loader functions...

##### Share on other sites
sounds about right... get the loader functions... their easy enough to find kicking about the internet now :D

##### Share on other sites
I'll try SDL_Image. Is that acceptable?

##### Share on other sites
Here's my image.

When I used the NeHe TGA loader, I am getting a white texture [crying] [crying]
Looks like there is no end to my problems!

I did remove the background in GIMP as I mentioned above, but somehow, GIMP shows the image to be 24bpp [crying]

How can I convert it to 32bpp in GIMP? There seems to be no particular option for that.

HELP!! [bawling] [bawling]

##### Share on other sites
Quote:
 Original post by horizon981How can I convert it to 32bpp in GIMP? There seems to be no particular option for that.

Also, post your call to glTexImage2D.

##### Share on other sites
Quote:
 Original post by horizon981Here's my image.Please download it, run it in GIMP and see what's wrong.I am unable to load it using IMG_Load.When I used the NeHe TGA loader, I am getting a white texture [crying] [crying]Looks like there is no end to my problems! I did remove the background in GIMP as I mentioned above, but somehow, GIMP shows the image to be 24bpp [crying]How can I convert it to 32bpp in GIMP? There seems to be no particular option for that.HELP!! [bawling] [bawling]

Your image works fine for me. It looks correct in GIMP, and also looks correct when loaded and used in OpenGL. I guess the issue might lie in your rendering code. Make sure you are properly enabling texturing at the right time and binding the texture before rendering the quads. Post up some code so we can see.

The following code was used before rendering the image to enable the alpha test and blending mode:

// enable and set modes for blending and alpha testingglEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_ALPHA_TEST);glAlphaFunc(GL_GREATER, 0);// bind and draw imageglBindTexture(GL_TEXTURE_2D,texName[0]);.. render image (glTexCoord* and glVertex* calls)

hth
F451

##### Share on other sites
Im going nuts. [crying]
#include <SDL/SDL.h>#include <SDL/SDL_Image.h>#include <GL/gl.h>#include <GL/glu.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#ifndef GL_BGR#define GL_BGR 0x80E0#endifstruct TextureImage										// Create A Structure{	GLubyte	*imageData;								// Image Data (Up To 32 Bits)	GLuint	bpp;									// Image Color Depth In Bits Per Pixel	GLuint	width;									// Image Width	GLuint	height;									// Image Height    GLuint texID;}textures;bool LoadTGA(TextureImage *texture, char *filename)					// Loads A TGA File Into Memory{         	GLubyte		TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};			// Uncompressed TGA Header	GLubyte		TGAcompare[12];							// Used To Compare TGA Header	GLubyte		header[6];							// First 6 Useful Bytes From The Header	GLuint		bytesPerPixel;							// Holds Number Of Bytes Per Pixel Used In The TGA File	GLuint		imageSize;							// Used To Store The Image Size When Setting Aside Ram	GLuint		temp;								// Temporary Variable	GLuint		type=GL_RGBA;			FILE *file = fopen(filename, "rb");						// Open The TGA File	if(	file==NULL ||								// Does File Even Exist?		fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||	// Are There 12 Bytes To Read?		memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0		||	// Does The Header Match What We Want?		fread(header,1,sizeof(header),file)!=sizeof(header))			// If So Read Next 6 Header Bytes	{		if (file == NULL)							// Did The File Even Exist? *Added Jim Strong*			return false;							// Return False		else		{			fclose(file);							// If Anything Failed, Close The File			return false;							// Return False		}	}		texture->width  = header[1] * 256 + header[0];					// Determine The TGA Width	(highbyte*256+lowbyte)	texture->height = header[3] * 256 + header[2];					// Determine The TGA Height	(highbyte*256+lowbyte)     	if(	texture->width	<=0	||						// Is The Width Less Than Or Equal To Zero		texture->height	<=0	||						// Is The Height Less Than Or Equal To Zero		(header[4]!=24 && header[4]!=32))					// Is The TGA 24 or 32 Bit?	{		fclose(file);								// If Anything Failed, Close The File		return false;								// Return False	}		texture->bpp	= header[4];							// Grab The TGA's Bits Per Pixel (24 or 32)	bytesPerPixel	= texture->bpp/8;						// Divide By 8 To Get The Bytes Per Pixel	imageSize	= texture->width*texture->height*bytesPerPixel;				texture->imageData=(GLubyte *)malloc(imageSize);				// Reserve Memory To Hold The TGA Data	if(	texture->imageData==NULL ||						// Does The Storage Memory Exist?		fread(texture->imageData, 1, imageSize, file)!=imageSize)		// Does The Image Size Match The Memory Reserved?	{		if(texture->imageData!=NULL)						// Was Image Data Loaded			free(texture->imageData);					// If So, Release The Image Data		fclose(file);								// Close The File		return false;								// Return False	} 	for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)				// Loop Through The Image Data	{										// Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)		temp=texture->imageData;						// Temporarily Store The Value At Image Data 'i'		texture->imageData = texture->imageData[i + 2];			// Set The 1st Byte To The Value Of The 3rd Byte		texture->imageData[i + 2] = temp;					// Set The 3rd Byte To The Value In 'temp' (1st Byte Value)	}	fclose (file);		glGenTextures(1, &texture[0].texID);						// Generate OpenGL texture IDs	glBindTexture(GL_TEXTURE_2D, texture[0].texID);					// Bind Our Texture	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);		// Linear Filtered	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);			if (texture[0].bpp==24)								// Was The TGA 24 Bits	{		type=GL_RGB;								// If So Set The 'type' To GL_RGB	}	glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData);	return true;									// Texture Building Went Ok, Return True}static void quit_tutorial( int code ){    SDL_Quit( );    glDeleteTextures(1,&textures.texID);    exit( code );}GLuint LoadTexturesTGA(char* filename){  glEnable(GL_BLEND);  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  glEnable(GL_ALPHA_TEST);  glAlphaFunc(GL_GREATER, 0);    GLuint texture;  glGenTextures( 1, &texture );  glBindTexture( GL_TEXTURE_2D, texture );    SDL_Surface *surf = IMG_Load( filename );  SDL_LockSurface( surf );  gluBuild2DMipmaps( GL_TEXTURE_2D, 3, surf->w, surf->h, GL_BGR, GL_UNSIGNED_BYTE, surf->pixels );  SDL_UnlockSurface( surf );  SDL_FreeSurface( surf );    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );  glBindTexture( GL_TEXTURE_2D, texture );  return texture;  }static void handle_key_down( SDL_keysym* keysym ){   switch( keysym->sym ) {    case SDLK_ESCAPE:         quit_tutorial(1);         break;    default:        break;    }}static void process_events( void ){    /* Our SDL event placeholder. */    SDL_Event event;    /* Grab all the events off the queue. */    while( SDL_PollEvent( &event ) ) {        switch( event.type ) {        case SDL_KEYDOWN:            /* Handle key presses. */            handle_key_down( &event.key.keysym );            break;        case SDL_QUIT:            /* Handle quit requests (like Ctrl-c). */            quit_tutorial( 0 );            break;        }    }}     static void draw_screen( void ){    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();        glColor3f(1.0f,1.0f,1.0f);    glTranslatef(0.0f,0.0f,-2.5f);        glBegin( GL_QUADS );     glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);     glTexCoord2d(1.0,0.0); glVertex2d(0.5,0.0);     glTexCoord2d(1.0,1.0); glVertex2d(0.5,0.5);     glTexCoord2d(0.0,1.0); glVertex2d(0.0,0.5);    glEnd();    /*     * Swap the buffers. This tells the driver to     * render the next frame from the contents of the     * back-buffer, and to set all rendering operations     * to occur on what was the front-buffer.     *     * Double buffering prevents nasty visual tearing     * from the application drawing on areas of the     * screen that are being updated at the same time.     */    SDL_GL_SwapBuffers( );}static void setup_opengl( int width, int height ){    float ratio = (float) width / (float) height;    /* Our shading model--Gouraud (smooth). */    glShadeModel( GL_SMOOTH );    /* Culling. */    glCullFace( GL_BACK );    glFrontFace( GL_CCW );    glEnable( GL_CULL_FACE );    glEnable( GL_DEPTH_TEST );    glEnable(GL_TEXTURE_2D);    /* Set the clear color. */    glClearColor( 0, 0, 0, 1 );    /* Setup our viewport. */    glViewport( 0, 0, width, height );        glEnable(GL_BLEND);    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);    glEnable(GL_ALPHA_TEST);    glAlphaFunc(GL_GREATER, 0);        glMatrixMode(GL_TEXTURE);    glScalef(1.0f, -1.0f, 1.0f);    glMatrixMode(GL_MODELVIEW);           glEnable(GL_BLEND);            glMatrixMode( GL_PROJECTION );    glLoadIdentity( );    /*     * EXERCISE:     * Replace this with a call to glFrustum.     */    gluPerspective( 60.0, ratio, 1.0, 1024.0 );}int main( int argc, char* argv[] ){    /* Information about the current video settings. */    const SDL_VideoInfo* info = NULL;    /* Dimensions of our window. */    int width = 0;    int height = 0;    /* Color depth in bits of our window. */    int bpp = 0;    /* Flags we will pass into SDL_SetVideoMode. */    int flags = 0;    /* First, initialize SDL's video subsystem. */    if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {        /* Failed, exit. */        fprintf( stderr, "Video initialization failed: %s\n",             SDL_GetError( ) );        quit_tutorial( 1 );    }    /* Let's get some video information. */    info = SDL_GetVideoInfo( );    if( !info ) {        /* This should probably never happen. */        fprintf( stderr, "Video query failed: %s\n",             SDL_GetError( ) );        quit_tutorial( 1 );    }    /*     * Set our width/height to 640/480 (you would     * of course let the user decide this in a normal     * app). We get the bpp we will request from     * the display. On X11, VidMode can't change     * resolution, so this is probably being overly     * safe. Under Win32, ChangeDisplaySettings     * can change the bpp.     */    width = 640;    height = 480;    bpp = info->vfmt->BitsPerPixel;    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );    /*     * We want to request that SDL provide us     * with an OpenGL window, in a fullscreen     * video mode.     *     * EXERCISE:     * Make starting windowed an option, and     * handle the resize events properly with     * glViewport.     */    flags = SDL_OPENGL | SDL_FULLSCREEN;    /*     * Set the video mode     */    if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {        /*          * This could happen for a variety of reasons,         * including DISPLAY not being set, the specified         * resolution not being available, etc.         */        fprintf( stderr, "Video mode set failed: %s\n",             SDL_GetError( ) );        quit_tutorial( 1 );    }    /*     * At this point, we should have a properly setup     * double-buffered window for use with OpenGL.     */    setup_opengl( width, height );        char file1[50] = "Data/TGA/player_attack_";    char file2[] = "east_1.tga";    strcat(file1,file2);     LoadTGA(&textures, file1);    //textures.texID = LoadTexturesTGA(file1);     /*     * Now we want to begin our normal app process--     * an event loop with a lot of redrawing.     */    while( 1 ) {        /* Process incoming events. */        process_events( );        /* Draw the screen. */        draw_screen( );    }    /*     * EXERCISE:     * Record timings using SDL_GetTicks() and     * and print out frames per second at program     * end.     */    /* Never reached. */    return 0;}

Still a white rectangle.
Note that I have two functions to load textures

When function 2 is used, the application simply closes, maybe indicating failure to load the image.
[crying] [crying]
And LoadTGA() shows me a plain white box.

It doesn't matter where I put:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0);

HELLLLLLLLLLLLLLLLP!!

[Edited by - horizon981 on July 4, 2006 8:37:43 AM]

##### Share on other sites
Yes, I use IMG_Load() for my textures. First of all, I wrote the following function to reverse the pixels (that are stored differently than how opengl requires for textures):
SDL_Surface *FlipSurfaceV(SDL_Surface *bitmap){	if(!bitmap)return NULL;	SDL_Surface *temp=SDL_CreateRGBSurface(0,bitmap->w,bitmap->h,		bitmap->format->BitsPerPixel,bitmap->format->Rmask,bitmap->format->Gmask,		bitmap->format->Bmask,bitmap->format->Amask);	if(!temp)return NULL;	unsigned int rowsize = bitmap->w*(bitmap->format->BitsPerPixel/8);	char* src = (char*)bitmap->pixels;	char* dest = ((char*)temp->pixels)+(temp->h-1)*rowsize;	for(int i=0;i<bitmap->h;i++)	{	    memcpy(dest, src, rowsize);	    src += rowsize;	    dest -= rowsize;	}	return temp;}

Then the following code loads the image and creates the texture:
                string file = map.name;                SDL_Surface* mm = IMG_Load(file.c_str());                SDL_Surface* m = FlipSurfaceV(mm);                unsigned int t;                glGenTextures(1, &t);                glBindTexture(GL_TEXTURE_2D, t);                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m->w, m->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, m->pixels);                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);	// Linear Filtering                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);	// Linear Filtering

##### Share on other sites
[crying] [crying] [crying][crying] [crying] [crying][crying] [crying] [crying]
There seems to be no end to my problems!!!

If I use the code provided by you above, my compiler tells me GL_BGRA is undeclared.

So, I used this Class to load the TGA texture in RGBA mode. To my surprise, the brown background of the image has returned!!! However, when I view that image in GIMP, it has no background. In IrfanView however, I see a brown background!!! In Nero PhotoSnap Viewer, it has a white background!!
What's going on?????

[Edited by - horizon981 on July 4, 2006 3:21:21 AM]

##### Share on other sites
I think that GL_BGRA is defined in glext.h, the header for the opengl extensions.

##### Share on other sites
Well, BGRA simply leads to a color format change. The damn image doesn't seem to be losing its background.

##### Share on other sites
Are you sure that you are correctly setting opengl parameters for blending? Try with this nehe lesson about blending and check that you're doing the right operations.