Android之OpenGL里FBO理解测试实例
本文主要记录个人对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 bufferGLES20.glGenFramebuffers(1, frameBuffer, 0);GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffer[0]);// generate textureGLES20.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 attachmentGLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, frameBufferTexture[0], 0);// unbindGLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, 0);GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
使用framebuffer 绘制两个滤镜,如何通过滤镜绘制图片略过
绘制之前需要绑定framebuffer,让openGL绘制到framebuffer,绘制完成后解除绑定,伪代码
// bind framebufferGLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferId);// draw....// unbind framebufferGLES20.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获取绘制后的结果,可以方便我们更好的使用。
更多相关文章
- Android(安卓)SurfaceView onDraw()绘图问题
- Android中view绘制常用知识
- 图像滤镜(GPUImage/GPU加速)、美化/图像处理技术 拼接及Skia- An
- Android中的Data Binding初探 (一)
- android之Android(安卓)Studio下自定义属性的定义和使用
- Android(安卓)ColorDrawable那些事
- Android中实现iPhone开关
- Android(安卓)生成长图并添加水印(一)
- Android(安卓)页面手势滑动