忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

かんたんXNA4.0 その23 深度バッファ関数

さて、深度バッファとは物体の前後関係から
適切に描画するためのデータでした。

カメラからの距離がより小さいときには描画し、
より大きいときには描画しないのです。

こうすることによって近くにあるものは遠くにあるものを隠し、
遠くにあるものは近くにあるものに隠されるのです。

実はこの挙動は変更することが出来ます。
例えば全く逆、カメラからの距離がより大きいときには描画し、
より小さいときには描画しないということができます。

近くにあるものは遠くにあるものに隠れ、
遠くにあるものは近くにあるものを隠すことが可能となるのです!!
(そんなことをして何が楽しいのかは知りませんが)
こういった挙動はDepthStencilState.DepthBufferFunctionプロパティで
設定します。

public CompareFunction DepthBufferFunction { get; set; }

このプロパティで表される条件を満たしたときのみ描画し、
満たさないときは描画しません。
そしてデフォルトの条件は「より小さいとき」です。

このプロパティの型は
Microsoft.Xna.Framework.CompareFunction列挙体です。

メンバ名 説明
Always 常に描画
Equal ==
Greater >
GreaterEqual >=
Less <
LessEqual <=
Never 常に描画しない
NotEqual !=

デフォルトの値はLessEqualです。
カメラからの距離が「より小さいとき」、
つまりカメラに近いときは描画すると言うことです。
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


class Triangle
{
    VertexPositionColor[] vertices = new VertexPositionColor[3];

    public Triangle(Vector3 p1, Vector3 p2, Vector3 p3, Color color)
    {
        vertices[0] = new VertexPositionColor(p1, color);
        vertices[1] = new VertexPositionColor(p2, color);
        vertices[2] = new VertexPositionColor(p3, color);
    }

    public void Draw(GraphicsDevice graphicsDevice, BasicEffect effect)
    {
        effect.VertexColorEnabled = true;

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();

            graphicsDevice.DrawUserPrimitives<VertexPositionColor>(
                PrimitiveType.TriangleList,
                vertices,
                0,
                1
                );
        }
    }
}

class MyGame : Game
{
    GraphicsDeviceManager graphics;
    BasicEffect effect;

    Triangle blueTriangle = new Triangle
    (
        new Vector3(0, 1, 0),
        new Vector3(1, -0.5f, 0),
        new Vector3(-1, -0.5f, 0),
        Color.Blue
    );
    Triangle redTriangle = new Triangle
    (
        new Vector3(1, 0.5f, -1),
        new Vector3(0, -1, -1),
        new Vector3(-1, 0.5f, -1),
        Color.Red
    );

    public MyGame()
    {
        graphics = new GraphicsDeviceManager(this);

    }

    protected override void LoadContent()
    {
        effect = new BasicEffect(GraphicsDevice)
        {
            View = Matrix.CreateLookAt
            (
                new Vector3(0, 0, 3),  //カメラの位置
                new Vector3(0, 0, 0),   //カメラの見る点
                new Vector3(0, 1, 0)    //カメラの上向きベクトル
            ),
            Projection = Matrix.CreatePerspectiveFieldOfView
            (
                MathHelper.ToRadians(45),   //視野の角度。ここでは45°
                GraphicsDevice.Viewport.AspectRatio,//画面のアスペクト比(=横/縦)
                1,      //カメラからこれより近い物体は画面に映らない
                100     //カメラからこれより遠い物体は画面に映らない
            )
        };
        GraphicsDevice.DepthStencilState = new DepthStencilState
        {
            DepthBufferFunction = CompareFunction.GreaterEqual
        };
    }

    protected override void UnloadContent()
    {
        effect.Dispose();
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(
            ClearOptions.Target | ClearOptions.DepthBuffer, //色と深度バッファをクリア
            Color.CornflowerBlue,   //色の初期値
            0,  //深度バッファの初期値(一番近いところから始める)
            0   //ステンシルバッファの初期値
            );


        blueTriangle.Draw(GraphicsDevice, effect);
        redTriangle.Draw(GraphicsDevice, effect);
    }
}

depthBufferFunctionGreaterEqual.jpg
このサンプルプログラムは、奇妙なことに
「近くのものが遠くのものに隠される」ようになっています。

カメラからの距離が「大きいか等しい」ときのみ描画するようなっているのです。

実際にこれがなんの役に立つかはさっぱりわかりませんが
こういうのもあるということです。

拍手[0回]

PR