Chapter 12-Not All Materials Are the Same

      本章主要讲解的是类似于天鹅绒的材质以及如何在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

原文地址:https://www.cnblogs.com/infintyward/p/3297744.html