1. 程式人生 > >cocos2dx 畫素黑邊處理

cocos2dx 畫素黑邊處理

//上面的官方不推薦,官方推薦使用下面的 Image::setPVRImagesHavePremultipliedAlpha(true);
黑白邊產生的原因:  黑白邊的產生的原因——AA 抗鋸齒。渲染出來的圖都是點陣圖,點陣圖中只有完全水平或垂直的直線才有可能是所有畫素都是 100% 不透明的。任何斜線都必然帶有很多透明畫素才能讓視覺看起來像斜線。這就是抗鋸齒。  alpha 的兩種型別,直通和預乘 帶 alpha 的圖片有兩種計算方法:直通 alpha ( straight alpha ) 和預乘 alpha (premultiplied alpha)。  直通 alpha 圖片保留最原本的 RGB 數值;預乘 alpha,是原本的 RGB 資訊乘以 alpha 數值以後得到的結果(預乘就是預先乘以 alpha);  直通和預乘,是兩個逆運算的關係。原圖乘以 alpha 就是預乘結果,預乘結果除以 alpha 又得到直通結果。  直通和預乘的計算方式:
如果我們把一張圖片合成到另外的背景上去,我們把這層本身叫做 A,下面的背景層叫做 B。  ps 的透明度演算法是這樣:result = A * alpha + B * (1 - alphaA)。這個公式就像是在計算圖層的貢獻值一樣,當 alpha 為白的時候,則結果色全部來自 A,背景唄掏空;當 alpha 為黑的時候,則結果色全部來自 B,前景完全消失;當 alpha 為 0.5 時候,則 A B 各自貢獻一半,則看起來就是半透明。  比如你有照片 A 和 B,把 A 放在 B 上面,把 A 的透明度下調時候,就相當於啟用上面的公式。透明度 100%,完全顯示 A 照片,透明度為 50%,各顯示一半。透明度為 0%,完全顯示 B 照片。調透明度的時候是相互影響的,A 透明度下降的同時 B 的透明度在上升。A 透明度為 100%,B 等於透明度為 0%。  三維軟體渲染出來的圖片,對於 alpha 的理解是使用的預乘型別。是另一種演算法:  result = A + B * (1 - alpha)  雖然 A 沒有乘以 A 本身的 alpha,但實際上預乘型別的圖片,以及高相當於在原始圖片上乘以一個 alpha。最終 result = A (原始或直通) * alpha + B * (1 - alpha)。  圖片先乘了以後,再合成時候就少算一個步驟,速度會加快。  PS中渲染輸出黑白邊解決方法:
說回圖片黑邊白邊的問題。當你把渲染好的圖片匯入ps的時候,比如說你用的TGA,那麼,你會有一個背景為黑色或者白色的實心圖片,順帶一個alpha通道,你要把這個圖合到背景上去,你就會用alpha把圖摳了,再放到背景上去。這時候圖片就會有黑邊,除非你背景是黑色看不出來。

原因是這樣的,你匯入ps的圖片本身是這樣的。

這是三維軟體裡直接渲染出來的圖,是一種預乘型別的圖。也就是說,這圖已經被alpha乘過了,你就可以理解成已經被alpha扣過了。但是ps這個軟體吧,它理解不了這個事情,它以為世界上所有的圖片都是直通型別的,就是沒有過被alpha扣過的圖。也就是說,它以為這圖本身的背景就是黑色的。而其實這個圖是有一個黃色背景的。

然後,你在ps裡面做的事情是用alpha通道去扣這張圖,而這張圖原本其實是一張預乘的圖。或者說,這張圖已經被alpha扣過一次了,那麼你再去扣一次,會讓很多地方看起來比從前更黑,於是黑邊就這麼產生了。(在影象邊緣,有抗鋸齒的地方,抗鋸齒就是透明,我就不放大看了。)

而在ps裡面想要解決的方案是,把一張直通的圖導進去。

再用alpha去摳,才能得到正確的結果。

mental ray渲染得到直通圖的方法是勾除premultiplyvray裡無法實現。

PS中消除黑白邊的另外一個方法:

這一段內容呢,在提供方法的同時,更能夠加深你對alpha通道的理解。講得非常棒。

方法是把背景層給摳一個洞,是用的是前景層alpha的反向。前景層是用addlinear dodge線性增加)模式疊加在背景層上,也是可以得到完美的效果的。

  原理是這樣的,前景層我麼用的是一張三維軟體裡面渲染出來,預設預乘了的圖。就相當於是A*alphaA,背景層原本是B,我們要得到正確的結果就要往公式上靠:
result=A*alphaA+B*(1-alphaA)

ps裡面,正常疊加模式的公式其實是

result=A*alphaA+B*(1-alphaA)

我們一般的做法,把前景層用通道摳一次,直接用normal疊在背景上,得到的結果其實是:

result=A*alphaA*alphaA+B*(1-alphaA)
因為前景層本身就是A*alphaA;背景層是B

add疊加模式的公式是:
result=A+B

如果直接把前景層用add模式疊在背景上,得到的結果是:
result=A*alphaA+B
視覺結果是過亮的。

為了得到正確的結果,我們需要手動把背景層反摳一個洞,模擬ps在做透明度合成時背後發生的事情,才能得到正確的結果。
當使用A圖層的alpha的反向去摳B圖層,則B圖層就變成了B*(1-alphaA)
最後的結果就變成:
result=A*alphaA+B*(1-alphaA)
這就是上圖我在ps裡做的事情,結果是非常正確的,只不過前景層很不好移動位置。因為要同時移動前景層和背景層的反向alpha(在我上面的圖中就是背景層的遮罩),我還真不知道怎麼能很方便地一起移動他們。

在AE及Nuke中解決alpha的問題:

因為ps它本身不是一個針對做三維合成使用者的後期軟體,所以在面對alpha問題的時候,能力很弱,解決起來很麻煩。但是在真正的能做合成的後期軟體中,解決起來是很方便的。

使用AE匯入TGA檔案,選擇預乘型別,背景色為你渲染的時候背景的顏色。問題就完美解決了。(注意,在分層渲染,分離前景的時候,要保證背景是純色,儘量是純黑,要是你墊在一個五顏六色的背景上渲染,之後又用alpha去摳,會摳不乾淨

nuke導進去就是好的,預設預乘。

最後,這篇文章相當於是講解了最基本的alpha的一些概念。正好,看懂了以後,可以比較好地理解我昨天錄的視訊,來解決怎麼消除模型邊緣受強光照射時的奇怪鋸齒問題。