上一篇主要一块学习了D3D绘制图元的一些个理论知识,再一起回顾一下:讲述了两个缓冲区的概念,存储顶点数据的静态与动态缓冲区的区别,如何访问内存,如何得知顶点索引缓冲区的信息,在一个就是绘制图元的方法,以及在哪绘制的问题。
这一篇我将跟大家伙一起学习一下,各个概念之间的关联,下一篇,我将贴出源码,好了拭目以待吧!闲话少说,开干:
一、昨晚描述遗留的模糊问题:
D3DUSAGE_WRITEONLY与D3DUSAGE_DYNAMIC间的关联,到底是怎么样的呢?为了描述清 楚这个问题,以及解决我思想上的包袱,今天中午我特意查了一下,望能给你解疑: 网上资料称,D3DUSAGE_DYNAMIC当被指定的时候,D3DUSAGE_WRITEONLY才具有存在的价值。
(1)D3DUSAGE_DYNAMIC+D3DUSAGE_WRITEONLY -->指定顶点数据被存储在显存中,读写速度并不快,但是有一个显著的特点就是渲染速 度很快!
(2)D3DUSAGE_DYNAMIC 不附加D3DUSAGE_WRITEONLY的时候,其指定的是AGP内存,该内存的优点是数据能被很快的刷新!常用于粒子系 统那块!
(3)D3DUSAGE_WRITEONLY 本身指定该内存为只写属性,任何试图从其中读数据的操作,均视为违法操作。
(4)不用D3DUSAGE_WRITEONLY标记的时候,指定的就是静态缓冲区中存储的数据,也就是存储在显存中,但是数据不宜频繁变动!
二、绘制图元的各个流程到底是在做些什么呢?
昨晚可能描述的不够准确或者是这些个知识点没有串联,因此你可能对我说的各个理论之间的关联并不是十分明朗,在这我简要的再 说一下这个流程:
D3D的基本绘制图元是以三角形绘制的。众所周知点成线,线成面的概念。所以,我们可以假想任何复杂的物体都是一系列相关联的点 组成的线连接起来的。要想绘制它,需要经过这些个步骤:
1、指定各个顶点的属性,你比如说它的位置、法线、纹理我们借助C++中的结构体来实现它;
2、根据你所定义的顶点的各个属性,来定制属于你自己的灵活顶点格式;
3、到了这个阶段,你就得需要考虑,你到底需要绘制哪种类型的图元呢?点?线段?三角形?正方形?还是多面体?完成这些,你需 要多少个你所指定类型的点组成呢?(这里暂时不提索引缓冲的概念)。这时呢,你就需要根据你想创建的图元的类型,来填充你的 这个顶点结构体
4、当你自定义了那么多的顶点数据,你总得找个地方保存一下吧!这时,就是需要为其申请一段可以保存这些个顶点数据的内存段了 !通过D3D为我们提供的创建顶点缓冲区的函数CreateVertexBuffer来实现
5、当你申请了足够容纳你所定义的顶点数据结构体数组之后,你就需要访问这块内存了,并且将你的顶点数据填入到你所申请的内存 段中。这就需要在加锁解锁函数中来实现了。
6、设置渲染状态,指定渲染的模式,你比如说是否开启拣选模式等等。具体的参看D3DSETRENDERSTATETYPE。
7、你以上搞的这一套,还只是设计阶段,我们的最终目的是看到效果,看不到都是白扯,所以我们需要将我们以上的想法或者设计, 通过某种介质来呈献给绘制设备。于是就有了资源流这么个概念。就是与你的顶点缓冲区与渲染数据流连接用的媒介。
8、设置你的灵活顶点格式
9、最后就可以绘制你的D3D图元了
三、顶点缓冲区与索引缓冲区的优劣比较
索引缓冲区诞生的意义是减少系统内存的开销,提高程序的性能。不相信的话,我们一块来算笔账,事实为证。当我们假设绘制一个 正方形图元的时候,我们需要定义几个点吧,傻子都知道我们需要4个顶点:如下图A、B、C、D。
A--------B
| / |
| / |
| / |
C | /--------| D
1、节省系统内存
当我们仅仅用顶点缓冲直接绘制这个长方形图元的时候,我们拿出一种组织方式来分析一下:ABC,CBD。这时需要6个点来记录这些 组织方式我们才可以绘制出来这个图元:我们的图元坐标是int类型的,int占用4个字节,所以,需要的字节数:6*(3*4) = 72个字节 。如果我们用索引缓冲来实现的话,我们就只需剔除重复的点,这时我们只需要保存4个点就可以完成我们的绘制工作,这里呢,你要 借住索引来操作,索引也是占据空间的,但是它是16位的索引就可以搞定了就是WORD,一个WORD就是16位,即两个字节,所以依靠索 引来完成咱们的绘制的话,就需要:4*(3*4)+6*2 = 60个字节需要。 这里体现的节省系统内存开销,并不是很明显,如果你搞个复杂的图元来搞搞,那性价比就体现的淋漓尽致了!
2、提高程序的执行性能 使用顶点缓冲区来渲染的时候,D3D会对每个顶点进行计算,这样6个顶点需要计算;而如果你使用索引缓冲区来渲染的时候,你仅 仅需要让D3D处理4个顶点就可以了,这样可以让系统避免了不必要的性能开销,在一定程度上提高了程序的性能!
四、顶点数组如何与索引数组搭配呢?
前期在以上我所说的创建顶点缓冲区之前的那些操作,该怎么写还是怎么写,但是呢,在你填充顶点数据结构体后,需要一个16 位的索引数组,用于你用索引下标来组织你的三角形顶点的组织方式。
五、顶点缓冲区如何与索引缓冲区搭配来完成图元绘制呢?
1、依旧创建顶点缓冲区,需要注意的是,创建顶点缓冲区的大小那个参数,是你真正用到的点的个 数所需的内存大小。
2、新创建索引缓冲区,这里需要注意的是,那个索引数组的元素格式是D3DFMT_INDEX16。
3、操作内存,这里用索引数组来替换之前的顶点数组。
4、资源流的设定,你要借住顶点来与渲染流接轨。
5、依旧设置你的灵活顶点格式
6、通过SetIndices(IDirect3DIndexBuffer*),这个函数将你的索引指针与其代表的索引数组链接起来了。
7、绘制图元调用DrawIndexPrimitive(...)来正式渲染基于索引缓冲区模式的渲染。
2010年8月19日 星期四晚
阿舰 于日照