半透明物体(Translucent materials)在我们周围随处可见。大理石、玉器、皮肤、牛奶等等就属于这一类。半透明物体的绘制必须考虑到次表面散射(subsurface scattering),表面的入射光线除了反射以外,还有大量光线经入射点进入物体,在物体内部传输的过程中不断被吸收,不断被散射,最后在入射点附近穿出(BSSRDF)。
DIRECTX SDK中早在2004年便把subsurface scattering包含进了PRT的API中。DIRECTX SDK的例子中一直有一个PRT DEMO的例子,也展示了subsurface scattering的效果,我当时对着几个参数捣鼓了好一阵,出来的半透明效果平淡无奇,一点也没有国外论文中所附样图的风采。是不是我用的模型面数太少啊?是不是PRT中带的SSS技术不适用半透明物体啊?是不是还有什么未知的东西啊?
带着这些疑问过了好几年。期间,曾经在MSN上碰到这方面的一个专家,来想问他些问题,但是又不好意思说,怕打扰了他的工作,只是向他讨要了他的博士论文(可惜后来在电脑中丢了)。
2008年初,我写EMAIL给了曾在微软研究院做过实习生的赵爽(上海交大的学生,我查到了他的主页,上面有EAMIL,SIGGRAPH 2008有一篇论文,他是第二作者),向他讨教了几个问题。赵爽真是很“爽快”,第二天就给我回了信,谈了几点他自己的看法:“PRT 简单地说,是利用光源输入和物体的亮度具有线性关系(也就是说,光源亮度提高1倍,那么物体亮度也提高1倍)这一性质,预先以一些特定的基函数为光源,计算物体的appearance。然后对于任意光源,通过投影到该基函数上,并将预先计算好的 apperance 相加,即可得到物体在当前光源下的appearance。因此 PRT 是可以应用在半透明材质的渲染上的。至于你说的按 vertex 计算这一问题,的确这是 PRT框架的一个一般性问题,和是否是半透明材料无关。相反,对于很多半透明材料,尤其是 homogeneous 的材料,它们的 appearance相对比较低频,vertex 采样率反而可以低一点。至于微软 SDK 里面的渲染效果,其实我并不清楚微软 SDK 里面是如何渲染半透明物体的”。由此可见,模型面数少一些对半透明效果的影响并不大,也不是决定性因素。
后来,我看到了清华博士生徐昆(他也在微软研究院做过实习生,我发现做半透明物体这方面论文的都在那儿做过Research Intern。与英雄呆在一起,不知不觉也会变成英雄,不知道这样的比喻恰不恰当。)在EUROGRAPHICS2007上发表的论文“Real-time homogenous translucent material editing”,这篇论文讲了可变半透明物体材质的实时绘制,还带了一段非常棒的DEMO VIDEO。这文章又燃起了我熄灭好久的探寻半透明物体绘制奥秘的希望。特别是其中一句话提醒了我为什么DIRECTX SDK中的PRT DEMO的半透明物体效果比较差劲。“Since human perceives glossy surfaces more translucent than surfaces without glossy, for increased realism, we add a specular component to the final rendering. ”也就是说,人眼看有光泽的物体表面更能感受到半透明质地,所以加上高光,半透明的真实感更能体现出来。嗯,找到了问题的关键。
我在DIRECTX SDK的PRT DEMO上做了个小修改,增加了几个点光源的Specular Lighting。引入些许高光,渲染的图像立刻与以往不同了,效果出奇的好。请看如下图片。材质使用的是预定义的MARBLE。原想把程序传上来,可是目前我无FTP可用,BLOG中以往的连接都失效了,如有哪位网友能提供我BLOG用的FTP,不胜感谢。