태그 보관물: Rendering

Rendering in Linear Color Space

http://juhlnet.egloos.com/m/1960058

# sRGB 컬러 공간

a0008416_4add15a95c626
우리가 사용하는 대부분의 디지털 이미지 장비들(디카, 스캐너, 모니터, 프린터) 은 표준 non-linear 색 공간인 sRGB 를
사용하도록 정해져있다. 따라서 사진이나 그림파일들도 그에 맞추어진 형태로 저장된다.
보통 이미지를 합성(필터링, 블렌딩, 쉐이딩,..) 할때 우리는 색공간이 linear 하다고 생각하지만, 실제 저장된 파일은
sRGB 에 맞춰져 있기 때문에 연산 전에 먼저 linearize 해줘야 정확한 컬러 연산이 가능해진다고 할 수 있다. 모니터 역시
sRGB 에 맞춰져 있기 때문에 연산 후 sRGB 색공간으로 변환해줘야 한다.
변환 수식은 아래와 같다. (gamma 2.2 에 근접)

[latex]\begin{bmatrix}
R_\mathrm{linear}\\G_\mathrm{linear}\\B_\mathrm{linear}\end{bmatrix}=
\begin{bmatrix}
3.2406&-1.5372&-0.4986\\
-0.9689&1.8758&0.0415\\
0.0557&-0.2040&1.0570
\end{bmatrix}
\begin{bmatrix}
X \\
Y \\
Z \end{bmatrix}[/latex]
[latex]C_\mathrm{srgb}=\begin{cases}
12.92C_\mathrm{linear}, & C_\mathrm{linear} \le 0.0031308\\
(1+a)C_\mathrm{linear}^{1/2.4}-a, & C_\mathrm{linear} > 0.0031308
\end{cases}
[/latex]*where [latex]a = 0.055[/latex]

[latex]C_\mathrm{linear}=\begin{cases}\frac{C_\mathrm{srgb}}{12.92}, & C_\mathrm{srgb}\le0.04045\\
\left(\frac{C_\mathrm{srgb}+a}{1+a}\right)^{2.4}, & C_\mathrm{srgb}>0.04045
\end{cases}
[/latex]
[latex]\begin{bmatrix}

X\\Y\\Z\end{bmatrix}=
\begin{bmatrix}
0.4124&0.3576&0.1805\\
0.2126&0.7152&0.0722\\
0.0193&0.1192&0.9505
\end{bmatrix}
\begin{bmatrix}
R_\mathrm{linear}\\
G_\mathrm{linear}\\
B_\mathrm{linear}\end{bmatrix}
[/latex]

대부분의 이미지 프로세싱 유틸리티나 게임들은 이를 무시하고 구현하고 있다. 자신이 작업한 텍스쳐가 실제 엔진에서
(포스트 프로세싱 끄고) 왠지 모르게 칙칙하고 어둡게 느껴진다면?… 100% 임다 -_-;
# sRGB 읽기
텍셀을 fetch 할 때 sRGB -> linear 변환
DX10 카드에서는 텍스쳐를 GPU 쪽으로 로딩할때 linear space 로 자동 변환되게 할 수 있다.  (변환될 때 색 손실을 막기
위해 채널 당 8bit 이미지가 내부적으로 12bit 나 16bit 로 저장된다고 한다) – 로딩 타임에 변환되므로 텍스쳐 필터링도
linear space 에서 하게 된다.
DX9 카드에서도 지원하지만 로딩 타임이 아닌 쉐이더에서 텍셀을 fetch 할때 linear space 로 변환되게 된다. –
필터링은 non-linear space 에서 하게 되므로 미묘하게 색이 변하게 된다.
주의. 컬러 이미지 외에 선형적인 데이터(노멀맵, 스페큘러맵, 하이트맵,…) 들은 이미 linear space 에 있기 때문에
따로 처리할 필요는 없다. – 생각해보니 스페큘러맵이 linear data 라고는 할 수 없겠다..
# sRGB 쓰기 & 블렌딩 쓰기
프레임 버퍼에 write 할 때 linear -> sRGB 변환
블렌딩 모드라면 프레임 버퍼에서 src 를 가져올때 sRGB -> linear 변환한 결과를 블렌딩 후 다시 sRGB 로 변환
DX10 이상의 카드에서 하드웨어적으로 지원한다.
지원하지 않는다면 픽셀 쉐이더에서 직접 처리해 줄 수 있다. – 하지만 블렌딩 할때 정확한 연산이 이루어지지 않는다.
(먼저 sRGB 프레임 버퍼를 읽어와서 linearize 해야 하므로..)
주의. 중간 단계 맵 (굴절맵, 반사맵, 거울맵, …) 들은 다시 linear space 에서 사용될 것이므로 linearity 를 유지 한다.
# 적용
첫번째 스크린샷이 linear space 쉐이딩, 두번째가 일반적인 non-linear space 쉐이딩
첫번째 스크린샷 보다 두번째 스크린샷의 텍스쳐가 좀 더 칙칙하고 어둡게 나오고, 스펙큘러 하이라이트 부분은 더 강렬하게
나온다. 라이트 세기를 밝게할 수록 더 확연하게 차이가 나는 걸 볼 수 있었다.
1024
1024
원본 디퓨즈 텍스쳐
512

참고 자료: