problem in my color keying code

Started by
13 comments, last by Khaos Dragon 19 years, 10 months ago
I am adapting the CreateTexture function from the famous gametutorials site to be able to handle both normal images and color
keyed images. The new function which I have so far takes in an additional boolean argument which is true if all black colored pixels
should be keyed out. Otherwise, if it is false, the function should work normally. By the way, it works fine whenever I don't use color keying... I just don't see any transparency when I do use color keying and it looks entirely the same as if I didn't use it all. Here is my function:

void CreateTexture( unsigned int* intPtr, char* filename, bool color_key)
{
    int channels;
    unsigned char * newData;
    SDL_Surface *pBitmap[1];
    pBitmap[0] = IMG_Load( filename );       
    if(pBitmap[0] == NULL)                                
        return;

    glGenTextures(1, intPtr );
    glBindTexture(GL_TEXTURE_2D, *intPtr );
    int width  = pBitmap[0] -> w;
    int height = pBitmap[0] -> h;
    unsigned char * data = (unsigned char *) (pBitmap[0] -> pixels);   

    if( !color_key)
    {
	channels = 3;
	newData = new unsigned char[width*height*3];
     }
    else
    {
	channels = 4;
	newData = new unsigned char[width*height*4];
     }

    int BytesPerPixel = pBitmap[0] -> format -> BytesPerPixel ; 
    for( int i = 0 ; i < (height / 2) ; ++i )
        for( int j = 0 ; j < width * BytesPerPixel; j += BytesPerPixel )
            for(int k = 0; k < BytesPerPixel; ++k)
			{
				unsigned char  temp = data[ (i * width * BytesPerPixel) + j + k];
				data[ (i * width * BytesPerPixel) + j + k]    =  data[ ( (height - i - 1) * width * BytesPerPixel ) + j + k];
				data[ ( (height - i - 1) * width * BytesPerPixel ) + j + k]    = temp;
			}
    for(i = 0; i < (width * height); ++i)
    {
        unsigned char r,g,b;                                               
        Uint32 pixel_value = 0;                                    
        for(int j = BytesPerPixel - 1 ; j >=0; --j)                
        {
            pixel_value = pixel_value << 8;                        
            pixel_value = pixel_value | data[ (i * BytesPerPixel) + j ]; 
        }                                                                 
        SDL_GetRGB(pixel_value, pBitmap[0] -> format, (Uint8 *)&r, (Uint8 *)&g, (Uint8 *)&b);    
        
	newData[(i * channels) + 0] = r;        
        newData[(i * channels) + 1] = g;          
        newData[(i * channels) + 2] = b;    
	if( color_key )
	{
	     if( r == 0 && g == 0 && b == 0 )
		newData[(i * channels) + 3] == 0;
	     else
		newData[(i * channels) + 3] == 255;
	}

        pixel_value = 0;                                           
    }
    
	if( color_key )
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pBitmap[0]->w, pBitmap[0]->h, GL_RGBA, GL_UNSIGNED_BYTE, newData);
	else
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pBitmap[0]->w, pBitmap[0]->h, GL_RGB, GL_UNSIGNED_BYTE, newData);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
    delete [] newData;
    SDL_FreeSurface(pBitmap[0]);                       
}
     
Then in my rendering loop I do this: glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); before I actually enable my texturing and draw my textured polies. But the black colored part of the texture still shows.I have no idea what I could be doing wrong. Any help would greatly be appreciated. [edited by - Khaos Dragon on June 2, 2004 12:10:38 AM] [edited by - Khaos Dragon on June 2, 2004 12:11:30 AM] [edited by - Khaos Dragon on June 2, 2004 12:14:37 AM] [edited by - Khaos Dragon on June 2, 2004 12:16:14 AM]
Advertisement
and for reference I am posting the original version of the CreateTexture function. I realize I use an integer pointer instead of an array but it works fine.
Example of how I make a texture.
unsigned int tex_id;
CreateTexture( &tex_id, "picture.bmp", false );

Anyways here is gametutorial''s version:

void CreateTexture(unsigned int textureArray[],char *strFileName,int textureID){    SDL_Surface *pBitmap[1];    if( strFileName == NULL )                           // Return from the function if no file name was passed in        return ;    // We need to load the texture data, so we use a cool function that SDL offers.        pBitmap[0] = SDL_LoadBMP(strFileName);              // Load the bitmap and store the data    if(pBitmap[0] == NULL)                                // If we can''t load the file, quit!    {        cerr << " Failed loading " << strFileName << " : " << SDL_GetError() << endl;        Quit(0);    }    // Now that we have the texture data, we need to register our texture with OpenGL    // To do this we need to call glGenTextures().  The 1 for the first parameter is    // how many texture we want to register this time (we could do a bunch in a row).    // The second parameter is the array index that will hold the reference to this texture.    // Generate a texture with the associative texture ID stored in the array    glGenTextures(1, &textureArray[textureID]);    // Now that we have a reference for the texture, we need to bind the texture    // to tell OpenGL this is the reference that we are assigning the bitmap data too.    // The first parameter tells OpenGL we want are using a 2D texture, while the    // second parameter passes in the reference we are going to assign the texture too.    // We will use this function later to tell OpenGL we want to use this texture to texture map.    // Bind the texture to the texture arrays index and init the texture    glBindTexture(GL_TEXTURE_2D, textureArray[textureID]);    // WARNING   : GO THROUGH THESE FEW LINES FOR SWAPPING ROWS onLY IF YOU REALLY NEED TO, OR ELSE SKIP    // THE LINES MARKED BELOW. Just take it for granted that these lines of code swap rows in the texture     // as required by us.        //       (FROM HERE)        -------------------    //    // IMPORTANT : SDL loads Bitmaps differently when compared to the default windows loader. The row 0    // corresponds to the top row and NOT the bottom row. Therefore if we don''t invert the order of the rows,    // then the textures will appear (vertically) inverted.    // Therefore we must reverse the ordering of the rows in the data of the loaded surface ( the member    //  ''pixels'' of the structure)        // Rearrange the pixelData         int width  = pBitmap[0] -> w;    int height = pBitmap[0] -> h;    unsigned char * data = (unsigned char *) (pBitmap[0] -> pixels);         // the pixel data    unsigned char * newData = new unsigned char[width*height*3];    int channels = 3; // R,G,B    int BytesPerPixel = pBitmap[0] -> format -> BytesPerPixel ;     //////////// This is how we swap the rows :    // For half the rows, we swap row ''i'' with row ''height - i -1''. (if we swap all the rows    // like this and not the first half or the last half, then we get the same texture again !    //    // Now these rows are not stored as 2D arrays, instead they are stored as a long 1D array.    // So each row is concatenated after the previous one to make this long array. Our swap     // function swaps one byte at a time and therefore we swap BytesPerPixel (= total bits per pixel)    // bytes succesively.    //    // so the three loops below are :    // for the first half of the rows    //   for all the width (which is width of image * BytesPerPixel, where BytesPerPixel = total bits per pixel).    //   (Here, for each pixel, we have to increment j by total bits per pixel (to get to next pixel to swap))    //      for(each byte in this pixel i.e k = 0 to BytesPerPixel - 1, i.e BytesPerPixel bytes.    //        swap the byte with the corresponding byte in the ''height -i -1''th row (''i''th row from bottom)    for( int i = 0 ; i < (height / 2) ; ++i )        for( int j = 0 ; j < width * BytesPerPixel; j += BytesPerPixel )            for(int k = 0; k < BytesPerPixel; ++k)                swap( data[ (i * width * BytesPerPixel) + j + k], data[ ( (height - i - 1) * width * BytesPerPixel ) + j + k]);     //        (TO HERE)   -------------------       // the following lines extract R,G and B values from any bitmap    for(int i = 0; i < (width * height); ++i)    {        byte r,g,b;                                                // R,G and B that we will put into pImage        Uint32 pixel_value = 0;                                    // 32 bit unsigned int (as dictated by SDL)        // the following loop extracts the pixel (however wide it is 8,16,24 or 32) and         // creates a long with all these bytes taken together.                for(int j = BytesPerPixel - 1 ; j >=0; --j)                // for each byte in the pixel (from the right)        {            pixel_value = pixel_value << 8;                        // left shift pixel value by 8 bits            pixel_value = pixel_value | data[ (i * BytesPerPixel) + j ];  // then make the last 8 bits of pixel value  =        }                                                                 // the byte that we extract from pBitmap''s data        SDL_GetRGB(pixel_value, pBitmap[0] -> format, (Uint8 *)&r, (Uint8 *)&g, (Uint8 *)&b);     // here we get r,g,b from pixel_value which is stored in the form specified by pBitmap->format        newData[(i * channels) + 0] = r;          // in our tImage classes we store r first        newData[(i * channels) + 1] = g;          // then g        newData[(i * channels) + 2] = b;          // and finally b (for bmps - three channels only)        pixel_value = 0;                                           // reset pixel , else we get incorrect values of r,g,b    }    // Now comes the important part, we actually pass in all the data from the bitmap to    // create the texture. Here is what the parameters mean in gluBuild2DMipmaps():    // (We want a 2D texture, 3 channels (RGB), bitmap width, bitmap height, It''s an RGB format,    //  the data is stored as unsigned bytes, and the actuall pixel data);    // What is a Mip map?  Mip maps are a bunch of scaled pictures from the original.  This makes    // it look better when we are near and farther away from the texture map.  It chooses the    // best looking scaled size depending on where the camera is according to the texture map.    // Otherwise, if we didn''t use mip maps, it would scale the original UP and down which would    // look not so good when we got far away or up close, it would look pixelated.    // Build Mipmaps (builds different versions of the picture for distances - looks better)    // Build Mipmaps (builds different versions of the picture for distances - looks better)    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pBitmap[0]->w, pBitmap[0]->h, GL_RGB, GL_UNSIGNED_BYTE, newData);    // Lastly, we need to tell OpenGL the quality of our texture map.  GL_LINEAR_MIPMAP_LINEAR    // is the smoothest.  GL_LINEAR_MIPMAP_NEAREST is faster than GL_LINEAR_MIPMAP_LINEAR,     // but looks blochy and pixilated.  Good for slower computers though.  Read more about     // the MIN and MAG filters at the bottom of main.cpp    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);    // Now we need to free the bitmap data that we loaded since openGL stored it as a texture    delete [] newData;        SDL_FreeSurface(pBitmap[0]);                        // Free the texture data we dont need it anymore} 
perhaps you should use a different color then black for the color key unless you dont want to show black in your textures.
The most popular color to set as the color key is magenta I think it is called. It is r = 255, g = 0, b = 255 I think....the bright pink color


"A soldier is a part of the 1% of the population that keeps the other 99% free" - Lt. Colonel Todd, 1/38th Infantry, Ft. Benning, GA
Oh I intend to change the color key eventually, however for testing purposes, I am using black right now.
Try to use Alpha Testing
quote:Original post by Raduprv
Try to use Alpha Testing


I tried glEnable(GL_ALPHA_TEST);glAlphaFunc(GL_GREATER,0.0f);
before my rendering and alas it had no effect.

It doesn''t make sense to me why this isn''t working.

Maybe I am stupid, but where do you call glTexImage2D()?
quote:Original post by Raduprv
Maybe I am stupid, but where do you call glTexImage2D()?


I call gluBuild2DMipMaps in place of it.

I am not sure what that function does exactly. Anyway, you might want to icnrease the Alpha Test value from 0.0 to 0.1
0.0 lets everything pass.
gluBuild2DMipmaps does exactly what it sounds like. Builds mip maps as well as a normal texture.

This topic is closed to new replies.

Advertisement