其实,根据我最近研究发现,暴雪早在DX8时代就做了批量渲染这件事,所以一举占据了RTS老大的地位.很凑巧的时候我现在的项目也是个RTS类游戏.所以批量渲染就成了一个亟待解决的问题.
Gamebryo是支持MeshInstancing的,就是模型的批量渲染。
哦,先介绍下DX9支持的几种Instancing的方式吧,一种叫HardwareInstancing,中文叫硬件批量渲染吧,其实是DX9提供了SetStreamSourceFreq这个接口,让你可以把一个数据源多次使用,比如我们要批量需然一组模型,每个模型有自己的Translation信息,但是他们的顶点和索引数据是共用的。例如,你要批量10个这样的模型的话,只要抽取出他们不同的数据上传到一个数据源中,然后顶点和索引数据重复使用十次就可以了。
另外一种是ShaderInstancing,所谓Shader Instancing,意思就是,把Instancing数据传到vertex shader里去,在渲染的时候通过一些方法索引到这些Instancing数据,用来对顶点数据做不同的描画。
关于D3D的SetRenderState切换影响效率的问题!!!
SetRenderState(a)
SetRenderState(b)
SetRenderState(a)
SetRenderState(b)
这是无论你手动判断,还是dx都无法优化的
instancing 渲染
在渲染重复的顶点数目很少的小物体时,使用instancing渲染方法能大量减少对绘制函数的调用,从而达到提高效率的目的。在gpu gems2中以及dx9 sdk的sample中对该方法有具体的描述。
在gpu gems2中将instancing渲染技术分成了4个种类:
l 静态批次
l 动态批次
l 顶点常量实例化
l 几何体实例api批次
书中对4中技术阐述的十分清楚,以下只针对dx sdk中的sample中的三种做法进行叙述。
stream instancing
stream instancing使用2个vb buffer,1个ib。一个存放数据的顶点,一个存放所有实例的属性。以绘制1000个立方体为例,一个vb存放一个立方体24个顶点(6个面,每个面4个顶点),一个ib存放36个索引(6个面,每个面2个三角形,每个三角形3个顶点)。另外一个vb存放所有1000个立方体的实例数据,包括:颜色,位置,方位角等等。
设置好各个buffer后即可渲染。渲染的时候一次只能渲染一个立方体,每次drawindexedprimitive之前都需要调用setstreamsource设置实例在第二个vb中的偏移量即可。显然对于每个物体都调用drawindexedprimitive的做法肯定对效率影响很大。
这种方法算是一种比较静态的方法,不过和gpu gems2中的静态方法不太一样。gpu gems2中的静态方法只使用一个大的vb和一个大的ib,这个vb中存放转换好的几何实例信息,ib中存放每一个实例的索引,然后使用一个drawindexedprimitive绘制出所有的几何体。这种方法需要耗费大量的储存器且不能支持骨骼运算,对cpu的消耗十分的大。
shader instancing
shader instancing需要一个大的vb和一个大的ib以容纳所有的实例的顶点和索引。另外几何体实例的所有信息存放在系统的内存中。和前面的方法不同的是,并不需要在创建vb的时候将几何体实例的信息lock到vb中去,而是在渲染的时候通过顶点常量传递进去。由于顶点常量的个数有限,所以一批几何体可能需要渲染几次才能全部完成。
这个方法和gpu gems2中的顶点常量实例化的方法很相似,不过由于gpu gems2中的这个方法将所有的顶点常量拿来做instancing运算,无法进行骨骼运算。为了解决这个问题dx sdk中的sample中并没有使用全部的顶点常量。
hw instancing
这种方法是dx sdk里面强烈推荐的方法,不过需要硬件支持vs3_0。前面2种方法都只是需要硬件支持vs1_1即可。
hw instancing的方法和前面说的stream instancing的方法如出一辙,所不同的是,hw instancing使用了dx sdk提供的api:setstreamsourcefreq()。通过这个api,就可以不需要在渲染的时候指定实例在vb中的偏移量,所以使用这个方法可以自动的将所有的实例使用一个drawindexedprimitive绘制完毕。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/udking/archive/2010/12/01/6048195.aspx
原文链接:https://www.f2er.com/vb/261224.html