关于Demo_Compositor 例子的分析

时间:2020-12-15 16:50:36
 通过对本例的学习, 初步了解了查看一个比较大的程序的方法。 另外学习了Ogre关于CEGUI的列表框一些用法, 以及如何添加合成器的内容。
本例最核心的方法是 用CompositorManager的方法addCompositor, setCompositorEnabled来实现脚本的添加

主要使用的类是 CompositorDemo, CompositorDemo_FrameListener, ItemSelectorViewManager, ItemSelectorInterface
CompositorDemo类实现了框架的架构, 创建场景
CompositorDemo_FrameListener 实现了每帧改变的内容, 并实现了对CEGUI界面的初始化, 如列表选项的添加
ItemSelectorViewManager 用于控制列表选项的添加, 并给每个选项增加事件处理函数
ItemSelectorInterface 是帧监听器和ItemSelectorViewManager之间的接口, 便于在ItemSelectorViewManager理设置的选项处理函数中实现在帧监听器中开启和关闭一些合成器的功能。

1. 两句代码就可以加载CEGUI的界面
    mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr);
    mGUISystem = new CEGUI::System(mGUIRenderer, (CEGUI::ResourceProvider *)0, (CEGUI::XMLParser*)0,
        (CEGUI::ScriptModule*)0, (CEGUI::utf8*)"CompositorDemoCegui.config");
    
    通过CompositorDemoCegui.config文件进行一些配置, 为XML格式, 设置scheme, layout, DefaultFont
    layout为组件的排列, 有组建名称等内容
   
    以下代码为设置缺省鼠标样式的
    CEGUI::System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow");
   
2. OgreCEGUIRenderer.h是Ogre包装了CEGUI一些API的类的头文件
    其中构造函数可以直接创建CEGUI的渲染器
    OgreCEGUIRenderer(Ogre::RenderWindow* window,
                        Ogre::uint8 queue_id,
                        bool post_queue,
                        uint max_quads,
                        Ogre::SceneManager* scene_manager);
    参数:
    window: 指向Ogre::RenderWindow对象的指针
    queue_id: 用于指定在Ogre的渲染结果中的次序
    post_queue: true 表示在渲染队列queue_id之后渲染, false表示在之前
    max_quads: 以不用的, 设置为0
    scene_manager: 指向Ogre::SceneManager对象
   
3. Ogre::MovableObject::setDefaultVisibilityFlags(0x00000001);
    设置所有的可移动对象的可见标志, 具体用法还需研究
4. tudorhouse.mesh 为房屋背景 mesh
5. createScene使用的三个重要函数 createTextures, connectEventHandlers, createEffects
    其中 createEffects 可以查看一下关于 在代码里编写合成器的例子
    createTextures 则是关于手工创建纹理的例子
    connectEventHandlers 则是关于CEGUI组件增加事件处理函数的代码
    createTextures
        创建手工纹理 HalftoneVolume
        得到该纹理的像素硬件缓存
        锁定该硬件缓存
            得到当前的锁定区域
            根据区域得到数据指针
            得到区域的宽高深
                设置纹理数据。 这似乎是一个立方体纹理, 某一部分的纹理数据为0xFF, 另一部分为0x00
        再创建一个手工纹理 DitherTex, 大小为视图大小, 这是一个2D纹理
        该手工纹理的数据为随机值
    connectEventHandlers()
        给ExitDemoBtn按钮定制鼠标点击处理函数 CompositorDemo::handleQuit
        handleQuit
            调用根节点的queueEndRendering()函数, 退出程序
   
    createEffects(void)        // 创建了两个合成器 Motion Blur 和 Heat Vision
        创建合成器“Motion Blur”, 资源为缺省资源组
            合成器技术
                纹理定义 scene
                    对该定义进行一些设置, 格式列表增加PF_R8G8B8
                纹理定义 sum
                    对该定义进行一些设置, 格式列表增加PF_R8G8B8
                纹理定义 temp
                    对该定义进行一些设置, 格式列表增加PF_R8G8B8
                创建合成器目标通路
                    设置输入模式为 IM_PREVIOUS
                    输出名称为scene
                创建合成器目标通路
                    设置输入模式为 IM_PREVIOUS
                    输出名称为sum
                    setOnlyInitial函数设置为真
                创建合成器目标通路
                    设置输入模式为 IM_NONE
                    输出名称为temp
                    该目标通路再创建通路
                        类型为 PT_RENDERQUAD
                        材质为 Ogre/Compositor/Combine
                        设置输入为 “scene”和 “sum”
                创建合成器目标通路
                    设置输入模式为 IM_NONE
                    输出名称为sum
                    该目标通路再创建通路
                        类型为 PT_RENDERQUAD
                        材质为 Ogre/Compositor/Copyback
                        设置输入为 "temp"
                创建合成器目标通路
                    设置输入模式为 IM_NONE
                    该目标通路再创建通路
                        类型为 PT_RENDERQUAD
                        材质为 Ogre/Compositor/MotionBlur
                        设置输入为 "sum"
       
        创建合成器“Heat Vision”
            合成器技术
                纹理定义 scene
                    设置宽高256, 格式列表增加PF_R8G8B8
                纹理定义 temp
                    设置宽高256, 格式列表增加PF_R8G8B8
                创建合成器目标通路
                    设置输入模式为 IM_PREVIOUS
                    输出名称为 scene
                创建合成器目标通路
                    设置输入模式为 IM_NONE
                    输出名称为 temp
                    创建通路
                        设置类型为 PT_RENDERQUAD
                        设置标记号 0xDEADBABE
                        设置材质为 Fury/HeatVision/LightToHeat
                        设置输入为 "scene"
                创建合成器目标通路
                    设置输入模式为 IM_NONE
                    创建通路
                        设置类型为 PT_RENDERQUAD
                        设置材质为 Fury/HeatVision/Blur
                        设置输入为 "temp"
                       
6. CompositorDemo_FrameListener 类
    initDebugRTTWindow函数用于给CEGUI窗口的Listbox添加事件和图像集
    connectEventHandlers 给CEGUI窗口增加事件处理函数, 这些事件处理函数也可以影响到Ogre帧监听器用到的一些变量
    registerCompositors函数
        得到当前渲染窗口的视口
        创建ItemSelectorViewManager对象
        设置交互的接口(ItemSelectorInterface派生类, 当前对象)
        创建CompositorManager::ResourceMapIterator对象
        遍历该迭代器
            得到下一个资源
            得到资源名称
            判断是否Ogre/Scene, 是的话, 下一个循环
            列表框增加一个选项
            HDR合成器必须位于第一个位置
            调用合成器管理器的addCompositor函数添加合成器
            初始的时候所有合成器无效
            合成器名称是否为 Heat Vision , 是的话, 增加监听器
            合成器名称是否为 HDR, 是的话,增加监听器, 调用监听器的notifyViewportSize和notifyCompositor函数
            合成器名称是否为 Gaussian Blur, 是的话,增加监听器, 调用监听器的notifyViewportSize
       
       
7. CEGUI要接收事件, 就必须调用inject*函数, 所以所有的mouse和key函数都要用inject向CEGUI注册信息。
    这里的鼠标和按键利用CEGUI的处理函数更新帧监听器用到的变量。
   
8. 在handle*系列函数中
    当鼠标移动时, 判断左右键的状态, 根据状态移动或者旋转, 注意鼠标可被隐藏
    当鼠标弹起时, 会显示鼠标, 更新状态
    当鼠标按下时, 注意设置上一个位置是否变化, 可以在鼠标移动时, 鼠标位置不变
   
9. ItemSelectorViewManager 类的分析
    构造函数
        根据父窗口名称从CEGUI中得到CEGUI窗口
        创建一个滚动面板, 类型为TaharezLook/ScrollablePane, 名称为MainScrollPane
            滚动面板 水平对齐 CEGUI::HA_CENTRE
            设置大小
        父窗口则加上该滚动面板
        设置该面板的位置(应该是相对于父窗口)
       
    addItemSelector函数
        增加一个结构体ItemSelector对象(在该类里创建的结构体)
        创建一个CEGUI::Checkbox对象
        设置ID, 大小, 属性, 订阅事件处理函数, 设置位置
   
    handleCheckStateChanged函数
        用于处理选择框变化
        如果存在与OGRE交互的接口对象(ItemSelectorInterface派生类)
            得到该checkbox
            调用Ogre监听器相应接口的函数, 在监听类对象中启动或者关闭该选项的合成器。
            设置checkbox的NormalTextColour属性
   
    setItemSelectorController
        设置与OGRE交互的接口对象(ItemSelectorInterface派生类)
       
    struct ItemSelector
        一个保存选项信息的结构体
        其成员CheckBoxWidget为CEGUI::Checkbox指针
       
9. ItemSelectorInterface 类
    这是一个纯虚函数, ItemSelectorInterface 只有一个构造函数和itemStateChanged函数(虚函数)
    在本例的派生类中;
        根据参数调用CompositorManager的setCompositorEnabled函数实现合成器的开启
       
10. 合成器是用脚本写的, 文件后缀为compositor, 详情可以查看该脚本文件
    用 CompositorManager的函数addCompositor, setCompositorEnabled来实现脚本的添加
    另外在createEffects函数中有手工创建合成器的方法。

11. 现在查看一下合成器监听器的细节
    基类为 Ogre::CompositorInstance::Listener
    该基类有两个主要的函数 notifyMaterialSetup 和 notifyMaterialRender
    在notifyMaterialSetup函数中
    得到 Ogre::GpuProgramParametersSharedPtr 的变量
    该函数在 编译渲染目标操作所包含的材质时激活。
   
    在 notifyMaterialRender
    则调用etNamedConstant函数对其中的片段参数进行设置
    该函数 在渲染目标操作之前激活。
   
12. 在本例中, 合成器实例监听器还有 notifyViewportSize 和 notifyCompositor函数
    在实例添加了监听器后, 在添加这两个函数进行一些基本的参数设置。