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 が足りなくなり、速度が極端に低下する
可能性も考えられます。場合によっては、極端な速度低下を検出したら
元のサイズに戻す処理も入れた方が良いのかもしれません。