游戏开发基础(三)

 

第三章
顶点缓存是一个包含顶点数据的连续内存空间
索引缓存是一个包含索引数据的连续的内存空间
之所以用顶点缓存和索引缓存而非数组来存储数据,是因为顶点缓存和索引缓存可以被放置在显存中
顶点缓存 IDirect3DVertexBuffer9表示,索引缓存用接口IDirectIndexBuffer9表示
创建顶点缓存
HRESULT IDirect3DDevice9::CreateVertexBuffer(
     UINT Length,
     DWORD Usage,
     DWORD FVF,
     D3DPOOL Pool ,
     IDirect3DVertexBuffer9** ppVertexBuffer,
     HANDLE* pShareHandle
     ); 
创建索引缓存
HRESULT IDirect3DDevice9::CreateIndexBuffer(
     UINT Length,
     DWORD Usage,
     D3DFORMAT Format,
     D3DPOOL Pool ,
     IDirect3DIndexBuffer9** ppIndexBuffer,
     HANDLE* pShareHandle
     );
*Length 为缓存分配的字节数
*Usage 指定关于如何使用缓存的一些属性。该值为0(表明无需附加属性)
    # D3DUSAGE_DYNAMIC 将缓存设为动态缓存
    # D3DUSAGE_POINTS  存储点图元
    # D3DUSAGE_SOFTWAREPROCESSING  指定软件顶点运算方式
    # D3DUSAGE_WRITEONLY  应用程序对缓存的操作模式为“只写”
*FVF 存储在顶点缓存中顶点的灵活顶点格式
*Pool 容纳缓存的内存池
*ppVertexBuffer 用于接收所创建的顶点缓存的指针
*pSharedHandle 不使用,为0
*Format 指定索引的大小,设为D3DFMT_INDEX16表示16为索引,设为D3DFMT_INDEX32表示32为索引
*ppIndexBuffer 用于接收所创建的索引缓存的指针
静态缓存一般放置在显存中
动态缓存一般放置在AGP中
对显存和AGP存储区进行读操作非常慢

例:创建一个可容纳8个Vertex类型的顶点的静态顶点缓存

IDirect3DVertexBuffer9* vb;
device -> CreateVertexBuffer(8*sizeof(Vertex),0,D3DFVF_XYZ,D3DPOOL_MANAGED,&vb,0);
创建一个动态缓存的例子,所创建的动态缓存可容纳36个16为索引
IDirect3DIndexBuffer9* ib;
device -> CreateIndexBuffer(36*sizeof(WORD),D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_MANAGED,&ib,0);
访问缓存内容
借助方法Lock来获取缓存内容指针。
如果常见顶点缓存或索引缓存时,使用了D3DUSAGE_WRITEONLY标记,便无法对该缓存进行读操作
HRESULT IDirect3DVertexBuffer9::Lock(UINT OffsetToLock,
     UINT SizeToLock,
     BYTE** ppbData,//指定被锁定存储区的起始位置的指针
     DWORD Flags//标记锁存方式
     );
HRESULT IDirect3DIndexBuffer9::Lock(UINT OffsetToLock,
     UINT SizeToLock,
     BYTE** ppbData,
     DWORD Flags
     );

*Flags 标记锁存方式,可以是0
#D3DLOCK_DISCARD 仅用动态缓存。它指示硬件将缓存内容丢弃,并返回一个指向重新分配的缓存的指针的指针。该标记十分有用,因为这

允许在我们访问新分配的内存时,硬件能够继续使用被丢弃的缓存中的数据进行绘制,这样硬件的绘制就不会中止
#D3DLOCK_NOOVERWTITE 仅用动态缓存,该标记数据只能以追加方式写入缓存,可以保证在缓存中增加数据时,硬件仍可持续进行绘制
#D3DLOCK_READONLY 表示所锁定的缓存只可读而不可写,利用这一点可以作一些内部优化

例: Lock使用方法
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 vbDescription;
vertexBuffer->GetDesc(&vbDescription);

D3DINDEXBUFFER_DESC ibDescription;
indexBuffer->GetDesc(&ibDescription);


D3DVERTEXBUFFER_DESC 和 D3DINDEXBUFFER_DESC 结构:
typedef struct _D3DVERTEXBUFFER_DESC{
 D3DFORMAT Format;
 D3DRESOURCETYPE Type;
 DWORD Usage;
 D3DPOOL Pool ;
 UINT Size;
 DWORD FVF;
}D3DVERTEXBUFFER_DESC

typedef struct _D3DINDEXBUFFER_DESC{
 D3DFORMAT Format;
 D3DRESOURCETYPE Type;
 DWORD Usage;
 D3DPOOL Pool ;
 UINT Size;
 DWORD FVF;
}D3DINDEXBUFFER_DESC

 

Direct3D封装了多种绘制状态(rendering state)
HRESULT IDirect3DDevice9::SetRenderState(
     D3DRENDERSTATETYPE State,
     DWORD Value 
     );
例:
_device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WRITEFRAME);

一旦我们创建了顶点缓存以及索引缓存,我们基本上已经可以准备对其所存储的内容进行绘制了,但是绘制之前,还有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_TEXI);
(3)设置索引缓存。
_device->SetIndices(_ib);

使用DrawPrimitive或DrawIndexdPrimitive方法将待绘几何体信息通过绘制流水线传输,这两个方法从顶点数据流中获取顶点信息,并从

当前设定的索引缓存中提取索引信息

//该方法可用于绘制未使用索引信息的图元
HRESULT IDirect3DDevice9::DrawPrimitve(
     D3DPRIMITIVETYPE PrimitiveType,//所要绘制的图元类型,#D3DPT_TRIANGLELIST三角形
     UINT StartVertex,//顶点数据流中标识顶点数据读取起点的元素的索引
     UINT PrimitiveCount//所要绘制的图元数量
     );
HRESULT IDirect3DDevice9::DrawIndexedPrimitve(
     D3DPRIMITIVETYPE Type,//绘制图元类型
     INT BaseVertexIndex,//索引增加的一个基数
     UINT MinIndex,//允许引用的最小索引值
     UINT NumVertices,//本次调用中将引用的顶点总数
     UINT StartIndex,//顶点缓存中标识索引的读取起始点的元素的索引
     UINT PrimitiveCount //所要绘制的图元总数
     );
所有绘制方法都必须在IDirect3DDevice9::BeginScene和IDirect3DDevice9::EndScene构成的方法之间进行调用
例:
_device->BeginScene();
_device->DrawPrimitive(...);
_device->EndScene();

D3DX库提供了一些用于生成简单3D几何体的网格数据方法
D3DX库提供如下6个网格创建函数
*D3DXCreateBox
*D3DXCreateSphere
*D3DXCreateCylinder
*D3DXCreateTeapot
*D3DXCreatePolygon
*D3DXCreateTorus
这6个方法都非常相似,并且都使用D3DX网格数据结构ID3DXMesh和ID3DXBuffer接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值