QT+OpenGL 面剔除和帧缓冲

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

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Qt 是一款跨平台应用程序开发框架,它提供了丰富的功能和工具来简化应用程序的开发OpenGL 是一种图形渲染库,用于创建高性能的2D和3D图形效果。那么,QtOpenGL 的结合能够为开发者提供强大的图形处理能力和丰富的用户界设计功能。 在学习使用 QtOpenGL 进行应用程序开发时,书籍是非常有帮助的资源。下是一些关于 QtOpenGL 的书籍推荐: 1.《Qt5 权威指南》:这本书全介绍了 Qt 的各个方,包括 Qt 的基础知识、GUI 编程、网络编程、数据库编程等内容,对初学者来说非常友好。同时,书中还有一章专门介绍了如何在 Qt 中使用 OpenGL 进行图形绘制。 2.《Qt5 与 OpenGL 高级编程指南》:这本书着重介绍了 Qt5 和 OpenGL 的结合应用,涵盖了 OpenGL 基础知识、渲染管线、光照、纹理、阴影等高级图形技术。它适合有一定编程经验且对图形编程有兴趣的开发者。 3.《OpenGL编程指南(第九版)》:虽然这本书不是专门讲解 Qt,但是它是学习 OpenGL 必备的经典教材之一。它详细介绍了 OpenGL 的基础知识和相关概念,包括顶点缓冲对象、渲染缓冲区、着色器编程等内容。通过学习这本书,开发者可以更加深入地理解 OpenGL 的工作原理。 以上是一些关于 QtOpenGL 的书籍推荐,选择适合自己水平和需求的书籍进行学习,可以帮助我们更好地掌握 QtOpenGL开发技巧,进而开发出功能丰富且高性能的应用程序。 ### 回答2: Qt是一种跨平台的应用程序开发框架,它提供了丰富的GUI界设计工具和功能强大的库,可以帮助开发者轻松地开发出高质量的图形界应用程序。而OpenGL是一种专门用于图形渲染的API,可以实现高性能、高质量的图形渲染效果。 在Qt中使用OpenGL可以帮助开发者更好地利用硬件加速来实现图形渲染,提高程序的性能和效果。因此,学习QtOpenGL的结合使用对于想要开发高质量图形应用程序的开发者来说是非常有价值的。 关于QtOpenGL的书籍,市上有很多优秀的选择。其中,一本非常经典的书籍是《Qt5与OpenGL开发实战指南》。这本书适合有Qt基础并对OpenGL感兴趣的开发者。书中介绍了使用QtOpenGL进行图形编程的基本原理和技巧,并通过丰富的实例演示了如何使用QtOpenGL实现各种图形效果和交互特性。 除了这本书之外,还有一些其他的书籍也值得推荐。例如,《OpenGL编程指南》是一本经典的OpenGL入门书籍,可以帮助开发者深入理解OpenGL的基本原理和使用方法。《Qt5开发及实例精解》是一本全介绍Qt开发的书籍,其中也包含了一些关于QtOpenGL结合使用的内容。 总之,选择适合自己的QtOpenGL书籍,可以帮助开发者更好地掌握QtOpenGL的基本知识和技术,从而开发出更加高效、高质量的图形应用程序。 ### 回答3: Qt是一个跨平台的C++应用程序开发框架,它提供了丰富的图形界和功能库,可以帮助开发者快速地构建高质量的应用程序。OpenGL则是一个用于图形渲染的开放标准,通过与Qt结合使用,可以实现更高级的图形效果和游戏开发。 对于想深入学习QtOpenGL开发者来说,有一些经典的书籍可以提供帮助。首先推荐《Qt编程开发实战》一书,该书详细介绍了Qt的基本概念和常用功能,让读者能够快速入门。接下来,可以阅读《QtOpenGL开发指南》,该书介绍了如何使用QtOpenGL创建高级图形应用程序,并深入解析了底层原理和技术细节。此外,《OpenGL超级宝典》是一本非常经典的OpenGL入门书籍,其中包含了许多实用的代码示例和案例讲解,对于理解OpenGL的基本原理和使用方法非常有帮助。 除了这些书籍,互联网上也有许多免费的教程和博客可以供开发者参考,例如《Qt官方文档》和《OpenGL教程》等。此外,参加一些相关的培训课程或者在线教育平台提供的课程,也是学习QtOpenGL的有效途径。最重要的是,实践是学习的关键,通过动手实践一些小项目,可以帮助开发者更好地理解和应用所学知识。 总的来说,QtOpenGL是非常强大的开发工具,在学习过程中可以参考一些经典的书籍和在线资源,结合实践经验,迅速掌握它们的使用方法和技巧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

turbolove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值