android為openGL ES支持提供了GLSurfaceView組件, 這個(gè)組件用于顯示3D圖形。GLSufaceView本身并不提供繪制3D圖形的功能,而是由GLSurfaceView.Renderer來(lái)完成了SurfaceView中3D圖形的繪制。歸納起來(lái),在android中使用openGl ES需要三個(gè)步驟:1,創(chuàng)建GLSurfaceView組件,使用activity來(lái)顯示GlSufaceView組件2. 為GLSufaceView組件創(chuàng)建GLSufaceView.Renderer實(shí)例,實(shí)現(xiàn)GLSurfaceView.Renderer類時(shí)需要實(shí)現(xiàn)接口里的三個(gè)方法。 (1) abstract void onDrawFrame(GL10 gl): Renderer對(duì)象調(diào)用該方法繪制GLSurfaceView的當(dāng)前幀。 (2)abstract void onSurfaceChanged(GL10 gl, int width, int height):當(dāng)GLSurfaceView的大小改變時(shí)回調(diào)該方法。 (3)abstract void onSufaceCreated(GL10 gl, EGLConfig config):當(dāng)GLSurfaceView被創(chuàng)建時(shí)回調(diào)該方法。3.調(diào)用GLSurfaceView組件的setRender()方法指定Renderer對(duì)象。該Renderer對(duì)象完成GLSurfaceView里3D圖形的繪制。從上面的介紹不難看出,實(shí)際上繪制3D圖像的難點(diǎn)不是如何使用GLSurface組件,而是如何實(shí)現(xiàn)Renderer類。是想Renderer類時(shí)需要三個(gè)方法。這三個(gè)方法都有一個(gè)GL10形參,他就代表了GLOpen ES的“繪制畫(huà)筆”, 讀者可以把它想象成Swing 2D繪圖中的Graphics,也就是想象成android2D繪圖中的Canvas組件-當(dāng)我們希望Renderer繪制3D圖像時(shí),實(shí)際上是調(diào)用GL10的方法來(lái)進(jìn)行繪制的。 當(dāng)SurfaceView被創(chuàng)建時(shí),系統(tǒng)會(huì)回調(diào)Rnderer對(duì)象的onSurfaceCreated()方法,該方法可以對(duì)OpenGL ES執(zhí)行一些無(wú)須任何改變的初始化,例如如下代碼:
@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {//關(guān)閉抗抖動(dòng)gl.glDisable(GL10.GL_DITHER);//設(shè)置系統(tǒng)對(duì)透視進(jìn)行修正gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);gl.glClearColor(0, 0, 0, 0);//設(shè)置陰影平滑模式gl.glShadeModel(GL10.GL_SMOOTH);//啟用深度測(cè)試gl.glEnable(GL10.GL_DEPTH_TEST);//設(shè)置深度測(cè)試的類型gl.glDepthFunc(GL10.GL_LEQUAL);}Gl10就是OpenGL ES的繪圖接口,雖然這里看到的是一個(gè)GL10,但實(shí)際上它也是GL11的實(shí)例,讀者可通過(guò)(gl instandeof GL11)判斷他是否為GL11接口的實(shí)例。上面的方法中用到了一些初始化方法,關(guān)于這些方法的說(shuō)明如下:(1)glDisable(int cap) : 該方法用于禁用OpenGL ES某個(gè)方面的特性。 該方法中第一行代碼用于關(guān)閉抗抖動(dòng),這樣可以提高性能。(2)glHint(int target, int mode):該方法用于對(duì)OpenGL ES某方面進(jìn)行校正。(3)clearColor(float red, float green, float alpha):該方法設(shè)置OpenGl ES"清屏"所用的顏色,四個(gè)參數(shù)分別設(shè)置紅、綠、藍(lán)、透明值:0為最小值,1為最大值。例如gl.glClearColor(0, 0, 0, 0);就是用黑色“清屏”。(4) glShadeModel(int mode): 該方法用于設(shè)置OpenGl ES的陰影模式。此處設(shè)置為平滑模式。 (5) glEnable(int cap): 該方法與glDisable(int cap)方法相對(duì), 用于啟用OpenGL ES某些特性。此處用于啟動(dòng)OpenGL ES的深度測(cè)試。所謂深度測(cè)試。就是讓OpenGL ES負(fù)責(zé)跟蹤每個(gè)物體在Z軸的深度,這樣就可避免后面的物體遮擋前面的物體。當(dāng)SurfaceView組件的大小發(fā)生改變時(shí),系統(tǒng)會(huì)回調(diào)Renderer對(duì)象的onSurfaceChanged()方法, 因此該方法通常用于初始化3D場(chǎng)景,例如如下初始化代碼:
@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {//設(shè)置3D視窗的大小及位置gl.glViewport(0, 0, width, height);//將當(dāng)前矩陣模式設(shè)置為投影矩陣gl.glMatrixMode(GL10.GL_PROJECTION);//初始化單位矩陣gl.glLoadIdentity();//計(jì)算透視視窗的高度、高度比f(wàn)loat ratio = (float)width / height;//調(diào)用此方法設(shè)置透視窗視窗的空間大小gl.glFrustumf(-ratio, ratio, -1, 0, 1, 10);}上面的方法中用到了GL10的一些初始化方法,關(guān)于這些方法的說(shuō)明如下。(1) glViewport(int x, int y, int width, int height): 設(shè)置3D視窗的位置與大小,其中前兩個(gè)參數(shù)指定該視窗的位置,后面兩個(gè)參數(shù)指定該視窗的寬、高。(2) glMatrixMode(int mode): 設(shè)置視窗的矩陣模型,通??山邮蹽L10.GL_PROJECTION、 GL10.GL_MODELVIEW兩個(gè)常量值。當(dāng)調(diào)用gl.glMatrixMode(GL10.GL_PROJECTION);代碼后,指定將屏幕設(shè)為透視圖(要想看到逼真的三維物體,這是必要的), 這意味著越遠(yuǎn)的東西看起來(lái)越?。划?dāng)調(diào)用gl.glMatrixMode(GL10.GL_MODELVIEW);代碼后,即將當(dāng)前矩陣模式設(shè)為模型視圖矩陣,這意味著任何新的變換都會(huì)影響該矩陣的所有物體。 (3)glLoaddentity():相當(dāng)于reset()方法,用于初始化單位矩陣。 (4)glFrustumfglFrustumf(float left, float right, float bottom, float top, float zNear, float zFar): 用于設(shè)置透視投影的空間大小,前面兩個(gè)參數(shù)用于設(shè)置X軸上的最小坐標(biāo)值、最大坐標(biāo)值,中間的兩個(gè)參數(shù)用于設(shè)置Y軸的最小坐標(biāo)值、最大坐標(biāo)值; 后面兩個(gè)參數(shù)用于設(shè)置Z軸上所能繪制的場(chǎng)景的深度的最小值、最大值。例如我們調(diào)用如下代碼:
gl.glFrustumf(-0.8f, 0.8f, -1f, 1f, 1f, 10f);這意味著如果有一個(gè)二維矩形,它的四個(gè)頂點(diǎn)的坐標(biāo)分別為:(-0.8, 1)、 (0.8,1)、(0.8, -1)、(-0.8, -1),這個(gè)矩形將會(huì)占滿整個(gè)視窗。提示:前面已經(jīng)指出:三維坐標(biāo)系統(tǒng)與二維坐標(biāo)系統(tǒng)并不相同,二維坐標(biāo)系統(tǒng)上的坐標(biāo)值通常就直接使用系統(tǒng)的像素?cái)?shù)量;但三維坐標(biāo)系統(tǒng)的坐標(biāo)值則取決于glFrustumf()方法的設(shè)置,當(dāng)我們調(diào)用gl.glFrustumf(-0.8f, 0.8f, -1f, 1f, 1f, 10f);方法時(shí),意味著該三維坐標(biāo)系統(tǒng)的最左邊的坐標(biāo)值為-0.8,最右邊的坐標(biāo)值為0.8;Y軸最上面的坐標(biāo)值為1.0,最下面的坐標(biāo)值為-1.0GlSurfaceView上的所有3D圖形都是由Renderer的onDrawFrame(GL10 gl)方法繪制出來(lái)的,重寫(xiě)該方法時(shí)就要把所有的3D圖形都繪制出來(lái),該方法通常如下形式開(kāi)始:
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);...接下來(lái)在onDrawFrame方法中就可以調(diào)用GL10的方法開(kāi)始繪制了。繪制平面上的多邊形調(diào)用GL10圖形繪制2D圖形的步驟如下:(1)調(diào)用GL10的glEnableClientState(GL10.GL_VERTEX_ARRAY);方法啟用頂點(diǎn)坐標(biāo)數(shù)組。(2)調(diào)用GL10的glEnableClientState(GL10.GL_COLOR_ARRAY);方法啟用頂點(diǎn)顏色數(shù)組。(3)調(diào)用GL10的glVertexPointer(int size, int type, int stride, Buffer pointer)方法設(shè)置頂點(diǎn)的位置數(shù)據(jù)。這個(gè)方法中pointer參數(shù)用于指定頂點(diǎn)坐標(biāo)值,但這里并未使用三維數(shù)組來(lái)指定每個(gè)頂點(diǎn)X、Y、Z坐標(biāo)值,point依然是一個(gè)一維數(shù)組,也就是該數(shù)組將會(huì)包含3N個(gè)數(shù)值,每三個(gè)值指定一個(gè)頂點(diǎn)的X、Y、Z坐標(biāo)值。 第一個(gè)參數(shù)size指定多少個(gè)元素指定一個(gè)頂點(diǎn)位置,該size參數(shù)通常總是3;type參數(shù)指定頂點(diǎn)值的類型,如果頂點(diǎn)坐標(biāo)值為float類型,則指定為GL10.GL_FLOAT;如果頂點(diǎn)坐標(biāo)值為整數(shù),則指定為GL10.GL_FIXED.(4)調(diào)用GL10的glColorPoint(int size, int type, int stride, Buffer pointer)方法設(shè)置頂點(diǎn)的顏色數(shù)據(jù)。 point依然是一維數(shù)組,每四個(gè)值指定一個(gè)頂點(diǎn)的紅、綠、藍(lán)、透明度的顏色值。第一個(gè)參數(shù)size指定多少個(gè)元素指定一個(gè)頂點(diǎn)位置,該size參數(shù)通??偸?, type參數(shù)指定頂點(diǎn)坐標(biāo)值的類型,如果頂點(diǎn)坐標(biāo)值為float類型,則指定為GL10.GL_FLOAT;如果頂點(diǎn)坐標(biāo)值為整數(shù),則指定為GL10.GL_FIXED.(5),調(diào)用GL10的glDrawArrays(int mode, int first, int count)方法繪制平面,該方法第一個(gè)參數(shù)用于指定繪制圖形的類型,第二個(gè)參數(shù)指定從哪個(gè)頂點(diǎn)開(kāi)始繪制,第三個(gè)參數(shù)指定總共繪制的頂點(diǎn)數(shù)量。(6),繪制完成后,調(diào)用GL10的glFinish()方法結(jié)束繪制;并調(diào)用glDisableClientState(int)方法來(lái)停用頂點(diǎn)坐標(biāo)數(shù)據(jù)、頂點(diǎn)顏色數(shù)據(jù)。
聯(lián)系客服