圧縮テクスチャ(インデックステクスチャ)の生成

OpenGL でインデックスカラーテクスチャを表示していたときには、 glPixelMap を利用してパレットデータを
参照するような実装をしていました.

一応、例を挙げておくとこんな感じ

GLfloat a_RedArray[ 256 ];
GLfloat a_GreenArray[ 256 ];
GLfloat a_BlueArray[ 256 ];
GLfloat a_AlphaArray[ 256 ];

color* a_clut = getClut();
for( s32 i = 0; i < 256; i++ ){
    a_RedArray[ i ] = a_clut[ i ].r;
    a_GreenArray[ i ] = a_clut[ i ].g;
    a_BlueArray[ i ] = a_clut[ i ].b;
    a_AlphaArray[ i ] = a_clut[ i ].a;
}

glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, a_RedArray );
glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, a_GreenArray );
glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, a_BlueArray );
glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, a_AlphaArray );

glPixelTransferi( GL_MAP_COLOR, true );

GLuint	a_Name;
glGenTextures(1, &a_Name);
glBindTexture(GL_TEXTURE_2D, a_Name);

glTexImage2D( GL_TEXTURE_2D,    // GL_TEXTURE_2D固定
              0,                // ミップマップ基準
              GL_RGBA,          // 内部フォーマット
              _getWidth(),      // 幅
              _getHeight(),     // 高さ
              0,                // 境界の幅
              GL_COLOR_INDEX,   // ピクセルフォーマット
              GL_UNSIGNED_BYTE, // i_pBuf のタイプ
              _getData() );

ずっとこれが普通なのかと...

で、 iPhone + egl でインデックスカラーテクスチャを表示しようと思ったら、 GL_COLOR_INDEX の定数が見つからんって
怒られたんで、じゃ、インデックスカラーテクスチャはどうやって表示するんだろうと調べていたら、 glCompressedTexImage2D ってのに
たどり着いたわけです.

てっきり、s3tc テクスチャとかにしかつかわんかと思っていたよ...

インデックスカラーテクスチャ

glCompressedTexImage2D を利用する.

void glCompressedTexImage2D(	GLenum target,
 	GLint level,
 	GLenum internalformat,
 	GLsizei width,
 	GLsizei height,
 	GLint border,
 	GLsizei imageSize,
 	const GLvoid * data);

公式にサポートされる圧縮フォーマットは、 internalformat によって決定されている.

インデックスカラーテクスチャも、圧縮テクスチャとして扱われていて、 internalformat には、 GL_PALETTE8_RGBA8_OES 等を
設定することになる.

data には、圧縮テクスチャのデータを指定することになる.

インデックスカラーテクスチャの場合、パレットデータの次にイメージデータが続くようなデータとなる.

すなわち

(データの先頭)

                      • -

パレットデータ

                      • -

イメージデータ

                      • -

として、 data を渡す必要がある.

簡単なサンプルを以下に示す

GLuint createTexture( s32 i_width, s32 i_height )
{
    s32 a_palette_size = sizeof( u32 ) * 256;
    s32 a_image_size = i_width * i_height;

    u8* a_data = new u8[ a_palette_size + a_image_size ];

    // パレットデータ
    for( s32 i = 0; i < 256; i++ ){
        a_data[ (4 * i) + 0 ] = i; // red
        a_data[ (4 * i) + 1 ] = i; // green
        a_data[ (4 * i) + 2 ] = i; // blued
        a_data[ (4 * i) + 3 ] = 255; // alpha

    }

    // イメージ部
    for( s32 h = 0; h < i_height; h++ ){
        MemCpy( a_data + a_palette_size, 0, a_image_size );
    }

    GLuint a_name;
    glGenTextures( 1, &a_name );
    glBindTexture( GL_TEXTURE_2D, a_name );
        
    glCompressedTexImage2D( GL_TEXTURE_2D,
                            0,
                            GL_PALETTE8_RGBA8_OES,
                            i_width,
                            i_height,
                            0,
                            a_palette_size + a_image_size,
                            a_data
                            );

    delete[] a_data;

    return a_name;
}

その他の圧縮テクスチャについて

glCompressTexImage2D() では、圧縮フォーマットを internalformat によって決定しているので、対応している
圧縮フォーマットは、実装によって異なる.

s3tc とかが指定できる実装が存在するってことだと思う.

iPhone では、 PVRTC(PowerVB Texture Compress?) が利用できるらしい.
(手が空いたら調べる)