Shader中的空间概念以及光照模型

来源:互联网 发布:linux查看gpu使用情况 编辑:程序博客网 时间:2024/06/10 00:56

模型空间:在Unity脚本中,可以通过tranform.worldToMatrix这个矩阵的MultiplyPoint()或者MultiplyVector()方法,把世界坐标表达的矢量转换为此物体的模型空间表达的矢量。在Shader可以通过左乘_Wrold2Object这个矩阵
世界坐标空间
世界坐标可以把两个点表达为统一的形式。在脚本中物体的Tranform组件的LocalToWorldMatrix矩阵的MulitplyPoint和MultiplyVector方法能把此物体自身以模型空间坐标的矢量变换到以世界坐标表达的矢量。在Shader中,对应的矩阵是
_Object2World.
视空间,又叫做相机空间,是为了表达以相机为世界的中心时所有物体的相互关系的一个空间。可以通过相机Camera组件的worldToCameraMatrix来把一个世界坐标的向量重新表示为一个以相机为中心的空间的表达式,如果想把一个空间的向量重新表示到世界坐标,可以用cameraToMatrix来实现。在Shader中,UNITY_MATRIX_MV可以把向量一次性从模型空间转换到视空间内。
视锥体:看得到的地方。只有处于视锥体内的物体才会被渲染,而其他部分都将处于视线之外,从而得到屏幕上能看到的东西。这个过程叫做Culling。
剪切空间
脚本中代表投影操作的是Camera组件的projectionMatrix,在Shader中则是UNITY_MATRIX_MVP矩阵。

基本的光照模型
把照射在物体上的光源可分为直接照明和间接照明,间接照明是光在物体间传播,最终又对物体形成照明。如果不考虑光线在物体间的传播,也不考虑光线在物体内部的传播,则光线对物体直接照明。直接光照是实时渲染的计算重点:
光照模型:
1.漫反射和Lambert
对于粗糙物体表面的某一点,其亮度应该与入射光线与该点的垂直程度相关,也就是入射光线与此店法线的夹角有关。L表示单位长度的入射光线,用C表示到达此点的光线的强度与颜色,用N表示此点的法线,那么物体表面到此点的亮度Lum可以表示为:
Lum = C*max(0,cos(L,N))
在实际计算时通过Cg函数dot(L,N)。这个值对于背向光线的点来说为负,也就是照明为0,因此使用标准函数库中的max(0,value)来对结果进行控制。
如果计算到此,可以把按照这种方式计算的模型叫做Lambert。在Unity的表面着色器中,有两个内置的Lighting Model函数,叫做LightLambert()和LightingLambert_PrePass(),分别表示了Forward和Deferred渲染路径下的简单照明方式:

inline fixed4 LightingLambert (SurfaceOutput 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;}inline fixed4 LightingLambert_PrePass (SurfaceOutput s, half4 light){    fixed4 c;    c.rgb = s.Albedo * light.rgb;    c.a = s.Alpha;    return c;}

2.镜面高光和Phong
镜面高光问题,计算某一光线ray在某一法线为normal的点经反射后的光线,这个反射可以通过Cg中的reflect来完成。如果R表示光线在此点的单位长反射方向向量,V表示视线的单位方向向量,那么高光部分Spec的计算方式为:
Spec = pow(max(0,cos(R,V)),gloss) gloss表示镜面的光滑程度。
3.半角向量和BlinnPhong
在上面的高光计算方式中,计算了一次入射光线的反射,然后考察此反射光线进入视野的程度,还有一种更简单的方法是使用入射光线和视线的中间中间平均值,即半角向量,然后使用此半角向量和法线计算出一个视角相关的高光,此种高光计算方式就是BlinnPhong。
Unity提供了两个BlinnPhong的实现分别对应Forward和Deferred渲染路径。

inline fixed4 LightingBlinnPhong (SurfaceOutput 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;}inline fixed4 LightingBlinnPhong_PrePass (SurfaceOutput s, half4 light){    fixed spec = light.a * s.Gloss;    fixed4 c;    c.rgb = (s.Albedo * light.rgb + light.rgb * _SpecColor.rgb * spec);    c.a = s.Alpha + spec * _SpecColor.a;    return c;
0 0
原创粉丝点击