Skip to content

Instantly share code, notes, and snippets.

@hirosof
Created July 30, 2014 17:10
Show Gist options
  • Save hirosof/e1c8414285183b378f6e to your computer and use it in GitHub Desktop.
Save hirosof/e1c8414285183b378f6e to your computer and use it in GitHub Desktop.
Direct3D 11の基本プログラムです
/*----------------------------------------------------------------------------
プログラム名:D3DBasic
プログラム概要:Direct3D 11の基本プログラムです
--------------------------------------------------------------------------------
*/
//インクルード
#include <windows.h>
#include <stdio.h>
#include <locale.h>
#include <vector>
#include <tchar.h>
#include <d3d11.h>
#pragma comment(lib,"D3D11.lib")
//マニフェスト登録
#pragma comment(linker,"\"/manifestdependency:type='win32' " \
"name='Microsoft.Windows.Common-Controls' " \
"version='6.0.0.0' " \
"processorArchitecture='*' " \
"publicKeyToken='6595b64144ccf1df' " \
"language='*'\"")
//マクロ部
#define PRONAME "D3DIntroduction - Basic" //プログラム名
#define PROVER "1.0.1.0" //プログラムバージョン
#define PRONAME_TXT TEXT(PRONAME) //プログラム名(テキスト)
#define PROVER_TXT TEXT(PROVER) //プログラムバージョン(テキスト)
//プロトタイプ(基本)
ATOM RegistWindowClass(HINSTANCE); /* ウィンドウクラスの登録 */
BOOL CreateMainWindow(HINSTANCE, int); /* ウィンドウの作成 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); /* ウィンドウプロシージャー */
BOOL OnIdle(void);
void OnRender(void);
void OnPaint(void);
//Direct3D関連プロトタイプ宣言
BOOL InitDirect3D(void);
void UninitDirect3D(void);
BOOL CreateD3DDeviceWithSwapChain(D3D_FEATURE_LEVEL *pD3DFeatureLevels, int NumberOfFeatureLevels, DXGI_SWAP_CHAIN_DESC *psd);
BOOL D3DBackBuffarSetup(void);
BOOL D3DDepthAndStencilBufferSetup(void);
BOOL CheckDevice(void);
//構造体宣言部
//Direct3Dデータ構造体
struct MyD3D_Data {
ID3D11Device *pDevice;
ID3D11DeviceContext *pDeviceContext;
IDXGISwapChain *pSwapChain;
ID3D11RenderTargetView *pRenderTargetView;
ID3D11Texture2D *pDepthStencil;
ID3D11DepthStencilView *pDepthStencilView;
D3D11_VIEWPORT ViewPort;
struct {
D3D_FEATURE_LEVEL RunningFeatureLevel;
}Info;
};
#ifdef _DEBUG
//通常
#define SET_CONSOLETEXTCOLOR_NORMAL SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY )
//エラー
#define SET_CONSOLETEXTCOLOR_FOR_ERROR SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
FOREGROUND_RED |FOREGROUND_INTENSITY )
//情報
#define SET_CONSOLETEXTCOLOR_FOR_INFORMATION SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
FOREGROUND_BLUE | FOREGROUND_GREEN|FOREGROUND_INTENSITY )
#endif
//定数部
const SIZE WindowClientSize = { 640, 480 };
const bool WindowSizeChangeByUserFlag = false;
//グローバル変数部
TCHAR szClassName[] = PRONAME_TXT; //ウィンドウクラス名
HWND hWindow = NULL;
HINSTANCE hInstance = NULL;
//Direct3Dデータ
MyD3D_Data D3DData = { NULL };
bool bInitializedD3D = false;
//メイン関数
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) {
MSG msg = { 0 };
//インスタンスハンドルをグローバル変数にコピー
hInstance = hCurInst;
#ifdef _DEBUG
//デバッグモードの場合コンソールを初期化する
FILE *fpConsoleWriter;
//コンソールを割り当てる
AllocConsole();
//コンソールのタイトルを変更する
SetConsoleTitle(TEXT("Direct3DApp - Debug Console"));
//ロケールを設定
_tsetlocale(LC_ALL, TEXT("Japanese"));
//標準出力系関数を使用できるようにする
freopen_s(&fpConsoleWriter, "CONOUT$", "w", stdout);
//コンソールウィンドウのタイトルバーのシステムメニューを消す
HWND hConsole = GetConsoleWindow();
int Style = GetWindowLong(hConsole, GWL_STYLE);
SetWindowLong(hConsole, GWL_STYLE, Style & ~WS_SYSMENU);
_tprintf(TEXT("%s デバッグコンソール\n\n"), PRONAME_TXT);
#endif
//ウィンドウクラスの登録
if (!RegistWindowClass(hCurInst)) return FALSE;
//ウィンドウ作成
if (!CreateMainWindow(hCurInst, nCmdShow)) return FALSE;
//Direct3D初期化
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_NORMAL;
_tprintf(TEXT("Direct3D の初期化を行います。\n"));
#endif
if (InitDirect3D()) {
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_FOR_INFORMATION;
_tprintf(TEXT("Direct3D の初期化に成功しました。\n"));
#endif
bInitializedD3D = true;
//メッセージループ(PeekMessage版)
do {
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}else {
if (!OnIdle()) {
DestroyWindow(hWindow);
}
}
} while (msg.message != WM_QUIT);
}else {
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_FOR_ERROR;
_tprintf(TEXT("Direct3D の初期化に失敗しました。\n"));
MessageBox(hConsole, TEXT("Direct3Dの初期化に失敗しました。"), PRONAME_TXT, MB_ICONERROR);
#else
MessageBox(hWindow, TEXT("Direct3Dの初期化に失敗しました。"), PRONAME_TXT, MB_ICONERROR);
#endif
}
//Direct3D終了処理
UninitDirect3D();
#ifdef _DEBUG
FreeConsole();
#endif
return (int)msg.wParam;
}
//ウィンドウクラス登録関数
ATOM RegistWindowClass(HINSTANCE hInst) {
WNDCLASSEX wc; //WNDCLASSEX構造体
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = WndProc; //プロシージャ名
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst; //インスタンス
wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL; //メニュー名
wc.lpszClassName = szClassName;
wc.hIconSm = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
return RegisterClassEx(&wc);
}
//メインウィンドウを作る関数
BOOL CreateMainWindow(HINSTANCE hInst, int nCmdShow) {
HWND hwnd;
int WindowStyle;
//ウィンドウスタイル
WindowStyle = WS_OVERLAPPEDWINDOW;
//ウィンドウサイズ固定ならばオーバーラップウィンドウから
//サイズ変更境界と最大化ボタンを無効化にする
if (WindowSizeChangeByUserFlag == 0)
WindowStyle &= ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
//ウィンドウサイズを計算
RECT windowRect = { 0 };
windowRect.right = WindowClientSize.cx;
windowRect.bottom = WindowClientSize.cy;
if (AdjustWindowRectEx(&windowRect, WindowStyle, FALSE, NULL) == FALSE)return FALSE;
windowRect.right += abs(windowRect.left);
windowRect.bottom += abs(windowRect.top);
//ウィンドウ作成
hwnd =
CreateWindowEx(NULL,
szClassName,
//タイトルバーにこの文字列が表示されます
PRONAME_TXT,
WindowStyle,//ウィンドウの種類
CW_USEDEFAULT, //x座標
CW_USEDEFAULT,//y座標
windowRect.right, //幅
windowRect.bottom,//高さ
NULL,//親ウィンドウのハンドル、親を作るときはNULL
NULL,//メニューハンドル、クラスメニューを使うときはNULL
hInst,//インスタンスハンドル
NULL);
if (!hwnd)return FALSE;
//ウィンドウ表示
ShowWindow(hwnd, nCmdShow);
//ウィンドウ更新
UpdateWindow(hwnd);
return TRUE;
}
//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
//メッセージごとの処理
switch (msg) {
case WM_CREATE:
hWindow = hwnd;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wp, lp);
}
return 0;
}
//Direct3D初期化関数
BOOL InitDirect3D(void) {
//Direct3D 11 機能レベル(候補)
D3D_FEATURE_LEVEL D3DFeatureLevels[] = { D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
//Direct3D 11 機能レベル(候補)の数
UINT NumberOfFeatureLevels = sizeof(D3DFeatureLevels) / sizeof(D3D_FEATURE_LEVEL);
//スワップチェインの初期化設定
DXGI_SWAP_CHAIN_DESC sd = { 0 };
sd.BufferCount = 1;
sd.BufferDesc.Width = WindowClientSize.cx;
sd.BufferDesc.Height = WindowClientSize.cy;
sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.OutputWindow = hWindow;
sd.Windowed = TRUE;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
//Direct3D デバイスとスワップチェインの作成
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_NORMAL;
_tprintf(TEXT("Direct3D デバイスの作成をします。\n"));
#endif
if (!CreateD3DDeviceWithSwapChain(D3DFeatureLevels, NumberOfFeatureLevels, &sd)) {
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_FOR_ERROR;
_tprintf(TEXT("Direct3D デバイスの作成に失敗しました。\n"));
#endif
return FALSE;
}
//バックバッファの設定
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_NORMAL;
_tprintf(TEXT("バックバッファの設定をします。\n"));
#endif
if (!D3DBackBuffarSetup()) {
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_FOR_ERROR;
_tprintf(TEXT("バックバッファの設定に失敗しました。\n"));
#endif
return FALSE;
}
//深度・ステンシル・バッファ設定
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_NORMAL;
_tprintf(TEXT("深度・ステンシル・バッファの設定をします。\n"));
#endif
if (!D3DDepthAndStencilBufferSetup()) {
#ifdef _DEBUG
SET_CONSOLETEXTCOLOR_FOR_ERROR;
_tprintf(TEXT("深度・ステンシル・バッファの設定に失敗しました。\n"));
#endif
return FALSE;
}
return TRUE;
}
//デバイスとスワップチェインを作成
BOOL CreateD3DDeviceWithSwapChain(D3D_FEATURE_LEVEL *pD3DFeatureLevels, int NumberOfFeatureLevels, DXGI_SWAP_CHAIN_DESC *psd) {
//ドライバタイプ
D3D_DRIVER_TYPE DriverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE };
HRESULT hr = E_FAIL;
for (int i = 0; i < (sizeof(DriverTypes) / sizeof(D3D_DRIVER_TYPE)); i++) {
hr = D3D11CreateDeviceAndSwapChain(NULL,
DriverTypes[i],
NULL,
NULL,
pD3DFeatureLevels,
NumberOfFeatureLevels,
D3D11_SDK_VERSION,
psd,
&D3DData.pSwapChain,
&D3DData.pDevice,
&D3DData.Info.RunningFeatureLevel,
&D3DData.pDeviceContext);
if (SUCCEEDED(hr)) break;
}
if (FAILED(hr)) return FALSE;
return TRUE;
}
//バックバッファの設定
BOOL D3DBackBuffarSetup(void) {
HRESULT hr;
ID3D11Texture2D *pTexture;
hr = D3DData.pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pTexture));
if (FAILED(hr)) {
return FALSE;
}
hr = D3DData.pDevice->CreateRenderTargetView(pTexture, NULL, &D3DData.pRenderTargetView);
pTexture->Release();
if (FAILED(hr)) {
return FALSE;
}
D3DData.pDeviceContext->OMSetRenderTargets(1, &D3DData.pRenderTargetView, NULL);
D3D11_VIEWPORT vp = { 0 };
vp.TopLeftX = 0;
vp.TopLeftY = 0;
vp.Width = 1.0f * WindowClientSize.cx;
vp.Height = 1.0f * WindowClientSize.cy;
vp.MinDepth = 0;
vp.MaxDepth = 1;
D3DData.ViewPort = vp;
return TRUE;
}
//深度・ステンシル・バッファ設定
BOOL D3DDepthAndStencilBufferSetup(void) {
//深度・ステンシル テクスチャの作成
D3D11_TEXTURE2D_DESC descDepth = { 0 };
descDepth.Width = WindowClientSize.cx;
descDepth.Height = WindowClientSize.cy;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D32_FLOAT;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
HRESULT hr = D3DData.pDevice->CreateTexture2D(&descDepth, NULL, &D3DData.pDepthStencil);
if (FAILED(hr))return FALSE;
D3D11_DEPTH_STENCIL_VIEW_DESC dsViewDesc;
dsViewDesc.Format = descDepth.Format;
dsViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
dsViewDesc.Flags = 0;
dsViewDesc.Texture2D.MipSlice = 0;
hr = D3DData.pDevice->CreateDepthStencilView(D3DData.pDepthStencil, &dsViewDesc, &D3DData.pDepthStencilView);
if (FAILED(hr))return FALSE;
return TRUE;
}
//アイドル時の処理
BOOL OnIdle(void) {
if (!CheckDevice())return FALSE;
if (D3DData.pSwapChain->Present(0, DXGI_PRESENT_TEST) != DXGI_STATUS_OCCLUDED) {
OnRender();
}
return TRUE;
}
//デバイスの消滅の検査
BOOL CheckDevice(void) {
HRESULT hr = D3DData.pDevice->GetDeviceRemovedReason();
switch (hr) {
case S_OK:
break;
case DXGI_ERROR_DEVICE_HUNG:
case DXGI_ERROR_DEVICE_RESET:
UninitDirect3D();
if (!InitDirect3D())return FALSE;
break;
default:
return FALSE;
}
return TRUE;
}
//描画処理
void OnRender(void) {
float bgColor[4] = { 0.0f, 0.0f ,0.25f, 1.0f };
D3DData.pDeviceContext->ClearRenderTargetView(D3DData.pRenderTargetView, bgColor);
D3DData.pDeviceContext->ClearDepthStencilView(D3DData.pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
D3DData.pDeviceContext->RSSetViewports(1, &D3DData.ViewPort);
D3DData.pDeviceContext->OMSetRenderTargets(1, &D3DData.pRenderTargetView, D3DData.pDepthStencilView);
OnPaint();
D3DData.pSwapChain->Present(0, 0);
}
//表示する内容の描画
void OnPaint(void) {
}
//Direct3D終了処理
void UninitDirect3D(void) {
MyD3D_Data ClearData = { 0 };
std::vector<IUnknown*> cFreeTargetInterfaceArray;
IUnknown *pCurrentTarget;
if (D3DData.pDeviceContext)D3DData.pDeviceContext->ClearState();
//解放するインタフェースクラスを追加
cFreeTargetInterfaceArray.clear();
cFreeTargetInterfaceArray.push_back(D3DData.pDepthStencilView);
cFreeTargetInterfaceArray.push_back(D3DData.pDepthStencil);
cFreeTargetInterfaceArray.push_back(D3DData.pRenderTargetView);
cFreeTargetInterfaceArray.push_back(D3DData.pSwapChain);
cFreeTargetInterfaceArray.push_back(D3DData.pDeviceContext);
cFreeTargetInterfaceArray.push_back(D3DData.pDevice);
//解放
for (unsigned int i = 0; i < cFreeTargetInterfaceArray.size(); i++) {
pCurrentTarget = cFreeTargetInterfaceArray[i];
if (pCurrentTarget)pCurrentTarget->Release();
}
D3DData = ClearData;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment