Quick Comparison
| 방식 | 핵심 | 장점 | 단점 |
|---|---|---|---|
| MSAA | 픽셀 안 여러 coverage sample | 기하 경계에 강함 | shader aliasing에는 약함 |
| FXAA | 최종 이미지 edge를 흐리게 처리 | 싸고 적용 쉬움 | 전체가 흐려질 수 있음 |
| TAA | 시간 축 샘플 누적 | subpixel aliasing에 강함 | ghosting, blur 위험 |
| SSAA | 더 높은 해상도로 렌더 후 축소 | 품질 좋음 | 매우 비쌈 |
MSAA: multisampled color/depth attachment -> resolve -> post-process
TAA: projection jitter + motion vector + depth -> history reprojection -> blend/reject구조
앨리어싱은 연속적인 신호를 제한된 샘플로 표현할 때 생깁니다. 그래픽스에서는 삼각형 경계, 얇은 선, 고주파 텍스처, specular highlight, subpixel 움직임에서 계단이나 반짝임으로 보입니다.
샘플 수 부족
-> 실제 경계와 픽셀 격자가 어긋남
-> jagged edge, shimmeringMSAA는 픽셀 안의 여러 위치에서 coverage를 검사해 경계 품질을 개선합니다. 하지만 fragment shader가 한 번만 실행되는 방식에서는 shader 내부의 고주파 aliasing까지 해결하지 못할 수 있습니다.
FXAA는 최종 이미지에서 edge처럼 보이는 부분을 찾아 후처리로 부드럽게 만듭니다. geometry나 shader 정보를 다시 쓰지 않아 적용은 쉽지만, 글자나 얇은 디테일까지 함께 흐려질 수 있습니다.
SSAA는 더 큰 해상도로 장면을 렌더링한 뒤 축소합니다. 품질은 직관적으로 좋지만, shading과 bandwidth 비용이 해상도 배수만큼 커져 실시간 렌더링에서는 제한적으로 씁니다.
텍스처가 멀리서 반짝이는 문제는 AA만으로 해결되지 않을 수 있습니다. mipmap, anisotropic filtering, specular anti-aliasing처럼 신호 자체의 고주파를 낮추는 처리가 함께 필요합니다.
시간 축 누적
TAA는 매 프레임 카메라 projection을 조금 흔들어 다른 샘플을 얻고, 이전 프레임 결과를 현재 프레임과 합칩니다. 정지 화면에서는 샘플 수가 늘어난 효과가 있지만, 움직임이 있으면 history rejection이 중요해집니다.
TAA의 history는 현재 pixel 위치가 아니라 motion vector로 되돌린 이전 위치에서 읽습니다. depth, normal, material 변화나 camera cut가 있으면 이전 결과를 줄이거나 버려야 합니다. 이 reset 규칙이 없으면 이전 물체 색이 남는 ghosting이 생깁니다.
선택 기준
| 상황 | 먼저 볼 방식 |
|---|---|
| 삼각형 경계 계단 | MSAA |
| 저비용 후처리 필요 | FXAA |
| subpixel shimmer가 심함 | TAA |
| 최고 품질 오프라인/캡처 | SSAA |
| 투명 texture edge | alpha coverage, alpha test 정책 |
| 텍스처가 멀리서 반짝임 | mipmap, anisotropic filtering |
앨리어싱은 한 가지 방식으로 모두 해결되지 않습니다. 기하 경계, 텍스처, shader highlight, 시간 축 움직임이 각각 다른 원인을 가질 수 있습니다.
주의할 점
TAA는 품질이 좋지만 이전 프레임을 섞기 때문에 ghosting과 blur가 생길 수 있습니다. motion vector, depth, reactive mask 같은 보조 정보가 없으면 빠른 움직임에서 실패하기 쉽습니다.
MSAA도 공짜가 아닙니다. sample count가 늘면 depth/color 저장과 resolve 비용이 증가합니다.
MSAA attachment의 sample count는 depth attachment와 render pass 설정에 맞아야 하며, shader가 일반 single-sample texture를 읽어야 하는 다음 pass 앞에서는 resolve가 필요합니다. 반대로 sample별 데이터를 실제로 읽을 이유가 없으면 sample count만 올려 bandwidth를 낭비하지 않습니다.
참고 링크
1 sources