Direct3D 10 では Window のリサイズが比較的簡単にできます。
もちろん何もしない状態でも、DirectX9 と同じようにサイズの異なる
FrontBuffer に対して BackBuffer を拡縮 Copy します。
よってそのままでもウィンドウのリサイズが可能です。
Direct3D 10 の場合、さらに BackBuffer のサイズも容易に追従
させることができます。
サイズの変更は IDXGISwapChain の ResizeBuffer() です。
SwapChain が作成した Buffer のリサイズは行いますが、Buffer を
参照しているオブジェクトがあると同時には解決できません。
それらのオブジェクトはあらかじめ Release() しておく必要があります。
通常は BackBuffer から ID3D10RenderTargetView を作りますので、
RenderTargetView は先に開放しておきます。
また OMSetRenderTarget() で同時に DepthStencilView を登録する
場合、RenderTargetView とサイズが異なると受け付けてくれません。
結局 DepthStencilView も作り直す必要があります。
まずは Release()
ID3D10RenderTargetView* iRTV= NULL;
iDevice->OMSetRenderTarget( 1, &iRTV, NULL ); // NULL, NULL の設定
iRenderTargetView->Release();
iDepthStencilView->Release();
次にリサイズ。サイズに 0, 0 を渡すと、Window の ClientRect
にあわせてくれます。(ここでは WindowMode のみ対象にしています)
iSwapChain->ResizeBuffers( 2,
0, 0, // ClientRect を参照する
SwapChainDesc.BufferDesc.Format, // Format は DESC から
0 );
必要なバッファを作り直します。この手順は最初の初期化時と全く
同じなので、共通化しておいたほうが良いです。
BackBuffer と DepthStencil の作成
// back buffer
ID3D10Texture2D* iBackBuffer= NULL;
iSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ),
reinterpret_cast( &iBackBuffer ) );
iDevice->CreateRenderTargetView(
iBackBuffer, NULL, &iRenderTargetView );
iBackBuffer->Release();
// depth stencil buffer
ID3D10Texture2D* iTexture= NULL;
D3D10_TEXTURE2D_DESC tex2ddesc= {
width, height, 1, 1, // width, height, mip, array
DXGI_FORMAT_D24_UNORM_S8_UINT, // format
{ 1, 0, }, // sample
D3D10_USAGE_DEFAULT,
D3D10_BIND_DEPTH_STENCIL,
0, // cpu flags
0 // misc flags
};
iDevice->CreateTexture2D( &tex2ddesc, NULL, &iTexture );
D3D10_DEPTH_STENCIL_VIEW_DESC vdesc= {
DXGI_FORMAT_D24_UNORM_S8_UINT,
D3D10_DSV_DIMENSION_TEXTURE2D
};
iDevice->CreateDepthStencilView(
iTexture, &vdesc, &iDepthStencilView );
iTexture->Release();
g_iDevice->OMSetRenderTargets( 1,
&g_iRenderTargetView, g_iDepthStencilView );
忘れてはならないのが Viewport の設定です。
またここでは書いていませんが、ProjectionMatrix も再計算が必要です。
// viewport
D3D10_VIEWPORT viewport= {
0, 0, width, height, 0.0f, 1.0f
};
iDevice->RSSetViewports( 1, &viewport );
WM_SIZE でサイズが変わったことを検知したら、これらの処理を
呼び出します。アイコン化最小化などもきちんと区別しておかないと、
サイズ (0, 0) に対してリサイズが発生してしまうので注意。
またリサイズによって VRAM が足りなくなり、速度が極端に低下する
可能性も考えられます。場合によっては、極端な速度低下を検出したら
元のサイズに戻す処理も入れた方が良いのかもしれません。