이번 글은 DirectX11의 멀티 샘플링에 대한 글입니다.
에일리어싱이란?
아래의 사진은 그냥 그림판에다가 선을 하나 그린 모습입니다.
이를 확대해서 보면은 아래처럼 이렇게 자글자글하게 보이는 것을 확인할 수 있습니다.
이러한 현상을 '에일리어싱(Aliasing)'또는 '계단 현상'이라고합니다.
에일리어싱을 완화하는 기능을 '안티 에일리어싱'이라고 하며 언리얼에서는 당연히 '안티 에일리어싱'기능을 제공합니다.
자세한 글은 https://docs.unrealengine.com/5.2/ko/anti-aliasing-and-upscaling-in-unreal-engine/
위의 공식문서를 참고해주세요!
에일리어싱 발생하는 이유
아래는 제 노트북의 모니터 필셀 수 입니다.
모니터의 픽셀 수가 1920*1080개가 있는데 그림판을 켜서 선을 하나 긋는다고 해도 어쨋든 픽셀 하나하나에 RGB값을 채워야 사용자가 이를 확인할 수 있겠죠?
그래서 그림판에 선을 하나 그리고 확대를 해보면 픽셀이 네모난 형태라 네모난 형태의 픽셀에 색을 하나하나 채워 넣어서 선의 형태로 사용자에게 보여주려고 하다보니 계단 현상이 발생하는 것입니다.
안티 에일리어싱 종류
안티 에일리어싱 기법의 종류로는 크게
'초과 표본화', '다중 표본화'가 있습니다.
'초과 표본화'
는 SuperSampling Anti-Aliasing SSAA라고 하며, 후면 버퍼, 전면 버퍼모두 화면 해상도보다 4배의 크기로 잡고 후면 버퍼에 렌더링 하는 방법입니다. 이를 출력하는 과정에서는 화면 해상도와 동일한 크기로 환원하여 보여줍니다.
일단 느낌적인 느낌으로 4배로 늘려서 늘어난 4개의 픽셀을 계산을 하다 보니까 비용이 비싸겠죵?
'다중 표본화'
는 Mutil Sampling Anti-Aliasing이라고 하며 MSAA라고 합니다.
초과 표본화 처럼 화면해상도의 4뱌인 후면 버퍼, 전면 버퍼를 사용하지만 4배로 늘어난 각 픽셀을 4번다 계산하는게 아니라, 하나의 픽셀을 한번만 계산을 하고 나머지 픽셀을 하나의 픽셀로 치고 평균색상을 구해 픽셀을 채우는 방식입니다.
구현
이를 DX11에서 '장치 초기화'하는 부분에서 구현해보도록 하겠습니다.
보통 장치 초기화를 할때 ID3D11Device, ID3D11DeviceContext를 만들 때 SwapChain도 같이 만들기 때문에 'D3D11CreateDeviceAndSwapChain'함수의 인자에 들어가는 DXGI_SWAP_CHAIN_DESC인자에서
멀티 샘플링의 서브 필셀의 개수를 설정할 수 있습니다.
아래의 ZeroMemory에서 desc.SampleDesc.Cout가 멀티 샘플링 서브 픽셀의 수인데 보통은 4로 설정하지만,
저는 사용하지 않을 것이기 때문에 1로 설정하였습니다.
DXGI_SWAP_CHAIN_DESC desc;
ZeroMemory(&desc, sizeof(desc));
{
desc.BufferDesc.Width = _width; // 800
desc.BufferDesc.Height = _height; // 600
desc.BufferDesc.RefreshRate.Numerator = 60; // 화면 주사율
desc.BufferDesc.RefreshRate.Denominator = 1; // 분모
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
desc.SampleDesc.Count = 1; // 서브 픽셀의 개수
desc.SampleDesc.Quality = 0; // 퀄리티
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = 1; // 후면 버퍼 개수
desc.OutputWindow = _hWnd; // 어떤 윈도우 핸들 설정?
desc.Windowed = true;
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
}
HRESULT hr = ::D3D11CreateDeviceAndSwapChain
(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr, 0,
nullptr, 0,
D3D11_SDK_VERSION,
&desc,
_swapChain.GetAddressOf(),
_device.GetAddressOf(),
nullptr,
_deviceContext.GetAddressOf()
);
감사합니다 :)
참고한 자료
https://lipcoder.tistory.com/22
'컴퓨터 그래픽스 > DirectX' 카테고리의 다른 글
NavMesh 만들기 (2) | 2024.12.07 |
---|---|
[Animation] 애니매이션을 만들어보기 (정리글) (1) | 2024.12.06 |
[Animation] 스키닝 애니매이션이란? (Skinning Animation) (1) | 2024.11.10 |
View Spcae Matrix 만들기 (0) | 2024.07.31 |
[DX] 렌더링 파이프 라인 (2) | 2023.11.30 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!