FBO帧缓冲对象,它的主要作用一般就是用作离屏渲染,例如做Camera相机图像采集进行后期处理时就可能会用到FBO。假如相机出图的是OES纹理,为了方便后期处理,
一般先将OES纹理通过FBO转换成普通的2D纹理,然后再通过FBO等增加美颜等其他各种特效滤镜,最后将FBO一路流送进编码器进行编码,另外一路渲染到屏幕上进行预览显示。
FBO总结起来就是可以暂时将未处理完的帧不直接渲染到屏幕上,而是渲染到离屏Buffer中缓存起来,在恰当的时机再取出来渲染到屏幕。
FBO(Frame Buffer Object)帧缓冲对象提供了与颜色缓冲区(color buffer)、深度缓冲区(depth buffer)和模版缓冲区(stencil buffer) ,但并不会直接为这些缓冲区分配空间,而只是为这些缓冲区提供一个或多个挂接点。我们需要分别为各个缓冲区创建对象,申请空间,然后挂接到相应的挂接点上。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLg73qy1-1664416288414)(https://flyer-blog.oss-cn-shenzhen.aliyuncs.com/FBO%E6%8C%82%E8%BD%BD%E7%82%B9.png)]
从上图可以看出FBO中包含了:
所谓的颜色附着(纹理附着)就是用于将颜色渲染到纹理中去的意思。后面我们主要介绍FBO的颜色附着。
glGenFramebuffers
生成一个FBO对象,保存对象ID。glBindFramebuffer
绑定FBO。glFramebufferTexture2D
关联纹理和FBO,并执行渲染步骤。后续如果需要使用FBO的效果时只需要操作与FBO绑定的纹理即可。glBindFramebuffer
解绑FBO,一般在Opengl中ID参数传递0就是解绑。glDeleteFramebuffers
删除FBO。当挂接完成之后,我们在执行FBO下面的操作之前,可以检查一下FBO的状态,使用函数GLenum glCheckFramebufferStatus(GLenum target)
检查。
本着学以致用的原则,我们将结合之前的文章,例如纹理贴图、VBO/VAO、EBO等相关知识点,使用这些知识点结合FBO绘制做一个实践的例子:首先将纹理渲染到FBO上去,然后再将FBO的纹理渲染到屏幕上。
插个话。。。总有人盗用不贴原文链接,看看是谁。。。
首先上代码,然后我们挑重要的稍微解读一下:
FBOOpengl.h
class FBOOpengl:public BaseOpengl{
public:
FBOOpengl();
void onFboDraw();
virtual ~FBOOpengl();
// override要么就都写,要么就都不写,不要一个虚函数写override,而另外一个虚函数不写override,不然可能编译不过
virtual void onDraw() override;
virtual void setPixel(void *data, int width, int height, int length) override;
private:
void fboPrepare();
GLint positionHandle{-1};
GLint textureHandle{-1};
GLuint vbo{0};
GLuint vao{0};
GLuint ebo{0};
// 本身图像纹理id
GLuint imageTextureId{0};
// fbo纹理id
GLuint fboTextureId{0};
GLint textureSampler{-1};
GLuint fboId{0};
// 用于fbo的vbo和vao 也可以用数组的形式,这里为了方便理解先独立开来
GLuint fboVbo{0};
GLuint fboVao{0};
int imageWidth{0};
int imageHeight{0};
};
注意:override作为现代C++的一个关键字,使用的时候需要注意一点,要么就整个类的虚函数都用,要么整个类的虚函数都不用,不要一个虚函数用override修饰,另外一个虚函数又不用override关键字修饰,不然很有可能会编译不过的。
在FBOOpengl中为了区分屏幕渲染和FBO离屏渲染,我们声明了两套VAO和VBO。
FBOOpengl.cpp
#include "FBOOpengl.h"
#include "../utils/Log.h"
// 顶点着色器
static const char *ver = "#version 300