alpha混合技術
alpha混合技術對熟悉遊戲的人來說不會陌生,這種技術在如今的遊戲特效裏已經被用爛了。3D
的遊戲就不說了,2D的遊戲裏,這種技術也是滿眼皆是。
alpha混合聽上去很神祕,實際非常簡單,其作用就是要實現一種半透明效果。假設一種不
透明東西的顏色是A,另一種透明的東西的顏色是B,那麼透過B去看A,看上去的顏色C就是B和A
的混合顏色,可以用這個式子來近似,設B物體的透明度爲alpha(取值爲0-1,0爲完全透明,1
爲完全不透明)
R(C)=alpha*R(B)+(1-alpha)*R(A)
G(C)=alpha*G(B)+(1-alpha)*G(A)
B(C)=alpha*B(B)+(1-alpha)*B(A)
R(x)、G(x)、B(x)分別指顏色x的RGB分量。看起來這個東西這麼簡單,可是用它實現的效
果絕對不簡單,應用alpha混合技術,可以實現出最眩目的火光、煙霧、陰影、動態光源等等一
切你可以想象的出來的半透明效果。
火光、煙霧的效果是事先做好一個火或霧的圖和一個alpha通道圖(用過Photoshop的人都該
知道什麼是alpha通道),畫上去的時候每點每點計算,得到的就是火光掩映的效果。霧化效果
在3D裏還需要模糊一下,在這裏就免了,本來alpha混合就有不小的計算量了,算法再不優化再
加上模糊或其它的一些什麼原因,那麼你就是在看幻燈片了。(關於優化,網上見仁見智,我再
找時候再講)。
動態光源,聽起來高深的一塌。那我先講一下陰影,這個就簡單了,以往的遊戲也有陰影(
象《仙劍》),不過我們把它升一下級,從不透明變成半透明而已。就是把一個影子圖放在地表
上面作alpha混合(而且可以簡化,因爲影子的alpha值可以是一定的,這樣就可以大幅提高計算
速度)就OK了。
該講動態光源了。我們把沒有光源的地方想象成一張黑幕蒙在屏幕上,沒光也就什麼都看
不到。那麼我們就加上一個光源,相當於在黑幕上挖了一個洞,這個洞的大小就是被照亮的範
圍,現在我們可以看到下面的東西了。但現在這個效果說是光源,倒不如說是個窗戶,要顯得
象光源,就要讓光源的中心最亮,逐漸向四周暗下去,最後到什麼都看不見,這才象個光源。
具體實現就是alpha混合啦,蒙版的顏色是黑,中心alpha值爲0,完全透明,到光源的盡頭
alpha值爲1,完全不透明,成果就是這個樣子,象這麼回事吧!光源做好了,動態的光源就是
實時生成一個動態的alpha蒙版,然後蓋上去就行了。
不難吧!遊戲裏(其實也不只遊戲,好多算法也是這樣)的一些技術聽起來很玄,說通了也
就是那麼回事,只不過不是一下子就能想到就是了。
現在再談談Alpha混合。Alpha混合指的是給定兩個點P1、P2,其RGB顏色分量分別爲
(r1,g1,b1)和(r2,g2,b2),假定P1位於P2的後面,P2的透明度爲a(0%<a<100%),要求我沒透過
點P2看到P1的顏色值是多少。假定該值爲P3(r3,g3,b3),其計算公式如下:
r3=(1-a)*r2+a*r1;
g3=(1-a)*g2+a*g1;
b3=(1-a)*b2+a*b1;
這就是通常所說的Alpha混合。
優化一下得到:
r3=r2+a*(r1-r2);
g3=g2+a*(g1-g2);
b3=b2+a*(b1-b2);
少做了一次乘法運算。但由於a爲浮點數,運算起來仍然很慢,所以一般不採用上面的公式
,而採用整數級的Alpha混合,如下:
r2=r2+n*(r1-r2)/256;
g2=g2+n*(g1-g2)/256;
b2=b2+n*(b1-b2)/256;
以上爲256級Alpha混合公式,由於VGA/SVGA調色板寄存器爲6bits,所以做256色的Alpha混
合意義不大。
而採用一下的64級Alpha混合公式:
r2=r2+n*(r1-r2)/64;
g2=g2+n*(g1-g2)/64;
b2=b2+n*(b1-b2)/64;
進一步優化爲L:
r2=r2+(n*(r1-r2)>>6);
g2=g2+(n*(g1-g2)>>6);
b2=b2+(n*(b1-b2)>>6);
僅做了一次乘法運算,這樣程序應該能跑得飛快了。
下面給出混合一個點的Alpha算法:
int Alpha(int p1,int p2,int n)
{
int c1[3];
int c2[3];
int c3[3];
GETRGB(p1,c1,c1+1,c1+2);
GETRGB(p2,c2,c2+1,c2+2);
c3[0]=c2[0]+(n*(c1[0]-c2[0])>>6);
c3[1]=c2[1]+(n*(c1[1]-c2[1])>>6);
c3[2]=c2[2]+(n*(c1[2]-c2[2])>>6);
return ARGB(c3[0],c3[1],c3[2]);
}
對半透明混合,可有如下更快的公式:
r2=r2+((r1-r2)>>1);
g2=g2+((g1-g2)>>1);
b2=b2+((b1-b2)>>1);
這個公式沒有乘法和除法,半透明在遊戲中運用也很廣。
以下是半透明的Alpha混合:
int Alpha(int p1,int p2,int n)
{
int c1[3];
int c2[3];
int c3[3];
GETRGB(p1,c1,c1+1,c1+2);
GETRGB(p2,c2,c2+1,c2+2);
c3[0]=c2[0]+((c1[0]-c2[0])>>1);
c3[1]=c2[1]+((c1[1]-c2[1])>>1);
c3[2]=c2[2]+((c1[2]-c2[2])>>1);
return ARGB(c3[0],c3[1],c3[2]);
}
對於n級Alpha混合中的乘法運算,我們也有辦法進一步優化,可以採用移位乘法的技術來
實現快速的乘法運算,但性能提升不大,有興趣的朋友可以自己查閱相關資料,這裏不再詳述