幻影坦克架構指南(一)

看這篇文章之前,必須強調,我是本著圖形學學術的態度,不是在教人如何開車。

事情的起因是這樣的,最近QQ群中老有人轉發一種圖片,在QQ聊天欄上是一張圖片,當你點擊放大後又是一張完全不一樣的圖片。這裡我用unity 進行演示,就是 一張圖片會隨著背景色黑白變化,變成完全不一樣的兩張圖片。

原圖

QQ空間

當背景色為白色的時候,如圖1

圖1

改變相機背景色為黑色,如圖2

圖2

回想下 alpha混合的計算公式

Color_{合}=Color_{前}*Alpha+Color_{後}*(1-Alpha)

於是我們導出一個計算 圖1(白底)與圖2(黑底)的顏色方程組

已知,PNG的某個像素點的顏色值為 Color_{mix}=(r_{mix},g_{mix},b_{mix},a_{mix})

求混合白底後的圖1顏色值為 Color_{1}=(r_{1},b_{1},g_{1},1) 以及混合黑底後的

圖2顏色值為 Color_{2}=(r_{2},g_{2},b_{2},1)

這其實就是解一個方程組(公式1)

begin{cases} & r_{1}= r_{mix} times a_{mix} + (1-a_{mix}) & g_{1}= g_{mix} times a_{mix} + (1-a_{mix}) & b_{1}= b_{mix} times a_{mix} + (1-a_{mix}) &  & r_{2}= r_{mix} times a_{mix} & g_{2}= g_{mix} times a_{mix} & b_{2}= b_{mix} times a_{mix} end{cases}

Color_{mix} 的值代入即可求出 Color_{1}Color_{2}

驗證下想法,把 shader的alpha混合關了,然後分別計算,得到結果。

圖1的效果

圖2的效果

(這裡注意,我已經在黑底下,顯示了開啟alpha通道白底的效果;在白底下顯示了開啟alpha通道黑底的效果。)

關鍵的Shader代碼

fixed4 frag (v2f IN) : COLOR {n fixed4 color = tex2D(_MainTex, IN.uv);// *IN.color;n fixed a = color.a;n n //這裡是白底n //fixed r = color.r * a + (1 - a);n //fixed g = color.g * a + (1 - a);n //fixed b = color.b * a + (1 - a);n n //這裡是黑底n fixed r = color.r * a;n fixed g = color.g * a;n fixed b = color.b * a;n color = fixed4(r, g, b, 1);nn return color;n}n

好的通過一張帶 alpha通道的圖片根據背景色不同分解成兩張圖片的原理已經說明了,我不經要想,如果我有兩張不帶alpha通道的等長等高圖片如何合成一張可根據背景色分解的圖片啊?

於是數學問題發生了轉變

已知白底的圖1顏色 Color_{1}=(r_{1},b_{1},g_{1},1) ,以及黑底的圖2顏色 Color_{2}=(r_{2},b_{2},g_{2},1) ,求帶alpha通道的顏色 Color_{mix}=(r_{mix},g_{mix},b_{mix},a_{mix})

同理我們的公式1仍然適用這個模型,回想下公式1

begin{cases} & r_{1}= r_{mix} times a_{mix} + (1-a_{mix}) & g_{1}= g_{mix} times a_{mix} + (1-a_{mix}) & b_{1}= b_{mix} times a_{mix} + (1-a_{mix}) &  & r_{2}= r_{mix} times a_{mix} & g_{2}= g_{mix} times a_{mix} & b_{2}= b_{mix} times a_{mix} end{cases}

對這個方程組進行求解得到:

begin{cases} & a_{mix}= 1-r_{1} +r_{2} & a_{mix}= 1-g_{1} +g_{2} &a_{mix}= 1-b_{1} +b_{2} &  & r_{mix}= r_{2} /( 1-r_{1}+r_{2}) & g_{mix}= g_{2} /( 1-g_{1}+g_{2}) & b_{mix}= b_{2} /( 1-b_{1}+b_{2}) end{cases}

這裡有兩個問題

第一個也是最大的問題, a_{mix} 有3個表達式,並且這3個表達式必須全部相等。而正常的一張五顏六色的圖片很難出現這種情況,所以為了正常顯示一張圖片的大概,最好的方式就是將其轉為灰度圖,也就是 r_{1}=g_{1}=b_{1},r_2=g_{2}=b_{2} ,很容易驗算 a_{mix} 三個表達式相等。

於是為了方便我把方程組的解省略為:

begin{cases} & a_{mix}= 1-r_{1} +r_{2} & r_{mix}= r_{2} /a_{mix} end{cases}

第二個問題,如果是灰度圖,那麼對每個像素 a_{mix}leq 1 也就是 r_{1}geq r_{2} ,因為alpha值的值域就是[0,1],如果超過就不正常。處理的做法就是將 r_{2} 縮小一定的比例(圖像顯示上就是變暗),因為對 r_{1} 顏色進行放大容易超過1,從而導致 顏色信息丟失。

既然驗證了思想我就來做實際行動吧,我隨便上崩壞3截了兩張圖

圖3

圖4

關鍵Shader代碼(要開啟alpha 混合,並且是正常疊加)

fixed4 frag (v2f IN) : COLOR {n fixed4 color1 = tex2D(_MainTex, IN.uv);n // 轉灰度圖n color1.rgb = dot(color1.rgb, fixed3(.222,.707,.071));nn fixed4 color2 = tex2D(_BackTex, IN.uv);n // 轉灰度圖,因為是黑色背景要使其變暗n color2.rgb = dot(color2.rgb, fixed3(.222, .707, .071)) * 0.3;nn fixed a = 1 - color1.r + color2.r;n fixed r = color2.r / a;n fixed4 color = fixed4(r, r, r, a);nn return color;n}n

運行起來的效果

白底

黑底

推薦閱讀:

計算機輔助設計與製造CAE/CAM目前有哪些技術問題需要解決?
【《Real-Time Rendering 3rd》 提煉總結】(八) 第九章 · 全局光照:光線追蹤、路徑追蹤與GI技術進化編年史
如何渲染分子結構?
【UnrealEngine4】距離場的使用技巧與應用

TAG:计算机图形学 | Unity游戏引擎 |