WisdomSoft - for your serial experiences.

ラスタライザステート

頂点配列のポリゴンを平面(サーフェス)に描画する処理(ラスタ化)の設定は、グラフィックスデバイスのラスタライザステートによって行われます。

カリング

頂点配列とポリゴン」で前述したように、デフォルトの設定では三角形の背面はカリングによって描画されません。多くの場合、閉じた物体の裏側は描画する必要がないのでカリングを有効にしますが、描画するプリミティブの背面も描画しなければならない場合はカリングを無効にしなければなりません。

カリングは頂点配列からなるポリゴンを 2D の平面に描画する方法を設定するラスタライザステートの一部です。ラスタライザステートを変更するには、グラフィックデバイスの描画に関連した状態を表すオブジェクトを RasterizerState プロパティを取得しなければなりません。

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

このプロパティは、グラフィックスデバイスが 3D のプリミティブをピクセルに変換するラスタ化に関する設定を提供する Microsoft.Xna.Framework.Graphics.RasterizerState クラスのオブジェクトを設定または取得します。

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

コンストラクタから独自のラスタライザステートを生成し、デバイスに設定することもできますが、カリングの設定を変更したいだけであれば、通常は組み込みのラスタライザステートを用います。組み込みのラスタライザステートは、RasterizerState クラスの静的な読み取り専用フィールドから得られます。

既定では RasterizerState プロパティには CullClockwise フィールドのオブジェクトが設定されています。このフィールドは時計回りに繋がれた頂点の面を描画します。逆に反時計回りの面を表として描画するには CullCounterClockwise フィールドから得られるラスタライザステートを用います。カリングを無効にするには CullNone フィールドのオブジェクトを設定します。

RasterizerState クラス CullClockwise フィールド
public static readonly RasterizerState CullClockwise
RasterizerState クラス CullCounterClockwise フィールド
public static readonly RasterizerState CullCounterClockwise
RasterizerState クラス CullNone フィールド
public static readonly RasterizerState CullNone

これらのフィールドのいずれかを RasterizerState プロパティに設定することで、プリミティブの背面を描画するかどうかを制御できます。当然、背面を描画する場合は計算量が増えるため、一般的にはカリングを有効にして描画します。

コード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, 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),
        };
        indices = new short[] { 0, 1, 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;

        GraphicsDevice.RasterizerState = RasterizerState.CullNone;

        base.LoadContent();
    }

    protected override void Update(GameTime gameTime)
    {
        effect.World *= Matrix.CreateRotationY(MathHelper.ToRadians(2));
        effect.View = Matrix.CreateLookAt(new Vector3(0, 0, 3), Vector3.Zero, Vector3.Up);
        effect.Projection = Matrix.CreatePerspectiveFieldOfView(
            MathHelper.ToRadians(45), 16F / 9F, 1, 10
        );
        base.Update(gameTime);
    }

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

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

        base.Draw(gameTime);
    }
}
実行結果

コード1は三角形プリミティブを回転させるだけの簡単なプログラムです。既定の設定ではカリングが有効になっており、ポリゴンの背面は描画されません。そこで LoadContent() メソッド内で GraphicsDevice オブジェクトの RasterizerState プロパティに RasterizerState クラスの CullNone フィールドを設定し、カリングを無効化しています。実行結果のように、カリングを無効化することで三角形の背面も描画されるようになることが確認できます。