頂点の取り扱い-1「TriangleList」
About
AppHubで配布されているパーティクルのサンプルが複雑すぎるので、噛み砕いていくことにした。そういう経緯のための時折パーティクルに関する言及がある。ここではポリゴンを構成する頂点情報の扱いについて解説する。頂点情報の扱いについて学習すると、動的な頂点の移動・編集が可能になるので、CGの各種技術に対応することが出来るようになる。ハズ。
SimpleVertex1.zip
- VisualStudio2010 / XNA4.0 で動作を確認しています。
簡単のための2次元座標系
ここでは解説する内容に注視し、余計な情報を省いて簡単化するため、3次元座標ではなく2次元座標を使って解説する。解説する内容は2次元座標に置いても3次元座標に置いても共通である。画面平面の2次元座標は図の通りとなっている。
頂点情報の定義
XNAで頂点情報を定義するには、原則として頂点を示す構造体を利用しなければならない。自分で用意することもできるが、ここでは予め用意された頂点用の構造体「VertexPositionColor」を用いる。ここでは頂点情報を配列として扱い、配列に3つの頂点を定義した。見ての通り、空間座標と色情報が頂点情報に含まれる格好になっている。
private VertexPositionColor[] vertices = { new VertexPositionColor(new Vector3(0, 1, 0), Color.Red), new VertexPositionColor(new Vector3(1, 0, 0), Color.Green), new VertexPositionColor(new Vector3(-1, 0, 0), Color.Blue) };
頂点の描画1
実は与えられた頂点情報だけで、それらの頂点を描画する手法が存在する。扱いが簡単であるため実用的ではないが、先にこちらの手法を紹介する。BasicEffectに「パス※線や図形の総称」を描画するための手順が用意されているので、その中で頂点を描画する。ここではBasicEffectに関しては気にしない。こういうものだとして扱うことにする。ただし今回は頂点の色情報を任意に変更するので次の設定「VertexColorEnable」を「true」にしておく必要がある。
basicEffect = new BasicEffect(graphics.GraphicsDevice); basicEffect.VertexColorEnabled = true;//頂点色の有効化
描画処理部分は「DrawUserPrimitives」メソッドである。「Primitive:プリミティブ」とは、CGにおいては基本的な図形として称されるものと思えば良い。描画したい図形を第一引数に定義する。「LineList」「LineStrip」「TriangleList」「TriangleStrip」が選択できる(各々の図形のイメージは下に掲載する図を参考にされたい)。その後、描画する頂点の配列、頂点のオフセット(始点とする頂点)、描画する図形の数、と続いていく。これだけで基本的に描画はできてしまう。
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes) { // パスの開始 pass.Apply(); // ポリゴンを描画する this.GraphicsDevice.DrawUserPrimitives( //描画する図形の種類 PrimitiveType.TriangleList, //描画対象とする頂点の配列 this.vertices, //頂点のオフセット=始点となる頂点 0, //描画する図形の数 1 ); }
XNA4.0にバージョンが上がり、「PointSprite」を扱うことが出来なくなったのが厄介。XNAでパーティクル表現を行おうとすると、結局「DrawPrimitive」周りを扱うことになる。OpenGL4.0ではまだPointSpriteの概念が残っているし、XNAの資料にしても未だ持ってPointSpriteについて言及しているものが多く存在するので、パーティクルを表現したい場合は注意する。
サンプルの実行結果
実行するとこの様な結果が表示される。それぞれ定義した頂点に色情報が含まれていて、それらを結ぶようにTriangle(三角形)が描画されるため、補間が働いて綺麗にグラデーションがかかる。XNAに限らず割とCGでは良く見かけられるサンプル。
頂点の描画2
頂点をバッファに登録する
先の手法では基本的な取り扱いなので、次は実質的に利用されている手法の初歩の初歩について学ぶ。先とどう変わるかというと、予めバッファに頂点を登録しておいてそこから描画する。元から転送しておく分だけ高速に動作する。
ここでそのバッファは「DynamicVertexBuffer」として用意する。類似する「VertexBuffer」が存在するが、どっちを選択しても問題ない。動的にバッファの内容を書き換える処理を行う場合は文字通り「Dynamic(動的な)VertexBuffer」を選択しておく方が良い。インスタンスの生成には、「GraphicsDevice」、「Declaration(頂点情報の構成情報)」、頂点数、バッファの使い方(基本はNoneで良い?)になっている。
バッファを生成したらそこに頂点をセット(SetData)し、準備を終える。ここで登録する頂点は先の手順で利用したものと同じ。
//バーテックスバッファ DynamicVertexBuffer dVertexBuffer; //頂点バッファの生成 dVertexBuffer = new DynamicVertexBuffer( GraphicsDevice, VertexPositionColor.VertexDeclaration, vertices.Length,//頂点数(=配列の大きさ) BufferUsage.None); //頂点バッファに頂点を登録 dVertexBuffer.SetData<VertexPositionColor>(vertices);
バッファを利用して描画する
先とは異なり今度はバッファを利用して描画する。まずデバイスに対して「SetVertexBuffer」を用いてバッファを登録する必要がある。その後は先と同様に「DrawPrimives」から描画する。実行結果は先と同じものになるので割愛する。
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes) { // パスの描画を開始 pass.Apply(); //頂点バッファへ用意したバッファの登録 this.GraphicsDevice.SetVertexBuffer(dVertexBuffer); //バッファからプリミティブの描画 this.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); }
ここでは扱う頂点数が少なすぎて速度を実感することはできない。