Unity Graphics (Unity 图形渲染 ) 官方教程文档笔记系列之六

时间:2024-04-04 14:55:15

Unity Graphics (Unity 图形渲染 )
- Everything for Lighting and Rendering in Unity
- 主要涉及到光照与渲染方面的知识

本文档主要是对Unity官方教程的个人理解与总结(其实以翻译记录为主:>)
仅作为个人学习使用,不得作为商业用途,欢迎转载,并请注明出处。
文章中涉及到的操作都是基于 Unity2017.3版本
参考链接:https://unity3d.com/cn/learn/tutorials/s/graphics


下面是将要介绍的章节,黑体是本次内容:

  • Introduction to Lighting and Rendering
    介绍光照和渲染
  • Precomputed Realtime GI (Realtime Global Illumination)(6)
    预处理实时全局光照(6)
  • Rendering and Shading
    渲染与着色
  • Cameras and Effects
    相机与效果
  • Geometry in Unity
    几何体

1.Introduction to Precomputed Realtime GI

1.预计算实时全局光照的介绍

In Unity, there are two distinct techniques available for precomputing global illumination (GI), or bounced lighting. These are Baked GI and Precomputed Realtime GI. This tutorial focuses on Precomputed Realtime GI.

When working with Precomputed Realtime GI, a lighting precompute is the process of calculating the bounce of light around the static geometry within a Scene in the Unity Editor and storing this data for use at run time. This process reduces the number of lighting calculations that must be performed at run time, allowing realtime bounced lighting while maintaining interactive framerates.

When using Baked GI, traditional lightmap textures are generated offline during the precompute process. These textures then exist as assets within the project and cannot be changed at run time. Precomputed Realtime GI does not create lightmap assets in the same way. Instead, lighting data is saved as a Lighting Data Asset which contains the information needed to generate and update a set of low resolution lightmaps interactively, at run time.

Unless our Scene has been properly prepared and optimized, the time it takes to complete these calculations can become excessive. In this tutorial, we will learn how to optimize a Scene for Enlighten (the backend for Unity’s Precomputed Realtime GI and Baked GI solutions) so that lighting precomputes take minutes rather than hours.

Unity中有两个不同的有效技术处理预计算全局光照,或称为碰撞/反弹光照。名字是:烘焙GI与预计算实时GI.这篇教程只讨论预计算实时GI。
当预计算实时GI工作时,一个光照预计算是Unity编辑器中场景静态几何体的光照碰撞的处理和存储这些数据用于运行时。这个处理减少了大量的一定会影响运行时性能的光照计算,允许实时碰撞光照同时保持合理的帧率。
用烘焙GI时,传统的光照图在预计算处理中离线生成。然后这些贴图存储为项目资产,在运行时不可改变。预计算实时GI并不创建光照图资产。相反,光照数据被存储为一个光照数据资产。此资产包括在运行时用于生成和更新的一系列低分辨率光照图信息。
除非我们的场景有合理的准备和优化,否则它完成这些计算将会花费过高。这个教程,我们将学习如何用启蒙系统优化场景,让光照预计算花费几分钟而不是几小时的时间。启蒙系统是Unity的预计算实时GI和烘焙GI解决方案的后台系统。

Over the course of the document we will cover:

  • How to determine an appropriate lighting resolution for our Scenes.
  • What Charts are and how they affect our precompute times.
  • How to start the precompute process.
  • Using probe lighting to reduce the complexity of our lighting
    solution.
  • Improving auto-unwrapped UVs generated by Unity’s Precomputed
    Realtime GI.
  • What Clusters are and how they are used to generate globally
    illuminated lighting.
  • Using Lightmap Parameters to fine-tune our lighting on a per-object
    basis.

Once we have learned and applied these techniques, we can leverage the benefits of using Precomputed Realtime GI: fast lighting iteration times, the ability to experiment more rapidly during the lighting process and realtime bounced lighting during gameplay.

这个文档的覆盖课程如下:

  • 如何决定一个合理的光照解决方案
  • 什么是“图表”和它们是如何影响到我们的预计算时间
  • 如果开始预计算处理
  • 用光照探头去减少我们光照解决方案的复杂性
  • 用Unity的预计算实时GI提高自动展开UV的生成
  • 什么是“集群”和它们是如何用于生成全局光照效果
  • 基于每个对象用光照图参数去微调我们的光照效果

一旦我们学习和应用了这些技术,我们可以利用预计算实时光照的优势:快速的光照效果生成迭代时间,在光照处理和运行时实时碰撞光照性能更快。

Reducing precompute times from hours to minutes

预计算从小时级减到分钟级

In the Lighting Tutorial Scene used for this tutorial, precomputing the lighting with a default, non-optimized setup took around 7.5 hours on our test machine. For a Scene of this complexity, clearly this is unacceptable.

本教程的光照教程场景,预计算光照默认未优化前在测试机上花费7.5小时。对于这类复杂度的场景,很明确这是不可接受的。
Unity Graphics (Unity 图形渲染 ) 官方教程文档笔记系列之六
Default Scene: Precompute took 7.5 hours. Optimized Scene: Precompute took 2.25 minutes.
默认场景:预计算花费7.5小时。优化后的场景:预计算花费2.25分钟。

Following around 30 minutes of Scene preparation using the techniques covered in this tutorial, the precompute time was 2.25 minutes for a production-quality result. Considering that we can rapidly iterate on Scene lighting without needing to re-calculate GI and change GI lighting during gameplay, the attractive benefits of this technology are quickly apparent.

在使用本教程所介绍的技术进行大约30分钟的场景准备之后,此种生产质量结果下预计算时间为2.25分钟。考虑到我们运行时可以快速迭代场景光照而不需要重复计算GI和改变GI光照,这个技术的吸引力将更为明显。

Downloading assets for this tutorial

下载关于本教程的资源

Throughout this tutorial we will be referring to the Lighting Optimisation Tutorial project available from the Unity Asset Store.

  • In this written tutorial, we will be using the example Scenes
    contained within the Scenes/Article folder: LightingTutorialOptimal,
    LightingTutorialNonOptimal and LightingTutorialStart.
  • LightingTutorialOptimal has been set up according to this tutorial
    and is intended to represent an example of how production-ready
    lighting results can be achieved with minimal precompute time using
    Unity’s Precomputed Realtime GI.
  • LightingTutorialNonOptimal reflects a lot of the common problems we
    see in projects that either don’t finish baking, or take an
    unacceptably long time. This is a good reference for how Scenes
    should not be configured.
  • LightingTutorialStart will be the Scene which we are working with
    throughout this tutorial. As we follow the steps laid out in this
    tutorial, we will take this Scene to a completed, production-ready
    result.

在本教程中,我们将引用Unity Asset Store(资源商店)中提供的光照优化教程项目。

  • 本教程,使用的示例场景,目录为Scenes/Article,包括 LightingTutorialOptimal,LightingTutorialNonOptimal,LightingTutorialStart场景。
  • LightingTutorialOptimal 可由本教程建立,目的是为了呈现一个产品准备好的示例,用Unity的预计算实时GI时间最小化。
  • LightingTutorialNonOptimal 反映出大量常见的问题,或者无法完成烘焙,或者有一个不可接受的时间花费。这是一个场景不应该被配置的好示例。
  • LightingTutorialStart 是一个我们将要在此工作的场景。接下来步骤中,我们会慢慢完成此场景,变成产品可用的结果。

2.Realtime Resolution

实时分辨率

When setting up a Scene for lighting using Precomputed Realtime GI, one of the first decisions that needs to be made is to determine your Scene’s default Realtime Resolution. Realtime Resolution is the number of realtime lightmap texels (texture pixels) used per world unit.

Realtime Resolution can be observed or set in the Lighting window, as follows:

  • Open the Lighting window (Window > Lighting) and then select the
    Scene tab.
  • Ensure Precomputed Realtime GI is enabled by checking the Precomputed
    Realtime GI checkbox.
  • Observe the Realtime Resolution property beneath the Precomputed
    Realtime GI checkbox.

当建立一个使用预计算实时GI的场景,首先要决定的是:场景默认实时分辨率。实时分辨率是每世界空间单位的光照图素的数量。
实时分辨率可查看或设置在光照窗口中:

  • 打开光照窗口(【Window > Lighting】),然后选择 场景(Scene ) 页签。
  • 检查预计算实时GI复选框被勾选,确保预计算实时GI被开启。
  • 查看预计算实时GI复选框下的实时分辨率(Realtime Resolution)属性,Unity2017.3为indirect Resolution。
    Unity Graphics (Unity 图形渲染 ) 官方教程文档笔记系列之六
    Unity’s Lighting window showing the Scene’s global Realtime Resolution setting.
    Unity的光照窗口的场景全局实时分辨率设置。

Choosing an appropriate Realtime Resolution

选择一种适当的实时分辨率

When setting up a Scene it is important to have some idea of the unit scale your project will need. It could be that in your project a unit is a meter, a foot or a centimeter. Unity units do not have a default equivalence in real world scale so it it down to the user to decide what a unit represents.
在建立场景时,有清楚的单位大小是比较重要的。可能是一米,一英尺,或一厘米。Unity的单位在现实世界中没有默认的对等,所以它由用户来决定一个单位代表什么。

In our example project we have decided that a unit is equivalent to 1 meter. Certain physics concepts assume the same. For example, gravity is represented in units per second as a default in Unity. Assuming that a unit is equivalent to 1 meter is therefore a good setup for a real world game scenario.
示例项目决定一单位为1米。某些物理概念也假设为此。比如,重力被表示为每秒多少米作为默认单位。假设单位是1米,因此容易建立一个真实世界游戏剧本。

Often your Scene’s Realtime Resolution can be determined from the scale of your game world. For example, is your Scene a small, but richly populated indoor environment with a lot of variance in the bounced lighting? In this case, higher lightmap resolutions such as 2-3 texels per unit might be justified in order to capture this more detailed or ‘high-frequency’ lighting.
一般场景实时分辨率可以是游戏世界的缩放。比如,场景小,但室内内容丰富,有很多种类可以碰撞光照。这样,更高的光照分辨率如每单位2-3的图素可能更适合,它可以捕获更多细节或“高频率的”光照。

Perhaps your Scene is a large outdoor environment where the world scale is considerably bigger. You might have surfaces that are hundreds or even thousands of units in area with little variation to modify the color of bounced light. In cases such as these, a resolution which is appropriate to capture the intricate lighting details present in an indoor Scene would be wasteful when applied across the large and less featured expanses of an outdoor environment. We would be wasting valuable CPU time and available memory by having to store and update lightmap texels which aren’t contributing much to the overall look of the Scene. More importantly, for the purposes of this tutorial, we would be increasing the number of lightmap texels that must be considered during the lighting precompute. This can have a huge impact on precompute times.
场景比较大的室外,世界规模也比较大。可能一百或上千单位对光照碰撞颜色更少的调整。这样,适用室外捕获更多的光照细节的分辨率用于大而较少特征广阔的区域有些浪费。这将会浪费有效的CPU时间和用于存储和更新对场景总体效果影响不大的光照图素的内存。更重要的是,本教程的目的,在增加预计算时要考虑光照图素的数量。这会对预计算时间有极大的影响。

In the case of an outdoor environment, an appropriate lightmap resolution might be be somewhere between 0.5 -1 texels per unit for large objects within the Scene, or 0.1 - 0.5 texels for the terrain.
室外环境的示例中,对场景中的大物件一个合理的光照分辨率可以在0.5-1图素每单位,或者对地型可以0.1-0.5图素。

Precomputed Realtime GI Resolution vs. traditional lightmaps

预计算实时GI解决方案 vs 传统光照图

The Realtime Resolution values needed by Unity’s Precomputed Realtime GI are orders of magnitude less than ‘traditional’ lightmap texel densities. This is because we are only capturing indirect lighting in these lightmaps, and this tends to be very soft or ‘low frequency’. When using Precomputed Realtime GI, crisp shadows will usually be provided by realtime shadows rather than high resolution lightmaps.

Using values which may seem appropriate in traditional lightmapping techniques - say 30 texels per unit - will likely result in precomputes failing or otherwise not completing. More suitable values are around 2 - 3 texels per unit for indoor Scenes, and 0.5 - 1 for outdoor environments. This is assuming that we are working with a human scale Scene with a unit size of 1 unit = 1 meter. If the world scale was substantially different, these values would need to be adjusted accordingly.

Unity预计算实时GI所需的实时分辨率值比传统的光贴图贴图密度要小。这是因为我们只需要捕捉间接光照到光照图上,这往往是非常平滑的或者是“低频”。在使用预计算实时GI时,洒落的阴影经常被实时阴影提供,而不是高分辨率的光照图。
看似用传统光照图技术,每单位30图素,在预计算可能导入失败或无法完成。在室内2-3个图素每单位更合理一些,0.5-1对室外环境。这是建立在我们以人类尺寸一个单位大小是1米的条件下。如果世界尺寸是大幅度不同,那么这个分辨率也要相应调整。

Scenario Realtime Resolution
Indoor 2 - 3 texels per unit
Outdoor 0.5 - 1 texels per unit
Terrains 0.1 - 0.5 texels per unit

Appropriate values assuming a human-scale world with 1 unit representing 1m.

情境 实时分辨率
室内 2 - 3 图素每单位
室外 0.5 - 1 图素每单位
地型 0.1 - 0.5 图素每单位

假设人类世界单位以米为尺寸下的合理值.

When initially setting our Scene’s Realtime Resolution, we are specifying the default resolution for Static objects within our Scene. New GameObjects with a MeshRenderer marked as Lightmap Static at the top of the Inspector will use this value until otherwise modified.

In addition to choosing the Realtime Resolution for the entire Scene we also have the option to change lightmap resolution on a per-object basis. In cases where we need the extra fidelity offered by higher resolutions, we can selectively increase this value. Generally it is less work to set the most common resolution as the Scene default and then manually raise the resolution on those objects which need more lighting detail. We will discuss approaches to modifying resolution per-object later in the tutorial.

当设置好实时分辨率,我们就指定了静态对象的默认分辨率。带有网格渲染的新游戏对象被标记为光照静态会使用此值。
除了为整个场景选择实时解决方案之外,我们还可以选择在每个对象的基础上更改光映射的分辨率。如果我们需要更高分辨率的额外精度,我们可以选择性地增加这个值。一般来说,设置最常见的分辨率为场景默认值,然后手动提高那些需要更多光照细节的对象的分辨率。我们将在本教程中讨论合理地修改每个对象的分辨率的方法。

Setting our Scene’s Realtime Resolution

设置场景的实时分辨率

If you want to follow along, we will be working in the LightingTutorialStart Scene included with the Lighting Optimisation Tutorial linked at the top of this page.
如果你想要跟随,我们将会在LightingTutorialStart 场景中工作,包括在这个页面顶部链接的 照明优化教程(应该是:LightingTutorialOptimal)。

In our example Scene, we have an outdoor environment with a medium size terrain of a reasonably consistent color. For this, a low Realtime Resolution of 0.5 texels per unit would be sufficient to capture the bounced lighting from other objects in the Scene. However, there are also a number of wooden houses. These are much more detailed. As there are many more houses than there are terrain objects in the Scene, we should set the Realtime Resolution to be appropriate for the houses. We can then modify the resolution used by the terrain objects individually. This will reduce the amount of work needed when preparing our Scene. With this in mind, we are going to use a value of 1 texel per world unit for our default Realtime Resolution.
在我们的示例场景中,我们有一个中等大小地型的户外环境,它的颜色相当一致。因此,一个低的实时分辨率,每单位0.5个图素,就足以捕捉到场景中其他物体的反射光线。然而,有很多木房子,这需要更多细节。由于在这个场景中有更多的房子,我们应该设置实时分辨率,使之适合于房屋。然后我们可以单独修改地形对象使用的分辨率。这将减少在准备场景时所需的工作量。考虑到这一点,我们将使用每个世界单位的1 图素值作为默认的实时分辨率。

Open the Lighting window (Window > Lighting) and select the Scene tab.
打开光照窗口(【Window > Lighting】),然后选择场景页签。

Set the Realtime Resolution value to 1.
设置间接光分辨率(Indirect Resolution )值为1。

Given that we have decided our Scene’s scale to be 1 unit = 1m, this means that a single lightmap texel created by Unity’s Precomputed Realtime GI will be equivalent to 1x1m in size. This might seem very low, but remember that we are only capturing the indirect light. Crisp shadows and specularity from direct lighting will be provided by realtime lights in the Scene.
考虑到我们把场景尺寸设定1单位1米,那意味着被Unity预计算实时GI创建的单个光照图素等价于1*1平方米空间。这可能看起来很低,但请记住,我们只是在捕捉间接光。场景的实时灯光将提供明亮的阴影和来自直接光照的高光。

3.Understanding Charts

3.理解图表

In Unity’s Precomputed Realtime GI, a Chart is an area of a lightmap texture to which we map the lightmap UVs of a given Scene object. We can think of this as a small tile containing an image of the lighting affecting that object. A Chart is made up of two parts: irradiance (lighting) and directionality (encoding the dominant light direction).

When the Precomputed Realtime GI is generated, lighting is calculated for every texel that is included in a Chart. Large numbers of Charts in a Scene can be one of the biggest detriments to precompute times so it is important to understand how Charts work and how we can manage them in order to optimize lighting precompute times.

在Unity的预计算实时GI中,一个图表是一个光照贴图的区域,光照贴图是将一个给定场景对象的光照图UV映射到的贴图。我们可以把它想象成一个小的贴图,它包含了一个影响着那个物体的光照贴图。一个图表包括两部分:发光(照明)和定向(编码主光照方向)。
当预计算实时GI被生成后,被计算的光照中每个图素都包括在图表里。大量的图表对预计算时间是最大困难之一,所以理解图表是如何工作并为了优化光照预计算时间,如何管理它们变得更为重要。

Unity Graphics (Unity 图形渲染 ) 官方教程文档笔记系列之六
Illustration showing a UV Chart of a minimum 4x4 texel size. Lightmap UVs are always clamped to within half a texel of the outside of the Chart in order to prevent bleed caused by texture filtering.
图中显示的是一个最小的4x4 图素大小的UV图表。为了防止纹理过滤造成的影响,光照图UVs总是被夹取在图表外边沿的一半图素的纹理中。

By default, each Chart is a minimum of 4x4 texels. A Chart therefore requires a minimum of 16 texels regardless of the scale of the object within the world or the size of the corresponding UV shell. So, for example, if an object is 1x1 meter, the object has 1 Chart and our indirect resolution is 1, 16 texels are required for the object. This minimum size enables Unity to stitch Charts together for seamless lighting across geometry edges. Unity requires at least 4 texels along a Chart edge in order to uniquely identify it before the corresponding partner can be found and stitched.
默认一个图表最小4x4图素。因此,一个图表至少需要16个图素,无论世界中对象的尺寸或相应UV外形大小。因此,比如一个对象是1x1米,这个对象有一个图表,我们的间接分辨率是1,这个对象也需要16个图素。这个最小大小使Unity可无缝连接几何体边沿。Unity需要至少4个纹理沿着图表边缘,才能在找到边缝上相应的合作伙伴之前对其进行唯一的识别。(不明了)

Note that no padding is needed for realtime GI because Unity clamps the lightmap UVs to give a half texel border inside the Chart during the packing stage of the mesh import pipeline. This means that Charts can be right next to each other and still be bilinearly interpolated without cross bleeding, saving valuable lightmap space.
请注意,实时GI不需要填充,因为Unity会在网格导入管道的包装阶段夹取光照UVs到图表里的一半图素边界处。这就意味着图表可以彼此相邻,并且仍然是双线性插值而没有交叉影响,节省了宝贵的光照图空间。

Imagine the same 1x1 meter object we discussed earlier had 50 Charts. Unity would create 800 texels for the object, despite it being relatively small. This demonstrates how having a large number of Charts can quickly drive up the number of texels. More texels means more lighting calculations and more data to compute, compress and store. All of this adds up in complex Scenes and can result in lengthy precomputes and reduced performance at run time.
想象一下我们之前讨论过的1x1米的物体有50个图表。Unity将为这个对象创建800个图素,尽管它相对较小。这演示了如何使用大量的图表可以快速地提高图素的数量。更多的图素意味着更多的照明计算和更多的数据来计算、压缩和存储。所有这些添加到复杂的场景中,可能导致在运行时进行冗长的预计算和降低性能。

Inappropriate Charting is the major culprit for lighting precomputes not completing or taking too long. With this in mind, many of our obvious strategies for reducing precompute times are to reduce the number of Charts we have in our Scene.
不适当的图表是光照预计算不能完成或花费太长时间的罪魁祸首。考虑到这一点,我们许多减少预计算时间的明显策略是减少我们在场景中的图表数量。