Disegnare sullo schermo
API importanti
È arrivato il momento di portare il codice che disegna il cubo rotante sullo schermo.
In OpenGL ES 2.0, il contesto di disegno è definito come tipo EGLContext contenente i parametri finestra e di superficie e le risorse necessarie per disegnare nelle destinazioni di rendering, le quali verranno usate per comporre l'immagine finale visualizzata nella finestra. Tale contesto consente di configurare le risorse grafiche per visualizzare correttamente i risultati della pipeline dello shader sullo schermo. Una delle principali risorse è il "back buffer" (anche detto "oggetto buffer frame") che contiene le destinazioni di rendering composte finali, pronte per essere presentate alla visualizzazione.
Con Direct3D, il processo di configurazione delle risorse grafiche per il disegno sullo schermo è più didattico e richiede molte altre API. Un modello Direct3D di Microsoft Visual Studio può però semplificare molto questo processo. Per ottenere un contesto (chiamato anche contesto di dispositivo Direct3D), devi prima ottenere un oggetto ID3D11Device1 e usarlo per creare e configurare un oggetto ID3D11DeviceContext1. Questi due oggetti vengono usati insieme per configurare le risorse specifiche necessarie per il disegno nella visualizzazione.
In breve, le API DXGI contengono principalmente API per la gestione delle risorse direttamente relative alla scheda grafica, mentre Direct3D contiene le API che consentono di interfacciarsi tra la GPU e il programma principale in esecuzione sulla CPU.
Ai fini del confronto in questo esempio, ecco i tipi pertinenti di ogni API:
- ID3D11Device1: fornisce una rappresentazione virtuale del dispositivo grafico e delle relative risorse.
- ID3D11DeviceContext1: fornisce l'interfaccia per configurare i buffer ed eseguire i comandi di rendering.
- IDXGISwapChain1: la swapchain è analoga al buffer nascosto in OpenGL ES 2.0. Si tratta dell'area di memoria nella scheda grafica che contiene le immagini di cui è stato eseguito il rendering finale per la visualizzazione. Viene chiamata "swapchain", cioè catena di scambio, perché ha diversi buffer che possono essere scritti e "scambiati" per presentare il rendering più recente sullo schermo.
- ID3D11RenderTargetView: contiene il buffer bitmap 2D in cui viene disegnato il contesto del dispositivo Direct3D e che viene presentato dalla swapchain. Come per OpenGL ES 2.0, è possibile avere più destinazioni di rendering, alcune delle quali non associate alla swapchain, ma usate per tecniche di ombreggiatura a più passaggi.
Nel modello, l'oggetto renderer contiene i campi seguenti:
Direct3D 11: Dichiarazioni del dispositivo e del contesto di dispositivo
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;
Ecco come il buffer nascosto viene configurato come destinazione di rendering e fornito alla swapchain.
ComPtr<ID3D11Texture2D> backBuffer;
m_swapChainCoreWindow->GetBuffer(0, IID_PPV_ARGS(backBuffer));
m_d3dDevice->CreateRenderTargetView(
backBuffer.Get(),
nullptr,
&m_d3dRenderTargetViewWin);
Il runtime Direct3D crea in modo implicito un IDXGISurface1 per ID3D11Texture2D, che rappresenta la texture come "buffer nascosto" utilizzabile dalla swapchain per la visualizzazione.
L'inizializzazione e la configurazione del dispositivo Direct3D e del contesto di dispositivo, oltre alle destinazioni di rendering, sono disponibili nei metodi CreateDeviceResources e CreateWindowSizeDependentResources nel modello Direct3D.
Per maggiori informazioni sul contesto di dispositivo Direct3D in relazione a EGL e al tipo EGLContext, leggere Convertire il codice EGL in DXGI e Direct3D.
Istruzioni
Passaggio 1: Rendering della scena e visualizzazione
Dopo avere aggiornato i dati del cubo (in questo caso ruotandolo leggermente intorno all'asse y), il metodo Render imposta il riquadro di visualizzazione sulle dimensioni del contesto di disegno (un oggetto EGLContext). Tale contesto contiene il buffer dei colori che verrà visualizzato sulla superficie della finestra (EGLSurface), usando la visualizzazione configurata (EGLDisplay). In questo momento, l'esempio aggiorna gli attributi dei dati dei vertici, associa nuovamente il buffer degli indici, disegna il cubo e scambia il buffer colori disegnato dalla pipeline di ombreggiatura alla superficie di visualizzazione.
OpenGL ES 2.0: rendering di un frame per la visualizzazione
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);
}
In Direct3D 11 il processo è molto simile. Si presuppone che si stia usando il riquadro di visualizzazione e la configurazione della destinazione di rendering dal modello Direct3D.
- Aggiornare i buffer costanti (matrice model-view-projection, in questo caso) con chiamate a ID3D11DeviceContext1::UpdateSubresource.
- Impostare il buffer dei vertici con ID3D11DeviceContext1::IASetVertexBuffers.
- Impostare il buffer degli indici con ID3D11DeviceContext1::IASetIndexBuffer.
- Impostare la topologia del triangolo specifica (elenco di triangoli) con ID3D11DeviceContext1::IASetPrimitiveTopology.
- Impostare il layout di input del buffer dei vertici con ID3D11DeviceContext1::IASetInputLayout.
- Associare il vertex shader con ID3D11DeviceContext1::VSSetShader.
- Associare lo shader del frammento con ID3D11DeviceContext1::PSSetShader.
- Inviare i vertici indicizzati tramite gli shader e restituire i risultati del colore nel buffer di destinazione di rendering con ID3D11DeviceContext1::DrawIndexed.
- Visualizzare il buffer di destinazione di rendering con IDXGISwapChain1::Present1.
Direct3D 11: rendering di un frame per la visualizzazione
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);
}
Dopo avere chiamato IDXGISwapChain1::Present1, il fotogramma viene restituito alla visualizzazione configurata.
Passaggio precedente
Osservazioni:
Questo esempio illustra gran parte della complessità che si estende alla configurazione delle risorse del dispositivo, in particolare per le app DirectX della piattaforma UWP (Universal Windows Platform). È consigliabile esaminare il codice completo del modello, in particolare le parti che eseguono la configurazione e la gestione delle risorse della finestra e del dispositivo. Le app UWP devono supportare gli eventi di rotazione e di sospensione/ripresa e il modello illustra le procedure consigliate per gestire la perdita di un'interfaccia o una modifica nei parametri di visualizzazione.
Argomenti correlati
- Procedura: convertire un semplice renderer OpenGL ES 2.0 in Direct3D 11
- Convertire gli oggetti shader
- Convertire il codice GLSL
- Disegnare sullo schermo
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per