您的位置:首页 > 其它

untiy 3d ShaderLab_第4章_基本的光照模型

2016-04-29 17:31 183 查看
基本的光照模型

4.1光源对物体照明的分类

4.1.1间接照明

在物体所处的环境中,我们可以把照射到物体上的光源简单地分为直接照明间接照明。间接照明是光在物体间传播后,最终又对物体形成照明。有用3d Max做效果图经验的同学一定会对诸如用VRay渲染器渲染出的效果图倍感惊讶,那是因为渲染器在漫长的几十分钟甚至几小时的时间内,通过光线跟踪较真实地计算了光源的直接照明和间接照明。但是,对于3D游戏来说,最大的特点是实时交互,玩家或者用户不可能等上半个小时让渲染器把场景渲染好了再做下一个动作,因此对这部分的照明进行实时计算在目前是不可能实现的。在实际应用中,这种照明一般是通过预先烘培得到的。关于Unity中烘培这部分的内容在本书第8章和第9章中有详细讲解。对于实时计算,间接照明一般作为一个常量。

4.1.2直接照明

如果不考虑光线在物体间的传播,也不考虑光线在物体内部的传播,则光线对物体直接照明。我们把照明的结果分为漫反射镜面反射两种,其中镜面反射会形成强烈的高光。直接照明是实时渲染时的计算重点。

4.2 照明的计算方式:光照模型

4.2.1漫反射和Lambert


对于粗糙物体表面的某一点,其亮度应该和入射光线与该点的垂直程度相关,也就是入射光线与此点法线的夹角相关。如果我们用L表示单位长度的入射光线,用C表示到达此点的光线的强度和颜色,用N表示此点的法线,那么物体表面此点的亮度Lum就可以用下面的公式来表示:

Lum = C * max(O,cos<L,N>)
<L,N>表示的是方向矢量L和N之间的夹角,其cos值也就是这个两个方向矢量的点积,在实际计算时通过Cg的标准函数库dot(L,N)来完成。这个值对于背向光线的点来说为负,其实就是对其照明为0,因此使用标准函数库中的max(O,value)来对结果进行一些控制。

如果计算到此为止,可以把按照这种方式对物体进行照明计算的模型叫做Lambert。在Unity的Surface Shader中,有两个内置的Lighting Model函数,叫LightLambert()LightingLambertes_PrePass(),分别表示了Forward和Deferred渲染路径下的这种简单照明方式。这两个函数在Unity安装目录下的Editor/Data/CGIncludes/Lighting.cginc文件中。其中对应于Forward渲染路径的LightingLambert函数如下:

inline fixed4 LightingLambert (Surface0utput s, fixed3 lightDir, fixed atten)
{

fixed diff = max (0, dot (s.Normal, lightDir));//对漫反射的计算
fixed4 c;
//下面计算了物体表面的纹理颜色、光源颜色以及光源强度的影响
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);
c.a = s.Alpha;
return c;
}
如图所示就是一个Lambent照明的例子,该例子在Lambent文件夹下。



4.2.2镜面高光和Phong

世界很复杂,当然也因此而丰富多彩。

下面我们就来考虑一下上面提到的镜面高光问题,可以很直接地计算某一光线ray在某一法线为normal的点经反射后的光线,这个反射可以通过Cg标准函数库中的reflect(ray, normal)来完成。如果用R表示光线在此点的单位长反射方向向量,V表示视线的单位方向向量,那么高光部分Spec的计算方式表示为:

Spec = pow(max(O,cos<R,V>),gloss)
<R,V>表示方向矢量I和N之间的夹角,gloss表示其表面的镜面光滑程度。再加上前面在Lambert部分提到的对漫反射的计算,就可以得到一个被渲染出高光的物体,

如图所示



4.2.3 半角向量和BlinnPhong

在上面的高光计算方式中,我们确确实实计算了一次入射光线的反射,然后考察此反射光线进入视野的程度。还有一种更简单、更易于调节的方法是使用入射光线和视线的中间平均值,即半角向量,然后使用此半角向量和法线计算出一个和视角相关的高光,此种高光计算方式即为BlinnPhong

对于Unity的Surface Shader,Unity在Lighting.cginc 中提供了两个BlinnPhong的实现,分别对应于Forward和Deferred渲染路径。其中对应于Forward渲染路径的实现如下:

inline fixed4 LightingBlinnPhong (Surface0utput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
half3 h = normalize (lightDir + viewDir);
fixed diff = max (0, dot (s.Normal, lightDir));//对漫反射的计算
float nh = max(0,dot (s.Normal,h));
float spec = pow (nh, s.Specular*128.0) * s.Gloss;
fixed4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);
c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;
return c;
}


如图所示是BinnPhong文件夹下的场景所展示的一个例子。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: