gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > Ahh the dreaded sprite transparency

#19700 - CyberSlag5k - Fri Apr 23, 2004 6:03 pm

Ok, I know there have been a ton of posts on the subject (and I do believe I've read them all), but something still isn't clicking. Let me lay down what (I think) I know:

Palette index 0 is always transparent. So, if you want a cetain area of your sprite to be transparent, you set it to palette index 0. Sound good?

Ok, so my palette looks like this:

const u16 palettePalette[] = {
0x0000 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFF, 0x0842, 0x0842,......};

So index 0 is 0x0000. Now I as I understand it, this does not mean that all instances of the color 0x0000 (black) will be transparent. Good, I wouldn't want them to be.

Now, I saw this post on gamedev:

Quote:

The origin of those color values is this:

0x1F1F:

1F is hex for 31. That means that the pixel is palette index #31. The GBA will look through the palette array for index 31, and use whatever color is there. You'll notice that there are two 1Fs, that's because each number stores two pixels. If you ever try to write your own converter, its important to know that they're reversed. If you had the number: 0x1FFF, the FIRST pixel is FF, or color 255. The SECOND is 1F, or 31.


Sounds good to me, although I've never seen anything similar anywhere else. Anyway, if this is the case, all I should have to do is replace all the 0xFFFF's (the color white) in my sprite (not the palette) to 0x0000 (index 0) all the white elements turn transparent. Is this right? Somehow this doesn't seem right to me. I'm quite confused.
_________________
When you find yourself in the company of a halfling and an ill-tempered Dragon, remember, you do not have to outrun the Dragon...

#19704 - niltsair - Fri Apr 23, 2004 6:48 pm

Ok, here's a plain explanation.

You have a 8x8 sprite :
Code:
Pixels :
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0A, 0x04, 0x0B, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,

Palette
Pal0 : 0x1235, Pal1 : 0x1111, Pal2 : 0x2222, Pal3 : 0x3333,
Pal4 : 0x4444, Pal5 : 0x5555, Pal6 : 0x6666, Pal7 : 0x7777,
Pal8 : 0x8888, Pal9 : 0x1111, PalA : 0x4444, PalB : 0xFFFF,
...
Now, every pixels that points to Pal0 won't be seen while any other one will just take the colors of it's entry in the palette. (pixel 0x04 would display the color 0x4444).

I think what got you confused is that fact that the pixels are stored 2 at a time(video memory can only be accessed in 16/32bits) , so they might look like this in a header
Code:
0x0000, 0x0100, 0x0000, 0x0000,
0x0000, 0x0200, 0x0000, 0x0000,
0x0000, 0x0300, 0x0000, 0x0000,
0x0000, 0x040A, 0x000B, 0x0000,
0x0000, 0x0500, 0x0000, 0x0000,
0x0000, 0x0600, 0x0000, 0x0000,
0x0000, 0x0700, 0x0000, 0x0000,
0x0000, 0x0800, 0x0000, 0x0000,
But they do not represent the palette color, just which color to pick in the palette.
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)


Last edited by niltsair on Fri Apr 23, 2004 6:51 pm; edited 1 time in total

#19705 - sajiimori - Fri Apr 23, 2004 6:50 pm

There's nothing unusual about the quote you posted. It fits nicely with your previous description, at least for 8-bit images. Without context, I would guess that the original poster was talking about pairs of pixels because you can only plot pairs in mode 4.
Quote:

Anyway, if this is the case, all I should have to do is replace all the 0xFFFF's (the color white) in my sprite (not the palette) to 0x0000 (index 0) all the white elements turn transparent.

Palettized graphics (such as GBA sprite data) have 2 components: the palette and the pixel data.

The palette is an array of colors encoded in some format, which is 15-bit BGR in the case of GBA. Colors are rounded up to the nearest byte (to 16 bits), and the highest bit is unused. Because of that unused bit, the values 0x8FFF and 0xFFFF both represent white.

The pixel data is an array of indexes into the palette. Their size depends on how many palette entries there are. To select one of 16 colors, you need 4 bits per pixel (because there are 16 possible combinations of 4 bits). For 256 colors, you need 8 bits.

So, your sprite pixel data does not contain "the color white". It just contains indexes into the palette. If your sprite data contains the bytes 0xFFFF somewhere, the meaning depends on whether the sprite is 16 color or 256 color. If it's 16 color, 0xFFFF is 4 palette indexes, all of which are 15 (because the hex digit F is 15). If it's 256 color, 0xFFFF is 2 palette indexes, both of which are 255 (because the hex number FF is 255).

Similarly, 0x0000 is a 16 bit number, and GBA's palette indexes are either 4 bits or 8 bits, so that number couldn't possibly refer to index 0. (One could argue that 0=0 no matter how many bits are involved, but in terms of sequences of bits in memory, 0x0000 describes a sequence of 16 bits.)

#19712 - CyberSlag5k - Fri Apr 23, 2004 7:52 pm

Quote:

Similarly, 0x0000 is a 16 bit number, and GBA's palette indexes are either 4 bits or 8 bits, so that number couldn't possibly refer to index 0. (One could argue that 0=0 no matter how many bits are involved, but in terms of sequences of bits in memory, 0x0000 describes a sequence of 16 bits.)


So what would I use to represent index 0? Just 0x0?
_________________
When you find yourself in the company of a halfling and an ill-tempered Dragon, remember, you do not have to outrun the Dragon...

#19713 - tepples - Fri Apr 23, 2004 8:02 pm

0x0000 means either four pixels in a row with index 0 (in 16-color mode) or two pixels in a row with index 0 (in 256 color mode). If, say, you are in 16-color mode and want to represent three transparent pixels and one opaque pixel of color 7, use 0x7000. (GBA reads pixels from right to left within a word length.)
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#19715 - niltsair - Fri Apr 23, 2004 8:05 pm

It depends,

Suppose you have 4 consecutive pixels having those values:
Pixel 0: Color Index 0
Pixel 1: Color Index 3
Pixel 2: Color Index 8
Pixel 3: Color Index 9

In 256 colors (8 Bits per color), it would be
0x0300, 0x0908

In 16 colors (4bits per color), it would be
0x9830

The thing is, you don't have to store those numbers in 16bits value, you just need to Write them in 16bits or 32bits chunk. Meaning that it would be fine to store the array as 8bits values, but you write them by 16bits chunk by casting it :
Code:

u8 SpriteImg[] ALIGN4 = {0x00, 0x03, 0x07, 0x09, ... };
//Only 2 copy needed, since we transfer 2Pixels at a time
PtrSpriteMem[0] = (u16*)SpriteImg[0];
PtrSpriteMem[1] = (u16*)SpriteImg[1];
Notice the ALIGN4, important. It tells the linker to locate the data at a 32bits bondaries, which is needed if you want to DMA the data in 16/32bits chunk (ALIGN2 for only 16bits).
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)

#19719 - CyberSlag5k - Fri Apr 23, 2004 8:33 pm

Alright. I think I'm following.

I've realized partly what I've been doing wrong is I'm looking at the wrong .h file. I forgot I swtiched from pcx2sprite to gifs2sprites. The file I'm really working with looks like this:

Code:

const u16 palette[25]=
{
RGB( 0, 0, 0),RGB(31,31,31),RGB(31, 2, 2),RGB( 0, 0, 0),RGB(31,30,17),
RGB(28,28,28),RGB(24,24,24),RGB( 7,17,25),RGB( 3, 0, 0),RGB( 3, 3, 3),
RGB( 4,11,18),RGB( 6, 3, 3),RGB( 7, 0, 0),RGB(31, 3, 3),RGB(13,13,13),
RGB(31, 4, 4),RGB( 2, 2, 2),RGB(25,25,25),RGB(27,27,27),RGB(17,17,17),
RGB(26,26,26),RGB( 3, 4, 5),RGB( 3, 5, 6),RGB( 4, 5, 7),RGB( 3, 4, 4)
};

/* soldier1.gif (64x64x256) */
const u16 obj0[2048]={
0x0101,   0x0101,   0x0101,   0x0101,
0x0101,   0x0101,   0x0101,   0x0101,
0x0101,   0x0101,   0x0101,   0x0101,
0x0101,   0x0101,   0x0101,   0x0101,
0x0101,   0x0101,   0x0101,   0x0101,
0x0101,   0x0101,   0x0101,   0x0101,
0x0101,   0x0101,   0x0101,   0x0101,
0x0101,   0x0101,   0x0101,   0x0101,
0x0101,   0x0101,   0x0101,   0x0301,
0x0101,   0x0101,   0x0501,   0x030e,
........


SO! the 0x0101 in the top left corner says that the obj0[0] will be the color white (as palette[1] is (31, 31, 31) and therefore white). Riiiight?

So,if I wanted to change everything white on the sprite to be transparent I would search for all the 01's and make them 00's. Riiiiiight?

I think I'm getting this but I tried doing what I said up there, changed all the 01's to 00's and nothing changed. So, just out of curiosity I changed them all into 0C's (the 12th index, some sort of red as it would seem) and still nothing changed! I've recompiled, of course, each time so you'd think something would change. Riiiiight?

Am I still missing something?
_________________
When you find yourself in the company of a halfling and an ill-tempered Dragon, remember, you do not have to outrun the Dragon...

#19720 - niltsair - Fri Apr 23, 2004 8:44 pm

Yes, changing the 0x0101 to 0x0000 would make the sprite transparent for those pixels. For example :
/* soldier1.gif (64x64x256) */
const u16 obj0[2048]={
0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001,
...

Would make every 2 pixels transparent for the first2 rows of the first Sprite Tile.
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)


Last edited by niltsair on Fri Apr 23, 2004 9:12 pm; edited 1 time in total

#19721 - sajiimori - Fri Apr 23, 2004 8:44 pm

Did you physically replace them in the header file by hand, or did you try to have your code do it? The array is const, so you can't modify it at runtime. Otherwise, try cleaning your project and recompiling, then make sure you're drawing what you think you're drawing, because obviously changing those numbers should change the image.

#19722 - CyberSlag5k - Fri Apr 23, 2004 9:03 pm

Ahh, I got it going now. I had a compile error I hadn't noticed and it wasn't rebuilding the file.

Thanks for everyone's help! I feel I have a complete understanding of how the sprite and palette interact now.
_________________
When you find yourself in the company of a halfling and an ill-tempered Dragon, remember, you do not have to outrun the Dragon...