Sign in to follow this  
DarkCybo1

Alpha transparency??

Recommended Posts

How can I draw textures where parts of the texture is transparent, and other parts are opaque? When I draw a texture like this in my program, the parts that are supposed to be transparent appear as white. Included code would also be a great help.

Share this post


Link to post
Share on other sites
In PSP 7.x, you use a mask. There are different ways to do it.

You can add a new mask from different images, or using different methods to generate them based off the image you already have. (Or you can paint by hand), then when you are done, save your mask to the alpha channel (Only 1).

Then you can delete your mask, because it's been exported to the alpha channel, and it's no longer needed, and tell the program NOT to merge the mask with the image layer. Then save as .tga. (if you leave the mask it will turn all masked pixels white)

Share this post


Link to post
Share on other sites
Quote:
Original post by Vampyre_Dark
In PSP 7.x, you use a mask. There are different ways to do it.

You can add a new mask from different images, or using different methods to generate them based off the image you already have. (Or you can paint by hand), then when you are done, save your mask to the alpha channel (Only 1).

Then you can delete your mask, because it's been exported to the alpha channel, and it's no longer needed, and tell the program NOT to merge the mask with the image layer. Then save as .tga. (if you leave the mask it will turn all masked pixels white)


Are you saying do this in OpenGl or in a paint program, because I am sick of loading a image and a mask all the time and I dont have Photoshop to put in the transparency layer.

Share this post


Link to post
Share on other sites
Quote:
Original post by DarkCybo1
Wow, having to add the alpha mask for every image is annoying. Oh well...
Thanks for the help though, I got it to work!
It takes less then 2 seconds, auto generate a mask from the image data, and save it out to the file's alpha channel. Note that the mask is not the alpha channel, it's a mask within the program only. You have to manually export the alpha channel and then delete the mask. If you don't delete the mask, it will get merged with the image layer when you save, causing all those pixels to go white (which you may not want).
Quote:
Original post by SirSapo
Are you saying do this in OpenGl or in a paint program, because I am sick of loading a image and a mask all the time and I dont have Photoshop to put in the transparency layer.
Quote:
Original post by Vampyre_Dark
In PSP 7.x
Use GIMP?

Share this post


Link to post
Share on other sites
It's pretty simple.



Notice the outside of each sprite: it's all pinkish-purple (0xFF00FF). You can pick any color you want, but make sure it's something that isn't used and won't be used elsewhere in your sprites. 0xFF00FF is a good one, so is lime green (0x00FF00). You can use white or black, just make sure you keep in mind not to use those while drawing (ie, if you have to use black in your sprite, use 0x080808 instead of 0x0000000.)

When loading, make the texture color format GL_RGBA. If you encounter a pixel set to your mask color (say, 0xFF00FF) write 0x00 to the alpha channel (AARRGGBB), otherwise write 0xFF.

When drawing, make sure alpha testing is enabled and that you've set an alpha function (glAlphaFunc(GL_LESS, 0.05f); is what I use.) Your sprite will automatically be masked. ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by RuneLancer

If you encounter a pixel set to your mask color (say, 0xFF00FF) write 0x00 to the alpha channel (AARRGGBB), otherwise write 0xFF.


I'm a beginner at this..how would I do this part?

Share this post


Link to post
Share on other sites
Quote:
Original post by DarkCybo1
I'm a beginner at this..how would I do this part?


I use NeHe's IPicture code to load my OpenGL textures.


bool LoadTexture( std::string fileName, GLuint &texID, GLint R, GLint G, GLint B )
{
HDC hdcTemp; // The DC To Hold Our Bitmap
HBITMAP hbmpTemp; // Holds The Bitmap Temporarily
IPicture *pPicture; // IPicture Interface
OLECHAR wszPath[MAX_PATH+1]; // Full Path To Picture (WCHAR)
char szPath[MAX_PATH+1]; // Full Path To Picture
long lWidth; // Width In Logical Units
long lHeight; // Height In Logical Units
long lWidthPixels; // Width In Pixels
long lHeightPixels; // Height In Pixels
GLint glMaxTexDim ; // Holds Maximum Texture Size

if (strstr(fileName.c_str(), "http://")) // If PathName Contains http:// Then...
{
strcpy(szPath, fileName.c_str()); // Append The PathName To szPath
}
else // Otherwise... We Are Loading From A File
{
GetCurrentDirectory(MAX_PATH, szPath); // Get Our Working Directory
strcat(szPath, "\\"); // Append "\" After The Working Directory
strcat(szPath, fileName.c_str()); // Append The PathName
}

MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); // Convert From ASCII To Unicode
HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture);

if(FAILED(hr)) // If Loading Failed
return FALSE; // Return False

hdcTemp = CreateCompatibleDC(GetDC(0)); // Create The Windows Compatible Device Context
if(!hdcTemp) // Did Creation Fail?
{
pPicture->Release(); // Decrements IPicture Reference Count
return FALSE; // Return False (Failure)
}

glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); // Get Maximum Texture Size Supported

pPicture->get_Width(&lWidth); // Get IPicture Width (Convert To Pixels)
lWidthPixels = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
pPicture->get_Height(&lHeight); // Get IPicture Height (Convert To Pixels)
lHeightPixels = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);

// Resize Image To Closest Power Of Two
if (lWidthPixels <= glMaxTexDim) // Is Image Width Less Than Or Equal To Cards Limit
lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f);
else // Otherwise Set Width To "Max Power Of Two" That The Card Can Handle
lWidthPixels = glMaxTexDim;

if (lHeightPixels <= glMaxTexDim) // Is Image Height Greater Than Cards Limit
lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
else // Otherwise Set Height To "Max Power Of Two" That The Card Can Handle
lHeightPixels = glMaxTexDim;

// Create A Temporary Bitmap
BITMAPINFO bi = {0}; // The Type Of Bitmap We Request
DWORD *pBits = 0; // Pointer To The Bitmap Bits

bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // Set Structure Size
bi.bmiHeader.biBitCount = 32; // 32 Bit
bi.bmiHeader.biWidth = lWidthPixels; // Power Of Two Width
bi.bmiHeader.biHeight = lHeightPixels; // Make Image Top Up (Positive Y-Axis)
bi.bmiHeader.biCompression = BI_RGB; // RGB Encoding
bi.bmiHeader.biPlanes = 1; // 1 Bitplane

// Creating A Bitmap This Way Allows Us To Specify Color Depth And Gives Us Imediate Access To The Bits
hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);

if(!hbmpTemp) // Did Creation Fail?
{
DeleteDC(hdcTemp); // Delete The Device Context
pPicture->Release(); // Decrements IPicture Reference Count
return FALSE; // Return False (Failure)
}

SelectObject(hdcTemp, hbmpTemp); // Select Handle To Our Temp DC And Our Temp Bitmap Object

// Render The IPicture On To The Bitmap
pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);

// Convert From BGR To RGB Format And Add An Alpha Value Of 255
for(long i = 0; i < lWidthPixels * lHeightPixels; i++) // Loop Through All Of The Pixels
{
// Grab The Current Pixel
BYTE* pPixel = (BYTE*)(&pBits[i]);
// Store 1st Color In Temp Variable (Blue)
BYTE temp = pPixel[0];
// Move Red Value To Correct Position (1st)
pPixel[0] = pPixel[2];
// Move Temp Value To Correct Blue Position (3rd)
pPixel[2] = temp;

// This Will Make Any Pixels Completely Transparent if we want to
if( R >= 0 && G >= 0 && B >= 0 )
{
// Is Pixel the color we want to set as colorkey
if ( ( pPixel[0] == R ) && ( pPixel[1] == G ) && ( pPixel[2] == B ) )
{
// Set The Alpha Value To 0, transparent
pPixel[3] = 0;
}
else
{
// Set The Alpha Value To 255, opaque
pPixel[3] = 255;
}
}
else
{
// Set The Alpha Value To 255, opaque
pPixel[3] = 255;
}
}

// Create The Texture
glGenTextures( 1, &texID );

// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texID); // Bind To The Texture ID
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // (Modify This For The Type Of Filtering You Want)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // (Modify This For The Type Of Filtering You Want)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits); // (Modify This If You Want Mipmaps)

DeleteObject(hbmpTemp); // Delete The Object
DeleteDC(hdcTemp); // Delete The Device Context

pPicture->Release(); // Decrements IPicture Reference Count

return TRUE; // Return True (All Good)
}





I made a few modifications so I can use any color I want for the color key. In this case, if you take a look at the segment starting with the for(long i = 0; i < lWidthPixels * lHeightPixels; i++). In there, the pixels are checked one by one and if they match the color we want, then the alpha is set to 0, which is transparent. You could also extend this code to make it allow for multiple color keys as well if you wanted to.

Share this post


Link to post
Share on other sites
Quote:
Original post by DarkCybo1
Interesting. Is it possible to grab my image's pixels using OpenGL API functions?


You could read and write to a texture, but why would you want to do that to acheive transparency?

My game uses a custom image format, so I need a custom texture loader. What I do is pretty simple: I reserve memory with new to hold my image (height x width x 4 (32 bits)) and read in the format. To populate the array, I have a pointer to the start of it. Every decompressed pixel, I write the R (array[0]), G (array[1]), and B (array[2]) values to my array. The array is initialised to 0x00 so the alpha channel (array[3]) doesn't have to be written to. Then I move my pointer ahead by 4 (array += 4;) and continue.

However, if I hit a pixel that has the color 0xFF00FF, I write 0xFF to the alpha channel (array[3] = 0xFF;) and move to the next pixel (array += 4;).

(Actually that's not entirely true; I can often memset large chunks instead of going pixel per pixel, but that's not the point here and it just makes it more complicated. :) )

Once the entire image is in my little temporary buffer, I just create a texture from it.

glTexImage2D(GL_TEXTURE_2D, 0, 4, myWidth, myHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, array);

That's basically all there is to it. Once this is done, every time the texture is used, so long as you've set alpha testing it will not render the transparent pixels on its own. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this