ogre Mesh的渲染流程

首先一个 Entity 对象必须 Attach 到一个 SceneNode
1.   创建一个 SceneNode
SceneManager::getRootSceneNode()  (在 SceneManager::init 时会创建一个 RootNode
à  SceneNode::createChildSceneNode()
à Node::createChild()
主要的操作在这个函数中完成,首先调用虚函数 SceneNode::createChildImpl (),此函数又会调用 OctreeSceneManager::createSceneNode (),此函数会 new 一个 SceneNode 的派生类对象,这里是 OctreeNode ,并加入到 SceneNodeList mSceneNodes 中;随后又进行了坐标变换;最后将此指针又加入到 ChildNodeMap mChildren 中,然后返回此指针;
2.   Entity Attach SceneNode SceneNode:: attachObject()
3.   渲染从 Root::startRendering() 函数开始,此函数启动一个循环,每次执行 Root::renderOneFrame ()
à Root::_updateAllRenderTargets
à RenderSystem::_updateAllRenderTargets()
à RenderWindow::update()
à D3D9RenderWindow::update(bool swap)
à RenderTarget::update()
à Viewport::update()
à Camera::_renderScene()
à  SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)
4.   绕了好大一圈,才来到了 SceneManager::_renderScene() ,此函数想必是渲染的主要操作所在;
5.  SceneManager:: _updateSceneGraph() root node 开始递归的调用了所有 scene node update ,主要是计算了 transform
6.   AutoParamDataSource 设置了一系列参数,这个类是用来为 gpu programs 提供一些参数的;
7.  SceneManager::prepareRenderQueue ()。这里有一个 Ogre 场景管理的概念 RenderQueue 。粗略的看,这个类主要是为了把 Objects 按照材质分组,它还将管理对象的渲染优先权;
8.  OctreeSceneManager::_findVisibleObjects ()
à  OctreeSceneManager::walkOctree
à  OctreeNode::_addToRenderQueue
如果想显示包裹盒的话,则会调用 ” sn->_addBoundingBoxToQueue(queue);”
可见这个操作利用 SceneManager 的空间管理算法来对所有的 SceneNode 进行了可见性判断,如果可能可见,则加入到 RenderQueue 中;
9.   在计算好了 RenderQueue 之后,开始调用 RenderSystem 的一系列函数,例如 _setProjectionMatrix 等等开始为真正的渲染操作做好准备;
10.              SceneManager::_renderVisibleObjects ,渲染操作就在这里了。
à SceneManager::renderVisibleObjectsDefaultSequence
à  SceneManager::_renderQueueGroupObjects
à  SceneManager::renderBasicQueueGroupObjects (此函数遍历 RenderQueueGroup 中的每个 RenderPriorityGroup ,然后先渲染 solids ,再渲染 transparents
à  SceneManager::SceneMgrQueuedRenderableVisitor::visit
11.               à  SceneManager::renderSingleObject ,此函数设置了灯光、 GPU programs ,然后使用一个 RenderOperation 对象来调用 D3D9RenderSystem::_render ,也就是真正的 Draw call RenderOperation 对象是由 SubEntity::getRenderOperation à  SubMesh::_getRenderOperation 来设置的,主要是 IndexData VertexData

这里有几个细节需要注意:
1.   SceneManager::renderObjects 函数中用到了一个 visitor 模式来访问 QueuedRenderableCollection (这个类的实例用来在 RenderPriorityGroup 中包括 solids transparents 等等)。
2.  Entity 是从 MoveableObject 派生的,而 SubEntity 才是从 Renderable 派生的;
3.   一个 SceneNode 可以 Attach 多个 Entity ;实际上 SceneNode 可以 Attach 任何的 MoveableObject
4.   前面只提到了 IndexData VertexData ,而对于渲染来说 Material 更是关注的焦点, Mesh 的材质是如何与 RenderSystem 交互的呢?
 
总结: SceneManager 进行可见性判断之后,形成一个 RenderQueue ,然后对于队列中的每个 Object 再使用 RenderOpertation RenderSystem 联系,来执行渲染操作。
总体感觉有些地方相当复杂,有些觉得比较罗索,例如通过 root 然后找到 RenderTarget 然后知道 ViewPort ,再找到 Camear ,最后才执行到 SceneManager 的渲染函数,为什么不把 ViewPort 做完 SceneManaer::_renderScene 的一个参数,交给上层来控制呢?毕竟多数程序要一个 RenderWindow ,一个 ViewPort 就够了。又比如 RenderQueue (见下图),不知道是不是因为要处理 Shadow 等才搞得这么复杂。
ogre Mesh的渲染流程
 
   对于 Objects 按照 Material 分组,然后对于每个 Group 再先显然 Solids 再渲染 transparents ,这种透明处理方式明显是不安全的,如果两个组中都有透明物体,那画面肯定会出问题的。

你可能感兴趣的:(sh)