OpenGL ES のパレットテクスチャを作る

glGenTextures でテクスチャの番号をもらって、glBindTexture でアクティブにして、適当にパラメータを設定して、glCompressedTexImage2D で作るだけ。

GLint texture;
GLenum format;
int width;
int height;
void* buf;
int bufsize;

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
if (linear) // 線形補完するかどうか
{
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, bufsize, buf);

使えるパレットの種類は RGB888, RGBA8888, RGB565, RGBA4444, RGBA5551 の5種類で、インデックスの種類は 4bit と 8bit の2種類。
これらを組み合わせて合計10種類のフォーマットが指定できる。

GL_PALETTE4_RGB8_OES
GL_PALETTE4_RGBA8_OES
GL_PALETTE4_R5_G6_B5_OES
GL_PALETTE4_RGBA4_OES
GL_PALETTE4_RGB5_A1_OES
GL_PALETTE8_RGB8_OES
GL_PALETTE8_RGBA8_OES
GL_PALETTE8_R5_G6_B5_OES
GL_PALETTE8_RGBA4_OES
GL_PALETTE8_RGB5_A1_OES

自分の使いたいものを glCompressedTexImage2D の第3引数に渡せばいい。


で、buf にはパレットデータとインデックスデータの両方を詰め込む。
4bit インデックスの場合は16個のパレット。8bit インデックスの場合は256個のパレット。RGBA の順番は定義の通りでいい。ただしリトルエンディアンなのでバイト単位で書き込む際は注意。
で、パレットの後にはインデックスデータが並ぶと。


あと width と height は2のべき乗じゃないとダメ。glTexImage2D は「2^n + 2border」とか書いてあるんだけど、glCompressedTexImage2D には書いてないから width や height が 1 でもきっと大丈夫っぽい?
自分はあまりその辺突っつきたくないので、とりあえず最低でも 4 以上の大きさになるように設定しておきますた。


それから、実際に使いたい範囲のイメージの大きさと、それを2のべき乗にした大きさというのは違うものだと思うんだけど、その状態で線形補完処理で大きく拡大すると、本来見えてはいけない部分が補完されてにじみ出てくることがあったりするので、線形補完する場合は余った領域をできるだけ透過するパレットに設定しておいた方がいい(大抵の場合は 0 だと思ふ)。