This translucency code is killing me
So I want to add the ability to draw sprites and tiles translucent. So rather than coming up with my own method, I thought I would just use BlitPixie, since BlitPixie rocks. The only real problem I saw was that my game uses GWorlds (ie, I'm not using SpriteWorld) and BlitPixie doesn't. So I created my own procedure to get the data I needed out of the GWorlds and then call the BlitPixie translucency code. And it almost works. When I copy an entire GWorld to another GWorld it works just fine. But when I try to copy just part of a GWorld to another it fails and draws nothing. I've been fiddling with the code for the past day and I just can't figure out what I'm missing. So if anybody can point out what I'm missing I'd be most appreciative.
Code:
void BlitTranslucent16(GWorldPtr srcGW, GWorldPtr destGW, Rect srcRect, Rect dstRect, unsigned short transLevel)
{
unsigned short *src;
unsigned short *dst;
PixMapHandle srcPixMapHandle = GetGWorldPixMap(srcGW);
PixMapHandle dstPixMapHandle = GetGWorldPixMap(destGW);
unsigned long srcRowBytes = (*srcPixMapHandle)->rowBytes & 0x3FFF;
unsigned long dstRowBytes = (*dstPixMapHandle)->rowBytes & 0x3FFF;
UInt16 *srcBaseAddr = (UInt16*)GetPixBaseAddr(srcPixMapHandle);
UInt16 *dstBaseAddr = (UInt16*)GetPixBaseAddr(dstPixMapHandle);
unsigned long source, dest;
unsigned short alpha;
short i, j;
short width, height;
LockPixels(srcPixMapHandle);
LockPixels(dstPixMapHandle);
alpha = ((transLevel >> 8) & 0xFF);
height = srcRect.bottom - srcRect.top;
width = srcRect.right - srcRect.left;
src = ((UInt16*)(srcBaseAddr + (srcRowBytes * srcRect.top) + (srcRect.left << 1)));
dst = ((UInt16*)(dstBaseAddr + (dstRowBytes * dstRect.top) + (dstRect.left << 1)));
srcRowBytes -= (unsigned long)(width << 1);
dstRowBytes -= (unsigned long)(width << 1);
for(j = 0; j < height; j++)
{
for(i = 0; i < width; i++)
{
source = *src++;
dest = *dst;
if(source != 0x0000) // Don't draw black
BLEND_PIXELS_16( source, dest, alpha );
*dst++ = dest;
}
src = (unsigned short *)((char *)src + srcRowBytes);
dst = (unsigned short *)((char *)dst + dstRowBytes);
}
UnlockPixels(dstPixMapHandle);
UnlockPixels(srcPixMapHandle);
}
well, apart from the BLEND_PIXELS_16(...) part, the code sure seems to be working, make sure you actually set "dest"
I see nothing wrong with the code, but I suggest not accessing memory when you don't have to. Instead of reading dest in and then writing dest even when the pixel in transparent, try this:
Code:
for(i = 0; i < width; i++)
{
source = *src++;
if(source != 0x0000) // Don't draw black
{
dest = *dst;
BLEND_PIXELS_16( source, dest, alpha );
*dst = dest;
}
*dst++;
}
So here's the working code:
A bunch of little changes (made mostly for aesthetic reasons, none of them fixed the problem). What did fix it? Changing these two lines from this:
To this:
It's days like these that I hate programming.
Code:
void BlitTranslucent16(GWorldPtr srcGW, GWorldPtr destGW, Rect srcRect, Rect dstRect, unsigned short transLevel)
{
unsigned short *src = 0;
unsigned short *dst = 0;
unsigned short *srcRowStart = 0;
unsigned short *dstRowStart = 0;
PixMapHandle srcPixMapHandle = GetGWorldPixMap(srcGW);
PixMapHandle dstPixMapHandle = GetGWorldPixMap(destGW);
unsigned long srcRowBytes = (*srcPixMapHandle)->rowBytes & 0x3FFF;
unsigned long dstRowBytes = (*dstPixMapHandle)->rowBytes & 0x3FFF;
UInt8 *srcBaseAddr = (UInt8*)GetPixBaseAddr(srcPixMapHandle);
UInt8 *dstBaseAddr = (UInt8*)GetPixBaseAddr(dstPixMapHandle);
unsigned long source, dest;
unsigned short alpha;
short i, j;
short width, height;
LockPixels(srcPixMapHandle);
LockPixels(dstPixMapHandle);
ForeColor(blackColor);
BackColor(whiteColor);
alpha = ((transLevel >> 8) & 0xFF);
height = srcRect.bottom - srcRect.top;
width = srcRect.right - srcRect.left;
srcRowStart = ((UInt16*)(srcBaseAddr + (srcRowBytes * srcRect.top) + (srcRect.left << 1)));
dstRowStart = ((UInt16*)(dstBaseAddr + (dstRowBytes * dstRect.top) + (dstRect.left << 1)));
src = srcRowStart;
dst = dstRowStart;
for(j = 0; j < height; j++)
{
src = srcRowStart;
dst = dstRowStart;
for(i = 0; i < width; i++)
{
source = *src;
if(source != 0x0000)
{
dest = *dst;
BLEND_PIXELS_16( source, dest, alpha );
*dst = dest;
}
*src++;
*dst++;
}
srcRowStart = (unsigned short *)((char *)srcRowStart + srcRowBytes);
dstRowStart = (unsigned short *)((char *)dstRowStart + dstRowBytes);
}
UnlockPixels(dstPixMapHandle);
UnlockPixels(srcPixMapHandle);
}A bunch of little changes (made mostly for aesthetic reasons, none of them fixed the problem). What did fix it? Changing these two lines from this:
Code:
UInt16 *srcBaseAddr = (UInt16*)GetPixBaseAddr(srcPixMapHandle);
UInt16 *dstBaseAddr = (UInt16*)GetPixBaseAddr(dstPixMapHandle);To this:
Code:
UInt8 *srcBaseAddr = (UInt8*)GetPixBaseAddr(srcPixMapHandle);
UInt8 *dstBaseAddr = (UInt8*)GetPixBaseAddr(dstPixMapHandle);It's days like these that I hate programming.
ofcourse i.e:
src = (UInt16*)(((UInt16*)srcBaseAddr) + (srcRowBytes * srcRect.top) + (srcRect.left << 1));
is just not the same as:
src = (UInt16*)(((UInt8*)srcBaseAddr) + (srcRowBytes * srcRect.top) + (srcRect.left << 1));
must have not noticed that.
if you want to make it look more aesthetic and avoid such problems in the first place you should write something like:
src = (UInt16*)(((UInt16*)srcBaseAddr) + (srcRowBytes * srcRect.top) + (srcRect.left << 1));
is just not the same as:
src = (UInt16*)(((UInt8*)srcBaseAddr) + (srcRowBytes * srcRect.top) + (srcRect.left << 1));
must have not noticed that.
if you want to make it look more aesthetic and avoid such problems in the first place you should write something like:
Code:
void BlitTranslucent16(GWorldPtr srcGW, GWorldPtr destGW, Rect srcRect, Rect dstRect, unsigned short transLevel)
{
UInt16 *src;
UInt16 *dst;
PixMapHandle srcPixMapHandle = GetGWorldPixMap(srcGW);
PixMapHandle dstPixMapHandle = GetGWorldPixMap(destGW);
UInt32 srcRowWidth = ((*srcPixMapHandle)->rowBytes & 0x3FFF)>>1;
UInt32 dstRowWidth = ((*dstPixMapHandle)->rowBytes & 0x3FFF)>>1;
UInt16 *srcBaseAddr = (UInt16*)GetPixBaseAddr(srcPixMapHandle);
UInt16 *dstBaseAddr = (UInt16*)GetPixBaseAddr(dstPixMapHandle);
UInt16 alpha,source;
UInt16 i,j;
UInt16 width, height;
LockPixels(srcPixMapHandle);
LockPixels(dstPixMapHandle);
alpha = ((transLevel >> 8) & 0xFF);
height = srcRect.bottom - srcRect.top;
width = srcRect.right - srcRect.left;
src = srcBaseAddr + srcRowWidth * srcRect.top + srcRect.left;
dst = dstBaseAddr + dstRowWidth * dstRect.top + dstRect.left;
srcRowWidth -= width;
dstRowWidth -= width;
for(j = 0; j < height; j++)
{
for(i = 0; i < width; i++)
{
source = *src++;
if(source) // Don't draw black
BLEND_PIXELS_16(source,*dst,alpha);
dst++;
}
src += srcRowWidth;
dst += dstRowWidth;
}
UnlockPixels(dstPixMapHandle);
UnlockPixels(srcPixMapHandle);
}
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Killing the char on the end of a char array | wyrmmage | 3 | 2,960 |
Dec 4, 2006 08:55 PM Last Post: wyrmmage |
|
| InvalWindowRect() is killing me!! | loki74 | 2 | 2,092 |
Jun 29, 2006 03:29 PM Last Post: loki74 |
|

