Android OpenGL ES2.0 实现步骤

定义顶点数据

顶点数据描述了OpenGL世界中元素的位置,下面定义了绘制一个三角形所需要的顶点数据,x,y,z对应三角形的每个顶点坐标,其中z代表深度,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,
    };

顶点数据转换

java的数据结构在opengl中无法直接使用,我们需要转成OpenGL能识别的buffer格式,我们将上面创建的顶点数据转换成了ByteBuffer类型。

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

编写顶点和片段着色器

顶点着色器定义了vec3类型的位置属性aPosition,它的长度为3,与上面的顶点数组中的x,y,z相对应。aTexCoord代表纹理坐标,它与顶点数组中的x1,y1列相对应。

    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";

创建顶点&着色器Shader

这个过程是将编写的顶点脚本和着色器脚本函数进行编译,编译完后将返回对应shader的句柄id

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="检查是否错误">
        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;
    }

创建GLProgram

创建gl程序的最核心的部分其实是将顶点shader和着色器shader与program进行关联,从progam中获取maPositionHandle和maTexCoordHandle的目的是为了方便后面进行顶点属性说明是用到。

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");

创建和绑定纹理

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();
        //激活纹理
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        //绑定纹理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);

顶点属性说明

/**
*指定maPositionHandle对应3个大小float,20代表整个数据段的长
*度,最后一个参数代表offset值(表示读取的偏移量)。
*整体可理解为:整个数据段长度为20字节,正好是我们定义的顶点数据的一行的长度(5个浮点型坐标),maPositionHandle需要12字节长度(3个浮点型坐标),读取的偏移量是0,所以取的数据正好是前面的x,y,z坐标。
**/
glVertexAttribPointer(maPositionHandle, 3, GL_FLOAT, false, 20, 0);
//启用顶点属性数组
glEnableVertexAttribArray(maPositionHandle);
glVertexAttribPointer(maTexCoordHandle, 2, GL_FLOAT, false, 20, 12);
//启用顶点属性数组
glEnableVertexAttribArray(maTexCoordHandle);

绘制元素

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);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值