Posted by: billconan | October 11, 2006

学究一下,编了一个radiosity辐射度渲染程序


我特别羡慕那些有强烈兴趣爱好,懂得自我发掘,而且做出一定成果的人。我不是这样的人,我的兴趣太多,又不太有常性。以前我在旧的博客上天南地北地扯了不少,却很少专注于自己的事业,所以当初决定把博客搬到这里的时候,我给自己规定的基调是尽量走学术路线。其直接的后果是,流量下降,评论大幅度减少,女Fans更是一个不剩,现在基本上已经属于是自娱自乐了。学究当到底,今天我编了一个radiosity的偷懒算法程序。
很早以前,我在azure的博客上看到他做了一个辐射度的渲染程序。当时我没有仔细看,但是有一点印象特别深,就是他把摄影机摆在patch上来模拟能量的入射。我不知道这个想法是不是他原创,但是真的是太聪明的一个偷懒办法了。传统的辐射度需要做很多射线,然后再和多边形求交,现在可以用现成的摄影机来替代,简直太省事了。
这样一来,辐射度程序实际上变成了这样的一个过程:
首先组织好一个场景,这一步我是在3D Max里随便做了一个房间,房间上开了一个窗户,用来透进点亮光,作为初始的光源。房间的中间放了一个柱子,主要我想看看这个柱子能形成什么样的影子。在3D Max中导出成obj格式的文件,然后把里面的数据直接粘帖到代码里,改了改,存放在数组中。
然后为每个面开辟光照贴图的空间,并且计算法线,切线。
将贴图分解成小patch,计算每个小patch中心点在3D场景中的位置,在这个位置上放置摄影机,拍摄当前的场景。将patch中心映射到3D场景中的公式是这样的(四边形v1、v2、v3、v4):
v1+(v2-v1)*u+(v4-v1)v 其中uv是贴图坐标,v1、v2、v3、v4是四边形的端点。
渲染的场景存放到一个空间中,我的程序里是一个64见方的数组。然后对这个数据进行分析,得到一个当前patch的颜色。分析的过程是,首先计算这个64见方的图像上每个象素距离中心点的距离,根据这个距离得到一个权重。为什么需要权重呢?因为在传统的辐射度算法中用的是射线来模拟光照,光照对于颜色的影响取决于入射的角度。因为我这里没有用射线,所以无法得到角度,但是摄影机得到的图像中,点的位置离中心越远,说明生成它的入射光线的入射角就越大,所以在最后决定颜色的时候越不重要,这样将所有点的权重计算出来作一个加权平均,得到一个颜色值。但是这还没完,还需要乘以一个数值,这个数值是一个近似的能量衰减。光在传播的过程中能量是衰减的。实际上这个衰减和光的传播距离应该是相关的。在传统的辐射度计算中,射线和多边形相交的同时可以得到这个距离,这样就比较容易计算精确的衰减。但是因为这个是偷懒版的程序,不能得到光源距离当前面长度。所以就简化假设任意距离的光源产生的光照都要衰减一个固定的比例。我的程序里用的0.2。当然也可以这样来假设,光源距离当前物体非常远,而当前物体中(我的这个房子)的所有面之间的距离相对于这个光源与这个房子之间的距离可以忽略不计,这样的话房子中各物体的衰减差别不大,就近似成一样的。
以上就是我的懒汉版光照模型。
一开始我在这个程序中用的贴图是128*128的,感觉稍微有些粗糙,后来改用256*256的,速度明显变慢了。不过最后出来的结果我总觉得别扭,但是又看不出来问题。不知道是不是我的懒汉光照模型有问题,还是我的程序什么地方疵了。有时间再看看。左边这个图显示的是如何从最开始的初始场景逐步照亮的过程,就第一次辐射变化比较明显,后面的变化及其细微。

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: