學習OpenGL ES之透明和混合

2021-09-11 14:11:27 字數 3061 閱讀 9489

本文主要講解opengl es對於透明顏色的處理,在例子中我繪製了三個平面,分別賦予綠色半透明紋理,紅色半透明紋理,和不透明紋理。

首先為這三張圖生成紋理。

- (void)gentexture 

複製**

接著將繪製平面的**用乙個方法封裝。

- (void)drawplaneat:(glkvector3)position texture:(glktextureinfo *)texture 

// 繫結紋理

gluint diffusemapuniformlocation = glgetuniformlocation(self.shaderprogram, "diffusemap");

glactivetexture(gl_texture0);

glbindtexture(gl_texture_2d, texture.name);

gluniform1i(diffusemapuniformlocation, 0);

[self drawrectangle];

}複製**

我要繪製三個平面,並且位置不一樣,只要呼叫三次上面的方法就可以了。具體繪製**如下。

- (void)glkview:(glkview *)view drawinrect:(cgrect)rect 

複製**

根據繪製平面z軸的位置,紅色平面在最下,不透明的在中間,綠色透明的在最上面。效果如下。

明顯沒有任何透明效果,如果要開啟對透明的支援,需要呼叫glenable(gl_blend);glblendfunc(gl_src_alpha, gl_one_minus_src_alpha);。我在glbaseviewcontrollersetupcontext中設定了這兩項。

- (void)setupcontext 

glkview *view = (glkview *)self.view;

view.context = self.context;

view.drawabledepthformat = glkviewdrawabledepthformat24;

view.drawablemultisample = glkviewdrawablemultisample4x;

[eaglcontext setcurrentcontext:self.context];

// 設定opengl狀態

glenable(gl_depth_test);

glenable(gl_blend);

glblendfunc(gl_src_alpha, gl_one_minus_src_alpha);

}複製**

glenable(gl_blend);開啟了顏色混合,glblendfunc(gl_src_alpha, gl_one_minus_src_alpha);指定了混合方式。混合方式中有兩個決定因素,將要混合的畫素顏色的比例fs和當前緩衝區畫素顏色比例fd,fsfd是四維向量(fr, fg, fb, fa)fr, fg, fb, fa分別代表每個顏色通道的混合比例。我們假定fs = (fsr, fsg, fsb, fsa)fd = (fdr, fdg, fdb, fda),緩衝區畫素顏色為(dr, dg, db, da),要混合的畫素顏色為(sr, sg, sb, sa)(kr, kg, kb, ka)是每個通道的最大值。那麼最終畫素值為:

r = min(kr, fsrsr + fdrdr)

g = min(kg, fsgsg + fdgdg)

b = min(kb, fsbsb + fdbdb)

a = min(ka, fsasa + fdada)

複製**

下面是每個混合比例列舉對應的值,其中rs,gs,bs,as是要混合的畫素顏色,rd,gd,bd,ad是緩衝區中畫素的顏色。(kr, kg, kb, ka)是每個通道的最大值。以glblendfunc(gl_src_alpha, gl_one_minus_src_alpha);為例,fs就是as/ka, as/ka, as/ka, as/ka,fd就是1 - as/ka, 1 - as/ka, 1 - as/ka, 1 - as/ka。假設要混合的畫素alpha值為0.4,那麼最終的顏色就是0.4乘以要混合的畫素顏色加上0.6乘以緩衝區的畫素顏色。

glblendfunc(gl_src_alpha, gl_one_minus_src_alpha);設定後效果如下。

綠色透明平面和不透明的平面很好的混合了,但是和紅色平面重疊的部分卻有問題,重疊部分紅色平面完全消失了。這是因為我們啟用了深度測試,紅色平面在綠色平面後面的部分在混合之前就已經被忽略掉了。為了解決這個問題,有個通用的辦法,先繪製不透明物體,然後再繪製透明物體。繪製透明物體的時候設定gldepthmask(false);gldepthmask為false時會禁止把當前的畫素深度值寫到深度緩衝區中,也就是說繪製透明物體的時候,深度測試永遠都是和同乙個深度值進行測試,也就不會存在透明物體之間相互遮擋的問題了。

啟用深度測試,每個畫素寫入緩衝區時也會寫入z軸對應的深度,寫入前會和當前的深度值對比,如果在當前深度的後面,就捨棄掉這個畫素。

下面是實現的**。

- (void)glkview:(glkview *)view drawinrect:(cgrect)rect 

複製**

效果如下。

學習OpenGL ES之ShadowMap 一

我們在了解shadowmap這項技術之前,先來了解一下什麼是陰影。在現實生活中,陰影伴隨著光而生。下面這張圖演示了在平行光下,影子是如何形成的。圖中的兩個物體,在光照方向上,距離光源最近的那些點會被照亮,之後的點則不會接受到光照。所以判斷乙個點是否在陰影中的關鍵就是,它是否是光照方向上距離光源最近的...

學習OpenGL ES之繪製地形

地形模型一般是由nxn的網格構成,網格的點在y軸上的座標由灰度地形圖上相應的顏色決定。顏色越亮,高度越高。顏色每個通道的取值範圍可以是0 255,通過公式轉換,可以很容易的控制生成模型的高度。上篇文章中,我們使用三角帶生成圓柱體的中間部分。現在我們要用多個三角帶來生成地形。如何生成單個三角帶我就不贅...

學習OpenGL ES之繪製圓柱體

為了更方便的進行頂點資料的管理,我建立了乙個glgeometry類。typedef enum nsuinteger glgeometrytype typedef struct glvertex inte ce glgeometry property strong,nonatomic nsmutabl...