我在Android上开发视频应用程序并使用OpenGL通过着色器从相机渲染和过滤视频 . 我的一个着色器使用两个纹理 - 一个是来自相机的实时帧,另一个是前一个渲染过程结果 . 所以我需要渲染图片两次 - 屏幕预览和分离纹理下一个渲染通道 . 为了实现它,我使用Frame Buffer对象 . 这是我的代码:

对于init帧缓冲区:

private void initPredrawBuffer() {

    GLES20.glActiveTexture(GLES20.GL_TEXTURE1);

    prevBuffer = new int[1];
    GLES20.glGenFramebuffers(1, prevBuffer, 0);
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevBuffer[0]);

    prevTexture = new int[1];
    GLES20.glGenTextures(1, prevTexture, 0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, prevTexture[0]);

    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_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
            GLES20.GL_CLAMP_TO_EDGE);


    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mFrameWidth, mFrameHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, prevTexture[0], 0);

    int[] depthRenderbuffers = new int[1];
    GLES20.glGenRenderbuffers(1, depthRenderbuffers, 0);
    GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRenderbuffers[0]);
    GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, mFrameWidth, mFrameHeight);
    GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRenderbuffers[0]);

    int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
    if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
        throw new RuntimeException("Incomplete buffer");
    }
}

并用于渲染:

private void draw(boolean offScreen, float[] mvpMatrix, FloatBuffer vertexBuffer, int firstVertex,
                  int vertexCount, int coordsPerVertex, int vertexStride,
                  float[] texMatrix, FloatBuffer texBuffer, int textureId, int texStride) {
    GlUtil.checkGlError("draw start");

    if (offScreen)
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevBuffer[0]);
    else
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

    // Select the program.
    GLES20.glUseProgram(firstFrame && firstFrameProgram > 0 ? firstFrameProgram : mProgramHandle);
    GlUtil.checkGlError("glUseProgram");

    // Set the texture.
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);

    // Copy the model / view / projection matrix over.
    GLES20.glUniformMatrix4fv(muMVPMatrixLoc, 1, false, mvpMatrix, 0);
    GlUtil.checkGlError("glUniformMatrix4fv");

    // Copy the texture transformation matrix over.
    GLES20.glUniformMatrix4fv(muTexMatrixLoc, 1, false, texMatrix, 0);
    GlUtil.checkGlError("glUniformMatrix4fv");

    // Enable the "aPosition" vertex attribute.
    GLES20.glEnableVertexAttribArray(maPositionLoc);
    GlUtil.checkGlError("glEnableVertexAttribArray");

    // Connect vertexBuffer to "aPosition".
    GLES20.glVertexAttribPointer(maPositionLoc, coordsPerVertex,
            GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
    GlUtil.checkGlError("glVertexAttribPointer");

    // Enable the "aTextureCoord" vertex attribute.
    GLES20.glEnableVertexAttribArray(maTextureCoordLoc);
    GlUtil.checkGlError("glEnableVertexAttribArray");

    // Connect texBuffer to "aTextureCoord".
    GLES20.glVertexAttribPointer(maTextureCoordLoc, 2,
            GLES20.GL_FLOAT, false, texStride, texBuffer);
    GlUtil.checkGlError("glVertexAttribPointer");

    // Setting Light Trails filter params
    if (mProgramType == ProgramType.TEXTURE_LIGHT_TRAILS && !firstFrame) {
        GLES20.glUniform1i(muTextureNew, 0);
        GlUtil.checkGlError("glUniform1i muTextureNew");

        GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
        GlUtil.checkGlError("temp glActiveTexture");

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, prevTexture[0]);
        GlUtil.checkGlError("temp glBindTexture");

        GLES20.glUniform1i(muTexturePrev, 1);
        GlUtil.checkGlError("glUniform1i muTexturePrev");

        GLES20.glUniform1f(muLightTrailsExposure, lightTrailsKernel[0]);
        GlUtil.checkGlError("glUniform1f muLightTrailsExposure");

        GLES20.glUniform1f(muLightTrailsEcho, lightTrailsKernel[1]);
        GlUtil.checkGlError("glUniform1f muLightTrailsEcho");

        GLES20.glUniform1f(muLightTrailsLimit, lightTrailsKernel[2]);
        GlUtil.checkGlError("glUniform1f muLightTrailsLimit");

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GlUtil.checkGlError("temp glActiveTexture");
    }

    // Draw the rect.
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, firstVertex, vertexCount);
    GlUtil.checkGlError("glDrawArrays");

    GLES20.glFinish();
}

问题是渲染到帧缓冲区不起作用, glReadPixels 总是返回一个空数组 . 渲染到屏幕工作正常 .