您的位置:首页 > 其它

OGRE mesh的渲染流程

2015-10-18 15:59 267 查看
首先一个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等才搞得这么复杂。



对于Objects按照Material分组,然后对于每个Group再先显然Solids再渲染transparents,这种透明处理方式明显是不安全的,如果两个组中都有透明物体,那画面肯定会出问题的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: