Radiosity Algorithms in BSP Scene 

2006-12-18 20:16 发布

引擎学习交流 /[各编程语言]
2126 0 0
 
Radiosity Algorithms in BSP Scene
在我翻译的《BSP技术详解》一文中对radiosity技术介绍的非常简单,而且很多地方都没有解释清楚,下面我将
结合自己研究的结果对如何在BSP场景中进行radiosity做一下介绍,这里只介绍关键的步骤,至于详细的实现细
节请自己参考相关的代码。
通常如果需要在一个构建好的BSP场景中进行radiosity计算大概需要下面的几个步骤:
1、将场景中每一个face分解为patch;
2、对每一个patch构建一个sample数组;
3、获得每一个patch的基本光照值;
4、对patch进行supersample操作;
5、通过pvs数据获得patch之间的可见性关系,为每一个patch建立一个可见patch列表;
6、在所有的patch之间模拟能量传递的过程,进行radiosity运算。
下面我对每一个步骤分别进行介绍。
第一步,在进行radiosity运算时能量传递是在patch之间进行的,因此需要将每一个face分解为patch,为了建立
patch需要确定patch最大size,它由引擎定义的lightmap最大size来决定,在ID系列引擎这个值定义为64,因此
patch在任意轴上的size不能超过64,知道这个值就可以建立patch了,为了方便管理,首先为每一个face建立一个
初始的patch,然后检查每个face在轴向上的size,如果大于64就沿最长轴对patch分割,获得两个子patch,接着
对子patch重复上面的过程直到face上所有的子patch在任意轴上的size都不超过64为止。当获得patch后需要计算
每一个patch的normal,注意face上的所有patch不能都使用face的normal,应该使用一种phong normal的算法来
获得,为了使用这种算法,应该从face上最顶层的root patch开始进行计算,对于root使用face的normal,接下来
计算两个子patch,计算子patch的normal时就需要使用phong normal了,方法很简单,通过比较子patch中心点
坐标和parent patch中心点的坐标获得一个权值,然后用这个权值在patent patch的normal和子patch上的所有
顶点的normal进行插值获得patch的phong normal。
第二步,在lightmap中每一个pixel被称为luxel,计算lightmap实际上也就是获得每个luxel的颜色值,因此首先
需要为每一个patch建立一张lightmap,然后为lightmap中的每一个luxel建立sample结构。这个过程并不太复杂
,在ID的引擎中每一个顶点并不存在纹理坐标这样的东西,它为每一个face都建立纹理坐标系和lightmap坐标系,
如果需要获得顶点对应的纹理坐标和lightmap坐标,只需要将顶点坐标通过矩阵变换到纹理空间就可以获得了,
现在为了获得patch的sample结构,首先应该获得每个patch的lightmap坐标系,注意这样作的原因是因为每个
patch的normal是phong normal,而不等于face的normal。获得patch的lightmap坐标系后获得patch上的每个顶点
的lightmap坐标,好了获得lightmap坐标之后就可以知道patch上到底存在多少个luxel了,然后沿着lightmap的
坐标轴对patch进行分割,建立和luxel同等数量的sample结构。
第三步,当上面的结构都建立起来后需要获得每个patch获得直接光照的lightmap,首先需要获得场景中所有的
灯光,然后对每一盏灯光做以下处理:
1、获得灯光D所在的cluster A索引;
2、通过pvs获得A所有可见的cluster;
3、遍历所有可见cluster中的每一个face上的每一个sample,检查其是否可以被灯光照亮,如果可以使用标准
的光照公式获得luxel的颜色值。
第四步、为了使patch上的lightmap看起来更加自然,剔除lightmap上的光斑和硬边需要对其进行supersample
操作,首先对每一个sample的颜色和相临8个sample的颜色进行比较,如果大于一个阀值,说明它需要进行
supersample操作,否则不需要。对于需要进行supersample操作的sample,首先将其颜色清空,然后根据其所
受到的光照类型分别处理,对于受到的环境光源按照正常方式进行计算,因为环境光源不需要进行supersample
处理,对于其他非环境光源需要进行supersample处理,通常在进行光源计算时我们使用的是sample的中心点
坐标,但是在做supersample时不能这样做,我们需要使用组成sample的顶点坐标进行计算,在前面进行分割
时我们将patch分割为一个一个sample,sample其实就是一个非常小的矩形patch,它由四个顶点构成,现在
为了做supersample需要计算出四个顶点的normal,然后计算每个顶点受到光照的颜色值,使用它们的算术平均
值作为sample的颜色值。
第五步、好了现在需要进行radiosity前的最后一步,因为radiosity的过程是在场景中所有patch之间进行不断
的能量传递的过程,直到在所有patch上的能量获得平衡为止,由于patch的能量只能从其可见的patch中获得,
因此需要获得每一个patch的所有可见patch列表,通过使用pvs数据可以快速的获得可见patch列表,并通过列表
获得其形状因子。
第六步、现在可以对场景进行radiosity运算了,首先将场景中的所有灯光剔除,接着将每一个patch所获得的
初始光照值做为每个patch需要发射的能量,换句话说就是将每一个patch都看作是场景中的灯光,而patch的
初始光照值作为灯光的光照值,好了,对于每一个patch来说都需要进行以下的步骤:
1、遍历可见patch列表,使用标准的光照公式计算从可见patch上获得的光照值并保存起来。
2、第一步完成后,接着使用从可见patch上获得的光照值作为每个patch的需要发射的能量,重新进行第一步。
3、当有patch需要发射的能量小于一个预定义的阀值将这个patch推出radiosity运算。
从上面的介绍可以看出整个radiosity运算最耗费时间的是在最后一步,因此为了提高运算速度可以使用多线程
技术(注意超线程技术对它并没有帮助)和分布式运算技术来进行优化,同时也可以使用逐步求精的算法来对
运算进行加速。
B Color Smilies

你可能喜欢

Radiosity Algorithms in BSP Scene 
联系
我们
快速回复 返回顶部 返回列表