본문 바로가기

Graphics , Rendering

선형의 중요성 (The Importance of being Linear)

원문 :  https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch24.html 


24fig01.jpg

제대로 된 감마 보정의 효과(Benefit)




24.2.2 무엇이 선형(Linear)인가?

수학적 관점에서, 선형변환은 입력(input) 과 출력(output) 사이의 관계가 아래와 같은 것을 의미한다:


  • 입력값의 합계의 출력은 각각 개별적인 입력값의 모든 출력값의 합계와 같다. 즉, f (x + y) = f (x) + f (y) 이다.
  • 출력값은 입력값과 같은 factor인 스칼라 k에 의해 스케일된다.  f(k x x) = k x f (x).

빛의 이동(Transport)는 선형적이다. 하나의 장면에서 두 개의 광원으로부터 오는 일루미네이션 기여(Illumination Contribution) 은 모두 더해져 합산될 것이다. 그 두 개의 값이 곱해지거나 뺄셈이 되거나, 애매한 방식으로 서로 간섭하지는 않을 것이다.


모니터는 비선형이고, 렌더러는 선형이다.

CRT 모니터는 전압을 빛의 강도로 변환할 때 선형적으로 동작하지 않는다. 그리고 LCD는 태생적으로 이런 속성이 없지만, 대체로 CRT의 반응을 흉내내도록 만들어졌다.

모니터의 응답은 아래 그림과 같은 지수 함수 곡선에 더 가깝고, 이 지수는 감마(Gamma)라고 불리운다. 일반적으로 2.2의 감마값은 50% 강도로 빛나는 픽셀이 100% 강도로 빛나는 픽셀의 절반이 아닌, 4분의 1보다도 적은 빛을 방출한다는 의미이다! 감마는 개개의 디스플레이마다 그 값이 다르지만 일반적으로 2.0에서 2.4 사이의 값이다. 이렇게 비선형적인 특성의 영향을 조정하는 것을 감마 보정(Gamma Correction) 이라고 한다.

24fig02.jpg

모니터의 일반적인 응답 곡선


지수값에 상관 없이 검정(0) 과 흰색(1) 이 항상 같은 것에 주목하자. 왜곡되거나 보정될 값은 중간 색깔 값들이다.

렌더러, 셰이더나 인쇄기들은 선형 데이터로 작동되는 것을 좋아한다. 그들은 여러 개의 광원의 기여(Contributions) 를 합산하고, 이들을 반사율로 곱한다. 이 반사율은 상수값이거나 디퓨즈 반사율을 표현하는 텍스처로부터 룩업된 것이다. 그러나 여기에는 숨겨진 가정이 있다 - 표면의 반사율을 나타내는 텍스처 맵도 선형 스케일을 가진다는 가정이다. 또는, 디스플레이 위에서 관찰자가 보게 될 빛의 강도는 렌더러가 프레임 버퍼에 저장한 값들에 당연히 비례할 것이라는 가정이다.

요점은, 비선형적인 입력값이 있을 경우, 렌더러나 섀이더, 인쇄기는 "잘못된 연산"을 하게 될 것이라는 것이다. 이것은 사실적인 결과물을 얻는 데 장애물이 될 것이다.

디지털 페인팅을 생각해보자. 만약 당신이 디지털 페인팅을 하는 동안 "올바른 감마 보정" 을 통해 보지 않고 있다면, 페인팅은 "숨겨진" 비선형성을 포함하게 될 것이다. 페인팅은 당신 모니터에서는 괜찮아 보일지 몰라도, 다른 모니터에서는 달라 보이거나, 3D 렌더링에서 실제로 사용되었을 때 당신이 원하던 대로 보이지 않을 수도 있다. 렌더러는 이미지가 선형이라고 가정할 경우 그 값을 올바르게 사용하지 않을 것이다. 또한, 만약 렌더러의 암묵적으로 선형적인 결과물을 감마보정 없이 디스플레이에 출력한다면, 결과물은 너무 어두워 보일 것이다 - 그러나 고르게 어두워 보이지는 않을 것이다. 그래서 그냥 그걸 밝게 만드는 걸로는 부족하다.

만약 이미지 파이프라인의 처음과 끝에 모두 문제가 있는 경우, 그러니까 당신이 이미지를  비선형적인 감마 스페이스에서 그리거나 캡쳐하고, 이를 선형적으로 렌더한 다음 렌더된 이미지를 제대로 보정하지 못했다면, 결과물은 척 보기에 괜찮아 보일 수도 있다. 왜냐고? 비선형적인 페인팅과 캡쳐, 그리고 비선형적인 디스플레이는 어느 정도 서로 상쇄할 수 있기 때문이다. 그러나 비선형적인 입력이 라이팅에 의해 밝아지거나 어두워면서 생기는 색상의 변화나, 잘못된 알파 채널 값으로부터 생기는 컴포지팅 문제, 그리고 잘못 만들어진 밉맵을 포함해서 많은 미묘한 문제들이 렌더링과 디스플레이 사이에 걸쳐져 있을 것이다. 게다가, 사실적인 라이팅을 위한 어떤 시도들 - HDR과 이미지 기반 라이팅 같은 - 도 당신이 기대하는 대로 동작하지 않을 것이다.

또한, 결과물은 그것을 디스플레이해서 보는 사람들 개개인에 따라 달라 보이기 쉬울 것이다. 왜냐하면 페인팅과 출력값 모두가 어떤 면에서는 특정한 모니터만을 참조해서 만들어졌기 때문이다. 그리고 페인팅과 3D 라이팅을 만드는 데 필연적으로 같은 모니터를 썼다는 보장도 없기 때문이다.


증상

만약 이 문제를 무시하고 모니터 스페이스(감마 스페이스)에서 페인팅히거나 라이팅하고 모니터 스페이스에서 디스플레이 한다면, 아래와 같은 문제게 부딪히게 될 것이다.


비선형적인 입력 텍스처

보통의 사용자들은 캘리브레이션 된 모니터도 없고 감마 보정에 대해 들어본 적도 없을 것이다. 따라서, 많은 시각 요소들이 그들을 위해 미리 보정된다. 예를 들어, 관례적으로 모든 JPEG 이미지 파일들은 2.2의 감마로 미리 보정된다. 이것은 어떤 모니터에도 딱 들어맞는 값이 아니지만, 대체적인 범위 내에 있다. 그러므로 이미지는 대부분의 모니터에서 봐줄 만 할 것이다. 이것은 JPEG 이미지는(스캔된 이미지나 디지털 카메라로 찍은 사진들을 포함해서) 대부분 선형적이지 않다는 뜻이다. 따라서 JPEG 이미지는 선형 입력값을 전제로 하는 셰이더의 텍스처 맵으로 쓰지 말아야 한다.

미리 보정된 포맷은 일반적인 LCD나 CRT 디스플레이에서 바로 디스플레이 되기에는 편리하다. 그리고 8비트 이미지의 저장 공간은 어두운 부분에서 더 많은 "색상 해상도(Color Resolution)" 을 감당할 수 있다.(어두운 부분에서 눈은 강도의 작은 변화에 더욱 민감하다) 그러나, 이 포맷은 이 이미지들이 어떤 종류의 렌더링이나 컴포지팅 과정에서든 사용되기 전에 가공이 필요하다.


밉맵

밉맵을 만들 때, 각각의 밉맵 레벨로 이미지들을 다운사이징 하기 위한 확실한 방법은 바로 윗 단계의해상도 밉맵의 4개 픽셀의 합을 1/4 한 텍셀이 낮은 밉맵의 각각의 텍셀이 되게끔 하는 것이다(...) 상위 텍스처에서 테두리를 처리한다고 가정해 보자: 1.0인 픽셀이 2개, 0.0인 픽셀이 2개씩 있다. 낮은 해상도의 픽셀은 0.5가 되어야 한다. 맞죠? 밝기의 절반인.. 왜냐하면 절반만큼 완전히 밝고(1.0) 절반만큼 완전히 어두우니까(0.0). 그리고 이것이 밉맵을 계산하는 방법이다. 아하. 하지만 이것은 선형 수학이다! 만약 2.0 같은 감마를 가진 비선형 색상 공간이라면, 아주 낮은 레벨의 텍셀에서 0.5의 값은 25% 정도의 밝기밖에 디스플레이 되지 않을 것이다. 그러므로 낮은 해상도의 밉맵에서는 그리 작지 않은  오류가 보일 것인데, 높은 해상도로부터의 강도가 단순히 올바르게 필터링되지 않았기 때문이다. 렌더링 된 오브젝트들의 밝기는 윤곽선 테두리를 따라, 그리고 3D 카메라로부터의 거리에 따라 달라질 것이다.

게다가, 밉맵을 만들 때 이 비선형성을 바로잡으려고 노력했어도, 비선형적인 텍스처를 GPU(또는 CPU 렌더러들) 에서 필터링하는 데에는 또 다른 문제가 있다. GPU는 "mipmap 레벨" 또는 "텍스처 LOD" 을 선택하기 위해 텍스처 룩업 필터를 사용하고, 필요할 시 인접한 두 밉맵 레벨을 블렌딩하기도 한다. 이제 당신이 이 논쟁의 골자를 이해했으리라 믿는다 - 렌더 타임 블렌딩 자체도 선형 입력을 전제로 이루어지는 계산이고, 입력된 두 텍스처가 모두 비선형이라면, 결과물은 올바른 컬러 강도를 내지 못할 것이다. 이 상황은 텍스처가 두 밉맵 사이의 전환점에서 미세하게 떨리게 할 것이다.


일루미네이션

아래와 같이 간단한 구의 일루미네이션을 생각해 보자.  만약 반사된 빛이 N·L에 비례한다면, N·L이 60도의 각도를 이루는 구 위의 A지점에서는 빛이 카메라로 절반만 반사되어 들어와야 한다. 그러므로, N이 광원을 똑바로 바라보는 지점 B보다 절반 정도 밝은 것으로 보인다. 만약 이 이미지 값들이 빛으로 선형적으로 변환되었다면, 이미지를 봤을때 이같은 반사 속성을 지닌 진짜 물체처럼 보여야 한다. 그러나 2.0의 감마를 지닌 모니터에서 이 이미지를 디스플레이 했을 때, a는 0.5gamma, 즉 B의 4분의 1 밝기밖에 되지 않을 것이다.

24fig03.jpg


선형 이미지(감마보정 된 것, 안된 것)


다른 말로, 컴퓨터에서 생성된(CG) 재질과 빛은 빛의 선형적인 속성을 전제하고 비선형적인 모니터로 디스플레이할 경우, 실제 세계의 재질과 빛과 맞아떨어지지 않을 것이다. 총체적으로, 장면은 실제의 시뮬레이션보다 어둑해 보일 것이다. 그러나, 단지 상수(constant factor)로 이를 밝아지게 하는 것은 충분치 않다: 밝은 부분은 중간 부분들보다 더욱 보정될 것이다. 그림자 명암 경계선과 (빛의) 강도 전환점은 더욱 날카로워질 것이다 - 예를 들어, 빛과 어둠 사이의 전환이 실제 세계보다 더욱 빨라질 것이다. 가장자리들은 너무 어둡게 보일 것이다. 그리고 HDR이나 어떤 종류의 글로벌 일루미네이션, Subsurface Scattering과 같은 더욱 "발전된" 라이팅 기술을 사용할수록, 라이팅에 사용된 선형 연산애 적합한 선형 색상 공간을 고수하는 것이 더욱 중요해질 것이다. 


두 개의 오류가 하나의 정답을 만들지는 못한다. (Two wrongs don't make a right)

렌더링에서 가장 흔히 저지르는 감마 실수는 셰이딩에 비선형적인 컬러 텍스처들을 사용하고, 최종 이미지에 감마 보정을 적용하지 않는 것이다. 이 2중의 실수는 둘 중 하나를 저지르는 것보다 더욱 알아채기 어렵다 - 왜냐하면 각각의 경우에 필요한 보정이 거의 반대이기 때문이다. 하지만, 이 상황은 쉽게 피할 수 있는 많은 문제들을 야기한다.


아래 이미지는 사실적인 스킨 셰이더를 사용한 실시간 렌더링의 비교이다. 스킨 셰이더에 대한 자세한 정보는 챕터 14를 참고하자. (나중에 언리얼 Realistic Human 예제와 함께 보도록 하겠읍니다) 왼쪽 이미지는 디퓨즈 텍스처를 선형 공간으로 변환한 것이다 - 왜냐하면 텍스처가 여러 개의 JPEG 사진으로부터 만들어졌기 때문이다. Subsurface scattering을 포함한 라이팅과 셰이딩이 선형 공간에서 제대로 수행된 뒤, 최종 이미지는 보통의 비선형적인 디스플레이 장치들에 맞춰 감마보정되었다.

24fig04.jpg

제대로 된 감마 보정을 거쳐 렌더링 / 감마를 무시하고 렌더링


오른쪽 이미지는 어떤 보정도 거치지 않아 몇몇 문제를 보여준다. 컬러 사진으로부터 만든 피부 톤은 라이팅이 비선형 공간에서 수행되었기 때문에 바뀌고, 라이팅이 컬러값을 밝히거나 어둡게 하면서 컬러는 우연적으로 바뀐다. 피부의 레드 채널 레벨은 그린이나 블루 채널의 레벨보다 놓기 때문에 빛과 그림자때문에 밝거나 어두워질 때 다른 영향을 받는다) 하얀 스페큘로 반사광은 디퓨즈 라이팅에 더해졌을 때, 노란색으로 변한다. 그림자 영역은 너무 어두워지고, subsurface scattering은(특히 그림자진 영역의 미묘한 붉은 난반사는) 거의 완전히 없어진다 - 왜냐하면 디스플레이 될 때 감마 커브에 의해 완전히 짜부러지기 때문이다.

라이트를 조정하는 것은 비선형적인 공간에서 문제가 된다.위의 장면을 라이트의 강도를 올려 렌더링하면, 비선형적인 버전은 아래 그림에서 보는 것처럼 더 안좋아질 것이다. 원칙적으로, 같은 오브젝트가 밝아지거나 어두워질 때 컬러 톤이 변한다면, 대부분 비선형적인 라이팅이 수행되고 있고 감마 보정이 필요하다.

24fig05.jpg

제대로 된 감마 보정이 된 것, 그리고 잘못된 감마로 렌더링된 것

감마 보정을 무시한 채 subsurface scattering을 사용해 피부를 렌더링할 때 가장 많이 부딪히는 문제는, 아래 그림과 같이 그림자 모서리에 파란~초록색 글로우가 나타나는 것과 너무 왁스처럼 보이는 피부이다. 이 문제들은 분산 파라미터들(Scattering patameters)이 그림자 모서리들에 원하는 만큼의 붉은 번짐을 주도록 조정될 때 발생한다. 이 효과는 비선형 컬러 스페이스에서 얻기 힘들며 레드 채널에서 조도(irradiance)에 크게 가중치를 준 광범위한 블러(Heavily weighted broad blur) 가 필요하다. 아 결과는 얼굴에 너무 많은 (빛의) 확산을 야기하고(따라서 왁스같이 보이게 하고), 그림자 테두리에 가까워질 수록 적색이 너무 어두워지도록 한다(따라서 그림자 테두리에 파란~초록색 글로우가 보이게 한다). 

24fig06.jpg

감마 보정 없이 Subsurface scattering을 트위킹하는 것은 문제가 된다.


해결책

감마 보정은 이미지 픽셀들이 디스플레이 되기 전, 이미지 픽셀에 대한 모니터 변환의 역을 적용하는 계산이다. 즉, 만약 디스플레이 하기 전에 픽셀 값을 1/gamma 로 제곱한다면, 디스플레이가 감마를 제곱하는 것을 완전히 상쇄할 것이고, 대체로 선형적인 결과를 낳을 것이다.

일반적인 구현 방법은 윈도우 시스템이 감마 보정을 포함하는 색상 보정 룩업테이블(color-correction lookup table) 을 적용하게 하는 것이다. 이 조정은 모든 렌더링, 컴포지팅, 다른 이미지 조작에서 선형 연산을 할 수 있도록 하며, 어떤 선형으로 스캔된(Linear-scanned) 이미지들, 그림이나 렌더링된 이미지들도 제대로 보이도록 할 것이다.


애니메이션과 비주얼 이펙트 스튜디오들, 상업 출판사들은 이 프로세스에 매우 주의를 기울인다. 그들의 모니터와 컴포지팅 파이프라인, 필름과 비디오 스캐닝, 그리고 최종 결과물까지의 컬러 매니지먼트를 이해하는 스태프는 보통 독점적인 직무이다.  사실, 하이엔드 어플리케이션에서는 간단한 감마 보정만으로는 충분치 않다. 보통 컴포지터들은 필름 스톡의 색상 반응 커브나 개개의 디스플레이에서 정밀하게 측정하여 얻어진 훨씬 복잡한 3D LUT를 사용한다. 영화의 비주얼 이펙트나 애니메이션에 비해서, 게임 개발자들은 이 프로세스를 흔히 잘못 수행해서 이 챕터에서 거론된 문제들을 유발한다. 이것이 대부분의(하지만 다는 아닌) 영화의 CG가 게임들보다 훨씬 좋아보이는 이유이다. - 폴리곤 수나 셰이딩, 게임 개발자들의 예술적인 기량과는 아무 관계가 없다.(가끔 잘 만든 영화 CG가 조악해 보이는 이유도, 색상 팔레트와 감마가 부주의한 컴포지터에 의해 잘못 조합되었기 때문이다)

 게임 플레이어 Joe는 캘리브리션된 모니터가 없다. 우리는 그의 모니터에 적합한 LUT도 모르고, 어떤 경우에는 그가 디스플레이 전체에 감마 보정을 적용하고 싶어하지 않을 수도 있다. 왜냐고? 웹 브라우저로 보이는 보통의 JPEG 이미지들은 물빠진 것처럼 보일 것이고, 그는 그걸 이해하지 못할 것이기 때문이다(영화 스튜디오에서는 아티스트의 워크스테이션에서 인터넷의 아무 이미지들이 이상해 보여도 상관하지 않는다 - 그들의 제작물인 영화가 조건을 완전히 제어할 수 있는 극장에서 완벽하게 보여지는 한은. 그러나 "평균의" 모니터를 위한 단순한 감마 보정은 대부분의 방법을 제공해 준다. 이 챕터의 나머지 부분에서는 당신이 개발중인 게임을 향상시키면서 이러한 아티팩트를 피하는 가장 쉬운 해결책을 제시해 줄 것이다.


입력 이미지들(스캔, 페인팅, 디지털 사진)

당신이 스캔했거나 디지털 사진으로 찍은 이미지들은 이미 감마 보정이 되어 있고(특히 그 이미지들이 당신이 얻었을 당시 JPEG였다면) 따라서 비선형 색상 공간에 있다. (디지털 카메라의 JPEG 사진들도 질감을 잡아내기 위해 카메라에 의해 샤픈된다. 이를 피하기 위해서는 RAW 파일 포맷을 사용하라) 만약 감마 LUT 없이 페인팅했다면, 이 페인팅들도 모니터 컬러 스페이스 안에 있을 것이다. 만약 이미지가 모니터의 웹 브라우저에서 잘 보인다면, 이미지가 감마 보정되었거 비선형일 가능성이 있다.

이미 감마 보정이 된 모든 입력 텍스처들은 셰이딩이나 컴포지팅에 사용되기 전에 다시 선형 공간으로 되돌릴 필요가 있다. (선형) 라이팅 계산에서 사용되기 전에 텍스처 값들에 이 조정을 적용하고 싶을때, 난반사광 색이나 라이트 밝기같은 색상 값들은 항상 셰이딩에 사용되기 전에 보정되지 말아야 한다(uncorrected). 알파해널, 노말맵, 디스플레이스먼트 등의 값들은 거의 대부분 이미 선형적이기 때문에 더 보정될 필요가 없고, 선형적인 방식으로 캡쳐하거나 페인팅한 텍스처도 마찬가지이다.

현대의 모든 GPU들은 sRGB 텍스처 포맷을 지원한다. 이 포맷들은 택스처 페치(texture fetch)의 결과값이 셰이딩에 사용되기 전에 픽셀 데이터를 하드웨어에 의해 적절한 감마 보정이 적용된 텍스처로 곧바로 바인딩할 수 있도록 한다. NVIDIA GeForce 8 클래스(그리고 미래의) 하드웨어들에서는, 텍스처 필터링에 사용되는 모든 샘플들은 올바른 필터링 수행을 보장하도록 항상 선형화된다.(오래된 GPU들은 감마 후처리 필터링을 적용한다). 적용된 감마 보정은 IEC-standard인데, 대략 2.2의 감마에 부합하고 정확한 감마 커브를 알 수 없는 비선형적 색상 데이터들에 대해 안전한 선택이다. 알파 값은(만약 있을 경우) 보정되지 않는다.


 OpenGL과 DirectX에서 모든 8비트 텍스처 포맷(RGB, RGBA, luminance, luminance alpha, 그리고 DXT compressed) 모두에 대해 적합한 sRGB 포맷이 정의되어 있다. 예를 들어,  GL_RGB 대신 GL_SRGB_EXT를 glTexImage2D에 넘겨주면 어떤 셰이더든 특정한 텍스처에 텍스처에 접근했을 때 선형 픽셀값을 반환하는 것이 보장된다.


자동 sRGB 보정은 공짜이고, 아래 예제에서 보듯이 각각의 텍스처에 대한 접근이 이루어진 이후에 셰이더에서 수동적으로 보정을 수행햐는 것이 선호된다. 왜냐하면 각각의 pow 인스트럭션이 스칼라 값이고 2개의 인스트럭션으로 확장되기 때문이다. 또한, 수동 보정은 비선형 공간에서는 올바르게 수행되지 않는 필터링 이후에 이루어진다. sRGB 포맷은 텍스처가 로드되기 전에 선형 버전으로 미리 변환하는 것보다 선호될 수 있다. 선형 픽셀들을 다시 8비트 이미지에 저장하는 것은 낮은 라이트 레벨에서의 정밀도를 잃을 뿐만 아니라 픽셀들이 모니터 공간으로 다시 변환되거나 셰이딩에 사용되었을 때 밴딩(띠?)을 일으킨다.


예제 24-1. 수동으로 색상 값을 선형 공간으로 변환하기

텍스처 룩업은 감마 보정의 역을 적용할 수 있어 셰이더의 남은 부분들을 선형 값으로 작업할 수 있도록 한다. 그러나, sRGB 텍스처를 사용하는 것이 더 빠르고, 적절한 선형 텍스처 필터링을 가능하게 한다. (GeForce 8 혹은 그 이상) 그리고 추가적인 셰이더 코드가 필요 없다.


1
2
3
4
float3 diffuseCol = pow( f3tex2D( diffTex, texCoord ), 2.2 );
// Or (cheaper, but assuming gamma of 2.0 rather than 2.2)
    float3 diffuseCol = f3tex2D( diffTex, texCoord );
           diffuseCol = diffuseCol * diffuseCol;
cs



선형적, 비선형적 입력값들을 혼합해야 하는 셰이더들을 관리하는 것은 엔지니어 프로그래머들과 텍스처를 제공하는 아티스트들에게 아주 난처한 잡무이다.  많은 경우에 가장 간단한 해결책은 그냥 모든 텍스처들을 렌더링에 사용되기 위해 전달되기 전 선형 공간으로 미리 보정하도록 요구하는 것이다.


출력 이미지들(최종 렌더링)

디스플레이 하기 전 마지막 단계는 최종 픽셀 값들을 감마 보정해서, 픽셀 값들이 비선형적인 응답의 모니터상에 디스플레이 될 때 이미지가 "올바르게" 보이도록 하는 것이다. sRGB 프레임 버퍼를 지정하는 것은 GPU가 보정을 수행하도록 맡기고, 셰이더는 변경할 필요가 없다. 셰이더에서 반환되는 모든 값들은 프레임 버퍼(또는 렌더 투 텍스처 버퍼) 에 저장소에 가기 전에 감마보정된다. 나아가, GeForce8 또는 그 이상의 하드웨어에서 블렌딩이 활성화되었을 경우, 이전에 저장되어있떤 값들은 블렌딩되기 전 선형으로 번환된 후, 블렌딩 결과물이 다시 감마 보정된다. 알파 값들은 sRGB 버퍼가 활성화되어 있을 경우 감마 보정되지 않는다. 만약 sRGB 버퍼를 사용할 수 없다면, 더 많은 비용이 드는 아래와 같은 커스텀 셰이더를 해결책으로 사용할 수 있다. 하지만 블렌딩이 활성화 되어 있을경우 제대로 블렌딩이 계산되지 않을 것이다.


예제 24-2. 최종 단계의 감마 보정 결과물

만약 sRGB 버퍼가 사용 불가능할 경우(또는 사용자 정의된 감마값이 노출되어있을 경우) 아래의 코드가 감마 보정을 수행할 것이다.


1
2
3
4
5
   float3 finalCol = do_all_lighting_and_shading();
float pixelAlpha = compute_pixel_alpha();
return float4(pow(finalCol, 1.0 / 2.2), pixelAlpha);
// Or (cheaper, but assuming gamma of 2.0 rather than 2.2)
   return float4( sqrt( finalCol ), pixelAlpha );
cs


중간 컬러 버퍼

몇몇 미묘한 문제들을 염두해 두자. 만약 이미지들에 포스트 프로세싱 패스를 적용하고 있다면, 마지막 포스트 프로세스의 최종 단계에서 감마 보정을 수행해야 한다. 마지막 결과물 이미지가 선형인 것처럼 렌더하거나 보정하거나, 더 이상의 연산을 해서는 안된다.

또한, 만약 텍스처를 만들기 위해 렌더링할 때, 아래 둘 중 하나를 수행해야 한다 : 

a. 감마 보정 한 다음, 더 이상의 가공을 수행할 때 그 텍스처를 비선형 입력값으로 취급한다.

b. 감마 보정을 하지 않고, 더 이상의 가공을 수행할 때 그 텍스처를 선형 입력값으로 취급한다.

중간 컬러 버퍼들은 8비트 선형 이미지에 저장되었을 때, 감마 보정된 이미지일때보다 어두운 부분의 정밀도를 잃을 수 있다. 그러므로, 중간 컬러 버퍼에 접근하거나 렌더링할 때는 16비트 부동소수점 플로트를 사용하거나 sRGB 프레임 버퍼나 sRGB 텍스처 포맷을 사용하라.


결론

OpenGL, DirectX 그리고 직접 짠 셰이더들은 모든 텍스처 입력들, 빛/재질의 상호작용, 결과물이 선형인 것처럼 연산을 수행하고 있을 것이다. 그러나 텍스처 값들이 비선형일 경우가 많고, 사용자들의 캘리브레이션도 되지 않고 보정도 되지 않은 모니터가 비선형 색상 공간 변환을 적용할것이 거의 확실하다. 이 시나리오는 모든 아티팩트들과 부정확함, 밉맵 필터링 오류 같은 미묘한 문제들이나 아주 부정확한 라이트 falloff와 같은 아주 큰 오류들을 만들어낼 것이다.

따라서, 개발자들은 아래와 같은 간단한 절차들을 따르기를 강력하게 권고한다:

  1. 대부분의 게임 플레이어들이 캘리브레이션하거나 보정하지 않은, 대략 2.2의 감마 지수로 특정지을 수 있는 모니터를 사용한다고 전제하라. (더 높은 퀄리티와 사용자 경험을 위해서는 당신의 게임 환경설정이 감마 캘리브레이션 차트를 표시하게 하고, 유저가 알맞은 감마 값을 선택할 수 있도록 하라.)
  2. 라이트나 색상 값을 나타내는 비선형 텍스처(이것은 보정되지 않은 모니터에서 "올바르게" 보인다)로부터 룩업을 수행할 때, 셰이더에서 사용될 수 있는 선형적인 값을 산출할 수 있도록 결과물에 감마를 제곱하라. 특정한 HDR 라이트맵이나 노멀, 범프 하이트, 컬러가 아닌 다른 데이터를 가진, 이미 선형 공간에 있는 값들에는 이 조정을 수행하지 말야아 한다. 가능하다면, GeForce8 혹은 그 이상의 GPU에서는 향상된 퍼포먼스와 올바른 텍스처 필터링을 위해 sRGB 포맷을 사용하도록 하자.
  3. 최종 픽셀값에 감마 보정을 적용하는 것(즉, 1/감마를 제곱하는 것)은 값들을 디스플레이 하기 전 가장 마지막 단계이다. 효과적인 자동 감마보정과 올바른 블렌딩을 얻기 위해서는 sRGB 프레임 버퍼 확장을 사용하라.

위 단계를 신중하게 따르는 것은 당신 게임의 룩을 향상시키는 데에 중요한 역할을 하고, 특히 셰이더에서 수행하는 라이팅이나 머티리얼 계산의 정확도를 높인다.


더 읽을거리

이 챕터에서는, 선형적 컬러 공간을 사용해야 하는 이유에 대해 상당히 비기술적인(non-technical) 논증을 하기 위한 의도로 설명과 조언을 간결하게 유지하도록 노력하였다. 이 과정에서 지나치게 간소화된 부분이 있다. 살인적인 디테일을 원하는 분들을 위해, 감마 문제에 대한 훌륭한 해결책이 소개된 Charles Poynton의 웹 페이지를 추천한다 : http://www.poynton.com/GammaFAQ.html.

위키피디아의 감마 보정 부분도 놀랍도록 좋다. http://en.wikipedia.org/wiki/Gamma_correction

OpenGL과 DirectX 의 sRGB 하드웨어 포맷에 관한 디테일은 아래의 자료를 보자.