当前位置: 首页 > news >正文

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

目录

      • FBO OverView
      • FBO 优点
      • 使用FBO的步骤

FBO OverView

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

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

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

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

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

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

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

FrameBuffer object

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 将绘制的内容保存下来

参考代码如下:

static int initInternal(ESContext* esContext) {UserData *userData = esContext->userData;......// gen bo & bind to textureglGenFramebuffers(1, &userData->FrameBufferObject);glBindFramebuffer(GL_FRAMEBUFFER, userData->FrameBufferObject);// Add color attachementglGenTextures(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 attachementglGenRenderbuffers(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 bufferglFinish();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);}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 一款好看的WordPress REST API 主题
  • 又双叒叕JavaScript 新增了 7 个方法!
  • 无人机技术的最新进展及未来趋势
  • 智能指针,然并卵
  • 精致潮人们,抠搜在电商平台
  • 前端常见**MS题 [3]
  • Android常见控件(一)
  • 怎么把JPG转成PDF?这3种转换方法一定不要错过
  • 单片机大小端模式
  • (六)Flink 窗口计算
  • react antd from表单全选按钮Button触发CheckBox状态回显
  • gin快速入门
  • Ps:高速缓存机制
  • 全面解读AI大模型:一文带你看懂发展脉络与未来走向!
  • 0成本学习Liunx系统【只需要一台笔记本电脑,无需购买云服务器】
  • 【译】JS基础算法脚本:字符串结尾
  • 【面试系列】之二:关于js原型
  • C++类的相互关联
  • eclipse(luna)创建web工程
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • markdown编辑器简评
  • npx命令介绍
  • React+TypeScript入门
  • vuex 笔记整理
  • 高程读书笔记 第六章 面向对象程序设计
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 爬虫模拟登陆 SegmentFault
  • 浅谈Golang中select的用法
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 赢得Docker挑战最佳实践
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 在weex里面使用chart图表
  • HanLP分词命名实体提取详解
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • $.ajax()方法详解
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (1) caustics\
  • (C#)获取字符编码的类
  • (vue)el-tabs选中最后一项后更新数据后无法展开
  • (二)linux使用docker容器运行mysql
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (一)Linux+Windows下安装ffmpeg
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转)Sublime Text3配置Lua运行环境
  • (转)人的集合论——移山之道
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • ***检测工具之RKHunter AIDE
  • .net 7和core版 SignalR
  • .Net 路由处理厉害了
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .Net的DataSet直接与SQL2005交互