




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
本章要求:第12章
利用OpenGL實(shí)現(xiàn)3D圖形OpenGL的基本概念構(gòu)建3D開發(fā)的基本框架繪制3D模型為3D圖形添加紋理貼圖效果為3D圖形添加旋轉(zhuǎn)效果為3D圖形添加光照效果為3D圖形添加透明效果12.1OpenGL簡(jiǎn)介12.2繪制3D圖形12.3添加效果12.4綜合實(shí)例——繪制一個(gè)不斷旋轉(zhuǎn)的金字塔第12章
利用OpenGL實(shí)現(xiàn)3D圖形在現(xiàn)在這個(gè)網(wǎng)絡(luò)游戲逐漸盛行的時(shí)代,2D游戲已經(jīng)不能完全滿足用戶的需求,3D技術(shù)已經(jīng)被廣泛的應(yīng)用在PC游戲中,3D技術(shù)下一步將會(huì)肯定向手機(jī)平臺(tái)發(fā)展,而Android系統(tǒng)作為當(dāng)前最流行的手機(jī)操作系統(tǒng),完全內(nèi)置3D技術(shù)——OpenGl支持,本章將對(duì)如何在Android中利用OpenGL實(shí)現(xiàn)3D圖形進(jìn)行詳細(xì)講解。第12章
利用OpenGL實(shí)現(xiàn)3D圖形OpenGL(OpenGraphicsLibrary)是由SGI公司于1992年發(fā)布的,一個(gè)功能強(qiáng)大、調(diào)用方便的底層圖形庫,它為編程人員提供了統(tǒng)一的操作,以便充分利用任何制造商提供的硬件。OpenGL的核心實(shí)現(xiàn)了視區(qū)和光照等我們熟知的概念,并試圖向開發(fā)人員隱藏大部分硬件層。由于OpenGL是專門為工作站設(shè)計(jì)的,它太大了,無法安裝在移動(dòng)設(shè)備上,所以KhronosGroup為OpenGL提供了一個(gè)子集OpenGLES(OpenGLforEmbeddedSystem)。OpenGLES是免費(fèi)的、跨平臺(tái)的、功能完善的2D/3D圖形庫接口API,它專門針對(duì)多種嵌入式系統(tǒng)(包括手機(jī)、PDA和游戲主機(jī)等)而設(shè)計(jì)的,提供一種標(biāo)準(zhǔn)方法來描述在圖形處理器或主CPU上渲染這些圖像的底層硬件。說明:KhronosGroup是一個(gè)圖形軟硬件行業(yè)協(xié)會(huì),該協(xié)會(huì)主要關(guān)注圖形和多媒體方向的開放標(biāo)準(zhǔn)。OpenGLES去除了OpenGL中的glBegin/glEnd,四邊形(GL_QUADS)、多邊形(GL_POLYGONS)等復(fù)雜圖元等許多非絕對(duì)必要的特性。經(jīng)過多年發(fā)展,目前的OpenGLES現(xiàn)在主要有OpenGLES1.x(針對(duì)固定管線硬件)和12.1OpenGL簡(jiǎn)介OpenGLES2.x(針對(duì)可編程管線硬件)兩個(gè)版本。OpenGLES1.0是以O(shè)penGL1.3規(guī)范為基礎(chǔ)的,OpenGLES1.1是以O(shè)penGL1.5規(guī)范為基礎(chǔ)的,OpenGLES2.0則是參照OpenGL2.0規(guī)范定義的,它補(bǔ)充和修改了OpenGLES1.1標(biāo)準(zhǔn)著色器語言及API,將OpenGLES1.1中所有可以用著色器程序替換的功能全部刪除了,這樣可以節(jié)約移動(dòng)設(shè)備的開銷及電力消耗。說明:OpenGLES可以應(yīng)用于很多主流移動(dòng)平臺(tái)上,包括Android、Symbian和iPhone等。Android為OpenGL提供了相應(yīng)的支持,它專門為支持OpenGL提供了android.opengl包。在該包中,GLES10類是為支持OpenGLES1.0而提供的;GLES11類是為支持OpenGLES1.1而提供的,GLES20類是為支持OpenGLES2.0而提供的。其中,OpenGLES2.0是從Android2.2(APILevel8)版本才開始使用的。如果你的應(yīng)用只支持OpenGLES2.0,你必須在該項(xiàng)目的AndroidManifest.xml文件中添加下列設(shè)置:<uses-featureandroid:glEsVersion="0x00020000"android:required="true"/>12.2.1構(gòu)建3D開發(fā)的基本框架12.2.2繪制一個(gè)模型12.2繪制3D圖形OpenGLES一個(gè)最常用的功能就是繪制3D圖形。要繪制3D圖形,大致可以分為兩個(gè)步驟,下面分別進(jìn)行講解。12.2繪制3D圖形構(gòu)建一個(gè)3D開發(fā)的基本框架大致可以分為以下幾個(gè)步驟:(1)創(chuàng)建一個(gè)Activity,并指定該Activity顯示的內(nèi)容是一個(gè)指定了Renderer對(duì)象的GLSurfaceView對(duì)象。例如,創(chuàng)建一個(gè)名稱為MainActivity的Activity,在重寫的onCreate()方法中,創(chuàng)建一個(gè)GLSurfaceView對(duì)象,并為其指定使用的Renderer對(duì)象,再將其設(shè)置為Activity要顯示的內(nèi)容,可以使用下面的代碼:@OverrideprotectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
GLSurfaceView
mGLView=newGLSurfaceView(this); //創(chuàng)建一個(gè)GLSurfaceView對(duì)象
mGLView.setRenderer(newCubeRenderer());//為GLSurfaceView指定使用的Renderer對(duì)象
setContentView(mGLView); //設(shè)置Activity顯示的內(nèi)容為GLSurfaceView對(duì)象}通常情況下,考慮到當(dāng)Activity恢復(fù)和暫停時(shí),GLSurfaceView對(duì)象也恢復(fù)或者暫停,還要重寫Activity的onResume()方法和onPause()方法。例如,12.2.1構(gòu)建3D開發(fā)的基本框架如果一個(gè)Activity使用的GLSurfaceView對(duì)象為mGLView,那么,可以使用以下的重寫onResume()和onPause()方法的代碼: @Override protectedvoidonResume(){
super.onResume();
mGLView.onResume(); } @Override protectedvoidonPause(){
super.onPause();
mGLView.onPause(); }(2)創(chuàng)建實(shí)現(xiàn)GLSurfaceView.Renderer接口的類。在創(chuàng)建該類時(shí),需要實(shí)現(xiàn)接口中的以下3個(gè)方法:publicvoidonSurfaceCreated(GL10
gl,EGLConfig
config):當(dāng)GLSurfaceView被創(chuàng)建時(shí)回調(diào)該方法。publicvoidonDrawFrame(GL10
gl):Renderer對(duì)象調(diào)用該方法繪制GLSurfaceView的當(dāng)前幀。publicvoidonSurfaceChanged(GL10
gl,intwidth,intheight):當(dāng)GLSurfaceView的大小改變時(shí)回調(diào)該方法。例如,創(chuàng)建一個(gè)實(shí)現(xiàn)GLSurfaceView.Renderer接口的類EmptyRenderer,并實(shí)現(xiàn)onSurfaceCreated()、onDrawFrame()和onSurfaceChanged()方法,為窗體設(shè)置背景顏色,具體代碼如下:importjavax.microedition.khronos.egl.EGLConfig;importjavax.microedition.khronos.opengles.GL10;importandroid.opengl.GLSurfaceView;publicclassEmptyRendererimplementsGLSurfaceView.Renderer{ publicvoidonSurfaceCreated(GL10
gl,EGLConfig
config){ //設(shè)置窗體的背景顏色
gl.glClearColor(0.7f,0.7f,0.9f,1.0f); } publicvoidonDrawFrame(GL10
gl){ //重設(shè)背景顏色
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT); } publicvoidonSurfaceChanged(GL10
gl,intwidth,intheight){
gl.glViewport(0,0,width,height); }}當(dāng)窗口被創(chuàng)建時(shí),需要調(diào)用onSurfaceCreated()方法,進(jìn)行一些初始化操作。onSurfaceCreated()方法有一個(gè)GL10類型的參數(shù)gl,gl相當(dāng)于OpenGLES的畫筆。通過它提供的方法不僅可以繪制3D圖形,也可以對(duì)OpenGL進(jìn)行初始化。下面將以表格的形式給出GL10提供的用于進(jìn)行初始化的方法,對(duì)于GL10提供的用于繪制3D圖形的方法將在12.2.2節(jié)進(jìn)行介紹。GL10提供的用于進(jìn)行初始化的方法如表12-1所示。表12-1GL10提供的用于進(jìn)行初始化的方法方
法描
述glClearColor(floatred,floatgreen,floatblue,floatalpha)用于指定清除屏幕時(shí)使用的顏色,4個(gè)參數(shù)分別用于設(shè)置紅、綠、藍(lán)和透明度的值,值的范圍是0.0f~1.0fglDisable(intcap)用于禁用OpenGLES某個(gè)方面的特性。例如,要關(guān)閉抗抖動(dòng)功能,可以使用gl.glDisable(GL10.GL_DITHER);語句glEnable(intcap)用于啟用OpenGLES某個(gè)方面的特性glFrustumf(floatleft,floatright,floatbottom,floattop,floatzNear,floatzFar)用于設(shè)置透視視窗的空間大小glHint(inttarget,intmode)用于對(duì)OpenGLES某個(gè)方面進(jìn)行修正glLoadIdentity()用于初始化單位矩陣glMatrixMode(intmode)用于設(shè)置視圖的矩陣模式。通??梢允褂肎L10.GL_MODELVIEW和GL10.GL_PROJECTION兩個(gè)常量值glShadeModel(intmode)用于設(shè)置OpenGLES的陰影模式。例如,要設(shè)置為平滑模式,可以使用gl.glShadeModel(GL10.GL_SMOOTH);語句glViewport(intx,inty,intwidth,intheight)用于設(shè)置3D場(chǎng)景的大小在基本框架構(gòu)建完成后,我們就可以在該框架的基礎(chǔ)上繪制3D模型了。在OpenGLES中,任何模型都會(huì)被分解為三角形。下面將以繪制一個(gè)2D的三角形為例介紹繪制3D模型的基本步驟。(1)在onSurfaceCreated()方法中,定義頂點(diǎn)坐標(biāo)數(shù)組。例如,要繪制一個(gè)2維的三角形,可以使用以下代碼定義頂點(diǎn)坐標(biāo)數(shù)組: privatefinalIntBuffer
mVertexBuffer; publicGLTriangle(){
intone=65536;
intvertices[]={ 0,one,0, //上頂點(diǎn) -one,-one,0, //左下點(diǎn) one,-one,0 //右下點(diǎn) };
ByteBuffer
vbb=ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer=vbb.asIntBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);}12.2.2繪制一個(gè)模型說明:在默認(rèn)的情況下,OpenGLES采取的坐標(biāo)是[0,0,0](X,Y,Z)表示GLSurfaceView的中心;[1,1,0]表示GLSurfaceView的右上角;[-1,-1,0]表示GLSurfaceView的左下角。(2)在onSurfaceCreated()方法中,應(yīng)用以下代碼啟用頂點(diǎn)坐標(biāo)數(shù)組。gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); //啟用頂點(diǎn)坐標(biāo)數(shù)組(3)在onDrawFrame()方法中,應(yīng)用步驟(1)定義的頂點(diǎn)坐標(biāo)數(shù)組繪制圖形。例如,要繪制一個(gè)三角形可以使用下面的代碼。gl.glVertexPointer(3,GL10.GL_FIXED,0,mVertexBuffer); //為畫筆指定頂點(diǎn)坐標(biāo)數(shù)據(jù)gl.glColor4f(1,0,0,0.5f); //設(shè)置畫筆顏色gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,3); //繪制圖形在了解了應(yīng)用OpenGLES繪制3D圖形的基本步驟后,下面將介紹一個(gè)具體的實(shí)例來介紹如何繪制一個(gè)立方體。【例12-1】在Eclipse中創(chuàng)建Android項(xiàng)目,實(shí)現(xiàn)繪制一個(gè)6個(gè)面采用不同顏色的立方體。(實(shí)例位置:光盤\MR\源碼\第12章\12-1)(1)在默認(rèn)創(chuàng)建的MainActivity中,創(chuàng)建一個(gè)GLSurfaceView類型的成員變量,關(guān)鍵代碼如下:privateGLSurfaceView
mGLView;(2)在重寫的onCreate()方法中,首先創(chuàng)建一個(gè)GLSurfaceView對(duì)象,然后為GLSurfaceView指定使用的Renderer對(duì)象,最后再設(shè)置Activity顯示的內(nèi)容為GLSurfaceView對(duì)象,代碼如下:
@Override protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
mGLView=newGLSurfaceView(this); //創(chuàng)建一個(gè)GLSurfaceView對(duì)象//為GLSurfaceView指定使用的Renderer對(duì)象
mGLView.setRenderer(newCubeRenderer()); //設(shè)置Activity顯示的內(nèi)容為GLSurfaceView對(duì)象
setContentView(mGLView); }(3)重寫onResume()和onPause()方法,具體代碼如下:
@Override
protectedvoidonResume(){
super.onResume();
mGLView.onResume(); }@Override protectedvoidonPause(){
super.onPause();
mGLView.onPause(); }(4)創(chuàng)建一個(gè)實(shí)現(xiàn)GLSurfaceView.Renderer接口的類CubeRenderer,并實(shí)現(xiàn)onSurfaceCreated()、onDrawFrame()和onSurfaceChanged()方法,具體代碼如下:importjavax.microedition.khronos.egl.EGLConfig;importjavax.microedition.khronos.opengles.GL10;importandroid.opengl.GLSurfaceView;publicclassCubeRendererimplementsGLSurfaceView.Renderer{ @Override publicvoidonDrawFrame(GL10
gl){ } @Override
publicvoidonSurfaceChanged(GL10
gl,intwidth,intheight){ } @Override publicvoidonSurfaceCreated(GL10
gl,EGLConfig
config){ }}(5)在onSurfaceCreated()方法中,應(yīng)用以下代碼進(jìn)行初始化操作,主要包括設(shè)置窗體背景顏色、啟用頂點(diǎn)坐標(biāo)數(shù)組、關(guān)閉抗抖動(dòng)功能、設(shè)置系統(tǒng)對(duì)透視進(jìn)行修正、設(shè)置陰影平滑模式、啟用深度測(cè)試及設(shè)置深度測(cè)試的類型等。具體代碼如下:publicvoidonSurfaceCreated(GL10
gl,EGLConfig
config){
gl.glClearColor(0.7f,0.9f,0.9f,1.0f); //設(shè)置窗體背景顏色
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); //啟用頂點(diǎn)坐標(biāo)數(shù)組
gl.glDisable(GL10.GL_DITHER); //關(guān)閉抗抖動(dòng)//設(shè)置系統(tǒng)對(duì)透視進(jìn)行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);
gl.glShadeModel(GL10.GL_SMOOTH); //設(shè)置陰影平滑模式
gl.glEnable(GL10.GL_DEPTH_TEST); //啟用深度測(cè)試
gl.glDepthFunc(GL10.GL_LEQUAL); //設(shè)置深度測(cè)試的類型說明:深度測(cè)試就是讓OpenGLES負(fù)責(zé)跟蹤每個(gè)物體在Z軸上的深度,這樣可避免后面的物體遮擋前面的物體。(6)在onSurfaceChanged()方法中,首先設(shè)置OpenGL場(chǎng)景的大小,并計(jì)算透視視窗的寬度、高度比,然后將當(dāng)前矩陣模式設(shè)為投影矩陣,再初始化單位矩陣,最后設(shè)置透視視窗的空間大小。具體代碼如下:publicvoidonSurfaceChanged(GL10
gl,intwidth,intheight){
gl.glViewport(0,0,width,height); //設(shè)置OpenGL場(chǎng)景的大小 floatratio=(float)width/height; //計(jì)算透視視窗的寬度、高度比
gl.glMatrixMode(GL10.GL_PROJECTION); //將當(dāng)前矩陣模式設(shè)為投影矩陣
gl.glLoadIdentity(); //初始化單位矩陣
GLU.gluPerspective(gl,45.0f,ratio,1,100f); //設(shè)置透視視窗的空間大小}(7)在onDrawFrame()方法中,首先清除顏色緩存和深度緩存,并設(shè)置使用模型矩陣進(jìn)行變換,然后初始化單位矩陣,再設(shè)置視點(diǎn),并旋轉(zhuǎn)總坐標(biāo)系,最后繪制立方體。具體代碼如下:publicvoidonDrawFrame(GL10
gl){//清除顏色緩存和深度緩存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW); //設(shè)置使用模型矩陣進(jìn)行變換
gl.glLoadIdentity(); //初始化單位矩陣 //當(dāng)使用GL_MODELVIEW模式時(shí),必須設(shè)置視點(diǎn),也就是觀察點(diǎn)
GLU.gluLookAt(gl,0,0,-5,0f,0f,0f,0f,1.0f,0.0f);
gl.glRotatef(1000,-0.1f,-0.1f,0.05f); //旋轉(zhuǎn)總坐標(biāo)系
cube.draw(gl); //繪制立方體}(8)創(chuàng)建一個(gè)用于繪制立方體模型的Java類,名稱為GLCube,在該類中,首先定義一個(gè)用于記錄頂點(diǎn)坐標(biāo)數(shù)據(jù)緩沖的成員變量,關(guān)鍵代碼如下:publicclassGLCube{privatefinalIntBuffer
mVertexBuffer; //頂點(diǎn)坐標(biāo)數(shù)據(jù)緩沖},(9)定義GLCube類的構(gòu)造方法,在構(gòu)造方法中創(chuàng)建一個(gè)記錄頂點(diǎn)位置的數(shù)組,并根據(jù)該數(shù)組創(chuàng)建頂點(diǎn)坐標(biāo)數(shù)據(jù)緩沖,具體代碼如下: publicGLCube(){
intone=65536;
inthalf=one/2;
intvertices[]={ //前面 -half,-half,half,half,-half,half, -half,half,half,half,half,half, //背面 -half,-half,-half,-half,half,-half, half,-half,-half,half,half,-half, //左面 -half,-half,half,-half,half,half, -half,-half,-half,-half,half,-half, //右面 half,-half,-half,half,half,-half,
half,-half,half,half,half,half, //上面-half,half,half,half,half,half, -half,half,-half,half,half,-half, //下面 -half,-half,half,-half,-half,-half, half,-half,half,half,-half,-half, }; //定義頂點(diǎn)位置 //創(chuàng)建頂點(diǎn)坐標(biāo)數(shù)據(jù)緩沖
ByteBuffer
vbb=ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder()); //設(shè)置字節(jié)順序
mVertexBuffer=vbb.asIntBuffer(); //轉(zhuǎn)換為int型緩沖
mVertexBuffer.put(vertices); //向緩沖中放入頂點(diǎn)坐標(biāo)數(shù)據(jù)
mVertexBuffer.position(0); //設(shè)置緩沖區(qū)的起始位置 }(10)在GLCube類中,編寫用于繪制立方體的draw()方法,在該方法中,首先為畫筆指定頂點(diǎn)坐標(biāo)數(shù)組,然后分別繪制立方體的6個(gè)面,每個(gè)面使用的顏色是不同的。draw()方法的具體代碼如下:publicvoiddraw(GL10
gl){
gl.glVertexPointer(3,GL10.GL_FIXED,0,mVertexBuffer);//為畫筆指定頂點(diǎn)坐標(biāo)數(shù)據(jù) //繪制FRONT和BACK兩個(gè)面
gl.glColor4f(1,0,0,1);
gl.glNormal3f(0,0,1);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4); //繪制圖形
gl.glColor4f(1,0,0.5f,1);
gl.glNormal3f(0,0,-1);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,4,4); //繪制圖形 //繪制LEFT和RIGHT兩個(gè)面
gl.glColor4f(0,1,0,1);
gl.glNormal3f(-1,0,0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,8,4); //繪制圖形
gl.glColor4f(0,1,0.5f,1);
gl.glNormal3f(1,0,0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,12,4); //繪制圖形 //繪制TOP和BOTTOM兩個(gè)面gl.glColor4f(0,0,1,1);
gl.glNormal3f(0,1,0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,16,4); //繪制圖形
gl.glColor4f(0,0,0.5f,1);
gl.glNormal3f(0,-1,0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,20,4); //繪制圖形}(11)打開CubeRenderer類,在該類中創(chuàng)建一個(gè)代表立方體對(duì)象的成員變量,并為CubeRenderer類創(chuàng)建無參的構(gòu)造方法,在該構(gòu)造方法中,實(shí)例化立方體對(duì)象。關(guān)鍵代碼如下: privatefinalGLCubecube; //立方體對(duì)象 publicCubeRenderer(){ cube=newGLCube(); //實(shí)例化立方體對(duì)象 }實(shí)例運(yùn)行結(jié)果如圖12-1所示。圖12-1繪制一個(gè)立方體12.3添加效果12.3.1應(yīng)用紋理貼圖12.3.2旋轉(zhuǎn)12.3.3光照效果12.3.4透明效果上一節(jié)中介紹了如何繪制3D模型,在實(shí)際應(yīng)用開發(fā)時(shí),經(jīng)常需要為其添加紋理貼圖、光照、旋轉(zhuǎn)等效果,本節(jié)將介紹如何為3D模型添加紋理貼圖、光照、旋轉(zhuǎn)以及透明效果等。12.3添加效果為了讓3D圖形更加逼真,我們需要為這些3D圖形應(yīng)用紋理貼圖。例如,要在場(chǎng)景中放置一個(gè)木箱,那么就需要為場(chǎng)景中的繪制的立方體應(yīng)用木材紋理進(jìn)行貼圖。為3D模型添加紋理貼圖大致可以分為以下3個(gè)步驟:(1)設(shè)置貼圖坐標(biāo)的數(shù)組信息,這與設(shè)置頂點(diǎn)坐標(biāo)數(shù)組類似。(2)設(shè)置啟用貼圖坐標(biāo)數(shù)組。(3)調(diào)用GL10的texImage2D()方法生成紋理。說明:在使用紋理貼圖時(shí),需要準(zhǔn)備一張紋理圖片,建議該圖片的長(zhǎng)寬是2的N次方,例如,可以是256*256的圖片,也可以是512*512的圖片?!纠?2-2】在例12-1的基礎(chǔ)上為繪制的立方體進(jìn)行紋理貼圖。(實(shí)例位置:光盤\MR\源碼\第12章\12-2)(1)打開GLCube類文件,在該類中定義,用于保存紋理貼圖數(shù)據(jù)緩沖的成員變量,具體代碼如下:privateIntBuffer
mTextureBuffer; //紋理貼圖數(shù)據(jù)緩沖(2)打開GLCube類文件,在構(gòu)造方法中,定義貼圖坐標(biāo)數(shù)組,并根據(jù)該數(shù)組創(chuàng)建貼圖坐標(biāo)數(shù)據(jù)緩沖,具體代碼如下:12.3.1應(yīng)用紋理貼圖int
texCoords[]={ //前面 0,one,one,one,0,0,one,0, //后面 one,one,one,0,0,one,0,0, //左面 one,one,one,0,0,one,0,0, //右面 one,one,one,0,0,one,0,0, //上面 one,0,0,0,one,one,0,one, //下面 0,0,0,one,one,0,one,one,}; //定義貼圖坐標(biāo)數(shù)組ByteBuffer
tbb=ByteBuffer.allocateDirect(texCoords.length*4);tbb.order(ByteOrder.nativeOrder()); //設(shè)置字節(jié)順序mTextureBuffer=tbb.asIntBuffer(); //轉(zhuǎn)換為int型緩沖mTextureBuffer.put(texCoords); //向緩沖中放入貼圖坐標(biāo)數(shù)組mTextureBuffer.position(0); //設(shè)置緩沖區(qū)的起始位置(3)GLCube類的draw()方法的最后,首先應(yīng)用GL10的glTexCorrdPointer()方法為畫筆指定貼圖坐標(biāo)數(shù)據(jù),關(guān)鍵代碼如下:
gl.glTexCoordPointer(2,GL10.GL_FIXED,0,mTextureBuffer);//為畫筆指定貼圖坐標(biāo)數(shù)據(jù)(4)編寫loadTexture()方法,用于進(jìn)行紋理貼圖,具體代碼如下:
/** * *功能:進(jìn)行紋理貼圖 * *@param
gl *@paramcontext *@paramresource */ voidloadTexture(GL10
gl,Contextcontext,intresource){ Bitmapbmp=BitmapFactory.decodeResource(context.getResources(),
resource); //加載位圖
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bmp,0); //使用圖片生成紋理
bmp.recycle(); //釋放資源 }(5)打開CubeRenderer類文件,在onSurfaceCreated()方法中,添加以下代碼,首先啟用貼圖坐標(biāo)數(shù)組,然后啟用紋理貼圖,最后調(diào)用GLCube類的loadTexture()方法進(jìn)行紋理貼圖。gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //啟用貼圖坐標(biāo)數(shù)組gl.glEnable(GL10.GL_TEXTURE_2D); //啟用紋理貼圖cube.loadTexture(gl,context,R.drawable.mr); //進(jìn)行紋理貼圖運(yùn)行本實(shí)例,將顯示如圖12-2所示的運(yùn)行結(jié)果。圖12-2為立方體進(jìn)行紋理貼圖12.3.2旋轉(zhuǎn)到目前為止,繪制的3D物體還是靜止的,為了更好的看到3D效果,還可以為其添加旋轉(zhuǎn)效果。這樣就可達(dá)到動(dòng)畫效果了。要實(shí)現(xiàn)旋轉(zhuǎn)比較簡(jiǎn)單,只需要使用GL10的glRotatef()方法不斷的旋轉(zhuǎn)要放置的對(duì)象即可。glRotatef()方法的語法格式如下:glRotatef(floatangle,floatx,floaty,floatz)其中,參數(shù)angle通常是一個(gè)變量,表示對(duì)象轉(zhuǎn)過的角度;x表示X軸的旋轉(zhuǎn)方向(值為1表示順時(shí)針、-1表示逆時(shí)針方向、0表示不旋轉(zhuǎn));y表示Y軸的旋轉(zhuǎn)方向(值為1表示順時(shí)針、-1表示逆時(shí)針方向、0表示不旋轉(zhuǎn));z表示Z軸的旋轉(zhuǎn)方向(值為1表示順時(shí)針、-1表示逆時(shí)針方向、0表示不旋轉(zhuǎn))。例如,要將對(duì)象經(jīng)過X軸旋轉(zhuǎn)n角度,可以使用下面的代碼:gl.glRotatef(n,1,0,0);【例12-3】在例12-2的基礎(chǔ)上實(shí)現(xiàn)一個(gè)不斷旋轉(zhuǎn)的立方體。(實(shí)例位置:光盤\MR\源碼\第12章\12-3)(1)打開CubeRenderer類文件,在該類中定義,用于保存開始時(shí)間的成員變量,具體代碼如下:privatelongstartTime; //保存開始時(shí)間(2)在構(gòu)造方法中,為成員變量startTime賦初始值為當(dāng)前時(shí)間,具體代碼如下:startTime=System.currentTimeMillis();(3)在onDrawFrame()方法的繪制立方體的代碼之前,添加以下代碼,完成旋轉(zhuǎn)立方體的操作。//旋轉(zhuǎn)longelapsed=System.currentTimeMillis()-startTime; //計(jì)算逝去的時(shí)間gl.glRotatef(elapsed*(30f/1000f),0,1,0); //在y軸上旋轉(zhuǎn)30度gl.glRotatef(elapsed*(15f/1000f),1,0,0); //在x軸上旋轉(zhuǎn)15度運(yùn)行本實(shí)例,將顯示如圖12-3所示的運(yùn)行結(jié)果。圖12-3旋轉(zhuǎn)的立方體為了使用程序效果更加美觀、逼真,還可以讓其模擬光照效果。在為物體添加光照效果前,我們先來了解一下3D圖形支持的光照類型。所有的3D圖形都支持以下3種光照類型:環(huán)境光:一種普通的光線,光線會(huì)照亮整個(gè)場(chǎng)景,即使對(duì)象背對(duì)著光線也可以。散射光:柔和的方向性光線.例如,熒光板上發(fā)出的光線就是這種散射光。場(chǎng)景中的大部分光線通常來源于散射光源。鏡面高光:耀眼的光線,通常來源于明亮的點(diǎn)光源。與有光澤的材料結(jié)合使用時(shí),這種光會(huì)帶來高光效果,增加場(chǎng)景的真實(shí)感。在OpenGL中,添加光照效果,通常分為以下兩個(gè)步驟進(jìn)行。1.光線在定義光照效果時(shí),通常需要定義光線,也就是為場(chǎng)景添加光源。這可以通過GL10提供的glLightfv()方法實(shí)現(xiàn)。glLightfv()方法的語法格式如下:glLightfv(intlight,int
pname,float[]params,intoffset)其中,light表示光源的ID,當(dāng)程序中包含多個(gè)光源時(shí),可以通過這個(gè)ID來區(qū)分光源;pname表示光源的類型(參數(shù)值為GL10.GL_AMBIENT表示環(huán)境光、12.3.3光照效果參數(shù)值為GL10.GL_DIFFUSE表示散射光);params:表示光源數(shù)組;offset:表示偏移量。例如,要定義一個(gè)發(fā)出白色的全方向的光源,可以使用下面的代碼:floatlightAmbient[]=newfloat[]{0.2f,0.2f,0.2f,1}; //定義環(huán)境光floatlightDiffuse[]=newfloat[]{1,1,1,1}; //定義散射光floatlightPos[]=newfloat[]{1,1,1,1}; //定義光源的位置gl.glEnable(GL10.GL_LIGHTING); //啟用光源gl.glEnable(GL10.GL_LIGHT0); //啟用0號(hào)光源gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_AMBIENT,lightAmbient,0); //設(shè)置環(huán)境光gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_DIFFUSE,lightDiffuse,0); //設(shè)置散射光gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_POSITION,lightPos,0); //設(shè)置光源的位置注意:在定義和設(shè)置光源后,還需要使用glEnable()方法啟用光源,否則,設(shè)置的光源將不起作用。2.被照射的物體在定義光照效果時(shí),通常需要定義被照射物體的制作材料,因?yàn)椴煌牧系墓饩€反射情況是不同的。使用GL10提供的glMaterialfv()方法可以設(shè)置材質(zhì)的環(huán)境光和散射光。glMaterialfv()方法的語法格式如下:glMaterialfv(intface,int
pname,float[]params,intoffset)其中,face表示是為正面還是背面材質(zhì)設(shè)置光源;pname表示光源的類型(參數(shù)值為GL10.GL_AMBIENT表示環(huán)境光、參數(shù)值為GL10.GL_DIFFUSE表示散射光);params:表示光源數(shù)組;offset:表示偏移量。例如,定義一個(gè)不是很亮的紙質(zhì)的物體,可以使用下面的代碼:floatmatAmbient[]=newfloat[]{1,1,1,1}; //定義材質(zhì)的環(huán)境光floatmatDiffuse[]=newfloat[]{1,1,1,1}; //定義材質(zhì)的散射光gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_AMBIENT,matAmbient,0);//設(shè)置環(huán)境光gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_DIFFUSE,matDiffuse,0);//設(shè)置散射光下面通過一個(gè)具體的實(shí)例來說明為物體添加光照效果的具體步驟?!纠?2-4】在例12-3的基礎(chǔ)上實(shí)現(xiàn)為旋轉(zhuǎn)的立方體添加光照效果的功能。(實(shí)例位置:光盤\MR\源碼\第12章\12-4)(1)打開CubeRenderer類文件,在onSurfaceCreated()方法中為被照射的物體設(shè)置材質(zhì)。首先定義材質(zhì)的環(huán)境光和散射光,然后設(shè)置材質(zhì)的環(huán)境光和散射光,具體代碼如下:floatmatAmbient[]=newfloat[]{1,1,1,1}; //定義材質(zhì)的環(huán)境光floatmatDiffuse[]=newfloat[]{1,1,1,1}; //定義材質(zhì)的散射光gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_AMBIENT,matAmbient,0);//設(shè)置環(huán)境光gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_DIFFUSE,matDiffuse,0);//設(shè)置散射光(2)在onSurfaceCreated()方法中添加場(chǎng)景光線。首先定義環(huán)境光和散射光,并定義光源的位置,然后啟用光源和0號(hào)光源,最后設(shè)置環(huán)境光、散射光和光源的位置,具體代碼如下:floatlightAmbient[]=newfloat[]{0.2f,0.2f,0.2f,1}; //定義環(huán)境光floatlightDiffuse[]=newfloat[]{1,1,1,1}; //定義散射光floatlightPos[]=newfloat[]{1,1,1,1}; //定義光源的位置gl.glEnable(GL10.GL_LIGHTING); //啟用光源gl.glEnable(GL10.GL_LIGHT0); //啟用0號(hào)光源gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_AMBIENT,lightAmbient,0); //設(shè)置環(huán)境光gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_DIFFUSE,lightDiffuse,0); //設(shè)置散射光gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_POSITION,lightPos,0); //設(shè)置光源的位置運(yùn)行本實(shí)例,將顯示如圖12-4所示的運(yùn)行結(jié)果。
圖12-4為立方體添加光照效果在游戲中,經(jīng)常需要應(yīng)用透明效果,使用OpenGLES實(shí)現(xiàn)簡(jiǎn)單的透明效果也比較簡(jiǎn)單,只需要應(yīng)用以下代碼就可以實(shí)現(xiàn)。gl.glDisable(GL10.GL_DEPTH_TEST); //關(guān)閉深度測(cè)試gl.glEnable(GL10.GL_BLEND); //打開混合gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE); //使用alpha通道值進(jìn)行混色說明:實(shí)現(xiàn)透明效果時(shí),需要關(guān)閉深度測(cè)試,并且打開混合效果,然后才能使用GL10類的glBlendFunc()方法進(jìn)行混色,從而達(dá)到透明效果。下面通過一個(gè)具體的實(shí)例來說明實(shí)現(xiàn)透明效果的具體步驟?!纠?2-5】在例12-4的基礎(chǔ)上制作一個(gè)透明的、不斷旋轉(zhuǎn)的立方體。(實(shí)例位置:光盤\MR\源碼\第12章\12-5)打開CubeRenderer類文件,在onSurfaceCreated()方法中為立方體添加透明效果。首先關(guān)閉深度測(cè)試,然后打開混合效果,最后再使用alpha通道值進(jìn)行混色,從而達(dá)到透明效果,具體代碼如下:gl.glDisable(GL10.GL_DEPTH_TEST); //關(guān)閉深度測(cè)試gl.glEnable(GL10.GL_BLEND); //打開混合gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE); //使用alpha通道值進(jìn)行混色12.3.4透明效果運(yùn)行本實(shí)例,將顯示如圖12-5所示的運(yùn)行結(jié)果。圖12-5透明且旋轉(zhuǎn)的立方體使用OpenGLES可以很方便的繪制一個(gè)不斷旋轉(zhuǎn)的金字塔,也就是一個(gè)四棱錐,本實(shí)例要求繪制一個(gè)從頂?shù)降诐u變的、不斷旋轉(zhuǎn)的金字塔。程序運(yùn)行效果如圖12-5所示。圖12-5繪制一個(gè)不斷旋轉(zhuǎn)的金字塔12.4綜合實(shí)例——繪制一個(gè)不斷旋轉(zhuǎn)的金字塔程序開發(fā)步驟如下:(1)繪制金字塔,首先需要定義金字塔的頂點(diǎn)坐標(biāo)位置和各個(gè)切面的顏色,并使用GL10對(duì)象的相關(guān)方法繪制金字塔;然后通過自定義類實(shí)現(xiàn)GLSurfaceView.Renderer接口的CubeRenderer類,并實(shí)現(xiàn)其中的onSurfaceCreated()、onDrawFrame()和onSurfaceChanged()方法,在這3個(gè)方法中分別對(duì)金字塔的背景顏色、場(chǎng)景、旋轉(zhuǎn)等進(jìn)行設(shè)置。定義金字塔頂點(diǎn)坐標(biāo)及繪制金字塔的代碼如下:publicclassGLPyramid{ privatefinalIntBuffer
mVertexBuffer; //頂點(diǎn)坐標(biāo)數(shù)據(jù)緩沖 privateIntBuffer
mColorBuffer; //紋理貼圖數(shù)據(jù)緩沖 publicGLPyramid(){
intone=65535;
intvertices[]={ //底面 -one,0,one, one,0,one, -one,0,-one,
one,0,-one,
one,0,one,one,0,-one,0,one,0,
0,one,0,one,0,-one,-one,0,-one, -one,0,-one,-one,0,one,0,one,0,
0,one,0,-one,0,one,one,0,one
}; //定義頂點(diǎn)位置//創(chuàng)建頂點(diǎn)坐標(biāo)數(shù)據(jù)緩沖
ByteBuffer
vbb=ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder()); //設(shè)置字節(jié)順序
mVertexBuffer=vbb.asIntBuffer(); //轉(zhuǎn)換為int型緩沖
mVertexBuffer.put(vertices); //向緩沖中放入頂點(diǎn)坐標(biāo)數(shù)據(jù)
mVertexBuffer.position(0); //設(shè)置緩沖區(qū)的起始位置 /**********************顏色*****************************************/
intcolors[]={
one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,0,one,one,one,0,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,one,0,one,one,one,0,one,one,one,one,one,one,one,one,one,one,}; //定義顏色坐標(biāo)數(shù)據(jù)
ByteBuffer
tbb=ByteBuffer.allocateDirect(colors.length*4);
tbb.order(ByteOrder.nativeOrder()) //設(shè)置字節(jié)順序
mColorBuffer=tbb.asIntBuffer(); //轉(zhuǎn)換為int型緩沖
mColorBuffer.put(colors); //向緩沖中放入顏色坐標(biāo)數(shù)據(jù)
mColorBuffer.position(0); //設(shè)置緩沖區(qū)的起始位置 /***************************************************************************/ } publicvoiddraw(GL10
gl){
gl.glVertexPointer(3,GL10.GL_FIXED,0,mVertexBuffer);//為畫筆指定頂點(diǎn)坐標(biāo)數(shù)據(jù)
gl.glEnableClientState(GL10.GL_COLOR_ARRAY); //繪制底面
gl.glColorPointer(4,GL10.GL_FIXED,0,mColorBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4); //繪制圖形 //繪制4個(gè)側(cè)面
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,4,12); //繪制圖形 }}(2)實(shí)現(xiàn)GLSurfaceView.Renderer接口的CubeRenderer類,并實(shí)現(xiàn)其中的onSurfaceCreated()、onDrawFrame()和on
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025國(guó)考常州市市場(chǎng)監(jiān)管崗位申論題庫含答案
- 解析卷人教版八年級(jí)上冊(cè)物理光現(xiàn)象《光的反射》同步訓(xùn)練試題(含答案解析)
- 歌曲《索爾維格之歌》的音樂特征與演唱分析
- 2025國(guó)考常州市出入境管理崗位申論預(yù)測(cè)卷及答案
- 解析卷-人教版八年級(jí)上冊(cè)物理《機(jī)械運(yùn)動(dòng)》專題測(cè)評(píng)試卷(附答案詳解)
- 東北三省基本公共服務(wù)供給水平測(cè)度及提升策略研究
- 2025國(guó)考白城市外交業(yè)務(wù)崗位行測(cè)必刷題及答案
- 考點(diǎn)解析人教版九年級(jí)物理《電流和電路》章節(jié)測(cè)試練習(xí)題(含答案詳解)
- 達(dá)標(biāo)測(cè)試人教版八年級(jí)上冊(cè)物理聲現(xiàn)象《聲音的特性聲的利用》必考點(diǎn)解析試題(含答案及解析)
- 高速公路出口交通流量管理方案
- 2025年共青團(tuán)考試題庫(附答案)
- 水果拼盤拼盤課件
- 項(xiàng)目策劃工作檢查考核表
- 習(xí)作:讓生活更美好-完整版課件
- 最全浙江行業(yè)協(xié)會(huì)名單
- 訪談提綱格式4篇
- ACUSONX150西門子彩色多普勒超聲系統(tǒng)
- 連鑄坯中心缺陷控制
- GYB培訓(xùn)全課件(最終版)
- 合伙開飯店協(xié)議書的范本
- 大橋墩柱蓋梁抱箍施工方案
評(píng)論
0/150
提交評(píng)論