alpha混合技術

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混合中的乘法運算,我們也有辦法進一步優化,可以採用移位乘法的技術來

實現快速的乘法運算,但性能提升不大,有興趣的朋友可以自己查閱相關資料,這裏不再詳述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章