QT之OpenGL帧缓冲

news2024/10/1 12:25:23

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使用示例

  • 单独使用 渲染缓冲对象示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/380640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【代码随想录训练营】【Day28】第七章|回溯算法|93.复原IP地址|78.子集|90.子集II

复原IP地址 题目详细:LeetCode.93 这道题与上一道练习题分割回文字符串十分详细,一样是涉及到分割字符串、判断字符串、递归与回溯的问题,所以这道题要解决的难点在于: 如何分割IP地址字符串如何判断分割的IP地址是否合法递归的…

Kafka基本概念

什么是Kafka Kafka是一个消息系统。它可以集中收集生产者的消息,并由消费者按需获取。在Kafka中,也将消息称为日志(log)。 一个系统,若仅有一类或者少量的消息,可直接进行发送和接收。 随着业务量日益复杂,消息的种类…

2.单例模式

基本概念 单例模式:保证一个类只有一个实例,并提供一个访问该实例的全局访问点 常见应用场景 读取配置文件的类一般设计为单例模式网站计数器应用程序的日志应用,因为共享日志文件一直处于打开状态,只能有一个实例去操作Spring…

新C++(11):unordered_map\set的封装

"假如可以让音乐停下来"一、unordered_map\unordered_set简介在C98中,STL底层提供了以红黑树封装的关联式容器map\set,其查询效率可以达到LogN(以2为底)。而在C11中,STL又提供了unordered(无序)容器,其使用方式与map\se…

企业对不同形态CRM系统价格需求不同

很多企业在选型时关心CRM客户管理系统的价格,有人对CRM的价格完全没有概念,也有的人先问价格再看其他。CRM价格在系统选型中到底有多重要?不同类型CRM系统的价格是否有所不同? CRM的不同产品形态也会影响价格 通常情况下&#x…

十五、MyBatis使用PageHelper

1.limit分页 limit分页原理 mysql的limit后面两个数字: 第一个数字:startIndex(起始下标。下标从0开始。) 第二个数字:pageSize(每页显示的记录条数) 假设已知页码pageNum,还有每页…

移动端笔记

目录 一、移动端基础 二、视口 三、二倍图/多倍图 四、移动端开发 (一)开发选择 (二)常见布局 (三)移动端技术解决方案 五、移动WEB开发之flex布局 六、移动WEB开发之rem适配布局 #END&#xff08…

嘀嗒出行再闯IPO:千军万马我无懈

羽扇纶巾笑谈间,千军万马我无懈。 在激烈竞争中再度冲刺港交所IPO的嘀嗒出行,闪露出一丝歌词里的气魄。交通运输部下属网约车监管信息交互系统的数据显示,截至2023年1月31日,全国共有300家网约车平台公司取得网约车平台经营许可。…

如何使用COM-Hunter检测持久化COM劫持漏洞

关于COM-Hunter COM- Hunter是一款针对持久化COM劫持漏洞的安全检测工具,该工具基于C#语言开发,可以帮助广大研究人员通过持久化COM劫持技术来检测目标应用程序的安全性。 关于COM劫持 微软在Windows 3.11中引入了(Component Object Model, COM)&…

2月第4周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩平台)发布!

飞瓜轻数发布2023年2月20日-2月26日飞瓜数据UP主排行榜(B站平台),通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况,为用户提供B站号综合价值的数据参考,根据UP主成长情况用户能够快速找到运营能力强的B…

基频估计算法简介

基频估计算法 F0 estimate methods 估计F0的方法可以分为三类:基于时域、基于频域、或混合方法。本文详细介绍了这些方法。 所有的算法都包含如下三个主要步骤: 1.预处理:滤波,加窗分帧等 2.搜寻:可能的基频值F0(候选…

chatgpt到底颠覆了什么 第二部分

以第二个理由就是两个字,垄断。 现在谈到范式转变,如果首先谈的还是算法,那说明还没有透彻理解范式改变范式改变,首先要改的是什么。是什么?是参赛资格。 过去我相信大企业大团队聚拢了许多聪明的脑袋,但我…

基于神经网络补偿的主动悬架自适应控制

目录 前言 1. 1/4悬架模型 2.仿真分析 2.1仿真模型 2.2仿真结果 2.1 形① 2.2 形② 3. 总结 前言 上两篇博客我们介绍了神经网络补偿控制律的仿真测试,从仿真结果我们可以得知神经网络具有逼近扰动,并将其补偿的作用。 上两篇文章链接&#xf…

在nestjs中进行typeorm cli迁移(migration)的配置

在nestjs中进行typeorm cli迁移(migration)的配置 在学习nestjs过程中发现typeorm的迁移配置十分麻烦,似乎许多方法都是旧版本的配置,无法直接使用. 花了挺长时间总算解决了这个配置问题. db.config.ts 先创建db.config.ts, 该文件export了两个对象,其…

AcWing算法提高课-3.1.2信使

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 题目传送门点这里 题目描述 战争时期&#xff0c;前线有 nnn 个哨所&#xff0c;每个哨所可能会与其他若干个哨所之间有通信联系。 信使负责在哨所之间传递信息&#xff0c;当然&#xff0c;…

CPU 偏高,和linux常用命令

CPU 偏高&#xff0c;和linux常用命令一、1、常用命令2、top 查看整体的cpu占有率&#xff08;哪个进程cpu占用过高&#xff09;3、top -Hp 8779 查看该pid 下哪个进程占用过高4、打印dump日志 重点关注&#xff08;RUNNABLE、BLOCKED&#xff09;一、 1、常用命令 整机 top …

k8s ConfigMap 中 subPath 字段和 items 字段

Kubernetes中什么是subPath 有时&#xff0c;在单个 Pod 中共享卷以供多方使用是很有用的。volumeMounts.subPath 属性可用于指定所引用的卷内的子路径&#xff0c;而不是其根路径。 这句话理解了&#xff0c;基本就懂subPath怎么用了&#xff0c;比如我们要替换nginx.cnf, 挂…

map和set的使用

文章目录关联式容器树形结构的关联式容器setinsert增减erase删除multiset修改mappair<key,value>insertoperator[] 的引入insert和operator[]的区别multimap小结map的使用统计最喜欢吃的前几种水果前K个高频单词&#xff0c;返回单词的频率由高到低,频率相同时&#xff0…

Isaac-gym(9):项目更新、benchmarks框架梳理

一、项目更新 近期重新git clone isaac gym的强化部分&#xff08;具体见系列第5篇&#xff09;时发现官方的github库有跟新&#xff0c;git clone下来后发现多了若干个task&#xff0c;在环境配置上也有一定区别。 例如新旧两版工程项目的setup.py区别如下&#xff1a; git …

现在的00后太强了,几个问题差点给我问懵了

前言 我们公司刚入职一个00后小伙&#xff0c;今天在办公室交流了一下&#xff0c;他问我会不会自动化测试&#xff0c;我说懂一点&#xff0c;然后直接问了我几个自动化测试问题&#xff0c;差点直接给我问懵了&#xff01; 问题如下&#xff1a; 我们在制定自动化测试实施…