WisdomSoft - for your serial experiences.

インデックスバッファ

デバイスに設定された頂点バッファを参照するインデックスを用いて描画する場合、インデックス配列も頂点バッファと同じようにインデックスバッファとしてデバイスに設定します。

インデックス配列をデバイスに設定する

グラフィックスデバイスに設定されている頂点バッファを、インデックス配列を用いて描画する場合、合わせてインデックスバッファを用意してデバイスに設定しなければなりません。基本的な考え方は頂点バッファと同じです。インデックスバッファは Microsoft.Xna.Framework.Graphics.IndexBuffer クラスで表されます。

Microsoft.Xna.Framework.Graphics.IndexBuffer クラス
public class IndexBuffer : GraphicsResource

IndexBuffer クラスのコンストラクタは、インデックスバッファのサイズを列挙型から指定するものと Type オブジェクトから指定するものにオーバーロードされています。

IndexBuffer クラスのコンストラクタ
public IndexBuffer (
         GraphicsDevice graphicsDevice,
         IndexElementSize indexElementSize,
         int indexCount,
         BufferUsage usage
)
public IndexBuffer (
         GraphicsDevice graphicsDevice,
         Type indexType,
         int indexCount,
         BufferUsage usage
)

graphicsDevice パラメータには、このインデックスバッファに関連付ける GraphicsDevice オブジェクトを指定します。indexElementSize パラメータは IndexElementSize 列挙型のメンバからインデックスの型を指定します。一方のコンストラクタにある indexType パラメータはインデックスの型を表す Type オブジェクトを指定します。indexCount パラメータはインデックスの要素数を、usage パラメータには、このインデックスバッファの使用方法を指定します。

実質的に、インデックスの要素となる方は 16 ビットの short 型、または 32 ビットの int 型のいずれかです。そのために Type オブジェクトを取得するのは効率的ではないので、通常は Microsoft.Xna.Framework.Graphics.IndexElementSize 列挙型のメンバを設定する形が好ましいでしょう。

Microsoft.Xna.Framework.Graphics.IndexElementSize 列挙型
public enum IndexElementSize

この列挙型には、16 ビット型を表す SixteenBits メンバと 32 ビット型を表す ThirtyTwoBits メンバが定義されています。

IndexBuffer クラスのインスタンスを生成することができれば、次に SetData() メソッドでインデックスを設定します。

IndexBuffer クラス SetData() メソッド
public void SetData<T> (T[] data) where T : ValueType

data パラメータにはインデックスの配列を指定します。指定する配列の型と要素数は、IndexBuffer クラスのコンストラクタで指定した型と要素数の範囲に収まっていなければなりません。

適切にインデックスバッファを初期化できれば、あとは GraphicsDevice オブジェクトの Indices プロパティに設定するだけです。

GraphicsDevice クラス Indices プロパティ
public IndexBuffer Indices { get; set; }

このプロパティに、頂点バッファを参照する適切なインデックス配列が設定された IndexBuffer オブジェクトを設定します。

GraphicsDevice オブジェクトに頂点バッファとインデックスバッファが正しく設定されていれば、DrawIndexedPrimitives() メソッドでプリミティブを描画できます。 

GraphicsDevice クラス DrawIndexedPrimitives() メソッド
public void DrawIndexedPrimitives (
         PrimitiveType primitiveType,
         int baseVertex,
         int minVertexIndex,
         int numVertices,
         int startIndex,
         int primitiveCount
)

primitiveType パラメータには、プリミティブの種類を指定します。baseVertex パラメータには、頂点バッファの最初の要素のインデックスを指定します。minVertexIndex パラメータには、頂点の最小インデックスを指定します。numVertices パラメータは、使用する頂点の数を指定します。頂点バッファの要素は baseVertex + minVertexIndex から数えられます。頂点バッファ全体を使う場合、baseVertex パラメータと minVertexIndex パラメータに 0 を設定し、numVertices パラメータに頂点バッファの要素数を指定してください。

startIndex パラメータには、インデックスバッファの使用する最初の要素を表すインデックスを指定します。インデックスバッファのすべての要素を使用する場合は 0 を指定してください。最後の primitiveCount パラメータにプリミティブの数を指定します。

コード1
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        using (Game game = new TestGame()) game.Run();
    }

    private GraphicsDeviceManager graphicsDeviceManager;
    private VertexBuffer vertexBuffer;
    private IndexBuffer indexBuffer;
    private BasicEffect effect;
    private VertexPositionColor[] vertices;
    private short[] indices;

    public TestGame()
    {
        graphicsDeviceManager = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void Initialize()
    {
        vertices = new VertexPositionColor[] {
	        new VertexPositionColor(new Vector3(-0.5F, 0.5F, 0), Color.Red),
	        new VertexPositionColor(new Vector3(0.5F, 0.5F, 0), Color.Blue),
	        new VertexPositionColor(new Vector3(-0.5F, -0.5F, 0), Color.Lime),
	        new VertexPositionColor(new Vector3(0.5F, -0.5F, 0), Color.Black),
        };
        indices = new short[] { 0, 1, 2, 1, 3, 2 };
        base.Initialize();
    }

    protected override void LoadContent()
    {
        vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), vertices.Length, BufferUsage.None);
        vertexBuffer.SetData(vertices);
        GraphicsDevice.SetVertexBuffer(vertexBuffer);

        indexBuffer = new IndexBuffer(GraphicsDevice, IndexElementSize.SixteenBits, indices.Length, BufferUsage.None);
        indexBuffer.SetData(indices);
        GraphicsDevice.Indices = indexBuffer;

        effect = new BasicEffect(GraphicsDevice);
        effect.VertexColorEnabled = true;

        base.LoadContent();
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.White);

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, 2);
        }

        base.Draw(gameTime);
    }
}
実行結果
コード1 実行結果

コード1の結果は「インデックス コード1」と同じですが、頂点バッファとインデックスバッファを用いた描画に書き換えています。