比较郁闷,发泄一下

3D引擎设计构想

一、渲染流水线
渲染流水线是指在更高层面上我们自己定义并实现的渲染状态管理机制。
渲染状态包括:D3D的RenderState和TextureStageState。
渲染流水线要根据渲染对象的这些属性,对渲染对象进行分组、统一渲染,从而减少硬件状态转换。
D3D有几十个RenderState,但不是所有的RenderState都作为分组的依据,只有部分对视觉效果有较明显影响的RenderState才作为分组的依据。比较重要的RenderState有:Zenable(打开/关闭深度缓冲)、AlphaBlendEnable(打开/关闭Alpha混合)等。其中AlphaBlendEnable是最为重要的分组依据,凡是AlphaBlendEnable设为TRUE的渲染对象,都必须分在同一组渲染,而且是在所有AlphaBlendEnable设为FALSE的渲染对象渲染之后,并且渲染前还应进行排序。
TextureStageState也是对渲染对象进行分组的重要依据。这是出于这样一条准则:“使用相同贴图的三角形一块渲染,可以提高渲染速度”。另外TextureStageState还包含一些贴图级别的混合操作,这些操作也可作为分组依据。
总体上讲,渲染流水线就是实现这样一种功能:在一桢开始时,接受所有该桢将要渲染的对象,按这些对象的属性对它们分组,然后对每一组,设置一遍渲染状态,进行渲染,直到所有组都被渲染。
渲染流水线是基于一套抽象的3D渲染API工作的。因此我们要抽象定义D3D(包括Device、Texture、VertexBuffer等)和它相关的枚举数据类型。这样的抽象3DAPI将是版本无关的,甚至可以用OpenGL来实现。

二、SceneGraph
3D游戏的场景十分庞大复杂。为了提高渲染性能,并让这个虚拟世界同玩家交互起来,有必要使用一种高效的场景组织方法。SceneGraph就是实现场景组织的模块。
SceneGraph要有如下两个功能:划分空间、组织物体。
划分空间往往使用一种树型结构。对一个室外渲染引擎来说,可能使用四叉树或者八叉树。我的地形渲染算法就是基于四叉树的,不过我的四叉树结构有一个问题不好解决,所以打算使用八叉树代替。八叉树可以更好的划分一个封闭的立体空间。每一个树的结点都可以拥有8个子结点,这8个子结点平分他们父结点所对应的空间。
由此可见使用树形结构划分空间的一大特点是:倘若某个结点位于一个范围内,则这个结点的所有子结点也都位于这个范围内;倘若某个结点位于一个范围外,则这个结点的所有子结点也都位于这个范围外。这一特点可以用于实现快速的可视判断。我们把所有的渲染对象按其空间位置将其“链接”到相应的树结点上。那么如果该结点在视野范围内,则该结点所链接的所有渲染对象及其子结点的所有渲染对象都是可见的。我们将这些可见的渲染对象提交给渲染流水线,分组后即可渲染到屏幕上了。
由于所有的对象都链接在相应的树结点上,且同层结点是平分他们父结点的空间范围且不会有重叠,因此位于不同叶结点内的渲染对象之间一定是互相不接触的,那么碰撞就只发生在同一结点内。这样对每一个要移动的物体来说,他只需与当前自己所位于的结点内的其他对象依次作碰撞检测就可以了,而不用与整个场景内的所有物体都做碰撞检测,这大大减小了碰撞检测的计算次数,提高了游戏运行速度。
以上说的都是空间划分。SceneGraph还要有组织物体的功能。比如想要做一个能量球,让它绕着玩家旋转,为玩家提供能量保护,而玩家本身还在做着或上或下或前或后的运动,这将使能量球在世界空间中的运动变得非常复杂。如果实时的更新该能量球在世界空间中的位置,那代码将是非常丑陋的。事实上能量球只是以玩家为中心做公转运动罢了。那么在渲染能量球的时候,将能量球相对玩家的位置加上玩家的位置便是能量球在世界空间中的位置。为此,我们可以实现一种将物体组织在一块的SceneGraph,优雅的解决多个物体的相对运动。这也要用到树结构,但与空间树不同,物体树的子结点与父结点没有空间上的包含关系,物体树的子结点只是相对父结点运动,而不是平分父结点的空间。
骨骼动画就类似这种物体树。

将空间划分为结点,另一个重要的目的是与室内场景的无缝衔接。室内场景因为有很多封闭的走廊、房间,所以很自然的可以用结点划分空间(室外常景往往是用四叉树或八叉树强行划分,且是标准的平衡树)。如果室内室外都是结点,衔接问题自然很好解决(有着兼容的接口)。

你可能感兴趣的:(比较)