그래픽스/DX11
D3D11 Resize Viewport
뽀또치즈맛
2025. 6. 10. 23:21
뷰 포트를 윈도우 전체가 아니라,
원하는 영역만 뷰포트를 사용하도록 하는 예제를 짜볼 것이다.
그 전에 RTV에 대한 정의를 해보자.
RTV(Render Target View)란?
RTV(Render Target View)는 GPU가 픽셀을 출력할 수 있는 대상(Render Target)을 가리키는 Direct3D 11의 뷰(View) 객체이다.
흔히 백 버퍼(back buffer)나 오프스크린 텍스처와 연결된다.
RTV를 OMSetRenderTargets()를 통해 파이프라인에 바인딩하면, 렌더링 결과가 해당 리소스에 출력된다.
뷰포트 설정 시, 이 RTV가 참조하는 텍스처의 크기를 기준으로 자동 조절 가능하다.
전체 코드: RTV 기준 자동 뷰포트 설정
#include <d3d11.h>
#include <wrl/client.h> // Microsoft::WRL::ComPtr
using Microsoft::WRL::ComPtr;
// 클래스 내 멤버 선언 예시
ComPtr<ID3D11DeviceContext> m_context;
D3D11_VIEWPORT m_screenViewport;
// 함수: RTV의 텍스처 크기를 기반으로 뷰포트를 자동 설정
void AppBase::SetViewportFromRenderTarget(ID3D11RenderTargetView* renderTargetView)
{
// 1. Render Target View에서 리소스를 가져옵니다 (보통은 텍스처입니다)
ComPtr<ID3D11Resource> resource;
renderTargetView->GetResource(&resource);
// 2. 이 리소스를 2D 텍스처로 캐스팅
ComPtr<ID3D11Texture2D> texture;
HRESULT hr = resource.As(&texture);
if (FAILED(hr)) {
// 캐스팅 실패 시 로그 출력 또는 처리
OutputDebugStringA("Failed to cast resource to Texture2D.\n");
return;
}
// 3. 텍스처의 설명(너비, 높이 등)을 가져옴
D3D11_TEXTURE2D_DESC desc = {};
texture->GetDesc(&desc);
// 4. 텍스처 크기를 기반으로 뷰포트를 설정
D3D11_VIEWPORT vp = {};
vp.TopLeftX = 0.0f; // 좌상단 X 좌표
vp.TopLeftY = 0.0f; // 좌상단 Y 좌표
vp.Width = static_cast<float>(desc.Width); // 텍스처 너비
vp.Height = static_cast<float>(desc.Height); // 텍스처 높이
vp.MinDepth = 0.0f; // 뷰포트의 최소 깊이
vp.MaxDepth = 1.0f; // 뷰포트의 최대 깊이
// 5. 멤버 변수로 저장하고 GPU에 적용
m_screenViewport = vp;
m_context->RSSetViewports(1, &m_screenViewport);
}
사용 예: 창 크기 변경 후 뷰포트 재설정
void AppBase::OnResize(UINT newWidth, UINT newHeight)
{
// 창 크기 변경에 따라 렌더 타겟 다시 생성
RecreateRenderTarget(newWidth, newHeight);
// 생성된 RTV를 기준으로 뷰포트 자동 설정
SetViewportFromRenderTarget(m_renderTargetView.Get());
}
ComPtr<ID3D11DeviceContext> m_context
Direct3 11의 디바이스 컨텍스트를 나타낸다.
GPU 파이프라인 상태를 설정하고, 그리기 명령을 보내는 핵심 객체이다.
주요 기능:
- 뷰포트 설정 (RSSetViewports)
- 렌더 타겟 설정 (OMSetRenderTargets)
- 쉐이더 바인딩 (VSSetShader, PSSetShader 등)
- 버퍼 바인딩 (IASetVertexBuffers, IASetIndexBuffer)
- 드로우 호출 (Draw, DrawIndexed, Dispatch 등)
ComPtr이란?
- Microsoft::WRL::ComPtr<T>는 COM 객체를 자동으로 참조 카운트 관리해주는 스마트 포인터
- 수동으로 Release()를 호출하지 않아도 안전하게 사용 가능
- COM 기반의 Direct3D에서 메모리 누수를 방지하는 매우 권장되는 방식
D3D11_VIEWPORT m_screenViewport
GPU에서 픽셀을 출력할 영역(viewport)을 정의하는 구조체이다.
보통 스크린에 렌더링할 때 사용할 렌더 타겟에 대응하는 크기와 위치로 설정한다.
TopLeftX | 뷰포트의 시작 X 좌표 (보통 0.0f) |
TopLeftY | 뷰포트의 시작 Y 좌표 (보통 0.0f) |
Width | 뷰포트의 너비 (픽셀 단위, 보통 화면 너비) |
Height | 뷰포트의 높이 (픽셀 단위, 보통 화면 높이) |
MinDepth | 깊이 버퍼의 최소값 (일반적으로 0.0f) |
MaxDepth | 깊이 버퍼의 최대값 (일반적으로 1.0f) |
정리
m_context | 디바이스 컨텍스트 객체 | GPU 파이프라인 설정 및 드로우 명령 |
m_screenViewport | 뷰포트 정의 구조체 | 화면에 그릴 영역의 위치와 크기 |
++Plus++
Device Context란?
디바이스 컨텍스트란 GPU에 모든 렌더링 명령을 전달하는 실행 창구이다.
더 쉽게 정리
- ID3D11Device: 렌더링에 필요한 GPU 자원을 생성하는 객체
→ 예: 버퍼, 텍스처, 쉐이더 생성 - ID3D11DeviceContext: 생성된 자원을 바탕으로 렌더링을 수행하는 객체
→ 예: 버퍼 바인딩, 쉐이더 설정, 그리기 명령 실행
ID3D11Device | 자원 생성자 |
ID3D11DeviceContext | 렌더링 실행자 |
GPU | 실제로 명령을 수행하는 장치 |
Device Context 주요 메서드 설명
RSSetViewports() | 뷰포트를 설정함 |
IASetVertexBuffers() | 정점 버퍼를 바인딩함 |
VSSetShader() | 버텍스 쉐이더 바인딩 |
OMSetRenderTargets() | 렌더 타겟을 바인딩 |
Draw() 또는 DrawIndexed() | 드로우 명령 실행 |
ClearRenderTargetView() | 화면을 색으로 초기화 (배경색 칠하기) |
예시 코
// 렌더 타겟 클리어
float clearColor[4] = { 0.1f, 0.1f, 0.3f, 1.0f };
m_context->ClearRenderTargetView(m_renderTargetView.Get(), clearColor);
// 정점 버퍼 바인딩
m_context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
// 쉐이더 바인딩
m_context->VSSetShader(m_vertexShader.Get(), nullptr, 0);
m_context->PSSetShader(m_pixelShader.Get(), nullptr, 0);
// 드로우 명령
m_context->Draw(vertexCount, 0);
Device | GPU 자원 생성자 | 리소스를 만드는 데 쓰임 |
DeviceContext | 렌더링 명령을 GPU에 보내는 실행자 | 실질적인 작업 수행 |