Android之OpenGL里FBO理解测试实例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/I_do_can/article/details/79084048

本文主要记录个人对OpenGL里FBO的理解,附上测试事例
测试源码: github
FBO : Frame Buffer Object, 是一个存储一帧数据的容器。

原理这里不介绍,(主要我也没怎么看懂),使用FBO的步骤:
- 使用FBO的步骤
- 创建 glGenFramebuffers()
- 绑定 glBindFramebuffer()
- (这里使用绑定texture2D), glFramebufferTexture2D()把一幅纹理图像关联到一个FBO
- 检查FBO状态 glCheckFramebufferStatus()
这里使用的FBO与Texture一起绑定使用,OpenGL的绘制是如果我们绑定了Framebuffer即glBindFramebuffer(),openGL的绘制内容会绘制到framebuffer里,绑定framebuffer和texture,是为了通过绑定的texture从frambuffer里拿数据
基本生成frambuffer和绑定texture代码:

int[] frameBuffer = new int[1];
int[] frameBufferTexture = new int[1];

// generate frame buffer
GLES20.glGenFramebuffers(1, frameBuffer, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer[0]);

// generate texture
GLES20.glGenTextures(1, frameBufferTexture, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameBufferTexture[0]);
// 绑定一个空的glTexImage2D,方便framebuffer 填充数据
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
        GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);

GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_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);

// set texture as colour attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
        GLES20.GL_TEXTURE_2D, frameBufferTexture[0], 0);

// unbind
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

使用framebuffer 绘制两个滤镜,如何通过滤镜绘制图片略过
绘制之前需要绑定framebuffer,让openGL绘制到framebuffer,绘制完成后解除绑定,伪代码

// bind framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferId);

// draw....

// unbind framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

测试代码对比了方案一和方案二的时间,结果如下,可以看懂性能提升很明显
这里写图片描述

方案二的基本代码

private void showImageFilter2(Bitmap bmp, GLESBackEnv backEnv) {
    int w =bmp.getWidth();
    int h =bmp.getHeight();

    NoFilter noFilter = new NoFilter();
    noFilter.setBitmap(bmp);
    noFilter.onCreate();
    noFilter.onSizeChange(w, h);

    // bind framebuffer
    FrameBuffer buffer = new FrameBuffer();
    buffer.create(w, h);
    buffer.beginDrawToFrameBuffer();
    noFilter.onDrawFrame();
    buffer.endDrawToFrameBuffer();

    // image filter 2, use textureId form framebuffer
    ColorFiler colorFiler = new ColorFiler(ColorFiler.Filter.GRAY);
    colorFiler.setTextureId(buffer.getTextureId());
    colorFiler.onCreate();
    colorFiler.onSizeChange(w, h);
    float[] coord=new float[]{
            0.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 1.0f,
            1.0f, 0.0f,
    };
    colorFiler.setTexBuffer(coord);

    colorFiler.onDrawFrame();

    bmp = backEnv.getBitmap();
    imageFilter2.setImageBitmap(bmp);

    buffer.release(true);
}

这里有个需要主意的是,bitmap的数据是从第一行开始存储, 而处理framebuffer 数据需要上下颠倒一下。
效果图
这里写图片描述

总结起来,FBO就是用来缓存opengl绘制的结果,通过绑定framebuffer和 textureId, 可以之间通过绑定的textureId获取绘制后的结果,可以方便我们更好的使用。

猜你喜欢

转载自blog.csdn.net/I_do_can/article/details/79084048