Anti Aliasing
카테고리: OpenGL
태그: Graphics
Main Reference
- Learn OpenGL
- Rinthel Kwon - OpenGL Lecture
Anti Aliasing
Object | After Rasterization |
---|---|
Graphics Pipeline에서 Rasterize 단계를 거치게 되면 어쩔 수 없이 오브젝트의 테두리 부분이 계단 식으로 표현되게 된다. 이러한 현상을 aliasing 현상이라고 한다. 현재보다 해상도가 많이 떨어지던 시대에는 상당히 거슬리는 현상이었을 것이다. 이러한 계단 현상을 없애기 위해 여러 anti-aliasing 기법이 등장했는데 그 중 하나는 SuperSampling Anti-Aliasing(SSAA) 기법이다. SSAA는 원래 해상도보다 더 큰 해상도로 렌더링을 한 후 이 결과를 interpolation하여 down sampling 하는 방식이다. 어느정도 효과는 있겠지만 너무 비용이 크기 때문에 현재에는 잘 사용하지 않는 기법이다. 이번 포스팅에서는 OpenGL에서 기본으로 제공하며, 기존의 SSAA 기법을 대체하는 MultiSampling Anti-Aliasing(MSAA) 기법에 대해 알아보자.
MSAA
기존의 Rasterize 기법은 특정 픽셀의 중심 좌표를 기준으로 해당 픽셀이 오브젝트에 포함되는지 아닌지 이진분류를 하는 방식이었다. MultiSampling Anti-Aliasing 기법은 한 픽셀당 하나의 샘플로 테스트하는 것이 아닌 여러 샘플을 통해 테스트 하는 것이다. 또한 0 또는 1로 이진 분류하는 것이 아니라 multi-sampling 결과를 바탕으로 알파값을 조절하여 결과를 내게 된다.
Object | After Rasterization |
---|---|
Example
// Init glfw
glfwInit();
// ...
glfwWindowHint(GLFW_SAMPLES, 4);
// Render()...
glEnable(GL_MULTISAMPLE);
Before MSAA | After MSAA |
---|---|
MSAA 설정을 키는 것은 간단한데 glfw를 생성한 후 픽셀 당 몇개의 샘플을 사용할지 glfwWindowHint
함수를 통해 지정하고, glEnable(GL_MULTISAMPLE)
로 MSAA를 키면 된다. 사실 까다로운 부분은 일반적인 window 위에서의 렌더링이 아닌 off-screen MSAA이다.
Off-Screen MSAA
일반적으로 off-screen framebuffer에 렌더링을 할 때 target texture를 GL_TEXTURE_2D
로 지정했었다. 하지만 GL_TEXTURE_2D는 MSAA가 불가능하므로 MSAA가 가능한 텍스처 GL_TEXTURE_2D_MULTISAMPLE
로 target texture를 지정해야 한다. 또한 최종 렌더링 화면과의 호환성을 위해 MSAA가 끝난 GL_TEXTURE_2D_MULTISAMPLE
텍스처를 다시 일반 GL_TEXTURE_2D
로 바꿔주는 작업이 필요하다.
// creating texture for render target
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, width, height, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
// attaching texture to framebuffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
unsigned int msFBO = CreateFBOWithMultiSampledAttachments();
// then create another FBO with a normal texture color attachment [...]
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, screenTexture, 0);
// [...]
while(!glfwWindowShouldClose(window)) {
// [...]
glBindFramebuffer(msFBO);
ClearFrameBuffer();
DrawScene();
// now resolve multisampled buffer(s) into intermediate FBO
glBindFramebuffer(GL_READ_FRAMEBUFFER, msFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO);
glBlitFramebuffer(0, 0, width, height,
0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// now scene is stored in 2D texture, use that for post-processing
glBindFramebuffer(GL_FRAMEBUFFER, 0);
ClearFramebuffer();
glBindTexture(GL_TEXTURE_2D, screenTexture);
DrawPostProcessingQuad();
// [...]
}
댓글 남기기