實驗 Unity Linear Color Space 發現結果不符合預期

  美術前上個禮拜找我問光照圖老是烘焙過暗的問題,一時興起我在 Gamma 和 Linear 兩個顏色空間切換了下,發現一個 Shader 明暗不一樣,另外一個 毫無變化,因而激發了我去研究下在 Unity 裏使用 Linear 的細節。(雖然最後發現美術的問題跟這個不太有關係)html

  這裏不想在過多冗長的去複述關於全部 Gamma 校訂的歷史和概念,假設已經閱讀過相關資料,好比如下(包括但不限於):緩存

  https://www.cnblogs.com/murongxiaopifu/p/9001314.html測試

  https://blog.csdn.net/candycat1992/article/details/46228771spa

  https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch24.html.net

  https://www.qiankanglai.me/2014/12/24/gamma-correction/3d

  https://docs.unity3d.com/Manual/LinearLighting.htmlhtm

  這裏僅僅討論下 Unity 平臺下 Linear 空間下渲染出現的和預期不一致的錯誤(姑且先叫錯誤,着實還不明白的地方),和所理解而後預期的結果不一致。測試場景也很簡單,製做三張紅色貼圖A, B 和 C,其中 A 和 B 同樣:(127,0,0),C 爲(187,0,0),其中187=((127/255)^0.45)*255。A 導入選項爲 Linear,不勾選 sRGB,B 勾選 sRGB,C勾選 sRGB。blog

圖片A     

                        A                                                            B                                                           C圖片

  能夠發現,A 保持顏色不變,B 和 C 的顏色都變暗,都被作了 Gamma 校訂 2.2,因此更暗;尤爲是 C,本來 187 的顏色被矯正後,正好變成127,這是符合預期的。get

  接下來在場景中建立三個材質,使用 Shader:Unit/Texture 來顯示貼圖自己顏色,貼圖分別使用 A, B, C;而後建立一個 Sphere 分別使用這三個材質在 Linear 空間下渲染查看顏色。顯示效果以下:

     

                       A                                                                                 B                                                                       C

  然而預期結果爲:球 A 和 C 均爲 (127,0,0)B 爲(55,0,0)。根據:A 貼圖爲 Linear,採樣後不會被硬件 Gamma 2.2 而維持原樣,Shader 計算輸出到 ColorBuffer 時 Gamma 0.45 提亮,最終輸出到顯示器再 Gamma 2.2,最終輸出顏色(127,0,0);B 貼圖爲 sRGB,採樣後被硬件 Gamma 2.2 爲 ((127/255)^2.2)*255=55,而後 Shader 中計算輸出 ColorBuffer 時 Gamma 0.45 變回到127,最終被顯示器 Gamma 2.2,輸出顏色(55,0,0);

  以上能夠看到實際渲染結果和預期結果的差別:實際渲染結果都被「提亮「了,都額外的被多增長了一個 Gamma 0.45。但是至少 Linear 的圖片是什麼顏色就應該輸出什麼顏色。因而將以上三種狀況分別在手機上使用 RenderDoc 抓幀分析下。

  場景 A:

以上分別顯示了 A 場景中,圖片的格式,以及紋理緩存的格式:

  Red127_Linear 格式:GL_COMPRESSED_RGB8_ETC2,顏色爲(127,0,0);

  Color Buffer 格式:GL_SRGB8_ALPHA8,顏色爲(187,0,0),

  因爲寫入 ColorBuffer 會作 Gamma 0.45 的校訂,因此 ColorBuffer 這個顏色是正確的,配合顯示器的 Gamma 2.2 校訂,應該正好爲(127,0,0)。但是實際上顯示器輸出的就是 ColorBuffer 的內容(187,0,0),像是沒有通過 Gamma 2.2 校訂;抑或是由於 sRGB 格式的 ColorBuffer 再次被 Gamma 0.45,而後再被顯示器 Gamma 2.2,不然如何解釋呢?暫時不明白。

  

  那麼再看下場景 B:

  Red127_sRGB 格式:GL_COMPRESSED_SRGB_ETC2 顏色爲(55,0,0),由於 sRGB 圖片作了 Gamma 2.2 校訂;

  ColorBuffer 格式:GL_SRGB8_ALPHA8,顏色爲(127,0,0),

  因此當 Color 輸出到顯示器作了 Gamma 2.2 校訂後,實際顏色應該爲 (55,0,0),然而貌似也少了這一步,跟狀況 A 同樣。

 

  最後來看下場景 C:

  Red187_sRGB 格式:GL_COMPRESSED_SRGB_ETC2 顏色爲(127,0,0),由於 sRGB 圖片作了 Gamma 2.2 校訂;
  ColorBuffer 格式:GL_SRGB8_ALPHA8,顏色爲(187,0,0),

  最後 ColorBuffer 輸出通過顯示器的 Gamma 2.2 矯正後應該輸出顏色 (127,0,0),然而實際倒是(187,0,0),同場景 A 和 B 的狀況如出一轍。

  以上測試使用 Unity 2018.1.2f1。


 

  綜上,以上三種結果和過程分析都指向一個事實:Unity 在 Linear 顏色空間下直接將 sRGB 格式的 ColorBuffer 輸出到了顯示器,缺乏了 Gamma 2.2 這一步,使得顏色都變亮了,沒法得出預期的結果,或許有什麼地方理解的還不到位,也或者我缺乏了過程當中的某個設置,目前還不得而知,若是有哪位大牛知道,還請指點下。

【本文固定地址:https://www.cnblogs.com/yaukey/p/unity_linear_color_space_unexpected_results.html

相關文章
相關標籤/搜索