由于内容有点多,而且本人是0基础学习这个,所以写博客来帮助记忆。
首先官方给的第一个例子提到了三个东西:
device(设备):创建资源
immediate context(直接上下文):应用程序使用直接上下文在缓冲区进行渲染
swap chain(交换链):获取设备呈现的缓冲区,在屏幕上呈现内容
首先创建一个交换链,具体的参数信息看文档。
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory( &sd, sizeof(sd) );
sd.BufferCount = 1;
sd.BufferDesc.Width = 640;
sd.BufferDesc.Height = 480;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
if( FAILED( D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, NULL, &g_pImmediateContext ) ) )
{
return FALSE;
}
然后就是通过直接上下文去渲染视图,首先通过GetBuffer获取后台缓冲区对象,再通过这个对象创建渲染目标视图,再用OMSetRenderTargets将视图绑定到管道。确保屏幕输出的是后台缓冲区.
ID3D11Texture2D *pBackBuffer;
if( FAILED( g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBackBuffer ) ) )
return FALSE;
hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );
pBackBuffer->Release();
if( FAILED( hr ) )
return FALSE;
g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );
然后就是初始化视口,视口用于输出渲染目标。这里设置左上角为(0,0),然后宽和高跟渲染的大小相同。
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)width;
vp.Height = (FLOAT)height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
g_pImmediateContext->RSSetViewports( 1, &vp );
然后是消息循环,通过peekmessage而不是getmeessage,前者非阻塞,后者阻塞,具体的区别看msdn文档。
MSG msg = {0};
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Render(); // Do some rendering
}
}
通过直接上下文进行渲染。
void Render()
{
//
// Clear the backbuffer
//
float ClearColor[4] = { 0.0f, 0.125f, 0.6f, 1.0f }; // RGBA
g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
g_pSwapChain->Present( 0, 0 );
}