Paletted Textures

Started by
9 comments, last by Sik_the_hedgehog 10 years, 8 months ago

I haven't seen paletted textures being used at all in shaders anymore. I think it'd be much faster too by using an 8-bit index per texel to a 1D texture containing 32-bit color data. If alpha texels have quite a lot of variance, just the RGB values could be stored in the 1D texture, and the alpha channel would be stored in a separate channel --since it's usually stored in 1 byte of data anyway bringing alpha textures to 16-bit textures with varying transparency (unlike 16-bit color textures), etc.

This is assuming that only 256 distinct colors are being used in the palette which would only make the 1D texture 256 pixels in total. The benefits, however, would be:

-Much less data needed per texture

-Much less memory consumption because the paletted texture

-Much less data to upload to the GPU on texture swaps

-Faster texture reads in the shader since there's less data to scan through (I'm hoping, I'm not familiar on how GPUs handle texture data)

It would require a little more effort to read these textures, and more instructions per shader per lookup, but I don't think it would be a big deal. but the largest benefit --less memory consumption. Mipmaps would probably have to be generated offline, but I think there are quite a few benefits here.

I'd like to make a game where the characters have really fluid animations in OpenGL ES 2.0. Animated vector graphics don't seem possible at all unless 3D modelers get involved. It's too bad ToonBoom Studio has the level of animation I'd like it to be, but it's exported as rasterized sprite sheets.

Advertisement

Why would you bother with with indexed textures when we already have DXTn, BC7 and (in the future hopefully) ASTC? These formats will give you better image quality and better compression ratios.

Aren't those lossy compressions though? Sometimes, very lossy.



Aren't those lossy compressions though? Sometimes, very lossy.

Converting a 24-bit texture to 8-bit indexed is extremely lossy. BC7 and ASTC have pretty decent quality, and even DXTn has better image quality than an 8-bit indexed image. If they didn't, there would be no point in having them and everyone would be using indexed textures. The way those formats work is essentially based on indexing with a palette, except each block of pixels (4x4 in DXTn) gets it's own color palette. The other advantage is that GPUs have dedicated hardware for handling them, so their performance will be greater than manually looking up colors in your shader. Not to mention, that if you were to manually implement indexed textures in your shaders, you would also have to manually implement texture filtering and mip-map generation, since hardware bi/tri-linear filtering is going to try and linearly interpolate between index values, which will not work.

 

Why would you bother with with indexed textures when we already have DXTn, BC7 and (in the future hopefully) ASTC? These formats will give you better image quality and better compression ratios.

 
And worse palette animation.

Performance concerns are silly (if one has so little memory and so many textures that degrading them to 8-bit colour is acceptable, using high-performance compressed formats is also acceptable), but the indirection of using a palette allows an enormous variety of tricks with carefully drawn pixel art (for which mipmapping and interpolation are a very bad idea).

Omae Wa Mou Shindeiru

For 2D images with a low shade count palettes can easily look better than those compression methods (though this heavily depends on the case). Also there's the issue because of the silhouettes: the compression formats that support translucency either do it by increasing the size or by reducing color precision even more.

The problem with the look-up idea is that it breaks texture filtering... This means you have to do it manually by reading the texture multiple times instead of just reading once, because otherwise you'll end up blending the indices. I think this is probably my biggest put off for attempting to use this idea (even if in practice it may not be as bad as I'm making it out to be, since usually you wouldn't be doing some of the really expensive operations 3D games do).

In practice I imagine this is one of those "try and see what happens" situations.

Don't pay much attention to "the hedgehog" in my nick, it's just because "Sik" was already taken =/ By the way, Sik is pronounced like seek, not like sick.

 

Why would you bother with with indexed textures when we already have DXTn, BC7 and (in the future hopefully) ASTC? These formats will give you better image quality and better compression ratios.

 
And worse palette animation.

Performance concerns are silly (if one has so little memory and so many textures that degrading them to 8-bit colour is acceptable, using high-performance compressed formats is also acceptable), but the indirection of using a palette allows an enormous variety of tricks with carefully drawn pixel art (for which mipmapping and interpolation are a very bad idea).

You do bring up an interesting point in that it's not entirely clear what the OP is trying to achieve with these textures. He only talks about performance and memory concerns, so I'm not sure what he's talking about in his last paragraph.

That said, I think palette-swap animation is probably not what anyone wants. It's certainly cool in 8/16 bit games with "extreme" (by today's standards) memory and rendering limitations as well as other idiosyncrasies, but it's not clear that there's any incentive to do it today.

To be honest the only time I've ever seen palette-swap animation combined with OpenGL is in that 3D Maze screensaver for Windows 95, on those weird animated fractally textures you could choose in the settings, and even then I'm only guessing that's what was going on.

-~-The Cow of Darkness-~-

For 2D images with a low shade count palettes can easily look better than those compression methods (though this heavily depends on the case). Also there's the issue because of the silhouettes: the compression formats that support translucency either do it by increasing the size or by reducing color precision even more.

The problem with the look-up idea is that it breaks texture filtering... This means you have to do it manually by reading the texture multiple times instead of just reading once, because otherwise you'll end up blending the indices. I think this is probably my biggest put off for attempting to use this idea (even if in practice it may not be as bad as I'm making it out to be, since usually you wouldn't be doing some of the really expensive operations 3D games do).

In practice I imagine this is one of those "try and see what happens" situations.

Depending on the OP's requirements, might it be worth storing the textures in a paletted format (even like PNG?) and then sending them to the GPU as RGB data? It seems very likely that you'd not get much benefit from trying to process the indexed data in real-time on the GPU, but if you're mainly trying to reduce the storage requirements of the game (which seems likely if the OP is using OpenGL ES) then this seems like it might have some value (and require relatively minimal effort to implement)

-~-The Cow of Darkness-~-

For 2D images with a low shade count palettes can easily look better than those compression methods (though this heavily depends on the case). Also there's the issue because of the silhouettes: the compression formats that support translucency either do it by increasing the size or by reducing color precision even more.

The problem with the look-up idea is that it breaks texture filtering... This means you have to do it manually by reading the texture multiple times instead of just reading once, because otherwise you'll end up blending the indices. I think this is probably my biggest put off for attempting to use this idea (even if in practice it may not be as bad as I'm making it out to be, since usually you wouldn't be doing some of the really expensive operations 3D games do).

In practice I imagine this is one of those "try and see what happens" situations.

Depending on the OP's requirements, might it be worth storing the textures in a paletted format (even like PNG?) and then sending them to the GPU as RGB data? It seems very likely that you'd not get much benefit from trying to process the indexed data in real-time on the GPU, but if you're mainly trying to reduce the storage requirements of the game (which seems likely if the OP is using OpenGL ES) then this seems like it might have some value (and require relatively minimal effort to implement)

It really depends on the type of game and art assets. 8-bit color textures is likely only going to look acceptable in a 8/16-bit era style game, and of course, if your game is 8/16-bit styled, then why would you have so much texture data to begin with that it would warrant the need for so many space saving measures? Chances are something like JPEG compression would give you better disk space utilization and better looking textures in most cases. If you really wanted a crisp looking retro style game, you could look into something like SVG, which would be way better than 8-bit PNG. smile.png

It wouldn't be faster because it requires a dependent texture read. You mentioned GL ES so here's Apple's advice (source: http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html#//apple_ref/doc/uid/TP40008793-CH7-SW3):

Dynamic texture lookups, also known as dependent texture reads, occur when a fragment shader computes texture coordinates rather than using the unmodified texture coordinates passed into the shader. Although the shader language supports this, dependent texture reads can delay loading of texel data, reducing performance. When a shader has no dependent texture reads, the graphics hardware may prefetch texel data before the shader executes, hiding some of the latency of accessing memory.

Memory savings are moot - are you really that short on video memory anyway? Maybe on mobile devices (I note that you mentioned GL ES) but there are other strategies to reduce video memory usage - compression or just flat-out reducing your texture sizes (who needs a 1024x1024 texture for a mobile device? Maybe in a few years time - by which time one may expect that video memory sizes will have increased too - but not today).

Texture upload performance could go either way. A standard texture change doesn't upload new data from GPU to CPU; it should be all resident on the GPU to begin with (for devices with shared/unified memory it won't matter one bit). For dynamic texture uploads, the required synchronization is going to kill you far more than the amount of data used.

On today's hardware texture reads are expensive operations - that's why you want to keep them to a minimum. And one's natural inclination to save memory must be kept in check because doing so can often be at the expense of performance, and often in quite unintuitive ways - the rules that you'd apply to CPUs just don't always work well on GPUs.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement