第八課:混合
混合:
在這一課裡,我們在紋理的基礎上加上了混合,它看起具有透明的效果,當然解釋它不是那麼容易,當希望你喜歡它。
簡單的透明
opengl中的絕大多數特效都與某些型別的(色彩)混合有關。混色的定義為,將某個象素的顏色和已繪製在螢幕上與其對應的象素顏色相互結合。至於如何結合這兩個顏色則依賴於顏色的alpha通道的分量值,以及/或者所使用的混色函式。alpha通常是位於顏色值末尾的第4個顏色組成分量。前面這些課我們都是用gl_rgb來指定顏色的三個分量。相應的gl_rgba可以指定alpha分量的值。更進一步,我們可以使用glcolor4f()來代替glcolor3f()。
絕大多數人都認為alpha分量代表材料的透明度。這就是說,alpha值為0.0時所代表的材料是完全透明的。alpha值為1.0時所代表的材料則是完全不透明的。
混色的公式
若您對數學不感冒,而只想看看如何實現透明,請跳過這一節。若您想深入理解(色彩)混合的工作原理,這一節應該適合您吧。
公式如下:
(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過程。接著設定公式,並在繪製透明物件時關閉寫深度快取。因為我們想在半透明的圖形背後繪製 物件。這不是正確的混色方法,但絕大多數時候這種做法在簡單的專案中都工作的很好。
考慮對兩個多邊形(1和2)進行alpha混合,不同的繪製次序會得到不同的結果。(這裡假定多邊形1離觀察者最近,那麼正確的過程應該先畫多邊形2,再畫多邊形1。正如您再現實中所見到的那樣,從這兩個《透明的》多邊形背後照射來的光線總是先穿過多邊形2,再穿過多邊形1,最後才到達觀察者的眼睛。)
在深度快取啟用時,您應該將透明圖形按照深度進行排序,並在全部場景繪製完畢之後再繪製這些透明物體。否則您將得到不正確的結果。我知道某些時候這樣做是很令人痛苦的,但這是正確的方法。
我們將使用第七課的**。一開始先在**開始處增加兩個新的變數。出於清晰起見,我重寫了整段**。
bool blend; // 是否混合?
bool bp; // b 鍵按下了麼?
然後往下移動到 loadgltextures() 這裡。找到" if (textureimage[0]=loadbmp("data/crate.bmp")) "這一行。我們現在使用有色玻璃紋理來代替上一課中的木箱紋理。
if (textureimage[0]=loadbmp("data/glass.bmp")) // 載入玻璃位圖
在initgl()**段加入以下兩行。第一行以全亮度繪製此物體,並對其進行50%的alpha混合(半透明)。當混合選項開啟時,此物體將會產生50%的透明效果。第二行設定所採用的混合型別。
rui martins 的補充: alpha通道的值為 0.0意味著物體材質是完全透明的。1.0 則意味著完全不透明。
glcolor4f(1.0f,1.0f,1.0f,0.5f); // 全亮度, 50% alpha 混合
glblendfunc(gl_src_alpha,gl_one); // 基於源象素alpha通道值的半透明混合函式
在接近第七課結尾處的地方找到下面的**段。
if (keys[vk_left]) // left方向鍵按下了麼?
接著上面的**,我們增加如下的**。這幾行監視b鍵是否按下。如果是的話,計算機檢查混合選項是否已經開啟。然後將其置為相反的狀態。
if (keys['b'] && !bp) // b 健按下且bp為 false麼?
else// 否則 }
if (!keys['b'])// b 鍵鬆開了麼?
但是怎樣才能在使用紋理貼圖的時候指定混合時的顏色呢?很簡單,在調整貼圖模式時,文理貼圖的每個象素點的顏色都是由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的顏色格式。
NeHe OpenGL第八課 混合
nehe opengl第八課 混合 混合 在這一課裡,我們在紋理的基礎上加上了混合,它看起具有透明的效果,當然解釋它不是那麼容易,當希望你喜歡它。簡單的透明 opengl中的絕大多數特效都與某些型別的 色彩 混合有關。混色的定義為,將某個象素的顏色和已繪製在螢幕上與其對應的象素顏色相互結合。至於如何...
第八課 混合
第八課 混合 opengl中的混色 在opengl中實現混色的步驟類似於我們以前提到的opengl過程。接著設定公式,並在繪製透明物件時關閉寫深度快取。因為我們想在半透明的圖形背後繪製 物件。這不是正確的混色方法,但絕大多數時候這種做法在簡單的專案中都工作的很好。rui martins 的補充 正確...
第八課 陣列
1 宣告 int arr string str 2 分配空間 arr new int 5 3 宣告同時分配記憶體 int arr new int 5 4 初始化 int arr new int 5 int arr2 1 宣告 int arr string str 2 分配空間 1 直接為每一維分配空...