android-camera2相機開發【10】-opengl離屏渲染、拍照、前後相機切換

先說下題外話哈,最近做了個領取電商平臺優惠券的小程序,掃碼支持下哈~


離屏渲染

之前已經將相機的預覽數據已經輸出到opengl的紋理上,渲染的時候,opengl直接將紋理渲染到了屏幕。

但是,如果想要對該紋理進一步處理,就不能直接渲染到屏幕,而是應該先渲染到屏幕外的緩衝區(FrameBuffer)處理完後再渲染到屏幕。渲染到緩衝區的操作就是離屏渲染。

離屏渲染的目的是更改渲染目標(屏幕->緩衝區),主要步驟如下:

  1. 準備離屏渲染所需要的 FrameBuffer 和 紋理對象
  2. 切換渲染目標(屏幕->緩衝區)
  3. 執行渲染(和之前一樣,執行onDrawFrame方法進行繪製)
  4. 重置渲染目標(緩衝區->屏幕)

關鍵代碼如下:

    //準備離屏渲染所需要的 FrameBuffer 和 紋理對象 
    public void genFrameBufferAndTexture() {
        glGenFramebuffers(frameBuffer.length, frameBuffer, 0);

        glGenTextures(frameTexture.length, frameTexture, 0);
    }
    //切換渲染目標(屏幕->緩衝區)
    public void bindFrameBufferAndTexture() {
        glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer[0]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, frameTexture[0], 0);
    }
    //重置渲染目標(緩衝區->屏幕)
    public void unBindFrameBuffer() {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

拍照

無論中間經過離屏渲染做了多少處理,最後都會切換渲染到屏幕,不渲染到屏幕看不到,也就沒法預覽。

拍照是再預覽的基礎上,再點擊拍照的一瞬間將最後一個渲染環節切換到FrameBuffer,然後通過 glReadPixels 方法將顯存中的數據回傳到內存中保存到本地,最後再將渲染切換回屏幕繼續預覽。

需要注意的是在屏幕預覽時y軸正方向是向下的,所以保存到本地的時候需要在y軸上做一次反轉。

關鍵代碼如下:

        if (isTakingPhoto()) {
            ByteBuffer exportBuffer = ByteBuffer.allocate(width * height * 4);

            bindFrameBufferAndTexture();
            colorFilter.setMatrix(MatrixUtil.flip(matrix, false, true));
            colorFilter.onDraw();
            glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, exportBuffer);
            savePhoto(exportBuffer);
            unBindFrameBuffer();

            setTakingPhoto(false);
            colorFilter.setMatrix(MatrixUtil.flip(matrix, false, true));
        } else {
            colorFilter.onDraw();
        }

前後相機切換

這個比較簡單,需要注意的就是前置/後置攝像頭默認的旋轉角度不同預覽的時候需要進行旋轉校正。

    //後置相機,順時針旋轉90度
    public static final float[] textureCoordCameraBack = {
            1.0f, 1.0f,
            0.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f
    };

    //前置相機,逆時針旋轉90度
    public static final float[] textureCoordCameraFront = {
            0.0f, 0.0f,
            1.0f, 0.0f,
            1.0f, 1.0f,
            0.0f, 1.0f
    };

另外一個需要注意的就是前置相機的鏡像問題,通過矩陣進行設置

        if (this.useFront != useFront) {
            this.useFront = useFront;
            cameraFilter.setUseFront(useFront);
            matrix = MatrixUtil.flip(matrix, true, false);
        }

項目github地址

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