Рисование на экранеDraw to the screen

Важные APIImportant APIs

Наконец, мы переносим код, который отрисовывает вращающийся куб на экране.Finally, we port the code that draws the spinning cube to the screen.

В OpenGL ES 2.0 тип контекста отрисовки определяется как EGLContext. Он содержит параметры окна и поверхности, а также ресурсы, необходимые для отрисовки в однобуферной прорисовке, которая будет использована для создания конечного изображения, отображаемого в окне.In OpenGL ES 2.0, your drawing context is defined as an EGLContext type, which contains the window and surface parameters as well the resources necessary for drawing to the render targets that will be used to compose the final image displayed to the window. Вы используете этот контекст, чтобы настроить графические ресурсы на правильное отображение результатов конвейера шейдеров на дисплее.You use this context to configure the graphics resources to correctly display the results of your shader pipeline on the display. Одним из основных ресурсов является задний буфер (или объект буфера кадра), который содержит окончательную составленную однобуферную прорисовку, готовую к представлению на дисплее.One of the primary resources is the "back buffer" (or "frame buffer object") that contains the final, composited render targets, ready for presentation to the display.

При использовании Direct3D процесс настройки графических ресурсов для отрисовки на дисплее носит более дидактический характер и требует большего количества API.With Direct3D, the process of configuring the graphics resources for drawing to the display is more didactic, and requires quite a few more APIs. (Хотя шаблон Direct3D в Microsoft Visual Studio может существенно упростить этот процесс!) Чтобы получить контекст (который называется контекстом устройства Direct3D), сначала необходимо получить объект ID3D11Device1 и использовать его для создания и настройки объекта ID3D11DeviceContext1.(A Microsoft Visual Studio Direct3D template can significantly simplify this process, though!) To obtain a context (called a Direct3D device context), you must first obtain an ID3D11Device1 object, and use it to create and configure an ID3D11DeviceContext1 object. Эти два объекта используются совместно для настройки определенных ресурсов, необходимых для отрисовки на дисплее.These two objects are used in conjunction to configure the specific resources you need for drawing to the display.

Если коротко, API DXGI содержат в основном API для управления ресурсами, которые имеют прямое отношение к графическому адаптеру, а Direct3D содержит API, которые обеспечивают интерфейс между GPU и вашей главной программой, работающей на ЦП.In short, the DXGI APIs contain primarily APIs for managing resources that directly pertain to the graphics adapter, and Direct3D contains the APIs that allow you to interface between the GPU and your main program running on the CPU.

Для сравнения в этом примере представлены соответствующие типы тех и других API.For the purposes of comparison in this sample, here are the relevant types from each API:

  • ID3D11Device1: обеспечивает виртуальное представление графического устройства и его ресурсов.ID3D11Device1: provides a virtual representation of the graphics device and its resources.
  • ID3D11DeviceContext1: обеспечивает интерфейс для настройки буферов и выпуска команд отрисовки.ID3D11DeviceContext1: provides the interface to configure buffers and issue rendering commands.
  • IDXGISwapChain1: цепочка буферов является аналогом заднего буфера в OpenGL ES 2.0.IDXGISwapChain1: the swap chain is analogous to the back buffer in OpenGL ES 2.0. Это область памяти на графическом адаптере, которая содержит окончательные обработанные изображения для дисплея.It is the region of memory on the graphics adapter that contains the final rendered image(s) for display. Она называется цепочкой буферов, потому что содержит несколько буферов, в которые можно записать последнюю обработку и которые можно переключить для ее представления на экране.It is called the "swap chain" because it has several buffers that can be written to and "swapped" to present the latest render to the screen.
  • ID3D11RenderTargetView: содержит буфер двухмерных точечных рисунков, в котором выполняет отрисовку контекст устройства Direct3D и который представляется цепочкой буферов.ID3D11RenderTargetView: this contains the 2D bitmap buffer that the Direct3D device context draws into, and which is presented by the swap chain. Как и в OpenGL ES 2.0, вы можете использовать многобуферную прорисовку, часть буферов которой не привязана к цепочке буферов, но используется для методов многоэтапной заливки.As with OpenGL ES 2.0, you can have multiple render targets, some of which are not bound to the swap chain but are used for multi-pass shading techniques.

В шаблоне объект обработчика содержит следующие поля.In the template, the renderer object contains the following fields:

Direct3D 11: объявления устройства и контекста устройстваDirect3D 11: Device and device context declarations

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;

Вот как можно настроить задний буфер в качестве однобуферной прорисовки и предоставить его цепочке буферов.Here's how the back buffer is configured as a render target and provided to the swap chain.

ComPtr<ID3D11Texture2D> backBuffer;
m_swapChainCoreWindow->GetBuffer(0, IID_PPV_ARGS(backBuffer));
m_d3dDevice->CreateRenderTargetView(
  backBuffer.Get(),
  nullptr,
  &m_d3dRenderTargetViewWin);

Среда выполнения Direct3D неявно создает IDXGISurface1 для ID3D11Texture2D, представляющий текстуру в качестве заднего буфера, который в свою очередь может использовать цепочка буферов для отображения.The Direct3D runtime implicitly creates an IDXGISurface1 for the ID3D11Texture2D, which represents the texture as a "back buffer" that the swap chain can use for display.

Инициализацию и настройку устройства и контекста устройства Direct3D, а также однобуферную прорисовку можно найти в пользовательских методах CreateDeviceResources и CreateWindowSizeDependentResources в шаблоне Direct3D.The initialization and configuration of the Direct3D device and device context, as well as the render targets, can be found in the custom CreateDeviceResources and CreateWindowSizeDependentResources methods in the Direct3D template.

Подробнее о контексте устройства Direct3D и его отношении к типам контекста EGL и EGLContext читайте в разделе Перенос кода EGL в DXGI и Direct3D.For more info on Direct3D device context as it relates to EGL and the EGLContext type, read Port EGL code to DXGI and Direct3D.

InstructionsInstructions

Шаг 1. Отрисовка и отображение сценыStep 1: Rendering the scene and displaying it

После обновления данных куба (в нашем случае путем небольшого вращения вокруг оси Y) метод обработки настраивает окно просмотра в соответствии с размерами контекста обработки (EGLContext).After updating the cube data (in this case, by rotating it slightly around the y axis), the Render method sets the viewport to the dimensions of he drawing context (an EGLContext). Этот контекст содержит буфер цвета, который будет отображен на поверхности окна (EGLSurface) с помощью настроенного дисплея (EGLDisplay).This context contains the color buffer that will be displayed to the window surface (an EGLSurface), using the configured display (EGLDisplay). В это время пример обновляет атрибуты данных вершины, повторно привязывает буфер индексов, отрисовывает куб и подключает буфер цвета, отрисованный конвейером заливки на поверхности отображения.At this time, the example updates the vertex data attributes, re-binds the index buffer, draws the cube, and swaps in color buffer drawn by the shading pipeline to the display surface.

OpenGL ES 2.0: отрисовка кадра для отображенияOpenGL ES 2.0: Rendering a frame for display

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);
}

В Direct3D 11 процесс очень прост.In Direct3D 11, the process is very similar. (Мы предполагаем, что вы используете окно просмотра и конфигурацию однобуферной прорисовки шаблона Direct3D.)(We're assuming that you're using the viewport and render target configuration from the Direct3D template.

Direct3D 11: отрисовка кадра для отображенияDirect3D 11: Rendering a frame for display

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, &parameters);
}

После вызова IDXGISwapChain1::Present1 кадр выводится на настроенный дисплей.Once IDXGISwapChain1::Present1 is called, your frame is output to the configured display.

Предыдущий шагPrevious step

Перенос GLSLPort the GLSL

RemarksRemarks

Этот пример значительно снижает сложность настройки ресурсов устройства, особенно для приложений универсальной платформы Windows (UWP) с DirectX.This example glosses over much of the complexity that goes into configuring device resources, especially for Universal Windows Platform (UWP) DirectX apps. Мы предлагаем вам просмотреть полный код шаблона, особенно те части, которые касаются настройки и управления окном и ресурсами устройства.We suggest you review the full template code, especially the parts that perform the window and device resource setup and management. Приложения UWP должны поддерживать события поворота, а также события приостановки и возобновления. Шаблон демонстрирует рекомендованный способ справиться с потерей интерфейса или изменением параметров дисплея.UWP apps have to support rotation events as well as suspend/resume events, and the template demonstrates best practices for handling the loss of an interface or a change in the display parameters.