Swapping palettes for each texture
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
Swapping palettes for each texture
I've come to the conclusion that 32-bit textures take up way too much RAM, so I wanted to try a different approach.
Let's say I had an 8-bit PCX file, which, being a PCX file, would be a completely 8-bit image. Now, with my old implementation, I would upsample the texture to a 32-bit image, then use that to render. However, I see now the amount of RAM that wastes.. Can somebody give me an example of swapping the palette whenever a texture is to be rendered?
Thanks :)
Let's say I had an 8-bit PCX file, which, being a PCX file, would be a completely 8-bit image. Now, with my old implementation, I would upsample the texture to a 32-bit image, then use that to render. However, I see now the amount of RAM that wastes.. Can somebody give me an example of swapping the palette whenever a texture is to be rendered?
Thanks :)
pspsdk/samples/gu/clut/
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
sceGuClutMode sets the clut mode (line 125 of the sample)
psp doesn't support 24 bbp you'll have to add an alpha channel
>Right now, my palette is stored as a pointer to a series of bytes that go as RGBRGBRGB.. etc. How would it be converted into the proper format?
you could use the GU_RGBA(r,g,b,a) macro
psp doesn't support 24 bbp you'll have to add an alpha channel
>Right now, my palette is stored as a pointer to a series of bytes that go as RGBRGBRGB.. etc. How would it be converted into the proper format?
you could use the GU_RGBA(r,g,b,a) macro
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
Okay; here's the issue.
The palette switches, sometimes, but it fails half the time, the correct palette will flash on and off every frame or so, it's really annoying. This is Quake, attempting to get Half-Life maps loading. The previous implementation I had would upsample the 8-bit textures to 32-bit textures and render them as such, but it took up far too much RAM, and now I decided to try this.
http://www.youtube.com/watch?v=32QDVXlJof4
I also put some good music on the video, so yay!
The palette switches, sometimes, but it fails half the time, the correct palette will flash on and off every frame or so, it's really annoying. This is Quake, attempting to get Half-Life maps loading. The previous implementation I had would upsample the 8-bit textures to 32-bit textures and render them as such, but it took up far too much RAM, and now I decided to try this.
http://www.youtube.com/watch?v=32QDVXlJof4
I also put some good music on the video, so yay!
Well... we see how the textures flicker, but we can't say what the reason is, since we don't know how you handle the palettes.
Do you have them in sys ram or vram?
Do you have all palettes in their own location and upload from there
or do you copy to your global palette each texture swap?
Do you set the parameters for sceGuClut* correctly?
...
Do you have them in sys ram or vram?
Do you have all palettes in their own location and upload from there
or do you copy to your global palette each texture swap?
Do you set the parameters for sceGuClut* correctly?
...
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
System RAM.Raphael wrote:Do you have them in sys ram or vram?
Yes.Raphael wrote:Do you have all palettes in their own location and upload from there
Every time I bind the texture, I swap by doing this:Raphael wrote:or do you copy to your global palette each texture swap?
Code: Select all
void VID_SetPaletteHL(unsigned char* palette)
{
ScePspRGBA8888 ALIGNED(16) d_8to24tableHL[palette_size];
// Convert the palette to PSP format.
for (ScePspRGBA8888* color = &d_8to24tableHL[0]; color < &d_8to24tableHL[palette_size]; ++color)
{
const unsigned int r = *palette++;
const unsigned int g = *palette++;
const unsigned int b = *palette++;
*color = GU_RGBA(r, g, b, 0xff);
}
// Upload the palette.
sceGuClutMode(GU_PSM_8888, 0, palette_size - 1, 0);
sceKernelDcacheWritebackRange(d_8to24tableHL, sizeof(d_8to24tableHL));
sceGuClutLoad(palette_size / 8, d_8to24tableHL);
}
Yeah.Raphael wrote:Do you set the parameters for sceGuClut* correctly?
...
EDIT:
In case you're wondering, here's me binding them:
Code: Select all
void GL_Bind (int texture_index)
{
// Which texture is it?
const gltexture_t& texture = gltextures[texture_index];
if (texture.palette)
VID_SetPaletteHL(texture.palette);
else
VID_SetPaletteTX();
// Binding the currently bound texture?
if (currenttexture == texture_index)
{
// Don't bother.
return;
}
// Remember the current texture.
currenttexture = texture_index;
// Set the texture mode.
if (texture.palette)
sceGuTexMode(GU_PSM_T8, texture.mipmaps , 0, GU_TRUE);
else
sceGuTexMode(texture.format, texture.mipmaps , 0, GU_TRUE);
if (texture.mipmaps > 0 && r_mipmaps.value > 0)
{
float slope = 0.4f;
sceGuTexSlope(slope); // the near from 0 slope is the lower (=best detailed) mipmap it uses
sceGuTexFilter(GU_LINEAR_MIPMAP_LINEAR, GU_LINEAR_MIPMAP_LINEAR);
sceGuTexLevelMode(int(r_mipmaps_func.value), r_mipmaps_bias.value);
}
else
sceGuTexFilter(texture.filter, texture.filter);
// Set the texture image.
const void* const texture_memory = texture.vram ? texture.vram : texture.ram;
sceGuTexImage(0, texture.width, texture.height, texture.width, texture_memory);
}
There you go. Not really.gotmilk065 wrote:Code: Select all
void VID_SetPaletteHL(unsigned char* palette) { ScePspRGBA8888 ALIGNED(16) d_8to24tableHL[palette_size]; // Convert the palette to PSP format. for (ScePspRGBA8888* color = &d_8to24tableHL[0]; color < &d_8to24tableHL[palette_size]; ++color) { const unsigned int r = *palette++; const unsigned int g = *palette++; const unsigned int b = *palette++; *color = GU_RGBA(r, g, b, 0xff); } // Upload the palette. sceGuClutMode(GU_PSM_8888, 0, palette_size - 1, 0); sceKernelDcacheWritebackRange(d_8to24tableHL, sizeof(d_8to24tableHL)); sceGuClutLoad(palette_size / 8, d_8to24tableHL); }
Yeah.Raphael wrote:Do you set the parameters for sceGuClut* correctly?
...
sceGuClutMode Parameter 2 is a mask parameter for the palette index read from the texture. As long as palette_size is exactly 256 this will work out perfectly well, for anything else it will fail. It doesn't really make sense to depend the index mask on the size, unless you have an T16 or T32 texture map. So just use 0xff there.
Apart from that, you should know that what you do there is gonna cause glitches obviously, as soon as you end up overwriting the stack where you place the palette before GU gets to use it (ie, the next texture is processed before GU got to render the previous one, hence ending up using the *wrong* palette data). This is because sceGu* functions are asynchronous, meaning that the pointer and it's data you give there *must* stay valid for the remainder of the whole frame (which it currently isn't, as its a local variable for that function, ie on stack).
Two solution options:
1. Use sceGuGetMemory to allocate the temporary palette in the current display list
2. allocate memory for the psp palette in your texture structure (256*4 bytes) and fill that with the right palette data on texture load time, then use that pointer (would also save you the need to convert the palette on each texture bind).
What does VID_SetPaletteTX() do exactly? Set a dummy palette? You don't have to, as GU won't use any palette information as soon as the texture format is non-paletted.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
Ooo Okay, thanks.Raphael wrote: There you go. Not really.
sceGuClutMode Parameter 2 is a mask parameter for the palette index read from the texture. As long as palette_size is exactly 256 this will work out perfectly well, for anything else it will fail. It doesn't really make sense to depend the index mask on the size, unless you have an T16 or T32 texture map. So just use 0xff there.
Useful information, mate, thanks! I think I'll take option 2. I actually was going to do that originally, but decided on this to test, and when the method I'm using now didn't work, I figured there was a problem in general, lol, so I didn't bother switching.Raphael wrote: Apart from that, you should know that what you do there is gonna cause glitches obviously, as soon as you end up overwriting the stack where you place the palette before GU gets to use it (ie, the next texture is processed before GU got to render the previous one, hence ending up using the *wrong* palette data). This is because sceGu* functions are asynchronous, meaning that the pointer and it's data you give there *must* stay valid for the remainder of the whole frame (which it currently isn't, as its a local variable for that function, ie on stack).
Two solution options:
1. Use sceGuGetMemory to allocate the temporary palette in the current display list
2. allocate memory for the psp palette in your texture structure (256*4 bytes) and fill that with the right palette data on texture load time, then use that pointer (would also save you the need to convert the palette on each texture bind).
Nah, it's to revert to the Quake palette, to retain a bit of backwards compatibility with Quake and so the textures on the viewmodels would render correctly when they use the Quake palette.Raphael wrote: What does VID_SetPaletteTX() do exactly? Set a dummy palette? You don't have to, as GU won't use any palette information as soon as the texture format is non-paletted.
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am