背景:
这是Delphi 3D 的3D Engine Dev.系列tutorial。({域名已经过期})
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.)。
要进行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之间剪裁,还将进一步减少需要绘制子空间的数量 。)
Portal Rendering 中最重要的问题就是----你该把Portal们摆在那里。“子空间是凸子空间(Convex subsector)”这个要求将产生过多的portals。于是,你需要一种能自动摆放portals的方法,要是办不到的话,就需要考虑一下凹子空间了:(。为什么我们需要凸子空间呢?因为,凸子空间可以不经过多边形排序,随便什么顺序绘制多边形,一个都不会盖着另一个。用凹子空间将大量减少portals。(想一下一个房间里摆着一个凸20面体的情况,就可以体会两种类型的子空间所带来的差别了。)
要是采用凹子空间的话,多边形排序少不了的。上面已经提到Untitled 3D采用BSP树来表示每个子空间。但是要处理移动的物体时就得多费点神了:这类物体并不包含在BSP中---因为要是这样的话,需要实时构建BSP树,复杂空间BSP树的构建是件极费时的事(若干小时:(.......)。通常运动物体的多边形排序,采用简单的Z-buffer。但是还是得当心,步骤大致如下:
-遍历BSP树,绘制不透明多边形。
-绘制移动物体。
-标记Z-buffer为只读(用glDephtMask())
-再次遍历BSP树,只绘制透明多变形
-re-enable Z-buffer
这样,一切就都OK了。是吗?还有一点:你的移动物体不能透明。这通常不是什么问题----比如,如果你想用精灵(Sprite)表现射击效果(想象一下Plasma Gun射击时,那一片漂亮的蓝光,不过据我观察Quake里的Plasma Gun的子弹好像不是采用精灵:(,姑且当它是吧:)),一个精灵就一个多边形,排序不会带来麻烦。
基本的Portal Renderign 算法离实用还差的远,有待提高。
采用凹子空间可以解决portals过多的问题,你也就用不着挖空心思去找一个合理自动摆放portals的方法了。但是同时带来了多边形排序的问题,我也讨论到了一些排序的方法。