本章主要讲解的是类似于天鹅绒的材质以及如何在RenderMonkey中构建这种材质的光照方程。
天鹅绒这种材质,我还是头一次听说,太孤陋寡闻了,于是乎我去认真百度了一下“天鹅绒”。这种材质反射情形如下图所示。
特点:布料的折边处非常容易看到类似于镜面高光的反射。
本章的几个小程序倒是很容易搞定。值得一说的是书中双向反射分布函数(BRDF)明显有错误,跟代码对不上。如222页的图12.6所示的Oren-Nayar光照模型计算公式,这个公式是错误的。
如果看书没有勘误表,看到这种公式跟代码不一致时,真是让人死的心都有了,到底以哪一个为准?
幸好现在网络很发达,Wiki百科上有这个公式非常详细的解释。
参考链接如下:http://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model(题外话,维基百科真是太强大了,相比之下,百度在专业搜索方面真显得非常业余)
最终精确的Oren-Nayar光照计算公式如下图所示:
上图的方位角Φi,Φr ,表示不够明显,我在《计算机图形学》中(Alan Watt著)中找到了一个比较好的图片——方位角就是入射光线、反射光线在正切平面上的投影与两线所在平面的夹角。
公式搞明白之后,就可以写代码了。书中代码并不是严格的按照公式来写的,比如如下代码的第27行在max函数、min函数中分别计算正弦和正切的最大值和最小值,作者就偷懒了,直接按照已经计算好的值来进行比较了,而没有拿反三角函数计算角度再进一步比较角度大小。不过还是行得通的,毕竟角度增减趋势和正弦正切的增减趋势在0°~90°是一致的。
1 float4 Light1_Color; 2 float Velvet_Exponent; 3 float PI; 4 float rho_pi; 5 float A; 6 float B; 7 float4 Light_Velvet(float3 Normal, float3 EyeVect, float3 LightDir, 8 float4 LightColor) 9 { 10 // calculate all the dot products 11 float NdotL = dot(Normal, LightDir); 12 float NdotE = dot(Normal, EyeVect); 13 // calculate the zenith angles 14 float sinTheta_r = length(cross(EyeVect,Normal)); 15 float cosTheta_r = max(NdotE,0.001); 16 float sinTheta_i = length(cross(LightDir,Normal)); 17 float cosTheta_i = max(NdotL,0.001); 18 float tanTheta_i = sinTheta_i / cosTheta_i; 19 float tanTheta_r = sinTheta_r / cosTheta_r; 20 // calculate the azimuth angles 21 float3 E_p = normalize(EyeVect-NdotE*Normal); 22 float3 L_p = normalize(LightDir-NdotL*Normal); 23 float cosAzimuth = dot(E_p, L_p); 24 // Compute final lighting 25 float inten = rho_pi * cosTheta_i * 26 (A + B * max(0, cosAzimuth) * 27 max(sinTheta_r, sinTheta_i) * min(tanTheta_i, tanTheta_r)); 28 return LightColor * clamp(inten,0,1); 29 }
如果你非要按照精确公式计算也是可以的。我顺便翻了一下《Advanced Lighting and Materials with Shaders》,第138页,7.3节,Oren-Nayar Materials这个示例就实实在在拿精确公式进行计算的,感兴趣的话可以参考一下。
最后关于Oren-Nayar Materials材质,有这么一点要注意:它是属于散射类材质,是专门针对diffuse光的反射模型。因此即便光源包含Specular光和Ambient,也全当Specular和Ambient不存在,在光照方程中不对它们进行处理。Oren-Nayar Materials的反射光与视点是相关的,即它反射出来的光跟Specular非常像,但是,它的的确确是diffuse的处理方式,即散射方式对光线进行处理。
对比图:左图是传统Phong光照模型,右图是Oren-Nayar光照模型。Oren-Nayar最大的特点,就是当你从入射光方向去观察被照亮模型,会发现整个模型向光面几乎都是亮的;而传统Phong就不一样,明暗分明。
//end