ARM 在Unity3D 中的美术优化解决方案 4.着色器和材质

从 2019.4 开始,只有 Mobile 部分下的内置无光照着色器能够与 Unity 通用渲染管线 (URP) 一起使用。如果你打算使用以移动设备为中心的光照着色器,则应使用 Universal Render Pipeline/Simple Lit 着色器作为基础,因为这是 URP 中更简单、性能更高的着色器。

最好仅使用所需的着色器功能来自定义材质。Unity 将为你选择和配置的着色器创建经过优化的运行时版本。这种着色器复杂性的下降有助于提高在移动平台上的性能。着色器和材质在确定目标硬件如何处理和渲染 3D 对象方面起着至关重要的作用。在本项目中,你将探索让着色器在资源有限的手机上运行时保持轻巧、快速的最佳实践。

着色器和材质 - 概述

在本教程中,我们将定义着色器和材质在渲染项目的 3D 对象中所扮演的角色,以及本项目的学习目标。

1.概述

着色器和材质在确定目标硬件将如何处理和渲染 3D 对象方面起着至关重要的作用,因此有必要了解它们的工作原理和优化方法。如果材质或着色器配置不当,可能导致严重的瓶颈,使移动设备本就有限的资源变得更加紧张。

在本项目中,你将:

  • 了解可与 Unity 通用渲染管线完美搭配使用的经过优化的移动着色器。

  • 比较不同的透明度实现及其各自的收益/回报。

  • 探索让着色器在资源有限的手机上运行时保持轻巧、快速的最佳实践。

2.什么是着色器和材质?

着色器是一种小程序,它告诉 GPU 如何在屏幕上绘制对象以及绘制该对象所必须进行的一切计算。对于编写着色器,有两种常见的脚本语言:高级着色语言 (HLSL) 和 OpenGL 着色语言 (GLSL)。

着色器通过定义对象外观的材质应用于游戏对象。材质用于设置着色器可用的参数。例如,材质可以指定着色器引用的颜色、纹理和数值。

下面的屏幕截图显示了 Unity 中应用于材质的 HLSL 着色器:

Unity 还提供了一个称为 Shader Graph 的基于节点的工具,该工具可让你以可视化的方式构建着色器,而不用手写代码。下面的屏幕截图显示了如何通过在图形网络中创建和连接节点来构建 Shader Graph:

3.总结

材质和着色器是 3D 渲染过程的核心部分,了解它们的工作原理对于优化过程至关重要。在下一个教程中,我们将介绍针对移动平台优化着色器的最佳实践。

针对移动平台优化着色器

在本教程中,我们将介绍在 Unity 中使用正确的光照着色器和无光照着色器针对目标移动平台优化着色器的最佳实践。

1.为移动平台使用无光照着色器

Unity 的通用渲染管线 (URP) 中包含一系列内置着色器。下面的屏幕截图显示了 URP 专用着色器的位置。

从 2019.4 开始,只有 Mobile 部分下的内置无光照着色器能够与 Unity 通用渲染管线 (URP) 一起使用。如果你打算使用以移动设备为中心的光照着色器,则应使用 Universal Render Pipeline/Simple Lit 着色器作为基础,因为这是 URP 中更简单、性能更高的着色器。

最好仅使用所需的着色器功能来自定义材质。Unity 将为你选择和配置的着色器创建经过优化的运行时版本。这种着色器复杂性的下降有助于提高在移动平台上的性能。

2.光照着色器与无光照着色器

在创建着色器时,你可以决定材质将如何对光作出反应。大多数着色器可归类为光照着色器或无光照着色器。无光照着色器是速度最快、计算成本最低的着色模型。因此,如果你的目标是低端设备,请使用无光照着色器。需要考虑的关键点包括:

  • 光照不影响无光照着色模型。这意味着可以避免很多计算,例如镜面反射计算。结果是渲染成本更低,或者渲染更快。

  • 类似于卡通的风格化美术设计可与无光照着色良好地配合使用。在为移动平台开发游戏时,这种风格值得考虑。

与无光照着色器相比,光照着色器需要更多的处理能力。但是:

  • 光照会影响光照着色器,并让表面能够产生镜面反射。

  • 这可能是当今移动游戏中最常用的着色模型。

下图显示了有光照和无光照对象之间的区别:

应用了相同的塔楼网格和纹理,但使用了不同的着色器。光照不影响无光照着色器,因此在屏幕上渲染它们所需的计算较少。这可带来更好的性能,特别是在性能较弱的设备上。

3.总结

请仔细考虑哪些着色器和材质特性是实现应用程序所需的视觉风格所必不可少的,并限制使用对该风格没有直接贡献的特性。在下一个教程中,我们将讨论透明材质对移动应用程序性能的影响。

透明材质

在本教程中,我们将讨论在 3D 移动应用程序中使用透明度的回报和后果。

1.使用透明材质

使用透明材质设置时,必须考虑性能影响。较好的做法是尽可能使用不透明材质,特别是对于移动平台。

与渲染不透明对象相比,渲染具有透明度的对象总是会使用更多的 GPU 资源。在移动平台上使用很多透明对象会影响性能,特别是多次渲染相互重叠的透明对象时,该过程称为过度绘制。

在下面的屏幕截图中,蓝色光线本来可以具有透明效果,但使用不透明材质时看起来也不错:

2.比较透明度实现

有多种方法可以在着色器中实现透明度;每种方法有各自的优缺点。

最常用的透明度实现是 Alpha 测试和 Alpha 混合。Alpha 测试使材质看起来完全不透明或完全透明。你可以设置遮罩的镂空阈值。在 Unity 中,这称为镂空。

Alpha 测试会禁用 GPU 中的某些优化功能,因此在不必要时,最好避免使用 Alpha 测试。当使用 Alpha 测试/镂空时,强烈建议你在目标移动平台上进行测试。此外,不要忘记进行性能分析,以比较该透明度实现与 Alpha 混合是否存在任何性能差异。

Alpha 混合使材质具有一定范围的透明度,让对象看起来部分透明。Unity 将该混合模式称为透明。

对于移动平台,Unity 建议使用 Alpha 混合,而不是 Alpha 测试。与 Alpha 测试实现一样,你应该进行性能分析,以比较 Alpha 测试与 Alpha 混合的性能。每个用例都是内容相关的,因此需要进行测量。如果需要使用 Alpha 混合,尽量让混合区域小一些。

Alpha 混合可实现部分透明,而 Alpha 测试可产生边界分明的镂空。下图对 Alpha 混合和 Alpha 测试进行了比较:

3.用例:树叶

在树叶的静态视图中,与 Alpha 测试产生的锐利切口相比,Alpha 混合产生的边缘较为柔和,视觉效果更好。

但是,当树叶运动时,Alpha 混合看起来不正确。叶子没有以真实的顺序渲染,因为部分透明会在树叶彼此遮挡和分开时产生类似鬼影的效果。

Alpha 测试可以更好地处理叶子在运动时的透明度和顺序,让每片叶子都完全渲染或模糊不清,而不是部分透明。但是,与 Alpha 混合相比,其边缘更粗糙或有锯齿。

通常,Alpha 测试的视觉质量是可以接受的,因为锯齿边缘在运动中不那么明显。而使用 Alpha 混合时,一旦叶子和树枝开始来回跳动,视错觉就被打破了。

4.总结

为避免过度绘制,在移动应用程序中实现任何类型的透明度之前,必须仔细评估需求。选择使用哪种类型的透明度并不总是明确的,但有疑问时,对应用程序进行性能分析可提供更多数据帮助你做出决定。在下一个教程中,我们将介绍适用于 3D 移动应用程序的更多材质和着色器最佳实践。

更多的材质和着色器最佳实践

在本教程中,我们将介绍优化 3D 移动应用程序材质和着色器时的更多最佳实践。

1.保持着色器简单

如果无法避免过度绘制,则应让着色器尽可能简单。请牢记以下原则:

  • 尽可能使用最简单的着色器(例如无光照着色器),避免使用不必要的功能。

  • 使用专为粒子设计的 Unity 内置着色器。

  • 为尽量减少过度绘制,请减少游戏中粒子的数量和/或大小。

2.对着色器复杂性进行性能分析

添加纹理采样器、透明度及其他功能会使着色器变得复杂,从而影响渲染。我们建议你经常对着色器进行性能分析。

Arm 提供了执行该操作的工具,例如 Mali Offline Shader CompilerStreamline。但是,这些工具要求使用者具备较高的图形知识水平

3.顶点着色器中的数学运算

在项目中,经常需要组合使用顶点着色器和片元着色器来实现特定外观。

顶点着色器在每个顶点上运行,而像素着色器在每个像素上运行。通常,要渲染的像素数多于屏幕上的顶点数。这意味着像素着色器的运行频率高于顶点着色器。因此,我们建议你尽可能将计算从像素着色器转移到顶点着色器。

将计算操作转移到顶点着色器通常意味着将处理后的数据转移到像素着色器。虽然这通常是个好办法,但必须注意 Tiler,以防其成为瓶颈。跟往常一样,进行优化后,必须做进一步的性能分析,以确定适合你特定情况的最佳解决方案。

4.避免使用复杂的数学运算

着色器中的数学运算可自定义所需的外观和行为。

但这些数学运算具有不同的性能成本。因此,必须谨慎使用。一些更复杂的运算包括 sin()、pow()、cos()、divide() 和 noise()。

加法和乘法等基本运算的处理速度较快。最好是尽量减少速度较慢的数学运算。在较旧的设备(例如使用 GLES 2.0 的设备)上,必须保持较低的复杂数学运算量。

5.总结

有许多不同的方法可以优化着色器代码,但要了解真正的瓶颈位置,必须对应用程序进行性能分析。而且,要比较进行任何优化前后的效果,也需要进行性能分析。在下一个教程中,我们将深入剖析一个在 Unity 中使用 SRP Batcher 优化着色器和材质的示例。

演示:绘制调用与 SRP Batcher

使用内置的通用渲染管线时,你还可以获得 Unity 的可编程渲染管线批处理程序。在本演示中,你将有机会试用 SRP Batcher,并比较启用该功能前后的性能。

1.SRP Batcher

在上一个教程中,你了解了如何在 Unity 中使用内置的通用渲染管线 (URP) 着色器,以确保获得最佳的移动性能。使用内置着色器的好处之一是可以访问 Unity 的 SRP(可编程渲染管线)Batcher。在本教程中,你将有机会评估该批处理程序带来的性能提升。

2.开始之前

请在此处下载包含示例演示的课程项目。弹出提示时,单击 Shaders and Materials Demo,或在 Project 视图中打开示例场景 (Assets > 3 Shaders & Materials > Scene > Scene 3)。下载并打开后,可以在编辑器中进入运行模式,也可以将该场景构建到移动设备上以在性能分析器中进行性能分析。

3.要观察的内容

示例场景包含几个移动部分 - 一个动画骑士,平面上的几片草,以及使用透明着色器模拟火焰的粒子效果,以便用户能够看到背景中的骑士。

所有着色器都是使用 Shader Graph(URP 中内置的基于节点的着色器工具)实现的。因此,URP 功能也支持使用 Shader Graph 创建的大多数着色器。SRP Batcher 就是这样的一个功能。

你可以在所提供的 UniversalRenderPipelineAsset (Assets > Content > Settings) 中找到打开和关闭 SRP Batcher 的选项。SRP Batcher 开关位于 Advanced 下面。

当开启 SRP Batcher 时,观察 Statistics 窗口及 Profiler 视图中 Rendering 部分下的 Vertices 图。除了运行帧率提升以外,所处理的三角形和顶点数量也大幅减少。由于我们的对象使用了与 URP 兼容的着色器,渲染管线会自动批处理所有相关的几何体数据,以减少处理数据量。

你还可以暂停游戏,并在开启和不开启 SRP Batcher 的情况下启用帧调试器。在开启 SRP Batcher 后,你会发现绘制调用次数明显减少。

4.总结

在 Unity 中,你可以轻松地微调和配置着色器及材质,用较小的性能成本换取令人震撼的视觉效果。通过通用渲染管线中提供的功能,并应用使用它们的内置着色器,你可以充分利用目标移动设备的有限资源。在下一个项目中,我们将介绍如何使用光源高效地为移动应用程序增添氛围和情绪,以及如何将光源与 URP 配合使用。

猜你喜欢

转载自blog.csdn.net/Kaitiren/article/details/129683159