Android官方开发文档Training系列课程中文版:OpenGL绘图之图形绘制
原文地址:http://android.xsoftlab.net/training/graphics/opengl/draw.html
如果你還不清楚如何定義圖形及坐標(biāo)系統(tǒng),請移步:Android官方開發(fā)文檔Training系列課程中文版:OpenGL繪圖之圖形定義。
在定義了圖形之后,你接下來需要做的就是將它繪制到屏幕上。不過使用OpenGL ES 2.0 API來繪制這個圖形所需要的代碼量可能要比想象中的多一些,這是因為API為圖形渲染管道提供了大量的控制細(xì)節(jié)。
這節(jié)課會展示如何繪制上節(jié)課所定義的圖形。
初始化圖形
在開始任何繪制之前,你必須先初始化并加載這個圖形。除非是在執(zhí)行的過程中圖形的結(jié)構(gòu)發(fā)生了改變。這個時候你應(yīng)該在渲染器的onSurfaceCreated()方法中去初始化它們,這樣可以使內(nèi)存和進(jìn)程的效率提升。
public class MyGLRenderer implements GLSurfaceView.Renderer {...private Triangle mTriangle;private Square mSquare;public void onSurfaceCreated(GL10 unused, EGLConfig config) {...// initialize a trianglemTriangle = new Triangle();// initialize a squaremSquare = new Square();}... }繪制圖形
繪制自定義圖形需要大量的代碼,因為你必須給圖形渲染管道提供大量的渲染細(xì)節(jié)。尤其是下面這些必須定義:
- Vertex Shader - 圖形頂點的渲染.
- Fragment Shader - 圖形表面的顏色或紋理的渲染。
- Program - 一個含有多個渲染器的OpenGL ES對象,可以用它來繪制一個或者多個圖形。
你需要至少一個頂點渲染器來繪制圖形,并需要一個表面渲染器來為圖形著色。這些渲染器首先必須是可執(zhí)行的,然后才能將其添加到OpenGL ES程序中,這時才能被用來繪制圖形。下面定義了一個最基本的可以用來繪制圖形的渲染器:
public class Triangle {private final String vertexShaderCode ="attribute vec4 vPosition;" +"void main() {" +" gl_Position = vPosition;" +"}";private final String fragmentShaderCode ="precision mediump float;" +"uniform vec4 vColor;" +"void main() {" +" gl_FragColor = vColor;" +"}";... }渲染器包含了OpenGL渲染語言代碼,這些代碼必須先在OpenGL ES環(huán)境中編譯通過。為了編譯這些代碼,需要在渲染器類中創(chuàng)建一個功能方法:
public static int loadShader(int type, String shaderCode){// create a vertex shader type (GLES20.GL_VERTEX_SHADER)// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)int shader = GLES20.glCreateShader(type);// add the source code to the shader and compile itGLES20.glShaderSource(shader, shaderCode);GLES20.glCompileShader(shader);return shader; }為了可以繪制圖形,必須先編譯這些渲染器代碼,然后再將其添加到OpenGL程序中,最后再鏈接到程序中。需要將這些工作放入繪制對象的構(gòu)造方法中,所以這些工作只用做一次。
Note: OpenGL ES的編譯與鏈接過程需要消耗較高的CPU資源與時間,所以你應(yīng)該避免這些工作做多次。如果在程序運行之前不知道渲染器的代碼,應(yīng)該確保這部分的構(gòu)建代碼只會執(zhí)行一次,并需要將其緩存下來以便稍后使用。
public class Triangle() {...private final int mProgram;public Triangle() {...int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);// create empty OpenGL ES ProgrammProgram = GLES20.glCreateProgram();// add the vertex shader to programGLES20.glAttachShader(mProgram, vertexShader);// add the fragment shader to programGLES20.glAttachShader(mProgram, fragmentShader);// creates OpenGL ES program executablesGLES20.glLinkProgram(mProgram);} }這時就可以真正的開始繪制了。圖形的繪制需要提供若干的參數(shù)來告訴渲染管道想要繪制什么及如何繪制。因為繪制選項可以定義多種多樣的圖形形式,所以可以自定義一個擁有獨立繪制邏輯的類來繪制各種圖形。
創(chuàng)建一個draw()方法開始繪制這個圖形。這部分代碼將會為頂點渲染器設(shè)置位置數(shù)據(jù),并為表面渲染器設(shè)置顏色數(shù)據(jù)。然后開始執(zhí)行繪制功能。
private int mPositionHandle; private int mColorHandle; private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX; private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex public void draw() {// Add program to OpenGL ES environmentGLES20.glUseProgram(mProgram);// get handle to vertex shader's vPosition membermPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");// Enable a handle to the triangle verticesGLES20.glEnableVertexAttribArray(mPositionHandle);// Prepare the triangle coordinate dataGLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,GLES20.GL_FLOAT, false,vertexStride, vertexBuffer);// get handle to fragment shader's vColor membermColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");// Set color for drawing the triangleGLES20.glUniform4fv(mColorHandle, 1, color, 0);// Draw the triangleGLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);// Disable vertex arrayGLES20.glDisableVertexAttribArray(mPositionHandle); }一旦完成以上所有的代碼,最后只需要調(diào)用一下draw()方法就可以開始繪制了:
public void onDrawFrame(GL10 unused) {...mTriangle.draw(); }當(dāng)程序啟動之后,設(shè)備上就會出現(xiàn)以下圖形:
上面的示例代碼還有幾個問題:首先,它不會給人留下什么深刻的印象。其次,當(dāng)屏幕旋轉(zhuǎn)的時候,這個三角形會有一點被壓扁的感覺。這是因為在旋轉(zhuǎn)的時候,代碼中所定義的頂點的相對位置被壓縮了。這些問題將會在下節(jié)課得到解決。
最后,這三角形是固定不變的,這會有些讓人有些不爽的感覺。在Adding Motion的課程中將會使這個圖形可以隨著手勢旋轉(zhuǎn)而旋轉(zhuǎn),還可以通過渲染管道做到其它更多有意思的事情。
總結(jié)
以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:OpenGL绘图之图形绘制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tensorflow--模型的保存和提取
- 下一篇: TypeError: cannot un