2014-12-04 106 views
1

如何更改DirectX 11中的屏幕分辨率?有沒有一個簡單的方法來做到這一點,或者我必須完全重新創建交換鏈,並創建一個新的backbuffer和rendertargetview?在DirectX 11中更改分辨率

+2

你說的是調整窗口大小或你說的是建立一個全屏幕與特定的屏幕分辨率呈現? – 2014-12-04 20:07:27

+0

我正在談論調整窗口大小 – Anti049 2014-12-05 20:27:11

回答

3

DXGI自動處理調整「前端緩衝區」的大小,即顯示給用戶的交換鏈部分。但是,應用程序負責調整「後臺緩衝區」的大小。當你這樣做時,你還應該重新創建所有'依賴於窗口大小'的資源。

的基本邏輯很簡單:

// 1. Clear the existing references to the backbuffer 
ID3D11RenderTargetView* nullViews [] = { nullptr }; 
m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr); 
m_renderTargetView.Reset(); // Microsoft::WRL::ComPtr here does a Release(); 
m_depthStencilView.Reset(); 
m_d3dContext->Flush(); 

// 2. Resize the existing swapchain 
hr = m_swapChain->ResizeBuffers(2, backBufferWidth, backBufferHeight, backBufferFormat, 0); 
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) 
    // You have to destroy the device, swapchain, and all resources and 
    // recreate them to recover from this case. The device was hardware reset, 
    // physically removed, or the driver was updated and/or restarted 

之後,步驟,其餘都是你做了什麼,當你第一次創建swapchain

// 3. Get the new backbuffer texture to use as a render target 
hr = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &backBuffer); 

hr = m_d3dDevice->CreateRenderTargetView(backBuffer.Get(), nullptr, &m_renderTargetView); 

// 4. Create a depth/stencil buffer and create the depth stencil view 
CD3D11_TEXTURE2D_DESC depthStencilDesc(depthBufferFormat, backBufferWidth, backBufferHeight, 1, 1, D3D11_BIND_DEPTH_STENCIL); 
hr = m_d3dDevice->CreateTexture2D(&depthStencilDesc, nullptr, &depthStencil); 

CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); 
hr = m_d3dDevice->CreateDepthStencilView(depthStencil.Get(), &depthStencilViewDesc, &m_depthStencilView)); 

// 5. Reset the rendering viewport to the new size 
CD3D11_VIEWPORT viewPort(0.0f, 0.0f, static_cast<float>(backBufferWidth), static_cast<float>(backBufferHeight)); 
m_d3dContext->RSSetViewports(1, &viewPort); 

// 6. Reset your camera's aspect ratio based on backBufferWidth/backBufferHeight 

// 7. Set your render target view/depth stencil view for rendering 
m_d3dContext->OMSetRenderTargets(1, m_renderTargetView.GetAddressOf(), m_depthStencilView.Get()); 

對於Win32桌面應用程序中,絕招正好知道要做這個過程。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    PAINTSTRUCT ps; 
    HDC hdc; 

    static bool s_in_sizemove = false; 
    static bool s_minimized = false; 

    switch (message) 
    { 

    ... 

    case WM_SIZE: 
     if (wParam == SIZE_MINIMIZED) 
     { 
      if (!s_minimized) 
      { 
       s_minimized = true; 
       // Your app should probably suspend 
      } 
     } 
     else if (s_minimized) 
     { 
      s_minimized = false; 
      // Your app should resume 
     } 
     else if (!s_in_sizemove) 
      // HERE is where you'd trigger a resize based on MINIMIZE/MAXIMIZE/RESTORE 
     break; 

    case WM_ENTERSIZEMOVE: 
     s_in_sizemove = true; 
     break; 

    case WM_EXITSIZEMOVE: 
     s_in_sizemove = false; 
     // HERE is where you'd trigger a resize based on the user resizing the window 
     break; 

     case WM_GETMINMAXINFO: 
     { 
      // You should set a minimize window size that is reasonable for your app. Here I use 320x200 
      auto info = reinterpret_cast<MINMAXINFO*>(lParam); 
      info->ptMinTrackSize.x = 320; 
      info->ptMinTrackSize.y = 200; 
     } 
     break; 
    } 

    ... 
    return DefWindowProc(hWnd, message, wParam, lParam); 
} 

對於Windows Store應用程序/ Windows的手機應用程序,該VS模板有用於創建設備,另一個用於創建設備相關的資源,獨特的功能,另一個用於創建窗口大小依賴的資源。最後一個被調用來調整大小。

全屏模式有點棘手,但基本上是一樣的想法。如果您的應用程序不支持全屏,你應該確保禁用默認ALT +通過調用這個ENTER行爲,當你第一次創建swapchain和設置HWND協會:

dxgiFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); 

的Windows Store應用程序/ Windows手機應用程序不允許真正的「全屏」模式分辨率更改,因此這種情況不適用於它們。

DirectX Graphics Infrastructure (DXGI): Best Practices