Stage3D と 2 つのシェーダと頂点情報

前回の記事 (Stage3D の裏側のお話) では、GPU (Stage3D) が 3 角形の描画を得意とすること、描画処理が大きく 2 つの段階に分けられ、それぞれの段階にシェーダと呼ばれるプログラムが必要となること、までカバーしました。

今回は、シェーダの役割をもう少し詳しく確認してから、シェーダに頂点情報を渡す Stage3D の API の使い方に話題を移します。

頂点シェーダと断片シェーダ

GPU 描画では、2 種類のシェーダが使われます。頂点シェーダと断片 (ピクセル) シェーダです。

実行される順序は、頂点シェーダ → 断片シェーダの順です。頂点シェーダが各頂点の位置を確定すると、断片シェーダが頂点の間の断片 (ピクセル) を色づけします。

下の図は、直方体を 2 種類のシェーダそれぞれが処理する様子を示したものです。

shaders.jpg

頂点シェーダでは頂点の位置が変換されます。これで形状が決まります。

次は断片シェーダで面の塗りが決定されるのですが、断片シェーダへの入力は面 (3 角形) である必要があり、頂点のまま渡しても処理できません。そのため、頂点シェーダの出力から 3 角形を構成するプロセスが入ります。 (上の図の場合であれば、それぞれの面を対角線で半分にした 12 個の 3 角形で、直方体の形状を表すことになるでしょう)

実際に断片シェーダが扱うのは 3 角形内の小さな断片 (ピクセル) なので、断片シェーダを呼び出す前に 3 角形の断片化、すなわちラスタライズの処理も行われます。

ややおおざっぱですが、GPU 描画の場合の画像処理の流れは、

(頂点情報)→ 頂点シェーダ →(変換された頂点)→(3 角形)→(断片)→ 断片シェーダ →(色の決まった断片)

となります。あとは、3 角形がビューポートに含まれるかの判定が、ラスタライズ前に行われたりもします。

色の情報をシェーダに渡すには、頂点シェーダに入力として渡す頂点の情報に、座標だけでなく色も含める方法があります。その場合、頂点シェーダは、座標は変換しつつ、色の情報はそのまま次の処理に渡します。

(シェーダは自分で用意するプログラムなので、値を操作したければ行うのは自由です)

頂点の色情報はラスタライズ処理の際に使用され、生成される断片それぞれに、頂点からの距離に応じて補間された色が割り当てられます。例えば 3 角形の中心に位置する断片の色は、3 つの頂点の色の中間色になります。このようにして割り当てられた色情報を持つ断片が、断片シェーダへの入力となります。

(なので、本当は、上の図で "断片シェーダ" と記述された処理は、"ラスタライザ + 断片シェーダ" とするのが正確です)

断片の色の指定方法として、断片シェーダにテクスチャを渡して、ビットマップデータから色指定を行うという方法もあります。その他、光と影、表面の反射など、断片シェーダは最終的な見た目を決める役割を持っています。

頂点情報の指定

さて、ここからは具体的に、シェーダに頂点の情報をアップロードする手順を紹介します。

頂点シェーダへの入力は頂点の情報でした。Stage3D では Number 型の値の Vector として頂点の情報をまとめます。 (来年には Number が Float に置き換えられるという話もありますが... 2012 (2013?) 年 Flash 予報 - 機能編 その 2

var vertexData:Vector.<Number> = Vector.<Number>([
  -0.3, -0.3, 0, 1, 0, 0, 1, // x, y, z, r, g, b, a のフォーマット
  -0.3, 0.3, 0, 0, 1, 0, 1,
  0.3, 0.3, 0, 0, 0, 1, 1,
  0.3, -0.3, 0, 1, 0, 0, 1
]);

上の例では 4 つの頂点の情報が記述されています。頂点情報が、7 つの値の組み合わせになっているのは、座標に加えて、RGBA 値も記述しているためです。各行の最初の 3 つが座標、残りの 4 つが色とアルファ値です。

このような、座標や色のことを頂点属性と呼びます。今回のサンプルでは、2 種類の頂点属性が書かれていることを覚えておいて下さい。

頂点シェーダに渡す情報は、頂点バッファと呼ばれる構造にパッケージして GPU にアップロードします。その際、Stage3D では VertexBuffer3D というクラスを使います。下は、上で定義した vertexData を GPU にアップロードするコードの例です。

var vertices:VertexBuffer3D;
// 7つの値を持つ4つの頂点用の頂点バッファを作成
vertices = context3D.createVertexBuffer(4, 7);
// 上で定義したvertexDataの全データをアップロード
vertices.uploadFromVector(vertexData, 0, 4);

VertexBuffer3D のインスタンス生成時には、頂点の数と、頂点の属性の指定に使われている値の数を、引数に指定します。そのあと、uploadFromVector() でアップロードする時は、第 2 引数と第 3 引数で、Vector 内の何番目から何個の頂点をアップロードするか指定します。

さて、今回の頂点バッファには 2 種類の頂点属性が記述されていたのを覚えているでしょうか?

そうすると、この頂点バッファからデータを読み込む頂点シェーダは、2 種類の属性を扱うように書かれているはず...です。

そこで、Vector 内の Number 値の列を、頂点シェーダへの入力となる属性にマップしてあげます。そのためには、setVertexBufferAt() メソッドを使って、頂点バッファに対し、値の組み合わせ及びデータフォーマットを指定します。

// 最初の属性は座標の情報:Float型の数値が3つ
context3D.setVertexBufferAt(0, vertices, 0, 
  Context3DVertexBufferFormat.FLOAT_3);
 
// 次の属性は色とアルファ情報:Byte型の数値が4つ
context3D.setVertexBufferAt(1, vertices, 3,
  Context3DVertexBufferFormat.FLOAT_4);

setVertexBufferAt() の最初の引数は頂点属性の番号です。第 2 引数は頂点情報を持つ配列、第 3 引数は Number 値の何番目からが指定中の属性で使われるか、第 4 引数は属性の型です。型として指定できる値は Context3DVertexBufferFormat クラスに定義されています。

これで、頂点シェーダに渡す頂点情報は準備できました。

頂点インデックスの指定

GPU 描画では 3 角形を使って形状が表現されるのでした。Stage3D では、頂点バッファにデータを設定するだけでは、3 角形を定義することができません。そのため、インデックスバッファと呼ばれる構造を別途用意することになっています。

インデックスバッファには、3 つの頂点の番号の組み合わせを 1 つの単位として、複数の 3 角形の定義が並べられます。3 角形の頂点を指定する番号には、頂点バッファ内の順番 (インデックス) が使われます。

最初のサンプルコードで 4 つの頂点情報を記述しましたが、それらを、矩形を成す 2 つの 3 角形として扱うには、例えば以下のようにデータを定義します。

var indexData:Vector.<uint> = Vector.<uint>([
  0, 1, 2, // 頂点バッファ内の最初の3つの頂点
  2, 3, 0  // 最初の頂点と最後の2つの頂点
]); 

インデックスは常に 3 つで 1 組です。上の例では、2 つの組み合わせが定義されています。どちらにも共通するインデックスは 0 と 2 なので、頂点 0 と頂点 2 を結ぶ線が 2 つの 3 角形に共通の (つまりお互いが接する) 線ということになります。

これで頂点から面を扱えるようになりました。

このデータをインデックスバッファにアップロードするには IndexBuffer3D クラスを使います。IndexBuffer3D の利用方法は VertexBuffer3D と同じです。

var indices:IndexBuffer3D;
// 2つの3角形を定義するため6つの値を持インデックスバッファを作成
indices = context3D.createIndexBuffer(6);
// 上で定義したindexDataの全データをアップロード
indices.uploadFromVector(indexData, 0, 6);

IndexBuffer3D のインスタンス生成時には、必要なインデックスの数、つまり 3 角形の数 × 3 を引数に指定します。次の行の、インデックスバッファをアップロードする uploadFromVector() は、VertexBuffer3D でも使用したものです。

ということで、CPU 側が準備する 3D モデル情報は以上です。形状が複雑になると人手で準備するのは大変そうですね。

次はシェーダのアップロード手順と、AGAL の簡単な解説の予定です。

 

トラックバック(0)

トラックバックURL: http://cuaoar.jp/mt4/mt-tb.cgi/221

コメントする

2014年1月

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
レンタルサーバー

月別 アーカイブ

Powered by Movable Type 4.261