Direct3D中的绘制
一.顶点缓存与索引缓存
一个顶点缓存是一个包含顶点数据的连续内存空间.
一个索引缓存是一个包含索引数据的连续内在空间.
我们之所以用顶点缓存和索引缓存而非数组来存储数据,是因为顶点缓存和索引缓存可以被放置在显存video memory中,显存在绘制时比内存中的数据快
顶点缓存用接口:
IDirect3DVertexBuffer9
索引缓存用接口
IDirect3DIndexBuffer9
1.创建顶点缓存和索引缓存
//创建顶点缓存
HRESULT CreateVertexBuffer(
UINT Length, //缓存的长度 顶点个数*FVF的结构体大小
DWORD Usage, //指定关于如何使用缓存的一些附加属性
DWORD FVF, //灵活顶点格式
D3DPOOL Pool, //容纳缓存的内存池
IDirect3DVertexBuffer9** ppVertexBuffer,//所要创建的顶点缓存的指针
HANDLE* pSharedHandle //0
);
//创建索引缓存
HRESULT CreateIndexBuffer(
UINT Length,
DWORD Usage,
D3DFORMAT Format, //指定索引的大小,设为D3DFMT_INDEX16表示16位索引
D3DPOOL Pool,
IDirect3DIndexBuffer9** ppIndexBuffer,//所要创建的索引缓存的指针
HANDLE* pSharedHandle //0
);
创建缓存时,如果未使用标记D3DUSAGE_DYNAMIC,则称所创建的缓存为静态缓存static buffer.静态缓存一般被放置在显存中,以保证存储于其中的数据得到最高效的处理.然而,静态缓存是以牺牲对静态缓存读写操作的速度为代价,这是因为访问显存的速度本身就很慢
动态缓存dynamic buffer一般放置在AGP(accelerated Graphics Ports)存储区中,其内容可以被迅速更新,动态缓存中数据的处理速度不像静态缓存那样快,就是因为在绘制前数据必须传输到显存中
注意:
对显示和AGP存储区进行读操作非常慢.所以如果您需要在程序运行时读取几何数据,最好在系统内在中保留一份副本,然后在需要时对其进行读报操作.
2.访问缓存内容:
我们需要获得指向缓存内部存储区域的指针,可以借助方法lock来获取指向缓存内容的指针.很重要的一点是,对缓存访问完毕后,必须对缓存进行解锁.
注意:
如果创建顶点缓存或索引缓存时,使用了D3DUSAGE_WRITEONLY标记,您便无法对该缓存进行读操作,否则会导致读取失败.
//
HRESULT IDirect3DVertexBuffer9::Lock(
UINT OffsetToLock, //自缓存的起始点到开始锁定的位置的偏移量
UINT SizeToLock, //要锁定的字节数
VOID ** ppbData, //指向被锁定的存储区起始位置的指针
DWORD Flags //指定锁定的方式,可以是0
);
HRESULT IDirect3DVertexBuffer9::Lock(
UINT OffsetToLock,
UINT SizeToLock,
VOID ** ppbData,
DWORD Flags
);
3.获取顶点缓存和索引缓存的信息
typedef struct D3DVERTEXBUFFER_DESC {
D3DFORMAT Format; //index的格式
D3DRESOURCETYPE Type;
DWORD Usage;
D3DPOOL Pool;
UINT Size;
DWORD FVF;
} D3DVERTEXBUFFER_DESC, *LPD3DVERTEXBUFFER_DESC;
得到CreateVertexBuff和CreateIndexBuff的一些信息
D3DVERTEXBUFFER_DESC vbDescription;
vertexBuffer->GetDesc(&vbDescription);
typedef struct D3DINDEXBUFFER_DESC {
D3DFORMAT Format;
D3DRESOURCETYPE Type;
DWORD Usage;
D3DPOOL Pool;
UINT Size;
} D3DINDEXBUFFER_DESC, *LPD3DINDEXBUFFER_DESC;
D3DINDEXBUFFER_DESC ibDescription;
indexBuffer->GetDesc(&ibDescription);
二.绘制状态
Direct3D封装了多种绘制状态(rendering state), 这些绘制状态将影响几何体的绘制方式.
用来改变原来默认的绘制状态:
HRESULT SetRenderState(
D3DRENDERSTATETYPE State, //绘制的状态
DWORD Value //改变的值
);
三.绘制的准备工作
步骤:
1.指定数据流输入源:将顶点缓存和数据流进行链接,实质上是将几何体的信息传输到绘制流水线中.
HRESULT SetStreamSource(
UINT StreamNumber, //标识与顶点缓存建立链接的数据流 ,0
IDirect3DVertexBuffer9 * pStreamData, //指向我们希望与给定数据流建立的链接的顶点缓存指针
UINT OffsetInBytes, //顶点的起始位置
UINT Stride //将链接到数据流的顶点缓存中每个元素的大小
);
2.设置顶点格式,在这里指定后续绘制调用中使用的顶点格式
HRESULT SetFVF(
DWORD FVF
);
之前顶点使用的灵活顶点格式
3.设置索引缓存.
HRESULT SetIndices(
IDirect3DIndexBuffer9 * pIndexData
);
四.使用顶点缓存和索引缓存进行绘制
目的:使用DrawPrimitive或DrawIndexedPrimitive方法将待绘几何体的信息通过绘制流水线传输.
1.IDriect3DDevice9::DrawPrimitive
HRESULT DrawPrimitive(
D3DPRIMITIVETYPE PrimitiveType,//所要绘制的图元类型
UINT StartVertex, //顶点数据流中标识顶点数据读取起点的元素索引
UINT PrimitiveCount //所要绘制的图元数量
);
2.IDirect3DDevice9::DrawIndexedPrimitive
HRESULT DrawIndexedPrimitive(
D3DPRIMITIVETYPE Type, //所要绘制的图元类型
INT BaseVertexIndex, //为索引增加一个基数
UINT MinIndex, //允许引用的最小索引值
UINT NumVertices, //本次调用中将引用的顶点总数
UINT StartIndex, //顶点缓存中标识索引的读取起始点的元素的索引
UINT PrimitiveCount //所要绘制的图元数量
);
3.Beign/End Scene
所有的绘制方法都必须在IDriect3DDevice9::BeginScene和IDriect3DDevice9::EndScene构成的方法对之间进行调用.
五.D3DX几何体
D3DXCreateBox
D3DXCreateSphere
D3DXCreateCylinder
D3DXCreateTeapot
D3DXCreatePolygon
D3DXCreateTorus
他们都使用D3DX网格结构ID3DXMesh和ID3DXBuffer
ID3DXMesh * mesh = 0;
D3DXCreateTeapot(_device, & mesh, 0);
_device->BeginScene();
_mesh->DrawSubset(0);
_device->EndScene();
_mesh->Release();
_mesh = 0;
六.例程
见: