Ogre 监听类与渲染流程

  Ogre中有许多监听类,我们可以简单理解成C#中的事件,这些类作用都不小,说大点可能改变流程,说小点修改参数等,下面列举一些常用的监听类.

  • FrameListener:由Ogre中的Root负责维护,主要针对所有RenderTarget监听

    • frameStarted:在一桢开始的时候,所有RenderTarget更新之前.
    • frameRenderingQueued:所有RenderTarget更新之后,但是还没交换缓冲区.(意思屏幕上显示没变)
    • frameEnded:所有RenderTarget更新并交换了缓冲区数据.
  • RenderTargetListener:由RenderTarget负责维护,主要针对当前RenderTarget监听
    • preRenderTargetUpdate:在Viewport开始更新之前,可以用来根据不同的RenderTarget改变Renderable的可见性,摄像机位置.或是捕获当前RenderTarget做别的处理.
    • postRenderTargetUpdate:在Viewport更新之后,一般用来还原在preRenderTargetUpdate做的处理.
    • preViewportUpdate:在上面的preRenderTargetUpdate之后,SceneManger开始渲染之前.可以针对viewport修改.
    • postViewportUpdate:在postRenderTargetUpdate之前,可以还原preViewportUpdate所做更改.
  • SceneManager::Listener:由SceneManager负责维护,针对场景节点更新,场景模型可见,阴影
    • preUpdateSceneGraph:在上面viewport开始更新后,SceneManager开始更新结果,由RootSceneNode递归更新.
    • postUpdateSceneGraph:如上所有节点更新完后.在去查找模型可见之前.
    • preFindVisibleObjects:更新节点后,开始查找Renderable可见之前.
    • postFindVisibleObjects:在所有可见的Renderable添加见渲染通道之后.
    • shadowTexturesUpdated:以及下面的几个方法主要是关于阴影的更新,这里不细说,以后细说阴影部分.
  • MaterialManager::Listener:由MaterialManager负责维护,能针对Viewport提供多方案.
    • handleSchemeNotFound:在查找所有可见的Renderable中,也就是添加在渲染通道的时候,查找对应Renderable的材质,是否和当前的方案一致,如不一致发生.
  • RenderQueueListener:由SceneManager负责维护,提供针对每组渲染通道设置.
    • preRenderQueues:开始渲染通道里的Renderable.所有通道组开始渲染之前.
    • postRenderQueues:所有渲染通道里的Renderable都渲染之后.
    • renderQueueStarted:同组的渲染通道开始渲染.preRenderQueues有多组渲染通道,在之后针对每组渲染.
    • renderQueueEnded:当前组的渲染通道渲染完后.
  • RenderObjectListener:由SceneManager负责维护,提供渲染时当前Renderable与Pass.
    • notifyRenderSingleObject:,在进入通道后,在渲染Renderable之前.其中RTSS就用来更新当前着色器参数.
  • CompositorInstance::Listener:由CompositorInstance负责维护,主要用于修改当前合成器的着色器参数.
    • notifyMaterialSetup:在RenderSystemOperation刚创建时,一般用于修改不变的着色器参数.
    • notifyMaterialRender:RenderSystemOperation每次更新调用,一般用来每桢要更新参数.
    • createResources:在createResources(创建当前CompositorInstance中的RenderTexture)后.
  • Viewport::Listener:由Viewport负责维护,主要检查当前viewport一些变化.
    • viewportCameraChanged:当前Viewport上摄像机变化后.
    • viewportDimensionsChanged:当前Viewport尺寸变化.
    • viewportDestroyed:当前Viewport析构时发生.

  如上这些是一些基本的监听类,还有一些没有列举出来.上面虽然大致说了那些监听事件在那调用,但是大家肯定也感觉不清晰,如下结合渲染流程来说,大家就会有个比较清楚的认识.

  如下是正常的渲染流程,大致说下主要过程,Root调用srartRendering开始渲染,每桢更新,在每桢中查找当前所有的RenderTarget,更新当前RenderTarget,然后交给viewport,camera到SceneManager,场景首先更新根节点下所有节点位置, 更新参数mAutoParamDataSource一部分已知参数,然后检查所有节点上的MovableObject是否可见,如果可见,把MovableObject对应的Renderable和pass根据渲染等级加入渲染通道组.(说下渲染等级RenderQueueGroupID,一般是从0到105,0是背景,100是UI,就是说RenderQueueGroupID越大,越在上面显示.)然后由渲染等级由低到高开始渲染通道内的Renderable,然后结束本桢.如下是一些主要的渲染过程.

  1. Root::startRendering->Root::renderOneFrame
  2. Root::_fireFrameStarted(FrameListener::frameStarted)
  3. Root::_updateAllRenderTargets 开始更新所有RenderTarget
    1. RenderSystem::_updateAllRenderTargets

      1. RenderTarget::update->RenderTarget::updateImpl 更新当前的RenderTarget
      2. RenderTarget::_beginUpdate(RenderTargetListener::preRenderTargetUpdate)
      3. RenderTarget::_updateViewport 
        1. RenderTarget::fireViewportPreUpdate(RenderTargetListener::preViewportUpdate)
        2. Viewport::update->Camera::_renderScene
          1. Camera::Listener::cameraPreRenderScene
          2. SceneManger::_renderScene
            1. SceneManger::_updateSceneGraph

              1. SceneManger::firePreUpdateSceneGraph(SceneManager::Listener::preUpdateSceneGraph)
              2. Node::processQueuedUpdate
              3. RootSceneNode::_update(true,false)
              4. SceneManger::firePostUpdateSceneGraph(SceneManager::Listener::postUpdateSceneGraph)
            2. SceneManager::setViewport
              1. RenderSystem::_setViewport

                1. RenderSystem::_setRenderTarget (设定渲染的RenderTarget)
              2. MaterialManager::setActiveScheme
            3. SceneManger::firePreFindVisibleObjects(SceneManager::Listener::preFindVisibleObjects)
            4. SceneManger::_findVisibleObjects(父节点,第一次为根节点)
              1. SceneNode::_findVisibleObjects
              2. RenderQueue::processVisibleObject(MovableObject)
              3. MovableObject::_notifyCurrentCamera
              4. Renderable::Visitor::visitor
              5. MovableObject::_updateRenderQueue
              6. RenderQueue::addRenderable
              7. Renderable::getTechnique(如果没找到当前方案,执行下面二句)
              8. MaterialManager:: _arbitrateMissingTechniqueForActiveScheme
              9. MaterialManager::Listener::handleSchemeNotFound
              10. QueuedRenderableCollection::addRenderable(Pass,Renderable)
              11. SceneNode:: _findVisibleObjects (子节点)
            5. SceneManger::firePostFindVisibleObjects(SceneManager::Listener::postFindVisibleObjects)
            6. RenderSystem::_beginFrame
            7. SceneManager::_renderVisibleObjects
              1. SceneManager::firePreRenderQueues(RenderQueueListener::preRenderQueues)
              2. SceneManager::fireRenderQueueStarted(RenderQueueListener::renderQueueStarted)
                1. SceneMangger::renderObjects ->QueuedRenderableCollection::acceptVisitorGrouped

                  1. SceneManager::SceneMgrQueuedRenderableVisitor::visit
                  2. SceneManager::renderSingleObject
                    1. RenderSystem::fireRenderSingleObject(RenderObjectListener::notifyRenderSingleObject)
                    2. SceneManager::updateGpuProgramParameters
                    3. Renderable::getRenderOperation
                    4. Renderable::preRender
                    5. RenderSystem::_render
                    6. Renderable::postRender
              3. SceneManager::fireRenderQueueEnded(RenderQueueListener::renderQueueEnded)
              4. SceneManager::firePostRenderQueues(RenderQueueListener::postRenderQueues)
            8. RenderSystem::_endFrame
          3. Camera::Listener::cameraPostRenderScene
        3. RenderTarget::fireViewportPostUpdate(RenderTargetListener::postViewportUpdate)
      4. RenderTarget::_endUpdate(RenderTargetListener::postRenderTargetUpdate)
    2. Root::_fireFrameRenderingQueued(FrameListener:: frameRenderingQueued)
    3. RenderSystem::_swapAllRenderTargetBuffers
  4. Root::_fireFrameEnded(FrameListener:: frameEnded)

  如果Ogre启用Compositor后,有些位置需要改变了,前篇Ogre Compositor解析里有简单介绍过CompositorChain实现了接口RenderTargetListener与Viewport::Listener,那么在上面3.1.2 RenderTarget::_beginUpdate中就捕捉到当前的RenderTarget,并且调用CompositorChain的compile,生成当前TargetOperation列表,RenderSystemOperation列表,在TargetOperation的RenderTarget更新时,指定对应的TargetOperation到RenderQueueListener中,这样在渲染通道时,执行当前TargetOperation下的所有RenderSystemOperation,然后开始渲染.

  1. RenderTarget::_beginUpdate(RenderTargetListener::preRenderTargetUpdate)

    1. CompositorChain::_compile

      1. CompositorChain::_complieTargetOperations

        1. CompositorChain::_complieTargetOperations (compiledState收集TargetOperation)
        2. CompositorChain::collectPasses(queueRenderSystemOp收集RenderSystemOperation)
          1. new RenderSystemOperation(根据CompositionTargetPass的type传入生成不同对象)
          2. CompositorInstance::_fireNotifyMaterialSetup(CompositorInstance::Listener::notifyMaterialSetup)
    2. TargetOperation->RenderTarget::update(一个CompositorChain里有多个TargetOperation)
      1. CompositorChain::preTargetOperation(指定当前TargetOperation, RenderSystemOperation到CompositorChain::RQListener)
      2. 同上面流程RenderTarget::update 到SceneManager::_renderVisibleObjects
      3. SceneManager::firePreRenderQueues(RenderQueueListener::preRenderQueues)
      4. SceneManager::fireRenderQueueStarted(RenderQueueListener::renderQueueStarted)
        1. CompositorChain::RQListener::flushUpTo(执行所有RenderSystemOperation)

          1. RenderSystemOperation::execute

            1. CompositorInstance:: _fireNotifyMaterialRender(CompositorInstance::Listener:: notifyMaterialRender)
      5. 检查skipThisQueue == true -> 跳过本级别(同RenderQueueGroupID)的SceneMangger::renderObjects,否则同原过程一样.
      6. SceneManager::firePostRenderQueues(RenderQueueListener::postRenderQueues)
    3. TargetOperation->RenderTarget::swapBuffers-> (如果选用RTT用FBO)GLFBORenderTexture::swapBuffers
  2. RenderTarget::_endUpdate(RenderTargetListener::postRenderTargetUpdate)

  以上渲染过程都只是一般情况下的,不是固定的,我们本身就可以修改其中一些过程,还有用户可以自己手动渲染Renderable,这些都会造成原来渲染流程变化.

  本文比较简单,但是相关流程是整个Ogre的核心,掌握上面的流程与监听事件,我们才能更好的使用Ogre.

时间: 2024-10-16 05:03:24

Ogre 监听类与渲染流程的相关文章

[Java聊天室server]实战之二 监听类

前言 学习不论什么一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列尽管涉及的是socket相关的知识,但学习之前,更想和广大程序猿分享的是一种心境:学习是一个循序渐进的过程,心态应该随时调节,保持戒骄戒躁的状态.比方近期在看网易公开课MIT<算法导论>,老师提到,学习算法之前要计算机数学+离散数学+概率论等课程的知识,所以一直学不好算法的程序猿最好还是从基础入手,这都是中国式教育惹的祸啊!(此处省略一万字...

赵雅智_android实例_当监听类有数据更新时下拉刷新

之前两篇文章分别介绍了OnScrollListener的实现和ContentProvider监听数据的变化,下面我们就结合者两个知识点实现一个小项目 项目需求 使用当ContentProvider监听类有数据更新时,在当前界面进行提示,并用OnScrollListener实现下拉刷新 实现效果 通过ContentProvider显示数据在界面 当监听类发生变化时 下拉刷新后显示数据 实现步骤 android_sqlite项目 定义操作标识 匹配结果码 继承ContentProvider类重写方法

Session监听类HttpSessionListener介绍及在listener里取得request

servlet-api.jar中提供了监听类HttpSessionListener,主要方法有两个,sessionCreated.sessionDestroyed,根据方法名就能明白是监听session的创建和销毁. 首先不可避免的要在sessionCreated方法中想要取得request对象(进而取得用户ip,浏览器等属性),但是HttpSessionEvent显然直接取不到request对象. 研究了下,发现spring(主要是context jar包)提供了监听类:RequestCont

Android手势监听类GestureDetector的使用

在使用自定义视图的时候,对触屏事件的处理是比不可少的,有能力的可以自己写代码处理,这样更加的灵活.如果不想这么麻烦,Android提供了一个手势监听类GestureDetector,可以供我们使用.GestureDetector使用很方便,提供了单击,双击,长按等操作的处理,但是一般的定义界面都比较复杂,还用很多需要注意的地方,在这儿总结一下GestureDetector的使用. 首先新建一个空白的工程,主界面的layout中只需要添加一个按钮就行 <RelativeLayout xmlns:a

[Java聊天室服务器]实战之二 监听类

前言 学习任何一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列虽然涉及的是socket相关的知识,但学习之前,更想和广大程序员分享的是一种心境:学习是一个循序渐进的过程,心态应该随时调节,保持戒骄戒躁的状态.比如最近在看网易公开课MIT<算法导论>,老师提到,学习算法之前要计算机数学+离散数学+概率论等课程的知识,所以一直学不好算法的程序员不妨从基础入手,这都是中国式教育惹的祸啊!(此处省略一万字......)

java中的四种监听类用法

在此列举四种方法: 自身类实现ActionListener接口,作为事件监听器 通过匿名类处理 通过内部类处理 通过外部类处理 下面依次介绍: 第一种:自身类实现ActionListener接口,作为事件监听器. 这种方法是最基本的,也是初学者经常使用的,我当初即是如此. import java.awt.Color; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent;

移动端 input输入实时监听查询数据渲染

目前有一个需求,用户每输入内容就查找相应的 效果图 遇到的问题 1:每输入一个字母就进行查找,后台压力太大,重复渲染 解决:加入setTimeout   确保输入一定内容后在进行查询渲染 ,注意清除延迟 var time; $('#bname').keyup(function () { time=setTimeout(function () { $.ajax({ url: "/sign", type: "post", data: {bname: $("#b

Springboot中的事件监听类

SpringBoot启动的时候会调用方法SpringApplicationRunListener#contextLoaded,它包含的事件类如下: EventPublishingRunListener 和 自定义的 SpringApplicationRunListener EventPublishingRunListener 发布 ApplicationPreparedEvent 事件 ConfigFileApplicationListener 监听 ApplicationEvent 事件 处理

按键监听类KeyListener及适配器改良方案

导包导的恶心,真是马上要对notepad累觉不爱了,好在顺利导完.. 监听按键信息 //source code import java.awt.Color ; import java.awt.Font ; import java.awt.GridLayout ; import java.awt.event.ActionEvent ; import java.awt.event.ActionListener ; import java.awt.event.WindowListener ; impo