QT之OpenGL帧缓冲
QT之OpenGL帧缓冲
- 1. 概述
- 1.1 帧缓冲的创建与删除
- 1.2 帧缓冲的数据来源
- 1.2.1 数据源与帧缓冲的关系
- 1.2.2 纹理Attachment
- 1.2.3 渲染缓冲对象Attachment
- 1.2.4 两者的区别
- 1.2.5 关于两者的使用场景
- 2. Demo
- 3. 后期处理
- 4. 参考
1. 概述
OpenGL管线的最终渲染目的地被称作帧缓冲(framebuffer),它由用于写入颜色值的颜色缓冲、用于写入深度信息的深度缓冲和允许根据一些条件丢弃特定片段的模板缓冲组合而成,它被储存在内存中。
1.1 帧缓冲的创建与删除
-
创建
unsigned int fbo; /* 第一个是要创建的帧缓存的数目 第二个是指向存储一个或者多个ID的变量或数组的指针 默认帧缓冲的id是0 */ glGenFramebuffers(1, &fbo); -
绑定激活
/* GL_READ_FRAMEBUFFER : 绑定到GL_READ_FRAMEBUFFER的帧缓冲将会使用在所有像是glReadPixels的读取操作中 GL_DRAW_FRAMEBUFFER : 而绑定到GL_DRAW_FRAMEBUFFER的帧缓冲将会被用作渲染、清除等写入操作的目标 GL_FRAMEBUFFER : 通常都会使用GL_FRAMEBUFFER,绑定到两个上 */ glBindFramebuffer(GL_FRAMEBUFFER, fbo); -
删除
glDeleteFramebuffers(1, &fbo); -
OpenGL允许自定义帧缓冲,一个完整帧缓冲需要满足以下条件:
- 附加至少一个缓冲(颜色、深度或模板缓冲)
- 至少有一个颜色
attachment - 所有的
attachment都必须是完整的(保存在内存) - 每个缓冲都应有相同的样本数
-
完整性检查
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
1.2 帧缓冲的数据来源

1.2.1 数据源与帧缓冲的关系
-
只是用纹理Attachment

-
只是用渲染缓冲对象Attachment

-
纹理Attachment与渲染缓冲对象Attachment结合使用

注:
GL_COLOR_ATTACHMENT的数量可以通过GL_MAX_COLOR_ATTACHMENTS获取- 一个帧缓冲至少要有一个颜色缓冲Attachment
- 这里的
Attachment仅仅是一个附着点,并不是将数据拷贝到FBO中 FBO提供了一种高效的切换机制,将前面帧缓冲关联的图形从FBO分离,然后把心的帧缓冲图像关联到FBO。在帧缓冲关联图像之间切换比在FBO之间切换要快的多。 切换函数如下:// 切换纹理图像 glFramebufferTexture2D(); // 切换渲染缓冲区 glFramebufferRenderbuffer();
1.2.2 纹理Attachment
把一个纹理附加附加到缓冲区的时候,所有的渲染指令都将会写入到这个纹理中,就像他是一个普通的颜色/深度或模板缓冲一样。使用纹理的优点是,所有渲染操作的结果将会被存储在一个纹理图像中,可以很方便的在着色器中只是用。
- 纹理创建
unsigned int texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture);/* 这里的data部分设置为NULL,表示仅仅分配了内存而没有进行数据填充。纹理的填充会在渲染到帧缓冲之后进行如果想将屏幕渲染到一个更小或更大的纹理上,需要(在渲染到帧缓冲之前)再次调用glViewport,使用纹理的新维度作为参数,否则只有一小部分的纹理或屏幕会被渲染到这个纹理上 */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);// 设置纹理过滤方式 压缩 采用线性采样 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 设置纹理过滤方式 放大 采用线性采样 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - 附加到帧缓冲
/* target:帧缓冲的目标(绘制、读取或者两者皆有) attachment:我们想要附加的附件类型。当前我们正在附加一个颜色附件。注意最后的0意味着我们可以附加多个颜色附件。我们将在之后的教程中提到。 textarget:你希望附加的纹理类型 texture:要附加的纹理本身 level:多级渐远纹理的级别。我们将它保留为0。 */ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); /*除了颜色附件之外,还可以附加一个深度和模板缓冲纹理到帧缓冲对象中。要附加深度缓冲,需要将附件类型设置为GL_DEPTH_ATTACHMENT。注意纹理的格式(Format)和内部格式(Internalformat)类型将变为GL_DEPTH_COMPONENT,来反映深度缓冲的储存格式。要附加模板缓冲的话,需要将第二个参数设置为GL_STENCIL_ATTACHMENT,并将纹理的格式设定为GL_STENCIL_INDEX。也可以将深度缓冲和模板缓冲附加为一个单独的纹理。纹理的每32位数值将包含24位的深度信息和8位的模板信息。要将深度和模板缓冲附加为一个纹理的话,我们使用GL_DEPTH_STENCIL_ATTACHMENT类型,并配置纹理的格式,让它包含合并的深度和模板值。将一个深度和模板缓冲附加为一个纹理到帧缓冲的例子如下所示: */glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 800, 600, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL );glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
1.2.3 渲染缓冲对象Attachment
渲染缓冲对象(Renderbuffer Object)是在纹理之后引入OpenGL的,它也是一个真正的缓冲,它会将数据存储为OpenGL原生的渲染格式,它是为了离屏渲染到帧缓冲优化过的。
- 创建
unsigned int rbo; glGenRenderbuffers(1, &rbo); - 绑定
glBindRenderbuffer(GL_RENDERBUFFER, rbo); - 创建深度和模板缓冲对象
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600); - 附加到渲染缓冲对象
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
注:
-
因为它的数据已经是原生的格式了,当写入或者复制它的数据到其它缓冲中时是非常快的。所以,交换缓冲这样的操作在使用渲染缓冲对象时会非常快。我们在每个渲染迭代最后使用的
glfwSwapBuffers,也可以通过渲染缓冲对象实现:只需要写入一个渲染缓冲图像,并在最后交换到另外一个渲染缓冲就可以了。渲染缓冲对象对这种操作非常完美。
1.2.4 两者的区别
- 纹理是可读可写的,而渲染缓冲对象则是只写的,但可以使用glReadPixels来读取它(从当前绑定的帧缓冲而不是
Attachment本身中返回特定区域的像素)
1.2.5 关于两者的使用场景
- 如果不需要从一个缓冲中采样,此时使用
渲染缓冲对象更好些 - 如果需要从一个缓冲中进行采样颜色或深度值等数据,此时使用
纹理Attachment更合理 - 两者在性能方面不会差别非常大
2. Demo
将场景渲染到一个小窗口中,源码链接

3. 后期处理
Demo效果展示如下:
-
反相(Inversion)

-
灰度(Grayscale)

-
加权(Weighted)

-
核(kernel)
在一个纹理图像上做后期处理的另外一个好处是,我们可以从纹理的其它地方采样颜色值。比如说我们可以在当前纹理坐标的周围取一小块区域,对当前纹理值周围的多个纹理值进行采样。
核(Kernel)(或卷积矩阵(Convolution Matrix))是一个类矩阵的数值数组,它的中心为当前的像素,它会用它的核值乘以周围的像素值,并将结果相加变成一个值。锐化(Sharpen)

模糊(Blur)

边缘检测(Edge-detection)

4. 参考
-
OpenGL Learn
-
http://www.songho.ca/opengl/gl_fbo.html
-
http://www.songho.ca/opengl/gl_fbo.html的翻译版
-
FBO使用示例
-
单独使用 渲染缓冲对象示例
相关文章:
QT之OpenGL帧缓冲
QT之OpenGL帧缓冲1. 概述1.1 帧缓冲的创建与删除1.2 帧缓冲的数据来源1.2.1 数据源与帧缓冲的关系1.2.2 纹理Attachment1.2.3 渲染缓冲对象Attachment1.2.4 两者的区别1.2.5 关于两者的使用场景2. Demo3. 后期处理4. 参考1. 概述 OpenGL管线的最终渲染目的地被称作帧缓冲(fram…...
$ 6 :选择、循环
if-else语句 #include <stdio.h> //判断输入值是否大于0 int main() {int i;while (scanf("%d",&i)){if (i > 0)//不要在括号后加分号{printf("i is bigger than O\n");}else {printf("i is not bigger than O\n");}}return O; } …...
【项目设计】高并发内存池 (四)[pagecache实现]
🎇C学习历程:入门 博客主页:一起去看日落吗持续分享博主的C学习历程博主的能力有限,出现错误希望大家不吝赐教分享给大家一句我很喜欢的话: 也许你现在做的事情,暂时看不到成果,但不要忘记&…...
玩转qsort——“C”
各位CSDN的uu们你们好呀,今天小雅兰的内容还是我们的深度剖析指针呀,上篇博客我们学习了回调函数这个知识点,但是没有写完,因为:小雅兰觉得qsort值得单独写出来!!!好啦,就…...
【干货】又是一年跳槽季!Nginx 10道核心面试题及解析
Nginx是一款轻量级的高性能Web服务器和反向代理服务器,由俄罗斯的Igor Sysoev开发。它具有占用资源少、高并发、稳定性高等优点,被广泛应用于互联网领域。在Nginx的面试过程中,面试官通常会提出一些核心问题,本文将介绍一些常见的…...
【线程安全的HashMap有哪些,CurrentHashMap底层是怎么实现线程安全的】
在 Java 中,线程安全的 HashMap 通常有以下几种实现: Collections.synchronizedMap 方法:该方法可以将 HashMap 转换为线程安全的 Map。 Hashtable 类:Hashtable 是一种线程安全的集合类,它与 HashMap 类似࿰…...
C语言-结构体【详解】
一、 结构体的基础知识 结构是一些值的集合,这些值称为成员变量结构的每个成员可以是不同类型的变量 (1)结构体的声明 写法一: 注: 括号后边的分号不能忘结构体末尾可以不创建变量,在主函数中再创建 struc…...
浏览器输入url到页面渲染完成经历了哪些步骤
一、URL解析 这一步比较容易理解,在浏览器地址栏输入url后,浏览器会判断这个url的合法性 ,以及是否有可用缓存,如果判断是 url 则进行域名解析,如果不是 url ,则直接使用搜索引擎搜索 二、域名解析 输入…...
大数据技术之Hadoop(Yarn)
第1章Yarn资源调度器思考:1)如何管理集群资源?2)如何给任务合理分配资源?Yarn是一个资源调度平台,负责为运算程序提供服务器运算资源,相当于一个分布式的操作系统平台,而MapReduce等…...
5.建造者模式
目录 简介 四个角色 应用场景 实现步骤 和工厂模式的区别 简介 建造者模式也叫生成器模式,是一种对象构建模式;它可以把复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象;…...
数据库基础-数据库基本概念(1-1)
你好,欢迎来到数据库基础系列专栏,欢迎留言互动哦~ 目录一、数据库基础1. 数据库基本概念1.1 数据库1.2 什么是数据库管理软件1.3 表1.4 行1.5 列和数据类型1.6 主键1.7 什么是 SQL一、数据库基础 1. 数据库基本概念 1.1 数据库 数据库是一个以某种有…...
学习笔记-架构的演进之服务容错策略-服务发现-3月day01
文章目录前言服务容错容错策略附前言 “容错性设计”(Design for Failure)是微服务的一个核心原则。 使用微服务架构,拆分出的服务越来越多,也逐渐导致以下问题: 某一个服务的崩溃,会导致所有用到这个服务…...
采编式AIGC视频生产流程编排实践
作者 | 百度人工智能创作团队 导读 本文从业务出发,系统介绍了采编式 TTV的实现逻辑和实现路径。结合业务拆解,实现了一个轻量级服务编排引擎,有效实现业务诉求、高效支持业务扩展。 全文6451字,预计阅读时间17分钟。 01 背景 近…...
Leetcode23. 合并k个升序链表
一、题目描述: 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。 示例 1: 输入:lists [[1,4,5],[1,3,4],[2,6]]输出:[1,1,2,3,4,4,5,6]解释&#…...
从用户出发,互联网产品策划方法论
【一】从用户到需求 产品经理需要具备两个非常重要的技能,一个叫策划,一个叫感知用户。 我们在分析问题的时候往往会说“这么做,我认为用户会怎么怎么样”、“用户会认为这样很不爽”,当我们这样说时,很有可能是把自己当成了用户,用某些特定的情感或记忆代表了用户。 当我…...
STM32 E18-D80NK红外检测
本文代码使用 HAL 库。 文章目录前言一、E18-D80NK 红外传感器:1. E18-D80NK 的介绍2. 电器特性二、红外检测小实验代码讲解三、实验现象总结前言 这篇文章介绍 如何使用 STM32 控制 E18-D80NK 进行红外检测。 一、E18-D80NK 红外传感器: 1. E18-D80N…...
Linux常用命令--进程和计划任务管理
一、程序和进程的关系 1、程序 ①保存在硬盘、光盘等介质中的可执行代码和数据 ②静态保存的代码 2、进程 ①在cpu及内存中运行及进程代码 ②动态执行的代码 ③父(fork)、子进程,每个程序可以创建一个或多个进程 父进程和子进程的区别&am…...
Unity TextMeshPro
Unity TextMeshPro 简介 TextMeshPro(也简称为TMP)号称是Unity的终极文本解决方案,它是Unity 的 UI 文本和旧版文本网格体的完美替代品。 功能强大且易于使用,使用高级文本渲染技术以及一组自定义着色器;提供实质性的视觉质量改进,同时在文本样式和纹理方面为用户提供令人…...
虹科分享| 浅谈HK-Edgility边缘计算平台
上周,我们推出了虹科新品HK-Edgility边缘计算平台以及uCPE解决方案。本篇文章我们再来谈一谈到底什么是边缘计算?为什么需要边缘计算?边缘计算和云计算有什么关系?HK-Edgility边缘计算平台将为您带来什么?一、边缘计算…...
React Router v6详解
旧版本React Router使用方式 BrowserRouter:通过 history 库,传递 history 对象,location 对象Switch:匹配唯一的路由 Route,展示正确的路由组件Route:视图承载容器,控制渲染 UI 组件 新版本R…...
如何快速掌握 SwiftyAttributes:Swift 富文本处理的终极指南
如何快速掌握 SwiftyAttributes:Swift 富文本处理的终极指南 【免费下载链接】SwiftyAttributes A Swifty API for attributed strings 项目地址: https://gitcode.com/gh_mirrors/sw/SwiftyAttributes SwiftyAttributes 是一个为 Swift 开发者打造的富文本处…...
AIGlasses OS Pro 智能视觉系统 Python 入门实战:环境部署与图像识别初体验
AIGlasses OS Pro 智能视觉系统 Python 入门实战:环境部署与图像识别初体验 你是不是也对那些能“看懂”世界的AI应用感到好奇?比如手机相册自动识别人脸分类,或者商场里能统计客流量的摄像头。这些功能背后,往往离不开强大的智能…...
用LDA主题模型分析新闻分类:从数据清洗到模型优化的完整实战
LDA主题模型实战:从新闻分类到业务落地的全流程解析 在信息爆炸的时代,如何从海量文本中自动提取关键主题并实现智能分类,成为数据科学家和NLP工程师的核心挑战。本文将带您深入LDA主题模型的工业级应用实践,从理论到代码实现&…...
springboot高校共享机房实验室报告评分管理系统vue
目录系统架构设计前端实现计划后端实现计划数据库设计核心功能实现测试与部署项目技术支持可定制开发之功能创新亮点源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作系统架构设计 采用前后端分离架构,前端使用Vue.js框架&#x…...
XPath 语法完全指南:从基础语法到 SQL 注入中的应用
爬虫、处理过配置文件、或者接触过 MySQL 的 XML 函数的一定都见过 XPath 这个名词。它是一种专门用来在 XML 文档中“寻址”的语言,语法像文件路径一样直观。同时,XPath 是 Web 安全领域中 SQL 报错盲注中的关键角色。一、XPath 是什么?XPat…...
C语言实现OTA安全降级与故障隔离:3层状态持久化+2次幂回退重试,让固件升级不再“一失足成千古恨”
第一章:C语言OTA升级失败处理的总体设计哲学在资源受限的嵌入式系统中,C语言实现的OTA升级失败处理并非简单的错误重试逻辑,而是一种以**确定性、可回滚性与状态自明性**为核心的系统级设计哲学。它要求每个操作步骤都具备原子边界࿰…...
三种经典恒流源电路原理、性能对比与工程选型指南
1. 经典恒流源电路原理与工程实现分析恒流源电路是模拟电子技术中的基础单元,在LED驱动、传感器激励、电化学测量、激光二极管偏置等场景中承担着关键角色。其核心设计目标是在负载阻抗变化或供电电压波动的工况下,维持输出电流的高稳定性。本文系统梳理…...
GME多模态向量-Qwen2-VL-2B快速部署:基于JDCloud镜像的Gradio服务上线实录
GME多模态向量-Qwen2-VL-2B快速部署:基于JDCloud镜像的Gradio服务上线实录 1. 项目简介与核心价值 GME多模态向量-Qwen2-VL-2B是一个强大的多模态向量生成模型,能够同时处理文本、图像以及图文对输入,并生成统一的向量表示。这个模型的核心…...
从Claude到Lingbot:对比不同AI模型在深度理解任务上的特点
从Claude到Lingbot:对比不同AI模型在深度理解任务上的特点 最近和几个做产品和技术的朋友聊天,大家聊到一个挺有意思的话题:现在AI模型这么多,有的擅长跟你聊天写文章,有的专门能看懂图片里的深度信息,它们…...
AI万能分类器入门教程:5分钟搭建新闻自动分类系统,零基础友好
AI万能分类器入门教程:5分钟搭建新闻自动分类系统,零基础友好 1. 引言:为什么需要零样本分类? 每天互联网上产生的新闻内容超过百万条,传统的人工分类方式早已无法应对这种信息爆炸。想象一下,如果你正在…...
