프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.

Bloom Effect

프로그래밍 2012. 5. 27. 08:21
Posted by cagetu

안녕하세요. 프로그래머 cagetu입니다. 


오늘은 Bloom 효과에 대해서 이야기해볼 생각입니다. 특별히 제가 설명하지 않아도 다들 무엇인지 아실정도로 너무나 잘 알려져 있고, 이미 많은 게임에서 사용하고 있는 기술입니다. 일명 뽀샤시 효과라고 하지요?! ㅎㅎ


(이미지 출처: http://photohistory.tistory.com/2322)

이처럼 보편적인 내용을 제가 또 다루어보는 이유는 저도 만들어보면서 참 어려웠기 때문입니다. 이 기술을 적용했을 때 뭔가 이렇게 환상적으로 좋아지는 결과를 생각하지만, 실제로 구현을 해보면 의외로 원하는 결과를 얻는 것이 생각보다 쉽지 않았습니다. 

그래서 오늘은 Bloom 효과가 어떤 것인지에 대해서 알아보고, 게임에서 Bloom을 어떻게 하면 좋게 만들 수 있을지에 대해서 제가 고민하면서 이런 저런 자료를 통해서 알게된 내용을 한번 정리해서 이야기 해볼까 합니다. 그렇다고 제가 이렇게 하면 완벽한 Bloom을 만들 수 있어요! 라고 이야기하는 건 아닙니다. 그걸 알면 저에게 알려주세요~. ^^

(분량 관계로 자세한 설명에 대해서는 관련 자료를 링크해서 설명하도록 하겠습니다.)


그렇다면 Bloom 효과란 무엇일까요?


카메라 렌즈에 빛이 들어올 때 카메라가 100% 정확히 그 빛의 정보를 담아내지 못하기 때문에, 태양과 같이 강렬한 빛을 찍으면 실제로 보이는 빛보다 더 큰 면적으로 찍히게 됩니다. 이런 현상은 마치 빛이 퍼져보이는 것과 같은 효과를 나타냅니다. 이것을 흉내내서 처리하는 것을 우리는 Bloom 효과라고 합니다. 

Bloom 효과의 정의는 다음과 같습니다. 보신 바와 같이 "강한 빛을 찍으면 실제로 보이는 빛보다 더 큰 몇적으로 찍히게 됩니다" 가 가장 큰 포인트입니다. 따라서, 위에서 언급한 Bloom의 성질에 의하면, 사실 위에서 처럼 강제로 뭉개서 뽀샤시 하게 만든 것은 실제로 Bloom의 성질과는 맞지 않습니다 (물론, 설정에 따라서 만들어 내지 못하는 것은 아닙니다만...). 즉, Bloom 효과와 뽀샤시 효과를 같은 것이 아니라는 이야기입니다. 우리가 만들려고 하는 것은 강한 빛을 받는 부분이 번지는 것이지 화면이 전체적으로 뽀샤시해지는 것이 아니라는 것을 정확히 해야 합니다!


그렇다면 게임에서 Bloom을 만들려면 어떻게 해야 할까요? 


가장 먼저 Bloom하면 빼놓을 수 없는 것이 HDR(High Dynamic Range)이기 때문에 HDR을 이야기 하지 않을수가 없습니다. 하지만, HDR이란 주제가 너무 방대하기 때문에, 여기서는 제가 이전에 발표했던 자료로 대체하도록 하겠습니다.
(알콜코더님의 발표자료도 함께 보시면 좋아요: http://gamedevforever.com/168)

게임 그래픽 특히 포스트 프로세싱이 본격적으로 사용되고 있는 현 시점에서 HDR은 굉장히 큰 의미를 가지고 있습니다. 

Bloom 이라는 효과의 기본 또한 HDR입니다 입니다. 물론 HDR을 사용하지 않다고 하더라도 Bloom 효과 자체는 표현이 가능합니다. 그래서, 우리는 구현 방식에 따라서, HDR Bloom과 LDR Bloom (유사 HDR)로 구분해서 사용을 하기도 합니다. 모든 Bloom 파이프라인을 Float Buffer에서 처리하는 방식을 HDR Bloom이라고 하고, HDR 장면을 LDR로 변경시킨 후 Bloom 파이프라인을 처리하는 것을 LDR Bloom 이라고 합니다. 


[HDR Bloom 과 LDR Bloom "HDR In Valve's Source Engine" Siggraph 2006]


그럼 간단하게 Bloom 효과를 만들어 내는 방법을 알아보도록 하겠습니다. 

  1. 렌더타겟에 장면을 렌더링 한다.
  2. 렌더타겟에  렌더링된 장면에서 밝은 부분을 추출해서 렌더링한다.
  3. 추출해낸 밝은 부분을 가진 렌더타겟을 블러시킨다.
  4. 렌더링된 장면 렌더타겟과 블러된 렌더타겟과 합성한다.
굉장히 간단하죠?! 사실 이게 전부입니다. 하지만, 이렇게 간단한데 이상하게 구현을 해보면 원했던 결과를 얻기가 쉽지 않았습니다. 그래서 과연 무엇을 놓치고 있는가? 어떻게 하면 좀 도 좋아 보이게 만들 수 있을까? 아니, 다른 게임들처럼 좋은 Bloom 효과를 만들 수 있을까? 에 대한 고민을 하게 되었습니다.

그럼 여기서 좀 더 나은 Bloom을 만들기 위한 방법들을 한번 알아보도록 하겠습니다.


* 밝은 부분을 추출하자!

블룸 현상은 강렬한 빛이 찍혔을 때 나오는 현상이기 때문에 실제로 렌더링된 장면에서도 이런 특성에 맞추어서 밝은 영역을 잘 추출해내는 것 가장 중요한 문제입니다. 하지만, Bloom을 처리할 때 부딪히는 문제 중에 하나가 바로 여기에 있습니다. 


실제 화상에서는 어지간히 강한 빛이 아니면 큰 번짐 효과가 나오지 않습니다. 이와 마찬가지로 HDR 렌더링이라고 하더라도 장면의 밝은 영역의 대역이 너무 낮은 영역에 포진되어 있다고 하면, 원하는 밝은 부분을 추출하기가 쉽지 않습니다. 그런 이유로 위와 같은 디퓨즈 영역까지 블룸이 적용되는 원하지 않는 결과가 발생하게 됩니다. 물론, 의도적으로 이렇게 뽀샤시한 느낌을 주기 위해서 낮은 영역을 포함하기도 합니다. 


[밝은 영역 추출하기]

이처럼 밝고 어두운 부분의 영역이 충분하지 않다면, 전체적으로 어두어야 할 부분도 번져버리는 결과가 나타나게 됩니다. 이렇게 올바르지 않은 밝은 영역을 찾는 것을 줄이기 위해서는 방법은 무엇이 있을까요?


- Bloom Curve

물리적으로 올바른 방법은 아니지만, Bloom에 의해 불필요하기 밝아지게 되는 부분을 줄이기 위해서 Bloom Curve를 적용하여 밝은 부분과 어두운 부분의 영역을 보장시킨다. 이는 Bloom을 적용하기 전에 HDR buffer에 curve를 적용해준다.

 
[Halo3 사례 Gamefest "HDR The BUNGIE Way"]


- Physically Based Lighting

물리적으로 올바르게 밝은 영역의 대역대는 높게 렌더링 하는 방법입니다. 즉, 재질의 specular 부분의 에너지를 높게 적용하도록 라이팅 모델을 적용하는 것입니다. 자세한 설명은 나중에 다시 한번 하기로, 아니... 그냥 이 문서를 보시면 될 것 같습니다. 
(http://simonstechblog.blogspot.com/2011/12/microfacet-brdf.html)


[Siggraph2010 "Physically Motivated Shading Models for Game Development"] 


* 좀 더 높은 퀄리티의 블러 만들기

우리는 Bloom 효과를 만들기 위해서, Bloom 이미지를 부드럽게 블러시키기 위해서 Gaussian Blur를 사용합니다. 하지만, Gaussian Blur는 커다란 블러 반경에다가 부드럽게 블러를 먹이려고 한다면, 부하가 높아서 리얼타임으로 사용하기가 어렵습니다. 그렇기 때문에 보통 Bloom 이미지를 다운스케일해서 블러시키면 좀 더 넓은 영역을 블러 시킬 수 있기 때문에 많이 사용하지만, 이럴 경우 퀄리티가 많이 훼손되게 됩니다. 이런 퀄리티를 높이기 위해서는 어떻게 해야 할까요? 


- Multiple Gaussian Filter

Masaki Kawase 씨가 발표하신 내용으로 좀 더 저렴한 비용으로 높을 퀄리티를 내기 위해서 소개한 방법입니다. 자세한 설명은 이 페이지를 참고하시면 좋을 듯 합니다(http://allosha.tistory.com/50). 


[GDC2004 "Practical Implementation of High Dynamic Range Rendering"]

이 기법은 이후 다른 게임들에도 많이 사용되었는데, Halo3의 구현 사례를 보도록 하겠습니다.

Halo의 경우도, 유사하게 단계적으로 블룸 이미지를 다운스케일하여 그 이미지들을 블러시켜서 합성해주는 방법을 사용합니다. 이렇게 하면 일반적으로 Bloom 샘플에서 보여지는 한장의 다운스케일 이미지를 이용해서 Bloom을 처리하는 방식보다 높은 퀄리티로 넓은 범위를 블러시키는데 도움을 줍니다.


- Flickering Artifact

저렴한 비용으로 넓은 범위를 블러시키기 위해서 다운스케일을 많이시키다보면 가우시안 블러를 적용해야 할  블룸 이미지의 픽셀 수가 부족하게 되기 때문에 카메라를 이동함에 따라서, 부족한 픽셀 때문에 블러가 적용되는 범위가 굉장히 영향을 많이 받게 됩니다. 이런 현상은 결과적으로 블러되는 부분이 깜빡 깜빡하게 되는 문제가 발생하게 됩니다. 


이를 해결하기 위해서는 다운스케일 할 때,  좀 더 넓은 범위의 픽셀들의 평균으로 내 픽셀의 값을 만들어내면 이렇게 이동에 따른 깜빡거리는 현상을 조금을 줄일 수 있게 됩니다. 하지만, 그렇다고 하더라도 기본적으로는 너무 많은 다운스케일을 하여 픽셀 수가 너무 많이 부족하게 되면 문제가 발생할 수 있기 때문에, 적절히 가우시안 블러의 범위와 다운스케일 사이즈를 결정하는 것이 중요합니다. 


* 결론

실제로 Bloom 효과가 렌더링 퀄리티에 미치는 영향은 꽤 큽니다. 그러니, HDR + Bloom의 퀄리티는 전체 화면의 품질을 결정짓는 가장 기본이라고 볼 수 있을 것입니다. 그런 이유로, 지금까지 Bloom 효과를 만들어 낼 때에 고민해봐야 할 것을을 한번 다루어 보았습니다. 우리가 많이 사용하고 있는 Bloom 효과이지만, 의외로 생각할게 많지요? 

저도 Bloom을 놓고 고민했을 때, 의외로 정리된 자료가 없고, 원하는 퀄리티가 나오지 않아서, 참 괴로워했습니다(물론, 아직도 원하는 퀄리티를 만들어내지는 못했습니다.. ㅜㅜ). 그래서, 제가 나름 공부하면서 이런 저런 자료들을 보고 적용해본 내용들을 한번 정리해 보았습니다.

어쩌면 저 같이 Bloom 효과에 대해서 많은 고민을 하셨던 분들이 있다면 그 분들에게 제가 고민했던 이런 내용들이 조금이나마 도움이 되었으면 좋겠습니다. ㅎㅎ. (혹시 좋은 결과가 나오시면, 저한테도 그 사례를 공유해주시면 감사하겠습니다. ㅎㅎ)


그럼 이만~ 안뇽~ 우리 딸이랑 놀러 갈게요~ 헤헤~

댓글을 달아 주세요

  1. Favicon of https://gamedevforever.com 대마왕J 2012.05.13 00:43 신고  댓글주소  수정/삭제  댓글쓰기

    HDR 하고 연계해서 설명하셔야겠네요?

  2. Favicon of https://gamedevforever.com ozlael 2012.05.17 00:03 신고  댓글주소  수정/삭제  댓글쓰기

    아이유출연시켜줘요!

  3. Favicon of https://gamedevforever.com 디퍼드H 2012.05.17 13:45 신고  댓글주소  수정/삭제  댓글쓰기

    기대할게요~! HDR + 뽀샤시 효과 저의 이번 학교 게임 프로젝트에 넣을겁니다 자세히 설명 부탁드려요!

  4. Favicon of https://gamedevforever.com cagetu 2012.05.17 15:22 신고  댓글주소  수정/삭제  댓글쓰기

    큰일이네.. 자세히 설명 안 할건데.. 흐규~ 흐규~ ㅡㅡ;;

    • Favicon of https://gamedevforever.com 디퍼드H 2012.05.17 16:12 신고  댓글주소  수정/삭제

      제가 HDR을 구현해보니 생각보다 Bloom effect가 제가 원하는데로 나오지 않더군요 뭐 만족스럽게는 나왔지만 원가 환상적이지 않던데 기대할거예요! 부담감을 크게 드림!

  5. Favicon of https://gamedevforever.com 친절한티스 2012.05.17 22:39 신고  댓글주소  수정/삭제  댓글쓰기

    이 포스트만 믿고 나도 블룸 적용 해봐야지

  6. Favicon of https://gamedevforever.com 끼로 2012.05.17 22:41 신고  댓글주소  수정/삭제  댓글쓰기

    저도 이 포스트 믿고 우리게임에 블룸 수정하자고 할꺼임..

  7. Favicon of https://gamedevforever.com 대마왕J 2012.05.18 01:09 신고  댓글주소  수정/삭제  댓글쓰기

    나도 이 포스트를 회사에 다 뿌려 버릴 것임.

  8. Favicon of https://gamedevforever.com 디퍼드H 2012.05.18 07:16 신고  댓글주소  수정/삭제  댓글쓰기

    엄..청난 댓글(부담이다)!!

  9. Favicon of https://gamedevforever.com cagetu 2012.05.20 01:06 신고  댓글주소  수정/삭제  댓글쓰기

    고급 엔진 사용자님들이 왜들 이러시지??

  10. Favicon of https://gamedevforever.com 김포프 2012.05.20 08:02 신고  댓글주소  수정/삭제  댓글쓰기

    저도 다음에 만들 엔진에 넣겠습니다..... -_-

  11. Favicon of https://gamedevforever.com denoil 2012.05.21 11:23 신고  댓글주소  수정/삭제  댓글쓰기

    헉 샘슨코어라면 쥬센사요, 레플리카 만드신분!!

  12. Favicon of http://blog.naver.com/sorkelf 풍풍풍 2012.05.28 23:43  댓글주소  수정/삭제  댓글쓰기

    여기 동네 무서움..ㅠ

  13. eppengine 2012.05.30 23:53  댓글주소  수정/삭제  댓글쓰기

    위에 링크에서 처럼 1/32 까지 내려간후 적절히(?) 가중치 * bilinear filter 로 다시 맨 위(최종사이즈) 까지 올라가면서 합성해주면 제법 볼만했던 기억이 납니다만....

    내려가면서 pass 추가 맨 마지막 사이즈에서야 down sampling 하면서 블러까지 해주면 된다지만..

    다시 올라가면서 기존 준비했던 사이즈들을 한벌 더 준비해서 bilinear up sampling .....

    비용이 생각보다 크더라구요.. 그래서 디폴트는 그냥 한벌만 가지고 하고있는데,

    혹 더 좋은 아이디어 없을까요? 1/4 두벌, 1/8 두벌, 1/16 두벌, 1/32 한벌.... 내려가면서 down sampling.... 올라가면서 더하면서 또 Pass 추가.. 렌더링 이 많아지니 다들 이렇게 하시는건지..

    • Favicon of https://gamedevforever.com cagetu 2012.05.31 09:34 신고  댓글주소  수정/삭제

      저는 한장으로 하다가 도저히 답이 안나와서 이런 저런 리서치 결과 여러장을 섞는 방식으로 가는 것이 맞지 않나 생각이 들더라구요.

      퀄리티 차이는 좀 나는 듯 한데, 그만큼 비용은 드는 듯 하구요.

      저도 좀 더 해봐야 할 것 같아요.

      어차피 해상도와 샘플링 수의 싸움이지 않을까요??

      Direct11 예제들을 보니까 컴퓨트 셰이더네서 가우시안 블러를 상수시간에 해버리던데, 이런거 이용하면 짱 도움이 많이 될거 같기도...

      암튼, 그렇습니다. 쿨럭~ 저도 정확한 답은 가지고 있지 않네요. ㅎㅎ