1. 程式人生 > >android平臺下OpenGL ES 3.0繪製圓點、直線和三角形

android平臺下OpenGL ES 3.0繪製圓點、直線和三角形

OpenGL ES 3.0學習實踐

目錄

新建SimpleRenderer

public class SimpleRenderer implements GLSurfaceView.Renderer

定義圓點座標

private float[] vertexPoints = new float[]{
        0.0f, 0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f
};

理想狀態下的螢幕座標系,我們定義的就是下圖中的三角形的三個頂點。

分配本地記憶體

因為OpenGL作為本地系統庫執行在系統中,虛擬機器需要分配本地記憶體,供其存取。

public SimpleRenderer() {
        //分配記憶體空間,每個浮點型佔4位元組空間
        vertexBuffer = ByteBuffer.allocateDirect(vertexPoints.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        //傳入指定的座標資料
        vertexBuffer.put(vertexPoints);
        vertexBuffer.position
(0); }

頂點著色器

#version 300 es
layout (location = 0) in vec4 vPosition;
void main() {
     gl_Position  = vPosition;
     gl_PointSize = 10.0;
}

上述頂點著色器的描述:

  • 第一行表示:著色器的版本,OpenGL ES 2.0版本可以不寫。
  • 第二行表示:輸入屬性的陣列(一個名為vPosition的4分量向量),layout (location = 0)表示這個變數的位置是頂點屬性0。
  • 第三行表示:宣告一個main函式。
  • 第四行表示:它將vPosition輸入屬性拷貝到名為gl_Position的特殊輸出變數。
  • 第五行表示:它將浮點資料10.0拷貝到gl_PointSize的變數中。

片段著色器

#version 300 es
precision mediump float;
out vec4 fragColor;
void main() {
     fragColor = vec4(1.0,1.0,1.0,1.0);
}

上述片段著色器的描述:

  • 第一行表示:著色器的版本,OpenGL ES 2.0版本可以不寫。
  • 第二行表示:宣告著色器中浮點變數的預設精度。
  • 第三行表示:著色器宣告一個輸出變數fragColor,這個是一個4分量的向量。
  • 第五行表示:表示將顏色值(1.0,1.0,1.0,1.0),輸出到顏色緩衝區。

編譯和載入著色器

	/**
     * 編譯
     *
     * @param type  頂點著色器:GLES30.GL_VERTEX_SHADER
     *               片段著色器:GLES30.GL_FRAGMENT_SHADER
     * @param shaderCode
     * @return
     */
    private static int compileShader(int type, String shaderCode) {
    	//建立一個著色器
        final int shaderId = GLES30.glCreateShader(type);
        if (shaderId != 0) {
        	//載入到著色器
            GLES30.glShaderSource(shaderId, shaderCode);
            //編譯著色器
            GLES30.glCompileShader(shaderId);
            //檢測狀態
            final int[] compileStatus = new int[1];
            GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
            if (compileStatus[0] == 0) {
                String logInfo = GLES30.glGetShaderInfoLog(shaderId);
                System.err.println(logInfo);
                //建立失敗
                GLES30.glDeleteShader(shaderId);
                return 0;
            }
            return shaderId;
        } else {
            //建立失敗
            return 0;
        }
    }

連結到著色器

    /**
     * 連結小程式
     *
     * @param vertexShaderId 頂點著色器
     * @param fragmentShaderId 片段著色器
     * @return
     */
    public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
        final int programId = GLES30.glCreateProgram();
        if (programId != 0) {
            //將頂點著色器加入到程式
            GLES30.glAttachShader(programId, vertexShaderId);
            //將片元著色器加入到程式中
            GLES30.glAttachShader(programId, fragmentShaderId);
            //連結著色器程式
            GLES30.glLinkProgram(programId);
            final int[] linkStatus = new int[1];
            GLES30.glGetProgramiv(programId, GLES30.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] == 0) {
                String logInfo = GLES30.glGetProgramInfoLog(programId);
                System.err.println(logInfo);
                GLES30.glDeleteProgram(programId);
                return 0;
            }
            return programId;
        } else {
            //建立失敗
            return 0;
        }
    }

設定視口

這一步通常在onSurfaceChanged中完成

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
     GLES30.glViewport(0, 0, width, height);
}

清除顏色緩衝區

GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

緩衝區將會用GLES30.glClearColor指定的顏色清除,清除的顏色被設定為(0.5f, 0.5f, 0.5f, 0.5f),所以螢幕顯示為灰色。

繪製圓點

public void onDrawFrame(GL10 gl)回撥方法中:

//準備座標資料
GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);
//啟用頂點的控制代碼
GLES30.glEnableVertexAttribArray(0);
//繪製三個點
GLES30.glDrawArrays(GLES30.GL_POINTS, 0, 3);

//禁止頂點陣列的控制代碼
GLES30.glDisableVertexAttribArray(0);

剛才的頂點著色器已經將vPosition變數與輸入屬性位置0綁定了,頂點著色器中每個屬性都由一個無符號整數值唯一標識的位置

繪製直線

//繪製直線
GLES30.glDrawArrays(GLES30.GL_LINE_STRIP, 0, 2);
GLES30.glLineWidth(10);

繪製如圖所示:

繪製三角形

//繪製三角形
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 2);

常用圖元型別

圖元型別 描述
GL_POINTS 點精靈圖元,對指定的每個頂點進行繪製。
GL_LINES 繪製一系列不相連的線段。
GL_LINE_STRIP 繪製一系列相連的線段。
GL_LINE_LOOP 繪製一系列相連的線段,首尾相連。
GL_TRIANGLES 繪製一系列單獨的三角形。
GL_TRIANGLE_STRIP 繪製一系列相互連線的三角形。
GL_TRIANGLE_FAN 繪製一系列相互連線的三角形。

直線圖元型別:

三角形圖元型別

專案地址:
https://github.com/byhook/opengles4android

參考:
《OpenGL ES 3.0 程式設計指南第2版》
《OpenGL ES應用開發實踐指南Android卷》