Android OpenGl ES 3.0绘制三角形

时间:2022-03-29 04:04:02

先上效果图


Android OpenGl ES 3.0绘制三角形


首先AndroidManifest.xml里声明版本:

<uses-feature
        android:glEsVersion="0x00030000"
        android:required="true" />
然后在Acitivity里声明版本:

GLSurfaceView glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setEGLContextClientVersion(3);
setContentView(glSurfaceView);
glSurfaceView.setRenderer(new TriangleRenderer(this));

然后在Renderer的onSurfaceCreated回调里初始化顶点和颜色数据:

float[] triangleCoords = new float[] {
        0.0f, 1, 0.0f,
        -1.0f, -1, 0.0f,
        1.0f, -1, 0.0f
};
mVertexBuffer = Utils.floatArray2FloatBuffer(triangleCoords);

float[] color = new float[] {
        1, 0, 0, 0,
        0, 0, 1, 0,
        0, 1, 0, 0
};
mColorBuffer = Utils.floatArray2FloatBuffer(color);

public static FloatBuffer floatArray2FloatBuffer(float[] array) {
    FloatBuffer floatBuffer = ByteBuffer.allocateDirect(array.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
    floatBuffer.put(array).position(0);
    return floatBuffer;
}
并且创建program:
mProgram = Utils.createProgram(mContext, R.raw.triangle_v, R.raw.triangle_f);
muMVPMatrixHandler = GLES30.glGetUniformLocation(mProgram, "uMVPMatrix");
mPosHandler = GLES30.glGetAttribLocation(mProgram, "aPosition");
mColorHandler = GLES30.glGetAttribLocation(mProgram, "aColor");

public static int createProgram(Context context, int vertextRawId, int fragmentRawId) {
    int vertexShader = loadShader(context, GL_VERTEX_SHADER, vertextRawId);
    if (vertexShader == 0) return 0;

    int fragmentShader = loadShader(context, GL_FRAGMENT_SHADER, fragmentRawId);
    if (fragmentShader == 0) return 0;

    int program = glCreateProgram();
    if (program != 0) {
        glAttachShader(program, vertexShader);
        glAttachShader(program, fragmentShader);
        glLinkProgram(program);
        int[] linkStatus = new int[1];
        glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
        if (linkStatus[0] != GL_TRUE) {
            Log.e(TAG, "createProgram : Cannot link program");
            Log.e(TAG, "createProgram glError : " + glGetProgramInfoLog(program));
            glDeleteProgram(program);
            program = 0;
        }
    }
    return program;
}

public static int loadShader(Context context, int type, int rawId) {
    String shaderCode = readStringFromInputStream(context.getResources().openRawResource(rawId));
    return loadShader(type, shaderCode);
}

public static String readStringFromInputStream(InputStream inputStream) {
    InputStreamReader reader = new InputStreamReader(inputStream);
    BufferedReader bufferedReader = new BufferedReader(reader);
    StringBuilder builder = new StringBuilder("");
    String str;
    try {
        while ((str = bufferedReader.readLine()) != null) {
            builder.append(str);
            builder.append("\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return builder.toString();
}

public static int loadShader(int type, String shaderCode) {
    int shader = glCreateShader(type);
    glShaderSource(shader, shaderCode);
    glCompileShader(shader);
    int[] compiled = new int[1];
    glGetShaderiv(shader, GL_COMPILE_STATUS, compiled, 0);
    if (compiled[0] == 0) {
        Log.e(TAG, glGetShaderInfoLog(shader));
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}
triangle_v.glsl代码如下:
#version 300 es
uniform mat4 uMVPMatrix;
layout (location = 0) in vec4 aPosition;
layout (location = 1) in vec4 aColor;
out vec4 vColor;
void main() {
    gl_Position = uMVPMatrix * aPosition;
    vColor = aColor;
}
triangle_f.glsl代码如下:
#version 300 es
precision mediump float;
in vec4 vColor;
out vec4 fragColor;
void main() {
    fragColor = vColor;
}
然后在onSurfaceChanged里执行如下代码:
float ratio = (float) height / width;
Matrix.frustumM(frustumM, 0, -1, 1, -ratio, ratio, 3, 7);
Matrix.setLookAtM(lookAtM, 0, 0, 0, 5, 0, 0, 0, 0, 1, 0);
Matrix.multiplyMM(mMVPMatrix, 0, frustumM, 0, lookAtM, 0);
最后在onDrawFrame里执行:
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
GLES30.glUseProgram(mProgram);
GLES30.glUniformMatrix4fv(muMVPMatrixHandler, 1, false, mMVPMatrix, 0);
GLES30.glVertexAttribPointer(mPosHandler, 3, GLES30.GL_FLOAT, false, 3 * 4, mVertexBuffer);
GLES30.glEnableVertexAttribArray(mPosHandler);
GLES30.glVertexAttribPointer(mColorHandler, 4, GLES30.GL_FLOAT, false, 4 * 4, mColorBuffer);
GLES30.glEnableVertexAttribArray(mColorHandler);

GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 3);
至此就可以绘制出上面截图中的三角形了。