//----------------------------------------------------------
//
// 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;
}
//=============================================================================
//
// 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;
}
//=============================================================================
//
// Create Render Target
// param :
// pDevice : (in)Direct3D device object
// pSwapChain : (in)device's swap chain
// ppRenderTargetView : (out)Created render target view
// ppRenderTargetShaderResourceView : (out)render target's shader resource view
//
HRESULT CreateRenderTargetView(
ID3D11Device *pDevice,
IDXGISwapChain *pSwapChain,
ID3D11RenderTargetView **ppRenderTargetView,
ID3D11ShaderResourceView **ppRenderTargetShaderResourceView
){
ID3D11Texture2D *pBackBuffer = NULL;
HRESULT hr = E_FAIL;
// スワップチェインよりバックバッファを取得.
hr = pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBackBuffer );
if ( FAILED( hr ) )
goto ERROR_EXIT;
// バックバッファより、レンダーターゲットを生成.
hr = pDevice->CreateRenderTargetView( pBackBuffer, NULL, ppRenderTargetView );
if ( FAILED( hr ) )
goto ERROR_EXIT;
// レンダーターゲットのシェーダリソースビューを生成.
hr = pDevice->CreateShaderResourceView( pBackBuffer, NULL, ppRenderTargetShaderResourceView );
if ( FAILED( hr ) )
goto ERROR_EXIT;
ERROR_EXIT:
SAFE_RELEASE(pBackBuffer); // バックバッファを開放
return hr;
}
//=============================================================================
//
// create depth-stencil view
// param :
// pDevice : (in)Direct3D device
// width : (in)screen width
// height : (in)screen height
// fmtDepthStencil : (in)depth stencil format.
// ppDepthStencilView : (out)depth stencil buffer
// ppDepthStencilTexture : (out)depth stencil surface texture
// ppDepthStencilShaderResourceView : (out)depth-stencil's shader resource view
//
HRESULT CreateDepthStencilView(
ID3D11Device *pDevice,
INT width,
INT height,
DXGI_FORMAT fmtDepthStencil,
ID3D11DepthStencilView **ppDepthStencilView,
ID3D11Texture2D **ppDepthStencilTexture,
ID3D11ShaderResourceView **ppDepthStencilShaderResourceView
){
DXGI_FORMAT textureFormat = DXGI_FORMAT_R16_TYPELESS;
DXGI_FORMAT resourceFormat = DXGI_FORMAT_R16_UNORM;
HRESULT hr = E_FAIL;
// 深度ステンシルテクスチャとシェーダリソースビューのフォーマットを
// 適切なものに変更.
switch( fmtDepthStencil )
{
case DXGI_FORMAT_D16_UNORM:
textureFormat = DXGI_FORMAT_R16_TYPELESS;
resourceFormat = DXGI_FORMAT_R16_UNORM;
break;
case DXGI_FORMAT_D24_UNORM_S8_UINT:
textureFormat = DXGI_FORMAT_R24G8_TYPELESS;
resourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
break;
case DXGI_FORMAT_D32_FLOAT:
textureFormat = DXGI_FORMAT_R32_TYPELESS;
resourceFormat = DXGI_FORMAT_R32_FLOAT;
break;
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
textureFormat = DXGI_FORMAT_R32G8X24_TYPELESS;
resourceFormat = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
break;
default:
hr = E_FAIL;
goto ERROR_EXIT;
}
// 深度ステンシルテクスチャの生成.
D3D11_TEXTURE2D_DESC td;
ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
td.Width = width;
td.Height = height;
td.MipLevels = 1;
td.ArraySize = 1;
td.Format = textureFormat;
td.SampleDesc.Count = 1; // MULTI SAMPLE COUNT
td.SampleDesc.Quality = 0; // MULtI SAMPLE QUALITY
td.Usage = D3D11_USAGE_DEFAULT;
td.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
td.CPUAccessFlags = 0;
td.MiscFlags = 0;
// 深度ステンシルテクスチャの生成.
hr = pDevice->CreateTexture2D( &td, NULL, ppDepthStencilTexture );
if ( FAILED( hr ) )
goto ERROR_EXIT;
// 深度ステンシルビューの設定.
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
ZeroMemory( &dsvd, sizeof( D3D11_DEPTH_STENCIL_VIEW_DESC ) );
dsvd.Format = fmtDepthStencil;
if ( td.SampleDesc.Count == 0 )
{
dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
dsvd.Texture2D.MipSlice = 0;
}
else
{
dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
}
// 深度ステンシルビューの生成.
hr = pDevice->CreateDepthStencilView( *ppDepthStencilTexture, &dsvd, ppDepthStencilView );
if ( FAILED( hr ) )
{
goto ERROR_EXIT;
}
// シェーダリソースビューの設定.
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
ZeroMemory( &srvd, sizeof( D3D11_SHADER_RESOURCE_VIEW_DESC ) );
srvd.Format = resourceFormat;
if ( td.SampleDesc.Count == 0 )
{
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvd.Texture2D.MostDetailedMip = 0;
srvd.Texture2D.MipLevels = 1;
}
else
{
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
}
// シェーダリソースビューを生成.
hr = pDevice->CreateShaderResourceView( *ppDepthStencilTexture, &srvd, ppDepthStencilShaderResourceView );
if ( FAILED( hr ) )
{
goto ERROR_EXIT;
}
ERROR_EXIT:
return hr;
}
//=============================================================================
//
// Get back-buffer size from swap chain
// param :
// pSwapChain : (in)swap chain
// pWidth : (out)back-buffer width
// pHeight : (out)back-buffer height]
//
HRESULT GetBackBufferSize(IDXGISwapChain *pSwapChain, DWORD *pWidth, DWORD *pHeight){
ID3D11Texture2D *pBackBuffer = NULL;
HRESULT hr = E_FAIL;
D3D11_TEXTURE2D_DESC desc;
// スワップチェインよりバックバッファを取得.
hr = pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ),
(LPVOID*)&pBackBuffer );
if ( FAILED( hr ) )
goto ERROR_EXIT;
pBackBuffer->GetDesc(&desc);
*pWidth = (DWORD)desc.Width;
*pHeight = (DWORD)desc.Height;
hr = S_OK;
ERROR_EXIT:
SAFE_RELEASE(pBackBuffer);
return hr;
}
//=============================================================================
//
// Debug utility
// Get the name of driver type
//
TCHAR *GetDriverTypeText(D3D_DRIVER_TYPE dt){
switch(dt){
case D3D_DRIVER_TYPE_UNKNOWN:
return _T("D3D_DRIVER_TYPE_UNKNOWN");
case D3D_DRIVER_TYPE_HARDWARE:
return _T("D3D_DRIVER_TYPE_HARDWARE");
case D3D_DRIVER_TYPE_REFERENCE:
return _T("D3D_DRIVER_TYPE_REFERENCE");
case D3D_DRIVER_TYPE_NULL:
return _T("D3D_DRIVER_TYPE_NULL");
case D3D_DRIVER_TYPE_SOFTWARE:
return _T("D3D_DRIVER_TYPE_SOFTWARE");
case D3D_DRIVER_TYPE_WARP:
return _T("D3D_DRIVER_TYPE_WARP");
}
return NULL;
}
//=============================================================================
//
// Debug utility
// Get the name of feature level
//
TCHAR *GetFeatureLevelText(D3D_FEATURE_LEVEL fl){
switch(fl){
case D3D_FEATURE_LEVEL_9_1:
return _T("D3D_FEATURE_LEVEL_9_1");
case D3D_FEATURE_LEVEL_9_2:
return _T("D3D_FEATURE_LEVEL_9_2");
case D3D_FEATURE_LEVEL_9_3:
return _T("D3D_FEATURE_LEVEL_9_3");
case D3D_FEATURE_LEVEL_10_0:
return _T("D3D_FEATURE_LEVEL_10_0");
case D3D_FEATURE_LEVEL_10_1:
return _T("D3D_FEATURE_LEVEL_10_1");
case D3D_FEATURE_LEVEL_11_0:
return _T("D3D_FEATURE_LEVEL_11_0");
}
return NULL;
}