·定义 实际上这个缓冲区就是一块malloc出来的存储区域,不过它不如malloc是在内存中申请的区域,而这个缓冲区是在gpu/agp中,它的写读速度更快。通常硬件缓冲区作用有拿来做顶点缓冲区,索引缓冲区,和象素缓冲区。 ·使用 硬件缓冲区的管理是交由一个硬件缓存管理器负责的HardwareBufferManager,他负责缓冲区的创建和释放,它是几何体创建工厂,单键在Root初始化时就会被创建,所以,当我们需要一块内存的时候,一定不要直接New或malloc操作,而应当是这样 VerBuf = HardwareBufferManager::GetSingleton().CreateVertexBuffer() ·类型 我们在分配一块硬件缓冲区时,需要传一个参数,来指明这块缓冲区的类型,是否需要频繁读写?这样对底层的硬件缓存区域分配管理提供很大的便利。我们来看一下硬件缓冲区的类型有哪些,我们分配它的时候应该做何选择。(HBU是HarewareBufferUsage简写) HBU_STATIC 静态硬件缓冲区,它意味着我们很少写入更新缓冲区,偶尔会从中进行数据读取。 HBU_STATIC_WRITE_ON HBU_DYNAMIC 动态硬件缓冲区。它意味着我们会经常性的更新缓冲区中的数据,并且也希望能从其中读取数据,这一个效率最低的缓冲区使用方法。 HBU_DYNAMIC_WRITE_ON HBU_DYNAMIC_WRITE_ON 建议:多使用WRITE_ON ·备份缓冲 当我们创建一个WRITE_ON ·缓存锁 当我们更新写入缓冲或者在读取缓冲的时候,都应该先“锁”住它,以免它被修改。当然,之后记得解锁。pBuffer->Lock(begin , length , lockType)一般来说,锁的范围越小越便捷快速。但是锁的类型lockType也可以对读取的效率产生影响。 锁的类型包括: ·HBL_NORMAL 这种锁支持从缓冲区读取数据,但是效率很低下,因为它允许我们从硬件缓冲区进行数据读取。但是,当我们使用备份缓冲的话,这种影响会得到一些改善。 ·HBL_READ_ON ·HBL_DISCARD 这种锁意味着我们每次操作都会将硬件缓冲区中的所有内容丢弃,一般这种操作也是会在每桢都处理的环境下才会使用,它是禁止读出的。但是一旦我们如此声明,也就基本上是向引擎宣称我们不会对硬件缓冲区的内容感兴趣,那么就不应当创建备份缓冲区。在我们没有使用备份缓冲区时尽量使用这种锁,它的效率很高,但若有了内存备份缓冲区的话,它就没有必要了。 ·HBL_NO_OVERWRITE 当我们有些时候需要更新部分缓冲区而非全部缓冲区时,使用HBL_DISCARD就显的不适合了。此时我们就需要使用这种锁了,它的效率依旧很高,但是也仅是没有备份缓冲的时候才有作用。 ·硬件缓冲区和缓冲锁使用经验 1:因为最快最优秀的缓冲自然是通过 HBU_STATIC_WRITE_ON 2:当我们需要频繁更新的缓冲,可以用HBU_DYNAMIC_WRITE_ON 3:若我们必须从缓冲区中读取数据的话,那么我们可以创建一个备份缓冲,用HBL_READ_ON 4:在我们对顶点的不同元素需要使用不同模式的时候,我们不要通过指针大量更新缓冲区的全部顶点结构,应该分块更新。例如,我们假设只需要经常更新纹理坐标信息,那么我们应当将纹理坐标信息保存在一个单独的缓冲区区域,而其他的不经常更新的元素拆分保存在HBU_STATIC_WRITE_ON ·顶点缓冲区 VertexData中有几个重要成员: ·VertexStart 顶点起始位置信息 ·VertexCount 顶点个数 ·VertexDeclaration 一个指向顶点数据个数的指针 ·VertexBufferBinding 一个指向顶点缓冲区绑定的指针 其中顶点类型描述中我们需要强调一个顺序问题,为了支持DX9以前的版本,我们有必要按如下顺序声明和数据保存: 1:顶点位置信息 2:顶点绑定权重 3:顶点法线信息 4:顶点环境光颜色信息 5:顶点镜面光颜色信息 6:顶点纹理坐标信息 除了上面的顺序需要注意以外,我们还需要注意的是顶点缓冲区中,是绝对不允许有空隙存在的。 我们创建了一个顶点缓冲区后,我们还需要将起和指定的资源进行绑定。 格式如下 verterBufferBinding->setBinding(0, vertexBuffer); 之后,我们在运行时将顶点缓冲区绑定起来,循环的将其信息更新填充进入,Ogre提供了临接点与点之间的间隔长度和起始点信息,以便我们进行数据更新。 ·索引缓冲区 与顶点缓冲区基本都是一致的。创建后更新。唯一的区别就是创建时有些属性不同而已。 ·象素缓冲区 这里是保存纹理象素信息的。但是和顶点缓冲和索引缓冲不同的是,我们不能手动创建象素缓冲区,只有在我们创建一个纹理的时候,象素缓冲会自动被创建出来。 象素缓冲区中支持的纹理类型: TEX_TYPE_1D 一维的纹理,通过1D纹理坐标来索引 TEX_TYPE_2D 二维的纹理,通过2D文理坐标来索引 TEX_TYPE_3D 三维的纹理,通过3D文理坐标来索引 TEX_TYPE_CUBE_MAP 一个立方体的六个表面纹理,通过3D纹理进行索引。 象素缓冲区的内存分配格式 Ogre中的图象数据的信息都被封装在一个个的PixelBox对象之中,我们需要注意的是PixelBox本身是保存在GPU中,但是真正的纹理都是保存在内存中,并非读到GPU中。GPU中的 PixelBox保存着内存中象素的格式位置内容信息的描述,但是PixelBox并没有内存管理的功能,它只能通过保存的内存指针来操作数据。象素盒中提供了通过深度,高度,宽度来索引象素的方法,若一维纹理没有高度和深度时,就将其参数补1。如下:(width, 1, 1),二维的纹理(width, height, 1) 象素缓冲区的更新 Ogre提供了两种更新象素缓冲区的方法。 1:手动建立一个纹理并将一个图片放入这个纹理中。我们可以如下代码Image img; img.load(“xxx.jpg”, “General”); Texture pTex = Texture::getSingleton().createManual( …. ); pTex->GetBuffer(0,0)->blitFromMemory( ); 2:对一个象素缓冲区加锁之后对其进行读取和写入。 Buffer->Lock(HarewareBuffer::HBL_DISCARD); const PixelBox &pb = buffer->getCurrentLock(); // 锁好了之后进行处理 for (int I = 0; I < pb.GetWindth(); ++I) { For( int j = 0; j < GetHeight(); ++j) { Static_cast<unit32*>(pb.da } } Buffer->unlock(); //最后记得解锁。 |