當我們計算出場景中所有畫素的最終顏色以後,我們就必須把它們顯示在監視器上。過去,大多數監視器是陰極射線管顯示器(crt)。這些監視器有乙個物理特性就是兩倍的輸入電壓產生的不是兩倍的亮度。輸入電壓產生約為輸入電壓的2.2次冪的亮度,這叫做監視器gamma。
因為人眼看到顏色的亮度更傾向於頂部的灰階,監視器使用的也是一種指數關係(電壓的2.2次冪),所以物理亮度通過監視器能夠被對映到頂部的非線性亮度;因此看起來效果不錯(譯註:crt亮度是是電壓的2.2次冪而人眼相當於2次冪,因此crt這個缺陷正好能滿足人的需要)。
因為所有中間亮度都是線性空間計算出來的(譯註:計算的時候假設gamma為1)監視器顯以後,實際上都會不正確。當使用更高階的光照演算法時,這個問題會變得越來越明顯,你可以看看下圖:
片元著色器為:
void
main()
執行,可得原始樣子:
gamma校正(gamma correction)的思路是在最終的顏色輸出上應用監視器gamma的倒數。回頭看前面的gamma曲線圖,你會有乙個短劃線,它是監視器gamma曲線的翻轉曲線。我們在顏色顯示到監視器的時候把每個顏色輸出都加上這個翻轉的gamma曲線,這樣應用了監視器gamma以後最終的顏色將會變為線性的。我們所得到的中間色調就會更亮,所以雖然監視器使它們變暗,但是我們又將其平衡回來了。
我們來看另乙個例子。還是那個暗紅色(0.5,0.0,0.0)。在將顏色顯示到監視器之前,我們先對顏色應用gamma校正曲線。線性的顏色顯示在監視器上相當於降低了2.2次冪的亮度,所以倒數就是1/2.2次冪。gamma校正後的暗紅色就會成為(0.5,0.0,0.0)(1/2.2)=(0.5,0.0,0.0)0.45=(0.73,0.0,0.0)。校正後的顏色接著被傳送給監視器,最終顯示出來的顏色是(0.73,0.0,0.0)^2.2=(0.5,0.0,0.0)。你會發現使用了gamma校正,監視器最終會顯示出我們在應用中設定的那種線性的顏色。
在vulkan中,我們在每個相關畫素著色器執行的最後應用gamma校正,所以在傳送到幀緩衝前,顏色就被校正了。
void
main()
執行,可見到:
最後一行**,將fragcolor的每個顏色元素應用有乙個1.0/gamma的冪運算,校正畫素著色器的顏色輸出。
這些單行**代表了gamma校正的實現。不太令人印象深刻,但當你進行gamma校正的時候有一些額外的事情別忘了考慮。
另乙個解決方案是重校,或把這些srgb紋理在進行任何顏色值的計算前變回線性空間。我們可以這樣做:
vec3 color =
pow(
vec3
(texture
(texsampler, fragtexcoord)
).rgb,
vec3
(gamma)
);
執行,可見:
在使用了gamma校正之後,另乙個不同之處是光照衰減(attenuation)。真實的物理世界中,光照的衰減和光源的距離的平方成反比。
float attenuation =
1.0/
(distance * distance)
;
編譯執行:
從上圖可見,當我們使用這個衰減公式的時候,衰減效果總是過於強烈,光只能照亮一小圈,看起來並不真實。出於這個原因,我們使用在基本光照教程中所討論的那種衰減方程,它給了我們更大的控制權,此外我們還可以使用雙曲線函式:
float attenuation =
1.0/ distance;
Unity高階功能 光探頭
首先我們先說一下我們在什麼時候會使用這個光探頭當我們在一些靜態場景中,將光照烘焙出來的時候,此時物體的陰影效果都是光照烘焙出來的結果,但是如果此時我們有乙個動態的物體進入了這個已經經過烘焙的場景之後,那麼這個動態的物體身上是不能反射出當前場景的光照的,就像這樣一樣 tip 當前場景中有乙個紅色的點光...
Python高階08 異常處理
異常處理 在專案開發中,異常處理是不可或缺的。異常處理幫助人們debug,通過更加豐富的資訊,讓人們更容易找到bug的所在。異常處理還可以提高程式的容錯性。我們之前在講迴圈物件的時候,曾提到乙個stopiteration的異常,該異常是在迴圈物件窮盡所有元素時的報錯。我們以它為例,來說明基本的異常處...
Python高階08 異常處理
本文特別感謝kylinfish 在專案開發中,異常處理是不可或缺的。異常處理幫助人們debug,通過更加豐富的資訊,讓人們更容易找到bug的所在。異常處理還可以提高程式的容錯性。我們之前在講迴圈物件的時候,曾提到乙個stopiteration的異常,該異常是在迴圈物件窮盡所有元素時的報錯。我們以它為...