Anti Aliasing

Date:     Updated:

카테고리:

태그:

Main Reference
- Learn OpenGL
- Rinthel Kwon - OpenGL Lecture


Anti Aliasing

Object After Rasterization
anti_aliasing_rasterization anti_aliasing_rasterization_filled

Graphics Pipeline에서 Rasterize 단계를 거치게 되면 어쩔 수 없이 오브젝트의 테두리 부분이 계단 식으로 표현되게 된다. 이러한 현상을 aliasing 현상이라고 한다. 현재보다 해상도가 많이 떨어지던 시대에는 상당히 거슬리는 현상이었을 것이다. 이러한 계단 현상을 없애기 위해 여러 anti-aliasing 기법이 등장했는데 그 중 하나는 SuperSampling Anti-Aliasing(SSAA) 기법이다. SSAA는 원래 해상도보다 더 큰 해상도로 렌더링을 한 후 이 결과를 interpolation하여 down sampling 하는 방식이다. 어느정도 효과는 있겠지만 너무 비용이 크기 때문에 현재에는 잘 사용하지 않는 기법이다. 이번 포스팅에서는 OpenGL에서 기본으로 제공하며, 기존의 SSAA 기법을 대체하는 MultiSampling Anti-Aliasing(MSAA) 기법에 대해 알아보자.


MSAA

anti_aliasing_sample_points

기존의 Rasterize 기법은 특정 픽셀의 중심 좌표를 기준으로 해당 픽셀이 오브젝트에 포함되는지 아닌지 이진분류를 하는 방식이었다. MultiSampling Anti-Aliasing 기법은 한 픽셀당 하나의 샘플로 테스트하는 것이 아닌 여러 샘플을 통해 테스트 하는 것이다. 또한 0 또는 1로 이진 분류하는 것이 아니라 multi-sampling 결과를 바탕으로 알파값을 조절하여 결과를 내게 된다.


Object After Rasterization
anti_aliasing_rasterization_samples anti_aliasing_rasterization_samples_filled


Example

// Init glfw
glfwInit();
// ...
glfwWindowHint(GLFW_SAMPLES, 4);


// Render()...
glEnable(GL_MULTISAMPLE);
Before MSAA After MSAA
12_aliasing_msaa_before_closeup 12_aliasing_msaa_after_closeup

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();
  // [...]
}



맨 위로 이동하기

OpenGL 카테고리 내 다른 글 보러가기

댓글 남기기