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

简介:

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

2.6 法线映射

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


972209183c62307a17c92bf3ceaa37e9c4f0f4c6

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


320feeac85e1937aec8010c3bdb3869c6d5ad86f

计算三维模型的法线原本是一项技术,但是迅速让位给另外一种更高级的技术,即法线映射。与纹理映射差不多,法线方向可以通过一个额外的纹理来提供。这个额外的纹理通常称为法线映射或者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项目中有一个。
本书中附带的法线映射示例如下图所示:


db4cc39abe44ebbab2ad4b1f2c654ec0719ed816

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

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


44b26cf1caf4f77940b95b44604cc184ea8f17e2

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

2. 将这些属性链接到Cg程序,方法是在CGPROGRAM语句下面的SubShader{}中进行声明:


ecc06d0335f1a27bc04359667fd396b63ad5d211

3. 需要确保Input结构体使用了正确的变量名进行更新,只有这样才能给法线映射纹理使用模型的UV值:


11a7d7cda919cab5de5fdabde893749402f0c121

4. 最后使用内建的UnpackNormal()函数来从法线映射纹理中提取法线信息,然后只需要将这些新的法线应用到表面着色器的输出中就可以了:


495d2f22dc316adadb5c313122e257c04218fb38

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


c5e9ca7c2d766bd94c2a3b933f5ebe7ccff2f303

 着色器可以既有纹理映射也有法线映射。很多时候这两种映射使用相同的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的属性:


b3a1f0ad07df81a7c6fd036cab2b1ba9ebf1d42d

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


20f28462be2cca5f14abedacee9a7789a419bcb5

 法线向量的长度可以是1,这里乘以_NormalMapIntensity之后会改变其长度,必要的时候需要处理一下数据格式。
现在可以让用户通过材质的Inspector标签页调整法线映射的光强了。下图展

c870d6e035df4e58717a434d12b050b8d8738920
相关文章
|
3月前
|
算法 vr&ar C#
使用Unity进行虚拟现实开发:深入探索与实践
【8月更文挑战第24天】使用Unity进行虚拟现实开发是一个充满挑战和机遇的过程。通过掌握Unity的VR开发技术,你可以创造出令人惊叹的VR体验,为用户带来前所未有的沉浸感和乐趣。随着技术的不断进步和应用场景的不断拓展,VR开发的未来充满了无限可能。希望本文能为你提供有用的指导和启发!
|
2月前
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
154 0
|
2月前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
145 0
|
3月前
|
vr&ar 图形学 开发者
步入未来科技前沿:全方位解读Unity在VR/AR开发中的应用技巧,带你轻松打造震撼人心的沉浸式虚拟现实与增强现实体验——附详细示例代码与实战指南
【8月更文挑战第31天】虚拟现实(VR)和增强现实(AR)技术正深刻改变生活,从教育、娱乐到医疗、工业,应用广泛。Unity作为强大的游戏开发引擎,适用于构建高质量的VR/AR应用,支持Oculus Rift、HTC Vive、Microsoft HoloLens、ARKit和ARCore等平台。本文将介绍如何使用Unity创建沉浸式虚拟体验,包括设置项目、添加相机、处理用户输入等,并通过具体示例代码展示实现过程。无论是完全沉浸式的VR体验,还是将数字内容叠加到现实世界的AR应用,Unity均提供了所需的一切工具。
118 0
|
5月前
|
图形学
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)
71 0
|
5月前
|
图形学
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏3(附项目源码)
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏3(附项目源码)
54 0
|
5月前
|
图形学 索引
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏1(附项目源码)
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏1(附项目源码)
123 0
|
3月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
147 6
|
2月前
|
测试技术 C# 图形学
掌握Unity调试与测试的终极指南:从内置调试工具到自动化测试框架,全方位保障游戏品质不踩坑,打造流畅游戏体验的必备技能大揭秘!
【9月更文挑战第1天】在开发游戏时,Unity 引擎让创意变为现实。但软件开发中难免遇到 Bug,若不解决,将严重影响用户体验。调试与测试成为确保游戏质量的最后一道防线。本文介绍如何利用 Unity 的调试工具高效排查问题,并通过 Profiler 分析性能瓶颈。此外,Unity Test Framework 支持自动化测试,提高开发效率。结合单元测试与集成测试,确保游戏逻辑正确无误。对于在线游戏,还需进行压力测试以验证服务器稳定性。总之,调试与测试贯穿游戏开发全流程,确保最终作品既好玩又稳定。
85 4
|
3月前
|
图形学 缓存 算法
掌握这五大绝招,让您的Unity游戏瞬间加载完毕,从此告别漫长等待,大幅提升玩家首次体验的满意度与留存率!
【8月更文挑战第31天】游戏的加载时间是影响玩家初次体验的关键因素,特别是在移动设备上。本文介绍了几种常见的Unity游戏加载优化方法,包括资源的预加载与异步加载、使用AssetBundles管理动态资源、纹理和模型优化、合理利用缓存系统以及脚本优化。通过具体示例代码展示了如何实现异步加载场景,并提出了针对不同资源的优化策略。综合运用这些技术可以显著缩短加载时间,提升玩家满意度。
93 5