カラーキーを超える者
![]()
![]()
![]()
・知らなかった機能
カラーキーを超える者(者じゃないが)を見つけたのは、前回の「ブレンドファクター121」でDestのα値について(結局わからずじまい)調べている途中、今まで疑問に思っていた「Zテストにも似たなんか」を見つけたので、「これがα値の手がかりになるか?」と期待して調べた時でした。DirectX6SDKのサンプル"Billboard"で使用されていたそれは、「D3DTextr(SDKに入ってる、テクスチャを使いやすくするもの)が透明色に何故カラーキーではなくαビットを使っていたのか?」「CAPSでZテストと同じD3DCMPFUNC列挙型が検出されている機能の正体」という疑問を一度に解決してくれるような機能でした。しかも、その機能の使いようによってはカラーキー以上の効果が可能です。
DirectX5日本語ヘルプにZバッファについては記述してありましたが、それについては詳しく記述されてなかったから全然知りませんでした。それに誰かが使ってるっていう話も聞いた事無いし……。
・まず、カラーキーとは?
カラーキーというのは、テクスチャに透過色を指定して、その透過色の部分は描画をしない機能の事です。DirectDrawを使った事がある方なら知ってると思いますが、機能は同じです。
使い方は、まずテクスチャのサーフェイスにどの色がカラーキーかを設定します。この設定もDirectDrawのカラーキーと同じです。そして、描画する時にSetRenderStateでD3DRENDERSTATE_COLORKEYENABLEにTRUEを指定するとカラーキーの有効なポリゴンの描画ができます。
黒をカラーキーに設定する→
その結果カラーキーを使えば、木や球などポリゴンだけで表現しようとするとかなりのポリゴン数になるような物体も、四角のポリゴン1つで表現できます。
四角のポリゴン2枚だけ。
三角ポリゴンなら4枚これについては後々、「ビルボードのいろは」で有効な使い方などを書く予定です。
あと、ポリゴン数を増やさずに穴を空けるなんてのも容易にできます。
立方体→
カラーキーで穴の空いた
テクスチャを使って描画
他にも変わった使い方ができそうですね。
・カラーキーとαビット付きテクスチャの違い
色を透明にするならテクスチャにαビットを使っても可能ですが、カラーキーを使うとちょっと違います。
カラーキーの良い所。透過色部分はZバッファに書き込まない。
αビットによる透過色だと、αビットの内容に関わらずZバッファに書き込む値は普通のポリゴンと一緒ですが、カラーキーを使えば透過色部分はZバッファに書き込みません。
この描画位置で、
背景→手前のポリゴン→
奥のポリゴンの順に描画
(数字は描画の順番)
カラーキー
手前と奥のポリゴンの
描画順が逆でも結果は同じ![]()
αビットによる透過。
手前→奥の描画順だとこうなる。
奥→手前なら描画結果は
カラーキーと同じα値を使った透過だと、結果が描画順番に依存してしまいます。奥→手前の順に描画すると正しく描画できますが、それにはZソートが必要になります。カラーキーなら描画順番に関わらず正しく描画できます。
カラーキーの悪い所。テクスチャのフィルタリングとの相性が悪い。
バイリニアフィルタリング(bi-linear filtering:双曲線補間)を使うとテクスチャのドットが補間されます。すると、描画される物体の縁にカラーキーの対象の色が若干見えます。カラーキーが黒なら、黒く縁取られたような感じに。
この白い四角の
部分を2倍に拡大→
フィルタリング無し
まぁ普通に拡大
されてますな![]()
RGB Emulation+双曲線補間
縁の部分が点描
HAL(GA-RUSH6)+双曲線補間
補間のせいで縁が黒くて
その分だけちょっと太い
αビットによる透過+双曲線補間
α値も補間されて他に比べて
割と自然だが、描画順に依存今回も減色のせいで変な所もありますが、気にしないでください。
この場合は縁が黒っぽくなってますが、カラーキーが白なら縁も白っぽくなります。
HALの場合は縁がどうなるかは3Dボードの種類やドライバによります。カラーキーの色が補間された部分も透過の対象にしたり(縁の分だけ小さくなる)、補間されて少しでもカラーキーの色と違ったらカラーキーの対象外になったり(縁が妙に太くなる。見栄えは悪い)。古い物ではカラーキー自体が使えない3Dボードもあります。
RGB Emulation(DirectX6)だと点描が使われるとは知らなかった。変な所凝ってますね。いや、悪いわけじゃないですが。
ミップマップについては試してませんが、やっぱり使わない方が無難なんでしょうか。HALだと3Dボードによっていろいろ違ってくるだろうし。
縁がカラーキーの色になるのが嫌な場合は、それでも我慢するかバイリニアフィルタを使わないかの2択でしょうね。カラーキーは使わずαビットを使うという方法もありますが、Zバッファがねぇ……。
でも、カラーキーよりも縁を滑らかに色も正確にZバッファへの書き込みも表示通りに、そしてカラーキーよりも自由に多彩に表現ができる機能があります。これで選択肢も3択。
・αテスト
ZバッファのZ値と描画するポリゴンのZ値を比較して描画するかしないかを決める処理はZテストといいますが、Direct3Dには設定されているα値と描画するポリゴンのα値を比較して描画するかしないかを決める処理があります。それがαテストです。αテストは、α合成を使わなくても使用できます。
ZテストはZバッファに書き込まれている値との比較ですが、αテストは比較する値を決める事ができます。
IDirect3DDevice3::SetRenderState( D3DRENDERSTATE_ALPHAREF, D3DFIXED );
D3DFIXEDの部分が比較するα値で、0〜255の数を設定します。
比較の仕方はZテストと同じで、比較関数の設定もZテストと同じです。IDirect3DDevice3::SetRenderState( D3DRENDERSTATE_ALPHAFUNC, D3DCMPFUNC );
D3DRENDERSTATE_ZFUNCがD3DRENDERSTATE_ALPHAFUNCになっているだけです。
D3DRENDERSTATE_ALPHAFUNCで設定する比較の種類はD3DCMPFUNC列挙型で定義されています。
なんだかいろいろありますが、LESS(未満)とEQUAL(イコール)とGREATER(超える)の組み合わせです。D3DCMPFUNC列挙型
D3DCMP_NEVER D3DCMP_LESS
D3DCMP_EQUAL
D3DCMP_LESSEQUAL
D3DCMP_GREATER
D3DCMP_NOTEQUAL
D3DCMP_GREATEREQUAL
D3DCMP_ALWAYS
常に失敗 Dest > Src の時成功
Dest == Src の時成功
Dest >= Src の時成功
Dest < Src の時成功
Dest != Src の時成功
Dest <= Src の時成功
常に成功
以下D3DRENDERSTATE_とD3DCMP_を略します、便宜上。
Srcがポリゴンのα値、DestがALPHAREFで指定された値になります。
例えばALPHAFUNCでGREATEREQUALを指定すると、ALPHAREFで指定されたα値以上の部分は描画します。
例。
この白い四角の
部分を2倍に拡大→
カラーキー+フィルタリング無し
手前のテクスチャはギザギザ
(奥のは遠い&うまく減色
できたので目立ってないが)![]()
ALPHAREFは0xff
透過部分はフィルタ無し
+カラーキーと同じだが
フィルタが効いている
ALPHAREFは0x90
α合成は使用してない。
α値も補間されてるため
ギザギザが滑らかにうまく説明できてませんが、使えばわかるでしょう。カラーキーだと、バイリニアフィルタを使ったら黒くなったり縁が太くなったり3Dボードによって結果が違ったりしますが、αテストならフィルタリングしながらフィルタ無しのカラーキーみたいな透過にしたり、滑らかにしたりできます。しかもカラーキーと同じく透過部分はZバッファに書き込まない!何故こんな便利な機能が今まで使われなかったのか……。DirectX5のHELだとα値が使えなかったんでしょうか?
問題点。カラーキーよりも対応ハードは少ないでしょうね。マイナーな機能ほどちゃんと実装されてないし。CAPSを調べて、αテストが使えない場合は素直にカラーキーを使いましょう。あとαビット付きテクスチャが使えないとαテストの実用性も格段に下がります。
ちなみに、DirectX6のRGB Emulationでポリゴンのα値が1.0(0xff)で、ALPHAFUNCにGREATEREQUALを設定(つまり0xff以上なら描画。なので0xffでも描画という設定)した時、ALPHAREFが0xffでαテストをすると何故か描画されません(RGB Emulation以外だとちゃんと描画される)。ALPHAREFが0xfeだと描画されます。α値が1.0(0xff)でも0xfe扱いにになるんでしょうか?
他にもピクセルフォーマットや精度の問題とかがありそうなので、αテストではEQUALとNOTEQUALの使い方はある程度限られてくるでしょうね。
・物体以外にも使おう
αテストはなにもカラーキーと同じ事しかできないわけではありません。テクスチャのαビットを利用するといろいろな事ができると思います。
自分の思い付いた手法では、画面の切り替えに使うと効果的かと。
まずαビット付きテクスチャを作成して、RGB値は切り替わった後の画面にして(一枚絵か、レンダリングした絵をテクスチャにコピー)、α値は白から黒の部分の順に描画されるようにします。そして、ALPHAREFを0xffから0まで変化させる事により、画面を一気に書き換えずいろいろな書き換え方ができるようになります。
αビットがこうだと、
右から左へ
書き換えていく
真ん中から広がって
いくように書き換え![]()
時計回りに書き換えこの絵のような書き換え方はほんの一例で、もっともっと凝った表現が可能です。F-ZEROXのタイトルが出る時みたいなのも実現できます(持ってないとわからないですが)。
やろうと思えばカラーキーでもできますが、DirectDrawなら実用性はあってもDirect3Dだといろいろ制限があって実用性が低いです。αテストならαビットとRGBのビットを別々に使えるので、簡単にできます。
これ以外にも、αテストはいろいろな使い方ができるような可能性を秘めています。例えば、αビットをαテストを使いながら、α合成を同時に使うという事もできるので、先程の画面切り替えと前回やったα合成による色の反転を使えば、ジワジワと色が反転していくなんてこともできます。いろいろと考えてみましょう。
![]()
![]()
![]()
written by Y.Ohde e-mail : oode@alles.or.jp