生活随笔
收集整理的這篇文章主要介紹了
Unity Gamma校正转为线性空间
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
相信大部分了解圖形學的人,都聽說過Gamma校正或者Gamma空間,線性空間這些詞。這里不對Gamma Space形成的歷史原因做過多描述。Gamma和Linear空間的一些原理,文章也很多,包括Unity官網的描述,都可以看看。 顯示器顯示的Gamma空間的顏色變化規律,對應了下圖中的黃色曲線。當美術在Gamma空間中,RGB(255,255,255)的顏色單位上,增加了1的顏色亮度,最后輸出顯示的亮度,其實是低于1的。這個差距,在特別暗的地方更加明顯,也就容易讓場景因為太暗,而看不清細節。我們公司的美術也表示,線性空間的效果其實更加直觀,而Gamma空間的顏色有可能會越疊越深。所以為了更好的美術效果,尤其是讓貼圖的陰暗處有更多的細節,將Gamma Space轉換為Linear Space還是相當有必要的。 基本思路,一般來說就是通過pow(1/Gamma)將顏色強度提高。下圖中的藍色曲線是pow(1/2.2)的近似數,pow(0.45),這樣就可以抵消掉黃色曲線的變化,使顏色變化可以趨于線性。 ?
三種函數的曲線
Infinite 3D Head Scan by Lee Perry-Smith,licensed under a Creative Commons Attribution 3.0 Unported License(available from www.ir-ltd.net)
雖然Unity 5.5開始,已經提供轉換工程為線性空間的功能,但是僅對OpenGLES 3.0及以上的設備進行支持。詳細數據可以參考這篇Unity的Blog,可以看到,還有兩成左右的設備是不具備這個條件的。所以如果項目組需要考慮低端機,尤其是考慮海外發行的話,就不能直接改變整個渲染空間。 因此替代的方法,是手動在Shader中,修改Colour Space。轉換空間用到的相關函數,Unity其實已經在Unity CG.cgnic中提供了,可以直接使用。 函數如下: ?
inline float GammaToLinearSpaceExact (float value) { ? ? ? ? ? ? ? ? if (value <= 0.04045F) ? ? ? ? ? ? ? ? ? ? ? ? return value / 12.92F; ? ? ? ? ? ? ? ? else if (value < 1.0F) ? ? ? ? ? ? ? ? ? ? ? ? return pow((value + 0.055F)/1.055F, 2.4F); ? ? ? ? ? ? ? ? else ? ? ? ? ? ? ? ? ? ? ? ? return pow(value, 2.2F); } inline half3 GammaToLinearSpace (half3 sRGB) { ? ? ? ? ? ? ? ? // Approximate version from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1 ? ? ? ? ? ? ? ? return sRGB * (sRGB * (sRGB * 0.305306011h + 0.682171111h) + 0.012522878h); ? ? ? ? ? ? ? ? // Precise version, useful for debugging. ? ? ? ? ? ? ? ? //return half3(GammaToLinearSpaceExact(sRGB.r), GammaToLinearSpaceExact(sRGB.g), GammaToLinearSpaceExact(sRGB.b)); } 復制代碼
inline float LinearToGammaSpaceExact (float value) { ? ? ? ? ? ? ? ? if (value <= 0.0F) ? ? ? ? ? ? ? ? ? ? ? ? return 0.0F; ? ? ? ? ? ? ? ? else if (value <= 0.0031308F) ? ? ? ? ? ? ? ? ? ? ? ? return 12.92F * value; ? ? ? ? ? ? ? ? else if (value < 1.0F) ? ? ? ? ? ? ? ? ? ? ? ? return 1.055F * pow(value, 0.4166667F) - 0.055F; ? ? ? ? ? ? ? ? else ? ? ? ? ? ? ? ? ? ? ? ? return pow(value, 0.45454545F); } inline half3 LinearToGammaSpace (half3 linRGB) { ? ? ? ? ? ? ? ? linRGB = max(linRGB, half3(0.h, 0.h, 0.h)); ? ? ? ? ? ? ? ? // An almost-perfect approximation from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1 ? ? ? ? ? ? ? ? return max(1.055h * pow(linRGB, 0.416666667h) - 0.055h, 0.h); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // Exact version, useful for debugging. ? ? ? ? ? ? ? ? //return half3(LinearToGammaSpaceExact(linRGB.r), LinearToGammaSpaceExact(linRGB.g), LinearToGammaSpaceExact(linRGB.b)) } 復制代碼
其中主要用到的是GammaToLinearSpace()和LinearToGammaSpace()。下面將說一下,到底怎么用這兩個函數。 主要的思路是, 手機靚號買號 把從貼圖中讀取進來的顏色,同時也是Gamma Space下的顏色,進行一次轉換,轉換到Linear Space。之后對這些顏色數據進行原本要進行的處理。處理結束后,在輸出的時候,進行一次逆轉換,將這些顏色數據,從Linear Space轉換回Gamma Space。 以下是我實際使用的一段代碼:
<blockquote>half4 color = UNITY_SAMPLE_TEX2D(_MainTex, i.uv); 復制代碼
補充一點,由于通道圖,一般來說,其實已經是線性的了,所以是不需要參與到這個轉換中的,直接用就好。但這段代碼里特別注意的一點是,最后轉換回Gamma Space的時候,我在Color上乘了一個Unity_ColorSpaceDouble。 最開始,我只進行了一個轉換回Gamma Space的方法,然后發現,場景不僅沒有變亮,反而變得更暗了。隨后查閱到一篇文章提到了,需要在最后轉回Gamma Space的時候,乘上一個值。 “與此相關的有,一個Unity提供的與色彩空間相關的值,Unity_ColorSpaceDouble。這個值在Gamma Color Space時為2,在Linear Color Space時為4.594(2的2.2次方)。對于這個值可以這樣來理解。一般在Gamma Color Space中將兩個Color值相乘后,為了避免顏色變得很暗,會在后面乘以2。” 也就是說,為了避免顏色變暗,應該擴大兩倍,但同時因為是在線性空間下,所以這個2要變成Unity_ColorSpaceDouble。 最后來看一下效果吧~ ?
上圖為Gamma Space時的效果,下圖為做完一系列變換后的結果。可以看到,整體顏色變亮,尤其是暗部的亮度和細節都有明顯的提升。 ?
可以看到特別暗的地方,在進行Gamma校正之后的變化也相對較大。所以這里也需要注意一點,如果是項目已經進行了一段時期之后,想要進行Gamma校正,一定要同時修改光照等一系列參數,以避免一些地方的光照效果過曝。
總結
以上是生活随笔 為你收集整理的Unity Gamma校正转为线性空间 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。