在3D游戏中采用场景管理的意义

来源:互联网 发布:网络教育文凭和函授 编辑:程序博客网 时间:2024/06/03 14:11

我们常说3D引擎应当包含若干功能:材质,模型,动画等等,这些功能我们很好理解,模型是我们需要渲染的几何体,材质表现的是几何体如何对光照如何做出回应,动画(特别的,骨骼动画)往往是3D世界中可运动模型的基础。除了这些与渲染直接关联的概念之外,往往还有个与渲染看似无关的概念:场景管理。

游戏渲染当中常用的场景管理往往被称为Scene Graph:它的实现通常采用树状结构,构成它的基本单位是节点,一个节点可以有若干个子节点,并且(除了根节点之外)往往有且只有一个父节点。

在实际游戏当中,对于需要渲染的几何体,比如静态的Mesh或者有Skeleton的Mesh,其本身不包含世界变换信息,而是由其所处的节点决定其位置与朝向。很久以前读Ogre的源码看到它就是这么做的,然而问题是,为什么必须要这么做?我一直心存疑惑,如果不采用Scene Graph的方案,我们给每一个需要渲染的模型赋予世界变换信息,那么这个模型不是一样可以渲染么?为什么非要把变换信息与模型本身分离开?分开有什么好处?而不这样做又有什么缺点呢?

以下是我对该问题做的小结:

问题1:视锥裁剪

采用了Scene Graph,提供层级结构之后,就可以高效的进行视锥裁剪:(更新父节点的包围盒时需要囊括其所有子节点的包围盒)如果父节点无法被看见,那么其所有子节点也都无法被看见。这样,如果一个节点有繁多(数以百计)的子孙节点,我们可以节约很多计算。

如果没有层级结构——我们采用线性表之类的数据结构,那么需要依此遍历所有物体,并依次根据其包围盒判断可见性。

这两个方案的优劣在场景不够复杂时很难分辨,但是显而易见,随着场景复杂度的增加,场景中的物体树N越大,采用层级结构的优势就越明显。

问题1衍生:碰撞检测支持

碰撞检测是比较耗时的算法,在游戏当中,如果一次碰撞检测需要计算的物体太多,会极大的影响效率,因此,与渲染时做可见性判断类似,碰撞检测也需要在进行计算之前尽可能多的剔除无关物体。

采用层级结构的场景,可以为碰撞检测提供天然的支持,如果父节点不与物体相交,那么自然其所有子节点都不会与之相交。

问题2:资源共享

有时候我们会遇到这种需求:需要在Pos[1], Pos[2], … , Pos[N]处渲染同一个Mesh,Mesh的几何数据是一样的,而变换矩阵不同。(这里不考虑Instancing的方案)

如果没有采用Scene Graph的分离变换信息与几何数据的方案,那么我们会遇到一个尴尬的局面:重复。

下面一个例子摘自SceneGraph的Wiki,生动的描述了这个问题:

For instance, a game might define a logical relationship between a knight and a horse so that the knight is considered an extension to the horse. The scene graph would have a ‘horse’ node with a ‘knight’ node attached to it.

As well as describing the logical relationship, the scene graph may also describe the spatial relationship of the various entities: the knight moves through 3D space as the horse moves.

In these large applications, memory requirements are major considerations when designing a scene graph. For this reason many large scene graph systems use instancing to reduce memory costs and increase speed.In our example above, each knight is a separate scene node, but the graphical representation of the knight (made up of a 3D mesh, textures, materials and shaders) is instanced. This means that only a single copy of the data is kept, which is then referenced by any ‘knight’ nodes in the scene graph. This allows a reduced memory budget and increased speed, since when a new knight node is created, the appearance data does not need to be duplicated.

可能有人会说:为什么不能在一个循环里依次设置世界矩阵,并绘制Mesh?这样就不会有重复。

是的,如果我们可以只针对这一个Mesh渲染的话,自然没有问题——但情况往往是,我们会预先注册很多个Mesh,最后一次性批量渲染(以尽可能最小化渲染状态切换的次数)。这样就要求我们注册Mesh的时候,附带着把Mesh的Transform信息也一起带着——如果不采用SceneGraph的方案,头疼的事情来了,这个Transform信息应该存放在哪?如果把它放在Mesh里:比如Mesh有一个属性说明自己在世界空间中的位置朝向 ,那么这个Mesh就被绑定到这个位置上了!绘制N个不同位置的Mesh就需要创建N个不同的Mesh实例!这在3D渲染中是无法想象的资源浪费。最后,我们还是不得不想办法把Mesh的Transform信息与Geometry数据分开。

SceneGraph是如何解决问题的?很简单,由于不同的Node可以挂接同一个Mesh,这样自然就实现的几何数据,乃至纹理,材质的共享。注册渲染的时候把Node注册到渲染器里就万事大吉了。

上述两个问题我认为是在3D游戏中采用SceneGraph的最重要的理由。

另,以下摘译自《3D Game Engine Design》一书:

采用场景图组织游戏内容,对于游戏来说非常重要,以下是原因:

1. 需要管理的数据通常很大,并且是有艺术家通过小片小片的形式建造出来的。关卡编辑者可以将一整个关卡的内容,通过树结构聚合起来,则自然的由此结构造出了整体性的结构。譬如,场景中的一盏灯可以只照亮场景图中的某个子树。关卡编辑者的责任就是将该灯赋予场景图中的某个节点,该灯的效果就由场景管理系统来维护。

2. 层次组织结构提供了一个局部性的模式:通常游戏中存在当前交互的对象,都处在相同的空间范围内。场景图可以使得游戏程序快速的排除游戏的其他区域,从而加速后续的处理。尽管将尽可能少的数据传送至显卡是让游戏运行效率提高的主要目标,但是聚焦处理小块的数据,也对碰撞检测尤为重要。如果潜在可碰撞物体特别多的话,那么碰撞检测模块也会变得非常慢。场景图可以将一组潜在需碰撞的物体组织起来,这些物体仅在当前游戏交互区域内被考虑进来。

3. 很多物体天然就被用层次结构搭建起来:譬如绝大多数类人体的骨架系统。手部的位置和朝向,自然的决定于腕部,肘部以及肩部的位置和朝向。

4. 有持久化需要的游戏,有的时候玩家需要在某一时刻将游戏状态储存起来,并在将来从此状态继续。层次化组织结构可以使得存储世界的状态非常简单:要求根节点存储自己,然后后续的就是递归的存储每一个节点即可。

关于Scene Graph 的实现:

SceneGraph的好处众多,但重要的问题是,维护这样一个数据结构需要的代价有多大?

最简单的Scene Graph就直接采用线性表,渲染,碰撞检测,都采取线性遍历即可,维护也极其简单,一个Node的移动旋转不会对其他Node产生任何影响(因为没有父子关系),因此也无需维护。对于小规模的场景,这种方案是可以接受的。但是当场景规模增大时,在可见性判断,碰撞检测等问题上,线性表的实现就表现出很大的局限性了。

因此比较常见的SceneGraph实现是一棵树,由Node构成,每个Node都可以挂接可渲染对象Object,并且可以有多个子Node,有且只有一个Parent Node。Node上挂接的可渲染对象决定了该Node的包围体。

当有Node的位置移动/朝向改变时(位于其局部坐标系内)一方面,从该Node出发,其父节点直至根节点的包围体都需要更新;另一方面,其所有的子孙节点的世界变换也需要更新以适应该节点的新位置朝向信息。

可能有不止一处改变在SceneGraph中的不同Node上同时发生,SceneGraph管理机制应当保证仅维护必要的节点:举例而言,如果A,B两个节点都有局部坐标变换发生,并且如果B是A的子孙节点,那么更新A的子树会自动更新B的子树,因此如果我们先更新B子树,再更新A子树,则会导致多余的计算,造成不必要的效率损失。

参考资料:

1.《3D Game Engine Desion》 Eberly, D.H http://book.douban.com/subject/3554163/

2. Wiki SceneGraph http://en.wikipedia.org/wiki/Scene_graph

3. http://www.gamerendering.com/category/scene-management/

 

本文转自:http://www.windameister.org/blog/2010/11/14/value-of-scene-management-in-3d-game/

 

原创粉丝点击