Ogre渲染队列RenderQueue结构图
来源:互联网 发布:日本和韩国知乎 编辑:程序博客网 时间:2024/05/19 02:43
渲染队列RenderQueue(自CSDN博客http://blog.csdn.net/qq18052887/archive/2010/08/15/5812611.aspx) 1. RenderQueue的组成 RenderQueue由Ogre::RenderQueueGroup组成的,RenderQueue中有一个RenderQueueGroup的Map的数据成员: typedef std::map< RenderQueueGroupID, RenderQueueGroup * > RenderQueueGroupMap RenderQueueGroupMap mGroups 可见RenderQueueGroupMap 的key为RenderQueueGroupID,代表Objects的渲染先后顺序。RenderQueueGroupID是一个枚举量,根据场景内物体的渲染顺序由先及后定义,RenderQueueGroupID的定义如下 enum RenderQueueGroupID { RENDER_QUEUE_BACKGROUND = 0, RENDER_QUEUE_SKIES_EARLY = 5, RENDER_QUEUE_1 = 10, RENDER_QUEUE_2 = 20, RENDER_QUEUE_WORLD_GEOMETRY_1 = 25, RENDER_QUEUE_3 = 30, RENDER_QUEUE_4 = 40, RENDER_QUEUE_MAIN = 50, RENDER_QUEUE_6 = 60, RENDER_QUEUE_7 = 70, RENDER_QUEUE_WORLD_GEOMETRY_2 = 75, RENDER_QUEUE_8 = 80, RENDER_QUEUE_9 = 90, RENDER_QUEUE_SKIES_LATE = 95, RENDER_QUEUE_OVERLAY = 100, } RenderQueue通过成员函数addRenderable 添加物体到渲染队列中,在RenderQueue的 getQueueGroup成员负责RenderQueueGroup的查找创建。RenderQueueGroup的生命周期由RenderQueue来控制。 2. RenderQueueGroup的组成 RenderQueueGroup中有一个RenderPriorityGroup的Map的数据成员: typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap; PriorityMap mPriorityGroups; PriorityMap的key为一个ushort,它代表着RenderPriorityGroup渲染的优先级。对同一优先级的Objects,RenderQueueGroup会通过成员函数addRenderable 将它加入相同的RenderPriorityGroup中,RenderPriorityGroup的生命周期是由 RenderQueueGroup管理的。 3. RenderPriorityGroup的组成 RenderPriorityGroup中是存放需要渲染的Objects的最终场所。需要渲染的Objects——Renderable,RenderPriorityGroup组织将其组织为RenderableList,然后把RenderableList组织成SolidRenderablePassMap: typedef std::vector<Renderable*> RenderableList; typedef std::map<Pass*, RenderableList*, SolidQueueItemLess> SolidRenderablePassMap; SolidRenderablePassMap mSolidPasses; SolidRenderablePassMap mSolidPassesDiffuseSpecular; SolidRenderablePassMap mSolidPassesDecal; SolidRenderablePassMap mSolidPassesNoShadow; 综上所述,需渲染的物体分别经过RenderPriorityGroup、RenderQueueGroup分类后,由RenderQueue统一管理。 4. QueuedRenderableCollection RenderPriorityGroup有5个成员变量mSolidsBasicm、SolidsDiffuseSpecular、mSolidsDecal、mSolidsNoShadowReceive、mTransparents都是QueuedRenderableCollection, QueuedRenderableCollection是存储Renderable和Pass的最终场所。通过多种排序实现Renderable和Pass的有序化。排序包括小于排序、深度递减排序和基数排序。 typedef std::vector<RenderablePass> RenderablePassList; typedef std::vector<Renderable*> RenderableList; typedef std::map<Pass*, RenderableList*, PassGroupLess> PassGroupRenderableMap; PassGroupRenderableMap mGrouped; RenderablePassList mSortedDescending; mGrouped和mSortedDescending中存储的是Renderable和Pass。 QueuedRenderableCollection组织Renderable和Pass有三种,分别是按Pass分组、按与camera的距离升序和按与camera的距离减序。 enum OrganisationMode{ OM_PASS_GROUP = 1, OM_SORT_DESCENDING = 2, OM_SORT_ASCENDING = 6 }; 5.QueuedRenderableVisitor QueuedRenderableVisitor是按访问者模式设计的抽象接口。在QueuedRenderableCollection中有一个公用接口和三个内部接口如下: void acceptVisitor(QueuedRenderableVisitor* visitor, OrganisationMode om) const; void acceptVisitorGrouped(QueuedRenderableVisitor* visitor) const; void acceptVisitorDescending(QueuedRenderableVisitor* visitor) const; void acceptVisitorAscending(QueuedRenderableVisitor* visitor) const; acceptVisitor按OrganisationMode3种方式分别调用内部接口acceptVisitorGrouped、 acceptVisitorDescending和acceptVisitorAscending。 switch(om) { case OM_PASS_GROUP: acceptVisitorGrouped(visitor); break; case OM_SORT_DESCENDING: acceptVisitorDescending(visitor); break; case OM_SORT_ASCENDING: acceptVisitorAscending(visitor); break; } 而acceptVisitorGrouped、acceptVisitorDescending和acceptVisitorAscending。内部调用如下 void QueuedRenderableCollection::acceptVisitorGrouped(QueuedRenderableVisitor* visitor) const { RenderableList* rendList = ipass->second; RenderableList::const_iterator irend, irendend; irendend = rendList->end(); for (irend = rendList->begin(); irend != irendend; ++irend) { visitor->visit(*irend); } } 通过以上分析可以看到最终的渲染任务是交到QueuedRenderableVisitor手中。 而在SceneManager中有如下定义,具体实现了渲染任务。 class SceneMgrQueuedRenderableVisitor : public QueuedRenderableVisitor SceneMgrQueuedRenderableVisitor* mActiveQueuedRenderableVisitor; SceneMgrQueuedRenderableVisitor mDefaultQueuedRenderableVisitor; 6. RenderTarget RenderTarget用来接收渲染操作的结果,它可以是屏幕上的窗口、离屏面(如texture)等。FPS信息的统计也是由RenderTarget完成的。在RenderTarget每次更新完成后,将会更新统计信息(封装于FrameStats中)。 除了负责统计帧的信息外,RenderTarget还负责创建维护Viewport(视口): typedef std::map<int, Viewport*, std::less<int> > ViewportList; ViewportList mViewportList; Viewport* RenderTarget::addViewport(Camera* cam, int ZOrder, float left, float top , float width , float height) { ViewportList::iterator it = mViewportList.find(ZOrder); if (it != mViewportList.end()) { … } Viewport* vp = new Viewport(cam, this, left, top, width, height, ZOrder); mViewportList.insert(ViewportList::value_type(ZOrder, vp)); fireViewportAdded(vp); return vp; } 由上面的代码可以看出,每个Viewport都对应一个Camera和一个RenderTarget。当创建一个Viewport后,它会自动建立与Camera的联系。可以把Camera看作是图像的来源,而RenderTarget是图像渲染的目的地。一个Viewport只能对应一个Camera和一个RenderTarget,而一个Camera也只能对应一个Viewport,但RenderTarget却可以拥有几个Viewport。 7. 渲染过程 OGRE通过WinMain或main调用go再通过Root调用startRendering进行消息循环,然后调用renderOneFrame,通过RenderSystem的_updateAllRenderTargets方法,更新所有的RenderTarget。RenderTarget通过update方法更新与之关联的Viewport并产生FPS统计信息。而Viewport则调用与之关联的Camera的_renderScene方法进行渲染,Camera此时把“球”踢给SceneManager。进入SceneManager的renderScene成员函数中后,在经过计算后,把需要渲染的场景送给RenderSystem去做真正的渲染,此时我们可以看到熟悉的_breginFrame和_endFrame。 一直下去经过RenderQueue、RenderQueueGroup、RenderPriorityGroup、QueuedRenderableCollection再通过访问者到达QueuedRenderableVisitor的子类SceneMgrQueuedRenderableVisitor,最终又回到SceneManager,由SceneManager再到RenderSystem完成整个渲染过程。过程伪码如下所示: int WinMain or main(int argc, char **argv) { app.go(); } virtual void go(void) { Root->startRendering(); } void Root::startRendering(void) { renderOneFrame(); } bool Root::renderOneFrame(void) { _updateAllRenderTargets(); } void Root::_updateAllRenderTargets(void) { RenderSystem->_updateAllRenderTargets(); } void RenderSystem::_updateAllRenderTargets(void) { RenderTarget->update(); } void RenderTarget::update(void) { Viewport->update(); } void Viewport::update(void) { Camera->_renderScene(this, mShowOverlays); } void Camera::_renderScene(Viewport *vp, bool includeOverlays) { SceneManager->_renderScene(this, vp, includeOverlays); } void SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays) { RenderSystem->_beginFrame(); _renderVisibleObjects(); RenderSystem->_endFrame(); } void SceneManager::_renderVisibleObjects(void) { //如果有阴影 renderVisibleObjectsCustomSequence(); //否则 renderVisibleObjectsDefaultSequence(); } void SceneManager::renderVisibleObjectsDefaultSequence(void) { fireRenderQueueStarted(qId,mIlluminationStage) _renderQueueGroupObjects(pGroup, QueuedRenderableCollection::OM_PASS_GROUP); fireRenderQueueEnded(qId, mIlluminationStage) } void SceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup, OrganisationMode om) { renderBasicQueueGroupObjects(pGroup, om); } void SceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup, OrganisationMode om) { renderObjects(pPriorityGrp->getSolidsBasic(), om, true); } void SceneManager::renderObjects(const QueuedRenderableCollection& objs, …) { objs.acceptVisitor(mActiveQueuedRenderableVisitor, om); } void QueuedRenderableCollection::acceptVisitor(QueuedRenderableVisitor* visitor…) { switch(om){ case OM_PASS_GROUP: acceptVisitorGrouped(visitor); … } } void QueuedRenderableCollection::acceptVisitorGrouped(QueuedRenderableVisitor* visitor) { QueuedRenderableVisitor->visit(Renderable); } void SceneManager::SceneMgrQueuedRenderableVisitor::visit(const Renderable* r) { SceneManager->renderSingleObject(r, mUsedPass, autoLights, manualLightList); } void SceneManager::renderSingleObject(const Renderable* rend, const Pass* pass…) { RenderSystem->_render(RenderOperation); } 最终进入的RenderSystem的子类D3D9RenderSystem or GLRenderSystem。 void D3D9RenderSystem::_render(const RenderOperation& op) { mpD3DDevice->DrawIndexedPrimitive or mpD3DDevice->DrawPrimitive } void GLRenderSystem::_render(const RenderOperation& op) { glDrawElements or glDrawArrays } 8. RenderQueueListener class _OgreExport RenderQueueListener { public: virtual ~RenderQueueListener() {} virtual void renderQueueStarted(uint8 queueGroupId, const String& invocation, bool& skip) = 0; virtual void renderQueueEnded(uint8 queueGroupId, const String& invocation, bool& repeat) = 0; }; RenderQueueListener的作用就是在SceneManager开始渲染和结束渲染时改变render state和别的操作,比如检查本次RenderQueue是否skip,如果skip就直接break本次render。 在上面渲染过程中有如下: void SceneManager::renderVisibleObjectsDefaultSequence(void) { fireRenderQueueStarted(qId,mIlluminationStage) _renderQueueGroupObjects(pGroup, QueuedRenderableCollection::OM_PASS_GROUP); fireRenderQueueEnded(qId, mIlluminationStage) } fireRenderQueueStarted和fireRenderQueueEnded中遍列RenderQueueListener。 定义如下: typedef std::vector<RenderQueueListener*> RenderQueueListenerList; RenderQueueListenerList mRenderQueueListeners; bool SceneManager::fireRenderQueueStarted(uint8 id, const String& invocation) { RenderQueueListener->renderQueueStarted(id, invocation, skip); } bool SceneManager::fireRenderQueueEnded(uint8 id, const String& invocation) { RenderQueueListener->renderQueueEnded(id, invocation, repeat); } 9. SpecialCaseRenderQueue SenceManager中的RenderQueue包含一种特殊情况的渲染队列(Special Case Render Queue) enum SpecialCaseRenderQueueMode{ SCRQM_INCLUDE, // 只渲染Special Case SCRQM_EXCLUDE // 不渲染Special Case }; 通过setSpecialCaseRenderQueueMode可以设置。以下是跟Special Case Render Queue有关的变量和操作: typedef std::set<uint8> SpecialCaseRenderQueueList; SpecialCaseRenderQueueList mSpecialCaseQueueList; SpecialCaseRenderQueueMode mSpecialCaseQueueMode; virtual void addSpecialCaseRenderQueue(uint8 qid); virtual void removeSpecialCaseRenderQueue(uint8 qid); virtual void clearSpecialCaseRenderQueues(void); virtual void setSpecialCaseRenderQueueMode(SpecialCaseRenderQueueMode mode); virtual SpecialCaseRenderQueueMode getSpecialCaseRenderQueueMode(void); 这里面需要说明一下的是qid,qid是RenderQueueGroupID,RenderQueueGroupID的定义在上面已经提过。 总之,通过上面分析可以看出render queue是Renderable的集合。其实场景树和渲染队列都是对Renderable进行分类,只是分类的标准不同,场景树主要是从空间结构对Renderable进行分类,而渲染队列则是对Renderable从material以及blend上进行分类。
- Ogre渲染队列RenderQueue结构图
- Ogre渲染队列RenderQueue结构图
- cocos2dx源码分析:渲染队列RenderQueue
- 渲染队列---Ogre
- OGRE渲染队列分析总结
- Ogre 渲染队列(一)
- Ogre 渲染队列(二)
- 【Unity3D】【NGUI】3.0+版本,粒子在UI后面显示(RenderQueue 渲染队列先后顺序)
- Ogre如何将一个可渲染对象加进渲染队列
- 简要分析Ogre渲染队列的实现原理
- 简要分析Ogre渲染队列的实现原理(一)
- 简要分析Ogre渲染队列的实现原理
- 简要分析Ogre的渲染队列实现原理
- 【转】转载:简要分析Ogre渲染队列…
- 简要分析ogre渲染队列的实现原理(一)
- 简要分析OGRE渲染队列的实现原理(二)
- 简要分析Ogre渲染队列的实现原理(一)
- 简要分析Ogre的渲染队列实现原理(二)
- WinCE内嵌数据库使用---小问题
- perl常用的批量改名
- 也可以做好系统和应用维护管理
- 使用行为树(Behavior Tree)实现网游奖励掉落系统
- 用Zookeeper实现数据库去中心化以及读写分离设计
- Ogre渲染队列RenderQueue结构图
- 超过了最大请求长度
- 常用js验证
- 在Android手机上实现阅读器的翻页效果
- 史上最牛的夫妻生活协议
- 来谈谈SQL数据库中"简单的"SELECT TOP—可能有你从未注意到的细节
- 投标服务和资料上传,文档管理的东西
- PackageManager 与 ActivityManager
- 如何为datagridview加上序号