DirectX 10/11禁止Alt Enter全屏的方法
DirectX 10/11的交换链有全屏功能,但是这个全屏并不是想象的那样,缓冲区大小不改变,画面会模糊,关掉的方法:
// 禁止Alt+Enter全屏
CComPtr<idxgifactory> dxgifac;
(comexcept)g_swpch->GetParent(__uuidof(IDXGIFactory), (void**)&dxgifac);
dxgifac->MakeWindowAssociation(g_hwnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
dxgifac = NULL;
</idxgifactory>
DXUT也有全屏切换,但实际上是重新建立了适合全屏的设备和交换链,不会模糊。
Win10中Debug Layer的安装
DirectX 9/10/11比较
DirectX 9.0用起来傻瓜化,直接用API就可以绘图,但是如果想实现高级特性的话,没有集成Shader编译器,需要先行编译或者使用D3DX库编译。
DirectX 10去掉了用API直接画图的功能,但是集成了Shader编译器,加入了Geometry Shader,同时分离了DXGI,用起来稍显复杂,初始化的复杂度增加了。
DirectX 11是基于DirectX 10小幅改进的版本,加上很多功能,包括Tessellation和DirectCompute以及CommandList。但同时,DirectX 11分离了编译器,必须安装运行库(2010或之前)或者附带dll(2012或之后)才能使用,剥离了Effects11必须自己编译。但同时2012又剥离了D3DX成为DirectXTK、DirectXTex、DirectXMesh等数个开源库,需要自己编译。
DirectX 9.0需要配合GDI+出图,DirectX 10/11可以用Direct2D和DirectWrite出图。
一个更理想的DirectX 10框架程序
实现了窗口大小变化,而且使用WndProc而不是C++类管理生命周期
// main.cpp - 主文件
#undef UNICODE
#define UNICODE 1
#include <windows.h>
#include <d3d10.h>
#include <xnamath.h> // <directxmath.h> for VS2012+
#pragma comment(lib, "d3d10.lib")
HINSTANCE hInst;
HWND hMainWnd;
#define WM_APPIDLE (WM_APP + 10)
struct WndData
{
ID3D10Device *dev;
D3D10_DRIVER_TYPE dt;
IDXGISwapChain *swpch;
ID3D10RenderTargetView *rtv;
ID3D10Texture2D *dsbuf;
ID3D10DepthStencilView *dsv;
};
HRESULT CreateRTV(HWND hWnd, WndData *data)
{
HRESULT hr = S_OK;
ID3D10Texture2D *backbuf = NULL;
hr = data->swpch->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)&backbuf);
if (FAILED(hr)) return hr;
hr = data->dev->CreateRenderTargetView(backbuf, NULL, &data->rtv);
backbuf->Release();
return hr;
}
HRESULT CreateDSBufAndDSV(HWND hWnd, WndData *data, int width, int height)
{
HRESULT hr = S_OK;
D3D10_TEXTURE2D_DESC dsbufdesc = {
width, height, 1, 1, DXGI_FORMAT_D32_FLOAT, { 1, 0 }, D3D10_USAGE_DEFAULT, D3D10_BIND_DEPTH_STENCIL, 0, 0
};
hr = data->dev->CreateTexture2D(&dsbufdesc, NULL, &data->dsbuf);
if (FAILED(hr)) return hr;
D3D10_DEPTH_STENCIL_VIEW_DESC dsvdesc = {
DXGI_FORMAT_D32_FLOAT, D3D10_DSV_DIMENSION_TEXTURE2D
};
dsvdesc.Texture2D.MipSlice = 0;
hr = data->dev->CreateDepthStencilView(data->dsbuf, &dsvdesc, &data->dsv);
return hr;
}
void SetViewport(HWND hWnd, WndData *data, int width, int height)
{
D3D10_VIEWPORT vp = {
0, 0, width, height, 0.0f, 1.0f
};
data->dev->RSSetViewports(1, &vp);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WndData *data = (WndData *)GetWindowLongPtr(hWnd, 0);
if (msg == WM_CREATE)
{
data = (WndData *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (WndData));
if (data == NULL) DestroyWindow(hWnd);
SetWindowLongPtr(hWnd, 0, (LONG_PTR)data);
RECT rc = { 0 };
GetClientRect(hWnd, &rc);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
DXGI_MODE_DESC mode = {
width, height, { 60, 1 }, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED, DXGI_MODE_SCALING_UNSPECIFIED,
};
DXGI_SWAP_CHAIN_DESC swpchdesc = {
mode, { 1, 0 }, DXGI_USAGE_RENDER_TARGET_OUTPUT, 1, hWnd, TRUE, DXGI_SWAP_EFFECT_DISCARD, 0
};
D3D10_DRIVER_TYPE drvtype[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_WARP, D3D10_DRIVER_TYPE_REFERENCE };
HRESULT hr = S_OK;
for (int i = 0; i < sizeof drvtype / sizeof drvtype[0]; i++)
{
data->dt = drvtype[i];
hr = D3D10CreateDeviceAndSwapChain(NULL, data->dt, NULL, 0, D3D10_SDK_VERSION, &swpchdesc, &data->swpch, &data->dev);
if (SUCCEEDED(hr)) break;
}
if (FAILED(hr)) DestroyWindow(hWnd);
hr = CreateRTV(hWnd, data);
if (FAILED(hr)) DestroyWindow(hWnd);
hr = CreateDSBufAndDSV(hWnd, data, width, height);
if (FAILED(hr)) DestroyWindow(hWnd);
data->dev->OMSetRenderTargets(1, &data->rtv, data->dsv);
SetViewport(hWnd, data, width, height);
// TODO - create objects
return 0;
}
if (msg == WM_DESTROY)
{
if (data != NULL)
{
if (data->dev) data->dev->ClearState();
if (data->dsv) data->dsv->Release();
if (data->dsbuf) data->dsbuf->Release();
if (data->rtv) data->rtv->Release();
if (data->swpch) data->swpch->Release();
if (data->dev) data->dev->Release();
HeapFree(GetProcessHeap(), 0, data);
}
PostQuitMessage(0);
return 0;
}
if (data == NULL)
return DefWindowProc(hWnd, msg, wParam, lParam); // 下边的消息都是需要data的
if (msg == WM_SIZE)
{
int width = LOWORD(lParam);
int height = HIWORD(lParam);
char buf[1024] = "";
wsprintfA(buf, "%d %d\r\n", width, height);
OutputDebugStringA(buf);
data->dev->ClearState();
data->rtv->Release(); data->rtv = NULL;
data->dsv->Release(); data->dsv = NULL;
data->dsbuf->Release(); data->dsbuf = NULL;
HRESULT hr = data->swpch->ResizeBuffers(1, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
if (FAILED(hr)) DestroyWindow(hWnd);
hr = CreateRTV(hWnd, data);
if (FAILED(hr)) DestroyWindow(hWnd);
hr = CreateDSBufAndDSV(hWnd, data, width, height);
if (FAILED(hr)) DestroyWindow(hWnd);
data->dev->OMSetRenderTargets(1, &data->rtv, data->dsv);
SetViewport(hWnd, data, width, height);
return 0;
}
if (msg == WM_APPIDLE)
{
float backcolor[4] = { 0.0f, 0.5f, 0.5f, 1.0f };
data->dev->ClearRenderTargetView(data->rtv, backcolor);
data->dev->ClearDepthStencilView(data->dsv, D3D10_CLEAR_DEPTH, 1.0f, 0);
// TODO - draw frames
data->swpch->Present(0, 0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{
hInst = hInstance;
WNDCLASSEX wcex = {
sizeof wcex, CS_VREDRAW|CS_HREDRAW, WndProc, 0, sizeof (WndData *), hInstance, LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
(HBRUSH)GetStockObject(NULL_BRUSH), NULL, L"MainWndClass", LoadIcon(NULL, IDI_APPLICATION),
};
RegisterClassEx(&wcex);
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
hMainWnd = CreateWindow(L"MainWndClass", L"Main Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
ShowWindow(hMainWnd, nShowCmd);
UpdateWindow(hMainWnd);
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
SendMessage(hMainWnd, WM_APPIDLE, 0, 0);
}
}
return 0;
}
</directxmath.h></xnamath.h></d3d10.h></windows.h>