DirectX(8.1)3D

DirectX(8.1)3D

自動生成した Windows 8.1 の DirectX 3D プロジェクトです。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの作成

  1. 2013年10月に Windows8.1 がリリースされ、私も 2013/10/20 にバージョンアップしました。
    同時に Visual Studio Professional 2003 をダウンロードしました。
    また Windows 8.1 app samples のページからサンプルプログラムをダウンロードすることが出来ます。
    2013/10/20 以降のプロジェクトは、Windows8.1 と Visual Studio Professional 2003 の環境で開発します。
    私は Visual Studio のショートカットをデスクトップに置いて起動しています。
    規定値でインストールすると、下記のフォルダに格納されます。
    "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe"
  2. Windows 8 のプロジェクトを Windows 8.1 で開くにはメンテナンスツールが必要なようです。
    私は「ストアアプリ用メンテナンスツール for Windows 8」をインストールして実行を確認しました。
    但し、全てのプロジェクトが実行できる訳では無いようで、幾つかのプロジェクトではコンパイルエラーが表示されました。
    正規の Windows 8.1 用のアプリケーションを作成するには、プロジェクトを再構築しなければならないようです。
  3. プロジェクトを起動して、自動生成される Direct 3D のプロジェクトをコンパイルしてみましょう。
    ショートカットから [Visual Studio] を起動します。
    [ファイル] [新規作成] [プロジェクト] から [Visual C++] [Windows ストア] を選択して、[DirectX アプリケーション] を選びます。
  4. 後は規定値で [OK] をクリックすると、プロジェクト(App1)が構築されます。
    シンプルなプロジェクトでは「ソリューションのディレクトリを作成(D)」のチェックを外す方がわかり易いでしょう。
    そのまま右三角アイコンでコンパイル&実行します。
    頂点に色を設定した立方体が回転しながら描画されます。
  5. 終了する(画面の上部から下部に向かってドラッグする)と Metro Style のスタート画面に戻ります。
    デスクトップをクリックして Visual Studio の画面に戻って下さい。
    メニューから [デバッグ] [デバッグの停止] を選択して、アプリケーションの実行を終了します。
  6. 作成されたプロジェクトのフォルダ(App1)の中を確認して下さい。
    次のファイルは削除することが出来ます。
    削除した状態で App1.sln をダブルクリックで起動して、コンパイル&実行が出来ることを確かめて下さい。

プログラムの説明

  1. 立方体の頂点座標(8頂点)と色は \Content\Sample3DSceneRenderer.cpp で定義されています。
    頂点座標の説明は 頂点座標の Index を使って BOX を描画する参照して下さい。
        auto createCubeTask = (createPSTask && createVSTask).then([this] ()
        {   static const VertexPositionColor cubeVertices[] = 
            {   {XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f)},
                {XMFLOAT3(-0.5f, -0.5f,  0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f)},
                {XMFLOAT3(-0.5f,  0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f)},
                {XMFLOAT3(-0.5f,  0.5f,  0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f)},
                {XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f)},
                {XMFLOAT3( 0.5f, -0.5f,  0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f)},
                {XMFLOAT3( 0.5f,  0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f)},
                {XMFLOAT3( 0.5f,  0.5f,  0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f)},
            };
    
           ・・・
    
  2. 三角形の頂点座標を組み合わせて立方体を定義します。
        static const unsigned short cubeIndices [] =
        {   0,2,1, // -x
            1,2,3,
    
            4,5,6, // +x
            5,7,6,
    
            0,1,5, // -y
            0,5,4,
    
            2,6,7, // +y
            2,7,3,
    
            0,4,6, // -z
            0,6,2,
    
            1,3,7, // +z
            1,7,5,
        };
    
  3. Update() メソッドで座標を回転して、Render() メソッドで描画します。
    void Sample3DSceneRenderer::Update(DX::StepTimer const& timer)
    {   if (!m_tracking)
        {   float radiansPerSecond = XMConvertToRadians(m_degreesPerSecond);
            double totalRotation = timer.GetTotalSeconds() * radiansPerSecond;
            float radians = static_cast<float>(fmod(totalRotation, XM_2PI));
            Rotate(radians);
        }
    }
    
    void Sample3DSceneRenderer::Render()
    {
        ・・・
    }
    
  4. main() やメッセージループ(Run)は App.cpp で定義されています。
    [Platform::MTAThread]
    int main(Platform::Array^)
    {
        auto direct3DApplicationSource = ref new Direct3DApplicationSource();
        CoreApplication::Run(direct3DApplicationSource);
        return 0;
    }
    
    void App::Run()
    {
        while (!m_windowClosed)
        {   if (m_windowVisible)
            {   CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
                m_main->Update();
                if (m_main->Render())
                {   m_deviceResources->Present();
                }
            }
            else
            {   CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
            }
        }
    }
    
  5. Run() から呼ばれる Update() メソッドと Render() メソッドです。
    ここから Sample3DSceneRenderer の Update や Render を呼び出します。
    void App1Main::Update() 
    {   m_timer.Tick([&]()
        {   m_sceneRenderer->Update(m_timer);
            m_fpsTextRenderer->Update(m_timer);
        });
    }
    
    bool App1Main::Render() 
    {
        if (m_timer.GetFrameCount() == 0)
        {   return false;  }
    
        auto context = m_deviceResources->GetD3DDeviceContext();
        auto viewport = m_deviceResources->GetScreenViewport();
        context->RSSetViewports(1, &viewport);
    
        ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
        context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
    
        context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue);
        context->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
    
        m_sceneRenderer->Render();
        m_fpsTextRenderer->Render();
    
        return true;
    }
    

XAML のプロジェクト

  1. 上記のプロジェクトには XAML は組み込まれていません。
    次に Direct 3D に XAML を組み込んだプロジェクトを構築してみましょう。
    [DirectX アプリケーション] に代えて [DirectX アプリケーション(XAML)] を選ぶだけです。
  2. そのまま右三角アイコンでコンパイル&実行します。
    頂点に色を設定した立方体が回転しながら描画されます。
    こちらはマウスの操作で立方体を回転することが出来るので試してみて下さい。

プログラムの説明

  1. XAML のプログラムは App.xaml.cpp から起動されます。
    App::App()
    {
        InitializeComponent();
        Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
        Resuming += ref new EventHandler<Object^>(this, &App::OnResuming);
    }
    
  2. レンダリングループは App1Main.cpp で定義されています。
    void App1Main::StartRenderLoop()
    {   if (m_renderLoopWorker != nullptr && m_renderLoopWorker->Status == AsyncStatus::Started)
        {   return;
        }
        auto workItemHandler = ref new WorkItemHandler([this](IAsyncAction ^ action)
        {   while (action->Status == AsyncStatus::Started)
            {   critical_section::scoped_lock lock(m_criticalSection);
                Update();
                if (Render())
                {   m_deviceResources->Present();
                }
            }
        });
        m_renderLoopWorker = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced);
    }  
    
  3. StartRenderLoop() から呼ばれる Update() メソッドと Render() メソッドです。
    ここから Sample3DSceneRenderer の Update や Render を呼び出します。
    void App1Main::Update() 
    {   ProcessInput();
        m_timer.Tick([&]()
        {   m_sceneRenderer->Update(m_timer);
            m_fpsTextRenderer->Update(m_timer);
        });
    }  
    
    bool App1Main::Render() 
    {
        if (m_timer.GetFrameCount() == 0)
        {   return false;  }
    
        auto context = m_deviceResources->GetD3DDeviceContext();
        auto viewport = m_deviceResources->GetScreenViewport();
        context->RSSetViewports(1, &viewport);
    
        ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
        context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
    
        context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue);
        context->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
    
        m_sceneRenderer->Render();
        m_fpsTextRenderer->Render();
    
        return true;
    }
    

超初心者のプログラム入門(DirectX Store)