顶点缓存与索引缓存可以被放置在显存中,绘制时使用显存中的数据比使用系统内存中的数据要快的多。
顶点缓存与索引缓存在D3D9中的表示:
顶点缓存 IDirect3DVetrexBuffer9
索引缓存 IDirect3DIndexBuffer9
可以用如下2个方法创建
HRESULT IDirect3DDevice9::CreateVertexBuffer(
UINT Length, //为缓存分配的字节数量
DWORD Usage, //关于如何使用缓存的附加信息
DWORD FVF, //存储在顶点缓存中顶点的灵活顶点格式
D3DPOOL Pool, //容纳缓存的内存池
IDirect3DVertexBuffer9** ppVertexBuffer, //接收所创建顶点缓存的指针
HANDLE* pSharedHandle //不使用 为0
);
HRESULT IDirect3DDevice9::CreateIndexBuffer(
UINT Length, //为缓存分配的字节数量
DWORD Usage, //关于如何使用缓存的附加信息
D3DFORMAT Format, //指定索引的大小D3DFMT_INDEX16或D3DFMT_INDEX32
D3DPOOL Pool, //容纳缓存的内存池
IDirect3DIndexBuffer9** ppIndexBuffer, //用于接收所创建的索引缓存的指针
HANDLE* pSharedHandle //不使用 为0
);
上述两个方法大部分参数相同,下面介绍参数:
Length 为缓存分配的字节数,如果想让顶点缓存足够存储8个顶点,该参数需设为8*sizeof(Vertex),其中Vetrex是定义顶点的结构。
Usage 指定关于如何使用缓存的一些附加属性,该值可为0(表面无需附加属性),或是一下标记中的某一个或某种组合。
FVF 存储在顶点缓存中顶点的灵活顶点格式。
POOL 容纳缓存的内存池。
ppVertexBuffer 用于接收所创建的顶点缓存指针。
pSharedHandle 不使用,该值设为0。
Format 指定索引的大小。设为D3DFMT_INDEX16表示16位索引,设为D3DFMT_INDEX32表示位32位索引。注意,并非所有图像设备都支持32位,如需使用,请检查硬件的性能。
ppIndexBuffer 用于接收所创建的索引缓存的指针。
使用的例子:
//下面例子中,创建了一个可以容纳8个Vertex类型的顶点的静态顶点缓存
IDirect3DVertexBuffer9* vb;//顶点缓存对象
device->CreateVertexBuffer(
8*sizeof(Vertex),
0, //0为静态顶点缓存
D3DFVF_XYZ,
D3DPOOL_MANAGED,
&vb,
0
);
//创建一个动态缓存的例子,可容纳36个16位的索引
IDirect3DIndexBuffer9* ib;
device->CreateIndexBuffer(
36*sizeof(WORD),
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, //动态缓存与只写
D3DFMT_INDEX16, //指定索引的大小为16位
D3DPOOL_MANAGED,
&ib,
0
);
为了访问顶点缓存或索引缓存中的数据,需要先获得指向缓存内部存储区的指针。使用方法Lock来获取。
很重要的一点是,对缓存访问完毕后,必须对缓存进行解锁。
获取拉指向缓存内容的指针后,就可以对其内容进行读写操作。
注意
//以下2个方法参数完全相同
//获取顶点缓存指针
HRESULT IDirect3DVertexBuffer9::Lock(
UINT OffsetToLock, //指定偏移量(字节)
UINT SizeToLock, //所要锁定的字节数
BYTE** ppbData, //指向被锁定的存储区起始位置的指针
DWORD Flags //标记描述位,描述锁定的方式
);
//获取索引缓存指针
HRESULT IDirect3DIndexBuffer9::Lock(
UINT OffsetToLock,
UINT SizeToLock,
BYTE** ppbData,
DWORD Flags
);
参数理解:
使用示例:
Vertex* vertices;
_vb->Lock(0,0,(void*)*&vertices,0); //锁定整个缓冲区
vertices[0] = Vertex(-1.0f, 0.0f, 2.0f); //将顶点写入缓冲区
vertices[1] = Vertex(0.0f, 1.0f, 2.0f);
vertices[2] = Vertex(1.0f, 0.0f, 2.0f);
_vb->Unlock(); //访问完缓冲区后解锁
有时需要得到有关顶点缓存和索引缓存的信息。下面的例子示范了用于获取这类信息的几种方法。
D3DVERTEXBUFFER_DESC dd;
vertexBuffer->GetDesc(&dd); //获取信息放入dd
D3DINDEXBUFFER_DESC dd2;
vertexBuffer->GetDesc(&dd2); //获取信息放入dd2
D3DVERTEXBUFFER_DESC 和 D3DINDEXBUFFER_DESC 结构定义如下:
typedef struct _D3DVERTEXBUFFER_DESC{
D3DFORMAT Format;
D3DRESOURCETYPE Type;
DWORD Usage;
UINT Size;
DWORD FVF;
}D3DVERTEXBUFFER_DESC;
typedef struct _D3DINDEXBUFFER_DESC{
D3DFORMAT Format;
D3DRESOURCETYPE Type;
DWORD Usage;
D3DPOOL Pool;
UINT Size;
}D3DINDEXBUFFER_DESC;
Direct3D封装拉多种绘制状态,这些绘制状态影响几何体的绘制方式。各种绘制状态均具有默认值,所以仅当应用程序需要使用一种不同的绘制状态时,才需要对其进行修改。自指定某种绘制状态起,该状态始终有效,直至该状态被修改为止。
设置绘制状态方法如下:
HRESULT IDirect3DDevice9::SetRenderState(
D3DRENDERSTATETYPE State, //要改变的状态
DWORD Value; //新状态的值
);
例如,示例中,将用线框模式来绘制物体。所以,应该这样设置绘制状态:
_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
注意:
一旦我们创建拉顶点缓存以及索引缓存(索引缓存是可选的),我们基本上已经可以对其所存储的内容进行绘制了,但是绘制之前,还有3个步骤需要完成。
1. 指定数据流输入源。将顶点缓存和数据流进行链接,实质上是将几何体的信息传输到绘制流水线中。
下面的方法用于设置顶点数据流的输入源。
HRESULT IDirect3DDevice9::SetStreamSource(
UINT StreamNumber,
IDirect3DVertexBuffer9* pStreamData,
UINT OffsetInBytes,
UINT Stride
);
假设 vb 是一个存储为 Vertex 类型的顶点数据的顶点缓存。
_device->SetStreamSource(0,vb,0,sizeof(Vertex));
2:设置顶点格式。在这里指定后续绘制调用中使用的顶点格式。
_device->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
3:设置索引缓存。如果要使用索引缓存,必须对后续绘制操作中所要使用的索引缓存进行设置。任意时刻只允许使用一个索引缓存,如果要使用不同的索引缓存时,必须进行切换。
下面的代码演示如何设置索引缓存:
_device->SetIndices(_id); //传递索引缓冲区指针的副本
待顶点缓存和索引缓存创建完毕,且准备工作完成之后,我们便可对几何体进行绘制,也就是使用 DrawPrimitive 或 DrawIndexedPrimitive 方法将待绘制几何体的信息通过绘制流水线传输。这两个方法从顶点数据流中获取顶点信息,并从当前设定的索引缓存中提取索引信息。
IDirect3DDevice9::DrawPrimitive
该方法可用于绘制未使用索引信息的图元。
HRESULT IDirect3Ddevice9::DrawPrimitive(
D3DPRIMITIVETYPE PrimitiveType,
UINT StartVertex,
UINT PrimitiveCount
);
//画四个三角形
_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 4);
IDirect3DDevice9::DrawlndexedPrimitive
HRESULT IDirect3DDevice9::DrawIndexedPrimitive(
D3DPRIMITIVETYPE Type,
INT BaseVertexIndex,
UINT MinIndex,
UINT NumVertices,
UINT StartIndex,
UINT PrimitiveCount
);
_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
BaseVertexlndex 参数的解释:
局部索引缓存的内容应与局部顶点缓存中的顶点一致。假定我们想将球,盒以及圆柱体的顶点合并到同一个全局缓存中。对于每个物体,我们必须重新计算索引,以保证这些索引正确的指向全局顶点缓存中对应的顶点。新索引的计算方法是为每个索引增加一个指定拉物体顶点在全局缓存中存储的起始位置的偏移量。注意,该偏移量用顶点的个数来度量而非字节。
最后还有一点要指出的是,所有的绘制方法都必须在 IDirect3DDevice9::BeginScene 和 IDirect3DDevice9::EndScene 构成的方法之间进行调用。例如:
_device->BeginScene();
_device->DrawPrimitive(...);
_device->EndScene();
总结:
以上所有内容都是在书中看到的,仅用于学习记录作用,另可供有需要的人查看,如有侵权,请联系我。