導航:首頁 > 操作系統 > androidopengl實例

androidopengl實例

發布時間:2024-07-12 12:49:48

A. Android OpenGL表面崩潰在設備方向改變問題,怎麼解決

准備為了開始本次的教程,你必須具備:1.一款支持Android開發的IDE,如果你沒有的話,可以在AndroidDeveloperwebsite下載最新版本的Androidstudio。2.一款運行Android4.0之上Android手機,並且GPU支持OpenGLES2.03.對OpenGL的基本知識了解設置OpenGLES環境創建GLSurfaceView為了顯示OpenGL的圖形,你需要使用GLSurfaceView類,就像其他任何的View子類意義,你可以將它添加到你的Activity或Fragment之上,通過在布局xml文件中定義或者在代碼中創建實例。在本次的教程中,我們使用GLSurfaceView作為唯一的View在我們的Activity中,因此,為了簡便,我們在代碼中創建GLSurfaceView的實例並將其傳入setContentView中,這樣它將會填充你的整個手機屏幕。Activity中的onCreate方法如下:protectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);GLSurfaceViewview=newGLSurfaceView(this);setContentView(view);}123456123456因為媒體效果的框架僅僅支持OpenGLES2.0及以上的版本,所以在setEGLContextClientVersion方法中傳入2;view.setEGLContextClientVersion(2);11為了確保GLSurfaceView僅僅在必要的時候進行渲染,我們在setRenderMode方法中進行設置:view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);11創建RendererRenderer負責渲染GLSurfaceView中的內容。創建類實現介面GLSurfaceView.Renderer,在這里我們打算將這個類命名為EffectsRenderer,添加構造函數並覆寫介面中的抽象方法,如下:.Renderer{publicEffectsRenderer(Contextcontext){super();}@(GL10gl,EGLConfigconfig){}@(GL10gl,intwidth,intheight){}@OverridepublicvoidonDrawFrame(GL10gl){}}回到Activity中調用setRenderer方法,讓GLSurfaceView使用我們創建的Renderer:view.setRenderer(newEffectsRenderer(this));11編寫Manifest文件如果你想要發布你的App到谷歌商店,在AndroidManifest.xml文件中添加如下語句:11這會確保你的app只能被安裝在支持OpenGLES2.0的設備之上。現在OpenGL環境准備完畢。創建一個OpenGL平面定義頂點GLSurfaceView是不能直接顯示一張照片的,照片首先應該被轉化為紋理,應用在OpenGLsquare之上。在本次教程中,我將創建一個2D平面,並且具有4個頂點。為了簡單,我將使用一個長方形,現在,創建一個新的類Square,用它來代表形狀。publicclassSquare{}123123默認的OpenGL系統的坐標系中的原點是在中心,因此4個角的坐標可以表示為:左下角:(-1,-1)右下角:(1,-1)右上角:(1,1)左上角:(-1,1)我們使用OpenGL繪制的所有的物體都應該是由三角形決定的,為了畫一個方形,我們需要兩個具有一條公共邊的三角形,那意味著這些三角形的坐標應該是:triangle1:(-1,-1),(1,-1),和(-1,1)triangle2:(1,-1),(-1,1),和(1,1)創建一個float數組來代表這些頂點:privatefloatvertices[]={-1f,-1f,1f,-1f,-1f,1f,1f,1f,};123456123456為了在square上定位紋理,需要確定紋理的頂點坐標,創建另一個數組來表示紋理頂點的坐標:privatefloattextureVertices[]={0f,1f,1f,1f,0f,0f,1f,0f};123456123456創建緩沖區這些坐標數組應該被轉變為緩沖字元(bytebuffer)在OpenGL可以使用之前,接下來進行定義:;;1212在initializeBuffers方法中去初始化這些緩沖區:使用ByteBuffer.allocateDirect來創建緩沖區,因為float是4個位元組,那麼我們需要的byte數組的長度應該為float的4倍。下面使用ByteBuffer.nativeOrder方法來定義在底層的本地平台上的byte的順序。使用asFloatBuffer方法將ByteBuffer轉化為FloatBuffer,在FloatBuffer被創建後,我們調用put方法來將float數組放入緩沖區,最後,調用position方法來保證我們是由緩沖區的開頭進行讀取。privatevoidinitializeBuffers(){ByteBufferbuff=ByteBuffer.allocateDirect(vertices.length*4);buff.order(ByteOrder.nativeOrder());verticesBuffer=buff.asFloatBuffer();verticesBuffer.put(vertices);verticesBuffer.position(0);buff=ByteBuffer.allocateDirect(textureVertices.length*4);buff.order(ByteOrder.nativeOrder());textureBuffer=buff.asFloatBuffer();textureBuffer.put(textureVertices);textureBuffer.position(0);}創建著色器著色器只不過是簡單的運行在GPU中的每個單獨的頂點的C程序,在本次教程中,我們使用兩種著色器:頂點著色器和片段著色器。頂點著色器的代碼:attributevec4aPosition;attributevec2aTexPosition;varyingvec2vTexPosition;voidmain(){gl_Position=aPosition;vTexPosition=aTexPosition;};12345671234567片段著色器的代碼precisionmediumpfloat;uniformsampler2DuTexture;varyingvec2vTexPosition;voidmain(){gl_FragColor=texture2D(uTexture,vTexPosition);};123456123456如果你了解OpenGL,那麼這段代碼對你來說是熟悉的,如果你不能理解這段代碼,你可以參考OpenGLdocumentation。這里有一個簡明扼要的解釋:頂點著色器負責繪制單個頂點。aPosition是一個變數被綁定到FloatBuffer上,包含著這些頂點的坐標。相似的,aTexPosition是一個變數被綁定到FloatBuffer上,包含著紋理的坐標。gl_Position是一個在OpenGL中創建的變數,代表每一個頂點的位置,vTexPosition是一個數組變數,它的值被傳遞到片段著色器中。在本教程中,片段著色器負責square的著色。它使用texture2D方法從紋理中拾取顏色,並且使用一個在OpenGL中被創建的變數gl_FragColor將顏色分配到片段。在該類中,著色器的代碼應該被轉化為String。="attributevec4aPosition;"+"attributevec2aTexPosition;"+"varyingvec2vTexPosition;"+"voidmain(){"+"gl_Position=aPosition;"+"vTexPosition=aTexPosition;"+"}";="precisionmediumpfloat;"+"uniformsampler2DuTexture;"+"varyingvec2vTexPosition;"+"voidmain(){"+"gl_FragColor=texture2D(uTexture,vTexPosition);"+"}";創建程序創建新的方法initializeProgram來創建一個編譯和鏈接著色器的OpenGL程序。使用glCreateShader創建一個著色器對象,並且返回以int為表示形式的指針。為了創建頂點著色器,傳遞GL_VERTEX_SHADER給它。相似的,為了創建一個片段著色器,傳遞GL_FRAGMENT_SHADER給它。下面使用glShaderSource方法關聯相對應的著色器代碼到著色器上。使用glCompileShader編譯著色器代碼。在編譯了著色器的代碼後,創建一段新的的程序glCreateProgram,與glCreateShader相似,它也返回一個以int為表示形式的指針。調用glAttachShader方法附著著色器到程序中,最後,調用glLinkProgram進行鏈接。代碼:privateintvertexShader;privateintfragmentShader;privateintprogram;privatevoidinitializeProgram(){vertexShader=GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);GLES20.glShaderSource(vertexShader,vertexShaderCode);GLES20.glCompileShader(vertexShader);fragmentShader=GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);GLES20.glShaderSource(fragmentShader,fragmentShaderCode);GLES20.glCompileShader(fragmentShader);program=GLES20.glCreateProgram();GLES20.glAttachShader(program,vertexShader);GLES20.glAttachShader(program,fragmentShader);GLES20.glLinkProgram(program);}你可能會發現,OpenGL的方法(以gl開頭的)都是在GLES20類中,這是因為我們使用的是OpenGLES2.0,如果我們使用更高的版本,就會用到這些類:GLES30,GLES31。畫出形狀現在定義draw方法來利用我們之前定義的點和著色器進行繪制。下面是你需要做的:1.使用glBindFramebuffer方法創建一個幀緩沖對象(FBO)2.調用glUseProgram創建程序,就像之前所提3.傳遞GL_BLEND給glDisable方法,在渲染過程中禁用顏色的混合。4.調用glGetAttribLocation得到變數aPosition和aTexPosition的句柄5.使用glVertexAttribPointer連接aPosition和aTexPosition的句柄到各自的verticesBuffer和textureBuffer6.使用glBindTexture方法綁定紋理(作為draw方法的參數傳入)到片段著色器上7.調用glClear方法清空GLSurfaceView的內容8.最後,使用glDrawArrays方法畫出兩個三角形(也就是方形)代碼:publicvoiddraw(inttexture){GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,0);GLES20.glUseProgram(program);GLES20.glDisable(GLES20.GL_BLEND);intpositionHandle=GLES20.glGetAttribLocation(program,"aPosition");inttextureHandle=GLES20.glGetUniformLocation(program,"uTexture");inttexturePositionHandle=GLES20.glGetAttribLocation(program,"aTexPosition");GLES20.glVertexAttribPointer(texturePositionHandle,2,GLES20.GL_FLOAT,false,0,textureBuffer);GLES20.glEnableVertexAttribArray(texturePositionHandle);GLES20.glActiveTexture(GLES20.GL_TEXTURE0);GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,texture);GLES20.glUniform1i(textureHandle,0);GLES20.glVertexAttribPointer(positionHandle,2,GLES20.GL_FLOAT,false,0,verticesBuffer);GLES20.glEnableVertexAttribArray(positionHandle);GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4);}在構造函數中添加初始化方法:publicSquare(){initializeBuffers();initializeProgram();}12341234渲染OpenGL平面和紋理現在我們的渲染器什麼也沒做,我們需要改變它來渲染我們在前面創造的平面。首先,讓我們創建一個Bitmap,添加一張照片到res/drawable文件夾之下,我把它命名為forest.jpg,使用BitmapFactory將照片轉化為Bitmap。另外將照片的尺寸存儲下來。改變EffectsRenderer的構造函數如下,privateBitmapphoto;privateintphotoWidth,photoHeight;publicEffectsRenderer(Contextcontext){super();photo=BitmapFactory.decodeResource(context.getResources(),R.drawable.forest);photoWidth=photo.getWidth();photoHeight=photo.getHeight();}1234567812345678

B. 如何在Android上使用OpenGL ES 2.0繪制點

FrameBuffer對象的概念可以參見前面文章AndroidOpenGLES開發教程(23):FrameBuffer。簡單的和2D圖像類比,FrameBuffer如果對應到二維圖形環境中,就是一個2D的內存數組空間,預設情況為屏幕的顯存,也可以創建Offscreen內存空間,此時FrameBuffer可以是一個二維數組,數組每個元素代表一個像素顏色。對於三維圖形來說,除了需要代表顏色的二維數組(ColorBuffer),還需要深度二維數組(DepthBuffer)或遮罩數組(StencilBuffer),因此在OpenGL中的FrameBuffer為上述ColorBuffer,DepthBuffer,StencilBuffer的集合。如果手機具有GPU,其預設的FrameBuffer也是3D屏幕顯示區域。通過OpenglES擴展支持,應用程序也可以創建內存中的FrameBuffer對象(不用於屏幕顯示)。通過這種應用程序創建的FrameBuffer對象,OpenGL應用可以將圖像顯示輸出重新定向到這個非屏幕顯示用FrameBuffer對象中,類似於二維圖形繪制中常用的Offscreen技術。和預設的屏幕顯示FrameBuffer一樣,由應用程序創建的FrameBuffer對象也是由ColorBuffer,DepthBuffer和StencilBuffer(可選)的集合組成。這些Buffer在FrameBuffer對象中可以稱為FrameBuffer-attachable圖像,FrameBuffer定義了一些接入點(AttachmentPoint)可以用於連接(Attach)這些Buffer數組。OpenGLES定義了兩種FrameBuffer-attachable圖像,Texture和renderbuffer,簡單的可以將Texture理解為Colorbuffer或是2D圖像,renderbuffer對應於depthbuffer。

C. Android OpenGL 的基本使用

由於本人現在在公司做Android上的OpenGL圖像處理相關功能,以前沒有搞過這方面的知識,所以一切只能從頭開始搞起,接下來將會慢慢分享其他方面的內容,先用這篇比較基礎的文章來開頭。

剛才我們談到圖像處理,在做圖像處理我們不是可以用Canvas來繪制嗎,怎麼還要用OpenGL那麼陌生的東西來搞?為什麼要用OpenGL,肯定有它的好處。

接下來我們會來講解如何在Android項目開發過程中加入OpenGL,在開始前我們先了解同OpenGL ES密切相關的載體:GLSurfaceView:

要用OpenGL繪制,首先要有GLSurfaceVie的實例

現在OpenGL ES版本已經到3.0了,Android平台上目前有1.0和2.0,我們使用的是2.0,在使用前在onCreate()方法中檢查是否支持2.0的版本並且確定使用2.0

一般我們只需要使用「configurationInfo.reqGlEsVersion >= 0x20000」,至於加後面主要是用於模擬器檢查,假定模擬器支持2.0。

前面說到GLSurfaceView挖了一個洞,就是為了看見下面的渲染表面,同樣實在onCreate()方法中

通過setEGLContextClientVersion()方法配置surface視圖,設定好使用的OpenGL版本,然後調用setRenderer()傳進有自定義Renderer類的新實例。當Surface創建或者發生變化的時候,以及繪制一幅新幀時,渲染器都會被GLSurfaceView調用。

GLSurfaceView的生命周期要協同好Activity的生命周期,避免造成內存泄漏。

Renderer類也就是我們的渲染類了,它是通過實現Renderer介面來實現功能的。

渲染器介面定義的方法:

實現Renderer的介面方法

首選在onSurfaceCreated()中調用glClearColor設置清空屏幕用的顏色,這里使用紅色。

設置視口的大小

在onDrawFrame()中調用glClear(GL_COLOR_BUFFER_BIT)清空屏幕,會調用glClearColor中定義的顏色來填充整個屏幕。通過這幾個步驟,基本上就可以在GLSurfaceView繪制出東西了,在這里我只是簡單的用紅色繪制整個屏幕。

OpenGL在Android上的使用基本上是這樣,但是,當然沒那麼簡單,在使用OpenGL進行繪制算是比較繁瑣的過程,後面也會慢慢去揭曉其他使用方法,來構造一幅一幅精美的特效靜/動圖。

閱讀全文

與androidopengl實例相關的資料

熱點內容
題庫演算法 瀏覽:476
臨沂壓縮機生產廠家 瀏覽:942
cad旋轉角度命令 瀏覽:389
阿里雲是用什麼牌子伺服器 瀏覽:670
java基礎入門百度雲 瀏覽:979
360壓縮咋加密 瀏覽:354
hadoopmapreduce編程 瀏覽:302
linuxraid軟體 瀏覽:589
北美gre範文pdf 瀏覽:264
硬碟錄像機接什麼伺服器設備 瀏覽:502
智慧醫療方面最優演算法 瀏覽:920
伺服器ban掉了是什麼意思 瀏覽:394
vvo手機拍的視頻在哪個文件夾 瀏覽:838
華為防火牆cli命令手冊 瀏覽:895
於正新劇玉樓春在什麼App播放 瀏覽:127
學習社會經驗下載什麼app 瀏覽:475
php發布站程序 瀏覽:204
源碼編譯ntfs內核模塊 瀏覽:120
r11s手機管家沒有加密 瀏覽:781
怎麼看電腦連接哪個伺服器 瀏覽:191