Android OpenGL ES2.0 implementation steps

Keywords: Attribute Java

Define vertex data

Vertex data describes the location of elements in the OpenGL world. The following defines the vertex data needed to draw a triangle. x,y,z correspond to each vertex coordinate of the triangle, where z represents the color code of the shader corresponding to depth, x1,y1.

float vertices[] = {
            // x      y     z     x1    y1
            0.0f, 1.0f, 0.0f, 0.3f, 1.0f,
            -0.8f, -0.8f, 0f, 0.0f, 0.0f,
            0.8f, -0.8f, 0.0f, 0.6f, 0.0f,
    };

Vertex data conversion

java's data structure can't be used directly in OpenGL. We need to convert it to the buffer format recognized by OpenGL. We convert the vertex data created above to the ByteBuffer type.

ByteBuffer verticesByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder());
            verticesFloatBuffer = verticesByteBuffer.asFloatBuffer().put(vertices);
            verticesFloatBuffer.position(0);

Writing vertex and clip shaders

The vertex shader defines the position attribute of vec3 type, aPosition, whose length is 3, corresponding to x,y,z in the vertex array above. aTexCoord stands for texture coordinates, which correspond to columns X1 and Y1 in the vertex array.

    private final String mVertexShader =
            "varying vec2 texCoord;\n" +
                    "attribute vec3 aPosition;\n" +
                    "attribute vec2 aTexCoord;\n" +

                    "void main() {\n" +
                    "  gl_Position = vec4(aPosition,1);\n" +
                    "  texCoord = aTexCoord;\n" +
                    "}\n";

    private final String mFragmentShader =
            "varying vec2 texCoord;\n" +
                    "uniform sampler2D sTexture;\n" +

                    "void main() {\n" +
                    "  gl_FragColor = texture2D(sTexture,texCoord);\n" +
                    "}\n";

Create vertex & Shader shaders

This process is to compile the vertex script and shader script functions. After compiling, the handle id of the corresponding shader will be returned

int vertexShader = createMyShader(GL_VERTEX_SHADER, mVertexShader);
int fragmentShader = createMyShader(GL_FRAGMENT_SHADER, mFragmentShader);

    private int createMyShader(int type, String textCode) {
        int shader = glCreateShader(type);
        glShaderSource(shader, textCode);
        glCompileShader(shader);
        //< editor fold desc = "check for errors" >
        int[] compiled = new int[1];
        glGetShaderiv(shader, GL_COMPILE_STATUS, compiled, 0);
        checkGlError("createMyShader");
        if (compiled[0] == 0) {
            glDeleteShader(shader);
            shader = 0;
        }
        //</editor-fold>
        return shader;
    }

Create GLProgram

The core part of creating gl program is actually to associate vertex shader and shader shader with program. The purpose of getting maPositionHandle and maTexCoordHandle from program is to facilitate vertex attribute description later.

int program = createMyProgram(vertexShader, fragmentShader);

private int createMyProgram(int vertexShader, int fragmentShader) {
        int program = glCreateProgram();
        if (program != 0) {
            GLES20.glAttachShader(program, vertexShader);
            checkGlError("glAttachShader");
            GLES20.glAttachShader(program, fragmentShader);
            checkGlError("glAttachShader");
            GLES20.glLinkProgram(program);
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] != GLES20.GL_TRUE) {
                Log.e("TEST", "Could not link program: ");
                Log.e("TEST", GLES20.glGetProgramInfoLog(program));
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }
int maPositionHandle = glGetAttribLocation(program, "aPosition");
int maTexCoordHandle = glGetAttribLocation(program, "aTexCoord");

Create and bind textures

int[] textures = new int[1];
        GLES20.glGenTextures(1, textures, 0);
        mTextureID = textures[0];
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);

        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);

        InputStream is = getResources()
                .openRawResource(R.raw.ab);
        Bitmap bitmap;
        try {
            bitmap = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                // Ignore.
            }
        }

        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
        //Activate texture
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        //Bind texture
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);

Vertex attribute description

/**
*Specify that maPositionHandle corresponds to three size float s, and 20 represents the length of the whole data segment
*Degree, the last parameter represents the offset value (the offset read).
*As a whole, it can be understood that the length of the whole data segment is 20 bytes, which is exactly the length of a row of vertex data defined by us (5 floating-point coordinates). maPositionHandle needs 12 bytes (3 floating-point coordinates). The offset read is 0, so the data taken is exactly the x,y,z coordinates in front.
**/
glVertexAttribPointer(maPositionHandle, 3, GL_FLOAT, false, 20, 0);
//Enable vertex attribute array
glEnableVertexAttribArray(maPositionHandle);
glVertexAttribPointer(maTexCoordHandle, 2, GL_FLOAT, false, 20, 12);
//Enable vertex attribute array
glEnableVertexAttribArray(maTexCoordHandle);

Draw elements

GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 5);
GLES20.glUseProgram(0);

Posted by mikegotnaild on Tue, 05 May 2020 04:47:22 -0700