學習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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章