テクスチャ(Texture)

SAMPLE http://ooo.iiyudana.net/bin/gl/simpletexture.exe( シンプルテクスチャ ) https://www.dropbox.com/s/m2bvbvtg4x8iw6m/dragdrop_texture.exe( ドラックアンドドロップした 2冪サイズのbmp ファイルをテクスチャにする )


処理の基本

DESC テクスチャ処理はフラグメント単位でされる。 UV値は rasterize の補間結果になる UV の値から画像のテクセル値を取得する 頂点毎の lighting 計算結果後 の fragment に適用される Fragment に適用される前は, Vertex 毎に tc を割り当てる ラスタライズ中に, 透視補正補間アルゴリズムを利用して, フラグメント毎に適用される TextureObject は高速な VideoMemory に配置される サイズはなるべく小さい方がいい
map される texel は 左下原点( 0,0 )の直交座標系 t | | | |-------- s glTexImage2D() で指定するピクセル列は以下のようになる (0,0) data の先頭 (1,1) data の最後 POINT Y 反転するのは 画像 data は左上から始まるため
頂点のカラーを基本色として、テクスチャステージ0から順番に処理される。 ステージ1はステージ0と頂点カラーの混色の結果になる。 頂点カラーは glColor() またはライティングされた色で、 ラスタライズされた時点では各頂点で線形補間された色になる。 混色の方法は glTexEnv() で指定する。
頂点カラー ---> [ ステージ0 ] ---> [ ステージ1 ] ---> ...
はみ出した部分を指定するときは, WRAP_S|T param を利用して mapping を制御する


基本的な流れ

テクスチャオブジェクトはアプリケーションの初期化でする。
unsigned int gId; void App::onInit() { // TextureObject を生成して、そのIDを取得する glGenTextures( 1, &gId ); glBindTexture( GL_TEXTURE_2D, gId ); // タイプを指定してつくる( GL_TEXTURE_2D ) typedef struct { unsigned char c[3]; } col; col O = { 0xFF, 0x00, 0x00 }; col I = { 0xFF, 0xFF, 0xFF }; col img[] = { I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, O, I, I, I, I, O, I, I, O, I, I, I, I, O, I, I, I, I, I, I, I, I, I, I, O, I, I, I, I, O, I, I, I, O, O, O, O, I, I, I, I, I, I, I, I, I, I, }; // ピクセルデータを指定( ファイルから読んでもよい ) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, img ); // 貼り方の設定 // 補間方法の設定 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // リピート設定 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // 混ぜ方 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); }
void App::draw() { // 描画時に貼り付けるテクスチャを指定する glBindTexture( GL_TEXTURE_2D, gId ); // TextureMap を利用することを宣言する glEnable( GL_TEXTURE_2D ); // UV座標を指定しながら、プリミティブを描画する float z = -1.0f, s = 200.0f; glBegin( GL_QUADS ); glTexCoord2f( 0, 0 ); glVertex3f( 0, 0, z ); glTexCoord2f( 1, 0 ); glVertex3f( s, 0, z ); glTexCoord2f( 1, 1 ); glVertex3f( s, s, z ); glTexCoord2f( 0, 1 ); glVertex3f( 0, s, z ); glEnd(); }
不要なテクスチャオブジェクトを破棄するには glDeleteTexture() を使う。
App::onReset() { glDeleteTextures( 1, &id ); }
// 描画毎に Texture Object を指定する( 変更がないなら そのままで ) App::update() { // id を指定して TextureObject を指定する. glBindTexture( id ); // かく Draw(); }
// 頂点毎に uv 座標を指定して GL に形状 data を送り出す( texture 領域を primitive に関連つける ) UV( 0,0 )は pixel[] の最初を指す -> BMP Format は 左下から格納されている TIP glTexImage2D() になぜ infmt, fmt の指定があるか ? infmt : 指定 data ptr を { fmt, type }のように読んでね. そしてそれを, infmt の形でもつ だから, texture から DEPTH_FORMAT がある MAX_SIZE = 2048 ( ifmt は考慮していないので注意 ) glGetIntegerv(GL_MAX_TEXTURE_UNITS, &n) // TexUnit 数取得. Format は MPEG2, AVI をはりつけることも可能. -> image がとれればよい.


glBindTexture

SYNTAX void glBindTexture( GLenum tgt, // テクスチャオブジェクトのタイプ GLuint id // バインドするテクスチャオブジェクトのID ); DESC TextureObject を選択する IDをはじめて渡す際に, TextureObject が生成される この時, TextureObject の param ( == State )は Default で初期化される ERROR GL_INVALID_OPERATION: 異なる tgt を指定して bind をする
App::init() { // 初期化時にテクスチャオブジェクトを生成 glBindTexture(); glBindTexture( GL_TEXTURE_2D, id ); } App::draw() { // 描画時に利用するテクスチャを指定する glBindTexture( GL_TEXTURE_2D, id ); }



glDeleteTextures

SYNTAX void glDeleteTextures( GLsizei, GLint * ); DESC 指定したテクスチャオブジェクトを破棄する。


TextureCoordを指定する

SYNTAX void glTexCoord( TYPE ); DESC 各頂点がテクスチャをサンプルするテクセルの位置をきめる。 TextureCoord { 0, 0 } ならば 画像の左下の色を取得する
// 各頂点を指定する前に、設定する。 // glTexCoord で指定した値は glVertex で影響をうける // glBegin( GL_TRIANGLES ); glTexCoord2f( 0, 0 ); glVertex3f( 1, 0, 0 ); // この頂点は UV { 0, 0 } を使う glTexCoord2f( 0, 0 ); glVertex3f( 1, 0, 0 ); glTexCoord2f( 0, 0 ); glVertex3f( 1, 0, 0 ); glEnd();
WARNING TextureCoord も頂点と同じく、テクセルをサンプルする前に TextureMatrix が乗算される 自動生成した場合もおなじ 利用しないならば、 TextureMatrix の使用をオフにすることで余計な変換がされることを回避できる。
TextureCoord = M * [ TextureCoord ]
// 頂点と同じように同次座標 であつかわれる // r = 0, q = 1 となる glTexCoord2f( 1, 1 ); // q = 1 glTexCoord2f( 1, 1, 1 ); // 明示する glTexCoord2f( 1, 1, 0, 0 );



パラメータ設定

DESC テクスチャオブジェクトは各種パラメータをもつ テクスチャをサンプルする時はこの設定の影響をうけるため、 適切な初期設定をしておく。 サンプリング方法の指定 拡大フィルタ NEARENT : ピクセルに最も近い Texel をサンプル LINEAR : Pixel を囲む 2 * 2 Texel をサンプル 縮小フィルタ NEARENT LINEAR GL_NEAREST_MIPMAP_NEAREST : 画面上のテクスチャサイズに合うミップマップから GL_NEAREST でテクセルを決定 GL_LINEAR_MIPMAP_NEAREST : 画面上のテクスチャサイズに合うミップマップから GL_LINEAR でテクセルを決定 GL_LINEAR_MIPMAP_LINEAR : 画面上のテクスチャサイズに合う2つミップマップから GL_LINEAR でテクセルを決定 トリリニアサンプリング GL_NEAREST_MIPMAP_LINEAR : 2つのミップマップから取得した値の加重平均とをる。 範囲外を指定したときの設定 GL_REPEAT : 繰り返す GL_CLAMP : 0:1 の範囲に収める Texel の真ん中をサンプルすると, Texel の色そのものになる TIP Texel 格子上の点で Sample すれば均等に 4Texel の平均がとれる ぼかし効果をつくるなら [ Texel 幅の整数倍の場所をサンプルすること ] wrap parameter
App::init() { // mipmap, 拡縮に対する, parameter // depth map parameter // ON glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); WARNING GL_TEXTURE_MIN_FILTER は default で GL_NEAREST_MIPMAP_LINEAR ( mipmap を利用しない texture では正しく描画されない ) GL_REPEAT は shadow map には不向き // OFF glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); }



glTexPrameter

SYNTAX void glTexPrameter( GLenum tgt, GLenum name, // 設定するパラメータ名 TYPE prm // 設定する値 ) DESC TextureObject の 各種パラメータを設定する
// 範囲外のリピート方法を指定する glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 補間方法を指定する
// テクスチャの自動生成にも利用できる
3 種類のカテゴリ. 1. Rasterize 時の Fragment と Texel の対応関係の指定. Fragment が Texel より小さい場合: GL_TEXTURE_MAG_FILTER Fragment が Texel を覆う場合: GL_TEXTURE_MIN_FILTER WARNING: Default が Mipmap を利用する GL に自動生成させる( 画像を指定する前に ) VER:1.4 { glTexPrameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); glTexImage2D(); } tc の wrapping Param : はみだしたときどうするか ? texture image を指定する際は mipmap をすべて指定する必要あり glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); で自動生成 && 自動再生成 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); において, Default が MipMap のため, 必ず変更すること.


画像を割り当てる




glTexImage2D

SYNTAX void glTexImage2D( GLenum tgt, // Texture Object の TYPE ( GL_TEXTURE_2D | CUBE_X ) GLint level, // ミップマップのレベル ( 利用しないならば 0 ) GLint internalFormat, // OpenGL 内部でどの成分(種類)にデータをもつか( RGBA, Depth, Luminance, Intensity ) GLsizei w, h, // 画像サイズ GLint border, GLenum format, // 設定する画像データのフォーマット GLenum type, // 各色要素のデータ型 void *texel // 画像データへのポインタ ) DESC バインドした TextureObject に画像データを設定する。 画像データは OpenGL に転送されるので アプリケーション側はメモリを保持しなくてもよい。 設定する画像データは, テクスチャの左下から右上に向かって割り当てられる。
-----------------End Start-------------
format, type, のパラメータで, アプリケーションから転送する画像データの構成を OpenGL に知らせて internalFormat に従って OpenGL 内でもつ画像データ構造を決める。
// GL_RGB を internalFormat で指定すると, alpha 成分は 1 として扱われる glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, data ); // GL_RGBA を internalFormat で指定すると, alpha 成分は画像データの alpha が利用される。 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
GL_RGBA は 各要素を 32 bit でもつ. 説明としては, どの成分( 明るさ, Depth, RGBA )が Texel として利用するかを決める. TIP GL_RGBA : 4個の要素をもち、カラー画像として使われる。 GL_LUMINANCE : 1個の要素をもち、グレースケールとして使われる。 GL_LUMINANCE_ALPHA : 2個の要素をもち、グレースケールとして使われる。 GL_DEPTH_COMPONENT : 1 成分 -> ( shadow map はこれ )
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, image ); // GL_DEPTH_COMPONENT は特定の解像度を要求しない // 要求に対して近い Format が選択される glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, image );
ミップマップ( あらかじめ縮小した画像のこと )の指定をする場合は、 レベルを変更しながらサイズが半分にした画像データを指定する。
for( i=0; i<3; i++ ){ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, i, GL_RGBA, GL_UNSIGNED_BYTE, image[i] ); }
WARNING 各列は default で 4byte アラインメントになっている必要がある。 ( GL がそう解釈するから )


glTexImage3D

SYNTAX void glTexImage3D(); NOTE 3D Texture は Tool では作成できない そのため Program で動的に作成する POINT DirectX の場合 [0:1] で決めるが GL は [0:255] で決める 3 次元 texture は短い video clip が可能
u32 i, j, k; for( i=0; i<32; i++ ){ for( j=0; j<32; j++ ){ for( k=0; k<32; k++ ){ texvol[i][j][k][0] = (u8)( 255 * myRand() ); texvol[i][j][k][1] = (u8)( 255 * myRand() ); texvol[i][j][k][2] = (u8)( 255 * myRand() ); texvol[i][j][k][3] = 255; } } } glGenTextures( 1, &idVol ); glBindTexture( GL_TEXTURE_3D, idVol ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); MyTex->load3dData( "noise3d.bmp", 32, 32, 32, texvol ); glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );



glTexSubImage2D

SYNTAX void glTexSubImage2D( GLenum tgt, // Texture Object の TYPE ( GL_TEXTURE_2D | CUBE_X ) GLint level, // ミップマップレベル ( 利用しないならば 0 ) GLint x, y, // オフセット GLsizei w, h, GLint border, GLenum format, // 設定する画像のフォーマット GLenum type, // 各要素 の Data 型 // ( GL_BYTE | GL_UNSIGNED_BYTE | GL_SHORT | GL_UNSIGNED_SHORT ) // ( GL_INT | GL_FLOAT | GL_UNSIGNED_INT ) // ( GL_BITMAP ) void *texel ) DESC バインドした既存のテクスチャの一部( SubSet )を 別の画像で置き換える。 glTexImage2D の 部分集合版なので、パラメータもほぼ同じ。 ERROR GL_INVALID_ENUM target が GL_TEXTURE_2D でない場合 format が容認された定数でない type が型定数でない場合 GL_INVALID_VALUE width < 0 | height < 0 GL_INVALID_OPERATION type がGL_UNSIGNED_SHORT_5_6_5 で、format が GL_RGB でない場合


glTexSubImage1D

SYNTAX void glTexImage2D( GLenum tgt, // Texture Object の TYPE ( GL_TEXTURE_2D | CUBE_X ) GLint level, // Image の MipMap Level ( 利用しないならば 0 ) GLint x, y, // Offset GLsizei w, h, GLint border, GLenum format, // 設定元 Image の Format GLenum type, // 各要素 の Data 型 // ( GL_BYTE | GL_UNSIGNED_BYTE | GL_SHORT | GL_UNSIGNED_SHORT ) // ( GL_INT | GL_FLOAT | GL_UNSIGNED_INT ) // ( GL_BITMAP ) void *texel ) DESC 現在の Texture の一部を 別の Texel でおきかえる
float texel[128]; glTexImage1D( GL_TEXTURE_2D, 0, texel );



テクスチャのブレンド方法を指定する

SYNTAX void glTexEnv(if)( GLenum tgt, GLenum namePrm, TYPE prm ) DESC テクセルの色をフラグメントの色とのブレンド方法を指定する。 この設定は テクスチャユニットごとに設定される。 加算処理とかできる ライティングした色と乗算する。(デフォルト)
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// 線形補間するには GL_COMBINE // tex0 * ( 1 - a ) + tex1 * a // glActiveTexture( GL_TEXTURE0 ); glActiveTexture( GL_TEXTURE1 ); glTexEnvi( GL_TEXTURE_ENV_MODE, GL_COMBINE ); glTexEnvi( GL_TEXTURE_ENV_MODE, GL_COMBINE );
GL_BLEND を指定したときは画像のアルファ値は使われないで かわりに画像の RGB 値が 別に設定した色と下地の色との混合比に使われる この色は glTexEnvf() の pname に GL_TEXTURE_ENV_COLOR を指定する この出力画像では テクスチャの暗い部分に下地の色(color: 赤)が現れ 明るい部分に別に定義した色 (blend: 緑) になる --- Rv, Gv, Bv, Av → テクスチャ環境関数の結果 Rt, Gt, Bt, At → テクスチャ色 Rf, Gf, Bf, Af → フラグメント色 Rc, Gc, Bc, Ac → テクスチャ環境色 (GL_TEXTURE_ENV_COLORを参照) --------------------------- // Multi Texture なら一番↓ ( TEXTURE0 ) から順に評価 [ ] <--- Texture [ ] <--- Texture [ ] <--- Texture [ ] <--- Fragment // 計算をするときは 次の 2 つが対象になる [ ] <---- 新しく貼ろうとしている Texture ( 基本形式 はこの Texture が対象 ) [ ] <---- 既に計算すみの Fragment 計算方法は 貼る対象の Texture の 内部フォーマットによって決まる Format は複数あるが 6 つの基本形式に分類される そして計算時は RGBA 形式に変換されて扱われる
GL_ALPHA 0, 0, 0, A GL_LUMINANCE 0, 0, 0, 1 GL_RGB R, G, B, 1 GL_RGBA R, G, B, A
GL_RBGA : 基本 Texture 形式


GL_MODULATE

各成分をかける( Alpha も乗算される )。 ライティング結果と乗算される デフォルトの設定。
out = src * texcol; Rv = Rf * Rt Gv = Gf * Gt Bv = Bf * Bt Av = Af * At



GL_DECAL

ステッカーを貼った効果を出す時に使う。 テクスチャのアルファ成分でマスクをする。 透明にしたい場所のアルファ値を 0 にしておく。 0ならば src の色となる。
out = texcol * texcol.a + ( 1 - texcol.a ) * src Rv = Rf * (1-At) + Rt * At Gv = Gf * (1-At) + Gt * At Bv = Bf * (1-At) + Bt * At Av = Af



GL_REPLACE

テクスチャの色で置き換える。 WARNING 利用すると, ライティング結果も無効になる。
out = texcol; Rv = Rt Gv = Gt Bv = Bt Av = At



GL_ADD

out = src + texcol



GL_COMBINE

演算子なども指定して細かく混色の方法を指定する。 次のような計算式を指定する。
out = arg0 演算子 arg1
次の要素を指定する。
// 算術演算子を指定する。 // 1番目の引数を指定する。 // 2番目の引数を指定する。
GL_RGB TIP 高速化のためには, Texture の内部 Format のサイズを小さくする 32bit -> 16bit におとす これをするには _EXT とつく 拡張フォーマットを使う // この式の [ 意.味 ] がわからん Rv = Rf * (1-Rt) + Rc * Rt Av = Af * At