頂点

ゲーム製作日誌 プログラム編 No.10-3 「GPUにヘルプを渡す」


 前回は画面に表示させる頂点をデータとして用意したので、今回はそれをGPUにも読んで解釈できるように、読み方(ヘルプ)を伝える処理を扱っていきます。


1,頂点の構成情報をまとめる意味とは


 前回、頂点一つ一つを構造体としてまとめてデータを作成しました。それを実際に三角形の描画を行うGPUに転送する必要があります。

vertexwhat
 しかし、転送するときは頂点一つ一つを区切ってわかるように書き込まれるのではなく、すべての頂点が連続してメモリに書き込まれていきます。また座標や色等のデータも続けて書き込まれるために、もはやデータが送られてきたGPUにはどこをどう読めばいいのかわからない状態になってしまいます。


vertexgive
 それでもGPUに、読み方の指南書を渡してあげれば話は別です。上図のような情報を与えておけば「0~12の位置に座標が書いてあって、12~28には色が書いてあるんだな」と解釈できるわけです。
 そのため、頂点の座標や色がどの部分に書き込まれているのかを事前にGPUに伝えることが必要となるのです。今後はその情報のことを「頂点の構成情報」と呼びますが、まずはその情報の作り方から見て行きましょう。



2,頂点の構成情報を作る

 頂点の構成情報を作るためには、まず頂点の構成要素(座標や色)一つ一つがどこに書き込まれていて、どんな役割を持つのかをVertexElementを作成して決めていきます。


VertexEle
 これがVertexElementのコンストラクタです。いま気にするべきは2,3,5行目です。
 
  • 2行目には、データが始まる番地を書く
    vertexgive
    例えば、座標はこの表でいうと「0」番目から始まっています。ですので座標用のVertexElementを作成するときは、2行目の引数を「0」に設定するわけです。色でしたら「12」になりますね

  • 3行目には、データの型を書く

    データの型は、C#でいうint,float,string等と同じものです。3つ要素(xyz)があるものなら「.Float3」と、4つ要素(rgba,xyzw)があるものなら「.Float4」と設定します。つまり座標なら3の方で、色なら4ですね。

  • 4行目には、使用目的を書く

    座標だったら「Position」とか、色だったら「Color」と書いておきます。まんまです。


 まとめると以下の様な定義をしてあげれば良いわけです。
//座標用
new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0)

//色用 new VertexElement(0, 12, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.Color, 0)


 次に、作った情報をすべて配列にまとめます。その際、配列の最後の要素には終わりの合図としてVertexElement.VertexDeclarationEndをいれておきます。作った配列は、前回作った頂点構造体の中に入れておくと扱いが楽です。
[StructLayout(LayoutKind.Sequential)]
public struct PositionColor
{
    public Vector3 Position;
    public Vector4 Color;
    public static readonly VertexElement[] Elements =
{
new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), new VertexElement(0, 12, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.Color, 0), VertexElement.VertexDeclarationEnd
}; }


 ここまでで作ったVertexElement配列を使って、VertexDeclarationというものを作成します。これがGPUに与える指南書になります。VertexDeclarationは、Direct3D9デバイスを初期化してからでなければ作れません。
VertexDeclaration vertexDec = new VertexDeclaration(D3Device, PositionColor.Elements);


4,まとめ

 GPUには、頂点データを連続的に書き並べたバイト列のみが転送されてくるため各要素の位置や意味をそれだけでは解釈することができません。
 そこで、あらかじめ解釈するためのヘルプのようなものを渡しておくことで、GPUにも頂点の意味を理解することが可能になります。今回は、そのヘルプの作成の仕方を扱いました。
 次回は、解釈の仕方が分かったGPUに頂点データを送ってみようと思います。

P.S.
 今回が一番の山場だったので次回は今回苦労した分楽になる予定?
 

ゲーム製作日誌 プログラム編 No.10-2 「頂点配列の用意」


 Direct3Dの複雑さが見えた前回に引き続き、今回は画面に表示させる頂点の用意をするところまで解説していきます。


1,頂点の構造体を用意する


 画面に三角形を描くことを目的としているため、まずはどのような三角形を描くかを定義する必要があります。

 Direct3Dでは、三角形自体に情報を与えずにそれを構成する3つの頂点1つ1つに情報を与えてそのような三角形にするのか定義します。

tri_vertex


 3つの頂点に別々に情報を与えて描画させると、Direct3Dは点の間の情報を補間して三角形内部の様子がしだいに移り変わっていくように描画してくれます。図の場合は色がグラデーションがかかったかのように描画されています。点の色を変えるだけでグラデーションできるなんて簡単でいいですね。

 この情報の補間機能ですが、色だけではなくほかにもテクスチャ座標や法線ベクトル等にも適応されます。そのことは今後扱っていきましょう。




 さて、三角形を作るには頂点を決めればいいということなので、まずは頂点1つをあらわす構造体を作成します。


[StructLayout(LayoutKind.Sequential)] public struct PositionColor { public Vector3 Position; public Vector4 Color; }

 Vector3やVector4型は、実数型floatを数個そなえているもので座標や色をあらわすときに使います。座標であれば順にx,y,zと割り当て、色であればr,g,b,aというように割り当てます。

 つまり、この構造体は頂点に座標と色を与えることができるそういった定義なわけです。


 構造体の前につけた
[StructLayout(LayoutKind.Sequential)]
は構造体の中身をメモリに記録する時に、定義した順に配置することを約束する属性です。おまじないなのでつけておきます。




2,頂点配列の作成

 構造体を定義し、頂点を表すことができるようになったため描画したい三角形の3つの頂点を表現したいと思います。

PositionColor[] tri_vertices = new PositionColor[3];

tri_vertices[0] = new PositionColor();
tri_vertices[0].Position = new Vector3(0f, 0.5f, 0f); //上
tri_vertices[0].Color = new Vector4(255f / 255f, 201f / 255f, 14f / 255f, 1f); //オレンジ

tri_vertices[1] = new PositionColor();
tri_vertices[1].Position = new Vector3(-0.5f, -0.5f, 0f); //左下
tri_vertices[1].Color = new Vector4(255f / 255f, 201f / 255f, 14f / 255f, 1f); //オレンジ

tri_vertices[2] = new PositionColor();
tri_vertices[2].Position = new Vector3(0.5f, -0.5f, 0f); //右下
tri_vertices[2].Color = new Vector4(255f / 255f, 0f / 255f, 0 / 255f, 1f); //赤

 先ほど定義した構造体の要素数3の配列を作成し、3つの頂点を決めました。座標や色は以下の形式に従って入力していきます。
vertex.Position = new Vector3(X座標, Y座標, Z座標);
vertex.Color = new Vector4(赤成分, 緑成分, 青成分, 透明度);
 ここで注意しなくてはならないことは、色成分は0~1の範囲に直さなければいけないことと、XYZ座標空間が多少変わっていることの2点です。
proj_space
 黒枠は、画面の枠です。そうしたとき画面の左上が(-1,1)、右下が(1,-1)となるような空間が設定されていてそこに三角形を配置していくことになります。間違っても画面のピクセル座標にあわせないようにしてください。

 この変わった座標配分の話は、今後変換行列のところですることになると思います。




3、まとめ

 今回で表示する三角形の頂点を定義することができました。次回はこの配列のデータをグラフィックボードに転送する処理を扱っていきます。

ゲーム製作日誌 プログラム編 No.10-1 「ポリゴン描画の全体の流れ」


 今回と次回では、Direct3Dを使って画面に三角形を描画するまでを扱っていきたいと思います。やることにしては意外とやることが多く、また後々の基本になることになるので何回かに分割して説明していきます。


1,ポリゴン描画の流れ

 「ポリゴン」とは、複数の点を結んだ線で囲まれた多角形のことを言います。

 例えば「三角ポリゴン」といえば、3つの頂点を結んだ三角形のことでして、今後はその三角形のみを扱っていきます。なぜ三角ポリゴンしか使わないかといえば、自分たちが使おうとしているDirect3Dが三角形の表示しか扱っていないからです。基本的にどんな図形でも三角形を何個も並べれば形作れるのでそういう仕様になっているのでしょうね。

polygon


 そんな三角形をDirect3D9で描画するには以下の手順を踏まなければいけません。

  1. 頂点自体のデータを用意する

    ・頂点1要素を表す構造体を定義する

    ・構造体の配列を作って全頂点のデータを作成する


  2. 頂点データが記録された位置を定義する

    ・頂点の各項目がどの位置に記録されているかをVertexElementで指定する

    ・指定したVertexElementでVertexDeclarationを作成する


  3. 頂点をグラフィックボードに送るための準備

    ・専用の格納場所VertexBufferを作成する

    ・頂点の配列をVertexBufferに書き込む


  4. 頂点を画面に表示するためのシェーダを用意する

    ・シェーダをコンパイルする

    ・シェーダの実体であるEffectを作成する


  5. 画面に描画する

    ・描画対象の空間(世界)の状況を設定する

    ・描画する


  6. 不必要なものを破棄する

    ・VertexBufferとVertexDeclarationとEffectを破棄する



 全体的に見ても、たかが三角形の描画でいろいろな準備が必要となっています。はっきりいってめんどうくさそうですね。
 でも拡張性つまり多種なシーンを作り出すためにここまで複雑な作りになっているわけですから、基本を大切にすべく次回からは一つ一つじっくり解説していきます。 
twitterはこちら
ニコ生放送します
ギャラリー
  • ウマモサク
  • ウマモサク
  • ウマモサク
  • 3/17 制作記録
  • 3/17 制作記録
  • C91告知
  • C91告知
  • C91告知
  • C91告知
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

  • ライブドアブログ