OpenGL-ES 学习(8) ---- FBO

目录

FBO OverView

FBO(FrameBuffer Object) 指的是帧缓冲对象,实际上是一个可以添加缓冲区容器,可以为其添加纹理或者渲染缓冲区对象(RBO)
FBO(FrameBuffer Object) 本身不能用于渲染,只有添加了纹理或者纹理缓冲区之后才可以作为渲染目标,而且它仅且提供了三类附着,分别是颜色附着,模板附着和深度附着

和顶点缓冲区不同,FBO 不能通过共享上下文的方式进行共享

在 opengl-es 可以通过共享上下文方式进行共享的资源有:

  • 纹理
  • shader
  • program 着色器程序
  • buffer 类对象,比如 VBO,EBO,RBO 等

不能通过共享上下文方式进行共享的资源有:

  • VAO 顶点数组对象(非Buffer类对象)
  • FBO 帧缓冲对象(非Buffer类对象)

这里需要说明的是,在不可以共享的资源中,FBO和VAO属于资源管理型对象 ,FBO负责管理几种缓冲区,本身不占用资源,VAO负责管理VBO或者EBO,本身也不占用资源
RBO(Render Buffer Object) 是渲染缓冲区对象,是一个由应用程序分配的2D图像缓冲区,渲染缓冲区可以用于分配和存储颜色、深度或者模板值 ,可以用作FBO中的颜色、深度和模板附着

如果要使用FBO作为渲染目标,首先要为FBO添加连接对象,比如颜色附着需要连接纹理或者渲染缓冲区对象的颜色缓冲区

FBO 优点

默认情况下,opengl-es通过绘制到窗口系统提供的帧缓冲区,然后将帧缓冲区对应的区域复制到纹理来实现渲染到纹理,但是此方法只有在纹理尺寸小于或等于帧缓冲区尺寸才有效

另一种方式是使用连接到纹理的 Pbuffer 来实现渲染到纹理,但是与上下文和窗口系统提供的可绘制表面切换开销也很大,因此,引入了帧缓冲区对象 FBO 来解决此问题

在 opengl-es 的场景中,有一些成绩不需要渲染到屏幕,比如在后台利用GPU实现一些图像转换,缩放等操作,这个时候就可以使用FBO

相对于渲染到屏幕,FBO渲染不改变图像的分辨率,在图像处理算法中比较常用

FBO(FrameBuffer object) 渲染是渲染到离屏的Buffer中,可以使用glReadPixels的方式将渲染后图像读出来

使用FBO的步骤

  • 创建一个 FBO 并且创建一个2D 纹理用于连接 FBO 的颜色附着
  • glBindFramebuffer 绑定FBO
  • glDrawElements 进行绘制
  • glBindFramebuffer 解绑FBO

如果要等待绘制完成需要添加如下步骤:

  • glFinish 等待绘制完成
  • 可以通过 glReadPixels 将绘制的内容保存下来

参考代码如下:

c 复制代码
static int initInternal(ESContext* esContext) {
    UserData *userData = esContext->userData;

    ......

    // gen bo & bind to texture
    glGenFramebuffers(1, &userData->FrameBufferObject);
    glBindFramebuffer(GL_FRAMEBUFFER, userData->FrameBufferObject);

    // Add color attachement
    glGenTextures(1, &userData->textureIdFbo );
    glBindTexture(GL_TEXTURE_2D, userData->textureIdFbo);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, test_width, test_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, userData->textureIdFbo, 0);

    // Add depth attachement
    glGenRenderbuffers(1, &userData->textureIdDepth);
    glBindRenderbuffer(GL_RENDERBUFFER, userData->textureIdDepth);
    glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16, test_width, test_height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, userData->textureIdDepth);
  
    // 检查 FBO 完整性
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
        printf("Framebuffer not complete: %d\n", status);
        return GL_FALSE;
    }
    userData->dumpCount = 0;
    return GL_TRUE;
}

static int drawLoopInternal(ESContext* esContext) {
    ... 
    
    // dump fbo buffer
    glFinish();
    if(userData->dumpCount < 10) {
        glBindFramebuffer(GL_FRAMEBUFFER, userData->FrameBufferObject);
        unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char)*test_width*test_height*4);
        if(data == NULL) {
            printf("malloc data failed \n");
            return 0;
        }
     
        glReadPixels(0, 0, test_width, test_height, GL_RGBA, GL_UNSIGNED_BYTE, data);
        sprintf(fileName,"./dumpfile/output_%d.ppm", userData->dumpCount);
        saveImagePPM(fileName, data, test_width, test_height);
        printf("save %s success!\n", fileName);
        free(data);
        userData->dumpCount++;
    } else {
        printf("dump finished! exit!\n");
        exit(0);
    }
}
相关推荐
~kiss~5 小时前
A Survey of On-Policy Distillation for LLMs 学习(一)
学习
小杨小杨、努力变强!7 小时前
python学习笔记
笔记·学习
Star(up up up)13 小时前
Redis Windows 安装教程:使用Windows 的 Redis 压缩包
redis·笔记·学习·程序人生·云原生·学习方法·改行学it
乌暮15 小时前
Spring AOP 与 Spring 事务:用大白话彻底理解原理与实践
java·数据库·spring boot·后端·sql·学习·spring
蒸蒸yyyyzwd20 小时前
从邓明学习的后端笔记
笔记·学习
机器学习之心20 小时前
基于变量相关图与残差学习的 GCN 多变量回归方法——混凝土 28 天抗压强度预测
学习·回归·gcn
Rabitebla1 天前
【Linux】进程控制(十二) 自定义 Shell(二):内建命令与进程工作目录管理
linux·c++·笔记·学习·bash
Gary移动存储固件1 天前
eMMC5.1协议中文学习讲解(6.6.17~6.6.22.4.6)
学习·ufs·emmc·nand·存储固件
一个天蝎座 白勺 程序猿1 天前
别让收藏夹替你学习:我搭AI知识体系的完整方法,脚本直接拿去用
人工智能·学习·ai·ai学习
楚山之石1 天前
【Nat Biomed Eng】Connectome 2.0 超高梯度扫描仪:500 mT/m 与 600 T/m/s 把活体人脑微观结构分辨推进到亚微米级
图像处理·学习·数据分析·mri