7. テクスチャ

3DS で扱うことのできるテクスチャには、ポリゴンモデルに貼り付ける 2 次元テクスチャ、キューブマップテクスチャのほかに、シャドウで使用するシャドウテクスチャ、ガスレンダリングで使用するガステクスチャ、予約フラグメントシェーダで使用する参照テーブル(テクスチャとしては使用しません)が存在します。

この章では、それらのテクスチャを使用するために必要な手順と、ネイティブフォーマットの違いについて説明します。

7.1. テクスチャオブジェクトの生成

テクスチャと関連付けるテクスチャオブジェクトを glGenTextures() で生成します。

コード 7-1. glGenTextures() の定義
void glGenTextures(GLsizei n, GLuint* textures);

7.2. テクスチャオブジェクトの指定

テクスチャと関連付けるテクスチャオブジェクトを glBindTexture() で指定します。この関数の呼び出し以降、各種テクスチャへの処理は指定されたテクスチャオブジェクトに対して行われるようになります。テクスチャイメージのロードなど、テクスチャオブジェクトへの処理結果はオブジェクトが破棄されるまで保持されます。そのため、テクスチャオブジェクトを切り替えることで、テクスチャイメージを再ロードすることなくテクスチャを切り替えることができます。

コード 7-2. glBindTexture() の定義
void glBindTexture(GLenum target, GLuint texture);

target にテクスチャの種類を、texture に関連付けるテクスチャオブジェクトを渡します。target に下表以外の値を指定した場合は GL_INVALID_ENUM のエラーを生成します。

表 7-1. テクスチャの種類

target に指定する値

テクスチャの種類

GL_TEXTURE_2D

2 次元テクスチャ、シャドウテクスチャ、ガステクスチャ

GL_TEXTURE_CUBE_MAP_POSITIVE_X

キューブマップテクスチャ

GL_TEXTURE_CUBE_MAP_NEGATIVE_X

キューブマップテクスチャ

GL_TEXTURE_CUBE_MAP_POSITIVE_Y

キューブマップテクスチャ

GL_TEXTURE_CUBE_MAP_NEGATIVE_Y

キューブマップテクスチャ

GL_TEXTURE_CUBE_MAP_POSITIVE_Z

キューブマップテクスチャ

GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

キューブマップテクスチャ

GL_LUT_TEXTUREi_DMPi は 0 から 31)

参照テーブル(予約フラグメントシェーダで使用)

GL_TEXTURE_COLLECTION_DMP

テクスチャコレクション(「7.9. テクスチャコレクション」を参照)

7.3. テクスチャイメージのロード

一般的なテクスチャイメージである 2 次元テクスチャのほかにも、キューブマップテクスチャ、シャドウテクスチャ、ガステクスチャといった特殊なテクスチャも glTexImage2D() でロードします。glTexSubImage2D() によるテクスチャの部分ロードはサポートしていません

コード 7-3. glTexImage2D() の定義
void glTexImage2D(GLenum target, GLint level, GLenum internalformat, 
                  GLsizei width, GLsizei height, GLint border, GLenum format, 
                  GLenum type, const void* pixels);

target には以下のいずれかを指定します。

表 7-2. glTexImage2D() の target に指定する値

target に指定する値

テクスチャの用途

GL_TEXTURE_2D

2 次元テクスチャ、シャドウテクスチャ、ガステクスチャ

GL_TEXTURE_CUBE_MAP_POSITIVE_X

キューブマップの +X 面のテクスチャ

GL_TEXTURE_CUBE_MAP_NEGATIVE_X

キューブマップの -X 面のテクスチャ

GL_TEXTURE_CUBE_MAP_POSITIVE_Y

キューブマップの +Y 面のテクスチャ

GL_TEXTURE_CUBE_MAP_NEGATIVE_Y

キューブマップの –Y 面のテクスチャ

GL_TEXTURE_CUBE_MAP_POSITIVE_Z

キューブマップの +Z 面のテクスチャ

GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

キューブマップの –Z 面のテクスチャ

pixels の指す領域に格納されているテクスチャイメージのフォーマットを formattype の組み合わせで指定します。3DS が扱うことのできるフォーマットの一覧を下表に示します。バイト数の列は 1 テクセルあたりのバイト数です。バイト数の後に"*"のついたフォーマットは PICA ネイティブフォーマットであり、OpenGL 標準のフォーマットとはバイトオーダーが異なるものです。PICA ネイティブフォーマットの詳細は「7.10. PICA ネイティブフォーマット」で説明します。

表 7-3. format と type によるテクスチャイメージのフォーマット

format

type

形式

バイト数

GL_RGBA

GL_UNSIGNED_SHORT_4_4_4_4

RGBA4

2

GL_RGBA

GL_UNSIGNED_SHORT_5_5_5_1

RGBA5551

2

GL_RGBA

GL_UNSIGNED_BYTE

RGBA8

4

GL_RGB

GL_UNSIGNED_SHORT_5_6_5

RGB565

2

GL_RGB

GL_UNSIGNED_BYTE

RGB8

3

GL_ALPHA

GL_UNSIGNED_BYTE

A8

1

GL_ALPHA

GL_UNSIGNED_4BITS_DMP

A4

0.5

GL_LUMINANCE

GL_UNSIGNED_BYTE

L8

1

GL_LUMINANCE

GL_UNSIGNED_4BITS_DMP

L4

0.5

GL_LUMINANCE_ALPHA

GL_UNSIGNED_BYTE

LA8

2

GL_LUMINANCE_ALPHA

GL_UNSIGNED_BYTE_4_4_DMP

LA4

1

GL_SHADOW_DMP

GL_UNSIGNED_INT

-

4

GL_GAS_DMP

GL_UNSIGNED_SHORT

-

4

GL_HILO8_DMP

GL_UNSIGNED_BYTE

-

2

GL_RGBA_NATIVE_DMP

GL_UNSIGNED_SHORT_4_4_4_4

RGBA4

2

GL_RGBA_NATIVE_DMP

GL_UNSIGNED_SHORT_5_5_5_1

RGBA5551

2

GL_RGBA_NATIVE_DMP

GL_UNSIGNED_BYTE

RGBA8

4*

GL_RGB_NATIVE_DMP

GL_UNSIGNED_SHORT_5_6_5

RGB565

2

GL_RGB_NATIVE_DMP

GL_UNSIGNED_BYTE

RGB8

3*

GL_ALPHA_NATIVE_DMP

GL_UNSIGNED_BYTE

A8

1

GL_ALPHA_NATIVE_DMP

GL_UNSIGNED_4BITS_DMP

A4

0.5

GL_LUMINANCE_NATIVE_DMP

GL_UNSIGNED_BYTE

L8

1

GL_LUMINANCE_NATIVE_DMP

GL_UNSIGNED_4BITS_DMP

L4

0.5

GL_LUMINANCE_ALPHA_NATIVE_DMP

GL_UNSIGNED_BYTE

LA8

2*

GL_LUMINANCE_ALPHA_NATIVE_DMP

GL_UNSIGNED_BYTE_4_4_DMP

LA4

1

GL_SHADOW_NATIVE_DMP

GL_UNSIGNED_INT

-

4*

GL_GAS_NATIVE_DMP

GL_UNSIGNED_SHORT

-

4*

GL_HILO8_DMP_NATIVE_DMP

GL_UNSIGNED_BYTE

-

2*

R、G、B:カラー(Red、Green、Blue)
A:アルファ
L:輝度

OpenGL ES1.1 での仕様と同様に、RGB のように A 成分の存在しないテクスチャをテクスチャコンバイナから参照した場合、A 成分には 1 が出力されます。これは、圧縮テクスチャについても同様です。

format GL_RGB または GL_RGB_NATIVE_DMP で、typeGL_UNSIGNED_BYTE の組み合わせは targetGL_TEXTURE_2D を指定している場合にのみ指定可能です。formatGL_*_NATIVE_DMP を指定した場合、pixels で指定されるデータは PICA のネイティブフォーマットでなければなりません。また、GL_GAS_DMP を指定した場合は、pixels は 0(NULL)でなければなりません。

width height にはテクスチャイメージの幅と高さを指定します。ともに 8 ~ 1024 の 2 のべき乗の数でなければなりません。

target の指定が GL_TEXTURE_CUBE_MAP_* である場合、widthheight の値は同じでなければなりません。また、各面の設定は pixels(と target)以外がすべて同じ指定でなければなりません。

pixels に 0(NULL)を指定した場合はイメージデータのロードは行われず、領域の確保だけが行われます。

internalformat には内部基本形式を指定します。internalformatformat の指定が同じでない場合は GL_INVALID_OPERATION のエラーが生成されます。イメージの RGBA 成分と内部基本形式の各成分との対応は以下のようになっています。

表 7-4. 内部基本形式による RGBA と内部形式の対応

内部基本形式

RGBA

内部形式

GL_ALPHA

A

A

GL_LUMINANCE

R

L

GL_LUMINANCE_ALPHA

R、A

L、A

GL_RGB

R、G、B

R、G、B

GL_RGBA

R、G、B、A

R、G、B、A

GL_HILO8_DMP

R、G

Nx、Ny

GL_HILO8_DMP の場合、B 成分と A 成分にはそれぞれ 0.0 と 1.0 が出力されます。

OpenGL の仕様と異なり、level にはミップマップ段数を負の値(例えば、段数が 2 ならば -2。0 と -1 は同じ段数 1 として扱う)で設定します。個別にミップマップの各レベルで使用するテクスチャを指定することはできず、pixels には最も大きなサイズのレベルで使用するテクスチャから最も小さなサイズのレベルで使用するテクスチャまでを連続して格納したデータを指定してください。

border には、0 以外の値を指定することはできません。

補足:

glTexImage2D()target に特別なフラグを論理和で渡すことで、GPU のアクセス先や領域確保時の処理を指定することができます。詳細については、「3DS プログラミングマニュアル - グラフィックス応用編」「メインメモリに置かれたデータの使用」を参照してください。

7.3.1. コンポーネントが 4 ビットのフォーマットについて

type GL_UNSIGNED_BYTE_4_4_DMP または GL_UNSIGNED_4BITS_DMP のテクスチャフォーマットは、1 つのコンポーネントが 4 ビットで構成されているため、そのデータの並びは特殊なものになっています。

type GL_UNSIGNED_BYTE_4_4_DMP のフォーマットは、1 バイトに 2 つのコンポーネントを含むフォーマットです。format には GL_LUMINANCE_ALPHA または GL_LUMINANCE_ALPHA_NATIVE_DMP を組み合わせることができます。上位 4 ビットに輝度成分、下位 4 ビットにアルファ成分が格納されます。

type GL_UNSIGNED_4BITS_DMP のフォーマットは、1 バイトに 2 テクセルを含むフォーマットです。format には GL_LUMINANCEGL_LUMINANCE_NATIVE_DMPGL_ALPHAGL_ALPHA_NATIVE_DMP のいずれかを組み合わせることができます。テクセルの並びで見ると、成分は下位 4 ビット、上位 4 ビットの順に格納されます。

注意:

type GL_UNSIGNED_4BITS_DMP を指定するテクスチャフォーマット(4 ビットフォーマット)と、それ以外のテクスチャフォーマット(非 4 ビットフォーマット。ETC1 方式の圧縮テクスチャ含む)を同時に有効にし、マルチテクスチャとして使用する場合はテクスチャの配置に制限があります。

4 ビットフォーマットのテクスチャを VRAM に配置する場合は 4 ビットフォーマットと非 4 ビットフォーマットのテクスチャを異なるメモリに配置しなければなりません。その際、VRAM-A と VRAM-B は異なるメモリとして扱われます。なお、同じメモリに配置した場合の動作は不定です。

4 ビットフォーマットのテクスチャをメインメモリに配置した場合はテクスチャの配置に制限はありません。

図 7-1. コンポーネントが 4 ビットで構成されているテクスチャフォーマットのビットレイアウト

Luminance[n] Alpha[n] +0 Byte Luminance[n+1] Alpha[n+1] +1 Byte Luminance[n+3] Alpha[n+2] Luminance[n+2] Alpha[n+3] GL_LUMINANCE_ALPHA(GL_LUMINANCE_ALPHA_NATIVE_DMP) GL_UNSIGNED_BYTE_4_4_DMP GL_LUMINANCE(GL_LUMINANCE_NATIVE_DMP) GL_ALPHA(GL_ALPHA_NATIVE_DMP) GL_UNSIGNED_4BITS_DMP

7.4. 圧縮テクスチャのロード

圧縮された画像データをテクスチャイメージとしてロードすることができます。glCompressedTexSubImage2D() による圧縮テクスチャの部分ロードはサポートしていません

コード 7-4. glCompressedTexImage2D() の定義
void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, 
                            GLsizei width, GLsizei height, GLint border, 
                            GLsizei imageSize, const void* data);

target に指定する値は glTexImage2D()target と同じです(表 7-2)。ただし、この関数で確保した領域をシャドウテクスチャやガステクスチャに使用することはできません。

width height にはテクスチャイメージの幅と高さを指定します。ともに 16 ~ 1024 の 2 のべき乗の数でなければなりません。

level border に指定する値と、キューブマップテクスチャおよびミップマップテクスチャについての制限は glTexImage2D() と同じです。詳細は「7.3. テクスチャイメージのロード」を参照してください。

テクスチャの圧縮方式は ETC1(Ericsson Texture Compression)方式のみがハードウェアでサポートされています。そのため、internalformat には GL_ETC1_RGB8_NATIVE_DMP または GL_ETC1_ALPHA_RGB8_A4_NATIVE_DMP が指定可能です。

ETC1 方式は 24 bit RGB フォーマットの 4x4 テクセルを 64 bit に圧縮します。GL_ETC1_RGB8_NATIVE_DMP はアルファチャンネルには対応していませんが、GL_ETC1_ALPHA_RGB8_A4_NATIVE_DMP は 16 テクセル× 4 bit のアルファ成分データを付加することによってアルファチャンネルに対応しています。

なお、アルファチャンネルに対応していないフォーマットの圧縮テクスチャをテクスチャコンバイナから参照した場合、A 成分には 1 が出力されます。

imageSize にはイメージデータのバイトサイズを指定します。imageSize はテクスチャの元画像の幅を w、高さを h とすれば以下の計算式で求めることができます。blockSize にはアルファチャンネルなしでは 8 が、アルファチャンネルありでは 16 が適用されます。

imageSize = (w / 4) * (h / 4) * blockSize

3DS で扱う ETC1 方式は標準の仕様とは異なっています。標準仕様とのフォーマットの違いは「7.10. PICA ネイティブフォーマット」で説明します。フォーマットの詳細については「3DS プログラミングマニュアル - グラフィックス応用編」を参照してください。

補足:

glCompressedTexImage2D()target に特別なフラグを論理和で渡すことで、GPU のアクセス先や領域確保時の処理を指定することができます。詳細については、「3DS プログラミングマニュアル - グラフィックス応用編」「メインメモリに置かれたデータの使用」を参照してください。

7.5. フレームバッファからのコピー

フレームバッファオブジェクトに関連付けられているカラーバッファ、デプスバッファの画像をテクスチャとして取得(コピー)することができます。

7.5.1. カラーバッファからのコピー

カラーバッファの画像をテクスチャとして取得(コピー)することができます。

コード 7-5. glCopyTexImage2D() の定義
void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, 
                      GLint x, GLint y, GLsizei width, GLsizei height, 
                      GLint border);

target に指定する値は glTexImage2D()target と同じです(表 7-2)。そのほかの引数も以下の違いを除けば同じです。

  • internalformat で指定可能な内部形式のフォーマットは GL_RGB または GL_RGBA のみで、カラーバッファのフォーマットからの変換を伴うコピーはできません(ピクセルサイズが同じフォーマットは可能です)。
  • x y にはカラーバッファからコピーする領域の開始点(左下原点、右上正方向)を指定します。widthheight にはコピーする領域の幅と高さを指定します。xy は 8 の倍数で指定しなければなりません。
  • level には 0 のみが指定可能です。
補足:

glCopyTexImage2D()target に特別なフラグを論理和で渡すことで、GPU のアクセス先や領域確保時の処理を指定することができます。詳細については、「3DS プログラミングマニュアル - グラフィックス応用編」「メインメモリに置かれたデータの使用」を参照してください。

7.5.2. カラーバッファからの部分コピー

カラーバッファからテクスチャイメージの部分領域にコピーすることもできます。

コード 7-6. glCopyTexSubImage2D() の定義
void glCopyTexSubImage2D(GLenum target, GLint level, 
                         GLint xoffset, GLint yoffset, GLint x, GLint y, 
                         GLsizei width, GLsizei height);

コピー先のテクスチャイメージの領域を、glTexImage2D() で事前に確保していなければなりません。

xoffset yoffset にコピー先領域の座標(左下原点、右上正方向。8 の倍数でなければなりません)を指定すること、widthheight には 8 の倍数(2 のべき乗でなくてもよい)を指定すること以外は、glCopyTexImage2D() と同じです。詳細は「7.5.1. カラーバッファからのコピー」を参照してください。

7.5.3. デプスバッファからのコピー

glEnable() の引数に GL_DEPTH_STENCIL_COPY_DMP を渡して呼び出し、デプスステンシルコピー機能を有効にした状態で glCopyTexImage2D() または glCopyTexSubImage2D() を呼び出したときはカラーバッファではなく、デプスバッファ(ステンシル含む)の内容がテクスチャにコピーされます。

カレントのデプスバッファのフォーマットによって、コピー先に指定するテクスチャのフォーマットは決められています。コピー時にフォーマットの変換は行われませんので、対応していないフォーマットのテクスチャにコピーをしようとした場合は GL_INVALID_OPERATION のエラーが生成されます。テクスチャにコピーされる内容は、テクスチャがネイティブフォーマットであるかどうかによって変化することはありません。

表 7-5. デプスバッファのフォーマットとテクスチャの format、type の対応

デプスバッファのフォーマット

テクスチャの format

テクスチャの type

成分の内容

GL_DEPTH24_STENCIL8_EXT

GL_RGBA

GL_RGBA_NATIVE_DMP

GL_UNSIGNED_BYTE

R: Stencil
G: D [23 : 16]
B: D [15 : 8]
A: D [7 : 0]

GL_DEPTH_COMPONENT24_OES

GL_RGB

GL_RGB_NATIVE_DMP

GL_UNSIGNED_BYTE

R: D [23 : 16]
G: D [15 : 8]
B: D [7 : 0]

GL_DEPTH_COMPONENT16

GL_HILO8_DMP

GL_HILO8_DMP_NATIVE_DMP

GL_UNSIGNED_BYTE

R: D [15 : 8]
G: D [7 : 0]

※ 「成分の内容」列の "D [x : y]" は、その成分に設定されるデプス値のビット位置を示しています。

デプスステンシルコピー機能は、GL_DEPTH_STENCIL_COPY_DMP を引数にして、glEnable()glDisable()glIsEnabled() を呼び出すことで、有効化、無効化、有効・無効の判定を行うことができます。

補足:

glCopyTexImage2D()glCopyTexSubImage2D() はブロックモードがブロック 32 モードのときに使用することができません。エラーは生成されませんが、画像の転送が正しく行われません。ブロックモードの設定については「3DS プログラミングマニュアル - グラフィックス応用編」を参照してください。

7.6. レンダーターゲットへのテクスチャの指定

glTexImage2D() で確保したテクスチャイメージを glFramebufferTexture2D() でフレームバッファオブジェクトに関連付けることで、レンダリング結果を直接テクスチャに書き込む(render to texture)ことができます。シャドウやガスで使用される特殊なテクスチャはそれぞれの機能においてレンダリング結果が直接テクスチャに書き込まれるため、この関数でテクスチャをレンダーターゲットに指定しなければなりません。

コード 7-7. glFramebufferTexture2D() の定義
void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, 
                            GLuint texture, GLint level);

target に指定することができるのは GL_FRAMEBUFFER のみです。

attachement にはテクスチャに書き込む情報を指定します。カラーバッファならば GL_COLOR_ATTACHMENT0、デプスバッファならば GL_DEPTH_ATTACHMENT を指定します。

textarget に指定する値は glTexImage2D()target と同じです(表 7-2)。

texture には、フレームバッファオブジェクトに関連付けるテクスチャオブジェクトを指定します。

level には 0 のみが指定可能です。

デプスバッファ(ステンシルバッファ含む)のレンダーターゲットにテクスチャを指定する場合、デプスバッファのフォーマットによって、テクスチャのフォーマットは決められています。対応するフォーマットは「7.5.3. デプスバッファからのコピー」と同じです(表 7-5)。デプスバッファのフォーマットが GL_DEPTH24_STENCIL8_EXT の場合、attachmentGL_DEPTH_STENCIL_ATTACHMENT を指定できますが、GL_DEPTH_ATTACHMENT と同じ結果になります。

7.7. 参照テーブルのロード

OpenGL の 1 次元テクスチャをロードする関数 glTexImage1D() を、3DS では参照テーブルのロードに使用します。参照テーブルとは、プロシージャルテクスチャやフラグメントライティング、フォグ、ガスで参照する 1 次元のテーブルのことで、テクスチャとして使用することはありません。

コード 7-8. glTexImage1D() の定義
void glTexImage1D(GLenum target, GLint level, GLint internalformat, 
                  GLsizei width, GLint border, GLenum format, GLenum type, 
                  const GLvoid *pixels);

target にはロード先の参照テーブルを GL_LUT_TEXTUREi_DMP で指定します。i は参照テーブルの番号(0 ~ glGetIntegerv()pnameGL_MAX_LUT_TEXTURES_DMP を渡して得られる値 - 1)です。つまり、参照テーブル番号は 0 ~ 31 の範囲で指定することができます。GL_LUT_TEXTUREi_DMP は(GL_LUT_TEXTURE0_DMP + i)で定義されています。

level には 0 、type には GL_FLOATformat および internalformat には GL_LUMINANCEF_DMP のみを指定することができます。level に 0 以外を指定した場合は GL_INVALID_VALUE のエラーを、typeformatinternalformat に上記以外を指定した場合は GL_INVALID_ENUM のエラーを生成します。

width にはテーブルの要素数を、pixels にはテーブルの要素を指定します。width に指定することのできる最大値は glGetIntegerv()pnameGL_MAX_LUT_ENTRIES_DMP を渡して得られる 512 ですが、テーブルの要素数および要素は予約フラグメント処理によって独自の制限が決められています。

glGetIntegerv()pnameGL_TEXTURE_BINDING_LUTi_DMPi は 0 ~ 31)を渡して呼び出すと、GL_LUT_TEXTUREi_DMP に関連付けられているテクスチャオブジェクト(の ID)を取得することができます。

すでにロードされている参照テーブルの内容を一部分だけ書き換えるには、glTexSubImage1D() を使用します。

コード 7-9. glTexSubImage1D() の定義
void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, 
                     GLsizei width, GLenum format, GLenum type, 
                     const GLvoid *pixels);

コピー先の参照テーブルの領域は、glTexImage1D() で事前に確保していなければなりません。

xoffset width に書き換えたい要素の先頭番号と要素数を指定すること以外は、glTexImage1D() と同じです。xoffsetwidth の合計がテーブルの要素数を超える場合は GL_INVALID_VALUE のエラーを生成します。

glCopyTexImage1D()glCopyTexSubImage1D() は実装されていません。また、テクスチャパラメータの設定には対応していません。

7.8. テクスチャオブジェクトの破棄

不要になったテクスチャオブジェクトは glDeleteTextures() で破棄することができます。

コード 7-10. glDeleteTextures() の定義
void glDeleteTextures(GLsizei n, const GLuint* textures);

7.9. テクスチャコレクション

テクスチャコレクションは 3DS が独自に導入したもので、テクスチャオブジェクトとテクスチャの関連付けを記録します。テクスチャコレクションを使用することで、記録された各種テクスチャとテクスチャオブジェクトの関連付けをまとめて行うことができます。テクスチャコレクションはテクスチャオブジェクトと名前空間を共有していますので、glGenTextures()glBindTexture()glDeleteTextures() を使用して生成・指定・破棄を行います。

7.9.1. テクスチャコレクションの生成

テクスチャコレクションは特殊なテクスチャオブジェクトとして動作します。そのためテクスチャオブジェクトと同じように、glGenTextures() でテクスチャコレクションとして使用するオブジェクトを生成します。

7.9.2. テクスチャコレクションの指定

テクスチャコレクションとして使用するテクスチャオブジェクトを指定するには glBindTexture() を使用します。targetGL_TEXTURE_COLLECTION_DMP を渡して呼び出してください。デフォルトでは、名前 0(texture に 0 を渡した状態)のオブジェクトがテクスチャコレクションとなっています。

呼び出し後は、各種テクスチャ(2 次元テクスチャ、キューブマップテクスチャ、参照テーブル)への glBindTexture() によるテクスチャオブジェクトの関連付けはテクスチャコレクションに記録されていきます。同じテクスチャへの関連付けは上書きされ、テクスチャコレクションへの記録はほかのテクスチャコレクションへ切り替えられるまで行われます。

テクスチャコレクションを切り替えると、各種テクスチャとテクスチャオブジェクトとの関連付けはテクスチャコレクションに記録されているオブジェクトにすべて切り替わります。

7.9.3. テクスチャコレクションの破棄

テクスチャオブジェクトと同じように、glDeleteTextures() でテクスチャコレクションを破棄することができます。テクスチャコレクションを破棄しても、記録されているテクスチャオブジェクトのテクスチャとの関連付けに影響ありません。

使用中のテクスチャコレクションへの glDeleteTextures() の呼び出しでは、すぐにテクスチャコレクションが破棄されません。ほかのテクスチャコレクションに切り替えられるまで使用状態のまま残ります。デフォルトのテクスチャコレクションは破棄できません。デフォルトのテクスチャコレクションに対する glDeleteTextures() の呼び出しは無視されます。

7.10. PICA ネイティブフォーマット

GPU のテクスチャユニットがサポートしているテクスチャフォーマットは OpenGL の仕様と異なっています。テクスチャユニットが実際にサポートしているフォーマットを PICA ネイティブフォーマットと呼びます。PICA ネイティブフォーマットのテクスチャをロードする場合、ライブラリ内でのフォーマット変換が行われないため、標準フォーマットよりも効率が良くなります。

OpenGL の仕様との大きな違いは以下の 3 つです。

  • バイトオーダー
    内部のアドレス処理の関係でバイトデータの記述順序が異なります。
  • V フリップ
    U、V 座標とテクセルとの配置の関係が V 方向で反対になっています。
  • アドレッシング
    リニアアドレッシング(OpenGL)とブロックアドレッシング(PICA ネイティブフォーマット)の相違により、テクセルおよび圧縮データブロックの記述順序が異なります。

OpenGL のフォーマットから PICA ネイティブフォーマットへ変換するには、非圧縮テクスチャ(glTexImage2D() でロード)であれば V フリップ変換→アドレッシング変換→バイトオーダー変換の順に行い、圧縮テクスチャ(glCompressedTexImage2D() でロード)であれば、V フリップ変換→ETC 圧縮→アドレッシング変換→バイトオーダー変換の順に行います。ETC 圧縮の前に V フリップ変換を行わなければならないことに注意してください。

7.10.1. バイトオーダーの違い

glTexImage2D()typeGL_UNSIGNED_BYTE を指定し、複数バイトで 1 テクセルを表現するフォーマットは、そのバイト数でバイトスワップ(バイトデータの入れ替え)を行います。

圧縮フォーマットの場合は 1 ブロック(4x4 テクセル分の 8 バイト)単位でバイトデータの入れ替えを行います。ただし、アルファチャンネルありの場合は、アルファ部分(前半の 8 バイト)のバイトデータの入れ替えは行いません。

図 7-2. 4 バイトスワップ

OpenGL ネイティブ R G B A

図 7-3. 3 バイトスワップ

OpenGL ネイティブ R G B

図 7-4. 2 バイトスワップ

OpenGL ネイティブ L A

図 7-5. 圧縮フォーマット(アルファチャンネルなし)のバイトスワップ

B0 B1 B2 B3 B4 B5 B6 B7 ETC1 ネイティブ B8 B9 B15 B14 8バイト単位での入れ替えが行われる

図 7-6. 圧縮フォーマット(アルファチャンネルあり)のバイトスワップ

B0 B1 B2 B3 B4 B5 B6 B7 ETC1 ネイティブ カラー部分は 8バイト単位での入れ替えが行われる B8 B9 B10 B11 B12 B13 B14 B15 アルファ部分は入れ替えが行われない

7.10.2. V フリップの違い

OpenGL の仕様では(u, v)=(0.0, 0.0)にあるテクセルを先頭にイメージがデータ化されますが、PICA ネイティブフォーマットでは(u, v)=(0.0, 1.0)にあるテクセルを先頭にイメージがデータ化されます。非圧縮・圧縮テクスチャでの違いはありません。

7.10.3. アドレッシングの違い

OpenGL の仕様では u 方向に連続したテクセルを格納(リニアアドレッシング)していきますが、PICA ネイティブフォーマットではブロック単位で u 方向に連続しますが、ブロック内はジグザグにテクセルを格納(ブロックアドレッシング)していきます。

7.10.3.1. 非圧縮テクスチャ

8x8 テクセルを 1 ブロックとして、ブロック内はジグザグ(図内の赤線)に格納していきますが、ブロック単位では u 方向に連続して格納していきます。

図 7-7. 非圧縮テクスチャのテクセル格納順

8x8テクセルが1ブロック(ブロック単位では u 方向に連続) 0.0 1.0

7.10.3.2. 圧縮テクスチャ

圧縮テクスチャは 4x4 テクセルをまとめてブロックと呼び、ブロック単位で圧縮されます。OpenGL の仕様ではブロック単位で u 方向に連続して格納(図内の青線)していきますが、PICA ネイティブフォーマットでは 2x2 ブロックをメタブロックとし、メタブロック内はジグザグに、メタブロック単位では u 方向に連続して格納(図内の赤線)していきます。

図 7-8. 圧縮テクスチャのテクセル格納順

0.0 1.0

圧縮テクスチャについての詳細は「3DS プログラミングマニュアル - グラフィックス応用編」を参照してください。