忍者ブログ

Memeplexes

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

かんたんXNA4.0 その28 テクスチャへの描画 RenderTarget

今まではウィンドウの画面にだけポリゴンを描画していましたが、
XNAでは実はテクスチャに対して描画することも出来ます。

これによりテクスチャを動的に作り出すことができ、
例えばゲームの中のアイテムとしてパソコンを作って、その画面を動かしたり出来るでしょう。
テクスチャに対していろいろ描画して、
それをゲームの中のパソコン画面に貼り付ければいいのです。



この、描画の対象となるテクスチャを
レンダーターゲットといいます。
クラスはMicrosoft.Xna.Framework.RenderTarget2Dです。

public class RenderTarget2D : Texture2D

このクラスのインスタンスを作成し、GraphicsDeviceにセットすると、
これまでと違って、画面ではなくこのレンダーターゲットにたいして
描画されるようになります。

コンストラクタを見てみましょう。

public RenderTarget2D (
        GraphicsDevice graphicsDevice,
        int width,
        int height
)


graphicsDeviceはグラフィックスデバイスです。
widthheightは作成するレンダーターゲットのテクスチャのサイズを表します。

このコンストラクタによって作成したレンダーターゲットを
GraphicsDeviceにセットするには、
GraphicsDevice.SetRenderTargetメソッドを使います。

public void SetRenderTarget (
        RenderTarget2D renderTarget
)


renderTargetはセットするレンダーターゲットです。



using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

class MyGame : Game
{
    GraphicsDeviceManager graphics;
    BasicEffect basicEffect;

    VertexPositionColor[] vertices =
    {
        new VertexPositionColor(new Vector3(0, 1, 0), Color.White),
        new VertexPositionColor(new Vector3(1, 0, 0), Color.Blue),
        new VertexPositionColor(new Vector3(-1, 0, 0), Color.Red)
    };

    RenderTarget2D renderTarget;
    SpriteBatch spriteBatch;

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

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

        spriteBatch = new SpriteBatch(GraphicsDevice);
        renderTarget = new RenderTarget2D(GraphicsDevice, 400, 200);
    }

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

    protected override void Draw(GameTime gameTime)
    {
        renderToRenderTarget();

        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        spriteBatch.Draw(renderTarget, new Rectangle(0, 0, 400, 200), Color.White);
        spriteBatch.End();
    }

    private void renderToRenderTarget()
    {
        GraphicsDevice.SetRenderTarget(renderTarget);
        GraphicsDevice.Clear(Color.Gray);

        foreach (var pass in basicEffect.CurrentTechnique.Passes)
        {
            pass.Apply();

            GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
            (
                PrimitiveType.TriangleList,
                vertices, 
                0,
                vertices.Length / 3
            );
        }

        GraphicsDevice.SetRenderTarget(null);
        
    }
}
renderTarget.JPG
このサンプルでは、まず400x200のテクスチャに対して三角形を描画した後、
そのテクスチャをさらにSpriteBatchで画面に描画しています。

レンダーターゲットをGraphicsDeviceにセットして、そのテクスチャをクリア、三角形をを描画します。
その後、その描画を解決、GraphicsDeviceからレンダーターゲットを取り除きます。
(これをやらないとウィンドウに何も映らなくなります。
その後の描画が全て画面ではなくレンダーターゲットに行われるのです)


これだけではビューポートを使った描画と区別がつかないかもしれません。
しかし、こちらはビューポートを使う場合よりもずっと柔軟で、用途が広いのです。

まず、ここではSpriteBatchで2Dとして描画していますが、
実際には3Dのモデルのテクスチャとして使ってもかまいません。
例えば斜めに傾いたモデルに貼り付ければ、そのモデルが実はディスプレイで、
そのテクスチャを表示しているように見えるでしょう。
これはビューポートには出来ない芸当です。

また、レンダーターゲットは光加減やぼやけ具合みたいな描画の効果を表現するのに利用されたりもします。
まずレンダーターゲットに対して何か描画して、
その後そのテクスチャを参考にして光やぼやけ具合などを計算するといった具合です。
XNA Creators Clubのサンプル、BloomPostprocessSampleもそのようなことをやっています。

このように、レンダーターゲットはかなりいろいろなことに使えるのです!

拍手[2回]

PR