Dessiner sur l’écran
API importantes
Enfin, nous portons le code qui dessine le cube épinglant à l’écran.
Dans OpenGL ES 2.0, votre contexte de dessin est défini comme un type EGLContext, qui contient les paramètres de fenêtre et de surface, ainsi que les ressources nécessaires pour dessiner sur les cibles de rendu qui seront utilisées pour composer l’image finale affichée dans la fenêtre. Vous utilisez ce contexte pour configurer les ressources graphiques pour afficher correctement les résultats de votre pipeline de nuanceur sur l’affichage. L’une des ressources principales est la « mémoire tampon de retour » (ou l’objet de mémoire tampon de trame) qui contient les cibles de rendu finales composites, prêtes pour la présentation à l’affichage.
Avec Direct3D, le processus de configuration des ressources graphiques pour dessiner sur l’affichage est plus didactique et nécessite quelques API supplémentaires. (Un modèle Microsoft Visual Studio Direct3D peut simplifier considérablement ce processus, cependant !) Pour obtenir un contexte (appelé contexte d’appareil Direct3D), vous devez d’abord obtenir un objet ID3D11Device1, puis l’utiliser pour créer et configurer un objet ID3D11DeviceContext1. Ces deux objets sont utilisés conjointement pour configurer les ressources spécifiques dont vous avez besoin pour dessiner sur l’affichage.
En bref, les API DXGI contiennent principalement des API pour la gestion des ressources qui se rapportent directement à la carte graphique, et Direct3D contient les API qui vous permettent d’interagir entre le GPU et votre programme principal s’exécutant sur l’UC.
Pour les besoins de comparaison dans cet exemple, voici les types pertinents de chaque API :
- ID3D11Device1 : fournit une représentation virtuelle de l’appareil graphique et de ses ressources.
- ID3D11DeviceContext1 : fournit l’interface pour configurer des mémoires tampons et émettre des commandes de rendu.
- IDXGISwapChain1 : la chaîne d’échange est analogue à la mémoire tampon arrière dans OpenGL ES 2.0. Il s’agit de la région de mémoire sur l’adaptateur graphique qui contient la ou les images rendues finales pour l’affichage. Il est appelé « chaîne d’échange », car il a plusieurs mémoires tampons qui peuvent être écrites dans et « permutées » pour présenter le rendu le plus récent à l’écran.
- ID3D11RenderTargetView : contient la mémoire tampon bitmap 2D dans laquelle le contexte d’appareil Direct3D s’inscrit et qui est présenté par la chaîne d’échange. Comme avec OpenGL ES 2.0, vous pouvez avoir plusieurs cibles de rendu, dont certaines ne sont pas liées à la chaîne d’échange, mais sont utilisées pour les techniques d’ombrage multi-passe.
Dans le modèle, l’objet renderer contient les champs suivants :
Direct3D 11 : Déclarations de contexte d’appareil et d’appareil
Platform::Agile<Windows::UI::Core::CoreWindow> m_window;
Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_d3dContext;
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChainCoreWindow;
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_d3dRenderTargetViewWin;
Voici comment la mémoire tampon de retour est configurée en tant que cible de rendu et fournie à la chaîne d’échange.
ComPtr<ID3D11Texture2D> backBuffer;
m_swapChainCoreWindow->GetBuffer(0, IID_PPV_ARGS(backBuffer));
m_d3dDevice->CreateRenderTargetView(
backBuffer.Get(),
nullptr,
&m_d3dRenderTargetViewWin);
Le runtime Direct3D crée implicitement un IDXGISurface1 pour l’ID3D11Texture2D, qui représente la texture en tant que « mémoire tampon back » que la chaîne d’échange peut utiliser pour l’affichage.
L’initialisation et la configuration du contexte d’appareil et d’appareil Direct3D, ainsi que les cibles de rendu, sont disponibles dans les méthodes CreateDeviceResources et CreateWindowSizeDependentResources personnalisées dans le modèle Direct3D.
Pour plus d’informations sur le contexte d’appareil Direct3D, car il est lié à EGL et au type EGLContext, lisez le code EGL du port vers DXGI et Direct3D.
Instructions
Étape 1 : Rendu de la scène et affichage de celle-ci
Après avoir mis à jour les données de cube (dans ce cas, en la faisant pivoter légèrement autour de l’axe y), la méthode Render définit la fenêtre d’affichage sur les dimensions du contexte de dessin (un EGLContext). Ce contexte contient la mémoire tampon de couleur qui s’affiche sur l’aire de fenêtre (un EGLSurface), à l’aide de l’affichage configuré (EGLDisplay). À ce stade, l’exemple met à jour les attributs de données de vertex, lie à nouveau la mémoire tampon d’index, dessine le cube et permute la mémoire tampon de couleur dessinée par le pipeline d’ombrage vers l’aire d’affichage.
OpenGL ES 2.0 : rendu d’un cadre pour l’affichage
void Render(GraphicsContext *drawContext)
{
Renderer *renderer = drawContext->renderer;
int loc;
// Set the viewport
glViewport ( 0, 0, drawContext->width, drawContext->height );
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
// Use the program object
glUseProgram (renderer->programObject);
// Load the a_position attribute with the vertex position portion of a vertex buffer element
loc = glGetAttribLocation(renderer->programObject, "a_position");
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE,
sizeof(Vertex), 0);
glEnableVertexAttribArray(loc);
// Load the a_color attribute with the color position portion of a vertex buffer element
loc = glGetAttribLocation(renderer->programObject, "a_color");
glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
glEnableVertexAttribArray(loc);
// Bind the index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer->indexBuffer);
// Load the MVP matrix
glUniformMatrix4fv(renderer->mvpLoc, 1, GL_FALSE, (GLfloat*) &renderer->mvpMatrix.m[0][0]);
// Draw the cube
glDrawElements(GL_TRIANGLES, renderer->numIndices, GL_UNSIGNED_INT, 0);
eglSwapBuffers(drawContext->eglDisplay, drawContext->eglSurface);
}
Dans Direct3D 11, le processus est très similaire. (Nous partons du principe que vous utilisez la fenêtre d’affichage et affichez la configuration cible à partir du modèle Direct3D.
- Mettez à jour les mémoires tampons constantes (matrice model-view-projection, dans ce cas) avec des appels à ID3D11DeviceContext1 ::UpdateSubresource.
- Définissez la mémoire tampon de vertex avec ID3D11DeviceContext1 ::IASetVertexBuffers.
- Définissez la mémoire tampon d’index avec ID3D11DeviceContext1 ::IASetIndexBuffer.
- Définissez la topologie de triangle spécifique (une liste de triangles) avec ID3D11DeviceContext1 ::IASetPrimitiveTopology.
- Définissez la disposition d’entrée de la mémoire tampon de vertex avec ID3D11DeviceContext1 ::IASetInputLayout.
- Lier le nuanceur de vertex avec ID3D11DeviceContext1 ::VSSetShader.
- Lier le nuanceur de fragments avec ID3D11DeviceContext1 ::P SSetShader.
- Envoyez les sommets indexés via les nuanceurs et affichez les résultats de couleur vers la mémoire tampon de la cible de rendu avec ID3D11DeviceContext1 ::D rawIndexed.
- Affichez la mémoire tampon cible de rendu avec IDXGISwapChain1 ::P resent1.
Direct3D 11 : Rendu d’un cadre pour l’affichage
void RenderObject::Render()
{
// ...
// Only update shader resources that have changed since the last frame.
m_d3dContext->UpdateSubresource(
m_constantBuffer.Get(),
0,
NULL,
&m_constantBufferData,
0,
0);
// Set up the IA stage corresponding to the current draw operation.
UINT stride = sizeof(VertexPositionColor);
UINT offset = 0;
m_d3dContext->IASetVertexBuffers(
0,
1,
m_vertexBuffer.GetAddressOf(),
&stride,
&offset);
m_d3dContext->IASetIndexBuffer(
m_indexBuffer.Get(),
DXGI_FORMAT_R16_UINT,
0);
m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_d3dContext->IASetInputLayout(m_inputLayout.Get());
// Set up the vertex shader corresponding to the current draw operation.
m_d3dContext->VSSetShader(
m_vertexShader.Get(),
nullptr,
0);
m_d3dContext->VSSetConstantBuffers(
0,
1,
m_constantBuffer.GetAddressOf());
// Set up the pixel shader corresponding to the current draw operation.
m_d3dContext->PSSetShader(
m_pixelShader.Get(),
nullptr,
0);
m_d3dContext->DrawIndexed(
m_indexCount,
0,
0);
// ...
m_swapChainCoreWindow->Present1(1, 0, ¶meters);
}
Une fois que IDXGISwapChain1 ::P resent1 est appelé, votre frame est généré dans l’affichage configuré.
Étape précédente
Notes
Cet exemple illustre une grande partie de la complexité de la configuration des ressources d’appareil, en particulier pour les applications DirectX (UWP) plateforme Windows universelle. Nous vous suggérons de passer en revue le code de modèle complet, en particulier les parties qui effectuent la configuration et la gestion des ressources de fenêtre et d’appareil. Les applications UWP doivent prendre en charge les événements de rotation, ainsi que les événements de suspension/reprise, et le modèle illustre les meilleures pratiques de gestion de la perte d’une interface ou d’une modification des paramètres d’affichage.
Rubriques connexes
- Guide pratique pour porter un convertisseur OpenGL ES 2.0 simple vers Direct3D 11
- Porter les objets nuanceur
- Porter le langage GLSL
- Dessiner sur l’écran