背景:
这是Delphi 3D 的3D Engine Dev.系列tutorial。(www.delphi3d.net)
This site is written and maintained by Tom Nuydens.
从基本的view system到高级的PVS(Possible Visible Set),LOD(Level of Detail)都有介绍,难能可贵的是写的深入浅出,别以为Tom Nuydens是某个传奇人物,他22岁,也是刚刚大学毕业,真是不尽牛人滚滚滚来啊!
我的翻译:
我最近在看Computer Graphics ,搜到这个站,发现很有用,所以本着learning by doing && share && just for fun的态度翻译(欢迎指正),并加上了一些我的理解和一些Expand(Maths ,some new figures etc.)。
[ 声明 ] :本文内容取自 www.delphi3d.net 网站上的 3D Engine Dev. 栏目,其著作权归原著者本人所有。译者 在未经原著者本人同意的情况下翻译本文。本翻译内容仅供自学和参考用,请所有阅读过本文的人不要擅自转载、传播本翻译内容;下载本翻译内容的人请在阅读浏览后,立即删除其备份。译者 对违反上述两条原则的人不负任何责任。特此声明。
========================================================================
Portal Rendering
上一节介绍了Visibility Determination 算法。这一次详细讨论一下Portal Rendering 算法。
1.基本Portal Rendering算法
要进行Portal Rendering 的第一步就是把你的空间分成凸子空间,这些子空间由Portal互相连接。绘制时,从观察者所处的子空间开始,如果这些子空间里有Portal并且可见的话,就先处理Portal后面的子空间。从一个子空间绘制另一个子空间时,Portal将用于其他Portal的剪裁。下面的几幅图可以使你更容易理解上面的算法:
黑色的轮廓就是你所在的房子。蓝色线段是Portals。第一幅图中对Portals编了号。红点表示观察者,箭头所指为视线方向。绿线表示视野(field of view)。现在第一步,观察者面对一面墙,左边可以看见1号Portal,那么就要先处理portal 后面的子空间。于是,调整视野,透过Portal 1不能看到的多边形都被删除。调整后的视野里,portal 2,portal 3都可见。如果先处理portal 3,由于portal 3后面没有其他portal,所以绘制该子空间即可。然后,继续处理portal 2,同样只需绘制portal 2后面的子空间即可。处理完portal 1后面的所有portal,回到最开始时观察者所在的子空间,该空间只有一个
portal -----portal 1,于是绘制该空间即可。
上面这个例子只是为了解释基本算法,不是一个能显示优越性的好例子,因为绘制了所有的子空间:(。现在来看一个能减少需要绘制的子空间的例子:
按着算法走一遍,你就会发现无论朝哪边看,大多数子空间不会绘制。(Note: 将portal和field of view剪裁,
或者portals之间剪裁,还将进一步减少需要绘制子空间的数量 。)
2. Sector Subdivision(子空间划分)
Portal Rendering 中最重要的问题就是----你该把Portal们摆在那里。“子空间是凸子空间(Convex subsector)”这个要求将产生过多的portals。于是,你需要一种能自动摆放portals的方法,要是办不到的话,就需要考虑一下凹子空间了:(。为什么我们需要凸子空间呢?因为,凸子空间可以不经过多边形排序,随便什么顺序绘制多边形,一个都不会盖着另一个。用凹子空间将大量减少portals。(想一下一个房间里摆着一个凸20面体的情况,就可以体会两种类型的子空间所带来的差别了。)
在Untitled-3D(Tom Nuydens的3D Engine)中,我将采用凹子空间。当然,如果用凹子空间和透明表面(指Portal)的话,免不了多边形排序----你画之前总得知道多边形从后向前的顺序。这就是为什么Untitled-3D 中每个子空间都需要建一棵BSP树的原因。这听起来挺复杂的,但是用这种方法,portal的数量可以减少到可以用“手工摆放”来完成的程度。如果你必须使用自动摆放portal,你其实有很多选择。常用的是用一个叶-BSP(多边形存在叶节点中而非中间节点,与之相对的是Node-BSP),叶节点中的多边形搭成一个凸子空间。
感兴趣的话可以参考 www.flipcode.com的Harmless' colum,另外gameprog.com也有一些有用的文章。
3.Ploygon sorting(多边形排序)
要是采用凹子空间的话,多边形排序少不了的。上面已经提到Untitled 3D采用BSP树来表示每个子空间。但是要处理移动的物体时就得多费点神了:这类物体并不包含在BSP中---因为要是这样的话,需要实时构建BSP树,复杂空间BSP树的构建是件极费时的事(若干小时:(.......)。通常运动物体的多边形排序,采用简单的Z-buffer。但是还是得当心,步骤大致如下:
-遍历BSP树,绘制不透明多边形。
-绘制移动物体。
-标记Z-buffer为只读(用glDephtMask())
-再次遍历BSP树,只绘制透明多变形
-re-enable Z-buffer
这样,一切就都OK了。是吗?还有一点:你的移动物体不能透明。这通常不是什么问题----比如,如果你想用精灵(Sprite)表现射击效果(想象一下Plasma Gun射击时,那一片漂亮的蓝光,不过据我观察Quake里的Plasma Gun的子弹好像不是采用精灵:(,姑且当它是吧:)),一个精灵就一个多边形,排序不会带来麻烦。
4. Conclusion(小结)
基本的Portal Renderign 算法离实用还差的远,有待提高。
采用凹子空间可以解决portals过多的问题,你也就用不着挖空心思去找一个合理自动摆放portals的方法了。但是同时带来了多边形排序的问题,我也讨论到了一些排序的方法。
Next Time,Part 3 Data Structures for 3D Engine。