关于 Demo_Instancing 例子的分析
1. 本例建立框架模板的时候, 使用release版本编译运行一番, 发现其所用的文件ogre.cfg, plugins.cfg, resources.cfg与debug的版本不同, 链接库也不同.
空白Ogre程序在release版本下FPS是1050左右, 但是在debug版本下只有90. 差距太大了啊
2. 天空盒使用的材质 是立体图 cubic_texture morning.jpg separateUV
3. Ogre的Plane类表示一个平面, 其normal成员表示该平面的朝向, 其d表示在mesh中距离原点的距离, 方向为normal
3. 在本例可以学会三种方式创建具有大量内容的几何体: 实体方式, 实例几何体, 静态几何体
4. 静态几何体和实例几何体的删除很简单, 直接delete创建的该对象就可以, 然后场景里的该对象就会消失.
5. 这里的buildInstancedMaterial讲述了如何克隆一个材质并如何设置所有通道的着色程序
6. 函数createInstanceGeom和函数createStaticGeom分别为创建实例几何体和静态几何体的重要方法
1. InstancingApplication 类
构造函数: 初始化 CEGUI的渲染器, 系统, 表单窗口
析构函数: 清理 CEGUI的表单窗口(WindowManager的destroyWindow方法), 系统, 渲染器
函数 getRenderWindow
得到Ogre的渲染窗口
函数 createScene
设置环境光, 光, 天空盒, 相机, 平面
setupGUI
setupEventHandlers
视口增加合成器 "Bloom"
函数 setupGUI
// 该函数设置CEGUI
方案 TaharezLookSkin.scheme
缺省光标 TaharezLook MouseArrow
光标图像 TaharezLook MouseMoveCursor
表单窗口 布局 InstancingDemo.layout
函数 setupEventHandlers
// 给所有的CEGUI窗口订阅事件处理函数
ExitDemoBtn PushButton::EventClicked handleQuit
tInstancing RadioButton::EventSelectStateChanged handleTechniqueChanged
tStaticGeometry RadioButton::EventSelectStateChanged handleTechniqueChanged
tIndependantEntities RadioButton::EventSelectStateChanged handleTechniqueChanged
Object Count Scrollbar::EventScrollPositionChanged handleObjectCountChanged
Time Burner Scrollbar::EventScrollPositionChanged handleTimeBurnerChanged
PostEffect Checkbox::EventCheckStateChanged handlePostEffectChanged
Shadows Checkbox::EventCheckStateChanged handleShadowsChanged
Objects Combobox::EventListSelectionAccepted handleObjectChanged
root
Window::EventMouseMove handleMouseMove
Window::EventMouseButtonUp handleMouseButtonUp
Window::EventMouseButtonDown handleMouseButtonDown
函数 handleQuit
调用监听器类的 requestShutdown
函数 handleMouseMove, handleMouseButtonDown, handleMouseButtonUp
调用监听器类的同名函数
函数 handleTechniqueChanged
首先调用监听器类的 destroyCurrentGeomOpt方法 先销毁当前的几何体
根据选择的ID设置相应几何体的模式, 然后调用监听器类的 createCurrentGeomOpt创建几何体
getSelectedButtonInGroup()->getID()
((CEGUI::RadioButton*)((const CEGUI::WindowEventArgs&)e).window)->getSelectedButtonInGroup()->getID();
函数 handleObjectCountChanged
首先调用监听器类的 destroyCurrentGeomOpt方法 先销毁当前的几何体
调用监听器类的setObjectCount函数设置对象数目
在调用监听器类的 createCurrentGeomOpt创建几何体
CEGUI窗口"Object Count Number" 设置文本为几何体的数目 setText方法
函数 handleTimeBurnerChanged
调用 监听器类的 setBurnedTime 设置CPU燃烧时间 setBurnedTime
函数 handlePostEffectChanged
给当前视口增加合成器的"Bloom"效果
CompositorManager::getSingleton().setCompositorEnabled(pViewport,"Bloom",true);
函数 handleShadowsChanged
设置阴影技术
调用SceneManager的setShadowTechnique方法即可
mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
函数 handleObjectChanged
调用监听器类的 destroyCurrentGeomOpt 函数和 changSelectedMesh函数, createCurrentGeomOpt函数 实现渲染的mesh的变化
2. InstancingListener 类
构造函数:
得到GPU程序支持的句法代码, 然后遍历写入Log
GpuProgramManager::getSingleton().getSupportedSyntax()
初始化一些参数
mGUIRenderer 为CEGUI的渲染器
numMesh 表示需要渲染的mesh数量
numRender 表示分几个批次渲染这些Mesh, 每批占一层的空间
createCurrentGeomOpt
该函数主要是根据当前选择的模式和Mesh, 创建了几何体(静态, 实例, 实体)
设置鼠标键盘的回调
得到一系列CEGUI的窗口
隐藏原来的Overlay的调试窗口
创建Ogre::Timer对象
调用getMicroseconds函数并除以1000000, 得到创建以来过去的秒, 并用该值赋给 mLastTime
析构函数
调用 destroyCurrentGeomOpt 清除当前的几何体
清除Ogre::Timer对象
函数 createCurrentGeomOpt --- 该函数主要是根据当前选择的模式和Mesh, 创建了几何体(静态, 实例, 实体)
根据需要渲染的Mesh数量, 得知这些Meshes分几个批次(每个批次最多渲染80个Mesh)
numRender - 渲染的批次数
根据 meshSelected 索引变量得到选择的是哪个Mesh, 通过调用MeshManager类的getByName方法得到该MeshPtr变量
如果该MeshPtr变量为空, 则调用load方法加载
得到该Mesh的围绕球体半径, 以便将来设置每个Mesh几何体的位置
设置 posMatrices 容器, 该容器为每个Mesh几何体的位置信息
首先设置该容器大小为渲染的批次数, 每个元素都为Vector3数组, 每个数组拥有numMesh个元素
每一批的Mesh几何体都拥有相同的高度
每一层有 numMesh/10 行
每一行放10个Mesh几何体
根据currentGeomOpt(即当前的模式), 调用各自的创建几何体函数
实例几何体 - createInstanceGeom()
静态几何体 - createStaticGeom ()
实体几何体 - createEntityGeom ()
函数 createInstanceGeom - 创建实例几何体
首先判断是否支持实例几何体
根据选择的mesh创建一个实体
重置容器 renderInstance, 大小为渲染的批次数
创建 InstancedGeometry 对象, 其参数为场景管理器(可用当前相机得到), 名称(自创)
setCastShadows - 设置阴影
setBatchInstanceDimensions - 设置尺寸为(1000000, 1000000, 1000000)
设置一批渲染的mesh数, 由于有时候需要渲染的mesh少于80
调用函数 setupInstancedMaterialToEntity
该函数主要是用于修正实体所有子实体的材质所用的着色程序.
该batch循环调用addEntity, 设置一个批次的batch实体内容
调用 setOrigin 设置几何体中心
调用 build 编译该实例几何体
调用 addBatchInstance 增加该实例几何体所用的批次
调用 getBatchInstanceIterator 遍历 各个批次, 每个遍历元素的类型为 InstancedGeometry::BatchInstance*
在各个批次中调用 getObjectIterator 遍历每个对象, 每个对象的类型为 InstancedGeometry::InstancedObject*
然后调用setPosition设置每个元素的位置, 位置信息在posMatrices容器中设置好了
设置该实例几何体可见, 调用setVisible
调用场景管理器销毁刚创建的实体
函数 setupInstancedMaterialToEntity
遍历参数实体的子实体, 修改子实体的材质名称(也就是克隆原材质, 然后修改原材质的所有着色程序部分)
setMaterialName(buildInstancedMaterial(materialName))
函数 buildInstancedMaterial
调用 StringUtil::endsWith方法, 来判断参数是否以"/instanced"为结尾, 是的话, 表示该材质已经修改过, 无需再创建, 直接范围该材质字符串
后面的内容是克隆原材质, 然后修改材质中的着色语言部分, 注意, 如果原材质不存在, 则用 "Instancing" 材质
p->setVertexProgram("Instancing", false);
p->setShadowCasterVertexProgram("InstancingShadowCaster");
函数 createStaticGeom
1. 创建一个实体 ent
2. 创建一个静态几何体 new StaticGeometry
3. 设置尺寸 setRegionDimensions
4. addEntity添加实体, 设置位置
5. setCastShadows 设置投射阴影
6. build构建
7. 在renderStatic容器中保存该静态几何体
8. 销毁实体 ent
函数 createEntityGeom
主要是创建节点, 挂接实体, 设置节点位置
void destroyEntityGeom();
void destroyStaticGeom();
void destroyInstanceGeom();
void destroyCurrentGeomOpt();
各种哦国内清理函数
注意 destroyCurrentGeomOpt 还需要清除保存的位置容器vector - posMatrices.
函数 burnCPU
在这个函数里, 不断的循环直到特定时间
然后计算 在该函数内耗费的时间与当前距离上一次调用该函数结束的时间的百分比
该百分比为要显示的文本内容
函数 setObjectCount, setBurnedTime, changSelectedMesh, setCurrentGeometryOpt
监听器类的公有函数, 用于CEGUI界面调用这些函数修改一些值, 实现CEGUI与OGRE程序的互动
函数 mouseMoved, mousePressed, mouseReleased
重载这些函数, 注入CEGUI窗口中
函数 requestShutdown
设置变量 mRequestShutDown 为真, 结束程序
以下几个窗口函数, 可通过CEGUI窗口的root窗口订阅鼠标事件时, 挂接为其处理函数
函数 handleMouseMove
如果按下左键, 旋转相机
函数 handleMouseButtonUp
显示鼠标, 设置鼠标上次消失的位置
函数 handleMouseButtonDown
保存鼠标位置, 隐藏鼠标
函数 updateStats
更新一些窗口的变化
重要类和方法
Ogre
MeshManager 类
函数 createPlane
// 创建一个平面
参数:
name - 创建出来的平面mesh的名称
groupname - 分配给该mesh的组的名称
plane - Plane类对象, 表示该平面的方向和距离
width - 该平面在世界坐标系中的宽度
height - 该平面在世界坐标系中的高度
xsegments - 该平面在X轴方向的片段数
ysegments - 该平面在Y轴方向的片段数
normals - 如果为真, 则创建垂直于平面的法线
numTexCoordSets - 纹理坐标系的个数
uTile - 在u轴方向纹理应当重复的次数
vTile - 在v轴方向纹理应当重复的次数
upVector - 平面向上的向量
vertexBufferUsage - 用于创建的平面顶点缓存的标志
indexBufferUsage - 用于创建的平面索引缓存的标志
vertexShadowBuffer - 如果为真, 则在系统内存中创建关于阴影的顶点缓存, 允许你更有效的读取该数据
ndexShadowBuffer - 如果为真, 则在系统内存中创建关于阴影的索引缓存, 允许你更有效的读取该数据
ySegmentsToKeep - 从屋顶的顶点向下的片段数
InstancedGeometry 类
预先转换并批处理meshes, 以便有效的使用一个场景中的 Instanced几何体
GpuProgramManager::SyntaxCodes 类型 - std::set<Ogre::String>
使用 GpuProgramManager::getSingleton().getSupportedSyntax() 得到支持的句法
Timer 类
函数 getMicroseconds
表示得到自初始化或者重置以来过去的微秒数
InstancedGeometry 类
函数 setOrigin
设置该几何体的起点
备注:
这个方法允许你配置这个几何体的世界中心, 从而所有的Batchinstance围绕这个位置. 除非你有一个很大的世界, 否则你可能不需要将mess关联到该起点.
缺省创建可以拥有一个句柄, 控制一个1024 * mBatchInstanceDimensions的区域, 并当渲染的时候没有任何的内容. 缺省为Vector3(0, 0, 0);
StringUtil 类
函数 endsWith
用于判断字符串的尾部是否等于另一字符串