DirectX11の初期化

DirectX11を触り始めたのでメモ書きに書いておきます。
Windows7以降であれば動くと思います。
多少説明をしていますがわからないところは説明がないです。
動かなければコメント、Twitterで報告していただけると助かります。

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

#include <tchar.h>
#include <Windows.h>
#include <D3D11.h>
#include <D3DX11.h>
#include <DxErr.h>

#define SAFE_RELEASE(x) { if(x){ (x)->Release(); (x)=nullptr; } }

#define WINDOW_W 640
#define WINDOW_H 480

// ウィンドウ
HWND g_HWnd;

// 機能レベル
D3D_FEATURE_LEVEL	g_pFeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
UINT			g_FeatureLevels    = 3;	  // 配列の要素数
D3D_FEATURE_LEVEL	g_FeatureLevelsSupported; // デバイス作成時に返される機能レベル

// インターフェイス
ID3D11Device*		g_pD3DDevice        = nullptr;	// デバイス
ID3D11DeviceContext*	g_pImmediateContext = nullptr;	// デバイス・コンテキスト
IDXGISwapChain*		g_pSwapChain        = nullptr;	// スワップ・チェイン

ID3D11RenderTargetView*	g_pRenderTargetView = nullptr;	// 描画ターゲット・ビュー
D3D11_VIEWPORT		g_ViewPort[1];			// ビューポート
ID3D11Texture2D*	g_pDepthStencil;		// 深度/ステンシル・テクスチャを受け取る変数
ID3D11DepthStencilView*	g_pDepthStencilView = nullptr;		// 深度/ステンシルビュー

void InitWindow();	 // ウィンドウ生成
HRESULT InitD3D();	 // D3D初期化
void CleanupD3D();	 // D3D後処理
bool DeviceRemoveProc(); // デバイス消失処理

void Clear();            // 画面クリア
HRESULT Flip();          // 画面表示

// エントリポイント
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	InitWindow();
	ShowWindow(g_HWnd, SW_SHOWDEFAULT);
	UpdateWindow(g_HWnd);

	if (FAILED(InitD3D()))
	{
		return 0;
	}

	MSG msg = {};
	ZeroMemory(&msg, sizeof(msg));
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			// デバイス消失処理
			if (DeviceRemoveProc()) break;

			// ゲームループ
			Clear();

			Flip();
		}
	}

	// 解放
	CleanupD3D();

	return 0;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

// ウィンドウ生成
void InitWindow()
{
	WNDCLASSEX wc = {
		sizeof(WNDCLASSEX),
		CS_CLASSDC,
		WindowProc,
		0L,
		0L,
		GetModuleHandle(NULL),
		NULL,
		NULL, 
		NULL,
		NULL,
		L"sample",
		NULL
	};
	RegisterClassEx(&wc);

	g_HWnd = CreateWindow(L"sample", L"DirectX11 sample" , WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_W, WINDOW_H, NULL, NULL, wc.hInstance, NULL);
}

// D3D初期化
HRESULT InitD3D()
{
	HRESULT hr = S_OK;

	DXGI_SWAP_CHAIN_DESC sd;
	ZeroMemory(&sd, sizeof(sd));
	sd.BufferCount          = 1;		// バックバッファの数
	sd.BufferDesc.Width     = WINDOW_W;	// バックバッファの幅
	sd.BufferDesc.Height    = WINDOW_H;	// バックバッファの高さ
	sd.BufferDesc.Format    = DXGI_FORMAT_R8G8B8A8_UNORM; // フォーマット
	sd.BufferDesc.RefreshRate.Numerator	= 60;	// リフレッシュレート(分子)
	sd.BufferDesc.RefreshRate.Denominator   = 1;	// リフレッシュレート(分母)
	sd.BufferDesc.ScanlineOrdering  = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	sd.BufferDesc.Scaling           = DXGI_MODE_SCALING_UNSPECIFIED;
	sd.BufferUsage		= DXGI_USAGE_RENDER_TARGET_OUTPUT; // バックバッファの使用方法
	sd.OutputWindow		= g_HWnd;	// 関連付けるウィンドウ
	sd.SampleDesc.Count	= 1;		// マルチサンプルの数
	sd.SampleDesc.Quality	= 0;		// マルチサンプルのクオリティ
	sd.Windowed		= TRUE;		// ウィンドウモード
	sd.Flags		= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // モード自動切り替え

	// デバイスとスワップチェインの作成
	hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, g_pFeatureLevels, 1, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, NULL, &g_pImmediateContext);
	if (FAILED(hr))
	{
		hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, g_pFeatureLevels, 1, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, NULL, &g_pImmediateContext);
		if (FAILED(hr))
		{
			hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, 0, g_pFeatureLevels, 1, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, NULL, &g_pImmediateContext);
			if (FAILED(hr))
				return E_FAIL;
		}
	}
	

	// バックバッファを描画ターゲットに設定
	// スワップチェインから最初のバックバッファを取得する
	ID3D11Texture2D* pBackBuffer; // バッファのアクセスに使うインターフェイス(バッファを2Dテクスチャとして扱う)
	hr = g_pSwapChain->GetBuffer(
		0,				// バックバッファのバン某
		__uuidof(ID3D11Texture2D),	// バッファにアクセスするインターフェイス
		(LPVOID*)&pBackBuffer		// バッファを受け取る変数
	);
	if (FAILED(hr))
		return E_FAIL;

	// バックバッファの描画ターゲットビューを作る
	hr = g_pD3DDevice->CreateRenderTargetView(
		pBackBuffer,			// ビューでアクセスするリソース
		NULL,				// 描画ターゲットビューの定義
		&g_pRenderTargetView            // 描画ターゲットビューを受け取る変数
	);
	if (FAILED(hr))
		return E_FAIL;

	// 描画ターゲットビューを出力マージャーの描画ターゲットとして設定
	g_pImmediateContext->OMSetRenderTargets(
		1,			        // 描画ターゲットの数
		&g_pRenderTargetView,	        // 描画ターゲットビューの配列
		NULL			        // 深度/ステンシルビューを設定しない
	);

	// ビューポートの設定(描画領域)
	g_ViewPort[0].TopLeftX	= 0.0f;		// ビューポート領域の左上X座標
	g_ViewPort[0].TopLeftY	= 0.0f;		// ビューポート領域の左上Y座標
	g_ViewPort[0].Width	= WINDOW_W;	// ビューポート領域の幅
	g_ViewPort[0].Height	= WINDOW_H;	// ビューポート領域の高さ
	g_ViewPort[0].MinDepth	= 0.0f;		// ビューポート領域の深度値の最小値
	g_ViewPort[0].MaxDepth	= 1.0f;		// ビューポート領域の深度値の最大値
	// ラスタライザにビューポートを設定
	g_pImmediateContext->RSSetViewports(1, g_ViewPort);

	// 深度/ステンシル・テクスチャの作成
	D3D11_TEXTURE2D_DESC descDepth;
	descDepth.Width		= WINDOW_W;     // 幅
	descDepth.Height	= WINDOW_H;	// 高さ
	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;	// 深度/ステンシルとして使用
	descDepth.CPUAccessFlags	= 0;    // CPUからアクセスしない
	descDepth.MiscFlags		= 0;    // その他の設定なし
	hr = g_pD3DDevice->CreateTexture2D(
		&descDepth,		// 作成する2Dテクスチャ
		NULL,			// 
		&g_pDepthStencil	// 作成したテクスチャを受け取る
	);
	if (FAILED(hr))
		return E_FAIL;

	// 深度/ステンシルビューの作成
	D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
	descDSV.Format = descDepth.Format;
	descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
	descDSV.Flags = 0;
	descDSV.Texture2D.MipSlice = 0;
	hr = g_pD3DDevice->CreateDepthStencilView(
		g_pDepthStencil,	// 深度/ステンシルビューを作るテクスチャ
		&descDSV,		// 深度/ステンシルビューの設定
		&g_pDepthStencilView	// 作成したビューを受け取る
	);
	if (FAILED(hr))
		return E_FAIL;

	return S_OK;
}

// 後処理
void CleanupD3D()
{
	// ステートのクリア
	if (g_pImmediateContext)
		g_pImmediateContext->ClearState();

	// インターフェイスの解放
	SAFE_RELEASE(g_pDepthStencilView);
	SAFE_RELEASE(g_pDepthStencil);
	SAFE_RELEASE(g_pRenderTargetView);
	SAFE_RELEASE(g_pSwapChain);
	SAFE_RELEASE(g_pImmediateContext);
	SAFE_RELEASE(g_pD3DDevice);
}
// デバイス消失処理
bool DeviceRemoveProc()
{
	HRESULT hr = g_pD3DDevice->GetDeviceRemovedReason();
	switch (hr)
	{
	case S_OK:
		break;
	case DXGI_ERROR_DEVICE_HUNG:
	case DXGI_ERROR_DEVICE_RESET:
		CleanupD3D();
		hr = InitD3D();
		if (FAILED(hr))
			return true;
	case DXGI_ERROR_DEVICE_REMOVED:
	case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
	case DXGI_ERROR_INVALID_CALL:
	default:
		return true;
	}

	return false;
}

// クリア
void Clear()
{
	// 描画ターゲットのクリア
	float clearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // クリアする値
	g_pImmediateContext->ClearRenderTargetView(
		g_pRenderTargetView,	// クリアする描画ターゲット
		clearColor		// クリアする値
	);

	// 深度/ステンシル値のクリア
	g_pImmediateContext->ClearDepthStencilView(
		g_pDepthStencilView,	// クリアする深度/ステンシルビュー
		D3D11_CLEAR_DEPTH,	// 深度値だけクリアする
		1.0f,			// 深度バッファをクリアする値
		0			// ステンシルバッファをクリアする値(今回は関係なし)
	);
}
// 描画
HRESULT Flip()
{
	// バックバッファの表示
	HRESULT hr = g_pSwapChain->Present(
		0,	// 画面をすぐに更新する
		0	// 画面を実際に更新する
	);

	return hr;
}

現状報告

お久しぶりです。

唐突ですが、
4月1日でプログラマーとしてゲーム会社に正社員として働くことになりました。

今までは学生だったのでアルバイトで働いていました。

これからはプロとしてゲームを開発する立場になったので、一層身を引き締めて精進していきます。


以上です。

XAudio2の初期化&現状報告

お久しぶりです。EFです。

なかなかブログを書く気力がなく放置してました。
すみません。

いろいろあって学校を卒業して、今はアルバイトで働きながらニートしてます。


そういうことで最近触り始めたXAudio2の初期化を書きます。

その前に、XAudio2とは何ぞや?って人がいると思うので一言で説明すると、
「DirectSoundの後継」です。

XBOXとかあの辺と一緒になった感じだと思っていただければいいかと思います。(知識不足なので違うかもしれません)

そんなわけで以下は初期化コード。
事前にプロジェクトのVC++ディレクトリのインクルードディレクトリとライブラリディレクトリにDirectXのパスを通しておくこと。

// ----------------------------------include
#include <xaudio2.h>

// ----------------------------------global
IXAudio2*                g_pXAudio2 = nullptr;
IXAudio2MasteringVoice*  g_pXAudio2MasteringVoice = nullptr;

// ----------------------------------prototype
bool Init(); // 初期化関数
void Cleanup(); // 後処理関数

// エントリポイント
int main()
{
    if ( Init() )
    {
        // 初期化失敗
        Cleanup();
        return 1;
    }

    // 初期化成功
   
    
    // 後処理
    Cleanup();

    return 0;
}

// 初期化関数
bool Init()
{

    // COMライブラリ初期化
    if ( FAILED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) )
    {
        return true;
    }

    // XAudio2のインスタンスを生成
    if ( FAILED( XAudio2Create( &g_pXAudio2, 0 ) ) )
    {
        return true;
    }

    // MasteringVoiceの生成
    if ( FAILED( g_pXAudio2->CreateMasteringVoice( &g_pXAudio2MasteringVoice ) ) )
    {
        return true;
    }

    return false;
}

// 後処理関数
void Cleanup()
{
    // MasteringVoiceが生成されていれば破棄
    if ( g_pXAudio2MasteringVoice != nullptr )
    {
        g_pXAudio2MasteringVoice->DestroyVoice();
        g_pXAudio2MasteringVoice = nullptr;
    }

    // XAudio2が生成されていれば破棄
    if ( g_pXAudio2 != nullptr )
    {
        g_pXAudio2->Release();
        g_pXAudio2 = nullptr;
    }

    // COMの破棄
    CoUninitialize();
}

コピペしてるわけではないので誤字があるかもしれません。
ちょっとだけ綺麗に書くように心がけてみました。
HRESULTでエラーを返すようなことはしてませんが、その辺がわかる人はちゃんと返しましょう。


今回はここまでです。お疲れ様でした。

OpenGL始めました

ラインで立方体描く!
マウス左ボタンで立方体が回転!
(ただのメモ書きなんて言えない…)

#include <stdlib.h>

#include <GL/glut.h>
#include <string>

using namespace std;

#define MAX_POINTS 100		// 記憶する点の数
GLint point[MAX_POINTS][2];	// 座標を記憶する配列
int pointNum = 0;		// 記憶した座標の数
int rubberBand = 0;		// ラバーバンドの消去

GLdouble vertex[][3] = 
{
	{ 0.0, 0.0, 0.0 }, 
	{ 1.0, 0.0, 0.0 }, 
	{ 1.0, 1.0, 0.0 }, 
	{ 0.0, 1.0, 0.0 }, 
	{ 0.0, 0.0, 1.0 }, 
	{ 1.0, 0.0, 1.0 }, 
	{ 1.0, 1.0, 1.0 }, 
	{ 0.0, 1.0, 1.0 }  
};

int edge[][2] = 
{
	{ 0, 1 },
	{ 1, 2 },
	{ 2, 3 },
	{ 3, 0 },
	{ 4, 5 },
	{ 5, 6 },
	{ 6, 7 },
	{ 7, 4 },
	{ 0, 4 },
	{ 1, 5 },
	{ 2, 6 },
	{ 3, 7 } 
};

void Display();
void Init();
void Resize(int w, int h);
void Mouse(int button, int state, int x, int y);
void Keybord(unsigned char key, int x, int y);
void Idle();

int main(int argc, char* argv[])
{
	string winName = "test window";

	// OpenGL初期化
	glutInit(&argc, argv);

	// ディスプレイの表示モード設定
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);

	// ウィンドウ生成
	glutInitWindowPosition(0, 0);
	glutInitWindowSize(400, 400);
	glutCreateWindow(winName.c_str());

	// ウィンドウが開かれたり、隠れて再び現れたりするとウィンドウを再描画する関数
	glutDisplayFunc(Display);

	// なにこれ
	glutReshapeFunc(Resize);

	// マウス
	glutMouseFunc(Mouse);

	// キーボード
	glutKeyboardFunc(Keybord);

	// アプリケーション初期化
	Init();

	// メインループ
	glutMainLoop();

	return 0;
}

void Display()
{
	// ウィンドウのクリア関数
	glClear(GL_COLOR_BUFFER_BIT);

	glLoadIdentity();
	
	// 視点位置と視線方向
	gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	// 図形の回転
	static int rot = 0;
	glRotated((double)rot, 0.0, 1.0, 0.0);

	// 図形の描画
	glColor3d(0.0, 1.0, 0.0);
	glBegin(GL_LINES);
	for (int i = 0; i < 12; i++)
	{
		glVertex3dv(vertex[edge[i][0]]);
		glVertex3dv(vertex[edge[i][1]]);
	}
	glEnd();

	glutSwapBuffers();

	// 1周回ったら回転角を0に戻す
	if (++rot >= 360) rot = 0;
}

void Mouse(int button, int state, int x, int y)
{
	switch (button)
	{
	case GLUT_LEFT_BUTTON:
		if (state == GLUT_DOWN)
		{
			// アニメーション開始
			glutIdleFunc(Idle);
		}
		else
		{
			glutIdleFunc(0);
		}
		break;
	case GLUT_RIGHT_BUTTON:
		if (state == GLUT_DOWN)
		{
			glutPostRedisplay();
		}
		break;

	default:
		break;
	}
}

void Idle()
{
	glutPostRedisplay();
}

void Resize(int w, int h)
{
	glViewport(0, 0, w, h);

	// プロジェクション変換行列
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

	// ビュー変換行列
	glMatrixMode(GL_MODELVIEW);
}


void Keybord(unsigned char key, int x, int y)
{
	switch (key)
	{
	case 'q':
	case 'Q':
	case '\033':	// '\033'はESCのASCIIコード
		exit(0);
	default:
		break;
	}
}

void Init()
{
	glClearColor(0.3, 0.3, 0.3, 1.0);
}

f:id:EorF:20151119020134p:plain

参考サイト:
GLUTによる「手抜き」OpenGL入門

TokyoEDGE2015参加しました。

今日はEvent for Diverse Game Engineersに参加しました。

参加した方々は現場のプロだったり学生だったりいろいろな方がいらっしゃいました。

 

セミナーの内容は

セッション

・shared_ptrとゲームプログラミングでのメモリ管理

Unreal Engine 4とUnreal C++でのプログラミング環境について

・元コンシューマ系PGがアケゲ開発やってみた ~アケゲ開発でのC++

 

LTタイトル

・思い描いてるものを形にするための事前準備

・JUCEで作るオーディオアプリケーション

プログラマ生存戦略 ~生き残る為に出世しろ~

 

の6本でした。

 

スマートポインタのマニアックな話から話題のゲームエンジンについて、生存戦略など面白いものが多かったです。

 

特に生存戦略は外では言えないアレコレを某サウンドプログラマさんがお話しをなさってました。

自分も将来のことを考えないといけないので大変ためになるお話でした。

 

いろいろな方とおしゃべりする中で自分の実力の低さを改めて感じました。

まだまだこれからではありますが、気を引き締めていかないといけないと思いました。

 

そして、登壇者、参加者の皆さまお疲れ様でした。またこういうイベントがあれば是非お逢いしましょう。

 

それでは。