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

> 创建时间：2021/2/23 17:59

  * 【光照】基础光照
    * 基础光照
      * 术语和概念
        * 辐照度和出射度
        * 散射(Scattering)和吸收(absorption)
        * 高光反射和漫反射
        * 着色与光照模型
        * 直接光照与间接光照
        * 其他术语
      * 光照模型
        * 标准光照模型(Blinn - Phong光照模型)
          * 自发光(emissive)
          * 高光反射(specular)
          * 漫反射(diffuse)
          * 环境光(ambient)
          * Unity中的应用
        * BRDF
    * 实践应用
      * 逐像素还是逐顶点
        * 逐像素光照(per-pixel lighting)
        * 逐顶点光照(per-vertex lighting)
      * 游戏场景中灯光照明的构成
      * lightmap
        * 光照烘焙
          * Unity场景光照烘焙步骤
    * Ref

## 基础光照

### 术语和概念

#### 辐照度和出射度

辐照度（ irradiance）—— 对于平行光L来说，可以通过计算在垂直于L的单位面积上单位时间内穿过的能量来得到。

![Alt text](/media/758e2cb62b11058b471a.png)

辐照度与物体表面光线之间的距离成反比，距离越大，强度越小。即，与d/cos成反比，与cos成正比。

出射度（exitance）——根据入射光线的数量和方向，可以计算出射光线的数量和方向。

辐照度和出射度满足线性关系，他们的比值就是材质的漫反射和高光反射属性

#### 散射(Scattering)和吸收(absorption)

散射：改变方向
吸收：改变颜色和密度

#### 高光反射和漫反射

  * 高光反射(specular) —— 我们只考虑某一个特定方向的高光反射

  * 漫反射(diffuse)—— 我们假设漫反射部分是没有方向的

#### 着色与光照模型

着色(Shading)： **根据材质属性(漫反射属性等)、光源信息(光源方向、辐照度等)，使用一个等式取计算沿某个观察方向的出射度的过程。**

把这个等式称为 **光照模型** (Lighting Model)。

#### 直接光照与间接光照

  * 直接光照(direct light) - 照射到物体表面，经过一次反射直接进入摄像机的光线。

  * 间接光照(indirect light) - 光线进入摄像机之前，经过了不止一次物体反射

#### 其他术语

环境光（Ambient Lighting）：环境光是来自周围环境整体的散射光，为处于环境中的所有物体提供照明。

阴影（Shadow）：光影通常具有方向性，也指向了光源方向。

明暗变化（Shading）：是特定图像在不同区域展现出来的不同的光的明暗度。举个例子，同一个物体在同一个场景中，表面光的情况也会随着观察者角度的变化、环境光强度的变化而变化。

镜面高光（Specular highlight）：通过直接光源的照射，物体表面会反射高光点。这种物体表面的高光会随着观察者的位置而发生变化。

反射（Reflection）：光的反射会根据物体表面是否具有镜面或漫反射的特性而略有不同。例如，一个金属球将具有较高的镜面反射能力，并映出周围环境中的事物。相反，如果球的表面是磨砂材质，灰色，则照到球表面上的光会被散射。现实生活中的很多物体通常兼具镜面反射和漫反射特点，比如一个磨损的保龄球、一张使用很久的信用卡。

### 光照模型

#### 标准光照模型(Blinn - Phong光照模型)

裴祥风（ Bui Tuong Phong）

只关心直接光照。
进入摄像机内的光线分为4个部分，每个部分使用一种方法来计算他的贡献度。

##### 自发光(emissive)

如果没有使用全局光照(Global illumination)技术，自发光表面并不会真的照亮周围的物体。

![Alt text](/media/5220b7a0ca3c0b8d5538.png)

##### 高光反射(specular)

描述当光线从光源照射到模型表面时， 该表面会在完全镜面反射方向散射多少辐射量。
经验模型，不完全符合真实世界

* * *

Phong模型

![Alt text](/media/47eac8b3e71e1e78d0a6.png)

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

  * Mgloss —— 材质的光泽度(gloss), 反光度(shininess)

  * Mspecular —— 材质的高光反射颜色

反射方向可用表面法线n和光照方向l计算：

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

* * *

Blinn模型
避免计算反射方向 r。

![Alt text](/media/8a986c30c4474f216799.png)

![Alt text](/media/013e1ff78ba71c160442.png)

![Alt text](/media/3f4cad2c4258fd7b842b.png)

  * 如果摄像机和光源距离模型足够远的话 Blinn 模型 会快于Phong 模型 —— v和l都是定值，h是一个常量

  * 如果v或者l不是定值，Phong模型可能反而更快

两个都是经验模型，不存在哪个“更正确”，一些情况下，Blinn模型更符合结果。

##### 漫反射(diffuse)

描述被物体表面随机散射到各个方向上的辐射度。
可以认为在任何反射方向上的分布都是一样的，但是入射光线角度很重要。

**兰伯特定律(Lambert’s law)** : 反射光线强度与表面法线和光源方向之间的夹角的余弦值成正比。

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

![Alt text](/media/5ea6f562f9be7f3409d0.png)

**半兰伯特光照(HalfLambert)** （没有物理依据，只是一个视觉加强技术）

![Alt text](/media/2895498165f70e6422f3.png)

把cos的值从[-1, 1]映射到[0, 1]。

##### 环境光(ambient)

描述其他所有的间接光照

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

##### Unity中的应用

环境光： 场景的环境光 - Lighting设置中，Ambient Source/ Ambient Color/ Ambient Intensity中控制，Shader内置变量 `UNITY_LIGHTMODEL_AMBIENT`获取

自发光：在fragment Shader输出最后颜色之前，把材质的自发光颜色添加到输出颜色上即可

（”Lighting.cginc”中）_LightColor.0 - 该Pass处理的光源的颜色和强度信息
_WorldSpaceLightPos0.xyz - 单一平行光的方向

#### BRDF

BRDF(Bidirectional Reflectance Distribution Function) - 是一个经验模型。

为了更加真实的模拟光和物体的交互，出现了基于物理的BRDF模型。

## 实践应用

### 逐像素还是逐顶点

#### 逐像素光照(per-pixel lighting)

在片元着色器中计算，以像素为基础，得到法线。

  * 顶点法线插值 —— Phong插值着色(Phong shading)技术，法线插值着色技术

  * 法线贴图采样

#### 逐顶点光照(per-vertex lighting)

在顶点着色器中计算
高洛德着色(Gouraud shading) - 顶点上计算光照后，在渲染图元内部进行线性插值，输出成像素颜色。

  * 如果光照模型中有非线性的计算（高光反射）时，逐顶点光照就会出问题。

  * 渲染图元内部进行插值，会导致渲染图元内部的颜色总是暗于顶点处的最高颜色值，在某些情况下会产生明显的棱角现象。

### 游戏场景中灯光照明的构成

光照计算方案分类：

  1. 直接模拟光线从被光源发出到最终被物体完全吸收的正向过程，也就是常说的GI（Global Illumination）；

  2. 不直接模拟光线，而是反向搜集物体表面特定点的受光照强度来模拟现实照明效果，也就是常说的FG（Final Gathering）;

  3. 完全不考虑光线的行为，单纯基于“物体上与其他物体越接近的区域，受到反射光线的照明越弱”这一现象来模拟模拟现实照明（的一部分）效果，也就是常说的AO（Ambient Occlusion）；

  4. 将场景光照结果完全烘焙到模型贴图上，从而完完全全的假冒现实光照效果，也就是我们所说的Lightmap。

不论是GI还是FG，计算量都是非常大的，一帧图片需要几十分钟甚至几十小时来渲染，所以很难被应用在游戏设计领域。因此在游戏设计领域，光照贴图技术依然是目前的主流方式。

由于光照贴图需要事先烘焙（baking）出来，且仅支持静态物体（Static Object），而我们的游戏场景中几乎不可能全都是静态物体，所以通常游戏场景中的灯光照明是多种照明方式的混合作用。

  * 对于静态物体来说，大多使用光照贴图来模拟间接光的照明效果，然后加上直接光源的动态照明效果；

  * 对于运动物体来说，则仅用直接光源的动态照明效果，或者使用光照探针来模拟间接光的照明效果。

### lightmap

A lightmap is a data structure used in lightmapping, a form of surface caching in which the brightness of surfaces in a virtual scene is pre-calculated and stored in texture maps for later use.

#### 光照烘焙

当我们进行游戏时，有些场面避免不了使用大量灯光渲染。大量的灯光渲染对于计算机来说无疑是个负担，为了尽量节省计算机的显卡资源，对于一些静态的不动的物体，可以采用烘培的方法，把灯光的效果，制作成游戏物体纹理的一部分，这样即使没有灯光的渲染。该游戏物品也会呈现一样的视觉效果。

##### Unity场景光照烘焙步骤

  1. 创建物体和灯光

  2. 把所有要渲染的游戏对象全选，在Inspecto面板里面单击Static选项，选择Lightmap static（新版本为Contribute GI）

  3. 将需要烘焙的光源的Mode模式改为Baked

  4. window -> RenderingLighting -> Lighting Settings，Generate Lighting。

## Ref

<https://www.jianshu.com/p/7594b044e6dc>
