unity入门精要之第6 章 Unity 中的基础光照---使用Unity 内置的函数

Unity系列文章目录

前言

读者可以发现,在计算光照模型的时候,我们往往需要得到光源方向、视角方向这两个基本
信息。在上面的例子中,我们都是自行在代码里计算的,例如使用normalize(_WorldSpace
LightPos0.xyz)来得到光源方向(这种方法实际只适用于平行光),使用normalize(_WorldSpace
CameraPos.xyz - i.worldPosition.xyz)来得到视角方向。但如果需要处理更复杂的光照类型,如点光
源和聚光灯,我们计算光源方向的方法就是错误的。这需要我们在代码中先判断光源类型,再计
算它的光源信息。具体方法会在9.2 节中讲到。
手动计算这些光源信息的过程相对比较麻烦(但并不意味着你不需要了解它们的原理)。幸运
的是,Unity 提供了一些内置函数来帮助我们计算这些信息。在5.3.1 节中,我们给出了
UnityCG.cginc 里一些非常有用的帮助函数。这里,我们再次回顾一下它们。表6.1 给出了计算光
照模型时,我们常常使用的一些内置函数。

在这里插入图片描述

注意,类似UnityXXX 的几个函数是Unity 5 中新添加的内置函数。这些帮助函数使得我们不
需要跟各种变换矩阵、内置变量打交道,也不需要考虑各种不同的情况(例如使用了哪种光源),
而仅仅调用一个函数就可以得到需要的信息。上面的9 个帮助函数中,有5 个我们已经掌握了其
内部实现,例如WorldSpaceViewDir 函数实现如下:
// Computes world space view direction, from object space position
inline float3 UnityWorldSpaceViewDir( in float3 worldPos )
{
return _WorldSpaceCameraPos.xyz - worldPos;
}
可以看出,这与之前计算视角方向的方法一致。需要注意的是,这些函数都没有保证得到的
方向矢量是单位矢量,因此,我们需要在使用前把它们归一化。
而计算光源方向的3 个函数:WorldSpaceLightDir、UnityWorldSpaceLightDir 和ObjSpace
LightDir,稍微复杂一些,这是因为,Unity 帮我们处理了不同种类光源的情况。需要注意的是,
这3 个函数仅可用于前向渲染(关于什么是前向渲染会在9.1 节中讲到)。这是因为只有在前向渲
染时,这3 个函数里使用的内置变量_WorldSpaceLightPos0 等才会被正确赋值。关于哪些内置变
量只会在前向渲染中被正确赋值,可以参见9.1.1 节。
下面介绍使用内置函数改写Unity Shader。
我们已经在本节涉及了过多的细节,如果读者无法理解所有内容的话,只需要知道,在实际
编写过程中,我们往往会借助于Unity 的内置函数来帮助我们进行各种计算,这可以减轻不少我
们的“痛苦”。
下面,我们将使用这些内置函数来改写6.5.3 小节中使用Blinn-Phong 光照模型的Unity

Shader。为此。
(1)在Unity 中新建一个场景。在本书资源中,该场景名为Scene_6_6。在Unity 5.2 中,默
认情况下场景将包含一个摄像机和一个平行光,并且使用了内置的天空盒子。在Window ->
Lighting -> Skybox 中去掉场景中的天空盒子。
(2)新建一个材质。在本书资源中,该材质名为BlinnPhongUseBuildInFunctionMat。
(3)新建一个Unity Shader。在本书资源中,该Shader 名为Chapter6-BlinnPhongUseBuildIn
unction。把新的Shader 赋给第2 步中创建的材质。
(4)创建一个胶囊体,并把第2 步中创建的材质赋给它。
Chapter6-BlinnPhongUseBuildInFunction 中的代码几乎和Chapter6-BlinnPhong 中的完全一样,
只是计算时使用了Unity 的内置函数。修改部分的代码如下:
(1)在顶点着色器中,我们使用内置的UnityObjectToWorldNormal 函数来计算世界空间下的
法线方向:
v2f vert(a2v v) {
v2f o;

// Use the build-in function to compute the normal in world space
o.worldNormal = UnityObjectToWorldNormal(v.normal);

return o;
}
(2)在片元着色器中,我们使用内置的UnityWorldSpaceLightDir 函数和UnityWorldSpaceView
Dir 函数来分别计算世界空间的光照方向和视角方向:
fixed4 frag(v2f i) : SV_Target {

fixed3 worldNormal = normalize(i.worldNormal);
// Use the build-in function to compute the light direction in world space
// Remember to normalize the result
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

// Use the build-in function to compute the view direction in world space
// Remember to normalize the result
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));

}
需要注意的是,由内置函数得到的方向是没有归一化的,因此我们需要使用normalize 函数来
对结果进行归一化,再进行光照模型的计算。

参考

Unity Shader入门精要
作者:冯乐乐

猜你喜欢

转载自blog.csdn.net/aoxuestudy/article/details/124370272