Skip to content

Commit

Permalink
feat: 环境光
Browse files Browse the repository at this point in the history
  • Loading branch information
melodyVoid committed Sep 15, 2021
1 parent 76137ee commit 924d708
Showing 1 changed file with 176 additions and 0 deletions.
176 changes: 176 additions & 0 deletions src/pages/md/如何用计算机表示光照.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# 如何用计算机表示光照

## 什么是颜色

现实生活中,当我们看一个物体的时候,很容易地能分辨出它的颜色。但大家有没有想过,颜色到底是什么?

其实颜色并不是客观存在的东西,只是一个视觉效果,决定这个视觉效果的关键因素是有三个:光、物体、视觉系统。

大家都知道,在有光线存在的时候,我们能够看到物体,准确分辨它们的颜色。但是到了晚上伸手不见五指的时候,这时候已经没了光线,我们是看不到任何东西的。

光是什么呢?光是一种电磁波,电磁波中的一部分能够被人眼所感知,这部分被称为可见光。

当光线照射到物体上时,物体能够吸收可见光的一部分,并反射不能吸收的那部分,反射出来的这部分可见光会刺激人眼,经过视神经传到大脑,形成对物体的色彩信息,这就是我们所说的颜色。

所以颜色的形成离不开这三个因素。

比如,当白色的太阳光照射在一个红色的物体上时,该物体吸收红色以外的光线,反射剩余的光线(红色光),所以我们看到了红色的物体。

假如我们有一盏蓝色的灯(r:0, g:0, b:1),照射在一个红色的物体(r:1, g:0, b:0)上,该物体吸收红色以外的光线,反射剩余的光线(r:0, g:0, b:0),黑色,所以我们看到的是一个黑色的物体。

简单一句话就是,人眼看到的物体是什么颜色,就代表这个物体反射该颜色。

## 颜色在计算机中的表示

那么,在计算机中,我们表示物体的颜色时,其实就是设置该物体能够**反射的可见光**。比如我们为一个物体指定蓝色,本质就是让该物体吸收除了蓝色以外的光线,只反射蓝色光线,这样我们看到的物体就是蓝色的。

我们前面的例子,都是只设置了物体的颜色,并没有加入光照因素。如果我们加入光照因素的话,该如何计算光照效果呢?

加入光照因素后,会影响进入人眼的颜色,所以,我们仍然是通过设置物体的颜色来表达加入光照后的效果。

当我们在计算机中创建一个光源时,需要给光源设置一个颜色(光源也是有颜色的哦),我们给光源设置为白色:

```js
vec3 light = vec3(1, 1, 1)
```

假设我们有一个物体是红色的:

```js
vec3 color = vec3(1, 0, 0)
```

在计算机领域中,将**光源颜色的各个分量****物体颜色的各个分量**相乘,得到的就是物体所反射的颜色,即该物体在该光源照射下进入人眼的颜色:

```js
vec3 resultColor = light * color
```

> 在 GLSL 语言中,vec3 与 vec3 相乘的实质是将两个 vec3 的分量分别相乘,得到一个新的 vec3。
得到的结果是 `vec3(1 * 1, 1 * 0, 1 * 0) = vec3(1, 0, 0)`,很明显,是红色,这也和现实生活中的表现一致。

前面讲了,如果蓝色的光线照射到红色的物体上,进入人眼的颜色是黑色,我们验证一下:

```js
vec3 light = vec3(0, 0, 1)
vec3 color = vec3(1, 0, 0)
vec3 resultColor = light * color
```

将光线的 rgb 分量和物体颜色的 rgb 分量相乘:

```js
resultColor = (0 * 1, 0 * 0, 1 * 0) = (0, 0, 0)
```

最终结果是黑色,和现实生活中的表现一致。

这就是在计算机中光照作用下物体颜色的计算原理。

## 环境光

在现实世界中,物体由于有本身材质的不同,对光线的反射效果也不同。材质粗糙的物体会将光线向各个方向进行反射,即漫反射,这也是现实生活中最为常见的反射类型,当漫反射的光线碰到另一个物体时,还会再次进行漫反射,所以,即使在没有光线照射到某个物体的情况下,其他物体的漫反射光也能照射到该物体,所以我们能够看到它。

那么在计算机中,如果想真实地模拟现实生活中没有光源直接照射物体时,通过其他物体的漫反射我们仍然能够看到该物体的情况,耗费的算力特别大,所以定义一种**环境光**的概念,来近似模拟这种效果。

> 请注意,虽然在环境光中多次提到了漫反射的概念,但是环境光要模拟的并不是有光线照射下的漫反射,而是多个物体的漫反射互相作用的光线效果。
那么环境光如何设置呢?

通常,我们使用一个较小的常量乘以光的颜色来模拟环境光。

## 环境光的计算

假设有一个光源,发出的光线是白色光:

```js
vec3 lightColor = vec3(1, 1, 1)
```

我们定义环境光的常量因子为 0.1

```js
float ambientFactor = 0.1
```

那么环境光的计算如下:

```js
vec3 ambientFactor = ambientFactor * lightColor
```
> GLSL中浮点数和 vec 向量相乘的实质是将该浮点数分别与vec向量的各个分量相乘,并返回新的 vec向量
计算出的环境光是:

```js
ambientColor = (1 * 0.1, 0.1 * 1, 0.1 * 1) = (0.1, 0.1, 0.1)
```

## 给物体增加环境光

之前的章节例子中,我们并没有提到光的概念,事实上我们默认有一个白色的环境光在里面的,所以我们能够看到它们。

看看我们之前的片元着色器

```js
gl_FragColor = v_Color
```

其实可以理解为一个强度因子为 1 的白色光源:

```js
vec3 ambientFactor = 1.0
vec3 lightColor = vec3(1, 1, 1)
vec3 ambientColor = ambientFactor * lightColor
gl_FragColor = vec4(ambientColor, 1) * v_Color
```

那这次,我们要改变强度因子,同时改变光线颜色,所以我们要定义两个常量,强度因子 `u_AmbientFactor` 和光源颜色 `u_LightColor`

增加了环境光的片元着色器如下:

```js
const FRAG_SHADER_SOURCE = `
precision mediump float;
varying vec4 v_Color;
uniform vec3 u_LightColor;
uniform float u_AmbientFactor;
void main() {
vec3 ambientColor = u_AmbientFactor * u_LightColor;
gl_FragColor = vec4(ambientColor, 1) * v_Color;
}
`
```
接下来我们需要通过 JavaScript 给片元着色器传递这两个常量:

```js
const u_AmbientFactor = gl.getUniformLocation(program, 'u_AmbientFactor')
const u_LightColor = gl.getUniformLocation(program, 'u_LightColor)
```
找到这两个常量位置,我们需要为他们传递强度因子和光线颜色,这里我们使用滑块来改变强度因子,并使用颜色选择器改变光线颜色,强度因子默认值是 0.2,光线颜色默认是白色:
```html
<div>
环境光因子:
<input id="ambientFactor" class="range" type="range" min="0" max="1" step="0.01" value="0.2" />
</div>
<div>
光线颜色:
<input id="lightColor" class="color" type="color" value="#FFFFFF" />
</div>
```
效果:
![](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/10/1665d141d1c28518~tplv-t2oaga2asx-watermark.awebp)
> 大家可以通过调节 1 处的滑块来改变强度因子,观察台体的亮度变化,调节 2 处的颜色选块来改变光线颜色,观察台体的在不同颜色光线照射下的变化。
为了便于观察,通过程序自动改变光线颜色:
![](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/10/1665d30d064c856f~tplv-t2oaga2asx-watermark.awebp)
可以看到,在不同颜色的光线照射下,人眼观察到的物体颜色也会不同。

0 comments on commit 924d708

Please sign in to comment.