硬件缓冲区和缓冲锁使用经验
1:因为最快最优秀的缓冲自然是通过 HBU_STATIC_WRITE_ONLY类型创建,不创建备份缓存,并且仅进行一次HBL_DISCARD的锁操作永不再额外处理的缓冲。
2:当我们需要频繁更新的缓冲,可以用HBU_DYNAMIC_WRITE_ONLY来创建,不创建备份缓存,之后使用HBL_DISCARD加锁,若不想全部更新,则使用HBL_NO_OVERWRITE进行锁操作。
3:若我们必须从缓冲区中读取数据的话,那么我们可以创建一个备份缓冲,用HBL_READ_ONLY将其锁住。可能的话,尽量声明缓冲区为静态的。
4:在我们对顶点的不同元素需要使用不同模式的时候,我们不要通过指针大量更新缓冲区的全部顶点结构,应该分块更新。例如,我们假设只需要经常更新纹理坐 标信息,那么我们应当将纹理坐标信息保存在一个单独的缓冲区区域,而其他的不经常更新的元素拆分保存在HBU_STATIC_WRITE_ONLY缓冲区 中。
·顶点缓冲区
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.data) // 数据获得,随便处理
}
}
Buffer->unlock(); //最后记得解锁。
6:外部纹理源
·定义。
我们读取一个纹理,通常是从一个.jpg.png.bmp等格式的图形文件中进行读取,但有些时候我们需要从avi.mpeg等电影格式文件,flv文件,实时渲染产生的来源中读取纹理,这些渠道来源就被称为外部纹理源。
·处理外部纹理源。
我们如何处理外部纹理源?本身Ogre是没有写的。不过它提供了方法的接口,以便我们写出需要的插件。
·外部纹理源插件编写方法
我们构建的插件必须继承于ExternalTextureSource类。它提供了一个通用的框架。另外,当我们开始需要获取外部纹理源的时候可以使用 ExternalTextureSourceManager类中的函数来获得。典型的函数可以如 下:AdvanceTextureManager::GetSingleton().GetCurrentPlugIn()
->CreateDefinedTexture(sMaterialName);
·外部纹理源脚本
Material Example/MyVideoExample
{
Technique
{
Pass
{
Texture_unit
{
Texture_source video
{
Filename MyMovie.avi
Play_mode play
Sound_mode Off // 注意:这些属性根据插件不同而且不同
}
}
}
}
}
7:阴影
·启动阴影
1:默认时阴影是被关闭的。我们要使用阴影就必须使阴影有效,而这个操作必须极其优先处理,因为,是否开启阴影会影响模型读取的方式。如:
M_SceneMgr->SetShadowTechnique( SHADOWTYPE_STENCIL_ADDITIVE ); //开启一个模板阴影。
2:关闭部分不支持投射阴影的光源。(有些光源并不支持投影)
Light::SetCastsShadow(false)
3:关闭那些不需要投射阴影的物体。(有些透明物体可能不需要投影)
MovableObject::SetCastsShadow(false)
4:设置投影的最远距离。(为了性能考虑,需要设置)
5:关闭那些不需要接受阴影的物体。(透明材质,自发光材质通常是不能接收投影的)
Material::SetReciveShadow(false )
8:动画
Ogre默认支持四种脚本动画。
1) 骨骼动画。使用骨骼结构来定义网格数据。
a) Ogre的骨骼和动画信息被保存在 .skeleton 的脚本文件中。
b) 我们进行动画操作时,需要创建一个叫动画状态的对象来控制该动画的状态。我们可以通过Entity::getAnimationState()来获得一个指向动画状态的指针,之后我们在frameStarted时间中,通过动画状态指针来进行动画更新。
2) 顶点动画。保存顶点快照来决定网格数据如何改变。
3) 场景节点动画。按照预先定义的路径,来操作场景节点上挂接的实体进行移动产生动画。
a) 我们可以为每个SceneNode创建一个对应的NodeAnimationTrack
4) 数值动画。使用Ogre的接口类AnimableObject来继承扩展。这样就可以自定义其对象属性。
|