ARM's art optimization solution in Unity3D 5. Lighting

(Note: While we chose progressive CPU lightmappers, we encourage you to experiment with progressive GPU lightmappers and perform profiling. Performance may vary depending on your system GPU.)

The Unity engine provides three options for generating lightmaps - Enlighten, Progressive CPU lightmapper and Progressive GPU lightmapper. In this project, we chose to use progressive CPU lightmappers, since Enlighten is about to be deprecated, and progressive GPU lightmappers are still in preview.

Baked lighting using progressive CPU lightmaps saves CPU cycles when processing lighting information. As a result, you may see a large increase in frames per second (FPS) while CPU usage drops. When measuring the FPS of the two scenes, you should see a noticeable difference in the Statistics window.

Mobile devices can really make that difference. Build the example scene onto a phone of your choice, profile both scenes while observing the Total CPU graph in the Global Illumination section of the profiler. Depending on the phone's specs, you should see a huge difference in CPU usage.

As you can see, higher resolutions increase the amount of work required. You should start with a low Lightmap Resolution (between 5 - 10) and scale it up or down as needed for your scene. Increasing the Lightmap Resolution will result in a large increase in size with each iteration.

For example, lowering the Lightmap Resolution from 15 to 12 reduces the number of lightmaps required from 7 to 4, as shown in the screenshot below.

2. Lightmaps and Global Illumination

Using static lighting is crucial when developing applications for mobile devices. Static lighting runs faster on mobile devices, resulting in a better user experience. Static lighting information on non-moving objects can be preserved through a process called baking, where Unity performs lighting calculations and saves the results before runtime.

In contrast, non-static lighting (such as dynamic or realtime lighting) is calculated and updated every frame. While this can increase the realism and immersion of a scene, it comes at a much higher cost. Therefore, when using non-static lighting, it is important to balance aesthetic goals with performance. 2. Bake Lighting Lighting is one of the most important aspects of real-time 3D visual effects. It sets the mood, guides interactions, and defines goals and objectives. In this project, we will introduce and compare the differences between various lighting and lighting modes that can be used in 3D mobile applications.

Lighting - Overview

In this tutorial, we'll briefly discuss why good lighting is important in 3D mobile applications and the learning objectives for this project.

1 Overview

Lighting is one of the most important aspects of real-time 3D visuals. It sets the mood, guides interactions, and defines goals and objectives. Lighting can also make or break the user experience. A good lighting technique can bring a simple model to life, while a poor lighting technique can take away a detailed model. In this project, you will:

  • Learn about and compare static and dynamic lighting.

  • Learn how to perform the visual effects you want, such as faking lighting/shadowing, while maintaining optimal performance.

  • Compare different lighting modes and light types to achieve the most efficient and accurate lighting for your 3D scene.

2. Description of the rendering pipeline

When creating a mobile application, it's very important to ensure that your final product runs smoothly on as many devices as possible. Unity's Universal Render Pipeline (URP), a pre-built programmable rendering pipeline tuned for mobile performance, is packed with features to help your mobile app perform at its best. For more information on URPs, see the Unity documentation .

In the next tutorial we'll cover the different light types and modes available in Unity.

Lighting Modes and Types

In this tutorial we'll compare the lighting modes and types available in Unity and their pros and cons.

1. Lighting mode

In Unity, there are several different lighting modes to choose from. These modes relate to the mobility of light sources and how they are used in the scene. The various modes vary in performance, so this is an important consideration when implementing lighting. In this tutorial, we'll explore the pros and cons of three different lighting modes: baked, mixed, and real-time.

2. Bake lighting

The baked lighting mode provides static lighting, that is, it does not change during runtime. Baking is the process of storing lighting data in texture maps before running the game. There are the following important notes about baking lighting modes:

  • Lighting and shadows are baked into lightmaps, so cannot be modified at runtime. This processing is done when lighting is created in Unity, so it does not affect runtime performance.

  • Shadows are static and can appear weird if there are dynamic or moving objects during gameplay.

  • Baked lighting models are the least computationally expensive method we've discussed in this guide.

3. Real-time lighting

Realtime lighting mode provides dynamic or movable lighting. The main features of the real-time lighting mode are as follows:

  • Dynamic lighting and shadows are not baked into lightmaps and can be modified at runtime.

  • Realtime lighting mode is the most computationally expensive lighting mode that we discuss in this guide.

4. Mixed lighting

Mixed lighting modes combine static lights with moving objects. Think of it as a hybrid of the other two approaches. The main features of the mixed lighting mode are as follows:

  • Provides dynamic direct lighting and shadows.

  • Light sources of mixed lighting types can participate in the lightmap baking process of static objects.

  • Light sources affect dynamic objects, including casting shadows on those objects.

  • Intensity can be changed at runtime and only direct lighting is updated.

  • Mixing lighting modes is a computationally expensive method.

5. Real-time light source and light source type

When building 3D mobile applications, try to handle all lighting with baked lighting, light probes, and material effects. When you need to use real-time lights, you must consider the type of real-time lights you want to use. There are differences in the computational cost of the various types:

  • Directional light: Directional light emits in all directions without attenuation. It is the lowest-cost real-time lighting. Usually only one directional light is needed as it can light the whole scene. This means that when forward rendering, Unity will always render a directional light. This is true even if there are no directional lights in the scene.

  • Point Light: A point light is located at a point in space and emits light evenly in all directions.

  • Spotlight: Spotlights cull more objects than spherical point lights, so they are the second cheapest realtime lighting type. Limits the cone width so that it only illuminates selected objects for best performance.

Using spotlights and point lights may seem stylish, but it also affects performance. Directional lights, by contrast, are computationally inexpensive and illuminate all areas. Spotlights should be used for small areas and point lights for large areas, taking into account their impact on performance. Shadow calculations are probably the most expensive part of lighting calculations, casting rays in all directions increases the amount of computational power that shadow calculations take. Dynamic lights are expensive to render and should not be used in mobile games. Sometimes 3D engines limit their use depending on the device and graphics API used. For example, in the Unity Universal Render Pipeline forward renderer, you can only use up to 8 lights per object (with OpenGL ES 2.0, the limit is 4 lights).

6. Summary

Lighting is an important part of 3D visualization, but there are performance implications to consider before placing lights in your scene. In the next tutorial we'll cover best practices for generating lighting on static objects.

Lighting for Static Objects

In this tutorial, we'll discuss the importance of lighting for static objects, and the application of lightmaps and global illumination.

1 Overview

Using static lighting is crucial when developing applications for mobile devices. Static lighting runs faster on mobile devices, resulting in a better user experience. Static lighting information on non-moving objects can be preserved through a process called baking, where Unity performs lighting calculations and saves the results before runtime.

In contrast, non-static lighting (such as dynamic or realtime lighting) is calculated and updated every frame. While this can increase the realism and immersion of a scene, it comes at a much higher cost. Therefore, when using non-static lighting, it is important to balance aesthetic goals with performance.

2. Lightmaps and Global Illumination

Baking produces individual textures called lightmaps, which store information about how lighting will look. This information is cached so there is no additional performance cost at runtime. When building applications for mobile platforms, you should bake as much information as possible into your lightmaps.

Pre-baked lighting cannot be adjusted to the dynamic aspects of the scene. However, baked lighting includes global illumination for all static elements in the scene, which allows each static element to emit and receive indirect bounce light, making lighting more realistic.

The image below shows a fully baked scene:

Unity makes baking lighting extremely easy. You must perform the following two steps beforehand:

1. Click on the game object containing the light component you want to toggle. Set Mode to Mixed or Baked.

对于移动平台,请尽可能选择 Baked 而不是 Mixed,因为 Baked 是代价最低廉的选项。

2.将接收烘焙光照的游戏对象标记为 Static:

可以向一个对象标记多个静态标记,但通常的做法是在设置中选择 Everything。当将一个对象标记为 Static 时,Unity 就知道要在烘焙过程中包括该对象。

(注意:如果为某个对象启用了 Batching Static,你将无法移动该对象或对其进行动画处理。这是另一种优化,应尽可能保持开启。)

请记住,在烘焙光照时,是基于开始烘焙时处于活动状态的场景保存数据的。将生成一个与活动场景同名的文件夹。烘焙光照的所有组件和数据都存储在该文件夹中。如果你的项目使用了多个同时加载的场景,则每个场景都需要单独烘焙光照。如果调整了场景中的光照或对象,则需要重新烘焙光照才能使更改生效。下图显示了一个包含主场景光照数据的文件夹的示例。

3.优化光照贴图

配置要烘焙的光照后,还应确保已优化烘焙光照贴图。

光照贴图的大小取决于烘焙时使用的设置。在移动平台上最好尽量减少内存使用,因此请密切注意光照贴图的大小。在下面的示例图像中,可以看到 7 个 1024x1024 像素的光照贴图。

在地图的预览中,可以看到其网格,其中突出显示了选定的网格。

Lightmapping Settings (Windows > Rendering > Lighting Settings) 中的以下选项和实际地图的大小决定了使用的内存量。

4.光照贴图

Unity 的 Lightmapper 提供了三种不同的方法来烘焙场景中的光照:

  • Enlighten(自 Unity 2019 LTS 起弃用,但仍可使用)

  • 渐进式光照烘焙(CPU)

  • 渐进式光照烘焙(GPU)

下图显示了这些选项:

你应该在任何项目中使用其中一个渐进式光照烘焙。渐进光照贴图以增量方式创建光照贴图,因此可以节省时间。如果选择了 Prioritize View,将优先处理 Scene 视图中的区域。为场景设置光照时,Prioritize View 可加快迭代速度。

CPU 与 GPU 渐进光照贴图的主要区别在于光照贴图是由 CPU 生成还是由 GPU 生成。结果是一样的,但如果你拥有性能强大的 GPU,则渐进 GPU 可能会快得多。可在此处找到更多关于 GPU 选项的要求和设置。

5.纹素

纹素(也称作纹理元素)是纹理贴图中的单个像素。纹素在光照贴图中光线命中某个对象的每个点处存储光照信息。可以通过计算纹素的数量来衡量烘焙光照所需的工作量。了解什么是纹素以及纹素如何影响光照质量、烘焙的计算时间、磁盘存储和 VRAM 成本非常重要。

为尽量减少所需的光照贴图数据量,应在 Lightmapping Settings 中调整每个烘焙单位的纹素数量。通过这些设置,你可以控制光照贴图,包括每个对象在烘焙中使用多少个纹素,如示例图像所示。

Lightmapping Settings 还包括一个名为 Lightmap Resolution 的选项。该选项决定了光照贴图中每个单位使用的纹素数量。要查看场景中纹素的布局,请执行以下操作:

  • 在 Scene 视图的左上角,单击 Shading Mode 下拉选单。

  • 找到并单击 Lightmap Indices。

已烘焙的对象将被置于棋盘格中。这就是烘焙光照时纹素的分布情况。下面的屏幕截图显示了一个立方体采用不同的 Lightmap Resolution 设置时的情况。左侧图像的设置为 1,中间图像的设置为 2,右侧图像的设置为 5。

可以看到,更高的分辨率会增加所需的工作量。应从较低的 Lightmap Resolution(5 - 10 之间)开始,然后根据场景需要进行放大或缩小。增加 Lightmap Resolution 会导致每次迭代时大小大幅增加。

例如,将 Lightmap Resolution 从 15 降低到 12,可将所需的光照贴图数量从 7 个减少到 4 个,如下面的屏幕截图所示。

6.纹素使用量

虽然可以使用 Lightmapping Settings 设置场景中的纹素数量,但你可能还想减少某些对象的纹素数量。

通过 Unity,你可以控制每个对象可以使用的纹素数量。进入对象的 Mesh Renderer (Inspector > Mesh Renderer),可以看到一个名为 Scale In Lightmap 的参数。调整该设置可更改对象在光照贴图中使用的纹素数量。

在下面的屏幕截图中,左侧是一个为每个烘焙单位获取 5 个光照信息纹素(因为 Lightmap Resolution 设置为 5)的普通对象。右侧是一个 Scale In Lightmap 设置为 0.5 的盒体:

右侧盒体的光照贴图占用的空间要远小于左侧盒体。在下面的屏幕截图中,可以看到 Mesh Renderer 组件中可用的光照贴图设置。

请尽量避免在以下元素上使用纹素:

  • 用户看不到的表面和对象。这可避免浪费内存存储更大的光照贴图,换来的却是屏幕上看不到的细节。

  • 光照变化不大的表面,如阴影中的对象或单一光线命中的对象。

  • 小或薄的对象。小或薄的对象接收的光照量不会给场景的最终渲染增色多少。

7.LOD 和光照贴图

在模型上使用细节级别 (LOD) 会影响到烘焙光照。LOD 组中只有最详细的模型会获得光照,就像它是一个静态对象一样,而该组中的其他模型都将获得动态光照。对于直接/间接光照和实时全局光照,将使用不同的光照贴图。

使用 Enlighten 光照贴图时,系统将只烘焙直接光照。要对间接光照进行采样,必须在场景中使用光照探针。

以下图像是 LOD 模型的一些示例。请注意,由于未在场景周围放置光照探针,只有第一张图像中的 LOD 0 模型获得了正确的光照。第二张图像是使用 LOD 的模型的示例,它通过光照探针获得了正确的光照。

为确保正确地对 LOD 模型进行烘焙光照处理,必须在 Static 复选框旁边的下拉菜单中将 LOD GameObject 标记为 Contribute GI。

8.总结

使用光照贴图存储静态对象的光照数据是优化 3D 美术的重要组成部分。在下一个教程中,我们将讨论光照探针如何为移动对象和具有 LOD 的对象提供更逼真的烘焙光照条件。

光照探针

在本教程中,我们将讨论光照探针在 3D 移动应用程序中的最佳用例。

1.光照探针用例

光照探针有两个主要用途:

  • 第一个用途是为场景中的移动对象提供高质量的光照(包括间接反射光)。

  • 第二个用途是在静态景物使用 Unity 的细节级别 (LOD) 系统时提供该景物的光照信息。

光照探针与光照贴图具有很多相同的优点,因为它们都能用于存储在运行游戏前就计算好的光照数据。光照贴图对场景中的表面在给定纹素处接收到的光照进行编码时,光照探针会存储穿过空白空间的光。然后,该数据可用于照亮动态对象,这有助于在视觉上将它们与整个场景中的光照贴图对象融合在一起。光照探针仅存储静态场景的光源和阴影信息。这是因为光照探针是预先烘焙的。它们不是从动态对象、实时光源或自身阴影创建光照的解决方案。尽管如此,光照探针仍可为场景提供大部分光照下面的屏幕截图显示了一个使用光照探针的示例。

有关在场景中实现光照探针的更多信息,请参阅 Unity 文档。

2.总结

光照探针是一种捕获静态场景光照并在运行时将数据应用于移动对象的简单方法,它的成本要低于实时全局光照。在下一个教程中,我们将讨论在 3D 移动应用程序中渲染阴影的最佳实践。

阴影

在本教程中,我们将讨论实现和优化阴影的替代方法。

1.实现伪阴影

真实阴影的渲染计算成本很高。我们建议在动态对象上实现伪阴影,而不要使用动态光照。实时阴影通常通过阴影贴图技术生成。渲染到阴影贴图的场景几何体的成本与绘制到其上的顶点数量相当。考虑到成本,限制场景中的阴影投射几何体数量以及实时阴影投射光照的数量非常重要。下面是实现伪阴影的一些方法:

  • 使用放置在角色下方的 3D 网格、平面或四边形,并对其应用模糊的纹理。

  • 编写自定义着色器以创建更复杂的模糊阴影。

下面的屏幕截图显示了使用阴影网格的阴影实现。

将光照信息直接绘制到纹理上不失为一个好方法。这样做可减少实时光照所需的额外计算。当在场景中烘焙光照时,绘制的光照还可以节省内存,因为场景需要较少的纹理存储光照贴图。

尽可能使用着色器或材质模拟光照。可以使用自定义材质模拟不同类型的光照效果。例如,你可能希望角色具有边缘光照,以提高其可见性和视觉效果。对于这种情况,可以使用着色器营造光照错觉,而不是使用光源创造这种效果。

2.网格渲染器(Mesh Renderer)组件设置

不管场景使用何种光照,都必须确保正确设置网格渲染器。

一个良好的原则是关闭一切不打算使用的设置。例如,Cast Shadows 等设置可能会增加渲染场景的成本,即使对象没有光照也是如此。下面的屏幕截图显示了一个网格渲染器设置的示例:

屏幕截图中显示的选项设置为通过混合最近探针的光照信息来接收光照,但不接收反射。我们使用的是 Blob 方法,因而关闭了 Cast Shadows。场景是烘焙的,没有任何对象投射实时阴影,因此也没有选中 Receive Shadows。

3.总结

阴影可以为 3D 环境增加真实感,但在运行时的计算成本很高。在移动设备上,最好尝试使用着色器、纹理或其他不依赖阴影投射光照的方法伪造阴影。在下一个教程中,我们将深入剖析一个光照演示,以展示烘焙光源可能带来的性能提升。

演示:光照烘焙

最佳做法是尽可能确定 3D 移动应用程序中的静态对象,以便正确、有效地照亮它们。在本演示中,我们将比较烘焙和非烘焙光照的性能。

1.概述

在上一个教程中,你了解了在 3D 场景中实现烘焙光照的好处。在本演示中,你将剖析两个示例场景,并比较烘焙与非烘焙光照的性能差异。

2.开始之前

请在此处下载包含示例演示的课程项目。当弹出提示时,单击 Lighting Demo - Non-baked 或 Lighting Demo - Baked。

也可以在 Project 视图中打开示例场景(Assets > 4 Lighting > Scene > Lighting_Baked 或 Assets > 4 Lighting > Scene > Lighting_Unbaked)。下载并打开后,可以在编辑器中进入运行模式,也可以将该场景构建到移动设备上以在性能分析器中进行性能分析。

3.要观察的内容

如上一个教程中所述,Unity 引擎提供了三个生成光照贴图的选项 - Enlighten、Progressive CPU lightmapper 和 Progressive GPU lightmapper。在本项目中,我们选择使用渐进 CPU 光照贴图,因为 Enlighten 即将弃用,而渐进 GPU 光照贴图还处于预览阶段。

使用渐进 CPU 光照贴图实现烘焙光照时,可在处理光照信息时节省 CPU 周期。因此,你可能会发现每秒帧数 (FPS) 大幅增加,而 CPU 使用率却出现下降。在测量两个场景的 FPS 时,你应会在 Statistics 窗口中看到明显的差异。

移动设备能够真正体现这种差异。将示例场景构建到你选择的手机上,对两个场景进行性能分析,同时在性能分析器的 Global Illumination 部分中观察 Total CPU 图。根据手机的规格,你应会看到 CPU 使用率存在巨大差异。

(注意:虽然我们选择了渐进 CPU 光照贴图,但我们鼓励你试用渐进 GPU 光照贴图并进行性能分析。根据系统 GPU 的不同,性能可能会有所差异。)

4.总结

光照可以强调移动应用程序中可能会被忽略或不被重视的特征。在做出光照决策时,请明智地选择静态和非静态光照,该选择将决定你的应用程序能否达到预期以及能否在目标设备上有效执行。

Guess you like

Origin blog.csdn.net/Kaitiren/article/details/129683287