SAMPLE
シンプルテクスチャ
ドラックアンドドロップした 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 が可能
unsigned int 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] = (unsigned char)( 255 * myRand() );
texvol[i][j][k][1] = (unsigned char)( 255 * myRand() );
texvol[i][j][k][2] = (unsigned char)( 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
■ GL_COMBINE
演算子なども指定して細かく混色の方法を指定する。
次のような計算式を指定する。
次の要素を指定する。
// 算術演算子を指定する。
// 1番目の引数を指定する。
// 2番目の引数を指定する。
GL_RGB
TIP
高速化のためには, Texture の内部 Format のサイズを小さくする
32bit -> 16bit におとす
これをするには _EXT とつく 拡張フォーマットを使う
// この式の [ 意.味 ] がわからん
Rv = Rf * (1-Rt) + Rc * Rt
Av = Af * At