Computer Graphics/OpenGL

OpenGL 정리 - 26. HDR, Bloom

surkim 2024. 11. 10. 12:06

1. HDR과 Bloom

1.1 HDR이란?

HDR(High Dynamic Range)은 더 넓은 밝기와 색상 범위를 표현해 현실감을 높이는 기술이다. 보통 그래픽에서는 색상값이 0.0에서 1.0 사이로 제한되는데, 이를 벗어나는 값들은 자동으로 잘려나가 밝은 장면에서도 빛의 강도를 제대로 표현하지 못한다. 이 제한을 넘어서려면 HDR을 사용해야 하고, 이를 통해 더 현실적인 조명을 표현할 수 있다.

1.2 빛의 제한을 넘는 방법

단순히 조명의 강도를 낮춰서 1.0을 넘지 않도록 설정하는 방식도 있지만, 이렇게 하면 원래 빛의 느낌이 사라지고, 장면이 밋밋해진다. 현실적인 표현을 위해서는 빛의 강도를 일단 1.0 이상으로 허용한 다음 나중에 이를 0.0 ~ 1.0 사이로 다시 조정하는 게 낫다. 이렇게 하면 강한 조명과 빛 반사가 잘 표현되어 빛이 실제로 퍼져나가는 듯한 효과를 준다. 자연스러운 밝기와 빛을 표현하려면 이런 접근이 필수다.

1.3 HDR 이미지와 Tone Mapping

HDR 이미지에서는 서로 다른 노출값을 가진 여러 이미지를 합쳐 밝고 어두운 영역이 동시에 잘 표현되도록 한다. 게임에서도 HDR을 사용해 밝기 범위를 넓게 설정하고, Tone Mapping을 통해 화면에 맞는 적절한 밝기로 조정한다. 이 과정은 인간의 눈이 자동으로 밝기에 적응하는 방식과도 비슷해, 훨씬 더 자연스러운 화면을 만들 수 있다.

1.4 Floating Point Framebuffer

일반적인 GPU는 색상값을 0.0 ~ 1.0 범위로 제한하지만, Floating Point Framebuffer를 사용하면 1.0 이상의 밝기 값도 손실 없이 저장할 수 있다. 이를 통해 HDR 표현에 필요한 넓은 밝기와 색상을 지원할 수 있게 된다.

  • 설정 예제:
      glBindTexture(GL_TEXTURE_2D, colorBuffer);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
    이처럼 GL_RGBA16FGL_RGBA32F와 같은 포맷을 사용해 색상값의 상한을 늘려주면, 1.0 이상의 값도 잘리지 않고 처리할 수 있다.

1.5 Tone Mapping

Tone Mapping은 HDR로 렌더링된 장면을 화면에 맞게 밝기를 조정하는 과정이다. 이를 통해 최종 화면에 어울리는 밝기와 대비가 조정되며, Tone Mapping에는 여러 방식이 있다.

  • Reinhard Tone Mapping: 밝은 영역과 어두운 영역을 부드럽게 조화시켜 자동으로 적절한 밝기를 조정한다.
  • Exposure Tone Mapping: 특정 노출값을 설정해 조명의 강도를 수동으로 조정하며, 사용자가 원하는 밝기 수준을 맞추기에 적합하다.

2. Bloom

Bloom은 장면에서 강한 빛이 번져 은은하게 퍼져 보이도록 하는 후처리 효과로, 빛나는 물체가 주변으로 빛을 퍼뜨리는 느낌을 준다. 이렇게 하면 장면의 밝은 부분이 자연스럽게 강조되고, 빛의 시각적 효과가 훨씬 더 사실적으로 표현된다.

2.1 Bloom의 기본 원리

Bloom은 밝기가 1.0을 넘는 부분을 따로 추출한 후, 그 부분을 블러링 처리하여 원래 장면에 더하는 방식이다. 이 과정을 통해 강한 조명이 번져나가며 퍼지는 듯한 효과를 만들어낼 수 있다.

2.2 밝은 영역 추출과 Multiple Render Target

Bloom 효과를 위해서는 장면에서 밝은 부분만을 따로 분리해야 한다. 이를 위해 Multiple Render Target(MRT)을 사용해 동일한 장면을 여러 텍스처에 렌더링하며, 특정 텍스처에서만 밝은 영역을 따로 추출할 수 있다. Fragment Shader에서 두 개의 out 변수를 설정하고 glDrawBuffers로 두 개의 컬러 어태치먼트를 활성화해 각각의 텍스처에 기본 장면과 밝은 영역을 분리해 렌더링한다.

  • Fragment Shader 예제:
layout(location = 0) out vec4 colorOutput; 
layout(location = 1) out vec4 brightOutput; 

void main() 
{ 
    colorOutput = ...; // 기본 장면
    brightOutput = ...; // 밝은 영역만 추출 
}

2.3 Gaussian Blur와 Two-pass Blur

Bloom 효과에서 추출한 밝은 영역은 Gaussian Blur를 통해 부드럽게 번져 보이도록 한다. Gaussian Blur는 주변 픽셀을 평균화하여 빛이 부드럽게 퍼지는 효과를 만들어낸다. 모든 픽셀에 대해 연산을 수행하면 상당한 연산량이 요구되므로, Two-pass Gaussian Blur 기법을 사용해 성능을 개선한다.

  • Two-pass Gaussian Blur: Gaussian Blur의 대칭 구조를 활용해 X축과 Y축을 나눠 두 번에 걸쳐 연산을 수행하면, 동일한 효과를 얻으면서도 연산량이 줄어들어 성능이 향상된다.

3. HDR과 Bloom 적용 과정

  1. HDR 설정: Floating Point Framebuffer를 통해 높은 밝기와 색상 범위를 처리할 수 있도록 설정한다.
  2. Tone Mapping: HDR로 렌더링된 장면을 Tone Mapping으로 0 ~ 1 범위로 조정해 화면에 적합한 밝기로 나타낸다.
  3. Bloom 적용:
    • 장면에서 밝은 영역을 추출하여 Gaussian Blur로 블러링 처리한다.
    • 블러링된 결과와 원본 장면을 합쳐 빛이 퍼져 나오는 듯한 효과를 완성한다.

4. 결론

HDR과 Bloom은 그래픽스에서 더 자연스럽고 사실적인 조명과 빛 표현을 가능하게 해주는 핵심 기법이다. HDR을 통해 넓은 색상 범위를 표현하여 빛이 잘리지 않도록 하고, Tone Mapping을 통해 화면에 맞는 밝기로 조정한다. Bloom은 강한 빛이 은은하게 퍼져나가는 느낌을 더해, 화면이 실제 빛을 받는 듯한 느낌을 만들어낸다.

이 두 기법을 적절히 조합하면, 화면에 햇빛, 반사된 빛, 강한 조명 효과 등을 사실적으로 구현해 몰입감을 높일 수 있다.