3.1顶点/索引缓存顶点和索引缓存有相似的接口并且共享相似的方法;因此我们把它们合在一起讲解。一个顶点缓存是一块连续的存储了顶点数据的内存。同样的,一个索引缓存是一块连续的存储了索引数据的内存。我们使用顶点和索引缓存保存我们的数据是因为它们能被放置在显存中。渲染显存中的数据要比渲染系统内存中的数据快的多。 在代码中,一个顶点缓存是通过IDirect3DVertexBuffer9接口来定义的。类似的,一个索引缓存是通过IDirect3DIndexBuffer9接口来定义。 3.1.1创建一个顶点和索引缓存我们能使用下面两个方法创建一个顶点缓存和索引缓存: HRESULT IDirect3DDevice9::CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle ); HRESULT IDirect3DDevice9::CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle ); 这两个方法大部分参数是相同的,因此我们一起介绍它们。 Length —— 分配给缓存的字节大小。假如想得到一个能存储8个顶点的顶点缓存,那么我们就要在顶点结构中设置这个参数为 8 * sizeof ( Vertex ) 。 Usage —— 指定关于怎样使用缓存的额外信息。这个值可以是0,没有标记,或者是下面标记的一个或多个的组合: D3DUSAGE_DYNAMIC——设置这个参数可以使缓存是动态的。 D3DUSAGE_POINTS——这个参数指定缓存存储原始点。这个参数仅仅用在顶点缓冲中。 D3DUSAGE_SOFTWAREPROCESSING——使用软件顶点处理 D3DUSAGE_WRITEONLY——指定应用程序只能写缓存。它允许驱动程序分配最适合的内存地址作为写缓存。注意如果从创建好的这种缓存中读数据,将会返回错误信息。 FVF —— 存储在缓存中的顶点格式 Pool —— 缓存放置在哪一个内存池中 ppVertexBuffer ——返回创建好的顶点缓存的指针。 pSharedHandle ——没有使用;设置为0。 Format ——指定索引的大小;使用D3DFMT_INDEX16设置16位索引,使用D3DFMT_INDEX32设置32位索引。注意并非所有设备都支持32位索引;请检查设备能力。 ppIndexBuffer ——返回创建好的索引缓存的指针。 注意:不使用D3DUSAGE_DYNAMIC参数创建的缓存被叫做静态缓存。静态缓存通常被放置在显存中,在其中的数据能被很有效的处理。然而,对于静态缓存,从中读取和写入数据是很慢的,因为访问显存是很慢的。因为这个原因我们用静态缓存存储静态数据(不需要被经常改变的数据)。地形和建筑物是很好的候选例子,因为在应用程序中他们通常不需要被改变。静态缓存应该在应用程序初始化的时候就被填充好,而不是在运行时才做。 注意:使用D3DUSAGE_DYNAMIC参数创建的缓存被叫做动态缓存。动态缓存通常被放在AGP内存中,这种内存中的数据能被很快的更新。处理动态缓存中的数据不会比处理静态缓存中的数据快,因为这些数据必须在渲染前被转移到显存中,动态缓存的好处是它们能够被稍微快点地被更新(比CPU写快)。因此,假如你需要经常更新缓存中的数据,那么你就应该使用动态缓存。粒子系统是很好的一个应用,因为它们是动态的,并且他们通常每一帧都会被更新。 注意:在程序中读取显存和AGP内存都是非常慢的。因此,假如你在运行时需要读取你的几何物体,最好的方案是指定一块系统内存,往其中拷贝并且读取数据。 下边是创建一个静态顶点缓存的例子,该缓存能存储8个顶点。 IDirect3DVertexBuffer9* vb; device->CreateVertexBuffer( 8 * sizeof( Vertex ), 0, D3DFVF_XYZ, D3DPOOL_MANAGED, &vb, 0); 3.1.2 访问缓冲内存为了访问一个顶点/索引缓存,我们需要得到一个指针。我们通过一个指针获得缓存数据必须使用Lock方法。当我们访问完缓存后必须对它解锁。一旦有一个指向内存的指针,我们就能对它进行读写。 HRESULT IDirect3DVertexBuffer9::Lock( UINT OffsetToLock, UINT SizeToLock, BYTE** ppbData, DWORD Flags ); HRESULT IDirect3DIndexBuffer9::Lock( UINT OffsetToLock, UINT SizeToLock, BYTE** ppbData, DWORD Flags ); 这两个方法的参数都是完全相同的。 OffsetToLock —— 偏移量,以字节为单位,从缓存开始位置到锁定开始位置的距离。如图3.1。 SizeToLock —— 锁定的字节数。 ppbData —— 一个指向锁定内存开始位置的指针。 Flags —— 标记描述怎样锁定内存。它可能是0或者是下面参数中的1个或多个的组合: D3DLOCK_DISCARD——这个参数仅仅会在动态缓存时被使用。它指示硬件丢弃缓存并返回一个指向新分配的缓存的指针。这是很有用,因为当我们存取一个新分配的缓存时它允许硬件继续从丢弃的缓存渲染。这防止了硬件延迟。 D3DLOCK_NOOVERWRITE——这个参数仅仅会在动态缓存时被使用。它声明你将向缓存中添加数据。即你不能向已经渲染的内存中写数据。这是有好处的因为他允许你在添加新数据到缓存的同时让硬件继续渲染。 D3DLOCK_READONLY——这个参数声明你锁定的缓存只能从中读取数据而不能写数据。这允许一些内在的优化。 用参数D3DLOCK_DISCARD和D3DLOCK_NOOVERWRITE表明缓存的一部分被锁定之后能继续被使用。假如硬件配置允许这些标记被使用,则在对缓存进行锁定时,其他的显示操作就不会中断。 下边的例子展示了通常怎样使用Lock方法。注意当我们使用完以后要调用Unlock方法。 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(); // 当你访问完缓存时,解锁缓存 3.1.3 找回顶点和索引缓存信息有时我们需要得到顶点/索引缓存信息。下面的例子示范了用于获得这些信息的方法: D3DVERTEXBUFFER_DESC vbDescription; _vertexBuffer->GetDesc(&vbDescription); // 取得顶点缓存信息 D3DINDEXBUFFER_DESC ibDescription; _indexBuffer->GetDesc(&ibDescription); //取得索引缓存信息 D3DVERTEXBUFFER_DESC和D3DINDEXBUFFER_DESC结构的定义如下: Describes a vertex buffer. typedef struct D3DVERTEXBUFFER_DESC { Members
Defines resource types. typedef enum D3DRESOURCETYPE Constants
Describes an index buffer. typedef struct D3DINDEXBUFFER_DESC { Members
|
Direct3D中的绘制(1)
最新推荐文章于 2018-04-27 15:16:36 发布
Direct3D中的绘制(1)