LoginSignup
6
7

More than 5 years have passed since last update.

Directx入門してみた1

Last updated at Posted at 2016-01-11

Directxでウィンドウ作成

メモです。

DXAppクラスでは初期化、更新、描画してます。
DXUtilヘッダーには解放の処理があります。

DXApp.h
#pragma once
#define WIN32_LEAN_AND_MEAN
//WIN32_LEAN_AND_MEAN を #define することで
//余計なヘッダファイルは include されず、コンパイルはすばやく終わるらしい
#include<windows.h>
#include<tchar.h>
#include<string>
#include"DXUtil.h"

class DXApp {
public:
    DXApp(HINSTANCE hInstance,int showCmd);
    virtual ~DXApp();

    int Run();

    virtual bool Init();
    virtual void Update(float dt) = 0;
    virtual void Render(float dt) = 0;
    virtual LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    //Window
    HWND            m_hAppWnd;
    HINSTANCE       m_hAppInstance;
    UINT            m_ClientWidth;
    UINT            m_ClientHeight;
    std::string     m_AppTitle;
    DWORD           m_WndStyle;
    int             m_Show;
    const int       WINDOW_WIDTH = 800;
    const int       WINDOW_HEIGHT = 600;
    //DIREDCTX
    ID3D11Device*           m_pDevice;
    ID3D11DeviceContext*    m_pImmediateContext;
    IDXGISwapChain*         m_pSwapChain;
    ID3D11RenderTargetView* m_pRenderTargetView;
    D3D_DRIVER_TYPE         m_DriverType;
    D3D_FEATURE_LEVEL       m_FeatureLevel;
    D3D11_VIEWPORT          m_Viewport;

protected:
    bool InitWindow();   //Windowの初期化
    bool InitDirect3D(); //Directxの初期化
};
#include "DXApp.h"

namespace {
    DXApp* g_pApp = nullptr;
}
//ウィンドウプロシージャ
//ウィンドウプロシージャは、メッセージを処理する専用のルーチンです。
static LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {

    if (g_pApp)
        return g_pApp->MsgProc(hWnd, msg, wParam, lParam);
    else
        return DefWindowProc(hWnd, msg, wParam, lParam);
}


DXApp::DXApp(HINSTANCE hInstance,int showCmd)
{
    //Window
    m_hAppInstance = hInstance;
    m_Show = showCmd;
    m_hAppWnd = NULL;
    m_AppTitle = "TUTORIAL";
    m_WndStyle = WS_OVERLAPPEDWINDOW;
    m_ClientWidth = this->WINDOW_WIDTH;
    m_ClientHeight = this->WINDOW_HEIGHT;
    g_pApp = this;
    //Directx
    m_pDevice = nullptr;
    m_pImmediateContext = nullptr;
    m_pRenderTargetView = nullptr;
    m_pSwapChain = nullptr;

}
//解放処理
DXApp::~DXApp() {
    if (m_pImmediateContext) {
        m_pImmediateContext->ClearState();
    }
    Memory::Saferelease(m_pRenderTargetView);
    Memory::Saferelease(m_pSwapChain);
    Memory::Saferelease(m_pImmediateContext);
    Memory::Saferelease(m_pDevice);
}
//初期化処理
bool DXApp::Init() {
    if (!InitWindow()) {
        return false;
    }
    if (!InitDirect3D()) {
        return false;
    }
    return true;
}
//Windowの初期化
bool DXApp::InitWindow() {
    WNDCLASSEX wc;                                    
    wc.cbSize = sizeof(WNDCLASSEX);//構造体のサイズ
    wc.style = CS_HREDRAW | CS_VREDRAW;//ウインドウスタイル
    wc.lpfnWndProc = MainWndProc;     //そのウインドウのメッセージを処理するコールバック関数へのポインタ
    wc.cbClsExtra = 0;//ウインドウクラス構造体の後ろに割り当てる補足バイト数
    wc.cbWndExtra = 0;//ウインドウインスタンスの後ろに割り当てる補足バイト数
    wc.hInstance = m_hAppInstance;//インスタンスハンドル
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);//アイコンのハンドル
    wc.hIconSm = 0;//16×16の小さいサイズのアイコン
    wc.hCursor = LoadCursor(NULL, IDI_APPLICATION);//マウスカーソルのハンドル
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);//ウインドウ背景色
    wc.lpszMenuName = NULL;//デフォルトメニュー名
    wc.lpszClassName = _T("DefaultWindowClass");//このウインドウクラスにつける名前
    if (!RegisterClassEx(&wc)) {//Windowクラスを登録
        OutputDebugString("\nFAILED TO CREATE WINDOW CLASS\n");
        return false;
    }
     //windowの作成
    m_hAppWnd = CreateWindowEx(
        WS_EX_COMPOSITED,
        _T("DefaultWindowClass"),
        m_AppTitle.c_str(),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        m_ClientWidth,
        m_ClientHeight,
        NULL,
        NULL,
        m_hAppInstance,
        NULL);

    if (!m_hAppWnd) {
        OutputDebugString("\nFAILED TO CREATE WINDOW\n");
        return false;
    }
     //指定されたウィンドウの表示状態を設定します。
    ShowWindow(m_hAppWnd, m_Show);

    return true;

}
//Directxの初期化
bool DXApp::InitDirect3D()
{
    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif // _DEBUG

    const D3D_DRIVER_TYPE driverTypes[] {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE
    };
    UINT numDriverTypes = ARRAYSIZE(driverTypes);

    const D3D_FEATURE_LEVEL featureLevels[] {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_9_3
    };

    UINT numFeatureLevels = ARRAYSIZE(featureLevels);

    DXGI_SWAP_CHAIN_DESC swapDesc;
    ZeroMemory(&swapDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
    swapDesc.BufferCount = 1;
    swapDesc.BufferDesc.Width = m_ClientWidth;
    swapDesc.BufferDesc.Height = m_ClientHeight;
    swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swapDesc.BufferDesc.RefreshRate.Numerator = 60;
    swapDesc.BufferDesc.RefreshRate.Denominator = 1;
    swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapDesc.OutputWindow = m_hAppWnd;
    swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    swapDesc.Windowed = true;
    swapDesc.SampleDesc.Count = 1;
    swapDesc.SampleDesc.Quality = 0;
    swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    HRESULT result;
    for (int i = 0; i < numDriverTypes; ++i) {
        result = D3D11CreateDeviceAndSwapChain(
        NULL, 
        driverTypes[i],
        NULL, 
        createDeviceFlags,
        featureLevels, 
        numFeatureLevels, 
        D3D11_SDK_VERSION, 
        &swapDesc,
        &m_pSwapChain,
        &m_pDevice,
        &m_FeatureLevel,
        &m_pImmediateContext
);
        if (SUCCEEDED(result)) {
            m_DriverType = driverTypes[i];
            break;
        }
    }
    if (FAILED(result)) {
        OutputDebugString("FAILED TO CREATE DEVICE AND SWAP CHAIN");
        return false;
    }

    //CREATE RENDER TARGET VIEW

    ID3D11Texture2D*    m_pBackBufferTex = 0;
    m_pSwapChain->GetBuffer(NULL, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&m_pBackBufferTex));
//
    m_pDevice->CreateRenderTargetView(m_pBackBufferTex, nullptr, &m_pRenderTargetView);

    //BIND RENDER TARGET VIEW

    m_pImmediateContext->OMSetRenderTargets(1, &m_pRenderTargetView, nullptr);

    //VIEWPORT CREATION
    m_Viewport.Width = static_cast<float>(m_ClientWidth);
    m_Viewport.Height = static_cast<float>(m_ClientHeight);
    m_Viewport.TopLeftX = 0;
    m_Viewport.TopLeftY = 0;
    m_Viewport.MinDepth = 0.0f;
    m_Viewport.MaxDepth = 1.0f;

    m_pImmediateContext->RSSetViewports(1, &m_Viewport);

    return true;
}
LRESULT DXApp::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg)
    {
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
            PostQuitMessage(0);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}

void DXApp::Update(float dt) {

}
void DXApp::Render(float dt) {

}

int DXApp::Run() {
    MSG msg {};
    while (WM_QUIT != msg.message) {
        if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } else {

            //Update
            Update(0.0f);

            //Render
            Render(0.0f);

        }
    }
    return 0;

}

WNDCLASSEX

ウインドウを作成するための基本的な情報の集まり
WNDCLASSEX

ID3D11Device::CreateRenderTargetView

リソース データへのアクセス用にレンダー ターゲット ビューを作成します。
ID3D11Device::CreateRenderTargetView

RegisterClassEx

ウィンドウクラスを登録します
RegisterClassEx

CreateWindowEx

windowを作成
CreateWindowEx

ShowWindow

指定されたウィンドウの表示状態を設定します。
ShowWindow

D3D_DRIVER_TYPE

ドライバの種類のオプション
D3D_DRIVER_TYPE

D3D_FEATURE_LEVEL

Direct3D デバイスのターゲットとなる機能セットを記述します。
D3D_FEATURE_LEVEL

D3D11CreateDeviceAndSwapChain

ディスプレイ アダプターを表すデバイスとレンダリングに使用するスワップ チェーンを作成します。
D3D11CreateDeviceAndSwapChain

DXGI_SWAP_CHAIN_DESC

スワップ チェーンを記述します。
DXGI_SWAP_CHAIN_DESC

ID3D11Texture2D

2D テクスチャー インターフェイスは、構造化されたメモリーであるテクセル データを管理します。
ID3D11Texture2D

IDXGISwapChain::GetBuffer

スワップ チェーン バック バッファーの 1 つにアクセスします。
IDXGISwapChain::GetBuffer

ID3D11DeviceContext::OMSetRenderTargets

1 つ以上のレンダー ターゲットをアトミックにバインドし、出力結合ステージに深度ステンシル バッファーをバインドします。
ID3D11DeviceContext::OMSetRenderTargets

ID3D11DeviceContext::RSSetViewports

パイプラインのラスタライザー ステージにビューポートの配列をバインドします。
ID3D11DeviceContext::RSSetViewports

DXUtil.h
#pragma once
#include<d3d11.h>
#include<DirectXColors.h>

#pragma comment(lib, "d3d11.lib")

namespace Memory {
    template<class T> void SafeDelete(T& t) {
        if (t) {
            delete t;
            t = nullptr;
        }
    }
    template<class T> void SafeDeleteArr(T& t) {
        if (t) {
            delete[] t;
            t = nullptr;
        }
    }
    template<class T>void Saferelease(T& t) {
        if (t) {
            t->Release();
            t = nullptr;
        }
    }
}
WinMain.cpp
#include"DXApp.h"
//テストアプリクラスを作成
class TestApp : public DXApp {
public:
    TestApp(HINSTANCE hInstance,int showCmd);
    ~TestApp();

    bool Init() override;
    void Update(float dt) override;
    void Render(float dt) override;

};

TestApp::TestApp(HINSTANCE hInstance,int showCmd) :
    DXApp(hInstance,showCmd)
{}

TestApp::~TestApp() {

}

bool TestApp::Init() {
    if (!DXApp::Init()) {
        return false;
    }
    return true;
}

void TestApp::Update(float dt) {

}

void TestApp::Render(float dt) {
      //青で塗る
    m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, DirectX::Colors::CornflowerBlue);
    //レンダリング結果を表示
    m_pSwapChain->Present(0, 0);
}

//メイン
int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd) {

    TestApp tApp(hInstance,nShowCmd);
    if (!tApp.Init())return 1;

    return tApp.Run();
}
6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7