Windows10 Rect

Windows10 Rect

Windows10 DirectX でウインドウに直接黄色の矩形を描画します。

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

プログラムの作成

  1. Win10 Base DirectX Windows10 のベースプロジェクトをベースに黄色の矩形を描画します。
    「DirectX10 ベースプロジェクト」からアプリを作成する方法を学んで下さい。
    Win10 Base のプロジェクトをコピーして下さい。
    プロジェクトの名前は App1 になっています。
  2. RectRenderer.h, RectRenderer.cpp を Content\ に格納します。
    App1 を選択して[追加][既存の項目]からプロジェクトに追加します。
  3. RectRenderer.h のソースコードです。
    #pragma once
    
    #include <string>
    #include "..\Common\DeviceResources.h"
    #include "..\Common\StepTimer.h"
    
    namespace App1
    {
        // Direct2D および DirectWrite を使用して、画面中央に矩形を描画します。
        class RectRenderer
        {
        public:
            RectRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources);
            void CreateDeviceDependentResources();
            void ReleaseDeviceDependentResources();
            void Render();
    
        private:
            // デバイス リソースへのキャッシュされたポインター。
            std::shared_ptr<DX::DeviceResources> m_deviceResources;
    
            // テキスト レンダリングに関連するリソース。
            Microsoft::WRL::ComPtr<ID2D1SolidColorBrush>    m_whiteBrush;
            Microsoft::WRL::ComPtr<ID2D1DrawingStateBlock>  m_stateBlock;
        };
    }
    
  4. RectRenderer.cpp のソースコードです。
    座標 50,50 から 300,200 の矩形を描画します。
        D2D1_RECT_F rectangle1 = D2D1::RectF(50.0f, 50.0f, 300.0f, 200.0f);
        context->FillRectangle(&rectangle1, yellowBrush.Get());
    
    #include "pch.h"
    #include "RectRenderer.h"
    
    #include "Common/DirectXHelper.h"
    
    using namespace App1;
    
    // テキスト レンダリングで使用する D2D リソースを初期化します。
    RectRenderer::RectRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources) : 
        m_deviceResources(deviceResources)
    {
        DX::ThrowIfFailed(
            m_deviceResources->GetD2DFactory()->CreateDrawingStateBlock(&m_stateBlock)
            );
    
        CreateDeviceDependentResources();
    }
    
    // フレームを画面に描画します。
    void RectRenderer::Render()
    {
        Microsoft::WRL::ComPtr<ID2D1SolidColorBrush>    yellowBrush;
        ID2D1DeviceContext* context = m_deviceResources->GetD2DDeviceContext();
        DX::ThrowIfFailed(
            context->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Yellow), &yellowBrush)
            );
    
        context->BeginDraw();
        context->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
    
        D2D1_RECT_F rectangle1 = D2D1::RectF(50.0f, 50.0f, 300.0f, 200.0f);
        context->FillRectangle(&rectangle1, yellowBrush.Get());
    
        HRESULT hr = context->EndDraw();
        if (hr != D2DERR_RECREATE_TARGET)
        {   DX::ThrowIfFailed(hr);  }
    }
    
    void RectRenderer::CreateDeviceDependentResources()
    {
        DX::ThrowIfFailed(
            m_deviceResources->GetD2DDeviceContext()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &m_whiteBrush)
            );
    }
    void RectRenderer::ReleaseDeviceDependentResources()
    {
        m_whiteBrush.Reset();
    }
    
  5. App1Main.h に RectRenderer.h を取り込んで m_RectRenderer を定義します。
    #pragma once
    
    #include "Common\StepTimer.h"
    #include "Common\DeviceResources.h"
    #include "Content\RectRenderer.h"
    
    // Direct2D および 3D コンテンツを画面上でレンダリングします。
    namespace App1
    {
        class App1Main : public DX::IDeviceNotify
        {
        public:
            App1Main(const std::shared_ptr<DX::DeviceResources>& deviceResources);
            ~App1Main();
            void CreateWindowSizeDependentResources();
            void Update();
            bool Render();
    
            // IDeviceNotify
            virtual void OnDeviceLost();
            virtual void OnDeviceRestored();
    
        private:
            // デバイス リソースへのキャッシュされたポインター。
            std::shared_ptr<DX::DeviceResources> m_deviceResources;
    
            // TODO: これを独自のコンテンツ レンダラーで置き換えます。
            std::unique_ptr<RectRenderer> m_RectRenderer;
    
            // ループ タイマーをレンダリングしています。
            DX::StepTimer m_timer;
        };
    }
    
  6. App1Main.cpp に RectRenderer を組み込みます。
    #include "pch.h"
    #include "App1Main.h"
    #include "Common\DirectXHelper.h"
    
    using namespace App1;
    using namespace Windows::Foundation;
    using namespace Windows::System::Threading;
    using namespace Concurrency;
    
    // アプリケーションの読み込み時にアプリケーション資産を読み込んで初期化します。
    App1Main::App1Main(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
        m_deviceResources(deviceResources)
    {
        // デバイスが失われたときや再作成されたときに通知を受けるように登録します
        m_deviceResources->RegisterDeviceNotify(this);
    
        // TODO: これをアプリのコンテンツの初期化で置き換えます。
        m_RectRenderer = std::unique_ptr<RectRenderer>(new RectRenderer(m_deviceResources));
    
        // TODO: 既定の可変タイムステップ モード以外のモードが必要な場合は、タイマー設定を変更してください。
        // 例: 60 FPS 固定タイムステップ更新ロジックでは、次を呼び出します:
        /*
        m_timer.SetFixedTimeStep(true);
        m_timer.SetTargetElapsedSeconds(1.0 / 60);
        */
    }
    
    App1Main::~App1Main()
    {
        // デバイスの通知を登録解除しています
        m_deviceResources->RegisterDeviceNotify(nullptr);
    }
    
    //ウィンドウのサイズが変更される (デバイスの方向が変更されるなど) 場合に、 アプリケーションの状態を更新します。
    void App1Main::CreateWindowSizeDependentResources() 
    {
        // TODO: これをアプリのコンテンツのサイズに依存する初期化で置き換えます。
    }
    
    // アプリケーション状態をフレームごとに 1 回更新します。
    void App1Main::Update() 
    {
        // シーン オブジェクトを更新します。
        m_timer.Tick([&]()
        {
            // TODO: これをアプリのコンテンツの更新関数で置き換えます。
        });
    }
    
    // 現在のアプリケーション状態に応じて現在のフレームをレンダリングします。
    // フレームがレンダリングされ、表示準備が完了すると、true を返します。
    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);
    
        // シーン オブジェクトをレンダリングします。
        // TODO: これをアプリのコンテンツのレンダリング関数で置き換えます。
        m_RectRenderer->Render();
    
        return true;
    }
    
    // デバイス リソースを解放する必要が生じたことをレンダラーに通知します。
    void App1Main::OnDeviceLost()
    {
        m_RectRenderer->ReleaseDeviceDependentResources();
    }
    
    // デバイス リソースの再作成が可能になったことをレンダラーに通知します。
    void App1Main::OnDeviceRestored()
    {
        m_RectRenderer->CreateDeviceDependentResources();
        CreateWindowSizeDependentResources();
    }
    
    
  7. メニューの[デバッグ]から[デバッグ開始]、または[緑色の右三角アイコン]でコンパイル&実行します。
    ウインドウに黄色の矩形が描画されます。
    FPS の表示と違って Update() で更新する必要はありません。
    細かいことを言えば、メッセージループから毎回矩形を描画する必要もありません。
    60fps(フロップス)の場合、1秒間に60回も同じ矩形が描画されることになります。
    何か良い方法を考えて下さい。 (^_^;)

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