チュートリアル33

ポリゴンモード、カラー、ブレンド


前のチュートリアルでは、JitterにおけるOpenGLシーンを構築するため、カメラやGLグループのオブジェクトの位置を調整する方法について見てきました。このチュートリアルを理解した後には、空間的な位置によって選ばれたGLグループオブジェクトのポリゴンを隠したり、選ばれたポリゴンを塗り潰されたモデルやワイヤーフレームモデルで描いたり、アンチエイリアシングやブレンディングを用いてドローバッファに結果を加えたりすることができるようになるでしょう。

・Jitter Tutorialフォルダにある33jPolyColorBlend.patというチュートリアルパッチを開いて下さい。そして、“Start Rendering”というラベルが付いているtoggleボックスをクリックしてください。

チュートリアルパッチのpwindowにあるグレーの球が見えるはずです。それは、jit.gl.gridshapeオブジェクトによって描画され、回転がコントロールできるようにjit.gl.handleオブジェクトに繋がっています。jit.gl.handleオブジェクトのauto_rotateアトリビュートがオンなので、球を一度回転させれば、設定されている軸に沿って回転し続けるでしょう。もし、試してみたければ回転を加えてみてください。


グレーの球


ワイヤーフレームモードと表面の選択

例のパッチの中で、“OpenGL Objects to Render”というラベルのすぐ下にpak poly_mode 1 1というオブジェクトがあります。このオブジェクトは、jit.gl.gridshapeオブジェクトのポリゴンモードアトリビュートを設定するメッセージを生成します。

・pak poly_modeオブジェクトにある両方のtoggleオブジェクトをクリックしてください。グレーの球がワイヤーフレームモードで見えるでしょう。


ワイヤーフレームモードでの球


ワイヤーフレームモードをオンに切り替えることで、この場合には四角形のポリゴンを使った球に近い形のjit.gl.gridshapeオブジェクトがはっきりと見えるようになります。OpenGLで描かれたすべてのポリゴンには表の面があり、それは、頂点が時計方向にポリゴンを囲むように見える側として定義されています。そのため、一つのシーンでの各ポリゴンは、表の面がカメラの方向を向いているのか逆を向いているのかによって、前向き、後ろ向きのどちらかに分類されます。

OpenGLは、前向きか後ろ向きのポリゴンのどちらかを自動的に隠すことができます。それは、描画の高速化にとても貢献し、映像化されるデータの特定の側を目立たせます。Jitterでは、cull_faceアトリビュートを使って、オブジェクト毎の方法でポリゴンの可視性をコントロールすることができます。

・prepend cull_faceオブジェクトの上のナンバーボックスに1を設定してください。


球の前向きポリゴン

GLグループオブジェクトのcull_faceアトリビュートは、0、1、または2に設定されます。0の設定は、オブジェクトのすべてのポリゴンを表示します。1の設定は、球の後ろ向きポリゴンを隠します。2の設定は、前向きポリゴンを隠します。いまの1の設定では、ワイヤーフレームの球は中空でないように見えます。なぜなら、その隠れた線、それは中空でない素材で作られた球なら見えないポリゴンの辺ですが、それが描画されていないためです。その回転(球を回転させてみましたか?)は、現実世界の中空でないオブジェクトを説得力のある表現で描きます

・prepend cull_faceオブジェクトの上にあるナンバーボックスに2を設定してください。


球の後ろ向きポリゴン

今度は球の前向きポリゴンが隠されています。それは、まるで球を通り越して、あなたの方を向いた内部の面だけが見えているようなものです。この画像からは遠近感が何か奇妙だと感じられるでしょうが、このパッチでの回転を見れば、そのシーンが“普通”には描画されていないことがとてもはっきりします。

一般的にcull_face 1の設定は、中空でない球のような凸状オブジェクトでの隠れるポリゴンをうまく消去します。しかし、中空のオブジェクトでは、前向きと後ろ向きのポリゴンの組み合わせが見えてしまうかもしれません。

・すべてのポリゴンを表示するため、prepend cull_faceオブジェクトの上にあるナンバーボックスに0を設定してください。pak poly_modeオブジェクトの上にある左側のtoggleボックスを1(オン)にして、右側のtoggleボックスに0(オフ)を設定してください。prepend shapeオブジェクトの上にあるubumenuを"opencylinder"に設定してください。


ワイヤーフレームの前向きポリゴンと無地の後ろ向きポリゴンのオープンシリンダ(中空の円筒)
(訳注:原文では前と後ろが逆になっているが、誤りだと思われる)

この新しい形を使うことで、前向きと後ろ向きのポリゴンの違いがわかるようになります。2つの整数aとbを与えるpoly_mode a bメッセージは、aが1ならば前向きポリゴンをワイヤーフレームモードに設定し、bが1ならば後ろ向きポリゴンをワイヤーフレームにします。


RGBAカラー

GLグループのオブジェクトの色は、color [R] [G] [B] [A]というメッセージを使うことによって指定され、Rは色の赤要素、Bは青、Gは緑、Aはアルファや不透明度の要素です。すべての値の範囲は0から1です。

pak color...オブジェクトの上のナンバーボックスオブジェクトを1., 0., 0., 0.5の値に設定して下さい。これは不透明度が50%の純粋な赤を指定します。

シリンダーの色が赤に変わるのが見えるでしょう。しかし、不透明度の変化は見えません。これは、ブレンディングというドローバッファにおけるその前の色との混合が、デフォルトでオフにされるからです。

jit.gl.gridshapeオブジェクトのブレンディングをオンに切り替えるために、blend_enable $1のメッセージボックスの上にあるtoggleボックスをクリックして下さい。次のようなものが見えるはずです。


ブレンディングが有効になった赤いシリンダ

ARGB対RGBA:もし、すでにJitterのビデオ操作オブジェクトを使ったことがあるなら、それらのオブジェクトの色は、プレーンに格納されてA、R、G、Bの順のアーギュメントで指定されることをご存知かと思います。GLグループのオブジェクトでの順番は、RGBAであり、アルファが最後です。これは奇妙に見えるかもしれませんので、少し説明します。Jitterオブジェクトは、OpenGLとビデオの両方の分野で、できる限り元来の形式に近くなるように関係付けられています。OpenGLはRGBAフォーマットでオブジェクトの色と頂点を格納しています。また、QuickTimeはARGBフォーマットで画像を格納しています。そして、Jitterオブジェクトにはこれが反映されています。もし、あなたのパッチでOpenGLとビデオのマトリックス処理を組み合わせるなら、packunpackjit.packjit.unpackオブジェクトは、その2つのシステムを変換するための簡単な方法を提供します。planemapアトリビュートを1 2 3 0に設定した jit.matrixオブジェクトを通してマトリクスを送ることによって、char値のマトリクスをARGBからRGBAへ変換することも可能です(1つだけですべてのプレーンを効果的にシフトします)。チュートリアル6では、jit.matrixオブジェクトのplanemapアトリビュートを使ったさらに多くの例を示しています。


色と残像を消す

いま、jit.gl.renderオブジェクトがeraseメッセージを受け取るたびに、描画バッファはデフォルトの消去色であるダークグレイで塗り潰されます。rendererオブジェクトの上のRGBAのナンバーボックスを使い、異なった消去色に設定できます。

jit.gl.renderオブジェクトの上のナンバーボックスオブジェクトに0、0、0.5、0.1を設定して下さい。

背景はダークブルー(赤 = 0, 緑 = 0, 青 = 0.5)に変わります。もしシリンダーが回転しているなら、画面中の残像も見えるでしょう。これは背景が0.1の不透明度で消去されているからです。ダークブルーのピクセルが、描画バッファに存在するピクセル上に描かれるとき、それは10分の1のダークブルーと10分の9の前にあった何かの色が重なった結果のようになります。それによって、前のフレームが完全に消去されるまでには、いくらかの時間がかかります。完全には不透明でない描画色を見るためには、blend_enableアトリビュートが設定されなければなりませんが、完全には不透明でない消去には、それが不要だということに注意してください。


回転するシリンダー、残る残像


ブレンドモード

GLグループオブジェクトのblend_enableアトリビュートがオンのとき、各ピクセルはブレンド機能を使う描画バッファに入れられます。ブレンド機能は画像合成の基本的な処理です。それは、新しいピクセル、そのソース、既存のピクセルの上書き、ディスティネーションの適用をコントロールします。この機能はソースブレンディングファクタ、ディスティネーションブレンディングファクタの2つの部分からなります。ソースブレンディングファクタは、最終的な画像に対してソースの割合がどのくらい含まれるべきかを指定します。ディスティネーションブレンディングファクタは、ディスティネーションの割合を指定します。

Jitterでは、11のブレンディングモードが利用可能です。いくつかはソースに対してのみ適用され、ディスティネーションに対してのみのもの、両方に対してのものもあります。各モードは、赤、緑、青、アルファに対する乗数の様々なセットを指定します。blend_mode [src_factor] [dest_factor] メッセージは、GLグループの任意の描画オブジェクトに対する両方のファクタを指定することができます。

ブレンドモード:ソースとディスティネーションのブレンドファクタはRGBAの4つで、それらはソースとディスティネーションピクセルのRGBA値によって要素別に乗算が行われます。対応するソースやディスティネーションの要素は、加算されてから、出力ピクセルを生成するために[0, 1]の範囲に狭められます。

この表では、ブレンドファクタがどのように計算されるかを示します。"Mode" の列は、blend_mode [src_factor] [dest_factor] のJitterメッセージの中に値を記述します。"OpenGL name" の列は、モードの名前です。"Relevant to" の列は、ソースファクタ、ディスティネーションファクタ、もしくは両者に適用できるモードかを示します。最後に "Blend Factor Equation" の列はピクセルを計算するために使われる実際の式を示しています。添え字のsとdは、それぞれソース要素かディスティネーション要素かを表します。例えば、Rsはソースピクセルの赤の要素を表します。

Mode OpenGL name Relevant to Blend Factor Equation
0 GL_ZERO both (0, 0, 0, 0)
1 GL_ONE both (1, 1, 1, 1)
2 GL_DST_COLOR source (Rd, Gd, Bd, Ad)
3 GL_SRC_COLOR destination (Rs, Gs, Bs, As)
4 GL_ONE_MINUS_DST_COLOR source (1, 1, 1, 1)-(Rd, Gd, Bd, Ad)
5 GL_ONE_MINUS_SRC_COLOR destination (1, 1, 1, 1)-(Rs, Gs, Bs, As)
6 GL_SRC_ALPHA both (As, As, As, As)
7 GL_ONE_MINUS_SRC_ALPHA both (1, 1, 1, 1)-(As, As, As, As)
8 GL_DST_ALPHA both (Ad, Ad, Ad, Ad)
9 GL_ONE_MINUS_DST_ALPHA both (1, 1, 1, 1)-(Ad, Ad, Ad, Ad)
10 GL_SRC_ALPHA_SATURATE source (f, f, f, 1); f = min(As, 1-Ad)

OpenGLグループの全オブジェクトでのソースとディスティネーションのデフォルトブレンドモードは、それぞれ6と7です。これらは、GLブレンドファクタのGL_SRC_ALPHAとGL_ONE_MINUS_SRC_ALPHAに対応します。これは非常に一般的に使われるブレンド操作で、他のものは不要かもしれません。ソースのアルファ値を変化させることで、ソースとディスティネーション間の直感的なクロスフェードを可能にします。

他の値は、物理的な対応を持たない特殊効果はもちろん、さまざまな現実世界のライティング状況をシミュレートするためにも役に立ちます。

jit.gl.renderオブジェクトの上にあるRGBAのナンバーボックスオブジェクトはerase_colorアトリビュートを制御するものですが、これに1.0、1.0、0.5、1.0の値を設定してください。これは背景色を黄色にし、軌跡は消去するように設定して、ブレンド効果をさらに見やすくします。

pak blend_modeオブジェクトの上にある左と右のナンバーボックスに、それぞれ0と6(訳注:原文では0と7だが誤りと思われる)を設定してください。これはGL_ZEROのソースブレンドファクタと、GL_SRC_ALPHAのディスティネーションブレンドファクタを指定します。


blend_mode 0 6(訳注:原文ではblend_mode 0 7だが誤りと思われる)に設定したシリンダ

このblend_modeが、ここで見られる画像をどのように生成するのかを検討してみましょう。ソースファクタはGL_ZEROです。これはソースピクセルのすべての要素に0が乗算されることを意味し、ソースピクセルは何のエフェクトもかかりせせん。シリンダに対して異なったRGBの値を試してみることで、これを確認することができます。それらはすべて同じ色を生成します。

ディスティネーションファクタはGL_SRC_ALPHAです。上記の表を見ると、(As, As, As, As)というブレンドファクタの式を見つけることができます。ディスティネーションピクセルの各要素は、ソースピクセルにソースファクタ(この場合は0)をかけたものが加算される前に、ソースのアルファ(この場合は0.5)が乗算されます。そして、ピクセルの各描画時に、 その輝度は1/2に減少させられます。


アンチエイリアシング


OpenGLがポリゴンや線を描くとき、ラスタの格子上のピクセルを塗り潰すことで、それらの理想的な幾何学的形状に近づけます。この処理は、デジタルオーディオでの理想的な波形の再現に似た問題になりがちです。理想的な画像に含まれない空間周波数、すなわちエイリアシングが、離散的なピクセルから再構成されることで発生するのは避けられないでしょう。このエイリアシングは、特に水平や垂直に近い線や端において、一般的に"ジャギー"として知られるものとして見られます。

OpenGLは、ジャギーを減少させるために、いくつかのアンチエイリアシング技術を有しています。Jitterでは、オブジェクトのGLグループのアトリビュートを使うことで、これを可能としています。これらのアトリビュートを使うことで、GLグループの任意のオブジェクトが描画されるときに、アンチエイリアシングを使用するように指定することができます。

・jit.gl.gridshapeオブジェクトにantialias 1のメッセージを送るため、antialiasing $1というメッセージボックスの上にあるtoggleボックスをオンにしてください。


アンチエイリアシングオフ


アンチエイリアシングオン


アンチエイリアスされた線は、見た目が滑らかで太めになります。描画は一段と遅くなるので、描画速度を考慮するなら、見た目の改善が時間の増加に見合う価値があるかどうかを判断しなければなりません

OpenGLにおけるアンチエイリアシングの挙動は実装に依存しています。これは、アンチエイリアスをかけようとしたときに正確には何をするのかということについて、OpenGLハードウェアやドライバのメーカーが多少の自由度を持つということです。上の図において、例えば線上のジャギーが減少しているのに、左下のポリゴンの境界は同じように見えることに注意してください。アンチエイリアスをオンにしたとき、Jitterはポリゴンの境界がアンチエイリアスされるように要求します。しかし、これらの図を生成した特定のOpengGLの実装(ATI Rage 128アクセラレータとそのバージョン5.9.8のドライバ)は、この点では役に立っていません。あなたのマシンでの実装は異なっているかもしれません。


まとめ

前向きと後ろ向きのポリゴンについて説明し、ソリッドとワイヤーフレームの両方のモードでそれらをどのように描画するかを見てきました(poly_modeとcull_faceアトリビュートの使用)。レンダラーのerase_colorアトリビュートと、軌跡の描画のためのその利用についても紹介しました。不透明度およびブレンドモードを考慮し、ソースピクセルが描画バッファーディスティネーションに適用されるとき、何が起こるか詳細に定義しました。そして最後に、便利ではあるけれど若干予測できないOpenGLのアンチエイリアスの特性を紹介しました。