Linear Space와 Gamma Space에 대한 이해
일반적으로 그래픽 어플리케이션에서 텍스쳐 등의 이미지 데이터를 입력 데이터로 활용할 때 해당 데이터를 디코딩한 후 사용하며, 반대로 이러한 어플리케이션들을 이용해 이미지를 생성하고 이를 모니터에 출력하거나 저장할 땐 인코딩을 해 준다. 이 때 디코딩과 인코딩을 한다는 것은, 적어도 감마 보정에 대한 이야기를 하는 한, 각각 Gamma/Linear Space에 정의된 색상 데이터를 Linear/Gamma Space로 변환하는 것을 말한다. Gamma? Linear? 둘 다 'Space(공간)' 을 지칭하는 것 같은데, 그럼 이 공간은 대체 무엇인가?
앞서 말한 'Space(공간)'은 Color Space(색 공간)을 의미한다. 색 공간은 디스플레이가 출력할 수 있는 색(이므로 빛의 광도-radiance-일 것이다)을 비트로, 또는 임의의 비트 데이터를 색으로 변환하는 시스템을 말한다. 모두가 알다시피 컴퓨터는 오직 비트(0과 1)만을 저장할 수 있으므로, 어떠한 이미지 데이터라 할지라도 디지털로 저장하는 순간 이산적인 수 데이터로 저장된다. 이처럼 수로 이루어진 데이터를 이용해 각 픽셀에 적절한 빛을 세팅함으로써 우리 눈에 색(이미지)을 표현하게 된다.
그렇다면 색 공간은 전 세계에 단 하나의 표준 공간만 있으면 될까? 마치 IEEE-754에 정의된 부동소수점의 표현 방식처럼, 모두가 동일하게 사용하기로 약속한 하나의 색 공간을 사용하면 될 것처럼 보이지만 그렇지 않다. 세상에는 많은 종류의 색 공간이 존재하는데, 이는 세상에 존재하는 다양한 종류의 디스플레이 장치들의 자신들만의 '색역(Color Gamut)'을 가지고 있기 때문이다. 색역은 말 그대로 색의 대역, 즉 해당 디스플레이가 표현할 수 있는 색의 범위를 의미한다.
게임 회사에서 일하고 있는 서버 프로그래머는 넓은 색역의 모니터가 필요하지 않을 것이다. 적당한 수준의 색을 표현할 수 있는 모니터라면 업무를 수행하는 데 전혀 지장이 없다. 그러나 같은 스튜디오의 아티스트는 더욱 정교한 색감을 파악하기 위해 최대한 넓은 색역의 모니터를 필요로 할 것이다. 방금의 비유는 모니터 간의 색역을 설명하는 것이지만 이 외에도 영사기, 빔 프로젝터, 대형 전광판 등 세상에 존재하는 수많은 디스플레이 장치들은 저마다의 이유로 해당 디스플레이만의 색역을 가지게 될 것이다. 다양한 색 공간이 정의된 이유는 이처럼 다양한 색역을 가진 디스플레이들이 동일한 비트 값에 대해 다른 색을 출력하게 되기 때문이다.
위의 도표를 보듯 sRGB, DCI-P3, Adobe RGB, 등 다양한 표준 색 공간들이 정의되어 있고 디스플레이 제조사나 혹은 디스플레이 장치를 사용하는 사용자들은 필요에 맞게 원하는 색 공간을 선택해 제작 또는 사용한다.
추가로 한 가지 더, 디스플레이 장치가 임의의 색 공간을 활용해 비트 데이터를 광도로 변환할 때, 이 변환 규칙을 함수 형태로 표현한 것을 '디스플레이 전이 함수(Display Transfer Function)'이라 한다.
여기까지 이해가 되었다면 이제 감마 보정에 대해 본격적으로 이야기할 수 있는 토대가 완성되었다. 감마 보정(Gamma Correction)이라는 개념은 20세기에 음극선관으로 구성된 디스플레이 장치(브라운관이라고도 부르며, 영어로는 Cathode-Ray Tube, CRT라고 부르는 그것이다)를 사용하면서부터 시작되었다. 당시의 CRT 디스플레이 장치는 음극선의 물리적인 성질에 의해 픽셀에 가하는 전압과 디스플레이 광도 사이에 1보다 큰 수의 거듭제곱 꼴의 관계가 나타났다. 이러한 현상을 디스플레이 전이 함수로 표현하면 다음과 같았다.
예를 들어, 지수가 2인 디스플레이 전이 함수를 가진 CRT 모니터를 이용해 빨간 점을 하나 렌더링한다고 가정하자. 빨간 색의 수치상 강도는 최대 강도의 40%정도로 출력한다. 즉 최저 강도를 0.0, 최대 강도를 1.0으로 놓으면 0.4의 R값을 출력할 것이다. 이 경우 CRT모니터는 실제 화면에 다음과 같이 0.16의 디스플레이 광도로 붉은색 점을 출력한다.
이를 통해 알 수 있는 CRT모니터의 특징은 다음과 같다.
첫 번째, 대체로 실제 디지털 이미지가 가진 값보다 조금 어둡게 출력된다.
두 번째, 색의 값이 낮을수록 인접한 값들 사이의 출력 변화를 느끼기 어렵다.
여기서 첫 번째 문제는 잠시 제쳐두고, 먼저 두 번째 특이다. 왜 색의 값이 낮을수록 인접한 값들 사이의 출력 변화를 느끼기 어려울까? 이는 CRT 모니터의 디스플레이 전이 함수를 그래프로 그려 보면 알 수 있다.
x축을 색의 값, y축을 광도라 할 때, x가 0.2에서 0.3으로 올라갔을 때의 광도 차이와 0.7에서 0.8로 올라갔을 때의 광도 차이를 비교해 보자. 똑같이 0.1이 증가했을 뿐이지만 실제 디스플레이의 광도는 높은 값에서 더 많이 상승한다.
그럼 완전히 어두운 모니터(grayscale 0.0)가 일정한 간격으로 밝기를 증가시켜 완전히 밝은 모니터(grayscale 1.0)로 변해간다고 할 때 모니터의 사용자는 그 변화가 비선형적으로 보이게 될 것이고, 그 어색함을 없애기 위해 모든 CRT 디스플레이에는 이를 제어하기 위한 별도의 조치가 필요했을 것이다.
그런데, 그럴 필요가 없었다.
모니터를 사용하는 인간에게는 이러한 광도 변화가 거의 선형적으로 보였다. 왜냐하면, 인간의 눈은 CRT모니터의 디스플레이 전이 함수와 반대로, 1보다 작은 거듭제곱 함수의 꼴로 빛의 변화를 감지하기 때문이다! 디스플레이 전이 함수와 마찬가지로, 이를 함수의 형태로 나타내면 다음과 같다.
즉, 인간의 눈은 어두운 빛일수록 그 변화를 민감하게 받아들이고, 밝은 빛일수록 변화를 둔감하게 받아들인다. 베버의 법칙에 입각해 빛의 변화를 감지하는 것이다.
이처럼 신기한 우연의 일치 덕분에 CRT모니터의 비선형적인 출력에도 불구하고 우리는 banding artifact를 별로 느끼지 못하며, 이러한 까닭에 LCD나 그 이후의 발전된 디스플레이에서도 추가적인 하드웨어적 보정을 통해 CRT의 응답 곡선을 모방하고 있다.
이제 첫 번째 문제를 다시 살펴보자. CRT모니터(와 그 이후에 나온 CRT모니터의 응답 곡선을 모방한 디스플레이 장치들)의 출력은 실제 데이터가 출력해야 할 색상의 밝기보다 어둡게 표현한다는 문제가 있다. 이를 위해 이미지, 비디오 등의 모든 시각 데이터들은 그 값에 CRT모니터의 디스플레이 전이 함수의 역을 취해 저장된다. 그래야 모니터로 바라볼 때 해당 데이터가 표현하고자 하는 정확한 색상이 표현되기 때문이다.
이 때 디스플레이 전이 함수의 역을 취해 저장하는 행동을 '인코딩(Encoding)'이라 한다. 그리고 사용하는 디스플레이 전이 함수는 색 공간에 의해 정해진다. 일반적으로 PC 모니터는 sRGB 색 공간을 거의 표준처럼 사용하고 있으며, 대부분의 이미지들이 sRGB 색 공간에 맞춰 인코딩 되어있다. sRGB를 표준처럼 사용하는 이유도 CRT모니터와 연관이 깊은데, sRGB색공간이 바로 CRT모니터의 디스플레이 전이 함수를 모방해 만들어진 색 공간이기 때문이다. 즉, CRT와 CRT의 톤 응답 곡선을 모방해 만들어진 디스플레이 장치들에 보여질 이미지 데이터들은 sRGB로 인코딩될 때 가장 정확한 색 표현을 나타낼 수 있기 때문에 표준처럼 사용되고 있다.
이 글을 읽다 보면 점점 답답한 기분이 들 것이다. 감마 보정의 역사에 대해 설명한다고 했는데 정작 글 안에 '감마 보정'이라는 단어는 등장하지 않았기 때문이다. CRT모니터에서 출발해 인코딩과 sRGB까지, 많은 얘기를 했는데 그래서 이게 도대체 감마 보정과 무슨 연관이 있을까?
혹시 글을 읽으면서 알아챘을지 모르겠지만, 앞서 디스플레이 전이 함수를 수식을 곁들여 설명하였다. 그 수식을 다시 가져와보자.
x의 지수 위치에 쓰여진 그리스 기호 'γ' 는 영어로 'Gamma'라 읽는다.
즉, 감마 보정은 색상 데이터를 임의의 감마 값으로 거듭제곱하는 것을 의미하며, 이는 CRT 응답 곡선을 감안하여 색상 데이터를 '인코딩'하는 것을 의미하기도 한다.
또, sRGB가 PC모니터의 표준 색 공간처럼 사용된다는 설명에 맞게 일반적으로 감마 보정은 감마 값으로 1.0/2.2(인코딩)와 2.2(디코딩)를 사용하는데, 이는 sRGB의 디스플레이 전이 함수의 근사이다. 참고로 정확한 sRGB의 디스플레이 전이 함수는 다음과 같다.
이제 렌더링 프로그래머의 입장에서 감마 보정을 바라보자. 렌더링 파이프라인에서 프로그래머는 다양한 텍스쳐를 사용하고, 파이프라인을 통해 생성한 이미지를 디스플레이에 출력한다. 텍스쳐는 아티스트가 이미 만들어 저장 장치에 존재하는 이미지 데이터이므로 매우 높은 확률로 이미 sRGB 인코딩 처리가 되어 있을 것이다. 이 데이터를 이용해 정확한 연산을 하기 위해선 선형 색상으로 변경해야 하므로 디코딩을 수행해야 한다. 그리고 파이프라인을 거쳐서 생성된 최종 이미지는 디스플레이 장치에 출력하기 전에 디스플레이 전이 함수를 감안해 인코딩을 해 주어야 한다. 다르게 말하면 감마 공간에 정의된(인코딩 처리된) 텍스쳐들을 리니어 공간으로 변환해 각종 연산에 활용한 뒤, 그 결과로 생성된 최종 이미지는 리니어 공간에서 정의되었지만 출력하기 전에 자연스럽게 표현하기 전에 감마 공간으로 변환해 주어야 한다.
글이 조금은 장황하게 느껴질 수 있어 별도로 요약을 하자면, 감마 보정을 하는 이유는 다음과 같다.
1. 인간의 눈은 빛의 변화를 비선형적으로 감지한다. 빛이 거의 없을 때(어두울 때)에는 약간의 변화도 민감하게 반응하지만, 빛이 충분할 때(밝을 때)에는 변화에 둔감하다.
2. CRT모니터는 우연히도 인간이 받아들이는 빛의 민감도의 역의 형태로 빛을 출력한다.덕분에 CRT모니터의 밝기 변화가 인간의 눈에는 꽤나 선형적으로 받아들여진다.
3. 이에 맞춰 이미지 데이터들은 자신의 원본 데이터를 CRT모니터 톤 응답 곡선에 맞게 표현하기 위해 sRGB기준 2.2라는 근삿값을 이용해 감마 보정을 수행해야 한다.
처음 감마 보정에 대해 찾아볼 때 인터넷에 감마 보정에 대한 설명글들이 매우 많았는데, 그 방법은 모두가 똑같이 명시해 놓았지만 감마 보정을 왜 해야 하는지에 대해서는 저마다 서로 다른 의견을 제시해 놓아 헷갈렸다. 사실 감마 보정을 해야 한다는 것과 하는 방법만 알면 된다고 생각은 하지만 개인적인 호기심이 생겨 자세한 히스토리를 찾아 보고 싶었고, 다양한 서적과 영상을 토대로 해 정리해 보았다. 사실 CRT모니터고 뭐고 다 제쳐 두고 감마 보정이 필요한 이유를 정말 근본적으로 따지자면 '인간의 눈이 빛의 변화를 비선형적으로 감지해서'일 것이다.
* 만약에 위 설명글에 잘못된 점이 있다면 추가적인 정보를 제시해 주시면 정말 감사하겠습니다.