今天继续D3D基础,如果时间足够的话,应该可以能够绘制出简单的三角面

D3D基础概念

灵活顶点格式 ( Flexible Vertex Format )FVF

其实这就是一个我们自己声明定义的一个结构,在其中,我们进行图元顶点的存储,我们在程序中用它来记录一切顶点的属性,但DX本身对它有一定的限制,那就是限制我们在设计其属性时各类型参数的顺序。在这个FVF中,我们可以设置顶点的:

  1. 位置x,y,z坐标
  2. RHW(已转化的顶点,齐次W倒数)
  3. 混合加权值
  4. 顶点的法线
  5. 扩散的颜色(漫射属性)
  6. 反射颜色(镜面反射属性)
  7. 纹理坐标集(UV坐标)等

我们可以根据不同的需要来选择部分的属性进行设置,这将比强硬全部设置来的方便,计算机在图形绘制时将根据我们的设置来处理必要的组成部分,节省了大量的内存和渲染时间。但是依旧是那句话,可以部分属性不进行设置,但顺序不可颠倒。

我们查找MSDN或DX DEV帮助文档搜索FVF可以获得FVF的格式可以是以下类型的组合

  • D3DFVF_XYZ包含未经转换的顶点坐标
  • D3DFVF_XYZRHW包含经过转换的顶点坐标
  • D3DFVF_XYZW包含经过转换和裁剪的顶点坐标
  • D3DFVF_XYZB1………D3DFVF_XYZB5包含用于骨骼动画的顶点和顶点对骨骼的权重信息
  • D3DFVF_NORMAL包含法线信息
  • D3DFVF_PSIZE顶点信息指明绘制点的大小
  • D3DFVF_DIFFUSE包含漫反射的信息
  • D3DFVF_SPECULAR包含镜面反射的信息
  • D3DFVF_TEX0………D3DFVF_TEX8包含0-8个纹理坐标信息

当我们同时需要两项以上的参数时,定义时加上位或符就可以了。

顶点缓冲区(Vertex Buffer)

就是D3D中用来保存顶点数据的一个内存缓冲区。我们这里值得注意的是顶点缓冲区设置应该是设置在显存中的,因为我们的CPU内存和显存的读取数据速度是没有办法比的,但是由于显存中可以存放的数据较少,我们需要尽一切可能将即将渲染的数据输送到显存中,即使该数据很大,我们也要根据显存的速度进行分割输送,尽可能的避免在系统内存中直接渲染的事情发生。这个在后面的设置时我会更详细的说明。

坐标系

呃,这么没什么可说的了吧,仅仅值得注意的是,我们D3D中使用的是左手坐标系,即Z轴正方向是向屏幕内的,而3DMAX等建模软件是使用的右手坐标系,即Z轴正方向是向屏幕外的。

图元

在三维图形领域中,一个立体物体我们经常是使用多组多边形来包围一个物体表面来近似的模拟物体的。如果有接触3DMAX,MAYA等3D建模软件那更容易理解一些。我们的物体是中空的,仅表面上由一些面片拼接而成,而这些面片通常又是由一个一个更小的图元来构成的。

在D3D中,我们采用的多是三角形网格(Triangle Mesh)来进行拼接。

图元类型

我刚说过我们使用的是三角形网格来进行图形表示,但是实际上D3D图元类型是分六种,三角形图元的创建方式也有三种。了解它们的原理对我们优化程序算法有很大的好处。

  • 点列集合 D3DPT_POINTLIST 一组点的集合
  • 线列集合 D3DPT_LINELIST 一组线段的集合
  • 线带集合 D3DPT_LINESTRIP 首尾相连的线段的集合
  • 三角形列 D3DPT_TRIANGLELIST 一组三角形的集合
  • 三角形带 D3DPT_TRIANGLESTRIP 首尾相连的三角形,有两个顶点重合
  • 三角形扇 D3DPT_TRIANGLEFAN 组成扇形的一组三角形

  1. 绘制点是相当容易的,我们给出点的空间坐标,再分别绘制就好了

g_pD3DDevice->DrawPrimitive(D3DPT_POINTLIST, 0, 6); //会绘制出6个点

恩,其中g_pD3DDevice是D3D设备指针,函数第一个参数是我们设置的灵活顶点格式结构,0是偏移量,设置为0代表从FVF结构中第一个顶点开始绘制,6是从偏移量开始绘制6个图元。

  1. 线列

g_pD3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, 3); //会绘制出3个未必相连的线段

参数和点差不多了。这里系统会默认的将FVF结构中的第1个点和第2个点连接成一个线段,第3个点和第4个点连接成一个线段,如此反复,结果我们得到的将是一系列未必连接的线段。

  1. 线带

g_pD3DDevice->DrawPrimitive(D3DPT_LINESTRIP, 0, 5); //会绘制出5个必定连接的线段

参数不说了,值得注意的是线带和线列区别在于,系统会默认的将第1,2个点连接之后,会再将2,3点连接,之后3,4点,如此类推,我们得到的将会是一系列连接起来的线段,当然在相同点数下,获得线段会比线列多,

  1. 三角形扇

g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 4); //会绘制出4个紧连的三角行

这个绘制的方法是0,1,2点绘制一个三角形,之后0,2,3点绘制一个三角形,之后是0,3,4。。。呃,还是一会画图好

  1. 三角行列

g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); //会绘制出2个不连接的三角形

这个绘制方法是0,1,2点绘制一个三角后,3,4,5点绘制一个三角。

  1. 三角形带

g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 4); //会绘制出4个连接的三角形

这个绘制方法是0,1,2点绘制一个三角形,1,2,3绘制一个三角行,2,3,4绘制一个三角行。


我再总结下绘制图元的方法:

HRESULT DrawPrimitive(
  D3DPRIMITIVETYPE    PrimitiveType, //基本图元类型
  UINT StartVertex,    //起始顶点
  UINT PrimitiveCount          //绘制的图元的数量
);