本文主要講解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);
。我在glbaseviewcontroller
的setupcontext
中設定了這兩項。
- (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
,fs
和fd
是四維向量(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...