幻影坦克架構指南(二)

看這篇文章之前,必須繼續強調,我是搞學術的,不是在教人發車的。

上篇文章評論中,有人問到能不能發彩色底圖。這個其實有點難度,但是又感覺不是實現不了,比如說我可以對白底圖的需求放寬,對黑底圖要求彩色。那麼好的,我就開始了一番數學推導:

回放下我們的需求:

已知白底的圖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})。並且我們最終得到的解如下:

egin{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} 	ag{1}

這裡最蛋疼的就是三個alpha的表達式,如果圖片允許我們帶3個alpha,那麼問題簡直迎刃而解,不過現實很殘酷。於是我想到,如果不關心白底的圖片顯示,只要看不出黑底長啥樣就行,於是只要把 Color_{1}=(r_{1},b_{1},g_{1},1) 的rgb當成未知數, Color_{2}=(r_{2},b_{2},g_{2},1) 當成已知數,求解3元一次方程組即可。對方程組進行 矩陣形式的變形如下

egin{cases} & r_{1}-g_{1}= r_{2} -g_{2}\ & g_{1}-b_{1}= g_{2} -b_{2}\ & b_{1}-r_{1}= b_{2} -r_{2} end{cases} 	ag{2}

化成矩陣形式如下

egin{bmatrix} 1 &-1 &0 \ 0& 1&-1 \ -1& 0&1 end{bmatrix}= egin{bmatrix} r_{2}-g_{2}\ g_{2}-b_{2}\ b_{2}-r_{2} end{bmatrix}

然後求解行列式

egin{vmatrix} 1 &-1 &0 \ 0 &1 &-1 \ -1&0 &1 end{vmatrix}=0

行列式為0代表,這個三元一次方程組秩數不夠,易得,這個矩陣的秩數為2(前兩行直接加到第三行),所以結果被 r_{1}-g_{1}= r_{2} -g_{2}g_{1}-b_{1}= g_{2} -b_{2} 兩個方程確定。

不過為了簡化理解,讀者只要知道 a_{mix} 目前可以在 [0,1] 這個值域中取任意值。

好的繼續研究下,(1)的下半部

egin{cases} & r_{mix}= r_{2} / a_{mix}\ & g_{mix}= g_{2} /a_{mix}\ & b_{mix}= b_{2} /a_{mix}\ end{cases}

這裡還是強調下顏色的值域是 [0,1] ,所以為了顏色不越界, a_{mix} 的值域為 [max(r_{2},g_{2},b_{2}),1],彩色圖片一般來說rgb的最大值很容易接近1,所以可以把黑底圖的顏色變暗,擴大值域範圍來增加白底圖與黑底圖的無關性,因為我們的目的就是讓白底圖看不見黑底圖,如果兩張圖片相關性太強就遠離了我們的初衷。並且當我們把黑底圖變的很暗的同時我發現一個很有趣的現象。

lim(r2-g2)
ightarrow 0、lim(g2-b2)
ightarrow 0、lim(b2-r2)
ightarrow 0

好的,(2)又變成了這樣

egin{cases} & r_{1}-g_{1}approx0\ & g_{1}-b_{1}approx0\ & b_{1}-r_{1}approx0 end{cases}

很容易得到通解 r_{1} approx g_{1} approx b_{1} 。灰度圖!!

很好,我現在歸納下兩個條件,只要白底圖是個灰度圖的前提下,把黑底圖的亮度調的足夠低。那麼我們就很容易把這兩張不帶alpha通道的圖片合成一張帶alpha通道的顏色

繼續我們上一課崩壞3的例子,這回我們要顯示彩色的黑底圖

圖1

圖2

關鍵的shader代碼

fixed4 frag (v2f IN) : COLOR { fixed4 color1 = tex2D(_MainTex, IN.uv); // 轉灰度圖 color1.rgb = dot(color1.rgb, fixed3(.222, .707, .071)); fixed4 color2 = tex2D(_BackTex, IN.uv); fixed scale = 0.2; // 為了減小alpha計算3個值差異太大,使用變暗灰度圖的值來計算alpha fixed a = dot(color2.rgb, fixed3(.222, .707, .071)) * scale; color2 = color2 * scale; // 計算黑底圖 rgb的最大值 fixed maxc = max(max(color2.r, color2.g), color2.b); a = max(1 - color1.r + a, maxc); fixed r = color2.r / a; fixed g = color2.g / a; fixed b = color2.b / a; fixed4 color = fixed4(r, g, b, a); return color;}

最後貼上效果

白底圖:

黑底圖

這裡要強調的是,彩色圖的顏色信息並沒有喪失。我們可以將於黑色疊加的rgb算好,乘回去即可還原。

好的,現在流行的手機貼圖中,有一種alpha分離技術。將原圖的alpha導出一種灰度圖,這樣就是一張彩色圖與一張灰度圖!很滿足我們這個 幻影坦克技術的需求啊,莫非etc2的技術與我的推論有不謀而合之處?

還原彩色圖的關鍵代碼如下

//5是因為縮小到0.2, 乘以a是因為黑色背景的疊加公式fixed4 color = fixed4(r*a*5, g*a*5, b*a*5, 1);

上還原之後的黑底彩色圖


推薦閱讀:

GPU Gems 基於物理模型的水面模擬 學習筆記 (一)
Unity特效(1) 夢幻旋屏
手游逆向分析<二>: Unity內還原《鎮魔曲》角色渲染效果
Unity命令行模式,也能「日誌實時輸出」
利用GPU實現無盡草地的實時渲染

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