学习OpenGL ES for Android(七)

上篇我们简单的学习了纹理的显示,这篇我们先把图片等比显示,然后使纹理和颜色叠加显示。

如果图片是正方形,直接使用缩放或投影即可,但是如果非正方形则需要计算图片的宽高比,然后和显示的宽高比一起计算得到真正的缩放,计算公式:比例=显示宽/显示高/(图片宽/图片高)。随后设置观察点,计算

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        super.onSurfaceChanged(gl, width, height);
        // 根据图片宽高比和屏幕宽高比把纹理显示为正常比例(不拉伸)
        float ratio = (float) width / height / imageWH;

        // 设置透视投影矩阵,近点是3,远点是7
        Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
        Matrix.setLookAtM(tempMatrix, 0, 0, 0, 4f,
                0f, 0f, 0f,
                0f, 1f, 0f);
        Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, tempMatrix, 0);
    }

当然我们使用投影和颜色叠加需要修改我们的着色器代码,要定义投影变量和颜色变量。着色器代码如下

        vertexShaderCode =
                "uniform mat4 uMVPMatrix;" +
                        "attribute vec4 aPos;" +
                        "attribute vec2 aTextCoord;" +
                        "varying vec2 TextCoord;" +
                        "attribute vec3 aColor;" +
                        "varying vec3 ourColor;" +
                        "void main() {" +
                        "  gl_Position = uMVPMatrix * aPos;" +
                        "  ourColor = aColor;" +
                        "  TextCoord = aTextCoord;" +
                        "}";

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

我们还需要定义坐标和颜色,使用一个数组存放这些数据,

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

把数据转换为FloatBuffer后使用position方法进行定位然后分别设置位置、颜色和纹理,最后设置转换再进行绘制,

    @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, 8 * 4, vertexBuffer);

        vertexBuffer.position(3);
        int colorHandle = GLES20.glGetAttribLocation(shaderProgram, "aColor");
        GLES20.glEnableVertexAttribArray(colorHandle);
        GLES20.glVertexAttribPointer(colorHandle, 3, GLES20.GL_FLOAT,
                false, 8 * 4, vertexBuffer);

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

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

        int mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
        // 将视图转换传递给着色器
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, vPMatrix, 0);

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

这样我们就看到了一个没有缩放的纹理,而且和颜色叠加显示,效果图如下

注:我们的计算没有判断宽高的显示是否会超出屏幕(例如:当显示一个很长的图片时宽可能会超出屏幕),接下来我们可以修改这部分代码来处理,

        // 根据图片宽高比和屏幕宽高比把纹理显示为正常比例(不拉伸)
        float ratio = (float) width / height;
        float w = ratio / imageWH, h = 1;
        if (w < 0.5f) {
            // 宽度超出
            w = 0.5f;
            // 相应的需要增加垂直方向的比例
            h = 0.5f / (ratio / imageWH);
        }
        // 设置透视投影矩阵,近点是3,远点是7
        Matrix.frustumM(projectionMatrix, 0, -w, w, -h, h, 3, 7);

源码https://github.com/jklwan/OpenGLProject/blob/master/sample/src/main/java/com/chends/opengl/view/texture/TextureColorView.java

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

猜你喜欢

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