QT+OpenGL 面剔除和帧缓冲

news2024/11/15 18:00:50

QT+OpenGL 面剔除和帧缓冲

本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主

面剔除

OpenGL能够检查所有面向(Front Facing)观察者的面,并且渲染他们,而丢弃那些背向的面,节省我们很多的片段着色器的调用。

我们需要告诉OpenGL哪些是正面,哪些是背面。逆时针是正面,顺时针是反面。

glEnable(GL_CULL_FACE);

glCullFace(GL_FRONT);

glCullFace函数有三个可用的选项:

  • GL_BACK:只剔除背向面。
  • GL_FRONT:只剔除正向面。
  • GL_FRONT_AND_BACK:剔除正向面和背向面。

帧缓冲

颜色缓冲、深度缓冲和模板缓冲,这些缓冲结合起来就叫帧缓冲。他被存储在显存中,我们目前所做的所有操作都在默认帧缓冲的渲染缓冲上进行的。

帧缓冲能够让我们在场景中加入类似镜子的东西,或者作出很酷的后期处理效果。

创建一个帧缓冲,并绑定它:

unsigned int fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffers(GL_FRAMEBUFFER, fbo);

也可以使用GL_READ_FRAMEBUFFER或者GL_WRITE_FRAMEBUFFER,将一个帧缓冲分别绑定到读取目标或者写入目标。

我们现在还不能使用我们的帧缓冲,因为它还不完整,一个完整的帧缓冲需要满足以下的条件:

  • 附加至少一个缓冲(颜色、深度或模板缓冲)。
  • 至少有一个颜色附件(Attachment)。
  • 所有的附件都必须是完整的(保留了内存)。
  • 每个缓冲都应该有相同的样本数。

从上面的条件中可以知道,我们需要为帧缓冲创建一些附件,并将附件附加到帧缓冲上。在完成所有的条件之后,我们可以以GL_FRAMEBUFFER为参数调用glCheckFramebufferStatus,检查帧缓冲是否完整。它将会检测当前绑定的帧缓冲,并返回规范中值的其中之一。如果它返回的是GL_FRAMEBUFFER_COMPLETE,帧缓冲就是完整的了。

  • GL_FRAMEBUFFER_UNDEFINED是 如果指定的帧缓冲是默认值,则返回 读取或绘制帧缓冲,但默认 帧缓冲不存在。
  • GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT如果有任何帧缓冲连接,则返回 点是帧缓冲不完整。
  • GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT如果帧缓冲没有 至少附有一个图像。
  • GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER如果值 为 对于任何颜色,则返回 由 命名的连接点。GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE GL_NONE GL_DRAW_BUFFERi
  • GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER如果不是,则返回,并且值 is 表示颜色 由 命名的连接点。GL_READ_BUFFER GL_NONE GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE GL_NONE GL_READ_BUFFER
  • GL_FRAMEBUFFER_UNSUPPORTED是 如果内部格式的组合返回 附加的图像违反了 依赖于实现的限制集。
  • GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE如果值不是 ,则返回 对于所有附加的渲染缓冲区都相同;如果 的值是 对于所有附加的纹理都不相同;或者,如果 附加的图像是渲染缓冲区和 纹理,做的价值 与 的值不匹配。GL_RENDERBUFFER_SAMPLES GL_TEXTURE_SAMPLES GL_RENDERBUFFER_SAMPLES GL_TEXTURE_SAMPLES
  • GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE如果 的值对于所有附着的纹理都不相同,则也会返回;或者,如果 附加的图像是渲染缓冲区和 纹理,的值不是所有附加的 纹理。GL_TEXTURE_FIXED_SAMPLE_LOCATIONS GL_TEXTURE_FIXED_SAMPLE_LOCATIONS GL_TRUE
  • GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS如果任何帧缓冲附件为 分层,任何填充的附件都不是 分层,或者如果所有填充的颜色附件都是 不是来自同一目标的纹理。
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
  // 执行胜利的舞蹈

渲染到一个不同的帧缓冲叫做离屏渲染

在完成所有的帧缓冲操作之后不要忘了删除这个帧缓冲对象:

glDeleteFramebuffers(1, &fbo);

对帧缓冲创建一个纹理和普通纹理差不多:

unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

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);

对于这个纹理,我们仅仅分配了内存而没有填充它。填充这个纹理将会在我们渲染到帧缓冲之后来进行。

已经创建好了一个纹理,要做的最后一件事情就是将它附加到帧缓冲上面:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

glFrameBufferTexture2D有以下的参数:

  • target:帧缓冲的目标(绘制、读取或者两者皆有)
  • attachment:我们想要附加的附件类型。当前我们正在附加一个颜色附件。注意最后的0意味着我们可以附加多个颜色附件。我们将在之后的教程中提到。
  • textarget:你希望附加的纹理类型
  • texture:要附加的纹理本身
  • level:多级渐远纹理的级别。我们将它保留为0。

将一个深度和模板缓冲附加为一个纹理,存入帧缓冲:

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);

当创建一个附件的时候我们有两个选项:

  • 纹理:过去纹理是唯一可用附件
  • 渲染缓冲对象: 它会将数据存储为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);

渲染到纹理

想要绘制场景到一个纹理上,我们需要采取以下步骤:

  • 将新的帧缓冲绑定为激活的帧缓冲,和往常一样渲染场景
  • 绑定默认的帧缓冲
  • 绘制一个四边形,将帧缓冲的颜色缓冲作为它的纹理。

在这里插入图片描述

代码在gitee中查看,这里不做展示了。

后期处理

既然整个场景都被渲染到了一个纹理上面,我们可以简单的通过修改纹理数据创建出一个非常有意思的效果。

反向:

void main()
{
    FragColor = vec4(vec3(1.0 - texture(screenTexture, TexCoords)), 1.0);
}

在这里插入图片描述

灰度:

void main()
{
    FragColor = texture(screenTexture, TexCoords);
    float average = (FragColor.r + FragColor.g + FragColor.b) / 3.0;
    FragColor = vec4(average, average, average, 1.0);
}

在这里插入图片描述

void main()
{
    FragColor = texture(screenTexture, TexCoords);
    float average = 0.2126 * FragColor.r + 0.7152 * FragColor.g + 0.0722 * FragColor.b;
    FragColor = vec4(average, average, average, 1.0);
}

在这里插入图片描述

核效果:

const float offset = 1.0 / 300.0;

void main()
{
    vec2 offsets[9] = vec2[](
    vec2(-offset,  offset), // 左上
    vec2( 0.0f,    offset), // 正上
    vec2( offset,  offset), // 右上
    vec2(-offset,  0.0f),   // 左
    vec2( 0.0f,    0.0f),   // 中
    vec2( offset,  0.0f),   // 右
    vec2(-offset, -offset), // 左下
    vec2( 0.0f,   -offset), // 正下
    vec2( offset, -offset)  // 右下
    );

   float kernel[9] = float[](
    1.0 / 16, 2.0 / 16, 1.0 / 16,
    2.0 / 16, 4.0 / 16, 2.0 / 16,
    1.0 / 16, 2.0 / 16, 1.0 / 16  
);

    vec3 sampleTex[9];
    for(int i = 0; i < 9; i++)
    {
        sampleTex[i] = vec3(texture(material.diffuse, TexCoords.st + offsets[i]));
    }
    vec3 col = vec3(0.0);
    for(int i = 0; i < 9; i++)
    col += sampleTex[i] * kernel[i];

    FragColor = vec4(col, 1.0);
}

在这里插入图片描述

模糊:

float kernel[9] = float[](
    1.0 / 16, 2.0 / 16, 1.0 / 16,
    2.0 / 16, 4.0 / 16, 2.0 / 16,
    1.0 / 16, 2.0 / 16, 1.0 / 16
);

在这里插入图片描述

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

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

相关文章

springboot logback日志+异常+阿里云日志 aliyun-log-logback-appender

前言最近有个新项目用了&#xff0c;springboot3.0&#xff0c;以前项目日志保存得方式是阿里云云服务自动读取日志文件&#xff0c;最近项目部署得方式可能有变化&#xff0c;所以新项目用logbackaliyun-log-logback-appender得方式保存到阿里云日志服务。用logback得原因主要…

《OpenGL宝典》--统一变量

统一变量 [layout (location 0)] uniform float f 1.0f;若设置layout&#xff0c;则不需要使用glGetUniformLocation来获取统一变量的位置 使用glUniform*传递值&#xff0c;glUniformMatrix*()设置矩阵统一变量。 glUseProgram(myShader); glUniform1f(0,45.2f);//0为loc…

思迅软锁安装配置说明

思迅软锁安装配置说明 一、软锁安装、申请及配置流程 1.软件安装环境要求 2.软件安装配置流程 步骤1: 在平台下载软锁程序并安装。在安装了总部数据库的服务器上&#xff0c;运行“思迅软锁服务.exe”程序&#xff0c;按照指引进行安装&#xff0c;安装完成后将在电脑的桌面上…

微服务之Gateway服务网关

&#x1f3e0;个人主页&#xff1a;阿杰的博客 &#x1f4aa;个人简介&#xff1a;大家好&#xff0c;我是阿杰&#xff0c;一个正在努力让自己变得更好的男人&#x1f468; 目前状况&#x1f389;&#xff1a;24届毕业生&#xff0c;奋斗在找实习的路上&#x1f31f; &#x1…

「亲测」0成本考证填报个税纳税额减免3600

「亲测」0成本考证填报个税纳税额减免3600 今天开始2022综合所得的年度汇算就开始办理了&#xff0c;刚刚步入工作的同学&#xff0c;对个税的填报有些苦恼&#xff0c;好像除了房租就没有能减税的政策了。 别急别急&#xff0c;其实个⼈所得税⾥⾯包含⼀个叫“专项附加扣除”的…

C++ 认识和了解C++

1.在使用C语言写代码的时候开头要用到的是&#xff1a; #include<iostream> using namespace std;不可以写成这样&#xff1a; #include iostream.h&#xff08;1&#xff09;iostream是输入输出流类&#xff0c; istream输入流类 cin >> ostream输出流类 cout &…

40系笔记本(可不联网激活)深度学习生产力(环境配置和简单训练测试)

40系笔记本深度学习、转码生产力&#xff08;环境配置和简单训练测试&#xff09;这里写自定义目录标题深度学习环境准备CUDA、CUDNN版本问题torch版本问题其他软件版本的安装命令训练测试代码地址关于Linux还是Windows的问题结果博主首发购买了枪神7超竞4080的版本&#xff0c…

git开发流程

分支介绍 dev&#xff1a;开发环境&#xff0c;从feature去mr test: 测试环境&#xff0c;从feature去mr pre&#xff1a; 预生产环境&#xff0c;从master去mr&#xff0c;为了验证master代码 master: 生产环境&#xff0c;从feature去mr feature&#xff1a; 开发分支----小…

4种方法教你如何隐藏电脑磁盘分区?

磁盘分区是电脑的重要组成部分&#xff0c;我们能够在电脑中保存众多数据&#xff0c;就离不开它。那么你知道该如何隐藏磁盘分区吗&#xff1f;下面小编就教你4个方法隐藏电脑磁盘分区。方法一&#xff1a;使用磁盘管理隐藏硬盘分区1、按下“WinR”键&#xff0c;输入“diskmg…

Python3-元组

Python3 元组 Python 的元组与列表类似&#xff0c;不同之处在于元组的元素不能修改。 元组使用小括号 ( )&#xff0c;列表使用方括号 [ ]。 元组创建很简单&#xff0c;只需要在括号中添加元素&#xff0c;并使用逗号隔开即可。 >>> tup1 (Google, Runoob, 19…

4-1 SpringCloud快速开发入门:RestTemplate类详细解读

RestTemplate类详细解读 RestTemplate 的 GET 请求 Get 请求可以有两种方式&#xff1a; 第一种&#xff1a;getForEntity 该方法返回一个 ResponseEntity对象&#xff0c;ResponseEntity是 Spring 对 HTTP 请求响应的封装&#xff0c;包括了几个重要的元素&#xff0c;比如响…

Python基础篇(十五)-- Pygame游戏编程

1 初识Pygame Pygame是一个开源的Python模块&#xff0c;专门用于多媒体应用&#xff08;如电子游戏&#xff09;的开发&#xff0c;其中包含对图像、声音、视频、事件、碰撞等的支持。Pygame建立在SDL的基础上&#xff0c;SDL是一套跨平台的多媒体开发库&#xff0c;用C语言实…

39万字完整版智能矿山项目建设整体解决方案

本资料来源网络&#xff0c;仅做知识分享&#xff0c;请勿商用。完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 1.1 总体技术要求 1.1.1 核心业务架构 智能矿山业务架构是在统一的标准与规范及安全运维保障体系下&#xff0c;按分层设计模式&#xff0c;分为设备层、…

QML鼠标事件

QML中常用的事件有&#xff1a; 鼠标事件键盘事件拖拽事件定时器MouseArea&#xff08;鼠标区域&#xff09; MouseArea是一个不可见的项目&#xff0c;同、通常用来和一个可见的项目配合使用来为其提供鼠标处理。鼠标处理的逻辑可以包含在MouseArea项目中 常用的属性&#xff…

【设计模式】原型模式与建造者模式

原型模式 原型模式是指通过原型实例指定创建对象的种类&#xff0c;然后通过拷贝的方式创建新的对象。属于创建型模式 原型模式的核心在于拷贝原型对象&#xff0c;主要用于对对象的复制。当你需要通过一大段get/set方法去构建对象的时候&#xff0c;就可以考虑使用原型模式了…

手牵手教Docker部署Springboot+vue ,全过程十分详细,轻松完成项目部署(简单,高效,通用)

手把手教Docker部署Springbootvue &#xff0c;详细全过程&#xff0c;轻松完成项目部署&#xff08;简单&#xff0c;高效&#xff09; 上线前准备 腾讯云的服务器&#xff0c;服务器安装好docker 和docker-compose 最好事先了解技术 nginxdocker-compose 整体编排 后端部…

【C++】Visual Studio C++ 配置并使用gtest(不好用你捶我)

文章目录 相信大家都能感受到Visual Studio C 编辑器链接 lib 或 dll文件是一件非常头疼的事情。配置gooleTest的过程也不例外。 市面上很多教程&#xff0c;要么就不全&#xff0c;要么就缺少一些细节&#xff0c;导致我自己再配置的过程中&#xff0c;踩了很多坑。今天就记录…

用不同的思路实现括号匹配(java)

给定一个只包括 (&#xff0c;) 的字符串&#xff0c;判断字符串是否有效。 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 以上就是题目要求 利用替换的思想 ()()()()()()()(())例如需要判断例子中的括号是否有效&#xff0c;用替换的思想具体就是 将字…

力扣sql简单篇练习(二十一)

力扣sql简单篇练习(二十一) 1 使用唯一标识符替换员工ID 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # Write your MySQL query statement below SELECT e2.unique_id,e1.name FROM Employees e1 LEFT JOIN EmployeeUNI e2 ON e1.ide2.id1.3 运行…

使用netlify实现自动化部署前端项目(无服务器版本)

介绍 本文以 github仓库进行介绍关联netlify的无服务前端自动化部署。用途&#xff1a;个人网站设计、小游戏等当然这只是让你入门~具体细节等待你自己去探索 实现 打开官方网站 如果没有注册过的账户&#xff0c;你需要使用 github 去进行登录。注册完成后会自动给你提示填…