学习OpenGL ES for Android(六)

前几篇主要学习的点线面的绘制,变换和投影的实现,绘制的都是颜色,如果想要绘制图片的话就需要使用纹理。一些相关的方法如下

 glGenTextures( int n, int[] textures, int offset ):生成n个纹理的index。其中n是就是数量,数组来保存这些index,offset是偏移量。

glBindTexture( int target, int texture ):绑定一个纹理。target:GL_TEXTURE_2D(2D贴图)或GL_TEXTURE_CUBE_MAP(立体);texture就是生成的index。

glTexParameteri( int target, int pname, int param ):确定图片映射到帧缓冲图象空间。target:GL_TEXTURE_2D(2D贴图)或GL_TEXTURE_CUBE_MAP(立体);pname有这些:GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T;param的参数与pname有关。可以参考https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/这篇文章查看显示效果。

GL_TEXTURE_MIN_FILTER:当要纹理化的像素映射到大于一个纹理元素的区域时,就使用纹理最小化功能;此时param可以使用这些:GL_NEAREST,GL_LINEAR,GL_NEAREST_MIPMAP_NEAREST,GL_LINEAR_MIPMAP_NEAREST,GL_NEAREST_MIPMAP_LINEAR,GL_LINEAR_MIPMAP_LINEAR。

GL_TEXTURE_MAG_FILTER:当被纹理化的像素映射到小于或等于一个纹理元素的区域时,使用纹理放大功能。param可以是GL_NEAREST或GL_LINEAR。

GL_TEXTURE_WRAP_S:设置纹理坐标s的wrap方式。param可以设置为GL_CLAMP_TO_EDGE,GL_MIRRORED_REPEAT或GL_REPEAT。

GL_TEXTURE_WRAP_T:设置纹理坐标t的wrap方式。param可以设置为GL_CLAMP_TO_EDGE,GL_MIRRORED_REPEAT或GL_REPEAT。

 texImage2D(int target, int level, Bitmap bitmap, int border):根据设置的属性指定二维纹理图像。target:GL_TEXTURE_2D或GL_TEXTURE_CUBE_MAP;level,级别;bitmap:图片;border:默认0.

glActiveTexture( int texture ):指定要激活的纹理单位。texture最大只能有32个,从GL_TEXTURE0到GL_TEXTURE31。

glBindTexture( int target, int texture ):绑定纹理。target:GL_TEXTURE_2D或GL_TEXTURE_CUBE_MAP;texture:纹理id。

我们先要修改着色器代码

        vertexShaderCode =
                "attribute vec4 aPos;" +
                        "attribute vec2 aTextCoord;" +
                        "varying vec2 TextCoord;" +
                        "void main() {" +
                        "  gl_Position = aPos;" +
                        "  TextCoord = aTextCoord;" +
                        "}";

        fragmentShaderCode =
                "precision mediump float;" +
                        "uniform sampler2D ourTexture;" +
                        "varying vec2 TextCoord;" +
                        "void main() {" +
                        "  gl_FragColor = texture2D(ourTexture, TextCoord);" +
                        "}";

随后我们设置绘制的坐标以及纹理的坐标。 

private float[] vertices = {
            //---- 位置 ---   -- 纹理坐标 -
            0.5f, 0.5f, 0.0f, 1.0f, 1.0f,   // 右上
            0.5f, -0.5f, 0.0f, 1.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,   // 左下
            -0.5f, 0.5f, 0.0f, 0.0f, 1.0f    // 左上
    };

最后同样的需要传入绘制的坐标和纹理坐标。

    @Override
    public void onDrawFrame(GL10 gl) {
        super.onDrawFrame(gl);
        int shaderProgram = OpenGLUtil.createProgram(vertexShaderCode, fragmentShaderCode);
        GLES20.glUseProgram(shaderProgram);

        FloatBuffer vertexBuffer = OpenGLUtil.createFloatBuffer(vertices);
        vertexBuffer.position(0);
        int positionHandle = GLES20.glGetAttribLocation(shaderProgram, "aPos");
        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT,
                false, 5 * 4, vertexBuffer);

        vertexBuffer.position(3);
        int coordHandle = GLES20.glGetAttribLocation(shaderProgram, "aTextCoord");
        GLES20.glEnableVertexAttribArray(coordHandle);
        GLES20.glVertexAttribPointer(coordHandle, 2, GLES20.GL_FLOAT,
                false, 5 * 4, vertexBuffer);

        int textureHandle = GLES20.glGetUniformLocation(shaderProgram, "ourTexture");
        //GLES20.glUniform1i(textureHandle, 0);
        OpenGLUtil.bindTexture(textureHandle, texture, 0);

        // 用 glDrawElements 来绘制,mVertexIndexBuffer 指定了顶点绘制顺序
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
                GLES20.GL_UNSIGNED_SHORT, OpenGLUtil.createShortBuffer(indices));
        GLES20.glDisableVertexAttribArray(positionHandle);
    }

运行代码我们就看到我们的图片就显示出来了。但是我们看到图片会缩放,而且图片是颠倒的(原因是因为OpenGL要求纹理坐标原点在图片最下面,而图片信息的原点一般在最上面),因此我们要利用投影来使图像不会变形;使用改变纹理坐标的方式来使图片变为正的。

源码参考https://github.com/jklwan/OpenGLProject/blob/master/sample/src/main/java/com/chends/opengl/renderer/texture/TextureRenderer.java

发布了53 篇原创文章 · 获赞 17 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/jklwan/article/details/103534582