Directxでウィンドウ作成
メモです。
DXAppクラスでは初期化、更新、描画してます。
DXUtilヘッダーには解放の処理があります。
# 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
# 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;
}
}
}
# 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();
}