當前位置:編程學習大全網 - 熱門推薦 - OpenGL中的混色問題(Alpha通道)

OpenGL中的混色問題(Alpha通道)

OpenGL混色2009-10-14 10:05今天介紹關於OpenGL混合的基本知識。混合是壹種常用的技巧,通常可以用來實現半透明。但其實它也是十分靈活的,妳可以通過不同的設置得到不同的混合結果,產生壹些有趣或者奇怪的圖象。

混合是什麽呢?混合就是把兩種顏色混在壹起。具體壹點,就是把某壹像素位置原來的顏色和將要畫上去的顏色,通過某種方式混在壹起,從而實現特殊的效果。

假設我們需要繪制這樣壹個場景:透過紅色的玻璃去看綠色的物體,那麽可以先繪制綠色的物體,再繪制紅色玻璃。在繪制紅色玻璃的時候,利用“混合”功能,把將要繪制上去的紅色和原來的綠色進行混合,於是得到壹種新的顏色,看上去就好像玻璃是半透明的。

要使用OpenGL的混合功能,只需要調用:glEnable(GL_BLEND);即可。

要關閉OpenGL的混合功能,只需要調用:glDisable(GL_BLEND);即可。

註意:只有在RGBA模式下,才可以使用混合功能,顏色索引模式下是無法使用混合功能的。

壹、源因子和目標因子

前面我們已經提到,混合需要把原來的顏色和將要畫上去的顏色找出來,經過某種方式處理後得到壹種新的顏色。這裏把將要畫上去的顏色稱為“源顏色”,把原來的顏色稱為“目標顏色”。

OpenGL 會把源顏色和目標顏色各自取出,並乘以壹個系數(源顏色乘以的系數稱為“源因子”,目標顏色乘以的系數稱為“目標因子”),然後相加,這樣就得到了新的顏 色。(也可以不是相加,新版本的OpenGL可以設置運算方式,包括加、減、取兩者中較大的、取兩者中較小的、邏輯運算等,但我們這裏為了簡單起見,不討 論這個了)

下面用數學公式來表達壹下這個運算方式。假設源顏色的四個分量(指紅色,綠色,藍色,alpha值)是 (Rs, Gs, Bs, As),目標顏色的四個分量是(Rd, Gd, Bd, Ad),又設源因子為(Sr, Sg, Sb, Sa),目標因子為 (Dr, Dg, Db, Da)。則混合產生的新顏色可以表示為:

(Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da)

當然了,如果顏色的某壹分量超過了1.0,則它會被自動截取為1.0,不需要考慮越界的問題。

源因子和目標因子是可以通過glBlendFunc函數來進行設置的。glBlendFunc有兩個參數,前者表示源因子,後者表示目標因子。這兩個參數可以是多種值,下面介紹比較常用的幾種。

GL_ZERO: 表示使用0.0作為因子,實際上相當於不使用這種顏色參與混合運算。

GL_ONE: 表示使用1.0作為因子,實際上相當於完全的使用了這種顏色參與混合運算。

GL_SRC_ALPHA:表示使用源顏色的alpha值來作為因子。

GL_DST_ALPHA:表示使用目標顏色的alpha值來作為因子。

GL_ONE_MINUS_SRC_ALPHA:表示用1.0減去源顏色的alpha值來作為因子。

GL_ONE_MINUS_DST_ALPHA:表示用1.0減去目標顏色的alpha值來作為因子。

除 此以外,還有GL_SRC_COLOR(把源顏色的四個分量分別作為因子的四個分量)、GL_ONE_MINUS_SRC_COLOR、 GL_DST_COLOR、GL_ONE_MINUS_DST_COLOR等,前兩個在OpenGL舊版本中只能用於設置目標因子,後兩個在OpenGL 舊版本中只能用於設置源因子。新版本的OpenGL則沒有這個限制,並且支持新的GL_CONST_COLOR(設定壹種常數顏色,將其四個分量分別作為 因子的四個分量)、GL_ONE_MINUS_CONST_COLOR、GL_CONST_ALPHA、 GL_ONE_MINUS_CONST_ALPHA。另外還有GL_SRC_ALPHA_SATURATE。新版本的OpenGL還允許顏色的alpha 值和RGB值采用不同的混合因子。但這些都不是我們現在所需要了解的。畢竟這還是入門教材,不需要整得太復雜~

舉例來說:

如果設置了glBlendFunc(GL_ONE, GL_ZERO);,則表示完全使用源顏色,完全不使用目標顏色,因此畫面效果和不使用混合的時候壹致(當然效率可能會低壹點點)。如果沒有設置源因子和目標因子,則默認情況就是這樣的設置。

如果設置了glBlendFunc(GL_ZERO, GL_ONE);,則表示完全不使用源顏色,因此無論妳想畫什麽,最後都不會被畫上去了。(但這並不是說這樣設置就沒有用,有些時候可能有特殊用途)

如 果設置了glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);,則表示源顏色乘以自身的alpha 值,目標顏色乘以1.0減去源顏色的alpha值,這樣壹來,源顏色的alpha值越大,則產生的新顏色中源顏色所占比例就越大,而目標顏色所占比例則減 小。這種情況下,我們可以簡單的將源顏色的alpha值理解為“不透明度”。這也是混合時最常用的方式。

如果設置了glBlendFunc(GL_ONE, GL_ONE);,則表示完全使用源顏色和目標顏色,最終的顏色實際上就是兩種顏色的簡單相加。例如紅色(1, 0, 0)和綠色(0, 1, 0)相加得到(1, 1, 0),結果為黃色。

註意:

所 謂源顏色和目標顏色,是跟繪制的順序有關的。假如先繪制了壹個紅色的物體,再在其上繪制綠色的物體。則綠色是源顏色,紅色是目標顏色。如果順序反過來,則 紅色就是源顏色,綠色才是目標顏色。在繪制時,應該註意順序,使得繪制的源顏色與設置的源因子對應,目標顏色與設置的目標因子對應。不要被混亂的順序搞暈 了。

二、二維圖形混合舉例

下面看壹個簡單的例子,實現將兩種不同的顏色混合在壹起。為了便於觀察,我們繪制兩個矩形:glRectf(-1, -1, 0.5, 0.5);glRectf(-0.5, -0.5, 1, 1);,這兩個矩形有壹個重疊的區域,便於我們觀察混合的效果。

先來看看使用glBlendFunc(GL_ONE, GL_ZERO);的,它的結果與不使用混合時相同。

void myDisplay(void)

{

glClear(GL_COLOR_BUFFER_BIT);

glEnable(GL_BLEND);

glBlendFunc(GL_ONE, GL_ZERO);

glColor4f(1, 0, 0, 0.5);

glRectf(-1, -1, 0.5, 0.5);

glColor4f(0, 1, 0, 0.5);

glRectf(-0.5, -0.5, 1, 1);

glutSwapBuffers();

}

嘗 試把glBlendFunc的參數修改為glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);以及 glBlendFunc(GL_ONE, GL_ONE);,觀察效果。第壹種情況下,效果與沒有使用混合時相同,後繪制的圖形會覆蓋先繪制的圖形。第二 種情況下,alpha被當作“不透明度”,由於被設置為0.5,所以兩個矩形看上去都是半透明的,乃至於看到黑色背景。第三種是將顏色相加,紅色和綠色相 加得到黃色。

三、實現三維混合

也許妳迫不及待的想要繪制壹個三維的帶有半透明物體的場景了。但是現在恐怕還不行,還有壹點是在進行三維場景的混合時必須註意的,那就是深度緩沖。

深 度緩沖是這樣壹段數據,它記錄了每壹個像素距離觀察者有多近。在啟用深度緩沖測試的情況下,如果將要繪制的像素比原來的像素更近,則像素將被繪制。否則, 像素就會被忽略掉,不進行繪制。這在繪制不透明的物體時非常有用——不管是先繪制近的物體再繪制遠的物體,還是先繪制遠的物體再繪制近的物體,或者幹脆以 混亂的順序進行繪制,最後的顯示結果總是近的物體遮住遠的物體。

然而在妳需要實現半透明效果時,發現壹切都不是那麽美好了。如果妳繪制了壹個近距離的半透明物體,則它在深度緩沖區內保留了壹些信息,使得遠處的物體將無法再被繪制出來。雖然半透明的物體仍然半透明,但透過它看到的卻不是正確的內容了。

要 解決以上問題,需要在繪制半透明物體時將深度緩沖區設置為只讀,這樣壹來,雖然半透明物體被繪制上去了,深度緩沖區還保持在原來的狀態。如果再有壹個物體 出現在半透明物體之後,在不透明物體之前,則它也可以被繪制(因為此時深度緩沖區中記錄的是那個不透明物體的深度)。以後再要繪制不透明物體時,只需要再 將深度緩沖區設置為可讀可寫的形式即可。嗯?妳問我怎麽繪制壹個壹部分半透明壹部分不透明的物體?這個好辦,只需要把物體分為兩個部分,壹部分全是半透明 的,壹部分全是不透明的,分別繪制就可以了。

即使使用了以上技巧,我們仍然不能隨心所欲的按照混亂順序來進行繪制。必須是先繪制不透明的物體,然 後繪制透明的物體。否則,假設背景為藍色,近處壹塊紅色玻璃,中間壹個綠色物體。如果先繪制紅色半透明玻璃的話,它先和藍色背景進行混合,則以後繪制中間 的綠色物體時,想單獨與紅色玻璃混合已經不能實現了。

總結起來,繪制順序就是:首先繪制所有不透明的物體。如果兩個物體都是不透明的,則誰先誰後 都沒有關系。然後,將深度緩沖區設置為只讀。接下來,繪制所有半透明的物體。如果兩個物體都是半透明的,則誰先誰後只需要根據自己的意願(註意了,先繪制 的將成為“目標顏色”,後繪制的將成為“源顏色”,所以繪制的順序將會對結果造成壹些影響)。最後,將深度緩沖區設置為可讀可寫形式。

調用glDepthMask(GL_FALSE);可將深度緩沖區設置為只讀形式。調用glDepthMask(GL_TRUE);可將深度緩沖區設置為可讀可寫形式。

壹 些網上的教程,包括大名鼎鼎的NeHe教程,都在使用三維混合時直接將深度緩沖區禁用,即調用glDisable(GL_DEPTH_TEST);。這樣 做並不正確。如果先繪制壹個不透明的物體,再在其背後繪制半透明物體,本來後面的半透明物體將不會被顯示(被不透明的物體遮住了),但如果禁用深度緩沖, 則它仍然將會顯示,並進行混合。NeHe提到某些顯卡在使用glDepthMask函數時可能存在壹些問題,但可能是由於我的閱歷有限,並沒有發現這樣的 情況。

那麽,實際的演示壹下吧。我們來繪制壹些半透明和不透明的球體。假設有三個球體,壹個紅色不透明的,壹個綠色半透明的,壹個藍色半透明的。紅色最遠,綠色 在中間,藍色最近。根據前面所講述的內容,紅色不透明球體必須首先繪制,而綠色和藍色則可以隨意修改順序。這裏為了演示不註意設置深度緩沖的危害,我們故 意先繪制最近的藍色球體,再繪制綠色球體。

為了讓這些球體有壹點立體感,我們使用光照。在(1, 1, -1)處設置壹個白色的光源。代碼如下:

void setLight(void)

{

static const GLfloat light_position[] = {1.0f, 1.0f, -1.0f, 1.0f};

static const GLfloat light_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};

static const GLfloat light_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};

static const GLfloat light_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};

glLightfv(GL_LIGHT0, GL_POSITION, light_position);

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);

glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);

glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);

glEnable(GL_LIGHT0);

glEnable(GL_LIGHTING);

glEnable(GL_DEPTH_TEST);

}

每壹個球體顏色不同。所以它們的材質也都不同。這裏用壹個函數來設置材質。

void setMatirial(const GLfloat mat_diffuse[4], GLfloat mat_shininess)

{

static const GLfloat mat_specular[] = {0.0f, 0.0f, 0.0f, 1.0f};

static const GLfloat mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);

glMaterialf (GL_FRONT, GL_SHININESS, mat_shininess);

}

有了這兩個函數,我們就可以根據前面的知識寫出整個程序代碼了。

坐標是可以設置的。OpenGL默認坐標系的確是樓上兩位說的那樣,但是我本人更習慣Z軸垂直顯示器平面向內,所以把它修改掉了。

glOrtho(-1, 1, -1, 1, 1, -1); // 默認情形

glOrtho(-1, 1, -1, 1, -1, 1); // 我設置的情形

這裏只給出了繪制的部分,其它部分大家可以自行完成。

void myDisplay(void)

{

// 定義壹些材質顏色

const static GLfloat red_color[] = {1.0f, 0.0f, 0.0f, 1.0f};

const static GLfloat green_color[] = {0.0f, 1.0f, 0.0f, 0.3333f};

const static GLfloat blue_color[] = {0.0f, 0.0f, 1.0f, 0.5f};

// 清除屏幕

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// 啟動混合並設置混合因子

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

// 設置光源

setLight();

// 以(0, 0, 0.5)為中心,繪制壹個半徑為.3的不透明紅色球體(離觀察者最遠)

setMatirial(red_color, 30.0);

glPushMatrix();

glTranslatef(0.0f, 0.0f, 0.5f);

glutSolidSphere(0.3, 30, 30);

glPopMatrix();

// 下面將繪制半透明物體了,因此將深度緩沖設置為只讀

glDepthMask(GL_FALSE);

// 以(0.2, 0, -0.5)為中心,繪制壹個半徑為.2的半透明藍色球體(離觀察者最近)

setMatirial(blue_color, 30.0);

glPushMatrix();

glTranslatef(0.2f, 0.0f, -0.5f);

glutSolidSphere(0.2, 30, 30);

glPopMatrix();

// 以(0.1, 0, 0)為中心,繪制壹個半徑為.15的半透明綠色球體(在前兩個球體之間)

setMatirial(green_color, 30.0);

glPushMatrix();

glTranslatef(0.1, 0, 0);

glutSolidSphere(0.15, 30, 30);

glPopMatrix();

// 完成半透明物體的繪制,將深度緩沖區恢復為可讀可寫的形式

glDepthMask(GL_TRUE);

glutSwapBuffers();

}

大家也可以將上面兩處glDepthMask刪去,結果會看到最近的藍色球雖然是半透明的,但它的背後直接就是紅色球了,中間的綠色球沒有被正確繪制。

小結:

本課介紹了OpenGL混合功能的相關知識。

混合就是在繪制時,不是直接把新的顏色覆蓋在原來舊的顏色上,而是將新的顏色與舊的顏色經過壹定的運算,從而產生新的顏色。新的顏色稱為源顏色,原來舊的顏色稱為目標顏色。傳統意義上的混合,是將源顏色乘以源因子,目標顏色乘以目標因子,然後相加。

源 因子和目標因子是可以設置的。源因子和目標因子設置的不同直接導致混合結果的不同。將源顏色的alpha值作為源因子,用1.0減去源顏色alpha值作 為目標因子,是壹種常用的方式。這時候,源顏色的alpha值相當於“不透明度”的作用。利用這壹特點可以繪制出壹些半透明的物體。

在進行混合時,繪制的順序十分重要。因為在繪制時,正要繪制上去的是源顏色,原來存在的是目標顏色,因此先繪制的物體就成為目標顏色,後來繪制的則成為源顏色。繪制的順序要考慮清楚,將目標顏色和設置的目標因子相對應,源顏色和設置的源因子相對應。

在進行三維混合時,不僅要考慮源因子和目標因子,還應該考慮深度緩沖區。必須先繪制所有不透明的物體,再繪制半透明的物體。在繪制半透明物體時前,還需要將深度緩沖區設置為只讀形式,否則可能出現畫面錯誤。

簡單的透明

OpenGL中的絕大多數特效都和某些類型的(色彩)混合有關。

混色的定義為,將某個象素的顏色和已繪制在屏幕上和其對應的象素顏色相互結合。

至於怎麽結合這兩個顏色則依賴於顏色的alpha通道的分量值,及/或所使用的混色函數。

Alpha通常是位於顏色值末尾的第4個顏色組成分量。

前面這些課我們都是用GL_RGB來指定顏色的三個分量。

相應的GL_RGBA能指定alpha分量的值。

更進壹步,我們能使用glColor4f()來代替glColor3f()。

絕大多數人都認為Alpha分量代表材料的透明度。

這就是說,alpha值為0.0時所代表的材料是完全透明的。

alpha值為1.0時所代表的材料則是完全不透明的。

混色的公式

若妳對數學不感冒,而只想看看怎麽實現透明,請跳過這壹節。

若妳想深入理解(色彩)混合的工作原理,這壹節應該適合妳吧。

『CKER的補充:其實並不難^-^。原文中的公式如下,CKER再嘮叨壹下吧。

其實混合的基本原理是就將要分色的圖像各象素的顏色及背景顏色均按照RGB規則各自分離之後,

根據-圖像的RGB顏色分量*alpha值+背景的RGB顏色分量*(1-alpha值)

-這樣壹個簡單公式來混合之後,最後將混合得到的RGB分量重新合並。』

公式如下:

(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)

OpenGL按照上面的公式計算這兩個象素的混色結果。

小寫的s和r分別代表源象素和目標象素。大寫的S和D則是相應的混色因子。

這些決定了妳怎麽對這些象素混色。

絕大多數情況下,各顏色通道的alpha混色值大小相同,

這樣對源象素就有 (As, As, As, As),

目標象素則有1, 1, 1, 1) - (As, As, As, As)。

上面的公式就成了下面的模樣:

(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As))

這個公式會生成透明/半透明的效果。

OpenGL中的混色

在OpenGL中實現混色的步驟類似於我們以前提到的OpenGL過程。

接著設置公式,並在繪制透明對象時關閉寫深度緩存。

因為我們想在半透明的圖像背後繪制 對象。

這不是正確的混色方法,但絕大多數時候這種做法在簡單的項目中都工作的非常好。

Rui Martins 的補充: 正確的混色過程應該是先繪制全部的場景之後再繪制透明的圖像。

並且要按照和深度緩存相反的次序來繪制(先畫最遠的物體)。

考慮對兩個多邊形(1和2)進行alpha混合,不同的繪制次序會得到不同的結果。

(這裏假定多邊形1離觀察者最近,那麽正確的過程應該先畫多邊形2,再畫多邊形1。

正如妳再現實中所見到的那樣,

從這兩個<透明的>多邊形背後照射來的光線總是先穿過多邊形2,

再穿過多邊形1,最後才到達觀察者的眼睛。)

在深度緩存啟用時,妳應該將透明圖像按照深度進行排序,

並在全部場景繪制完畢之後再繪制這些透明物體。否則妳將得到不正確的結果。

我知道某些時候這樣做是非常令人痛苦的,但這是正確的方法。

我們將使用第七課的代碼。

壹開始先在代碼開始處增加兩個新的變量。出於清晰起見,我重寫了整段代碼。

}

Var

h_RC : HGLRC; // Rendering Context(著色描述表)。

h_DC : HDC; // Device Context(設備描述表)

h_Wnd : HWND; // 窗口句柄

h_Instance : HINST; // 程式Instance(實例)。

keys : Array[0..255] Of Boolean; // 用於鍵盤例程的數組

light : Boolean; // 光源的開/關

blend : Boolean; // Blending OFF/ON? ( 新增 )

lp : Boolean; // L鍵按下了麽?

fp : Boolean; // F鍵按下了麽?

bp : Boolean; // B 鍵按下了麽? ( 新增 )

xrot : GLfloat; // X 旋轉

yrot : GLfloat; // Y 旋轉

xspeed : GLfloat; // X 旋轉速度

yspeed : GLfloat; // Y 旋轉速度

z : GLfloat = -5.0 f; // 深入屏幕的距離

LightAmbient : Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0); //環境光參數 ( 新增 )

LightDiffuse : Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0); // 漫射光參數 ( 新增 )

LightPosition : Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0); // 光源位置 ( 新增 )

filter : GLuint; // 濾波類型

texture : Array[0..2] Of GLuint; // 3種紋理的儲存空間

Procedure glGenTextures(n: GLsizei; Var textures: GLuint); stdcall; external

opengl32;

Procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external

opengl32;

Function gluBuild2DMipmaps(target: GLenum; components, width, height: GLint;

format, atype: GLenum; data: Pointer): Integer; stdcall; external glu32 name

gluBuild2DMipmaps;

{

然後往下移動到 LoadGLTextures() 這裏。

找到 if (TextureImage[0]=LoadBMP(Data/Crate.bmp))

這壹行。我們目前使用有色玻璃紋理來代替上壹課中的木箱紋理。

if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // 載入玻璃位圖 ( 已修改 )

}

Function LoadTexture: boolean; // 載入位圖並轉換成紋理

Var

Status : boolean; // Status 指示器

TextureImage : Array[0..1] Of PTAUX_RGBImageRec; // 創建紋理的存儲空間

Begin

Status := false;

ZeroMemory(@TextureImage, sizeof(TextureImage)); // 將指針設為 NULL

TextureImage[0] := LoadBMP(Walls.bmp);

If TextureImage[0] <> Nil Then

Begin

Status := TRUE; // 將 Status 設為 TRUE

glGenTextures(1, texture[0]); // 創建紋理

// 創建 Nearest 濾波貼圖

glBindTexture(GL_TEXTURE_2D, texture[0]);

// 生成紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // ( 新增 )

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // ( 新增 )

glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,

TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,

TextureImage[0].data);

glBindTexture(GL_TEXTURE_2D, texture[1]); // 使用來自位圖數據生成 的典型紋理

// 生成紋理

glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,

TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,

TextureImage[0].data);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 線形濾波

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 線形濾波

// 創建 MipMapped 紋理

glBindTexture(GL_TEXTURE_2D, texture[2]);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,

GL_LINEAR_MIPMAP_NEAREST); // ( 新增 )

gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,

TextureImage[0].sizey, GL_RGB, GL_UNSIGNED_BYTE,

TextureImage[0].data); //(新增) }

End;

If assigned(TextureImage[0]) Then // 紋理是否存在

If assigned(TextureImage[0].data) Then // 紋理圖像是否存在

TextureImage[0].data := Nil; // 釋放紋理圖像占用的內存

TextureImage[0] := Nil; // 釋放圖像結構

result := Status; // 返回 Status

End;

{

在glInit()代碼段加入以下兩行。

第壹行以全亮度繪制此物體,並對其進行50%的alpha混合(半透明)。

當混合選項打開時,此物體將會產生50%的透明效果。

第二行設置所采用的混合類型。

Rui Martins 的補充:

alpha通道的值為 0.0意味著物體材質是完全透明的。

1.0 則意味著完全不透明。

}

End;

不過怎樣才能在使用紋理貼圖的時候指定混合時的顏色呢?非常簡單,

在調整貼圖模式時,文理貼圖的每個象素點的顏色都是由alpha通道參數

和當前地象素顏色相乘所得到的。

比如,繪制的顏色是 (0.5, 0.6, 0.4),

我們會把顏色相乘得到(0.5, 0.6, 0.4, 0.2)

(alpha參數在沒有指定時,缺省為零)。

就是如此!OpenGL實現Alpha混合的確非常簡單!

}

{

原文註 (11/13/99)

我(NeHe)混色代碼進行了修改,以使顯示的物體看起來更逼真。

同時對源象素和目的象素使用alpha參數來混合,會導致物體的人造痕跡看起來非常明顯。

會使得物體的背面沿著側面的地方顯得更暗。

基本上物體會看起來非常怪異。

我所用的混色方法也許不是最佳的,但的確能夠工作。

啟用光源之後,物體看起來非常逼真。

感謝Tom提供的原始代碼,他采用的混色方法是正確的,

但物體看起來並不象所期望的那樣吸引人:)

代碼所作的再次修改是因為在某些顯卡上glDepthMask()函數存在尋址問題。

這條命令在某些卡上啟用或關閉深度緩沖測試時似乎不是非常有效,

所以我已將啟用或關閉深度緩沖測試的代碼轉成老式的glEnable和glDisable。

紋理貼圖的Alpha混合

用於紋理貼圖的alpha參數能象顏色相同從問題貼圖中讀取。

方法如下,妳需要在載入所需的材質同時取得其的alpha參數。

然後在調用glTexImage2D()時使用GL_RGBA的顏色格式。

}

  • 上一篇:十三釵徐子晏怎麽死的
  • 下一篇:SysTreeView32 是什麽東東?如何操作
  • copyright 2024編程學習大全網