[譯]Gamma Correction

作者:i_dovelemon

日期:2016-04-10

來源:http://www.nutty.ca/?page_id=352&link=gamma_correction,CSDN

主題:Gamma Correction, Shader



引言



        最近在研究PBR(Physical-based Rendering)相關的東西。所以看了幾篇關於線性顏色空間相關的文章,同時瞭解到了一個如何保證我們的shader計算出來的顏色會忠實的被顯示器反應出來的概念-Gamma Correction。在網上搜索相關的內容,發現這篇文章講解的很通俗易懂,所以翻譯出來分享給大家!!!



未進行gamma修正和進行gamma修正的渲染


介紹



        當你在你的顯示器上看一張圖片的時候,你所看到的像素實際上是被修改過的,爲的是能夠更加符合我們人類的視覺體驗。人類對於陰影部分更加的敏感,而對於中間色調和高光色調相對來說就不是那麼的敏感。硬件生產商們通過對軟件傳輸過去的顏色值釋加一個指數曲線,使得顏色並不是呈現線性的變化。而這個具體的指數值就被稱之爲gamma值。也真是由於顯示器生產商做的這個“人性化”的操作,使得我們這些圖形遊戲開發者想要產生我們預期的正確的圖像就需要考慮這個問題。而這篇文章的目的就是爲了向大家講述什麼是gamma correction以及如何進行gamma correction。


Gamma是什麼?



        Gamma是一種指數曲線,顯示器用這個指數曲線來調整真實輸出到顯示屏幕上的顏色值,以此更好的適應人類的視覺體驗。



        上面的圖反應了一個具有2.2gamma值的指數曲線。上面的曲線能夠反應出實際上顯示器顯示出來的值普遍要比我們真真傳遞給它的值要暗的多。比如說,當我們傳遞給顯示器強度值爲0.5的像素的時候,輸出的實際上並不是這個強度的值。0.5^2.2 = 0.21,比輸入的強度值的一半還要小。從另外一個角度來看這一條曲線,我們可以發現在這個曲線中50%的顏色強度都低於21%,只有27%的顏色強度高於50%。我們真的是非常喜歡陰影。爲了計算出輸出的顏色強度值,顯示器通過給傳遞進來的顏色值施加一個指數函數。

        O = i^gamma

        上面的O就是顯示器最終顯示的顏色,i就是我們軟件傳遞給顯示器的顏色,gamma就是顯示器所使用的gamma指數值。

        需要注意的一點就是並不是所有的顯示器都會使用2.2的gamma值。另外一些常用的gamma值像2.4,2.0,1.8等等。如果能夠使用正確的gamma值更好,但是大部分情況下,我們使用2.2的gamma值就已經能夠滿足要求了。如果還是不能夠滿足,那麼你就只能夠讓用戶自行的調節顯示器的顯示設定。如果你能夠在你的遊戲中添加一個類似的小工具,讓用戶僅僅在你的遊戲中的使用gamma修正,這樣就不會演影響到用戶在桌面系統上的使用了。一旦你獲取到了合適的gamma值,你就能夠在你的shader中計算出正確的顏色值出來。


Gamma Correction是什麼?



        Gamma是顯示器用來修改我們輸入的顏色值的操作,那麼gamma correction就是逆轉顯示器修改的過程,從而能夠讓我們這些圖形開發者在一個真實的線性RGB空間中進行光照和着色。比如說,我們想要一個物體的光照強度是0.5,那麼我們不會直接保存0.5作爲它的光照強度,而是保存0.5^1.0/2.2 = 0.73。當我們將這個0.73的值發送給顯示器之後,顯示器會在這個值的基礎上施加一個gamma函數,也就是0.73^2.2 = 0.5,而這個值就是我們希望顯示器顯示的光照強度值。爲了實現這樣的效果,你就需要施加一個翻轉gamma函數。

        O = i^1.0/gamma

        上面的O就是進行gamma correction之後的顏色值,i是輸入的顏色值,gamma是顯示器所使用的gamma值。

        添加上面的一個函數之後,會產生如下所示的一條曲線。

 = 
  
        上圖中的藍色線條表示的是我們希望施加的翻轉gamma correction曲線。然後當我們施加了這條曲線之後,將結果發送給顯示器,顯示器又會在這個的基礎上施加他的gamma函數,也就是上圖中紅色的線,最終的結果就變成了中間綠色的那條直線,也就是得到了一個線性的顏色變化。如果不進行這個gamma修正的操作,那麼顯示出來的顏色值要比真實的線性空間RGB值要暗的多。最重要的是它並不是我們的shader計算出來的顏色值。

        下面的圖例,展示出來從0-255之間的灰度變化:


不正確的漸變


正確的漸變

        上面圖中不正確的灰度漸變圖就是我們的顯示器呈現給我們的。當我們進行了gamma修正之後,線性的漸變變化就會呈現出來。當我們渲染圖像的時候,我們實際上是需要一個線性的顏色空間進行工作,但是顏色圖像並不是線性的。也就是說,A+B != C。所以在處理貼圖的時候,我們首先需要將貼圖變得線性化。爲了實現這一點,我們必須要施加一個gamma函數(不是gamma修正函數),然後我們才能夠正確的對它進行操作(譯者注:想象一下,我們在Photoshop軟件中繪製出了一張貼圖,而這張貼圖是以我們的觀察爲基準來實現的,也就是說如果貼圖的顏色亮度我們觀察的結果是0.5,那麼實際上保存的值是0.73,爲了能夠讓圖像變成真實的我們所觀察顏色的數據,我們需要對貼圖中的數據施加一個和顯示器gamma函數一樣的函數,這樣就能夠保證我們後續使用的這個貼圖就是我們所觀察到的顏色的值,而不是顯示器修改過後的值)。一旦我們使用貼圖渲染好了場景圖像之後,我們在施加一個翻轉的gamma correction函數,得到一張gamma修正過後的圖像。接着這個圖像又會被顯示器進行調節,從而真實的呈現出我們想要的結果出來。


如何實現Gamma Correction?




        最好的,也是最健壯的實現gamma修正的方法就是通過使用一個post-processing shader來實現。這個shader將最後渲染好的圖像當作一張貼圖,然後在這個貼圖的基礎上計算翻轉的gamma correction過後的顏色值,再傳遞給顯示器。這樣就需要我們將場景渲染到一個貼圖上去,然後發送給gamma correction的shader。如果對性能比較擔憂的話,我們也就將gamma correction的操作放在其他的什麼地方進行,這樣能夠從一定程度上提高性能,但是卻失去的靈活性。

        同樣的我們還要記住,我們需要對外部輸入進來的貼圖施加額外的gamma函數,從而確保在shader中使用的是呈線性變化的貼圖顏色值。但是需要注意,並不是所有的貼圖都需要經歷這個過程,一些自動產生的圖像像法線貼圖之類的就不需要額外添加gamma函數,僅僅是被gamma編碼過的貼圖需要額外施加一個gamma函數。


Gamma調節



        下面的測試能夠用來獲取顯示器的gamma值。這個測試工具使用一張具有黑白相間和一條經過gamma correction之後的灰色線條的圖像。一半的線條是黑色的,另外一半的線條是白色的,所以顯示器的平均輸出值爲50%。50%的RGB值即爲128,但是128是一個線性的顏色值。我們需要找到gamma修正過後的顏色值,也就是0.5^1.0/2.2 = 0.729 * 255 = 186,這個值就是中間的灰色方塊。當你站在顯示器幾米之外去看這張圖像,如果你的顯示器的gamma值是2.2的時候,你就會發現這張圖片只有一種顏色。
  
Gamma 2.2顯示器測試圖像

        爲了測試其他的gamma值,你需要將這張圖片的中間灰色的方塊的顏色值,使用新的gamma值計算出來的顏色替代。這個測試恐怕很難在LCD屏幕上面進行,因爲這種顯示器會隨着觀察角度的不同,而呈現不同的變化。同時還要注意不能夠過濾這張圖像,因爲會破壞這個測試。

       你沒有辦法改變一個顯示器的gamma值,但是你能夠通過調節shader中的計算,使得我們能夠產生出一個比較令人滿意的灰度變化。這種調節方式需要玩家有一定的辨識能力。也就是說,當我們把一個白色的線條和一條黑色的線條放在一起的時候,玩家需要能夠看得出來。對於某些人或者某些糟糕的顯示器,這可能是一個非常艱鉅的任務。我們往往會將RGB值分成10個亮度變化。



        這是一個非常簡單的漸變。用戶應該能夠很容易的識別出來。如果上面的任何一個很難辨別出來,那麼用戶就需要調節以至於能夠很清晰的識別出這10種階度變化。
發佈了92 篇原創文章 · 獲贊 95 · 訪問量 34萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章