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 :
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 :
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 :
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


