Direct3D11 の初期化と終了
(VS2012)プロジェクトをダウンロード
ウィンドウを生成してWindowsアプリケーションを初期化したら、
Direct3Dを初期化します。具体的には5つのオブジェクトを生成します。
- デバイスコンテキスト
- デバイス
- スワップチェイン
- レンダーターゲット
- 深度ステンシルバッファ
これらのオブジェクトが生成できたら、とりあえずDirect3Dが使用可能になります。
【DX11_Init.cpp】
//----------------------------------------------------------
//
// Application
// DX11_Init
//
// First Edition : October 21 2016
// Author Mr.K
//
#include "stdafx.h"
#include <stdio.h>
#include <crtdbg.h>
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
using namespace DirectX;
// import libraries
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dcompiler.lib")
#define MAX_LOADSTRING 100
#define SAFE_DELETE(o) if (o){ delete (o); o = NULL; }
#define SAFE_DELETE_ARRAY(o) if (o){ delete [] (o); o = NULL; }
#define SAFE_RELEASE(o) if (o){ (o)->Release(); o = NULL; }
// Globals
TCHAR *g_pDriverType = NULL;
TCHAR *g_pFeatureLevel = NULL;
UINT g_uiCount=0;
//
// prototypes
//
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HRESULT GetBackBufferSize(IDXGISwapChain *pSwapChain, DWORD *pWidth, DWORD *pHeight);
HRESULT CreateDepthStencilView(
ID3D11Device *pDevice,
INT width,
INT height,
DXGI_FORMAT fmtDepthStencil,
ID3D11DepthStencilView **ppDepthStencilView,
ID3D11Texture2D **ppDepthStencilTexture,
ID3D11ShaderResourceView **ppDepthStencilShaderResourceView
);
HRESULT CreateRenderTargetView(
ID3D11Device *pDevice,
IDXGISwapChain *pSwapChain,
ID3D11RenderTargetView **ppRenderTargetView,
ID3D11ShaderResourceView **ppRenderTargetShaderResourceView
);
HRESULT CreateDeviceContextAndSwapChain(
HWND hWnd,
ID3D11Device **ppDevice,
ID3D11DeviceContext **ppContext,
IDXGISwapChain **ppSwapChain,
D3D_DRIVER_TYPE *pDriverType,
D3D_FEATURE_LEVEL *pFeatureLevel
);
TCHAR *GetDriverTypeText(D3D_DRIVER_TYPE dt);
TCHAR *GetFeatureLevelText(D3D_FEATURE_LEVEL fl);
//
// WinMain
// the entry point of windows application
//
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("D3D11_Sprite"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("D3D11_Sprite"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,640,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
640 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
//==========Direct3D11 の初期化処理===================
CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // COM を初期化
D3D_DRIVER_TYPE DriverType = D3D_DRIVER_TYPE_NULL;
ID3D11DeviceContext *pContext = NULL; // 描画環境
ID3D11Device *pDevice = NULL; // 仮想アダプタ(ハードウエア)
IDXGISwapChain *pSwapChain = NULL; // スワップチェイン
ID3D11RenderTargetView *pRenderTargetView = NULL; // レンダーターゲット
ID3D11DepthStencilView *pDepthStencilView = NULL; // 深度ステンシルバッファ
ID3D11Texture2D *pDepthStencilTexture = NULL; // 深度ステンシルサーフェイス
ID3D11ShaderResourceView *pRenderTargetShaderResourceView = NULL; // RenderTargetを TextureSampler からアクセス可能にしておく
ID3D11ShaderResourceView *pDepthStencilShaderResourceView = NULL; // DepthStencilを TextureSampler からアクセス可能にしておく
D3D_FEATURE_LEVEL FeatureLevel;
DWORD width, height; // Screen width, Screen height
HRESULT hr;
// デバイス、デバイスコンテキストそしてスワップチェインを生成
hr = CreateDeviceContextAndSwapChain(hWnd,&pDevice,&pContext,&pSwapChain,&DriverType,&FeatureLevel);
if ( FAILED( hr ) )
goto ERROR_EXIT;
// RenderTaget を生成
hr = CreateRenderTargetView(pDevice,pSwapChain,&pRenderTargetView,&pRenderTargetShaderResourceView);
if ( FAILED( hr ) )
goto ERROR_EXIT;
// 深度ステンシルバッファ生成のため Backbuffer のサイズを取得
hr = GetBackBufferSize(pSwapChain,&width, &height);
if ( FAILED( hr ) )
goto ERROR_EXIT;
// サイズとフォーマットを指定して、深度ステンシルバッファを生成
hr = CreateDepthStencilView(pDevice,width,height,DXGI_FORMAT_D16_UNORM,&pDepthStencilView,&pDepthStencilTexture,&pDepthStencilShaderResourceView);
if ( FAILED( hr ) )
goto ERROR_EXIT;
// デバイスコンテキストにレンダーターゲットと深度ステンシルを設定
pContext->OMSetRenderTargets( 1, &pRenderTargetView,pDepthStencilView);
// ビューポートの設定.
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)width;
vp.Height = (FLOAT)height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
// デバイスコンテキストにビューポートを設定.
pContext->RSSetViewports( 1, &vp );
//==========各種オブジェクト生成===================
//=================================================
// メイン メッセージ ループ:
// (2)メッセージループ
FLOAT fAngle = 0;
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
// 指定色で画面クリア
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
pContext->ClearRenderTargetView( pRenderTargetView, ClearColor );
pContext->ClearDepthStencilView( pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
g_uiCount++;
//結果をウインドウに反映
if (FAILED(hr = pSwapChain->Present( 1, 0 ))){
// デバイスロストへの対処は可能だが、ここでは単に終了する事にする
if (hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DEVICE_REMOVED){
MessageBox(NULL,_T("Device が失われましたので終了します"),_T("Assert"),MB_OK);
break;
}
}
}
}
ERROR_EXIT:
if (pContext){
pContext->ClearState();
pContext->Flush();
}
SAFE_RELEASE(pRenderTargetShaderResourceView);
SAFE_RELEASE(pDepthStencilTexture);
SAFE_RELEASE(pDepthStencilShaderResourceView);
SAFE_RELEASE(pRenderTargetView);
SAFE_RELEASE(pDepthStencilView);
SAFE_RELEASE(pSwapChain);
SAFE_RELEASE(pContext);
SAFE_RELEASE(pDevice);
CoUninitialize(); // COM の終了
return (int) msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
【CreateDeviceContextAndSwapChain・・・デバイスとスワップチェインの生成】
Direct3D11 では、Device, DeviceContext, SwapChain の3つを同時に生成します。
以下のプログラムでは、ウィンドウのクライアント領域一杯に表示するよう、
Device, DeviceContext, SwapChain を生成します。それぞれ以下のような
役割を果たします
- Device
- ビデオカードなどのハードウェア固有の処理を抽象化したもの
- DeviceContext
- 描画環境
- SwapChain
- 表示用バッファ(テクスチャ)と描画用バッファの組み合わせ
//=============================================================================
//
// Create DeviceContext and SwapChain
// param :
// hWnd : (in)window's handle
// ppDevice : (out)created device
// ppContext : (out)created device context
// ppSwapChain : (out)swap chain
// pDriverType : (out)device's driver type
// pFeatureLevel : (out)device's feature level
//
HRESULT CreateDeviceContextAndSwapChain(
HWND hWnd,
ID3D11Device **ppDevice,
ID3D11DeviceContext **ppContext,
IDXGISwapChain **ppSwapChain,
D3D_DRIVER_TYPE *pDriverType,
D3D_FEATURE_LEVEL *pFeatureLevel
){
HRESULT hr = E_FAIL;
// デバイス生成フラグ.
UINT createDeviceFlags = 0;
// ドライバータイプ候補
D3D_DRIVER_TYPE driverTypes[] = {
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT numDriverTytpes = sizeof( driverTypes ) / sizeof( driverTypes[0] );
// 機能レベル候補
static const D3D_FEATURE_LEVEL featureLevels[] = {
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
UINT numFeatureLevels = sizeof( featureLevels ) / sizeof( featureLevels[0] );
RECT rc;
GetClientRect( hWnd, &rc );
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
// スワップチェインの構成設定.
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory( &sd, sizeof(DXGI_SWAP_CHAIN_DESC) );
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
for( UINT idx = 0; idx < numDriverTytpes; ++idx ){
// ドライバータイプ設定.
D3D_DRIVER_TYPE DriverType = driverTypes[ idx ];
// デバイスとスワップチェインの生成.
hr = D3D11CreateDeviceAndSwapChain(
NULL,
DriverType,
NULL,
createDeviceFlags,
featureLevels,
numFeatureLevels,
D3D11_SDK_VERSION,
&sd,
ppSwapChain,
ppDevice,
pFeatureLevel,
ppContext
);
*pDriverType = DriverType;
// 成功したらループを脱出.
if ( SUCCEEDED( hr ) )
break;
}
return hr;
}