Gamma矯正實驗

引子

3d渲染中Gamma矯正初看很簡單,但是理解起來卻費了很大勁,起碼對我來說是這樣,相關資料看了很多,基本是理解流程了,記錄下來方便以後翻看。

響應曲線

Gamma矯正的原因是顯示器(crt或者現在的液晶顯示器都一樣)的相應曲線是非線性的:指數爲2.2的指數函數,輸入->顯示對應如下:
0 -> 0
0.5 ->0.218
1 -> 1
而人 的眼睛對光子(photon)的響應也是非線性的,光子->人眼響應對應如下:
0 -> 0
0.218 ->0.5
1 ->1
理解Gamma矯正,主要就是這兩個響應關係,剩下的就是怎麼用了。
上面2個響應結合起來,則輸入->顯示->人眼響應剛好是線性關係。

顏色空間

根據上面2個響應關係,有2個經常聽到的顏色空間:
線性空間:物理上的線性空間,表示有多少個光子
sRGB空間:基於屏幕顯示的空間,或者說基於人眼響應的空間
線性空間存儲的圖片,如果顯示在顯示器上,由於顯示器的響應曲線,會偏暗。比如圖片中某一點的值是0.5,物理上0.5的亮度應該是比較亮(感官上應該是0.73),但是由於顯示器的響應特性,顯示的實際亮度爲0.218,再加上人眼的響應,爲0.5,而不是應該的0.73,如果屏幕取色,會發現是0.73。
sRGB空間則是基於顯示器的,sRGB圖片中 的0.5對應的線性空間值爲0.218,這樣顯示出來感覺是0.5亮度,如果屏幕取色,會發現是0.5。

渲染中使用流程

早期圖形渲染中使用sRGB空間,這樣最簡單直觀,但是事實上是錯誤的,跟物理世界不符,由於現在pbr的廣泛使用,光照計算必須得在線性空間計算,這樣Gamma矯正就是必須理解的內容。基本流程如下(還是以線性空間0.5爲例):
美術製作圖片保存成sRGB空間格式,這是美術最習慣的工作方式,大部分的圖片製作工具都是這麼使用的(法線圖和高光圖等使用線性空間),線性空間中0.5對應的值爲sRGB空間中的0.73。
渲染過程中加載圖片轉換到線性空間,比如opengl中glTexImage2D使用參數GL_SRGB,這樣讀取到的值爲0.5
線性空間計算光照
最後進行gamma矯正,opengl中使用glEnable(GL_FRAMEBUFFER_SRGB);或者shader中添加FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma));這樣在顯示器顯示之前,輸入顯示器的值爲0.73,經過顯示器響應,輸出值爲0.5,人眼感受的值爲0.73,屏幕截圖發現屏幕上像素值爲0.73。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章