---
title: "【光照】渲染路径与光源类型"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/rendering-paths-light-types/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/05-游戏图形与运行时/渲染基础/【光照】渲染路径与光源类型.md"
content_hash: 40a8e72b1ca4657df5a033c6a9f64943e520511b6978a2cca2a90e5deaf6217c
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# 【光照】渲染路径与光源类型

> 创建时间：2021/3/12 19:53

  * 【光照】渲染路径与光源类型
    * 渲染路径
      * 前向渲染路径
        * Unity的光照处理方式
        * RenderMode Tag
          * Bass Pass
          * Additional Pass
        * 可以使用的光照变量和函数
        * 缺点
        * 实际渲染过程
      * 延迟渲染路径
        * 特点
        * 局限性
        * Unity G-buffer
        * 可访问变量和函数
      * 顶点照明渲染路径
      * Comparison
    * Unity的光源类型
      * 平行光
      * 点光源
      * 聚光灯

## 渲染路径

A rendering path is a series of operations related to lighting and shading.

### 前向渲染路径

```cpp
string s = String.Empty;

```

如果物体在n个逐像素光源的影响区域内,那么该物体需要执行n个Pass,每个Pass计算逐像素光源的光照结果,然后在帧缓冲中把这些光照结果混合起来得到最终的颜色值。

#### Unity的光照处理方式

在Unity中前向渲染有三种处理(即照亮物体)的方式： **逐顶点处理** 、 **逐像素处理** 、 **球谐函数(SH)** 处理。

根据光源设置以及光源对物体的影响程度(该物体的远近、光源强度等),按照重要程序对光源进行排序

  * 一定数目的光源进行逐像素方式处理

    * 最亮的平行光

    * Light Component -> 渲染模式(Render Mode) == Important

  * 最多四个光源按逐顶点方式处理

    * Not Important

  * 剩下就使用最差的SH方式处理

    * Not Important

如果以上规则得到的像素光源数量效于Quality Setting中的逐像素光源数量(Pixel Light Count)，会有更多的光源逐像素处理

#### RenderMode Tag

告诉Unity该Pass在渲染路径中的位置，引擎会据此进行一些相关计算并填充一些内置变量。

一个Unity Shader通常会定义一个Base Pass（ Base Pas 也可定义多次， 例如需要双面渲染等情况）以及一个 Additional Pass。

  * 一个 Base Pass仅会执行 一次

  * 每个逐像素光源会执行一次Additional Pass

##### Bass Pass

`# pragma multi_compile_fwdbase`

> 使用编译指令，才可以在Pass得到一些正确的变量，如光照衰减值等

计算——一个 **逐像素** 的 **平行光** \+ 所有逐顶点和SH光源。只计算一次。

可实现的光照效果：

  * **光照纹理**

  * 环境光

  * 自发光

  * 阴影（平行光的阴影）

##### Additional Pass

`# pragma multi_compile_fwdadd`

计算——其他影响该物体的逐像素光源，每个光源执行一次Pass

  * 默认情况下没有阴影效果

  * 可以使用`#pragma multi_compile_fwdadd_fullshadows`代替`# pragma multi_compile_fwdadd`，为点光源和聚光灯开启阴影效果

  * 设置混合模式`Blend One One` \- 每个Additional Pass可以与上一次计算的结果在帧缓存中叠加。(若不开启，会覆盖之前的结果)

#### 可以使用的光照变量和函数

![Alt text](/media/ae73ac39e886b7e27850.png)

![Alt text](/media/d936d98091ee5b54ede8.png)

![Alt text](/media/d5e2bce3c4bda73ec891.png)

![Alt text](/media/9e130b8548e4e403ec37.png)

#### 缺点

当场景中包含大量实时光源时，前向渲染的性能会急速下降。

每个物体多个Pass，每执行一个Pass都需要重新渲染一遍物体，很多计算是重复的。

#### 实际渲染过程

![Alt text](/media/412635250664c91ae5fb.png)

  1. 清除颜色、深度和模板缓冲，为后面的渲染做准备

  2. 利用Base Pass，将平行光的光照渲染到Frame Buffer中

  3. 使用Additional Pass，依次将4个点光源的光照应用到物体上，得到最后的渲染结果。

渲染点光源的顺序——按照重要程度排序，因素有:

  * 颜色

  * 强度

  * 距离
Unity具体的做法没有官方说明

### 延迟渲染路径

G-buffer (Geometry buffer) - 存储了我们所关心的表面（离摄像机最近的表面）的其他信息（法线，位置，视角方向，用于光照计算的材质属性等）。

两个Pass：
Pass1 - 不进行光照计算，仅仅计算片元的可见性（深度缓冲技术），可见片元的信息存储到G-buffer。

Pass2 - 利用G-buffer中的片元信息进行真正的光照计算。

```cpp
string s = String.Empty;

```

#### 特点

效率不依赖于场景的复杂度，而是和屏幕空间的大小有关（决定缓冲区的大小，缓冲区实质上就是一张张2D图像）

适用于场景中光源数目很多，使用前向渲染会造成性能瓶颈的情况下。

#### 局限性

  * 不支持真正的抗锯齿（anti-aliasing）

  * 不能处理半透明物体

  * 显卡要求

    * 必须支持MRT（Multiple Render Targets）

    * Shader Mode 3.0及以上

    * 深度渲染纹理

    * 双面的模板缓冲

#### Unity G-buffer

默认包含以下几个渲染纹理(RenderTexture)

  * RT0 - ARGB32 - 漫反射颜色(A不使用)

  * RT1 - ARGB32 - 高光反射颜色 - A存储高光反射的指数部分

  * RT2 - ARGB2101010 - RGB存储法线(A不用)

  * RT3 - ARGB32(非HDR) or ARGBHalf(HDR) - 存储自发光 + lightmap + 反射探针(reflection probes)

  * 深度缓冲(Z-buffer)

  * 模板缓冲(stencil buffer)

#### 可访问变量和函数

UnityDeferredLibrary.cginc

![Alt text](/media/df38a620876c54d2432d.png)

### 顶点照明渲染路径

  * ForwardPath的一个子集，Unity只会填充一些逐顶点相关的光源变量

  * 最快速

  * 硬件支持最广泛

  * 最多访问到8个逐顶点光源

![Alt text](/media/529c2681cd83cc31c767.png)

![Alt text](/media/6656a93d65d0ed209543.png)

### Comparison

![Alt text](/media/09d77a997f88674ab0b8.png)

## Unity的光源类型

  * 平行光(directional light) - 没有位置，没有衰减

  * 点光源(point light)

  * 聚光灯(spot light)

  * 面光源(area light)

> 光源属性
>
>   * 位置
>
>   * 方向（到某点的方向）
>
>   * 颜色
>
>   * 强度
>
>   * 衰减 (attenuation)到某点的衰减）
>
>

### 平行光

  * 方向 - _WorldSpaceLightPos0

  * 颜色和强度 - _LightColor0 (已经是相乘后的结果)

  * 衰减 - 没有衰减(attenuation = 1.0)

### 点光源

Range - 半径
Position
颜色
强度
衰减

### 聚光灯

空间中的一块锥形区域定义，表示由一个特定位置出发，向特定方向延伸的光

  * Range

  * Spot Angle

  * Position
