그래픽스/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에 보내는 실행자 실질적인 작업 수행