はかせのラボ

私の頭の中を書いていく雑記ブログです

プログラミング 色々試すためのDirectX11初期化最小構成作ってみた

あいさつ

どうも、はかせです。
今回は今まで触ってたプロジェクトを改造する形での
学習にめんd限界を感じてきたので一回プロジェクトを作り直すことにしました。

それに伴ってどうせなら今後DirectX11で色々やる際に
なるべく手間なくできるようコード量をできる限り少なくしてみました。

コード

実際のコードがこちらです。

#include "stdafx.h"
#include "resource.h"

#include <Windows.h>
#include <d3d11.h>
#include <string>
#include <wrl/client.h>

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

#define WIN_STYLE WS_OVERLAPPEDWINDOW

using namespace Microsoft::WRL;

//ウィンドウクラス作成に必要な情報群
HWND mWindowHandle;
std::string mClassName = _T("main_window");
//表示されるウィンドウの名前
std::string mWindowName = _T("簡単お手軽最小構成(多分)");
//ウィンドウの横幅
UINT mWindowWidth = 1000;
//ウィンドウの縦幅
UINT mWindowHeight = 800;
//DirectXに必要な変数
ComPtr<IDXGISwapChain> mSwapChain;
ComPtr<ID3D11Device> mDevice;
ComPtr<ID3D11DeviceContext> mDeviceContext;
ComPtr<ID3D11RenderTargetView> mRenderTargetView;
//コールバック
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);

//今回のメイン関数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hInstancePrev, LPSTR pCmdLine, int nCmdShow) 
{
	// ウィンドウクラスを登録する
	WNDCLASS windowClass = { 0 };
	windowClass.lpfnWndProc = WinProc;
	windowClass.hInstance = hInstance;
	windowClass.lpszClassName = mClassName.c_str();
	RegisterClass(&windowClass);
	// ウィンドウの作成
	mWindowHandle = CreateWindow(mClassName.c_str(), mWindowName.c_str(), WIN_STYLE, CW_USEDEFAULT, CW_USEDEFAULT, mWindowWidth, mWindowHeight, NULL, NULL, hInstance, NULL);
	if (mWindowHandle == NULL) return 0;
	ShowWindow(mWindowHandle, nCmdShow);
	// メッセージループの実行
	MSG msg = { 0 };
	//背景クリア色
	float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
	while (msg.message != WM_QUIT) 
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else 
		{
			// DirectXのループ処理                        
			mDeviceContext->ClearRenderTargetView(mRenderTargetView.Get(), clearColor);  
			mSwapChain.Get()->Present(0, 0);                                           
		}
	}
	return 0;
}


LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{
	switch (uMsg) 
	{
	case WM_CREATE:
	{
		/*スワップチェインの設定*/
		DXGI_SWAP_CHAIN_DESC swapChain = { 0 };
		swapChain.BufferDesc.Width = mWindowWidth;
		swapChain.BufferDesc.Height = mWindowHeight;
		swapChain.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
		swapChain.BufferDesc.RefreshRate.Numerator = 60;              
		swapChain.BufferDesc.RefreshRate.Denominator = 1;             
		swapChain.SampleDesc.Count = 1;                              
		swapChain.SampleDesc.Quality = 0;                             
		swapChain.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      
		swapChain.BufferCount = 1;                                    
		swapChain.OutputWindow = hwnd;                                
		swapChain.Windowed = TRUE;                                    

		D3D_FEATURE_LEVEL fl = D3D_FEATURE_LEVEL_11_0;
		D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &fl, 1, D3D11_SDK_VERSION, &swapChain, &mSwapChain, &mDevice, NULL, &mDeviceContext);
		//描画先の設定
		ID3D11Texture2D *renderTexture;
		mSwapChain.Get()->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&renderTexture);
		mDevice->CreateRenderTargetView(renderTexture, NULL, &mRenderTargetView);
		renderTexture->Release();
		return 0;
	}
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

行数で言うと100行くらいですね。
ただスワップチェインとバックバッファを作って
Windowsのコールバックで毎フレ更新してるだけです。

基本的な部分しかしてないので実際の作品で使うとかってなると
もうちょい小細工が必要ですが、DirectXのテストをするだけならば
これだけあれば十分かなと思います。

実際の処理とかはまた別にクラス分けして
そのクラスを移植して呼び出すだけでできるようにしようと計画中です。

あとがき

今回はDirectX11最小構成(多分)でした。
(まだ短くできるぜ!という方は是非教えてくださいorz)

最初はめんどくさいなぁと思っていたDirectXでしたが、
ある程度慣れてしまえばそこまでめんどうにも感じないですね。

それでは今回はこの辺でノシ