透過に対応

ousttrue2008-02-08

思ったより大変だ(画像のほっぺのぐるぐるが透明ぶぶん)

まずmqo形式の透明は、
模様画像にアルファチャンネルがついているもの(pngとかtgaで)と、
透明にグレイスケール画像(とは限らないが)を指定する2種類がある。

ひとつめに対応するのは簡単で、

glEnable(GL_ALPHA_TEST)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

とすることで対応することができる。ただし奥から順番に描画しないといけないのだがその件については後述。

ふたつめのアルファチャンネルが別画像になっているものはちょっと厄介でマルチテクスチャを使う必要がある(模様画像に透明画像を合成する手もあるな・・・)。
マルチテクスチャを使うにはテクスチャユニットを使う必要があって、
テクスチャユニットを使うにはテクスチャオブジェクトを使う必要がある。
言い換えると、
テクスチャユニット0に模様画像のテクスチャオブジェクトをバインドし、
テクスチャユニット1に透明画像のテクスチャオブジェクトをバインドする。
ここまでで形状のRGBAが準備される。

次が透明テクスチャを描画順によらずブレンドする問題。
これが意外と面倒で、
OpenGLプログラミングガイドによると不透明(アルファ値1.0)のものだけを先に描画して、
あとかから透明なものだけを描画する方法があるらしい。これは説明するよりコード見たほうが早いw

# 1st
glAlphaFunc(GL_EQUAL, 1) # 完全に不透明な部分だけを描画する
self.DrawScene(0) 
# 2nd
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glDepthMask(GL_FALSE) # Zバッファを読み出し専用に
glAlphaFunc(GL_NOTEQUAL, 1) # 透明な部分だけを対象に
self.DrawScene(1) 
glDepthMask(GL_TRUE)
glDisable(GL_BLEND)

この辺までくるとOpenGLレンダリングパイプラインとかDepthテスト、アルファテストにブレンド周りに
関する知識が必要になってくる。赤本必要。

以上で、OpenGLによるmqo読み込み実験はひとまず終了。
もう少し高速化するとか改善の余地はありますが・・・

完全なソースこっちに↓
http://gunload.web.fc2.com/opengl/sample03.html