■ 2004年09月15日 [OpenGL][テクスチャ] 第3回 テクスチャの合成
下地の色
前回のプログラムでは,ポリゴンにテクスチャを貼る場合にも glMaterialfv() を使って材質を設定していました.では,この材質によって決まるポリゴンの色は,そのポリゴンにテクスチャを貼ったときに,どのように扱われるのでしょうか.今回はポリゴンの色とテクスチャの色との合成について説明します.
アルファ値
これまで画像データの形式は,光の三原色(赤,緑,青)の3つの成分,すなわち RGB 形式で表していました.しかし,OpenGL が内部で色について処理する時は,RGBA という4つの成分を取り扱っています.この4つ目の成分 "A" は「アルファ値」と呼ばれ,一般に「不透明度」として扱われます.アルファ値は画像の合成の際に利用されます.
では,今まで使ってきたデータをもとに,RGBA 形式の画像を作成してみましょう.実は Photoshop Elements では,RGBA 形式の画像データのアルファ値(アルファチャンネル)を扱う(編集する)ことができません (GIMP や PictBear は可能).しかし,アルファ値を持った画像データを作ることは可能です.
まず,元の画像を開きます.そして,その画像の必要な部分だけを選択した状態にします.下図ではタイヤの周囲とホイールの穴の部分以外を選択しています.
つぎに,この選択範囲を保存します.
すると選択範囲に付ける名前を聞かれますから,適当に決めてください.
あとはこの第1回でやったように,この画像を RAW 画像として保存します.
RGBA 画像ファイルの読み込み
次に,画像の読み込みプログラムを,RGBA 画像を読み込むように変更します.1 画素あたり 3 要素だったものが,4 要素になるだけです.
・・・ /* ** 初期化 */ static void init(void) { /* テクスチャの読み込みに使う配列 */ GLubyte texture[TEXHEIGHT][TEXWIDTH][4]; FILE *fp; /* テクスチャ画像の読み込み */ if ((fp = fopen(texture1, "rb")) != NULL) { fread(texture, sizeof texture, 1, fp); fclose(fp); } else { perror(texture1); }
また RGBA 画像なら,1 画素のデータが 4 バイトとなるので,データはワード境界に配置されます.したがって,GL_UNPACK_ALIGNMENT に 4 が指定できます.
/* テクスチャ画像はワード単位に詰め込まれている */ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
そして,テクスチャを割り当てる際に,RGBA 画像として割り当てるようにします.
/* テクスチャの割り当て */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXWIDTH, TEXHEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); /* テクスチャを拡大・縮小する方法の指定 */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ・・・
ここまでできたら一度プログラムをコンパイルして実行し,今までと同じようにポリゴンにテクスチャが貼られることを確認してください.画像が RGBA 形式になっていなかったり,読み込みプログラムやテクスチャの割当の部分が画像の形式と一致していなかったりすると,つぶれたテクスチャが貼られてしまいます.
ポリゴンの陰影
雛形のプログラムでポリゴンをまわすと,テクスチャを貼っても,テクスチャを貼らないのと同じように,ポリゴンに陰影が付いていることがわかります.テクスチャを貼ったポリゴンの陰影付けは,まずテクスチャを貼り付けていないポリゴンに対して陰影付けを行い,その結果をテクスチャの色で「変調 (modulate)」することによって実現しています.
したがって,もとのポリゴンの材質を変更すれば,それはテクスチャを貼ったポリゴンにも反映されます.ためしに,もとのポリゴンの拡散反射係数を指定している変数 color に,赤色を設定してみてください.
・・・ /* ** シーンの描画 */ static void scene(void) { static const GLfloat color[] = { 1.0, 0.0, 0.0, 1.0 }; /* 材質 (色) */ /* 材質の設定 */ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); /* テクスチャマッピング開始 */ glEnable(GL_TEXTURE_2D); ・・・
すると,こういう具合に下地の色,すなわちポリゴンの色がテクスチャに反映されます.
テクスチャ環境
下地の色とテクスチャの色の組み合わせ方は,glTexEnvi() という関数で指定します.初期状態では,glTexEnvi() で GL_TEXTURE_ENV_MODE に GL_MODULATE が指定されている状態になっています.そこで初期化の関数 init () 内で,glTexEnvi() を使って GL_TEXTURE_ENV_MODE に GL_REPLACE を指定してみてください.すると今度はテクスチャの色が下地の色を完全に置き換えてしまいます.プログラムに太字の部分を追加してください.
なお,雛形のプログラムでは,下地の色はポリゴンの材質で決定されるものしかありませんが,複数のテクスチャを重ね合わせて使うマルチテクスチャでは,このテクスチャ環境が大きな意味を持ちます.
・・・ /* ** 初期化 */ static void init(void) { ・・・ /* テクスチャ画像はバイト単位に詰め込まれている */ glPixelStorei(GL_UNPACK_ALIGNMENT, 4); /* テクスチャの割り当て */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXWIDTH, TEXHEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); /* テクスチャを拡大・縮小する方法の指定 */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); /* テクスチャ環境 */ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); ・・・
- void glTexEnvi(GLenum target, Genum pname, GLint param)
- テクスチャの合成環境を設定します.引数 target は GL_TEXTURE_ENV である必要があります.引数 pname は GL_TEXTURE_ENV_MODE である必要があります.引数 param には GL_MODULATE, GL_DECAL, GL_BLEND, および GL_REPLACE が指定できます.初期値は GL_MODULATE です.
陰影は下地の色についていますから,この場合は陰影付けも反映されなくなります.ポリゴンを回して,色を確認してみてください.なお,プログラムの実行中にテクスチャ環境を変更しないなら,glTexEnvi() はテクスチャを割り当てた直後に実行すれば十分です.
それでは,次に GL_REPLACE を GL_DECAL に書き換えてみてください.
・・・ /* テクスチャ環境 */ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); ・・・
GL_DECAL では下地の色をすべてテクスチャで置き換えるのではなく,テクスチャ画像の選択範囲だけを置き換えます.したがって,選択範囲外には下地の色(ポリゴンの色)が現れます.
GL_BLEND を指定したときは画像のアルファ値は用いられず,かわりに画像の RGB 値が別に設定した色と下地の色との混合比として用いられます.この色は glTexEnvf() の pname に GL_TEXTURE_ENV_COLOR を指定して定義します.
・・・ /* テクスチャ環境 */ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); /* 混合する色の設定 */ static const GLfloat blend[] = { 0.0, 1.0, 0.0, 1.0 }; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blend); ・・・
- void glTexEnvfv(GLenum target, Genum pname, GLint param)
- テクスチャの合成環境を設定します.引数 target は GL_TEXTURE_ENV である必要があります.引数 pname は GL_TEXTURE_ENV_MODE あるいは GL_TEXTURE_ENV_COLOR が指定できます.pname に GL_TEXTURE_ENV_MODE を指定したときは,引数 param には GL_MODULATE, GL_DECAL, GL_BLEND, あるいは GL_REPLACE を格納した単一の実数値 (GLfloat 型) へのポインタを指定します.pname に GL_TEXTURE_ENV_COLOR を指定したときは,引数 param には RGBA 値を格納した4要素の GLfloat 型の配列が指定できます.
この出力画像では,テクスチャの暗い部分に下地の色(color: 赤)が現れ,明るい部分に別に定義した色 (blend: 緑) が現れています.