Nanashi-softプログラマ専用DirectX11開発


◇DirectX11プログラミング -一旦まとめる-

ここまで差分だけで来たので,一旦ソースをまとめます

一番始めからいきます
VC++2010を起動し,新しいプロジェクト→Win32コンソールアプリケーション
名前にクラス名とプロジェクト名を入れて,OKボタン
次へボタンをクリックして,追加オプションのチェックを全部外す
完了ボタンをクリック

左のソリューションエクスプローラー(無い時は,メニューの表示→その他のウィンドウから表示する)
プロジェクト名(左に小さな三角が出ているヤツ)を右クリック→プロパティ
左の VC++ディレクトリをクリック
インクルードディレクトリをクリックすると,右端に三角が出てくるので,クリック
編集をクリック
上の欄をクリックすると入力できるようになるので,
$(DXSDK_DIR)Include;$(IncludePath)
と入力して,OKボタンをクリック
同様に,ライブラリディレクトリに,
$(DXSDK_DIR)Lib\x86;$(LibraryPath)
を設定
終わったら,OKボタンをクリックして閉じる

ソリューションエクスプローラーのソースファイルを右クリック→追加→新しい項目をクリック
C++ファイル(.cpp)をクリックして,名前にファイル名を入力して,追加ボタンをクリック

追加した cppファイルを開いて,そこにプログラムを書いていきます

#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>

#include "vs.h" //Vertex Shader
#include "ps.h" //Pixcel Shader

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

#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

//ウィンドウのコールバック関数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message){
case WM_CLOSE:
PostMessage(hWnd, WM_DESTROY, 0, 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}

return(DefWindowProc(hWnd, message, wParam, lParam));
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
//ウィンドウクラスを登録して
TCHAR szWindowClass[] = "3DDISPPG";
WNDCLASS wcex;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
RegisterClass(&wcex);

//ウィンドウをクリエイト
HWND hWnd;
hWnd = CreateWindow(szWindowClass,
"3D Disp Pg",
WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
0,
0,
1920,
1080,
NULL,
NULL,
hInstance,
NULL);

D3D_DRIVER_TYPE driverTypes[] = {
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT numDriverTypes = ARRAYSIZE(driverTypes);

DXGI_SWAP_CHAIN_DESC hDXGISwapChainDesc;
hDXGISwapChainDesc.BufferDesc.Width = 1980;
hDXGISwapChainDesc.BufferDesc.Height = 1080;
hDXGISwapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
hDXGISwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
hDXGISwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
hDXGISwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
hDXGISwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
hDXGISwapChainDesc.SampleDesc.Count = 1;
hDXGISwapChainDesc.SampleDesc.Quality = 0;
hDXGISwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
hDXGISwapChainDesc.BufferCount = 1;
hDXGISwapChainDesc.OutputWindow = hWnd;
hDXGISwapChainDesc.Windowed = TRUE;
hDXGISwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
hDXGISwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

//デバイスとスワップチェインを一気に生成
HRESULT hr;
D3D_DRIVER_TYPE hDriverType = D3D_DRIVER_TYPE_NULL;
IDXGISwapChain* hpDXGISwpChain = NULL;
ID3D11Device* hpDevice = NULL;
ID3D11DeviceContext* hpDeviceContext = NULL;
D3D_FEATURE_LEVEL hFeatureLevel = D3D_FEATURE_LEVEL_11_0;
for(UINT driverTypeIndex=0; driverTypeIndex < numDriverTypes; driverTypeIndex++){
hDriverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDeviceAndSwapChain(NULL, hDriverType, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &hDXGISwapChainDesc, &hpDXGISwpChain, &hpDevice, &hFeatureLevel, &hpDeviceContext);
if(SUCCEEDED(hr)){
break;
}
}
if(FAILED(hr)){
MessageBoxW(hWnd, L"D3D11CreateDeviceAndSwapChain", L"Err", MB_ICONSTOP);
goto End;
}

//スワップチェインのバックバッファ取得
ID3D11Texture2D* hpBackBuffer = NULL;
if(FAILED(hpDXGISwpChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&hpBackBuffer))){
MessageBoxW(hWnd, L"SwpChain GetBuffer", L"Err", MB_ICONSTOP);
goto End;
}

//そのバックバッファから描画ターゲット生成
ID3D11RenderTargetView *hpRenderTargetView = NULL;
if(FAILED(hpDevice->CreateRenderTargetView(hpBackBuffer, NULL, &hpRenderTargetView))){
MessageBoxW(hWnd, L"CreateRenderTargetView", L"Err", MB_ICONSTOP);
goto End;
}

//更にその描画ターゲットをコンテキストに設定
hpDeviceContext->OMSetRenderTargets(1, &hpRenderTargetView, NULL);

//ビューポート設定
D3D11_VIEWPORT vp;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
vp.Width = 1920;
vp.Height = 1080;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
hpDeviceContext->RSSetViewports(1, &vp);

//初期化ここまで
// =====================================================
//初期化ここまで
// =====================================================

//ポリゴン頂点構造体
struct Vertex3D {
float pos[3]; //x-y-z
float col[4]; //r-g-b-a
float tex[2]; //x-y
};

const int TYOUTEN = 6; //ポリゴンの頂点数

//頂点データ(六角ポリゴン1枚)
Vertex3D hVectorData[TYOUTEN] = {
//500x811
{ {+0.0f, +0.75f, +0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {+0.5f, +0.0f} },
{ {+0.4f, +0.35f, +0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {+1.25f, +0.27f} },
{ {-0.4f, +0.35f, +0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {-0.25f, +0.27f} },
{ {+0.4f, -0.35f, +0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {+1.25f, +0.73f} },
{ {-0.4f, -0.35f, +0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {-0.25f, +0.73f} },
{ {+0.0f, -0.75f, +0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {+0.5f, +1.00f} },
};
//頂点レイアウト
//5番目のパラメータは先頭からのバイト数なので,COLORにはPOSITIONのfloat型4バイト×3を記述
D3D11_INPUT_ELEMENT_DESC hInElementDesc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 4*3, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 4*3 + 4*4, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};

//頂点バッファ作成
D3D11_BUFFER_DESC hBufferDesc;
hBufferDesc.ByteWidth = sizeof(Vertex3D) * TYOUTEN;
hBufferDesc.Usage = D3D11_USAGE_DEFAULT;
hBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
hBufferDesc.CPUAccessFlags = 0;
hBufferDesc.MiscFlags = 0;
hBufferDesc.StructureByteStride = sizeof(float);

D3D11_SUBRESOURCE_DATA hSubResourceData;
hSubResourceData.pSysMem = hVectorData;
hSubResourceData.SysMemPitch = 0;
hSubResourceData.SysMemSlicePitch = 0;

ID3D11Buffer* hpBuffer;
if(FAILED(hpDevice->CreateBuffer(&hBufferDesc, &hSubResourceData, &hpBuffer))){
MessageBoxW(hWnd, L"CreateBuffer", L"Err", MB_ICONSTOP);
goto End;
}

//その頂点バッファをコンテキストに設定
UINT hStrides = sizeof(Vertex3D);
UINT hOffsets = 0;
hpDeviceContext->IASetVertexBuffers(0, 1, &hpBuffer, &hStrides, &hOffsets);

//プリミティブ(ポリゴンの形状)をコンテキストに設定
// hpDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
hpDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

//予めHLSLをコンパイルしてヘッダーに追加しておきます

//頂点レイアウト作成
ID3D11InputLayout* hpInputLayout = NULL;
if(FAILED(hpDevice->CreateInputLayout(hInElementDesc, ARRAYSIZE(hInElementDesc), &g_vs_main, sizeof(g_vs_main), &hpInputLayout))){
MessageBoxW(hWnd, L"CreateInputLayout", L"Err", MB_ICONSTOP);
goto End;
}

//頂点レイアウトをコンテキストに設定
hpDeviceContext->IASetInputLayout(hpInputLayout);

//テクスチャー読み込み
D3DX11_IMAGE_LOAD_INFO LoadInfo;
LoadInfo.Width = 0;
LoadInfo.Height = 0;
LoadInfo.Depth = 0;
LoadInfo.FirstMipLevel = 0;
LoadInfo.MipLevels = D3DX11_DEFAULT,
LoadInfo.Usage = D3D11_USAGE_DEFAULT;
LoadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE;
LoadInfo.CpuAccessFlags = 0;
LoadInfo.MiscFlags = 0;
LoadInfo.Format = DXGI_FORMAT_R32G32B32_FLOAT;
LoadInfo.Filter = D3DX11_FILTER_TRIANGLE;
LoadInfo.MipFilter = D3DX11_FILTER_TRIANGLE;
LoadInfo.pSrcInfo = NULL;

ID3D11ShaderResourceView* hpShaderResourceView = NULL;
if(FAILED(D3DX11CreateShaderResourceViewFromFile(hpDevice, TEXT("ira.siyoko.png"), &LoadInfo, NULL, &hpShaderResourceView, NULL))){
MessageBoxW(hWnd, L"D3DX11CreateShaderResourceViewFromFile", L"Err", MB_ICONSTOP);
goto End;
}

//そのテクスチャーをコンテキストに設定
ID3D11ShaderResourceView* hpShaderResourceViews[] = { hpShaderResourceView };
hpDeviceContext->PSSetShaderResources(0, 1, hpShaderResourceViews);

//頂点シェーダー生成
ID3D11VertexShader* hpVertexShader;
if(FAILED(hpDevice->CreateVertexShader(&g_vs_main, sizeof(g_vs_main), NULL, &hpVertexShader))){
MessageBoxW(hWnd, L"CreateVertexShader", L"Err", MB_ICONSTOP);
goto End;
}

//ピクセルシェーダー生成
ID3D11PixelShader* hpPixelShader;
if(FAILED(hpDevice->CreatePixelShader(&g_ps_main, sizeof(g_ps_main), NULL, &hpPixelShader))){
MessageBoxW(hWnd, L"CreateVertexShader", L"Err", MB_ICONSTOP);
goto End;
}

//ラスタライザー生成
ID3D11RasterizerState* hpRasterizerState = NULL;
D3D11_RASTERIZER_DESC hRasterizerDesc = {
D3D11_FILL_SOLID,
D3D11_CULL_NONE, //ポリゴンの裏表を無くす
FALSE,
0,
0.0f,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE
};
if(FAILED(hpDevice->CreateRasterizerState(&hRasterizerDesc, &hpRasterizerState))){
MessageBoxW(hWnd, L"CreateRasterizerState", L"Err", MB_ICONSTOP);
goto End;
}

//グラフィックパイプライン処理
//頂点シェーダーをコンテキストに設定
hpDeviceContext->VSSetShader(hpVertexShader, NULL, 0);
//ハルシェーダーは無し
hpDeviceContext->HSSetShader(NULL, NULL, 0 );
//テッセレーターは無し
//ドメインシェーダーは無し
hpDeviceContext->DSSetShader(NULL, NULL, 0 );
//ジオメトリシェーダーは無し
hpDeviceContext->GSSetShader(NULL, NULL, 0 );
//ラスタライザーをコンテキストに設定
hpDeviceContext->PSSetShaderResources(0, 1, hpShaderResourceViews);
//ピクセルシェーダーをコンテキストに設定
hpDeviceContext->PSSetShader(hpPixelShader, NULL, 0);

//メインループ
MSG hMsg;
while(true){
while(PeekMessageW(&hMsg, NULL, 0, 0, PM_REMOVE)){
if(hMsg.message == WM_QUIT){
goto End;
}
TranslateMessage(&hMsg);
DispatchMessage(&hMsg);
}

//背景クリア
float ClearColor[] = {0.0f, 0.0f, 1.0f, 1.0f};
hpDeviceContext->ClearRenderTargetView(hpRenderTargetView, ClearColor);

//描画
hpDeviceContext->Draw(TYOUTEN, 0);

hpDXGISwpChain->Present(0, 0);
}

End:
//ポインタで生成したものはリリースする必要がある
//どの変数か識別し易いように,hpで始めてある
SAFE_RELEASE(hpPixelShader);
SAFE_RELEASE(hpVertexShader);
SAFE_RELEASE(hpShaderResourceViews);
SAFE_RELEASE(hpShaderResourceView);
SAFE_RELEASE(hpInputLayout);
SAFE_RELEASE(hpBuffer);
SAFE_RELEASE(hpRasterizerState);
//↓初期化
SAFE_RELEASE(hpRenderTargetView);
SAFE_RELEASE(hpBackBuffer);
SAFE_RELEASE(hpDXGISwpChain);
SAFE_RELEASE(hpDeviceContext);
SAFE_RELEASE(hpDevice);

return 0;
}
別ソースファイルのシェーダー部分
・頂点シェーダー
//入力用
struct vertexIn
{
float4 pos : POSITION0;
float4 col : COLOR0;
float2 tex : TEXCOORD0;
};

//出力用
struct vertexOut
{
float4 pos : SV_POSITION;
float4 col : COLOR;
float2 tex : TEXCOORD0;
};

vertexOut vs_main(vertexIn IN)
{
vertexOut OUT;

OUT.pos = IN.pos;
OUT.col = IN.col;
OUT.tex = IN.tex;

return OUT;
}
・ピクセルシェーダー
//入力用
struct pixcelIn
{
float4 pos : SV_POSITION;
float4 col : COLOR;
float2 tex : TEXCOORD0;
};

Texture2D txDiffuse : register( t0 );
SamplerState samLinear : register( s0 );

float4 ps_main(pixcelIn IN) : SV_Target
{
pixcelIn OUT;

OUT.col = txDiffuse.Sample(samLinear, IN.tex);

//少し暗くする
OUT.col.r -= 0.3f;
OUT.col.g -= 0.3f;
OUT.col.b -= 0.3f;

return OUT.col;
}
全部記述して,ビルドすると,六角形の中にしよ子さんが表示されます


え? どうやって6角形の中に入る座標計算をしたのかって?
0.01ずつ値を動かして,同じ形になるようにしたに決まっています(人力かよw)
アフォな人には,相応のやり方と言うものがあるのですよ('-'*)


TOPプログラマ専用DirectX11開発

チアガール☆花穂ネコミトリ ナンプレー -ノーマル-+