Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android官方開發文檔Training系列課程中文版:OpenGL繪圖之圖形繪制

Android官方開發文檔Training系列課程中文版:OpenGL繪圖之圖形繪制

編輯:關於Android編程

原文地址:http://android.xsoftlab.net/training/graphics/opengl/draw.html

在定義了圖形之後,你接下來需要做的就是將它繪制到屏幕上。不過使用OpenGL ES 2.0 API來繪制這個圖形所需要的代碼量可能要比想象中的多一些,這是因為API為圖形渲染管道提供了大量的控制細節。

這節課會展示如何繪制上節課所定義的圖形。

初始化圖形

在開始任何繪制之前,你必須先初始化並加載這個圖形。除非是在執行的過程中圖形的結構發生了改變。這個時候你應該在渲染器的onSurfaceCreated()方法中去初始化它們,這樣可以使內存和進程的效率提升。

public class MyGLRenderer implements GLSurfaceView.Renderer {
    ...
    private Triangle mTriangle;
    private Square   mSquare;
    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        ...
        // initialize a triangle
        mTriangle = new Triangle();
        // initialize a square
        mSquare = new Square();
    }
    ...
}

繪制圖形

繪制自定義圖形需要大量的代碼,因為你必須給圖形渲染管道提供大量的渲染細節。尤其是下面這些必須定義:

Vertex Shader - 圖形頂點的渲染. Fragment Shader - 圖形表面的顏色或紋理的渲染。 Program - 一個含有多個渲染器的OpenGL ES對象,可以用它來繪制一個或者多個圖形。

你需要至少一個頂點渲染器來繪制圖形,並需要一個表面渲染器來為圖形著色。這些渲染器首先必須是可執行的,然後才能將其添加到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環境中編譯通過。為了編譯這些代碼,需要在渲染器類中創建一個功能方法:

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 it
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);
    return shader;
}

為了可以繪制圖形,必須先編譯這些渲染器代碼,然後再將其添加到OpenGL程序中,最後再鏈接到程序中。需要將這些工作放入繪制對象的構造方法中,所以這些工作只用做一次。

Note: OpenGL ES的編譯與鏈接過程需要消耗較高的CPU資源與時間,所以你應該避免這些工作做多次。如果在程序運行之前不知道渲染器的代碼,應該確保這部分的構建代碼只會執行一次,並需要將其緩存下來以便稍後使用。

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 Program
        mProgram = GLES20.glCreateProgram();
        // add the vertex shader to program
        GLES20.glAttachShader(mProgram, vertexShader);
        // add the fragment shader to program
        GLES20.glAttachShader(mProgram, fragmentShader);
        // creates OpenGL ES program executables
        GLES20.glLinkProgram(mProgram);
    }
}

這時就可以真正的開始繪制了。圖形的繪制需要提供若干的參數來告訴渲染管道想要繪制什麼及如何繪制。因為繪制選項可以定義多種多樣的圖形形式,所以可以自定義一個擁有獨立繪制邏輯的類來繪制各種圖形。

創建一個draw()方法開始繪制這個圖形。這部分代碼將會為頂點渲染器設置位置數據,並為表面渲染器設置顏色數據。然後開始執行繪制功能。

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 environment
    GLES20.glUseProgram(mProgram);
    // get handle to vertex shader's vPosition member
    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
    // Enable a handle to the triangle vertices
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                                 GLES20.GL_FLOAT, false,
                                 vertexStride, vertexBuffer);
    // get handle to fragment shader's vColor member
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    // Set color for drawing the triangle
    GLES20.glUniform4fv(mColorHandle, 1, color, 0);
    // Draw the triangle
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
    // Disable vertex array
    GLES20.glDisableVertexAttribArray(mPositionHandle);
}

一旦完成以上所有的代碼,最後只需要調用一下draw()方法就可以開始繪制了:

public void onDrawFrame(GL10 unused) {
    ...
    mTriangle.draw();
}

當程序啟動之後,設備上就會出現以下圖形:
\vcfQzrvh09DSu7XjsbvRubHitcS40L71oaPV4srH0vLOqtTa0P3XqrXEyrG68qOstPrC69bQy/m2qNLltcS2pbXjtcTP4LbUzrvWw7G70bnL9cHLoaPV4tCpzsrM4r2ru+HU2s/Cvdq/zrXDtb294r72oaM8L3A+DQo8cD7X7rrzo6zV4sj9vcfQzsrHucy2qLK7seS1xKOs1eK74dPQ0KnIw8jL09DQqbK7y6y1xLjQvvWho9TaPGEgaHJlZj0="http://android.xsoftlab.net/training/graphics/opengl/motion.html">Adding Motion的課程中將會使這個圖形可以隨著手勢旋轉而旋轉,還可以通過渲染管道做到其它更多有意思的事情。

   
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved