これまた随分と突然なのですけれど、2D,3D描画ライブラリを新月獅子さんと共同開発することになりました。(え、なったよね?獅子さん?本気だよね?)
じゃあまずはDirectX11を一緒に勉強していこうということになりまして、今まさにそれを進めている次第なのであります。
そんなわけで今日は、環境を整備して(VC++2012が無料で使えることを知らなかったとかDirectX SDKを入れようと思ったら失敗してなんでだろうって思ったらwin8からはWindows8 SDK に変わってたりとかVC++2012のwin8版をダウンロードしたら実はそれはウィンドウズストア用のアプリを開発するためのバージョンだったとわかって普通のバージョンをインストールし直したりとかSDKの中に入ってるはずのインクルードフォルダがなかなか見つからなかったりとかなんてこと、全然無かったですからね?ね?)、DirectX11を初期化する所までをやってみました。
ソースコード
► スポイラーを表示
main.cpp
newwin.h
#define _CRT_SECURE_NO_DEPRECATE
#include "d3d11.h"
#pragma comment(lib, "d3d11.lib")
//#include "d3d11.lib"
#define FW_WIN_MAIN_
#include "newwin.h"
namespace fw{
bool processage(){
MSG msg;
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)==0) return true;
if(msg.message==WM_QUIT) return false;
TranslateMessage(&msg);
DispatchMessage(&msg);
return true;
}
}
int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC){
fw::newwin w("test", 512,384);
ID3D11RenderTargetView *hpRenderTargetView = NULL;
ID3D11Texture2D* hpBackBuffer = NULL;
IDXGISwapChain* hpDXGISwpChain = NULL;
IDXGIFactory* hpDXGIFactory = NULL;
IDXGIAdapter* hpAdapter = NULL;
IDXGIDevice1* hpDXGI = NULL;
ID3D11Device* hpDevice = NULL;
ID3D11DeviceContext* hpDeviceContext = NULL;
do{
//デバイス作成
HRESULT result = D3D11CreateDevice
(
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
0,
NULL,
0,
D3D11_SDK_VERSION,
&hpDevice,
NULL,
&hpDeviceContext
);
if(FAILED(result) ) break;
//インターフェース取得
if(FAILED(hpDevice->QueryInterface(__uuidof(IDXGIDevice1), (void**)&hpDXGI) ) ) break;
//アダプター取得
if(FAILED(hpDXGI->GetAdapter(&hpAdapter) ) ) break;
//ファクトリー取得
hpAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&hpDXGIFactory);
if(hpDXGIFactory == NULL) break;
//ALT+Enterでフルスクリーンを許可する
if(FAILED(hpDXGIFactory->MakeWindowAssociation(w.handle(), 0) ) ) break;
//スワップチェイン作成
DXGI_SWAP_CHAIN_DESC hDXGISwapChainDesc;
/*
hDXGISwapChainDesc.BufferDesc.Width = 1980;
hDXGISwapChainDesc.BufferDesc.Height = 1080;
//*/
hDXGISwapChainDesc.BufferDesc.Width = 640;
hDXGISwapChainDesc.BufferDesc.Height = 480;
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 = w.handle();
hDXGISwapChainDesc.Windowed = TRUE;
hDXGISwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
hDXGISwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
if(FAILED(hpDXGIFactory->CreateSwapChain(hpDevice, &hDXGISwapChainDesc, &hpDXGISwpChain) ) ) break;
//そのスワップチェインのバックバッファ取得
if(FAILED(hpDXGISwpChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&hpBackBuffer) ) ) break;
//そのバックバッファから描画ターゲット生成
if(FAILED(hpDevice->CreateRenderTargetView(hpBackBuffer, NULL, &hpRenderTargetView) ) ) break;
//更にその描画ターゲットをコンテキストに設定
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);
while(fw::processage() ){
/*
float ClearColor[] = {0.0f, 0.0f, 1.0f, 1.0f};
hpDeviceContext->ClearRenderTargetView(hpRenderTargetView, ClearColor);
hpDXGISwpChain->Present(0, 0);
//*/
}
}while(false);
#define release(p) if(p){ (p)->Release(); (p)=NULL; }
release(hpRenderTargetView)
release(hpBackBuffer)
release(hpDXGISwpChain)
release(hpDXGIFactory)
release(hpAdapter)
release(hpDXGI)
release(hpDeviceContext)
release(hpDevice)
#undef release
}
#pragma once
#define _CRT_SECURE_NO_DEPRECATE
#define OEMRESOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib, "shlwapi.lib")
#include
#include
#include
#include
namespace fw{
typedef unsigned int uint;
const uint minID = 100;
class newwin{
static std::map buttons;
static uint ChildID;
WNDCLASSEX wc;
HWND mainWH;
static bool notmine(const uint childID){ return childID=ChildID; }
static LRESULT CALLBACK WindowProc(HWND hwnd,UINT uiMsg,WPARAM wParam,LPARAM lParam){
static HBRUSH aquaBrsh = NULL;
uint childID = static_cast(GetWindowLongPtr(reinterpret_cast(lParam), GWLP_ID) );
switch(uiMsg){
case WM_COMMAND:
if(notmine(childID) ) break;
buttons[childID-100] = true;
break;
case WM_CTLCOLORSTATIC:
if(notmine(childID) ) break;
if(childID%2){
// 背景色を白色に設定
SetBkColor(reinterpret_cast(wParam), 0xffffff);
return reinterpret_cast(GetStockObject(WHITE_BRUSH) );
}
else{
// 背景色を水色に設定
SetBkColor(reinterpret_cast(wParam), RGB(200,255,255) );
if(aquaBrsh==NULL) aquaBrsh = CreateSolidBrush(RGB(200,255,255) );
return reinterpret_cast(aquaBrsh);
}
break;
case WM_DESTROY:
if(aquaBrsh!=NULL){
DeleteObject(aquaBrsh);
aquaBrsh = NULL;
}
PostQuitMessage(wParam);
break;
}
return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
static void InitIndex(uint index){ buttons[index] = false; }
static bool clicked(uint index){
bool res = buttons[index];
InitIndex(index);
return res;
}
static HMENU childID(){ return reinterpret_cast(ChildID++); }
public:
class text{
HWND handle;
public:
text(){ handle = NULL; }
text & create(const newwin & w, const std::string & str, int x,int y, int width,int height){
if(handle!=NULL) del();
handle = CreateWindow(
"STATIC",
str.c_str(),
WS_CHILD|WS_VISIBLE,
x,y,
width,height,
w.handle(),
newwin::childID(),
GetModuleHandle(NULL),
NULL
);
return *this;
}
text(const newwin & w, const std::string & str, int x,int y, int width,int height){ create(w, str, x,y, width,height); }
std::string gets(){
char content[257];
GetWindowText(handle, content, 256);
return content;
}
text & sets(const std::string & output){
SetWindowText(handle, output.c_str() );
return *this;
}
text & del(){
DestroyWindow(handle);
return *this;
}
~text(){ del(); }
};
class button{
HWND handle;
uint index;
public:
button(){ handle = NULL; }
button & create(const newwin & w, const std::string & str, int x,int y, int width,int height, bool defbutton = false){
if(handle!=NULL) del();
int attribute = WS_CHILD|WS_VISIBLE;
if(defbutton) attribute = attribute|BS_DEFPUSHBUTTON;
else attribute = attribute|BS_PUSHBUTTON;
HMENU id = newwin::childID();
index = reinterpret_cast(id);
index -= 100;
newwin::InitIndex(index);
handle = CreateWindow(
"BUTTON",
str.c_str(),
attribute,
x,y,
width,height,
w.handle(),
id,
GetModuleHandle(NULL),
NULL
);
return *this;
}
button(const newwin & w, const std::string & str, int x,int y, int width,int height, bool defbutton = false){ create(w, str, x,y, width,height, defbutton); }
bool clicked() const { return newwin::clicked(index); }
button & del(){
DestroyWindow(handle);
return *this;
}
~button(){ del(); }
};
newwin(){}
void init(const std::string &title, int width=CW_USEDEFAULT, int height=CW_USEDEFAULT){
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = reinterpret_cast(COLOR_APPWORKSPACE+1);
wc.hCursor = LoadCursor(GetModuleHandle(NULL),IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = "myClass";
wc.lpszMenuName = NULL;
wc.style = CS_DBLCLKS;
RegisterClassEx(&wc);
mainWH = CreateWindowEx(
WS_EX_TOOLWINDOW,
"myClass",
title.c_str(),
WS_BORDER|WS_SYSMENU,
CW_USEDEFAULT,CW_USEDEFAULT,
width,height,
NULL,NULL,GetModuleHandle(NULL),NULL
);
ShowWindow(mainWH,SW_SHOWDEFAULT);
UpdateWindow(mainWH);
}
newwin(const std::string &title, int width=CW_USEDEFAULT, int height=CW_USEDEFAULT){ init(title, width, height); }
HWND handle() const { return mainWH; }
newwin & del(){
for(uint i=minID;i(i) );
DestroyWindow(mainWH);
return *this;
}
~newwin(){ del(); }
};
#ifdef FW_WIN_MAIN_
std::map newwin::buttons;
uint newwin::ChildID = minID;
#endif
}
意味はおいおい理解してゆけば良いでしょう。
たぶん触っていくうちにわかってくると思います。
ウインドウを作成して表示する部分は、以前別の用途で作ったものを流用しましたけれど。
故にウインドウプロシージャ部分が汎用的ではないですね。
まあ差し支えは無いでしょう。
そんなこんなで頑張ってゆきますよ!!