다음을 통해 공유


화면에 그리기

중요 API

마지막으로 회전하는 큐브를 화면에 그리는 코드를 포팅합니다.

OpenGL ES 2.0에서 그리기 컨텍스트는 창 및 표면 매개 변수뿐만 아니라 창에 표시되는 최종 이미지를 작성하는 데 사용할 렌더링 대상에 그리는 데 필요한 리소스를 포함하는 EGLContext 형식으로 정의됩니다. 이 컨텍스트를 사용하여 디스플레이에 셰이더 파이프라인의 결과를 올바르게 표시하도록 그래픽 리소스를 구성합니다. 기본 리소스 중 하나는 디스플레이에 프레젠테이션할 준비가 된 최종 복합 렌더링 대상이 포함된 "백 버퍼"(또는 "프레임 버퍼 개체")입니다.

Direct3D를 사용하면 디스플레이에 그리기 위해 그래픽 리소스를 구성하는 프로세스가 더 복잡하며 API가 훨씬 더 필요합니다. 하지만 Microsoft Visual Studio Direct3D 템플릿을 사용하면 이 프로세스를 크게 간소화할 수 있습니다. 컨텍스트(Direct3D 디바이스 컨텍스트라고 함)를 가져오려면 먼저 ID3D11Device1 개체를 가져 와서 이를 사용하여 ID3D11DeviceContext1 개체를 만들고 구성해야 합니다. 이러한 두 개체는 디스플레이에 그리는 데 필요한 특정 리소스를 구성하기 위해 함께 사용됩니다.

즉, DXGI API에는 그래픽 어댑터와 직접 관련된 리소스를 관리하기 위한 API가 주로 포함되며, Direct3D에는 GPU와 CPU에서 실행되는 기본 프로그램 간에 인터페이스할 수 있는 API가 포함되어 있습니다.

이 샘플의 비교를 위해 각 API의 관련 형식은 다음과 같습니다.

  • ID3D11Device1: 그래픽 디바이스 및 해당 리소스의 가상 표현을 제공합니다.
  • ID3D11DeviceContext1: 버퍼를 구성하고 렌더링 명령을 실행할 수 있는 인터페이스를 제공합니다.
  • IDXGISwapChain1: 스왑 체인은 OpenGL ES 2.0의 백 버퍼와 유사합니다. 표시할 최종 렌더링된 이미지를 포함하는 그래픽 어댑터의 메모리 영역입니다. "스왑 체인"은 화면에 최신 렌더링을 표시하기 위해 쓸 수 있고 "교환"할 수 있는 여러 버퍼가 있기 때문에 "스왑 체인"이라고 합니다.
  • ID3D11RenderTargetView: Direct3D 디바이스 컨텍스트가 그리는 2D 비트맵 버퍼가 포함되어 있고, 이는 스왑 체인에 의해 표시됩니다. OpenGL ES 2.0과 마찬가지로 여러 렌더링 대상이 있을 수 있으며, 그 중 일부는 스왑 체인에 바인딩되지 않지만 다중 패스 음영 기술에 사용됩니다.

템플릿에서 렌더러 개체에는 다음 필드가 포함됩니다.

Direct3D 11: 디바이스 및 디바이스 컨텍스트 선언

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;

백 버퍼가 렌더링 대상으로 구성되고 스왑 체인에 제공되는 방법은 다음과 같습니다.

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

Direct3D 런타임은 ID3D11Texture2D에 대한 IDXGISurface1을 암시적으로 만들며, 이는 스왑 체인이 표시에 사용할 수 있는 "백 버퍼"로 텍스처를 나타냅니다.

Direct3D 디바이스 및 디바이스 컨텍스트의 초기화 및 구성과 렌더링 대상은 Direct3D 템플릿의 사용자 지정 CreateDeviceResourcesCreateWindowSizeDependentResources 메서드에서 찾을 수 있습니다.

EGL 및 EGLContext 형식과 관련된 Direct3D 디바이스 컨텍스트에 대한 자세한 내용은 EGL 코드를 DXGI 및 Direct3D로 포팅을 참조하세요.

지침

1단계: 장면 렌더링 및 표시

큐브 데이터를 업데이트한 후(이 경우 y축을 약간 회전하여) Render 메서드는 뷰포트를 그리는 컨텍스트(EGLContext)의 크기로 설정합니다. 이 컨텍스트에는 구성된 디스플레이(EGLDisplay)를 사용하여 창 화면(EGLSurface)에 표시되는 색 버퍼가 포함됩니다. 이때 예제에서는 꼭짓점 데이터 특성을 업데이트하고, 인덱스 버퍼를 다시 바인딩하고, 큐브를 그리고, 음영 파이프라인에서 그린 색 버퍼를 디스플레이 화면에 교환합니다.

OpenGL ES 2.0: 표시할 프레임 렌더링

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에서는 프로세스가 매우 유사합니다. (Direct3D 템플릿에서 뷰포트 및 렌더링 대상 구성을 사용한다고 가정합니다.

Direct3D 11: 표시할 프레임 렌더링

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::P resent1을 호출하면 프레임이 구성된 디스플레이에 출력됩니다.

이전 단계

GLSL 포팅

설명

이 예제에서는 특히 UWP(유니버설 Windows 플랫폼) DirectX 앱의 경우 디바이스 리소스 구성에 들어가는 대부분의 복잡성을 설명합니다. 전체 템플릿 코드, 특히 창 및 디바이스 리소스 설정 및 관리를 수행하는 부분을 검토하는 것이 좋습니다. UWP 앱은 순환 이벤트와 일시 중단/다시 시작 이벤트를 지원해야 하며, 템플릿은 인터페이스 손실 또는 표시 매개 변수 변경 처리를 위한 모범 사례를 보여 줍니다.