GPU上大规模粒子系统的Dx9实现细节总结

来源:互联网 发布:湖北中科网络欠款 编辑:程序博客网 时间:2024/04/16 23:38

 

GPU上大规模粒子系统的Dx9实现细节总结

转自我们的博客http://www.xiaomingjia.com/?p=51

GPU上的粒子系统在DX10上的实现已经不是什么新鲜事了。考虑到公司使用的现有渲染器,我决定在dx9上实现之。

首先看到的是fannyfish在csdn上的博文,它把Shader X3上的Massively Parallel Particle Systems on the GPU论文大致做了翻译,但fannyfish同学的代码并未体现论文的算法思路,具体算法详见原版论文,基本思路在这里不再赘述。这篇论文的思路还是比较容易理解的,但随着开发的进行,遇到的问题也逐渐增多。首先遇到的是在顶点纹理中采样出来的点老是不准。经常会采到周围某个像素点去。解决办法是把纹理坐标加上半个像素。因为顶点纹理需要使用最近点采样,如果不加半个像素,那么离他最近的有4个像素点,到底采哪个是不确定的。其次遇到的是渲染帧速提升不明显。当时我是严格按照论文里的思路进行的编码,Cpu并不是完全空闲的,他要负责更新所有粒子的生命期,这就要维护一个粒子队列,而且当有粒子出生或是消亡的时候要通知GPU,这就需要更新粒子的顶点数据。而我一直认为lock顶点缓冲耗时,尤其数据放在显存中时。于是我想只在初始化时生成一边所有粒子的顶点数据,之后就不在碰它。那么粒子的消亡就在GPU中实现,通过把将要消亡的粒子移到很远处使之在ps前被剔除掉,而粒子的诞生则是通过shader中的一个变量控制。这个变量存储着位置纹理中需要诞生的那个粒子的索引和需要在这次draw中诞生的粒子个数。那么在GPU中可以计算出那些粒子索引需要被初始化。这个变量实际上就是每个点对应的纹理坐标。在cpu中,它需要做的就是填写这一帧需要产生多少个粒子和起始粒子的纹理坐标。

整个cpu参与运算的部分只有20行代码,剩下的粒子位置的更新和粒子的生命期都由GPU管理。

通过在NV GT220上的对比测试,Ogre 渲染1w个粒子最大帧速为155,GPU上渲染1w个粒子为362帧,我们的OGRE最大粒子只有1w个,大于1w的无从比较,但是用GPU渲染6w个为118帧,10w个为73帧。当粒子数小于5k时两者差别不太明显。

影响渲染帧速的原因其中之一是RT的尺寸,对于渲染同样的1w个粒子,128*128为362帧,256*256的纹理为297帧,512*512为182帧。对于6w以上的粒子,只有使用512*512以上的纹理,但对于游戏而言,一般128*128就满足需求了,同时能保持较高的帧速。

另外,当粒子很多时,渲染粒子的瓶颈主要产生在填充率上,所以为了比较客观地进行对比,需要把粒子拉的比较远一点,当两者帧速都趋于稳定时,差别就体现在cpu耗时与AGP带宽上。

cpu占用率问题上,在我的双核笔记本上在10%左右,如此可见时间消耗主要集中在显卡上,达到了解放cpu负载的目的。

                                                        128*128 1w

                                     256*256 1w

                   512*512 1w

512*512 10w

10w粒子demo

http://download.csdn.net/download/itlmy/3665744