1.17 멀티 샘플 앤티앨리어싱(MSAA)
우리는 샘플링을 통해 세상을 인지합니다. 예를 들어, 우리의 눈은 30~60Hz 사이의 프레임 속도로 샘플링합니다. 샘플링 속도가 불충분하면 불쾌한 아티팩트가 발생할 수 있습니다. 컴퓨터 그래픽에서는 샘플링 제한을 관리하는 것이 끊임없는 도전입니다.
플레이그라운드 실행 - 1_17_msaa일반적인 문제는 특히 래스터화 과정에서 이미지 해상도와 관련이 있습니다. 이전에 이 과정을 벽돌(픽셀)을 놓아 삼각형 영역을 덮는 것에 비유했습니다. 삼각형 가장자리를 확대하면 상황은 다음과 같이 설명할 수 있습니다:
래스터화 중에는 픽셀이 삼각형 내부에 있는지 외부에 있는지 판단하기 위한 휴리스틱이 필요합니다. 간단한 접근 방식은 픽셀의 중심을 확인하는 것입니다. 위 예시에서는 오직 하나의 픽셀 중심만이 삼각형 내부에 완전히 있습니다. 가장자리를 가로지르는 두 픽셀의 경우, 삼각형과 넓은 영역이 겹쳐도 중심이 외부에 있으므로 완전히 외부에 있는 것으로 간주됩니다. 이러한 픽셀에 대한 더 합리적인 색상 지정 전략은 겹치는 비율에 따라 삼각형의 색상과 배경 색상을 혼합하는 것일 수 있습니다.
이러한 종류의 아티팩트는 앨리어싱이라고 불리며, 낮은 출력 해상도에서 더 두드러집니다. 불충분한 샘플링 속도는 다른 이상한 아티팩트를 유발할 수도 있습니다. 예를 들어, 우리 예시에서 픽셀은 정사각형으로 모델링되지만, 색상은 오로지 그 중심에 의해 결정됩니다. 만약 픽셀보다 작은 구조가 있다면, 전체 픽셀은 그 작은 구조에서 중심점이 샘플링하는 것에 따라 색이 지정될 것입니다. 더 합리적인 접근 방식은 작은 구조의 색상을 평균화하는 것입니다.
다행히도, 물리적으로 모니터를 업그레이드하지 않고도 샘플링 품질을 향상시키는 방법이 있습니다. 우리는 이 문제를 해결하기 위해 앤티앨리어싱이라고 통칭되는 일련의 알고리즘을 사용합니다. 예를 들어, 앤티앨리어싱은 각 글리프가 매우 작고 해상도가 제한적일 때에도 텍스트 렌더링 품질을 향상시키기 위해 일반적으로 적용됩니다.
이 튜토리얼에서는 멀티 샘플 앤티앨리어싱(MSAA)으로 알려진 기본 앤티앨리어싱 방법을 소개하겠습니다. MSAA의 개념은 간단합니다: 먼저 각 픽셀에 대해 네 개의 샘플로 결과를 렌더링합니다. 그런 다음, 이 네 개의 샘플을 픽셀당 평균화하여 이미지를 원하는 크기로 축소합니다. 이 평균화는 배경과 삼각형의 겹치는 영역을 기반으로 혼합된 색상을 만드는 우리의 전략을 구현합니다. 실제 겹침 비율을 계산하는 비용이 많이 드는 작업을 더 많은 샘플을 단순히 검사하는 것으로 피할 수 있습니다.
MSAA는 WebGPU API의 내장 기능이므로, 몇 가지 추가 구성만으로 구현이 간단합니다. 이를 달성하는 방법을 살펴보겠습니다.
먼저, 멀티 샘플 텍스처를 생성합니다:
const msaaTexture = device.createTexture({
size: [canvas.width, canvas.height],
sampleCount: 4,
format: navigator.gpu.getPreferredCanvasFormat(),
usage: GPUTextureUsage.RENDER_ATTACHMENT,
});
또한 멀티 샘플링을 지원하도록 깊이 텍스처를 업데이트해야 합니다:
const depthTextureDesc = {
size: [canvas.width, canvas.height, 1],
sampleCount: 4,
dimension: '2d',
format: 'depth24plus-stencil8',
usage: GPUTextureUsage.RENDER_ATTACHMENT
};
두 경우 모두, `sampleCount` 속성을 4로 설정하여 픽셀당 네 개의 샘플을 원함을 나타냅니다. `format` 및 `usage` 속성은 MSAA가 아닌 구성과 동일하게 유지됩니다.
MSAA는 셰이더에 투명하게 작동하므로 셰이더를 수정할 필요가 없다는 점은 주목할 가치가 있습니다. 주요 변경 사항은 렌더링 대상을 정의할 때 발생합니다.
다음으로, 색상 첨부 파일 구성을 업데이트합니다:
let colorAttachment = {
view: view,
resolveTarget: colorTextureView,
clearValue: { r: 1, g: 0, b: 0, a: 1 },
loadOp: 'clear',
storeOp: 'store'
};
이 구성에서 두 가지 렌더링 대상을 지정합니다:
`view` 속성은 이제 멀티 샘플 텍스처(`msaaTexture.createView()`)를 가리킵니다.
새로운 `resolveTarget` 속성을 도입했으며, 이는 실제 캔버스 텍스처 뷰(`colorTextureView`)를 가리킵니다. 최종, 해상된 출력이 여기에 저장됩니다.
렌더링 프로세스는 이제 두 단계로 진행됩니다:
장면은 먼저 멀티 샘플 텍스처(`msaaTexture`)에 렌더링됩니다.
결과는 자동으로 해상(평균화)되어 `resolveTarget`으로 출력됩니다.
이 두 단계 프로세스는 우리가 수행한 구성 변경 외에 추가 코드 없이 투명하게 진행됩니다.
MSAA의 효과를 설명하기 위해, MSAA를 활성화하기 전과 후의 렌더링된 장면을 확대하여 비교할 수 있습니다. MSAA가 활성화된 버전에서는 가장자리가 더 부드러워지고 앨리어싱 아티팩트가 줄어들어 그 차이가 눈에 띄게 나타날 것입니다.