Intro :
Dans une application DirectX, l’utilisateur peut vouloir redimensionner la fenêtre à sa guise ou passer le jeu en mettre en mode plein écran.
Il faut implémenter et coder cette fonctionnalité.
Prérequis :
– Avoir suivi la cinquième partie de ce tutoriel.
Sixième partie :
Redimensionnement et plein écran de la fenêtre de rendu.
Explications :
Avant tout, juste pour énoncer un petit point mis à part :
L’appel à D3D11DeviceContext::ClearState réinitialise par défaut toutes les configurations du contexte d’affichage (remet à zéro les shaders, les inputs layout, les viewports, etc..)
Avec les interfaces DXGI* on peut obtenir les informations sur la carte graphique :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
bool D3D10Renderer::GetGPUInfo() { HRESULT hr = S_OK; uint32 iNumModes; IDXGIFactory* pDXGIFactory = nullptr; IDXGIAdapter* pDXGIAdapter = nullptr; IDXGIOutput* pDXGIAdapterOutput = nullptr; DXGI_MODE_DESC* pDisplayModeList = nullptr; DXGI_ADAPTER_DESC adapterDesc; // Créée une interface métier "factory" DirectX hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pDXGIFactory); HR_FAILED_RETURN_FALSE(hr); // Utilise la "factory" hr = pDXGIFactory->EnumAdapters(0, &pDXGIAdapter); HR_FAILED_RETURN_FALSE(hr); // Enumère l'adpatateur principal de l'écran hr = pDXGIAdapter->EnumOutputs(0, &pDXGIAdapterOutput); HR_FAILED_RETURN_FALSE(hr); // Obtient le nombre de modes d'affichage qui corresppond à DXGI_FORMAT_R8G8B8A8_UNORM hr = pDXGIAdapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &iNumModes, nullptr); HR_FAILED_RETURN_FALSE(hr); /* Créé une liste qui détient tous les modes d'affichage possibles pour cette carte graphique et le format d'affichage */ pDisplayModeList = new DXGI_MODE_DESC[iNumModes]; if (!pDisplayModeList) { return false; } // Remplie la précédente structure hr = pDXGIAdapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &iNumModes, pDisplayModeList); HR_FAILED_RETURN_FALSE(hr); /* On parcourt tous les modes d'affichages possibles et on trouve celui qui correspond à la taille spécifiée en paramètre ; puis on enregistre le numérateur et le dénominateur du taux de rafraichissement de l'écran */ for (uint32 i = 0; i < iNumModes; i++) { if (pDisplayModeList[i].Width == (uint32)m_iWidth) { if (pDisplayModeList[i].Height == (uint32)m_iHeight) { m_iNumerator = pDisplayModeList[i].RefreshRate.Numerator; m_iDenominator = pDisplayModeList[i].RefreshRate.Denominator; } } DXGI_MODE_DESC desc = pDisplayModeList[i]; // On vérifie que ce mode n'a pas déjà été ajouté bool bAlreadyExist = false; for (uint32 i = 0; i < m_modes.size(); i++) { if (m_modes[i].Width == desc.Width && m_modes[i].Height == desc.Height) { bAlreadyExist = true; break; } } if (!bAlreadyExist) { m_modes.push_back(desc); } } hr = pDXGIAdapter->GetDesc(&adapterDesc); HR_FAILED_RETURN_FALSE(hr); // On enregistre la taille de la mémoire vidéo en mégabytes m_iVideoCardMemory = (adapterDesc.DedicatedVideoMemory / 1024 / 1024); size_t iStringLength = 0; // Convertie le nom la carte vidéo dans une chaîne de caractères int iError = wcstombs_s(&iStringLength, m_sVideoCardDescription, 128, adapterDesc.Description, 128); if (iError != 0) { return false; } // On supprime les objets dont a plus besoin ! SAFE_DELETE_ARRAY(pDisplayModeList); SAFE_RELEASE(pDXGIAdapterOutput); SAFE_RELEASE(pDXGIAdapter); SAFE_RELEASE(pDXGIFactory); return true; } |
Voici le programme de cet article une fois compilé et lancé :
La fonction qui redimensionne les buffers :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
bool D3D10Renderer::ResizeSwapChain(const size_t iWidth, const size_t iHeight) { /* On décharge les précédents objets de rendu */ SAFE_RELEASE(m_pRenderTargetView); SAFE_RELEASE(m_pDepthStencilView); HRESULT hr = S_OK; hr = m_pSwapChain->ResizeBuffers(2, iWidth, iHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0); HR_FAILED_RETURN_FALSE(hr); m_iWidth = iWidth; m_iHeight = iHeight; /* Puis on les recréer */ CreateRenderTarget(); CreateDepthStencilView(); //m_pCube->SetLens() SetViewport(); return true; } |
La fonction qui gère les entrées clavier :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
void D3D10Renderer::OnKeyPressed(const KeyEvent& arg) { if (arg.keyCode == VK_ESCAPE) { SYSTEM->Quit(); } else if (arg.keyCode == VK_F1) { m_bFullscreen = !m_bFullscreen; if (m_bFullscreen) { ResizeSwapChain(m_iWidth, m_iHeight); } m_pSwapChain->SetFullscreenState(m_bFullscreen, nullptr); } else if (arg.keyCode == VK_F2) { static uint32 iMode = 0; // Largeur de la fenêtre uint32 iWidth = m_modes[iMode].Width; // Hauteur de la fenêtre uint32 iHeight = m_modes[iMode].Height; ResizeSwapChain(iWidth, iHeight); RECT rc; GetWindowRect(m_hWnd, &rc); SetWindowPos(m_hWnd, 0, rc.left, rc.top, iWidth, iHeight, SWP_SHOWWINDOW); iMode++; if (iMode >= m_modes.size()) { iMode = 0; } } } |
Résumé :
Depuis DirectX 10 il est plus facile et aisé de changer de résolution et de passer en mode plein écran.
Voici les fichiers source – Partie 6
Références :
– https://msdn.microsoft.com/en-us/library/windows/desktop/ff476389%28v=vs.85%29.aspx
– https://msdn.microsoft.com/en-us/library/windows/desktop/bb174577%28v=vs.85%29.aspx



