화면에 그리기
중요 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 템플릿의 사용자 지정 CreateDeviceResources 및 CreateWindowSizeDependentResources 메서드에서 찾을 수 있습니다.
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 템플릿에서 뷰포트 및 렌더링 대상 구성을 사용한다고 가정합니다.
- ID3D11DeviceContext1::UpdateSubresource에 대한 호출로 상수 버퍼(이 경우 모델-뷰 프로젝션 매트릭스)를 업데이트합니다.
- ID3D11DeviceContext1::IASetVertexBuffers를 사용하여 꼭짓점 버퍼를 설정합니다.
- ID3D11DeviceContext1::IASetIndexBuffer를 사용하여 인덱스 버퍼를 설정합니다.
- ID3D11DeviceContext1::IASetPrimitiveTopology를 사용하여 특정 삼각형 토폴로지(삼각형 목록)를 설정합니다.
- ID3D11DeviceContext1::IASetInputLayout을 사용하여 꼭짓점 버퍼의 입력 레이아웃을 설정합니다.
- ID3D11DeviceContext1::VSSetShader를 사용하여 꼭짓점 셰이더를 바인딩합니다.
- ID3D11DeviceContext1::P SSetShader를 사용하여 조각 셰이더를 바인딩합니다.
- 셰이더를 통해 인덱싱된 꼭짓점을 보내고 ID3D11DeviceContext1::D rawIndexed를 사용하여 렌더링 대상 버퍼에 색 결과를 출력합니다.
- IDXGISwapChain1::P resent1을 사용하여 렌더링 대상 버퍼를 표시합니다.
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, ¶meters);
}
IDXGISwapChain1::P resent1을 호출하면 프레임이 구성된 디스플레이에 출력됩니다.
이전 단계
설명
이 예제에서는 특히 UWP(유니버설 Windows 플랫폼) DirectX 앱의 경우 디바이스 리소스 구성에 들어가는 대부분의 복잡성을 설명합니다. 전체 템플릿 코드, 특히 창 및 디바이스 리소스 설정 및 관리를 수행하는 부분을 검토하는 것이 좋습니다. UWP 앱은 순환 이벤트와 일시 중단/다시 시작 이벤트를 지원해야 하며, 템플릿은 인터페이스 손실 또는 표시 매개 변수 변경 처리를 위한 모범 사례를 보여 줍니다.
관련 항목