come from:http://blog.csdn.net/weiqubo/article/details/6956005

要理解OGRE引擎,就要理解其中占很重要位置的 Renderable接口,今天先将一部分我分析的内容贴出来。

以下是 Ogre 的代码中的详细说明:

Renderable是OGRE中所有可渲染对象的抽象接口

这个接口抽象出了在渲染管线中的被分组的离散的可渲染对象基本的方法。

此接口的实现类必须是基于单一的材质、单一的世界矩阵(或者是一组通过权重混合的世界矩阵),以及单一的渲染操作。

通过这个说明,应该能明确的是,Renderable 封装了3D世界中被渲染对象的基本属性和数据,这包括:渲染操作,材质属性,光照信息、变换矩阵(四元组)、LOD信息、渲染方式等信息。这些信息在渲染循环中被取出,并应用在图形渲染管线中。其中需要注意的是RenderOperation(渲染操作)对象,它封装了图形硬件的顶点数据和渲染的图元类型,在最终的渲染操作里使用这些数据来进行图元渲染,值得注意的是 RenderOpration 中的保存的顶点信息的类VertexData中是抽象的,它包含了一组硬件顶点缓存数据对象-HardwareVertexBuffer,这个类是从 HardwareBuffer 中继承过来的,这个类包括了 hardware buffer中的抽象操作方法,这里使用了模板方法和抽象工厂等设计模式,每个具体的渲染系统可以实现自己的硬件缓存数据,当然,这当中也一定有HardwareBufferManager,而且具体的渲染系统也要实现这个类,来创建具体的渲染系统相关的数据缓存。

先说明OGRE内部重要的几个对象:

1.       RenderSystem,此抽象类定义出 3D 渲染系统的基本功能,同时实现了一些通用的方法。各个不同的渲染平台实现此类,OGRE 内部交互由此抽象类负责,从而实现了渲染平台无关性。应用一般不会与此对象直接进行交互,在OGRE内部的其他重要对象,如SceneManager与它进行交互,整个过程是透明的。

2.       SceneManager,组织场景中的对象并将对象送入渲染系统中渲染。这个类定义了场景管理器的基本功能,应用客户端根据自己需要重新实现场景的组织功能。这个对象掌控了所有的可渲染对象。

3.       RenderTarget , 定义:接受渲染操作结果的画布。此抽象类定义了基本的渲染目标属性和操作的功能。渲染目标可以是窗口、屏幕、或者离屏表面,如:渲染到一张纹理图等等。每个具体的渲染引擎需要实现自己的RenderTarget,如:D3D9RenderWindow,D3D9RenderTexture 等。这个抽象类包含了一个到多个的 ViewPort 对象,在渲染时会跌代更新每个ViewPort。

4.       ViewPort,定义:一块渲染目标区域。 
说明:视口是相机和渲染表面的交集,并把这个结果放在整个渲染表面或者表面的一部分。每个视口都有一个相机作为源,一个目标作为目标。一个相机只有一个视口,但一个渲染目标可以有多个视口。视口有 z 序属性,如果渲染目标有多个视口,要对视口进行 z 排序.

5.       Camera,这个就不需要解释了吧,需要注意的是它与ViewPort 和SceneManager之间的关系。

6.       SceneNode,这个类从Node继承过来,除了自身是一个树形结构之外,它还可以附加多个可移动对象(MoveableObject),这样他可以与世界中的所有可移动对象(比如实体对象)关联起来。

7.       Entity,定义了一个离散的、基于 mesh 的可移动对象的实例。

OGRE 通常将可渲染对象分为2组,一是在世界中移动的离散的极其相关小对象。一种是大规模的杂乱的通常组成静态场景的对象。

Mesh 和 SubMesh 处理那些在离散的可移动对象中使用的图元的定义。Entity 在世界中是真正的基于这种图元的对象的实例,因此对于一个汽车来说它就是一个独立的网格集合,但是在世界中可以有多个基于相同网格集合的实体,这些实体可以改变网格的外在表现,例如通过改变材质属性(这样你就可以在相同的图元数据上用不同的纹理来拥有不用的小汽车),为了这个目标,因为 Mesh 被分成多个 SubMesh,所以实体类是一个分组的类(与Mesh类很相似)并且相关的独立的个体改变的细节信息被保存在 SubEntity 类中。这是1:1的关系,Entity 与 SubEntity及其关联的 Mesh 和 SubMesh。

实体和子实体都不会被直接的创建出来,用 SceneManager 的 createEntity (传递一个模型的名字)方法来创建他们。

实体是被关联他们的场景节点对象包含在场景中的,使用 attachEntity方法关联,参照 SceneNode 类的说明或取完整的信息。

8.      RenderQueue,定义了渲染队列,此队列中包含了按照材质排序的可渲染对象,这样会使渲染状态的切换最少,它包含了一组RenderQueueGroup对象

9.       RenderQueueGroup,渲染队列组,按照渲染的优先级别排列的渲染对象列表。

10.   RenderPriorityGroup,渲染优先级分组,包含的所有的渲染对象都具有相同的优先级。分出透明对象和非透明对象及其它渲染方式对象,使渲染状态切换最小。

具体流程如下:
首先Ogre引擎在启动时会根据配置创建一个合适的场景管理器(SceneManager),SceneManager会自动创建一个根节点对象(SceneNode),有了这个root node 我们就可以在这个 root node下创建场景节点并将3D渲染实体附加到节点上。应用程序可以在任意节点下创建子节点,创建之后将3D渲染实体附加到此节点上。在SceneNode内部,保存着一个MoveableObject列表,由于Entity是从MoveableObject继承过来,所以可以把Entity附着在SceneNode上,同时,Entity内部包含一个SubEntity的列表,而SubEntity是从Renderable继承过来,这样在场景更新时,首先调用SceneNode的 _addToRenderQueue 方法,这个方法内部迭代MoveableObject列表的每一项,调用MoveableObject的_updateRenderQueue抽象方法,每个从MoveableObject继承的类都要实现此方法,比如Entity,在Entity的这个方法内部,迭代SubEntity列表的每一项(SubEnbtity从Renderable继承),将每个SubEntity送入渲染队列中去,这样就完成了渲染队列的更新工作。以上说明只是很粗略的描述,具体还有许多细节没有说明,比如进行可视判断,是否透明物体,是否为骨骼节点等等,但主要的流程是这样的。下一部份我将会说明加入渲染队列之后的内部流程。

好久没更新这个系列了,今天在同同事的讨论中说到了渲染对象排序的问题,正好自己的引擎也快做到这部分了,晚上回家看了一下 Ogre 的代码,整体如下:
先贴上一张 RenderQueue 的类和数据类型关系图:

数据类型说明:

1. RenderableList:
   原型:typedef std::vector<Renderable*> RenderableList;
   描述:可渲染对象列表。
2. TransparentRenderablePassList:
   原型: typedef std::vector<RenderablePass> TransparentRenderablePassList;
   描述:透明的渲染对象列表。
3. RenderableSolidPassMap:
   原型: typedef std::map<Pass*, RenderableList*, SolidQueueItemLess> SolidRenderablePassMap;
   描述:以Pass分组的非透明可渲染对象列表,每个Pass对应一个到多个可渲染对象,也就是说将相同渲染状态的对象作为一组进行渲染,减少渲染管线的切换操作,提高渲染性能。
4. RenderPriorityGroupMap:
   原型: typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
   描述:以优先级分组的可渲染对象队列的列表,以优先级作为列表中每一项的关键字。
5. RenderQueueGroupMap:
   原型: typedef std::map< RenderQueueGroupID, RenderQueueGroup* > RenderQueueGroupMap;
   描述:以渲染分组ID分组的渲染队列的列表,以渲染分组ID作为列表中每一项的关键字。所谓渲染分组标示(RenderQueueGroupID)就是标示粗粒度分组,比如2D背景一定会先渲染,天空会次之,2DUI可能会最后渲染,Ogre中已经定义好了一系列的粗粒度分组号,具体参考枚举类型RenderQueueGroupID的定义说明,大部分渲染对象使用的是RENDER_QUEUE_MAIN,这也是缺省的渲染粒度。
对象说明:
1. Pass:
   描述:从顶点到像素的一次生成过程,包含渲染状态的设置参数,比如光照参数、纹理阶段设置、Alpha 混合操作、深度缓冲、雾、裁减方式、填充模式等等,也包含了可编程管线PS\VS的相关设置。
2. Renderable:
   描述:请参考我的《关于 OGRE 中的 Renderable 》的文章。
3. RenderQueue:
   描述:定义了渲染队列,此队列中包含了按照渲染分组ID排序的可渲染对象列表,也就是上面的 RenderQueueGroupMap 类型。这里会进行最粗粒度的排序,按照2D背景、天空、场景对象、2DUI等进行排序。SceneManager 中包含此对象。
4. RenderQueueGroup:
   描述:渲染队列组,按照渲染对象的渲染优先级别排列的渲染对象列表,此类中拥有一个上面的 RenderPriorityGroupMap 类型成员。
5. RenderPriorityGroup:
   描述:渲染优先级组,包含的所有的渲染对象都具有相同的优先级。分出透明对象和非透明对象及其它渲染方式对象,使渲染状态切换最小。其中的渲染对象烈表是以 Pass 分组的,对于半透明物体,每个对象对应一个 Pass。
渲染流程:
每桢更新渲染队列,首先清除 SceneManager 中的 RenderQueue,然后在具体的场景管理器(BSP\OCTREE)中剔除不可见物体,将可见物体按照最粗粒度的划分加入到 RenderQueue 中,RenderQueue 将对象传递到 RenderQueueGroup 中按照并按照指定的优先级加入到 RenderPriorityGroup 中的 SolidRenderablePassMap(非透明) 或者 TransparentRenderablePassList (透明)中,在 SolidRenderablePassMap 中还要按照渲染状态排序,也就是 Pass 排序,将相同 Pass 的对象保存在一个列表中。这样,更新渲染队列的工作就完成了,在渲染时按照已经排好的顺序进行绘制就可以了。

Ogre内部渲染流程分析系列的更多相关文章

  1. 转:Ogre内部渲染流程

    以下是 Ogre 的代码中的详细说明: Renderable是OGRE中所有可渲染对象的抽象接口 这个接口抽象出了在渲染管线中的被分组的离散的可渲染对象基本的方法. 此接口的实现类必须是基于单一的材质 ...

  2. Cocos2dx开发之运行与渲染流程分析

    学习Cocos2dx,我们都知道程序是由 AppDelegate 的方法 applicationDidFinishLaunching 开始,在其中做些必要的初始化,并创建运行第一个 CCScene 即 ...

  3. 从React渲染流程分析Diff算法

    1.什么是虚拟DOM 在React中,render执行的结果得到的并不是真正的DOM节点,结果仅仅是轻量级的JavaScript对象,我们称之为virtual DOM. 简单的说,其实所谓的virtu ...

  4. ENode 2.0 - 深入分析ENode的内部实现流程和关键地方的幂等设计

    前言 ENode是一个基于消息的架构,使用ENode开发的系统,每个环节都是处理消息,处理完后产生新的消息.本篇文章我想详细分析一下ENode框架内部是如何实现整个消息处理流程的.为了更好的理解我后面 ...

  5. 深入分析ENode的内部实现流程和关键地方的幂等设计

    ENode 2.0 - 深入分析ENode的内部实现流程和关键地方的幂等设计 前言 ENode架构图 ENode框架内部实现流程分析 Command的幂等处理 Domain Event持久化时的并发冲 ...

  6. MyCat源码分析系列之——配置信息和启动流程

    更多MyCat源码分析,请戳MyCat源码分析系列 MyCat配置信息 除了一些默认的配置参数,大多数的MyCat配置信息是通过读取若干.xml/.properties文件获取的,主要包括: 1)se ...

  7. Ogre 监听类与渲染流程

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

  8. [源码分析] 带你梳理 Flink SQL / Table API内部执行流程

    [源码分析] 带你梳理 Flink SQL / Table API内部执行流程 目录 [源码分析] 带你梳理 Flink SQL / Table API内部执行流程 0x00 摘要 0x01 Apac ...

  9. CobaltStrike逆向学习系列(1):CS 登陆通信流程分析

    这是[信安成长计划]的第 1 篇文章 关注微信公众号[信安成长计划][SecSource] 0x00 目录 0x01 密码校验 0x02 aggressor.authenticate 0x03 agg ...

随机推荐

  1. mongodb基本操作及存储图片显示方案

    先介绍下mongodb的基本操作及使用 第一部:开启安全性验证 如果需要给MongoDB数据库使用安全验证,则需要用--auth开启安全性检查,则只有数据库认证的用户才能执行读写操作,开户安全性检查, ...

  2. JMeter Tutorial的安装和具体操作

    1.下载Jmeter 下载地址:http://jmeter.apache.org/download_jmeter.cgi 目前最新版为2.9,其余文件如源代码等也可从如下官网下载: http://jm ...

  3. LeetCode153:Find Minimum in Rotated Sorted Array

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...

  4. 将动态库添加到VC程序中

    应用程序使用DLL可以采用两种方式:一种是隐式链接,另一种是显式链接.在使用DLL之前首先要知道DLL中函数的结构信息.Visual C++6.0在VC\bin目录下提供了一个名为Dumpbin.ex ...

  5. hibernate相关知识

    1.为什么要用Hibernate JDBC的优点 直接底层操作,提供了很简单.便捷的访问数据库的方法,跨平台性比较强.灵活性比较强,可以写很复杂的SQL语句. JDBC的缺点 因为JAVA是面向对象的 ...

  6. hdu4504java

    import java.util.*;  class   Main{ public static void main(String[] args) { Scanner cin=new Scanner( ...

  7. PHP表单验证内容是否为空

    内容为空效果图为: 填写内容效果图: 下面是验证程序的代码: <!doctype html> <html> <head> <meta http-equiv=& ...

  8. RedHat7安装Sublime Text 3

    下载Sublime Text 3 # wget http://c758482.r82.cf2.rackcdn.com/sublime_text_3_build_3083_x64.tar.bz2 解压S ...

  9. Nginx Resource

    Nginx中URL转换成小写首先编译安装nginx_lua_module模块server节: location / { if($uri ~ [A-Z]){ rewrite_by_lua 'return ...

  10. linux+apache+mod_Jk+tomcat实现tomcat集群

    最近一段时间一直在研究实现apache + jk_mod + tomcat实现负载均衡,起初负载均衡算是配置蛮顺利的,但是到了配置tomcat集群时所有配置都没有问题,但是tomcat日志中一直提示没 ...