Desenhar na tela
APIs importantes
Por fim, portamos o código que desenha o cubo giratório para a tela.
No OpenGL ES 2.0, o contexto de desenho é definido como um tipo EGLContext, que contém os parâmetros de janela e superfície, bem como os recursos necessários para desenhar nos destinos de renderização que serão usados para compor a imagem final exibida na janela. Use esse contexto para configurar os recursos gráficos para exibir corretamente os resultados do pipeline do sombreador na exibição. Um dos principais recursos é o "buffer traseiro" (ou "objeto buffer de quadro") que contém os destinos de renderização finais compostos, prontos para apresentação na exibição.
Com o Direct3D, o processo de configuração dos recursos gráficos para desenhar na exibição é mais didático e requer mais algumas APIs. (No entanto, um modelo Direct3D do Microsoft Visual Studio pode simplificar significativamente esse processo!) Para obter um contexto (chamado de contexto de dispositivo Direct3D), primeiro você deve obter um objeto ID3D11Device1 e usá-lo para criar e configurar um objeto ID3D11DeviceContext1 . Esses dois objetos são usados em conjunto para configurar os recursos específicos necessários para desenhar na exibição.
Resumindo, as APIs DXGI contêm principalmente APIs para gerenciar recursos que pertencem diretamente ao adaptador gráfico, e o Direct3D contém as APIs que permitem que você faça interface entre a GPU e o programa principal em execução na CPU.
Para fins de comparação neste exemplo, aqui estão os tipos relevantes de cada API:
- ID3D11Device1: fornece uma representação virtual do dispositivo gráfico e seus recursos.
- ID3D11DeviceContext1: fornece a interface para configurar buffers e emitir comandos de renderização.
- IDXGISwapChain1: a cadeia de troca é análoga ao buffer traseiro no OpenGL ES 2.0. É a região de memória no adaptador gráfico que contém as imagens renderizadas finais para exibição. É chamado de "cadeia de troca" porque possui vários buffers que podem ser gravados e "trocados" para apresentar a renderização mais recente na tela.
- ID3D11RenderTargetView: contém o buffer de bitmap 2D no qual o contexto do dispositivo Direct3D é desenhado e que é apresentado pela cadeia de troca. Assim como no OpenGL ES 2.0, você pode ter vários destinos de renderização, alguns dos quais não estão vinculados à cadeia de troca, mas são usados para técnicas de sombreamento de várias passagens.
No modelo, o objeto renderizador contém os seguintes campos:
Direct3D 11: Declarações de dispositivo e contexto do 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;
Veja como o buffer traseiro é configurado como um destino de renderização e fornecido à cadeia de troca.
ComPtr<ID3D11Texture2D> backBuffer;
m_swapChainCoreWindow->GetBuffer(0, IID_PPV_ARGS(backBuffer));
m_d3dDevice->CreateRenderTargetView(
backBuffer.Get(),
nullptr,
&m_d3dRenderTargetViewWin);
O runtime do Direct3D cria implicitamente um IDXGISurface1 para o ID3D11Texture2D, que representa a textura como um "buffer traseiro" que a cadeia de troca pode usar para exibição.
A inicialização e a configuração do dispositivo Direct3D e do contexto do dispositivo, bem como os destinos de renderização, podem ser encontrados nos métodos personalizados CreateDeviceResources e CreateWindowSizeDependentResources no modelo Direct3D.
Para obter mais informações sobre o contexto do dispositivo Direct3D no que se refere ao EGL e ao tipo EGLContext, leia Código EGL de porta para DXGI e Direct3D.
Instruções
Passo 1: Renderizando a cena e exibindo-a
Depois de atualizar os dados do cubo (neste caso, girando-o ligeiramente em torno do eixo y), o método Render define a janela de visualização para as dimensões do contexto de desenho (um EGLContext). Esse contexto contém o buffer de cores que será exibido na superfície da janela (um EGLSurface), usando a exibição configurada (EGLDisplay). Neste momento, o exemplo atualiza os atributos de dados de vértice, associa novamente o buffer de índice, desenha o cubo e troca o buffer de cores desenhado pelo pipeline de sombreamento para a superfície de exibição.
OpenGL ES 2.0: Renderizando um quadro para exibição
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);
}
No Direct3D 11, o processo é muito semelhante. (Estamos supondo que você esteja usando a configuração de viewport e destino de renderização do modelo Direct3D.
- Atualize os buffers constantes (a matriz model-view-projection , nesse caso) com chamadas para ID3D11DeviceContext1::UpdateSubresource.
- Defina o buffer de vértice com ID3D11DeviceContext1::IASetVertexBuffers.
- Defina o buffer de índice com ID3D11DeviceContext1::IASetIndexBuffer.
- Defina a topologia de triângulo específica (uma lista de triângulos) com ID3D11DeviceContext1::IASetPrimitiveTopology.
- Defina o layout de entrada do buffer de vértice com ID3D11DeviceContext1::IASetInputLayout.
- Associe o sombreador de vértice com ID3D11DeviceContext1::VSSetShader.
- Associe o sombreador de fragmento com ID3D11DeviceContext1::P SSetShader.
- Envie os vértices indexados por meio dos sombreadores e gere os resultados de cor para o buffer de destino de renderização com ID3D11DeviceContext1::D rawIndexed.
- Exiba o buffer de destino de renderização com IDXGISwapChain1::P resent1.
Direct3D 11: Renderizando um quadro para exibição
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);
}
Depois que IDXGISwapChain1::P resent1 é chamado, o quadro é enviado para a exibição configurada.
Etapa anterior
Comentários
Este exemplo encobre grande parte da complexidade envolvida na configuração de recursos do dispositivo, especialmente para aplicativos DirectX da Plataforma Universal do Windows (UWP). Sugerimos que você examine o código completo do modelo, especialmente as partes que executam a configuração e o gerenciamento de recursos da janela e do dispositivo. Os aplicativos UWP precisam dar suporte a eventos de rotação, bem como eventos de suspensão/retomada, e o modelo demonstra as práticas recomendadas para lidar com a perda de uma interface ou uma alteração nos parâmetros de exibição.
Tópicos relacionados
- Como portar um renderizador OpenGL ES 2.0 simples para o Direct3D 11
- Portar os objetos de sombreador
- Portar o GLSL
- Desenhar na tela