QtOpenGL入门教程(七)—— TransformFeedBack(GPU粒子)
_italink
编辑于 2021年09月09日 13:35
收录于文集
共7篇

潜水两个多月,up终于回来辣!

这一节中的猪脚是GPU粒子,而我们要做的,就是一个GPU粒子系统。

什么是粒子系统?

    粒子系统表示三维计算机图形学中模拟一些特定的模糊现象的技术,而这些现象用其它传统的渲染技术难以实现真实感的物理运动规律。经常使用粒子系统模拟的现象有火、爆炸、烟、水流、火花、落叶、云、雾、雪、尘、流星尾迹或者象发光轨迹这样的抽象视觉效果等等。(摘自百度百科《粒子系统》)    

    相信很多小伙伴都看到过一些粒子效果,甚至使用过一些软件的粒子系统了(基本3D引擎都会支持粒子系统,此外一些视频处理软件,比如AE,都会为用户提供一套简单易用的粒子系统),下面是up制作的一些粒子效果的演示:

由于UP时间比较紧,所以咱废话不多说,直接上重点:

粒子的状态

首先我们来思考一个问题:粒子作为粒子系统的基础单位,它应该具有什么样的属性呢?

【位置】【旋转】【缩放】:由于位于3D空间之中,那么这三个参数肯定是少不了的

【存活时间】则是用来记录粒子的存活时间,知道粒子的存活时间我们才知道什么时候该销毁它(当然你也可以不销毁,只需要保证粒子的数量不要无限增长即可)

【形状】:这个没啥说的。

【颜色】:对了,粒子还有颜色,不过有时候我们不会使用单一的颜色,而是使用纹理来对粒子着色。

当然,你还能添加一些其他属性,如【重量】什么的。

除此之后,我们还好附加一些额外的控制属性,比如说【速度】,这个一般都会用到,【速度】的本质是更改了粒子的【位置】,它不算是粒子的基础属性,但是通过附加这个控制属性,我们可以很简单的控制粒子的【加速度】,从而模拟一些物理运动,比如说重力,阻力,风力等等的。

为了让这一节的代码不是很复杂,up不打算实现可自定义形状的粒子系统,而是只使用一个带颜色的点来表示粒子(因为这会使用到另外一个特性——实例化)

因此,这一节中,我们的粒子拥有这样的状态:

代码块
C++
自动换行
复制代码
    struct Particle{
        QVector3D position;
        QVector3D velocity;
        float size;
        float life;
        QVector4D color;
    };
复制成功

粒子系统的实现方式

粒子一般分为CPU粒子和GPU粒子,GPU拥有强大的并行能力,使用它能轻轻松松完成百万级别的粒子效果,这是CPU无法做到的。这里主要说的是GPU粒子,是有两种实现方式:

状态相关粒子:状态相关粒子指的是粒子运动过程中,能够产生相互的作用,在编程层面,也就是在一个粒子的着色器处理过程中,能访问另一个粒子的数据,

    ·原理:是将粒子状态都绘制到一张或多张纹理上,通过控制顶点数据对纹理采样,并在着色器中处理粒子状态,渲染时从粒子纹理中解析出状态数据,从而进行显示。(也正是因为粒子状态是存储在纹理上,粒子间的数据才能相互访问)

状态无关粒子:状态无关粒子与之相反,也就是在一个粒子的着色器处理过程中,是不能访问另一个粒子的数据的。

    ·原理:TransformFeedBack:正常情况下,顶点数据经过顶点着色器和几何着色器之后,会进入光栅化阶段,而TransformFeedBack则是在几何阶段结束之后,直接把顶点数据输出到顶点缓存区,可以看作是,我们使用一个VBO输入顶点数据,结果输出到另一个VBO之中。这个过程看起来像是这样的:

这两种粒子的实现方式各有优劣:

Texture粒子:能够让粒子间能够相互作用,不易实现。

TransformFeedback粒子:需要较高的OpenGL版本支持,有较高的性能,比较容易实现。

我的建议是如果不需要粒子间的关联状态,就用TransformFeedback,所以这一节我们只讲它。

但是你要知道无论是TransformFeedback还是Texture,它们其实都是在做这样的事:

直接在GPU上处理大量数据,而CPU和GPU之间只有微量的数据传输。

还记得我之前说过的吗?(CPU和GPU之间的数据传输,是一个很耗时的过程),在避免大量数据传输的问题后,你会发现:卧槽,原来GPU这么顶,几百万的粒子轻轻松松就绘制出来了。

粒子系统的架构

粒子的管理主要有三个阶段:

  • 生成(发射)阶段:该阶段生成新的粒子,编程层面就是把新粒子的状态数据追加到顶点缓存区里面

  • 更新(运动)及回收(销毁)阶段:该阶段主要是对已有粒子的状态进行处理,并回收(或抛弃)超过生命周期的粒子,编程层面则是通过VBO输入数据到TransformFeedback流水线当中对粒子状态进行处理,最后输出到另一个VBO中(请注意,我们需要交叉使用两个VBO)。

  • 渲染阶段:这一阶段则是根据之前得到的粒子数据,将粒子显示出来,由于我们知道了position、rotation及scaling等数据,根据这些数据我们可以将粒子以任何形式显示出来,可以是一个点,亦或是一个小方块,或者说是一个复杂的模型,都是在此阶段进行的。x