在最近的项目中,尝试进行了一些小实验,并记录了数据作为比较。实验机器的显卡是NVidia Geforce 8800 GT。

1. Skinning

skinning on CPU

                          skinning on CPU

skinning on GPU

                          skinning on GPU

从图中可以清晰的看出,对于骨骼蒙皮计算,CPU和GPU的差距可见一斑,GPU比CPU要快上10倍之多!这就是GPU并行计算的魅力!

2. Instancing & Stream Output

人物模型延用上面的这个模型(该模型差不多有1300个面),采用instancing技术渲染上千人(所有的Instance的动画在每一帧保持一致),并且实现了SO的版本,对它们的FPS进行比较。

Instancing without SO

   

     1,000 Instances              2,000 Instances             3,000 Instances

Instancing with SO

   

     1,000 Instances              2,000 Instances             3,000 Instances

因为所有的Instance的动画在每一帧都是一致的,所以如果不使用SO技术,则不得不对每个instance都需要进行一次蒙皮动画,这显然是一种浪费。Stream Output技术使得所有的Instance的蒙皮动画只需要执行一次,所以在效率上得到了一定的提高,如下表。

Number of Instances

FPS(Without SO)

FPS(With SO)

1,000

40

56

2,000

19

36

3,000

13

24

 3. Frustum Culling

换了一个低质量的模型(只有不到200个面),基本上万人级别是没有问题了,加上了Frustum Culling,则可以跑得更快!

使用3种方法实现了Frustum Culling,前两个都是基于CPU的,最后一个是基于GPU

  1. 顺序执行(最简单的对所有Instance遍历执行Frustum Culling算法)
  2. 四叉树(四叉树裁剪,我这里用四叉树用得有点牵强,因为人物不能移动且必须保持边长为2的N次方的阵型。这么简单的处理四叉树,只是为了做实验比较而已)
  3. GPU上的Frustum Culling(算法基本上跟1是一致的,只不过是在GPU上执行)

三个方法在同一个视角,使得它们截取和渲染的数量是一致的。总共65536个Instance,当前绘制都是15485个。

   

           顺序执行                              四叉树                             在GPU

效率比较如下表。

Current Rendering / Number of Instances
FPS
(Sequential Frustum Culling)
FPS
(Frustum Culling With Quad-tree)
FPS
(Frustum Culling on the GPU)
4388/16384 61 143 102
15485/65536 16 43 32

发现最快的是使用四叉树,而GPU的算法反而相对比较慢。原因很有可能是后者需要处理GPU和CPU的同步问题,在GPU进行Frustum Culling需要CPU从GPU读取Frustum Culling执行的结果(为了知道有多少个instance需要被渲染),在DX10的SDK文档里可清楚的写着,从GPU向CPU进行Map读取操作,是比较严重影响效率的,因为总有一方要停下来去等待另外一方的数据。