[Atelier Blue アトリエブルー]HomeプログラミングManaged DirectX3D>マルチターゲットレンダリング

マルチターゲットレンダリング

面白そうなのでやってみました。解説が欲しい方は掲示板で言って頂ければ書きます。

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Project2
{
    /// <summary>
    /// md3d2 の概要の説明です。
    /// </summary>
    public class md3d2:Form
    {

        public md3d2():base()
        {
            //最小サイズを設定
            this.MinimumSize=new Size(80,60);
            //ウィンドウの名前(かっこいいのを付けてあげてください)
            this.Text ="Direct3D-My";
        }

        private Device device_;
        private PresentParameters presentParam_;


        /// <summary>
        /// メッシュ
        /// </summary>
        private Mesh teaMesh_;

        /// <summary>
        /// 1パス目の描画先
        /// </summary>
        private Texture targetTexture;

        /// <summary>
        /// 1パス目のzバッファ
        /// </summary>
        private Surface depthStencilSurface;

        /// <summary>
        /// Direct3Dの初期化を行います。
        /// </summary>
        /// <returns>初期化が成功したかどうか</returns>
        public bool DXInitialize()
        {
            try
            {
                presentParam_ = new PresentParameters();

                presentParam_.Windowed =true;
                presentParam_.SwapEffect = SwapEffect.Discard;

                //Zバッファを使うための設定
                presentParam_.AutoDepthStencilFormat = DepthFormat.D16;
                presentParam_.EnableAutoDepthStencil = true;

                device_ = new Device(0,DeviceType.Hardware,this
                    ,CreateFlags.HardwareVertexProcessing,presentParam_);

                targetTexture =new Texture(
                    device_,512,512,1,Usage.RenderTarget,
                    Format.A8R8G8B8,Pool.Default);
                depthStencilSurface = device_.CreateDepthStencilSurface(
                    512,512,DepthFormat.D16,MultiSampleType.None,0,true);


                //メッシュを作成
                creatMesh();

                creatVertex();

                return true;
            }
            catch(Exception)
            {
                return false;
            }

        }
        /// <summary>
        /// 頂点バッファ
        /// </summary>
        private VertexBuffer vertexBuffer_;

        /// <summary>
        /// 頂点バッファ作成関数
        /// </summary>
        private void creatVertex()
        {
            //頂点バッファ領域を確保
            vertexBuffer_ = new VertexBuffer(
                typeof(CustomVertex.PositionTextured),4, device_
                , 0, CustomVertex.PositionTextured.Format, Pool.Managed);

            //頂点データの配列を作成
            CustomVertex.PositionTextured[] verts =
                new CustomVertex.PositionTextured[4];

            //頂点データ
            verts[0].Position  =new Vector3(1, 1,0);
            verts[0].Tu = 0; verts[0].Tv =0;

            verts[1].Position  =new Vector3(-1, 1,0);
            verts[1].Tu = 1; verts[1].Tv =0;

            verts[2].Position  =new Vector3(1, -1,0);
            verts[2].Tu = 0; verts[2].Tv =1;

            verts[3].Position  =new Vector3(-1, -1,0);
            verts[3].Tu = 1; verts[3].Tv =1;

            //バッファをロック
            GraphicsStream stm = vertexBuffer_.Lock(0,0,0);

            //頂点データをバッファに書き込み
            stm.Write(verts);

            //バッファのロックを解除
            vertexBuffer_.Unlock();
        }


        /// <summary>
        /// メッシュを作成する
        /// </summary>
        private void creatMesh()
        {
            teaMesh_ = Mesh.Teapot(device_);
        }

        public void Render()
        {
            if(device_==null)return;
            if(this.WindowState ==FormWindowState.Minimized)return;

            device_.RenderState.ZBufferEnable =true;
            device_.RenderState.ZBufferWriteEnable =true;

            device_.RenderState.CullMode =Cull.None;

            //ライトの設定
            device_.Lights[0].Direction =Vector3.Normalize(new Vector3(-1,-2,-3));
            device_.Lights[0].Type = LightType.Directional;
            device_.Lights[0].Diffuse = Color.FromArgb(255,255,255);
            device_.Lights[0].Ambient = Color.FromArgb(40,40,40);
            device_.Lights[0].Enabled =true;
            device_.Lights[0].Update();

            //マテリアルの設定
            Material mat =new Material();
            //色設定
            mat.AmbientColor = new ColorValue(0.0f,1.0f,0.0f);
            mat.DiffuseColor = new ColorValue(0.0f,1.0f,0.0f);
            device_.Material = mat;


            //############################################
            //1パス目開始
            //############################################
            //情報保存
            Viewport view = device_.Viewport;
            Surface depthBuffer = device_.DepthStencilSurface;
            Surface backBuffer = device_.GetRenderTarget(0);
            Matrix projection = device_.Transform.Projection;

            Viewport passOneView =view;
            passOneView.Height =512;
            passOneView.Width =512;
            device_.Transform.View = Matrix.LookAtLH(
                new Vector3(3,3,3),
                new Vector3( 0.0f, 0.0f, 0.0f ),
                new Vector3( 0.0f, 1.0f, 0.0f ) );
            device_.Transform.Projection =
                Matrix.PerspectiveFovLH((float)Math.PI / 4,
                1.0f,1.0f, 15.0f);

            device_.RenderState.Lighting=true;
            device_.Transform.World = Matrix.RotationY(Environment.TickCount/600f);

            device_.SetRenderTarget(0,targetTexture.GetSurfaceLevel(0));
            device_.DepthStencilSurface = depthStencilSurface;


            //クリア
            device_.Clear(ClearFlags.Target|ClearFlags.ZBuffer,Color.White,1.0f,0);

            //シーンの開始
            device_.BeginScene();

            teaMesh_.DrawSubset(0);

            device_.EndScene();
            try
            {
                //更新
                device_.Present();
            }
            catch(DeviceLostException)
            {
                resetDevice();
            }

            //############################################
            //2パス目
            //############################################
            //情報復元
            device_.Viewport =view;
            device_.DepthStencilSurface=depthBuffer;
            device_.SetRenderTarget(0,backBuffer);
            device_.Transform.Projection =projection;


            device_.Transform.View = Matrix.LookAtLH(
                new Vector3( 0.0f, 0.0f, 3.0f),
                new Vector3( 0.0f, 0.0f, 0.0f ),
                new Vector3( 0.0f, 1.0f, 0.0f ) );
            device_.Transform.Projection =
                Matrix.PerspectiveFovLH((float)Math.PI / 4,
                (float)this.ClientSize.Width / (float)this.ClientSize.Height,
                1.0f, 15.0f);

            device_.RenderState.Lighting=false;
            device_.Transform.World = Matrix.RotationX(Environment.TickCount/600f);

            //クリア
            device_.Clear(ClearFlags.Target|ClearFlags.ZBuffer,Color.Blue,1.0f,0);

            //シーンの開始
            device_.BeginScene();

            device_.SetTexture(0,targetTexture);

            device_.SetStreamSource(0,vertexBuffer_,0);
            device_.VertexFormat = CustomVertex.PositionTextured.Format;
            device_.DrawPrimitives(PrimitiveType.TriangleStrip,0,2);

            device_.EndScene();

            try
            {
                //更新
                device_.Present();
            }
            catch(DeviceLostException)
            {
                resetDevice();
            }

        }

        /// <summary>
        /// デバイスのリセットを行う
        /// </summary>
        private void resetDevice()
        {
            int result;
            if(!device_.CheckCooperativeLevel(out result))
            {
                if(result ==(int)ResultCode.DeviceLost)
                {
                    //ちょっと待つ
                    System.Threading.Thread.Sleep(10);
                }
                else if(result ==(int)ResultCode.DeviceNotReset)
                {
                    device_.Reset(presentParam_);
                }
            }
        }
    }

    /// <summary>
    /// エントリクラス
    /// </summary>
    class Program
    {
        public static void Main()
        {
            using(md3d2 dxform =new md3d2())
            {
                if(!dxform.DXInitialize())
                {
                    MessageBox.Show("Diret3Dの初期化に失敗しました。"
                        ,"初期化の失敗");
                    return;
                }
                dxform.Show();

                while(dxform.Created)
                {
                    dxform.Render();
                    Application.DoEvents();
                }
            }
        }
    }
}


ページの一番上へ
前のページへ 一覧に戻る 次のページへ
初版2006-5-13
[Atelier Blue アトリエブルー]HomeプログラミングManaged DirectX3D>マルチターゲットレンダリング