棋盤格與幻影坦克

看本篇文章前先溫習下我的幻影坦克架構指南(一)

這篇文章主要要解決的問題是,在電腦上比如說在QQ群中,我點開一張幻影坦克,因為背景不是純黑的,所以會導致別人看到的時候會出現白底的幻影。

比如像這樣:

不管是白底還是黑底,感覺都不太正常,仔細看都能看出影子出來。

本篇文章只對灰度圖進行討論,並且假設,QQ聊天背景為白色,那麼把圖片拉到白色背景的時候,我們圖片的背景顏色值差不多 為0.5的灰色,顏色計算公式差不多為:

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

alpha計算公式為:

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

好的,確定下目標:為了讓灰底顯示的圖片與黑底的差不多。那麼就是 0.5times(1-a_{mix})approx0 ,受到我們控制的只有alpha這個值,所以圖片每個像素的透明度越高,那麼我們在QQ上打開的效果越好,也就是說在教程1裡面提到的為了解決問題:

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

教程1中黑底圖的亮度縮小了一定的比例,所以 0.5times(1-a_{mix}) 會變得很大,因為 a_{mix} 變小了,並且如果白底為黑色,而黑底為白色的時候,不管縮小多少都會顯示出來。

所以本文的最終目標是:尋找一種保證黑底的亮度不被縮小,並且還要解決QQ發出來的白底圖會出現黑底圖幻影的問題。

白底:

黑底

不調低黑底的亮度,合成出來的圖片:

白底

完全被黑底給覆蓋了,理由也很簡單,黑底的顏色亮度比白底高,導致alpha值為1,直接就拿背景色來顯示,顯然不可取。

那麼怎麼辦?這裡用到兩個技術,一: 棋盤的靜態渲染,二:人眼的柵格錯覺。

棋盤渲染:PS4pro所謂棋盤渲染到底是什麼概念? - 一疼的回答 - 知乎

zhihu.com/question/5071

柵格錯覺:如何解釋這張「永遠追不到的黑點」圖? - 暗涌的回答 - zhihu.com/question/3887

了解了之後,我們來構造兩張圖(重點,敲黑板)

白底:

被我標記出來的顏色坐標為原來的顏色,沒有標記出來的,為白色。記住(同奇同偶)。

黑底:

被我標記出來的顏色為原來的顏色,沒有標記出來的為黑色。(不是同奇同偶數)

沒錯兩張圖片計算alpha值的時候,可以不用擔心黑底的顏色亮度比白底的高!因為黑底對應計算的白底值為 g_{1}=1 ,而白底對應黑底計算值 g_{2}=0 也就是 a_{mix}= 1-g_{1} +g_{2} 值永遠坐落於0~1之間,所以就沒有必要調低黑底的亮度了。

而背景色為灰色的時候,我們利用眼睛的柵格錯覺(屏幕解析度越高越好),會自動幫我們把顯示出來的顏色與相鄰的顏色插值,讓人眼感覺圖片顯示的暗一點。

棋盤格合成出來的效果:

白底:

黑底:

QQ上發出來的效果:

QQ上點開放大的效果:

關鍵代碼:

private void SetWhiteColor(Bitmap picture) {n int width = picture.Width;n int height = picture.Height;n for (int i = 0; i < width; i++) {n for (int j = 0; j < height; j++) {n if ((i + j) % 2 == 0) {n Color c = Color.FromArgb(255, 255, 255, 255);n picture.SetPixel(i, j, c);n }n }n }n}nnprivate void SetBlackColor(Bitmap picture) {n int width = picture.Width;n int height = picture.Height;n for (int i = 0; i < width; i++) {n for (int j = 0; j < height; j++) {n if ((i + j) % 2 != 0) {n Color c = Color.FromArgb(255, 0, 0, 0);n picture.SetPixel(i, j, c);n }n }n }n}n

PS為什麼不討論彩色坦克呢?

因為彩色坦克都是以犧牲亮度跟色彩來保證黑底為彩色的,詳見:幻影坦克架構指南(三),如果犧牲色彩的話,那就是本文的內容了,犧牲亮度絕對不可取,因為會導致 0.5times(1-a_{mix}) 過大。

所以本文也算是幻影坦克系列的終結文章吧,理論上在QQ聊天上的幻影坦克也到此為止了。

自己寫了個工具,下載地址:

鏈接:/s/1dkWLhO 密碼:lt32


推薦閱讀:

一口氣解決RenderQueue、Ztest、Zwrite、AlphaTest、AlphaBlend和Stencil
關於Unity動畫系統優化,你可能遇到這些問題
一個關於渲染管線中坐標變換的簡單實例
Unity3D插件開發教程(四):獲取地址組件

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