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 更新当前RenderTarget的当前Viewport
        1. RenderTarget::fireViewportPreUpdate(RenderTargetListener::preViewportUpdate) 可以针对Viewport修改
        2. Viewport::update->Camera::_renderScene 转交给Camera
          1. Camera::Listener::cameraPreRenderScene 可以针对当前Camera修改
          2. SceneManger::_renderScene 场景接管渲染
            1. SceneManger::_updateSceneGraph 更新场景中所有节点
              1. SceneManger::firePreUpdateSceneGraph(SceneManager::Listener::preUpdateSceneGraph) 当前场景与摄像机
              2. Node::processQueuedUpdate 标记所有需要更新的节点
              3. RootSceneNode::_update(true,false) 更新所有需要更新的节点 递归RootSceneNode
              4. SceneManger::firePostUpdateSceneGraph(SceneManager::Listener::postUpdateSceneGraph) 节点更新完后
            2. SceneManager::setViewport 设置当前viewport
              1. RenderSystem::_setViewport
                1. RenderSystem::_setRenderTarget (设定渲染系统的RenderTarget)
              2. MaterialManager::setActiveScheme 把当前viewport方案给MaterialManager知道
            3. SceneManger::firePreFindVisibleObjects(SceneManager::Listener::preFindVisibleObjects) 在查找所有模型可见前
            4. SceneManger::_findVisibleObjects(父节点,第一次为根节点) 
              1. SceneNode::_findVisibleObjects 开始查找当前节点下模型
              2. RenderQueue::processVisibleObject 查找模型MovableObject是否在当前摄像机下可见
              3. MovableObject::_notifyCurrentCamera 通知MovableObject当前模型机在查找
              4. Renderable::Visitor::visitor 当前MovableObject关联的Renderable的访问者执行
              5. MovableObject::_updateRenderQueue 当前MovableObject关联的Renderable添加到渲染通道
              6. RenderQueue::addRenderable 添加Renderable,RenderQueue里开始根据RenderQueueGroupID开始分组成RenderQueueGroup
              7. Renderable::getTechnique 添加到RenderQueueGroup时要找到对应技术(如果没找到当前方案,执行下面二句)
              8. MaterialManager:: _arbitrateMissingTechniqueForActiveScheme 找所有的MaterialManager::Listener
              9. MaterialManager::Listener::handleSchemeNotFound 当前材质,Renderable,方案
              10. QueuedRenderableCollection::addRenderable(Pass,Renderable) RenderQueueGroup根据优先级分成RenderPriorityGroup,根据投射阴影,接收阴影,透明等继续分组,添加技术下各个Pass到QueuedRenderableCollection
              11. SceneNode:: _findVisibleObjects (子节点) 递归子节点
            5. SceneManger::firePostFindVisibleObjects(SceneManager::Listener::postFindVisibleObjects) 结束查找所有节点下模型可见
            6. RenderSystem::_beginFrame RenderSystem开始渲染准备
            7. SceneManager::_renderVisibleObjects SceneManager开始渲染可见物体
              1. SceneManager::firePreRenderQueues(RenderQueueListener::preRenderQueues) 通知用户开始渲染通道里的所有通道组
              2. SceneManager::fireRenderQueueStarted(RenderQueueListener::renderQueueStarted) 通知用户开始渲染当前通道组
                1. SceneMangger::renderObjects ->QueuedRenderableCollection::acceptVisitorGrouped 渲染当前通道组各优先级通道
                  1. SceneManager::SceneMgrQueuedRenderableVisitor::visit 访问当前QueuedRenderableCollection下的各个RenderablePass
                  2. SceneManager::renderSingleObject 渲染当前的Renderable与pass
                    1. RenderSystem::fireRenderSingleObject(RenderObjectListener::notifyRenderSingleObject) 通知用户
                    2. SceneManager::updateGpuProgramParameters 更新当前pass下着色器代码参数
                    3. Renderable::getRenderOperation 获取当前Renderable的缓冲区对象数据
                    4. Renderable::preRender 开始渲染当前Renderable
                    5. RenderSystem::_render 交给RenderSystem渲染了
                    6. Renderable::postRender 结束渲染当前Renderable
              3. SceneManager::fireRenderQueueEnded(RenderQueueListener::renderQueueEnded) 通知用户结束了当前通道组
              4. SceneManager::firePostRenderQueues(RenderQueueListener::postRenderQueues) 通知用户结束了所有通道组
            8. RenderSystem::_endFrame RenderSystem结束渲染
          3. Camera::Listener::cameraPostRenderScene 通知用户当前桢摄像机结束渲染
        3. RenderTarget::fireViewportPostUpdate(RenderTargetListener::postViewportUpdate) 当前桢视图结束渲染
      4. RenderTarget::_endUpdate(RenderTargetListener::postRenderTargetUpdate) 当前桢RenderTarget结束渲染
    2. Root::_fireFrameRenderingQueued(FrameListener:: frameRenderingQueued) 当前桢结束渲染
    3. RenderSystem::_swapAllRenderTargetBuffers 交换所有RenderTarget的桢缓冲
  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.

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

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

    前言 学习不论什么一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列尽管涉及的是socket相关的知识,但学习之前,更 ...

  2. Android手势监听类GestureDetector的使用

    在使用自定义视图的时候,对触屏事件的处理是比不可少的,有能力的可以自己写代码处理,这样更加的灵活.如果不想这么麻烦,Android提供了一个手势监听类GestureDetector,可以供我们使用.G ...

  3. 基于Java+Selenium的WebUI自动化测试框架(四)-----设置监听类

    基于上一篇的内容,这里我们开始写监听类Listener.我这里写监听类的思路是,继承TestListenerAdapter这个类,然后对其中的方法进行重写.网上也有很多资料,建议先学习一下,然后写出来 ...

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

    Session监听类HttpSessionListener介绍及在listener里取得request servlet-api.jar中提供了监听类HttpSessionListener,主要方法有两 ...

  5. Spring事件监听ApplicationListener源码流程分析

    spring的事件机制是基于观察者设计模式的,ApplicationListener#onApplicationEvent(Event)方法,用于对事件的处理 .在容器初始化的时候执行注册到容器中的L ...

  6. java中的四种监听类用法

    在此列举四种方法: 自身类实现ActionListener接口,作为事件监听器 通过匿名类处理 通过内部类处理 通过外部类处理 下面依次介绍: 第一种:自身类实现ActionListener接口,作为 ...

  7. kafka监听类

    package com.datad.dream.service; import com.alibaba.fastjson.JSON; import com.datad.dream.dao.KafkaI ...

  8. 【Android】关于连续多次点击控件的控制方案(新建监听类)

    参考:防止Android过快点击造成多次事件的三种方法_胖胖的博客-CSDN博客 实现逻辑很简单: 设置限定时间 在用户点击时开始计时 若计时未超过限定时间,则不允许触发点击事件 因还未学习过Rxja ...

  9. 监听器以及在监听类里面获得bean的方法

    1实现HttpSessionListener和ServletContextListener,2个接口 2然后在contextInitialized初始化方法里面: ServletContext app ...

随机推荐

  1. Quantum Computation and Quantum Information

    https://www.amazon.com/Quantum-Computation-Information-10th-Anniversary/dp/1107002176/ref=asap_bc?ie ...

  2. 实例分析JVM安全体系:双亲委派、命名空间、保护域、策略

    在了解双亲委派模型之前,先了解一下类加载器的概念: 类加载器的作用就是将真实的class文件根据位置将该Java类的字节码装入内存,并生成对应的Class对象.用户可以通过继承ClassLoader和 ...

  3. javascript基础拾遗(二)

    1.对象定义 定义属性 var language = { name:'javascript', score:9.0 }; console.log(language.name) console.log( ...

  4. lua面向对象编程之点号与冒号的差异详细比较

    首先,先来一段在lua创建一个类与对象的代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Class = {} Class.__index = Cl ...

  5. Android中XML文件的序列化生成与解析

    xml文件是非常常用的,在android中json和xml是非常常用的两种封装数据的形式,从服务器中获取数据也经常是这两种形式的,所以学会生成和解析xml和json是非常有用的,json相对来说是比较 ...

  6. Python字符串、时间戳、datetime时间相关转换

    总结的时间转换函数 # datetime时间转为字符串 def Changestr(datetime1): str1 = datetime1.strftime('%Y-%m-%d %H:%M:%S') ...

  7. iOS同步后couldn't load project

    使用Cornerstone同步后,有时候出现下面的现象,点击运行,提示“couldn't load project” 解决方法: 1.鼠标右键点击工程“XX_Internal”,选择“show in ...

  8. 慢慢来,比较快。四年Android,共勉。

    四年阿,我特么以为我才17岁,不想已经27了,操蛋阿.加班熬夜,我的黑眼圈,黑头泛滥.如果木有自拍神器,我是决计不会爆照的!! 第一年,学了七天android找上了第一份工作,后来接了个外包,是做智能 ...

  9. 【WPF】树形结构TreeView的用法(MVVM)

    TreeView控件的用法还是有蛮多坑点的,最好记录一下. 参考项目: https://www.codeproject.com/Articles/26288/Simplifying-the-WPF-T ...

  10. Linux 系统内核空间与用户空间通信的实现与分析-NETLINK (转载)

    Linux中的进程间通信机制源自于Unix平台上的进程通信机制.Unix的两大分支AT&T Unix和BSD Unix在进程通信实现机制上的各有所不同,前者形成了运行在单个计算机上的Syste ...