이번 포스트에서는 Render Target View와 Depth Stencil View에 대한 내용을 정리해보았다. Render Target View와 Depth Stencil View가 무엇인지에 대해 알아보기 전에 Resource와 View가 무엇이고 어떤 관계인지에 대해 알아야 한다.
Resource (ID3D11Resource) & View (ID3D11View)
Resource는 DirectX에서 사용되는 다양한 자원들을 의미한다 (예 : Texture2D). DirectX에서 렌더링을 할 때, 일반적으로 Device로부터 Resource를 생성하고, 생성된 Resource를 Device Context에 전달하여 어떤 방식으로 렌더링할 것인지 설정하는 구조를 갖게 된다. 이 때, Resource를 Device Context에 직접 전달하는 것이 아니고, View라는 것을 대신 전달한다. View는 어떤 Resource가 특정한 역할을 할 것임을 나타내는 자격증이자 중간 전달자 같은 역할을 하는 객체이다. Render Target View의 설명을 보다보면 더 이해가 잘 될 것이다.
Render Target View
Render Target은 이전 포스트에서 Swapchain을 다룰 때 설명했던 BackBuffer 역할을 하는 텍스쳐이다.
(1) SwapChain으로부터 Render Target Texture 전달 받기
우리는 Device Context가 어떤 Texture에 렌더링을 수행할 지 설정을 해줘야 하는데, Swapchain을 생성할 때 전달해준 Description (예: 해상도, Format)을 통해 이미 Texture가 생성되어있어 이 Texture을 받아서 사용하면 된다. 아래는 SwapChain으로부터 ID3D11Texture2D타입의 리소스를 m_RTTex에 전달받는 코드이다.
// m_SwapChain : 생성했던 Swapchain, ComPtr<IDXGISwapChain>
// m_RTTex : Render Target Texture, ComPtr<ID3D11Texture2D>
m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)m_RTTex.GetAddressOf());
(2) Render Target View 생성
이 Texture을 Render Target 용도로 사용하기 위해서는 Render Target View를 생성해서, Device Context에 전달해줘야 한다. 아래는 m_RTTex가 들고 있는 텍스쳐로 Render Target View를 생성해서 m_RTView에 전달받는 코드이다.
// m_Device : Device, ComPtr<ID3D11Device>
// m_RTView : Render Target View, ComPtr<ID3D11RenderTargetView>
m_Device->CreateRenderTargetView(m_RTTex.Get(), nullptr, m_RTView.GetAddressOf());
마지막으로 이 Render Target View를 Device Context에 전달해주면 되는데, 이 때 Depth Stencil View도 필요하므로 Depth Stencil View를 먼저 알아보고 마지막에 설정해주도록 하겠다.
Depth Stencil View
Depth Stencil이란 Depth 정보와 Stencil 정보를 담고 있는 텍스쳐이다.
Depth는 깊이 값으로, 여러 물체가 한 픽셀에 겹쳐 있는 경우, 최종적으로 어떤 픽셀 값을 선택할 것인지 결정할 수 있게 해준다. 깊이 값은 0부터 1까지로, 0에 가까울 수록 앞에 있는 픽셀이라고 생각하면 된다. 따라서 픽셀에 여러 물체가 겹쳐있으면 Depth 값이 가장 작은 녀석을 최종적인 픽셀 값으로 선택하게 된다.
Stencil은 masking과 같은 기능을 하는 것으로 생각하면 된다. 렌더링할 때 특정 모양으로 masking을 주고 싶으면 stencil 값을 적절히 설정해서 그 모양을 만들어서 그 모양 안에 있는 픽셀만 렌더링 하도록 설정할 수 있다.
(1) Texture2D 생성
Depth Stencil 용도로 사용할 텍스쳐는 직접 만들어줘야 하므로 CreateTexture2D를 우선 진행한 뒤, Depth Stencil View를 생성하게 된다. 아래 코드는 Texture2D Description을 이용해 Texture2D객체를 생성하여 m_DSTex에 전달받는 코드이다.
D3D11_TEXTURE2D_DESC Desc{};
Desc.Width = (UINT)m_Resolution.x;
Desc.Height = (UINT)m_Resolution.y;
Desc.ArraySize = 1;
Desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; // 깊이 저장 전용 Format) Depth 24, Stencil 8 = 총 32byte
// 텍스쳐 용도 결정. 여러 용도로 사용할 수 있긴 함 (비트 합)
// 근데 조합 수가 매우 적고, 조합 안되는 걸 만들려고 하면 텍스쳐 생성이 실패됨
// BindFlag에 설정한 용도로만 View가 생성됨.
Desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
// CPU 메모리에 옮겨올 수 있는지 여부 (생성 이후)
Desc.Usage = D3D11_USAGE_DEFAULT;
Desc.CPUAccessFlags = false;
// MipMap : 해상도에 따른 텍스쳐 버전 (고해상도/중해상도/저해상도용)
// Miplevel 0번 = 원본, 1번 = 절반 사이즈, 2번 = 1/4 사이즈...
// Miplevel 1로 설정하면 1개만 생성하므로 0번만 만들어짐
Desc.MipLevels = 1;
// Miscellaneous Flag (추가 옵션, 0:사용 안함)
Desc.MiscFlags = 0;
// MultiSampling, Count를 1로 하면 사용하지 않음
Desc.SampleDesc.Count = 1;
Desc.SampleDesc.Quality = 0;
// m_DSTex : Depth Stencil Texture, ComPtr<ID3D11Texture2D>
m_Device->CreateTexture2D(&Desc, nullptr, m_DSTex.GetAddressOf());
DirectX를 사용하다 보면 Description에 값을 설정해서 리소스를 생성하는 경우가 많은 데, 겹치는 요소가 많아서 별도 포스트에서 Description의 옵션에 대해서 정리해보도록 하겠다. 지금은 코드의 주석을 통해 이해해보자.
(2) Depth Stencil View 생성
생성한 Texture2D 객체를 이용해 Depth Stencil View를 생성한다. 아래 코드는 Depth Stencil View를 생성해서 m_DSView에 전달받는 과정이다.
// m_DSView : Depth Stencil View, ComPtr<ID3D11DepthStencilView>
m_Device->CreateDepthStencilView(m_DSTex.Get(), nullptr, m_DSView.GetAddressOf());
Render Target 및 Depth Stencil 설정
Device Context에 Render Target View (포인터의 주소, 이중 포인터)와 Depth Stencil View (포인터)를 전달해서 설정하는 코드이다.
m_Context->OMSetRenderTargets(1, m_RTView.GetAddressOf(), m_DSView.Get());
이렇게 최초 1회 설정하고 나면, 이후 Device Context를 이용해 Render할 때 m_DSTex의 깊이와 스텐실 값을 기반으로 m_RTTex의 텍스쳐에 출력을 하게 된다.
[DirectX] Graphics Pipeline 2 - Vertex Shader & HLSL (0) | 2024.08.25 |
---|---|
[DirectX11] Graphics Pipeline 1 - Input Assembler (0) | 2024.08.24 |
[DirectX11] ComPtr (0) | 2024.08.23 |
[DirectX11] SwapChain (0) | 2024.08.18 |
[DirectX11] Device & Device Context (0) | 2024.08.18 |