《Unity着色器和屏幕特效开发秘笈(原书第2版)》——2.6 法线映射

简介:

本节书摘来自华章计算机《Unity着色器和屏幕特效开发秘笈(原书第2版)》一书中的第2章,第2.6节,作者 [英]艾伦朱科尼(Alan Zucconi)[美]肯尼斯拉默斯(Kenneth Lammers),译 占红来,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.6 法线映射

三维模型中的每一个三角形都有一个面朝方向(facing direction),顾名思义指的是三角形的朝向。这个方向通常用一个从三角形中心出发垂直于三角形表面的箭头表示。面朝方向对于光线在物体表面反射的时候起到了至关重要的作用。如果两个相隔很近的三角形朝向不同,它们就会将照射光反射到不同的角度上,因此这两个三角形的着色方式会大不一样。对于弧形物体就有点麻烦了,因为弧形表面没法用平的三角形拼凑出来。

为了避免这个问题,在处理弧形表面的光照效果时,我们忽略其朝向,而是使用其法线方向(normal direction)。在2.4节中已经提到过了,顶点可以储存数据。在顶点所保存的数据中,法线方向是仅次于UV值的一个非常重要的参数。法线方向是一个单位长度的向量,表示顶点面朝的方向。与面朝方向不同的是,三角形中的每一个点都有其独有的法线方向,它们的法线方向是基于顶点的法线方向通过线性插值得到的。通过这种方式,我们可以用一些低精度模型制作出高精度的几何体。下图展示了一个相同的几何体在使用不同的顶点法线时的渲染效果。最左边这个图像中,法线完全垂直于三个顶点围城的平面,可以看出每个面之间有清晰的分界,而最右侧的图像中法线是在整个表面进行插值计算得到的,通过这种方式哪怕物体表面是粗糙的,也可以让它看起来很光滑。通过下图很容易看出来,即便是三个一模一样的几何体,它们在光照下的反射情况也大不一样。尽管最右边这个图像中的几何体也是用平面三角形围成的,但是看起来就好像它是一个完美的球面一样。

image

使用顶点法线插值得到的物体都有一个普遍的特点:表面看着很光滑,但是边缘却很尖锐。这一点可以通过标注出每一个顶点保存的法线方向看出来,如下图所示。你可以发现虽然每一个三角形都只有三个法线,但是大部分三角形放在一起的时候,某些相邻的顶点的法线方向是一样的,这也是为什么右边这个图像中的法线数量较少的原因,因为很多顶点的法线都重合了。

image

计算三维模型的法线原本是一项技术,但是迅速让位给另外一种更高级的技术,即法线映射。与纹理映射差不多,法线方向可以通过一个额外的纹理来提供。这个额外的纹理通常称为法线映射或者bump映射。法线映射通常是一些RGB图像,RGB的成分值分别用来表示法线方向(X, Y, Z)的值。有很多方式可以创建法线映射。某些应用程序,比如CrazyBump(http://www.crazybump. com/ )或者NDO Painter(http://quixel.se/ndo/ ),可以接受一个二维数据然后将其转化为你想要的法线数据。其他一些应用程序,比如Zbrush 4R7(http://www.pixologic. com/)和AUTODESK(http://usa.autodesk.com ),可以接受一个三维雕刻数据,然后创建一些法线映射。创建法线映射的步骤完全超出了本书的范围,但是上面提到的这些链接或许会给你提供些许帮助。

在Unity中给表面着色器添加法线映射的过程非常简单,只需要使用UnpackNormals()函数就可以了,我们接下来看看应该怎么做。

2.6.1 准备工作

创建一个新的材质和着色器,然后启动一个新的项目,将新的着色器和材质放置到Scen视图中。这样我们就可以得到一个干净的工作空间,接下来可以看看法线映射技术。

这一节需要一个法线映射,如果没有的话在本书附带的Unity项目中有一个。

本书中附带的法线映射示例如下图所示:

image

2.6.2 操作步骤

下面是创建法线映射着色器的详细步骤:

  1. 设置好Properties代码块,添加一个颜色和纹理。
    image

 通过将纹理初始化为bump,告诉Unity _NormalTex会包含一个法线映射。如果没有设置纹理,则会使用一个灰度纹理替代。这里用的(0.5,0.5,0.5,1)颜色用来表示一点bump都没有。

  1. 将这些属性链接到Cg程序,方法是在CGPROGRAM语句下面的SubShader{}中进行声明:
    image
  2. 需要确保Input结构体使用了正确的变量名进行更新,只有这样才能给法线映射纹理使用模型的UV值:
    image
  3. 最后使用内建的UnpackNormal()函数来从法线映射纹理中提取法线信息,然后只需要将这些新的法线应用到表面着色器的输出中就可以了:
    image

下图是使用了我们的法线映射着色器之后得到的效果:

image

 着色器可以既有纹理映射也有法线映射。很多时候这两种映射使用相同的UV数据,然而我们也可以在顶点数据(UV2)中给法线映射专门提供另外一套UV数据。

2.6.3 工作原理

实际的数学过程中如何实现法线映射特效完全超出了本书的范畴,你只需要知道Unity已经做好了这些就可以了。Unity创建了一些方便的函数,让我们不用一遍一遍地耗在一些重复的数学计算中。这也是表面着色器是一种高效地编写着色器的方式的原因之一。

看看Unity安装目录的Data目录下的UnityCG.cginc文件,应该可以找到UnpackNormal()函数的定义。当你在表面着色器中声明这个函数时,Unity会接收到你所提供的法线映射,然后对其进行适当的处理以确保你可以在每一个像素的光照函数中正确使用这些映射结果。这非常节约时间!在采样纹理的时候,采样结果是0到1的RGB值,但是法线向量的值是从–1到1。UnpackNormal()知道如何匹配对应的值域。

一旦用UnpackNormal()函数处理了法线映射之后,便会将法线映射回传给SurfaceOutput结构,这样它就可以用在光照函数中了。这是通过o.Normal = normalMap.rgb来完成的。我们会在第3章中看到法线是如何用来计算每个像素上的最终颜色的。

2.6.4 更多内容

还可以在法线映射着色器中添加更多的控件,让用户可以调整法线映射的光强。这可以通过修改法线映射变量的x和y值来完成。给Properties代码块添加另外一个名为_NormalMapIntensity的属性:
image

将解压之后的法线映射的x和y均乘上该属性之后作为新的法线映射变量的x和y值:
image

 法线向量的长度可以是1,这里乘以_NormalMapIntensity之后会改变其长度,必要的时候需要处理一下数据格式。

现在可以让用户通过材质的Inspector标签页调整法线映射的光强了。下图展示了不同光强下法线映射的效果:

image

相关文章
|
3月前
|
算法 安全 图形学
Unity Hololens2开发|(十一)MRTK3 Solver(求解器)
Unity Hololens2开发|(十一)MRTK3 Solver(求解器)
|
3月前
|
API 图形学
Unity Hololens2开发|(十)MRTK3空间操作 ObjectManipulator (对象操控器)
Unity Hololens2开发|(十)MRTK3空间操作 ObjectManipulator (对象操控器)
|
3月前
|
Go 图形学
Unity Hololens2开发|(九)MRTK3空间操作 ConstraintManager(约束)
Unity Hololens2开发|(九)MRTK3空间操作 ConstraintManager(约束)
|
3月前
|
算法 图形学 UED
Unity Hololens2开发|(八)MRTK3空间操作 BoundsControl(边界控制)
Unity Hololens2开发|(八)MRTK3空间操作 BoundsControl(边界控制)
|
3月前
|
图形学
Unity Hololens2开发|(七)MRTK3子系统 TextToSpeechSubsystem(文本转语音)
Unity Hololens2开发|(七)MRTK3子系统 TextToSpeechSubsystem(文本转语音)
|
3月前
|
图形学
Unity Hololens2开发|(六)MRTK3子系统 DictationSubsystem(听写功能)
Unity Hololens2开发|(六)MRTK3子系统 DictationSubsystem(听写功能)
|
3月前
|
图形学
Unity Hololens2开发|(五)MRTK3子系统 KeywordRecognitionSubsystem(关键字识别)
Unity Hololens2开发|(五)MRTK3子系统 KeywordRecognitionSubsystem(关键字识别)
|
4月前
|
C# 图形学
【Unity 3D】元宇宙案例之虚拟地球信息射线实战(附源码、演示视频和步骤 超详细)
【Unity 3D】元宇宙案例之虚拟地球信息射线实战(附源码、演示视频和步骤 超详细)
49 0
|
4月前
|
人工智能 自然语言处理 区块链
【Unity 3D】元宇宙概念、应用前景、价值链等概述
【Unity 3D】元宇宙概念、应用前景、价值链等概述
52 0
|
4月前
|
vr&ar C# 图形学
【Unity 3D】VR飞机拆装后零件说明功能案例实战(附源码和演示视频 超详细)
【Unity 3D】VR飞机拆装后零件说明功能案例实战(附源码和演示视频 超详细)
38 0