解決三維出圖黑白邊緣溢出問題:STRAIGHT與PREMULT ALPHA剖析
像素抗鋸齒的基本概念:
首先是黑邊白邊產生的原因:AA抗鋸齒,要明確我們渲染出來的圖都是位圖,在位圖中只有完全水平或者垂直的直線才有可能是所有像素都是100%不透明的,任何斜線都必然帶有很多透明像素才能讓視覺效果看著像斜線。這就是抗鋸齒。 從小圖看的話,就是黑色的直線。
從大圖看的話,實則斜線的邊緣很多黑色都是半透明的。
因為每個像素都是一個方格,而且并不是無限小,你想象一根有粗細的繩子放在一片小格子上,那么有的格子會被繩子完全沾滿,有的可能占了一半,有的可能占了三分之一。那么占滿的格子就顯示純黑色,占了一半的格子就顯示50%黑,占了三分之一的格子就顯示33%黑。從近處看是很多像素方格,但是放遠了看,就很像一根斜線了。這是位圖對圖形的一種近似描述方式。而輪廓線邊緣這種像素呈半透明現象要做抗鋸齒(Anti-Aliasing)。叫這個名字的原因是,如果邊緣輪廓像素都是純黑色的話,圖像看起來就會有明顯的鋸齒感! 當我們在三維軟件里渲染某一個物體或者角色,并且這個物體或者角色沒有占滿整個畫面的時候。我們就會面臨這個輪廓邊緣的問題。同樣是由于抗鋸齒,渲染的物體的邊緣像素都是半透明的。
Alpha的兩種類型,直通和預乘:
帶Alpha的圖片有兩種計算方法,一種叫做直通Alpha(Straight Alpha),一種叫做預乘Alpha(Premultiplied Alpha)。這兩種類型在AE軟件里是市場可以看到的,當你導入一張帶通道的圖片,比如說TGA,AE就會問你,這張圖的Alpha是怎么來的,是直通類型還是預乘類型。
這兩種類型的唯一區別在于,直通Alpha圖片保留最原本的RGB數值;而預乘Alpha,是原本的RGB信息乘以Alpha的數值以后得到的結果(預乘意思就是預先乘以alpha)。 我在三維軟件中渲染了一個透明的球。
它的Alpha通道明顯是這樣的。
但其實這張圖片原本并不是你看到的那樣,它其實應該是下圖所示,你看到的球里面多出來的顏色,是場景本身的背景。過程是這樣的:本來完好的一張圖,前景和背景都有,你分開渲染的時候,前景部分使用alpha通道摳除,就會得到透明效果,而沒有被alpha通道摳除之前的效果呢,就是下圖這樣的。這兩種狀態呢,其實就是對應的我們Alpha通道的兩種計算方式:直通和預乘。 這張圖其實就是一張直通類型的圖片,它其實就是我們之前透明的預乘圖片,除以Alpha值得到的結果,這一個除法的步驟,相當于預乘的原圖乘以Alpha的逆運算,抵消掉了,就可以得到原始的可以看到背景的圖片了;圖中黑色區域沒有原先的背景,是由于我們這張直通的圖片,是通過預乘的圖片除以Alpha通道的值得來的,因為純透的地方Alpha值為0,任何數除以0都得到無限大,所以這些地方原本的信息已經丟失了,只好顯示黑色。
所以你會發現,直通和預乘,就是兩個逆運算的關系。你原圖不用Alpha去摳,就是直通的效果,乘以Alpha以后就是預乘的效果,預乘的效果除以Alpha又得到直通的效果。這就是直通和預乘的關系。
那么定義這兩種Alpha的計算方式又有啥意義呢?且慢慢道來。
直通和預乘的計算方式:
如果我們要把它合成到一個另外的背景上面去,我們把這層本身叫做A,下面的背景層叫做B。
那么在我們最最熟悉的ps里的透明度算法就是這樣的:result(結果色)=A*alphaA+B*(1-alphaA)。這個公式就像是在算計兩個圖層的貢獻值一樣,當alpha為白的時候,則結果色全部都來自圖層A,背景被掏空;當alpha為黑的時候,則結果色全部來自圖層B,前景完全消失,只看到背景;當alpha為0.5的時候,則前景和背景各貢獻一半,則看起來就是半透明的。
當你有照片A和B,你把A放在B的上面,把A圖層的透明度往下調的時候,就相當于啟用上面的公式了,透明度為100%,完全顯示A照片,透明度為50%,各顯示一半,透明度為0%,則完全顯示B照片。因為這個操作實在是太熟悉了,所以很多人會忽略在調節透明度的過程中,A圖層的透明度在下降,同時B圖層的透明度也在上升。在A圖層的透明度為100%的時候,B圖層等于透明度是0%的,所以你才在最終結果里只看到A圖層。
然而,三維軟件里面渲染出來的圖片,對于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去摳,才能得到正確的結果。
MentalRay里渲染得到直通圖的方法是勾除Premultiply,Vray里無法實現。
PS中消除黑白邊的另外一個方法:
這一段內容呢,在提供方法的同時,更能夠加深你對alpha通道的理解。講得非常棒。
方法是把背景層給摳一個洞,是用的是前景層Alpha的反向。前景層是用Add(Linear 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導進去就是好的,默認預乘。
*CGahz.COM 收集整理,轉載請注明來自CG愛好者網(www.www17488.com)
下一篇:? 路面水漬的制作