mirror of
https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git
synced 2025-08-22 20:25:28 +08:00
docs: replace 冯氏 to 风氏
This commit is contained in:
committed by
Gary Wang
parent
6c4ad5ec81
commit
c4b1eb0dd8
@@ -6,12 +6,12 @@
|
|||||||
翻译 | [Django](http://bullteacher.com/), Krasjet, Geequlim, [BLumia](https://github.com/blumia/)
|
翻译 | [Django](http://bullteacher.com/), Krasjet, Geequlim, [BLumia](https://github.com/blumia/)
|
||||||
校对 | [AoZhang](https://github.com/SuperAoao)
|
校对 | [AoZhang](https://github.com/SuperAoao)
|
||||||
|
|
||||||
现实世界的光照是极其复杂的,而且会受到诸多因素的影响,这是我们有限的计算能力所无法模拟的。因此OpenGL的光照使用的是简化的模型,对现实的情况进行近似,这样处理起来会更容易一些,而且看起来也差不多一样。这些光照模型都是基于我们对光的物理特性的理解。其中一个模型被称为<def>冯氏光照模型</def>(Phong Lighting Model)。冯氏光照模型的主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。下面这张图展示了这些光照分量看起来的样子:
|
现实世界的光照是极其复杂的,而且会受到诸多因素的影响,这是我们有限的计算能力所无法模拟的。因此OpenGL的光照使用的是简化的模型,对现实的情况进行近似,这样处理起来会更容易一些,而且看起来也差不多一样。这些光照模型都是基于我们对光的物理特性的理解。其中一个模型被称为<def>风氏光照模型</def>(Phong Lighting Model)。风氏光照模型的主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。下面这张图展示了这些光照分量看起来的样子:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- <def>环境光照</def>(Ambient Lighting):即使在黑暗的情况下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不会是完全黑暗的。为了模拟这个,我们会使用一个环境光照常量,它永远会给物体一些颜色。
|
- <def>环境光照</def>(Ambient Lighting):即使在黑暗的情况下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不会是完全黑暗的。为了模拟这个,我们会使用一个环境光照常量,它永远会给物体一些颜色。
|
||||||
- <def>漫反射光照</def>(Diffuse Lighting):模拟光源对物体的方向性影响(Directional Impact)。它是冯氏光照模型中视觉上最显著的分量。物体的某一部分越是正对着光源,它就会越亮。
|
- <def>漫反射光照</def>(Diffuse Lighting):模拟光源对物体的方向性影响(Directional Impact)。它是风氏光照模型中视觉上最显著的分量。物体的某一部分越是正对着光源,它就会越亮。
|
||||||
- <def>镜面光照</def>(Specular Lighting):模拟有光泽物体上面出现的亮点。镜面光照的颜色相比于物体的颜色会更倾向于光的颜色。
|
- <def>镜面光照</def>(Specular Lighting):模拟有光泽物体上面出现的亮点。镜面光照的颜色相比于物体的颜色会更倾向于光的颜色。
|
||||||
|
|
||||||
为了创建有趣的视觉场景,我们希望模拟至少这三种光照分量。我们将以最简单的一个开始:**环境光照**。
|
为了创建有趣的视觉场景,我们希望模拟至少这三种光照分量。我们将以最简单的一个开始:**环境光照**。
|
||||||
@@ -35,7 +35,7 @@ void main()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
如果你现在运行你的程序,你会注意到冯氏光照的第一个阶段已经应用到你的物体上了。这个物体非常暗,但由于应用了环境光照(注意光源立方体没受影响是因为我们对它使用了另一个着色器),也不是完全黑的。它看起来应该像这样:
|
如果你现在运行你的程序,你会注意到风氏光照的第一个阶段已经应用到你的物体上了。这个物体非常暗,但由于应用了环境光照(注意光源立方体没受影响是因为我们对它使用了另一个着色器),也不是完全黑的。它看起来应该像这样:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ Normal = mat3(transpose(inverse(model))) * aNormal;
|
|||||||
|
|
||||||
# 镜面光照
|
# 镜面光照
|
||||||
|
|
||||||
如果你还没被这些光照计算搞得精疲力尽,我们就再把镜面高光(Specular Highlight)加进来,这样冯氏光照才算完整。
|
如果你还没被这些光照计算搞得精疲力尽,我们就再把镜面高光(Specular Highlight)加进来,这样风氏光照才算完整。
|
||||||
|
|
||||||
和漫反射光照一样,镜面光照也决定于光的方向向量和物体的法向量,但是它也决定于观察方向,例如玩家是从什么方向看向这个片段的。镜面光照决定于表面的反射特性。如果我们把物体表面设想为一面镜子,那么镜面光照最强的地方就是我们看到表面上反射光的地方。你可以在下图中看到效果:
|
和漫反射光照一样,镜面光照也决定于光的方向向量和物体的法向量,但是它也决定于观察方向,例如玩家是从什么方向看向这个片段的。镜面光照决定于表面的反射特性。如果我们把物体表面设想为一面镜子,那么镜面光照最强的地方就是我们看到表面上反射光的地方。你可以在下图中看到效果:
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ vec3 result = (ambient + diffuse + specular) * objectColor;
|
|||||||
FragColor = vec4(result, 1.0);
|
FragColor = vec4(result, 1.0);
|
||||||
```
|
```
|
||||||
|
|
||||||
我们现在为冯氏光照计算了全部的光照分量。根据你的视角,你可以看到类似下面的画面:
|
我们现在为风氏光照计算了全部的光照分量。根据你的视角,你可以看到类似下面的画面:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -270,17 +270,17 @@ FragColor = vec4(result, 1.0);
|
|||||||
|
|
||||||
!!! Important
|
!!! Important
|
||||||
|
|
||||||
在光照着色器的早期,开发者曾经在顶点着色器中实现冯氏光照模型。在顶点着色器中做光照的优势是,相比片段来说,顶点要少得多,因此会更高效,所以(开销大的)光照计算频率会更低。然而,顶点着色器中的最终颜色值是仅仅只是那个顶点的颜色值,片段的颜色值是由插值光照颜色所得来的。结果就是这种光照看起来不会非常真实,除非使用了大量顶点。
|
在光照着色器的早期,开发者曾经在顶点着色器中实现风氏光照模型。在顶点着色器中做光照的优势是,相比片段来说,顶点要少得多,因此会更高效,所以(开销大的)光照计算频率会更低。然而,顶点着色器中的最终颜色值是仅仅只是那个顶点的颜色值,片段的颜色值是由插值光照颜色所得来的。结果就是这种光照看起来不会非常真实,除非使用了大量顶点。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
在顶点着色器中实现的冯氏光照模型叫做<def>Gouraud着色</def>(Gouraud Shading),而不是<def>冯氏着色</def>(Phong Shading)。记住,由于插值,这种光照看起来有点逊色。冯氏着色能产生更平滑的光照效果。
|
在顶点着色器中实现的风氏光照模型叫做<def>Gouraud着色</def>(Gouraud Shading),而不是<def>风氏着色</def>(Phong Shading)。记住,由于插值,这种光照看起来有点逊色。风氏着色能产生更平滑的光照效果。
|
||||||
|
|
||||||
现在你应该能够看到着色器的强大之处了。只用很少的信息,着色器就能计算出光照如何影响到所有物体的片段颜色。[下一节](03 Materials.md)中,我们会更深入的研究光照模型,看看我们还能做些什么。
|
现在你应该能够看到着色器的强大之处了。只用很少的信息,着色器就能计算出光照如何影响到所有物体的片段颜色。[下一节](03 Materials.md)中,我们会更深入的研究光照模型,看看我们还能做些什么。
|
||||||
|
|
||||||
## 练习
|
## 练习
|
||||||
|
|
||||||
- 目前,我们的光源是静止的,你可以尝试使用<fun>sin</fun>或<fun>cos</fun>函数让光源在场景中来回移动。观察光照随时间的改变能让你更容易理解冯氏光照模型。[参考解答](https://learnopengl.com/code_viewer.php?code=lighting/basic_lighting-exercise1)。
|
- 目前,我们的光源是静止的,你可以尝试使用<fun>sin</fun>或<fun>cos</fun>函数让光源在场景中来回移动。观察光照随时间的改变能让你更容易理解风氏光照模型。[参考解答](https://learnopengl.com/code_viewer.php?code=lighting/basic_lighting-exercise1)。
|
||||||
- 尝试使用不同的环境光、漫反射和镜面强度,观察它们怎么是影响光照效果的。同样,尝试实验一下镜面光照的反光度因子。尝试理解为什么某一个值能够有着特定视觉输出。
|
- 尝试使用不同的环境光、漫反射和镜面强度,观察它们怎么是影响光照效果的。同样,尝试实验一下镜面光照的反光度因子。尝试理解为什么某一个值能够有着特定视觉输出。
|
||||||
- 在观察空间(而不是世界空间)中计算冯氏光照:[参考解答](https://learnopengl.com/code_viewer.php?code=lighting/basic_lighting-exercise2)。
|
- 在观察空间(而不是世界空间)中计算风氏光照:[参考解答](https://learnopengl.com/code_viewer.php?code=lighting/basic_lighting-exercise2)。
|
||||||
- 尝试实现一个Gouraud着色(而不是冯氏着色)。如果你做对了话,立方体的光照应该会[看起来有些奇怪](../img/02/02/basic_lighting_exercise3.png),尝试推理为什么它会看起来这么奇怪:[参考解答](https://learnopengl.com/code_viewer.php?code=lighting/basic_lighting-exercise3)。
|
- 尝试实现一个Gouraud着色(而不是风氏着色)。如果你做对了话,立方体的光照应该会[看起来有些奇怪](../img/02/02/basic_lighting_exercise3.png),尝试推理为什么它会看起来这么奇怪:[参考解答](https://learnopengl.com/code_viewer.php?code=lighting/basic_lighting-exercise3)。
|
||||||
|
@@ -25,7 +25,7 @@ uniform Material material;
|
|||||||
|
|
||||||
在片段着色器中,我们创建一个结构体(Struct)来储存物体的材质属性。我们也可以把它们储存为独立的uniform值,但是作为一个结构体来储存会更有条理一些。我们首先定义结构体的布局(Layout),然后简单地以刚创建的结构体作为类型声明一个uniform变量。
|
在片段着色器中,我们创建一个结构体(Struct)来储存物体的材质属性。我们也可以把它们储存为独立的uniform值,但是作为一个结构体来储存会更有条理一些。我们首先定义结构体的布局(Layout),然后简单地以刚创建的结构体作为类型声明一个uniform变量。
|
||||||
|
|
||||||
如你所见,我们为冯氏光照模型的每个分量都定义一个颜色向量。<var>ambient</var>材质向量定义了在环境光照下这个表面反射的是什么颜色,通常与表面的颜色相同。<var>diffuse</var>材质向量定义了在漫反射光照下表面的颜色。漫反射颜色(和环境光照一样)也被设置为我们期望的物体颜色。<var>specular</var>材质向量设置的是表面上镜面高光的颜色(或者甚至可能反映一个特定表面的颜色)。最后,<var>shininess</var>影响镜面高光的散射/半径。
|
如你所见,我们为风氏光照模型的每个分量都定义一个颜色向量。<var>ambient</var>材质向量定义了在环境光照下这个表面反射的是什么颜色,通常与表面的颜色相同。<var>diffuse</var>材质向量定义了在漫反射光照下表面的颜色。漫反射颜色(和环境光照一样)也被设置为我们期望的物体颜色。<var>specular</var>材质向量设置的是表面上镜面高光的颜色(或者甚至可能反映一个特定表面的颜色)。最后,<var>shininess</var>影响镜面高光的散射/半径。
|
||||||
|
|
||||||
有这4个元素定义一个物体的材质,我们能够模拟很多现实世界中的材质。[devernay.free.fr](http://devernay.free.fr/cours/opengl/materials.html)中的一个表格展示了一系列材质属性,它们模拟了现实世界中的真实材质。下图展示了几组现实世界的材质参数值对我们的立方体的影响:
|
有这4个元素定义一个物体的材质,我们能够模拟很多现实世界中的材质。[devernay.free.fr](http://devernay.free.fr/cours/opengl/materials.html)中的一个表格展示了一系列材质属性,它们模拟了现实世界中的真实材质。下图展示了几组现实世界的材质参数值对我们的立方体的影响:
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
翻译 | [Geequlim](http://geequlim.com), Krasjet
|
翻译 | [Geequlim](http://geequlim.com), Krasjet
|
||||||
校对 | [AoZhang](https://github.com/SuperAoao)
|
校对 | [AoZhang](https://github.com/SuperAoao)
|
||||||
|
|
||||||
我们在前面的教程中已经学习了许多关于OpenGL中光照的知识,其中包括冯氏着色(Phong Shading)、材质(Material)、光照贴图(Lighting Map)以及不同种类的投光物(Light Caster)。在这一节中,我们将结合之前学过的所有知识,创建一个包含六个光源的完全照明场景。我们将模拟一个类似太阳的定向光(Directional Light)光源,四个分散在场景中的点光源(Point Light),以及一个手电筒(Flashlight)。
|
我们在前面的教程中已经学习了许多关于OpenGL中光照的知识,其中包括风氏着色(Phong Shading)、材质(Material)、光照贴图(Lighting Map)以及不同种类的投光物(Light Caster)。在这一节中,我们将结合之前学过的所有知识,创建一个包含六个光源的完全照明场景。我们将模拟一个类似太阳的定向光(Directional Light)光源,四个分散在场景中的点光源(Point Light),以及一个手电筒(Flashlight)。
|
||||||
|
|
||||||
为了在场景中使用多个光源,我们希望将光照计算封装到GLSL<def>函数</def>中。这样做的原因是,每一种光源都需要一种不同的计算方法,而一旦我们想对多个光源进行光照计算时,代码很快就会变得非常复杂。如果我们只在<fun>main</fun>函数中进行所有的这些计算,代码很快就会变得难以理解。
|
为了在场景中使用多个光源,我们希望将光照计算封装到GLSL<def>函数</def>中。这样做的原因是,每一种光源都需要一种不同的计算方法,而一旦我们想对多个光源进行光照计算时,代码很快就会变得非常复杂。如果我们只在<fun>main</fun>函数中进行所有的这些计算,代码很快就会变得难以理解。
|
||||||
|
|
||||||
|
@@ -8,24 +8,24 @@
|
|||||||
|
|
||||||
恭喜您已经学习到了这个地方!辛苦啦!不知道你有没有注意到,总的来说我们在学习光照教程的时候关于OpenGL本身并没有什么新东西,除了像访问uniform数组这样细枝末节的知识。目前为止的所有教程都是关于使用一些技巧或者公式来操作着色器,达到真实的光照效果。这再一次向你展示了着色器的威力。着色器是非常灵活的,你也亲眼见证了我们仅仅使用一些3D向量和可配置的变量就能够创造出惊人的图像这一点。
|
恭喜您已经学习到了这个地方!辛苦啦!不知道你有没有注意到,总的来说我们在学习光照教程的时候关于OpenGL本身并没有什么新东西,除了像访问uniform数组这样细枝末节的知识。目前为止的所有教程都是关于使用一些技巧或者公式来操作着色器,达到真实的光照效果。这再一次向你展示了着色器的威力。着色器是非常灵活的,你也亲眼见证了我们仅仅使用一些3D向量和可配置的变量就能够创造出惊人的图像这一点。
|
||||||
|
|
||||||
在前面的几个教程中,你学习了颜色、冯氏光照模型(包括环境光照、漫反射光照和镜面光照)、物体的材质、可配置的光照属性、漫反射和镜面光贴图、不同种类的光,并且学习了怎样将所有所学知识融会贯通,结合到一个完全照明的场景中。记得去实验一下不同的光照、材质颜色、光照属性,并且试着利用你无穷的创造力创建自己的环境。
|
在前面的几个教程中,你学习了颜色、风氏光照模型(包括环境光照、漫反射光照和镜面光照)、物体的材质、可配置的光照属性、漫反射和镜面光贴图、不同种类的光,并且学习了怎样将所有所学知识融会贯通,结合到一个完全照明的场景中。记得去实验一下不同的光照、材质颜色、光照属性,并且试着利用你无穷的创造力创建自己的环境。
|
||||||
|
|
||||||
在[下一节](../03 Model Loading/01 Assimp.md)当中,我们在我们的场景当中加入更高级的几何形状,这些形状将会在我们之前讨论过的光照模型中非常好看。
|
在[下一节](../03 Model Loading/01 Assimp.md)当中,我们在我们的场景当中加入更高级的几何形状,这些形状将会在我们之前讨论过的光照模型中非常好看。
|
||||||
|
|
||||||
## 词汇表
|
## 词汇表
|
||||||
|
|
||||||
- **颜色向量(Color Vector)**:一个通过红绿蓝(RGB)分量的组合描绘大部分真实颜色的向量。一个物体的颜色实际上是该物体所不能吸收的反射颜色分量。
|
- **颜色向量(Color Vector)**:一个通过红绿蓝(RGB)分量的组合描绘大部分真实颜色的向量。一个物体的颜色实际上是该物体所不能吸收的反射颜色分量。
|
||||||
- **冯氏光照模型(Phong Lighting Model)**:一个通过计算环境光,漫反射,和镜面光分量的值来近似真实光照的模型。
|
- **风氏光照模型(Phong Lighting Model)**:一个通过计算环境光,漫反射,和镜面光分量的值来近似真实光照的模型。
|
||||||
- **环境光照(Ambient Lighting)**:通过给每个没有被光照的物体很小的亮度,使其不是完全黑暗的,从而对全局光照进行近似。
|
- **环境光照(Ambient Lighting)**:通过给每个没有被光照的物体很小的亮度,使其不是完全黑暗的,从而对全局光照进行近似。
|
||||||
- **漫反射着色(Diffuse Shading)**:一个顶点/片段与光线方向越接近,光照会越强。使用了法向量来计算角度。
|
- **漫反射着色(Diffuse Shading)**:一个顶点/片段与光线方向越接近,光照会越强。使用了法向量来计算角度。
|
||||||
- **法向量(Normal Vector)**:一个垂直于平面的单位向量。
|
- **法向量(Normal Vector)**:一个垂直于平面的单位向量。
|
||||||
- **法线矩阵(Normal Matrix)**:一个3x3矩阵,或者说是没有平移的模型(或者模型-观察)矩阵。它也被以某种方式修改(逆转置),从而在应用非统一缩放时,保持法向量朝向正确的方向。否则法向量会在使用非统一缩放时被扭曲。
|
- **法线矩阵(Normal Matrix)**:一个3x3矩阵,或者说是没有平移的模型(或者模型-观察)矩阵。它也被以某种方式修改(逆转置),从而在应用非统一缩放时,保持法向量朝向正确的方向。否则法向量会在使用非统一缩放时被扭曲。
|
||||||
- **镜面光照(Specular Lighting)**:当观察者视线靠近光源在表面的反射线时会显示的镜面高光。镜面光照是由观察者的方向,光源的方向和设定高光分散量的反光度值三个量共同决定的。
|
- **镜面光照(Specular Lighting)**:当观察者视线靠近光源在表面的反射线时会显示的镜面高光。镜面光照是由观察者的方向,光源的方向和设定高光分散量的反光度值三个量共同决定的。
|
||||||
- **冯氏着色(Phong Shading)**:冯氏光照模型应用在片段着色器。
|
- **风氏着色(Phong Shading)**:风氏光照模型应用在片段着色器。
|
||||||
- **Gouraud着色(Gouraud shading)**:冯氏光照模型应用在顶点着色器上。在使用很少数量的顶点时会产生明显的瑕疵。会得到效率提升但是损失了视觉质量。
|
- **Gouraud着色(Gouraud shading)**:风氏光照模型应用在顶点着色器上。在使用很少数量的顶点时会产生明显的瑕疵。会得到效率提升但是损失了视觉质量。
|
||||||
- **GLSL结构体(GLSL struct)**:一个类似于C的结构体,用作着色器变量的容器。大部分时间用来管理输入/输出/uniform。
|
- **GLSL结构体(GLSL struct)**:一个类似于C的结构体,用作着色器变量的容器。大部分时间用来管理输入/输出/uniform。
|
||||||
- **材质(Material)**:一个物体反射的环境光,漫反射,镜面光颜色。这些东西设定了物体所拥有的颜色。
|
- **材质(Material)**:一个物体反射的环境光,漫反射,镜面光颜色。这些东西设定了物体所拥有的颜色。
|
||||||
- **光照属性(Light(properties))**:一个光的环境光,漫反射,镜面光的强度。可以使用任何颜色值,对每一个冯氏分量(Phong Component)定义光源发出的颜色/强度。
|
- **光照属性(Light(properties))**:一个光的环境光,漫反射,镜面光的强度。可以使用任何颜色值,对每一个风氏分量(Phong Component)定义光源发出的颜色/强度。
|
||||||
- **漫反射贴图(Diffuse Map)**:一个设定了每个片段中漫反射颜色的纹理图片。
|
- **漫反射贴图(Diffuse Map)**:一个设定了每个片段中漫反射颜色的纹理图片。
|
||||||
- **镜面光贴图(Specular Map)**:一个设定了每一个片段的镜面光强度/颜色的纹理贴图。仅在物体的特定区域显示镜面高光。
|
- **镜面光贴图(Specular Map)**:一个设定了每一个片段的镜面光强度/颜色的纹理贴图。仅在物体的特定区域显示镜面高光。
|
||||||
- **定向光(Directional Light)**:只有方向的光源。它被建模为无限距离,这使得它的所有光线看起来都是平行的,因此它的方向矢量在整个场景中保持不变。
|
- **定向光(Directional Light)**:只有方向的光源。它被建模为无限距离,这使得它的所有光线看起来都是平行的,因此它的方向矢量在整个场景中保持不变。
|
||||||
|
@@ -7,11 +7,11 @@
|
|||||||
校对 | 暂未校对
|
校对 | 暂未校对
|
||||||
|
|
||||||
|
|
||||||
在[光照](../02 Lighting/02 Basic Lighting.md)小节中,我们简单地介绍了冯氏光照模型,它让我们的场景有了一定的真实感。虽然冯氏模型看起来已经很不错了,但是使用它的时候仍然存在一些细节问题,我们将在这一节里讨论它们。
|
在[光照](../02 Lighting/02 Basic Lighting.md)小节中,我们简单地介绍了风氏光照模型,它让我们的场景有了一定的真实感。虽然风氏模型看起来已经很不错了,但是使用它的时候仍然存在一些细节问题,我们将在这一节里讨论它们。
|
||||||
|
|
||||||
## Blinn-Phong
|
## Blinn-Phong
|
||||||
|
|
||||||
冯氏光照不仅对真实光照有很好的近似,而且性能也很高。但是它的镜面反射会在一些情况下出现问题,特别是物体反光度很低时,会导致大片(粗糙的)高光区域。下面这张图展示了当反光度为1.0时地板会出现的效果:
|
风氏光照不仅对真实光照有很好的近似,而且性能也很高。但是它的镜面反射会在一些情况下出现问题,特别是物体反光度很低时,会导致大片(粗糙的)高光区域。下面这张图展示了当反光度为1.0时地板会出现的效果:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -21,15 +21,15 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
现在问题就应该很明显了。左图中是我们熟悉的冯氏光照中的反射向量,其中$\theta$角小于90度。而右图中,视线与反射方向之间的夹角明显大于90度,这种情况下镜面光分量会变为0.0。这在大多数情况下都不是什么问题,因为观察方向离反射方向都非常远。然而,当物体的反光度非常小时,它产生的镜面高光半径足以让这些相反方向的光线对亮度产生足够大的影响。在这种情况下就不能忽略它们对镜面光分量的贡献了。
|
现在问题就应该很明显了。左图中是我们熟悉的风氏光照中的反射向量,其中$\theta$角小于90度。而右图中,视线与反射方向之间的夹角明显大于90度,这种情况下镜面光分量会变为0.0。这在大多数情况下都不是什么问题,因为观察方向离反射方向都非常远。然而,当物体的反光度非常小时,它产生的镜面高光半径足以让这些相反方向的光线对亮度产生足够大的影响。在这种情况下就不能忽略它们对镜面光分量的贡献了。
|
||||||
|
|
||||||
1977年,James F. Blinn在冯氏着色模型上加以拓展,引入了<def>Blinn-Phong</def>着色模型。Blinn-Phong模型与冯氏模型非常相似,但是它对镜面光模型的处理上有一些不同,让我们能够解决之前提到的问题。Blinn-Phong模型不再依赖于反射向量,而是采用了所谓的<def>半程向量</def>(Halfway Vector),即光线与视线夹角一半方向上的一个单位向量。当半程向量与法线向量越接近时,镜面光分量就越大。
|
1977年,James F. Blinn在风氏着色模型上加以拓展,引入了<def>Blinn-Phong</def>着色模型。Blinn-Phong模型与风氏模型非常相似,但是它对镜面光模型的处理上有一些不同,让我们能够解决之前提到的问题。Blinn-Phong模型不再依赖于反射向量,而是采用了所谓的<def>半程向量</def>(Halfway Vector),即光线与视线夹角一半方向上的一个单位向量。当半程向量与法线向量越接近时,镜面光分量就越大。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
当视线正好与(现在不需要的)反射向量对齐时,半程向量就会与法线完美契合。所以当观察者视线越接近于原本反射光线的方向时,镜面高光就会越强。
|
当视线正好与(现在不需要的)反射向量对齐时,半程向量就会与法线完美契合。所以当观察者视线越接近于原本反射光线的方向时,镜面高光就会越强。
|
||||||
|
|
||||||
现在,不论观察者向哪个方向看,半程向量与表面法线之间的夹角都不会超过90度(除非光源在表面以下)。它产生的效果会与冯氏光照有些许不同,但是大部分情况下看起来会更自然一点,特别是低高光的区域。Blinn-Phong着色模型正是早期固定渲染管线时代时OpenGL所采用的光照模型。
|
现在,不论观察者向哪个方向看,半程向量与表面法线之间的夹角都不会超过90度(除非光源在表面以下)。它产生的效果会与风氏光照有些许不同,但是大部分情况下看起来会更自然一点,特别是低高光的区域。Blinn-Phong着色模型正是早期固定渲染管线时代时OpenGL所采用的光照模型。
|
||||||
|
|
||||||
获取半程向量的方法很简单,只需要将光线的方向向量和观察向量加到一起,并将结果正规化(Normalize)就可以了:
|
获取半程向量的方法很简单,只需要将光线的方向向量和观察向量加到一起,并将结果正规化(Normalize)就可以了:
|
||||||
|
|
||||||
@@ -52,21 +52,21 @@ float spec = pow(max(dot(normal, halfwayDir), 0.0), shininess);
|
|||||||
vec3 specular = lightColor * spec;
|
vec3 specular = lightColor * spec;
|
||||||
```
|
```
|
||||||
|
|
||||||
除此之外Blinn-Phong模型就没什么好说的了,Blinn-Phong与冯氏模型唯一的区别就是,Blinn-Phong测量的是法线与半程向量之间的夹角,而冯氏模型测量的是观察方向与反射向量间的夹角。
|
除此之外Blinn-Phong模型就没什么好说的了,Blinn-Phong与风氏模型唯一的区别就是,Blinn-Phong测量的是法线与半程向量之间的夹角,而风氏模型测量的是观察方向与反射向量间的夹角。
|
||||||
|
|
||||||
在引入半程向量之后,我们现在应该就不会再看到冯氏光照中高光断层的情况了。下面两个图片展示的是两种方法在镜面光分量为0.5时的对比:
|
在引入半程向量之后,我们现在应该就不会再看到风氏光照中高光断层的情况了。下面两个图片展示的是两种方法在镜面光分量为0.5时的对比:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
除此之外,冯氏模型与Blinn-Phong模型也有一些细微的差别:半程向量与表面法线的夹角通常会小于观察与反射向量的夹角。所以,如果你想获得和冯氏着色类似的效果,就必须在使用Blinn-Phong模型时将镜面反光度设置更高一点。通常我们会选择冯氏着色时反光度分量的2到4倍。
|
除此之外,风氏模型与Blinn-Phong模型也有一些细微的差别:半程向量与表面法线的夹角通常会小于观察与反射向量的夹角。所以,如果你想获得和风氏着色类似的效果,就必须在使用Blinn-Phong模型时将镜面反光度设置更高一点。通常我们会选择风氏着色时反光度分量的2到4倍。
|
||||||
|
|
||||||
下面是冯氏着色反光度为8.0,Blinn-Phong着色反光度为32.0时的一个对比:
|
下面是风氏着色反光度为8.0,Blinn-Phong着色反光度为32.0时的一个对比:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
你可以看到,Blinn-Phong的镜面光分量会比冯氏模型更锐利一些。为了得到与冯氏模型类似的结果,你可能会需要不断进行一些微调,但Blinn-Phong模型通常会产出更真实的结果。
|
你可以看到,Blinn-Phong的镜面光分量会比风氏模型更锐利一些。为了得到与风氏模型类似的结果,你可能会需要不断进行一些微调,但Blinn-Phong模型通常会产出更真实的结果。
|
||||||
|
|
||||||
这里,我们使用了一个简单的片段着色器,让我们能够在冯氏反射与Blinn-Phong反射间进行切换:
|
这里,我们使用了一个简单的片段着色器,让我们能够在风氏反射与Blinn-Phong反射间进行切换:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
void main()
|
void main()
|
||||||
@@ -85,4 +85,4 @@ void main()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
你可以在[这里](https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/1.advanced_lighting/advanced_lighting.cpp)找到这个Demo的源代码。你可以按下`B`键来切换冯氏光照与Blinn-Phong光照。
|
你可以在[这里](https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/1.advanced_lighting/advanced_lighting.cpp)找到这个Demo的源代码。你可以按下`B`键来切换风氏光照与Blinn-Phong光照。
|
||||||
|
@@ -43,7 +43,7 @@ G缓冲(G-buffer)是对所有用来储存光照相关的数据,并在最后的
|
|||||||
- 所有光源的位置和颜色向量
|
- 所有光源的位置和颜色向量
|
||||||
- 玩家或者观察者的位置向量
|
- 玩家或者观察者的位置向量
|
||||||
|
|
||||||
有了这些(逐片段)变量的处置权,我们就能够计算我们很熟悉的(布林-)冯氏光照(Blinn-Phong Lighting)了。光源的位置,颜色,和玩家的观察位置可以通过uniform变量来设置,但是其它变量对于每个对象的片段都是不同的。如果我们能以某种方式传输完全相同的数据到最终的延迟光照处理阶段中,我们就能计算与之前相同的光照效果了,尽管我们只是在渲染一个2D方形的片段。
|
有了这些(逐片段)变量的处置权,我们就能够计算我们很熟悉的(布林-)风氏光照(Blinn-Phong Lighting)了。光源的位置,颜色,和玩家的观察位置可以通过uniform变量来设置,但是其它变量对于每个对象的片段都是不同的。如果我们能以某种方式传输完全相同的数据到最终的延迟光照处理阶段中,我们就能计算与之前相同的光照效果了,尽管我们只是在渲染一个2D方形的片段。
|
||||||
|
|
||||||
OpenGL并没有限制我们能在纹理中能存储的东西,所以现在你应该清楚在一个或多个屏幕大小的纹理中储存所有逐片段数据并在之后光照处理阶段中使用的可行性了。因为G缓冲纹理将会和光照处理阶段中的2D方形一样大,我们会获得和正向渲染设置完全一样的片段数据,但在光照处理阶段这里是一对一映射。
|
OpenGL并没有限制我们能在纹理中能存储的东西,所以现在你应该清楚在一个或多个屏幕大小的纹理中储存所有逐片段数据并在之后光照处理阶段中使用的可行性了。因为G缓冲纹理将会和光照处理阶段中的2D方形一样大,我们会获得和正向渲染设置完全一样的片段数据,但在光照处理阶段这里是一对一映射。
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ void main()
|
|||||||
|
|
||||||
光照处理阶段着色器接受三个uniform纹理,代表G缓冲,它们包含了我们在几何处理阶段储存的所有数据。如果我们现在再使用当前片段的纹理坐标采样这些数据,我们将会获得和之前完全一样的片段值,这就像我们在直接渲染几何体。在片段着色器的一开始,我们通过一个简单的纹理查找从G缓冲纹理中获取了光照相关的变量。注意我们从`gAlbedoSpec`纹理中同时获取了`Albedo`颜色和`Spqcular`强度。
|
光照处理阶段着色器接受三个uniform纹理,代表G缓冲,它们包含了我们在几何处理阶段储存的所有数据。如果我们现在再使用当前片段的纹理坐标采样这些数据,我们将会获得和之前完全一样的片段值,这就像我们在直接渲染几何体。在片段着色器的一开始,我们通过一个简单的纹理查找从G缓冲纹理中获取了光照相关的变量。注意我们从`gAlbedoSpec`纹理中同时获取了`Albedo`颜色和`Spqcular`强度。
|
||||||
|
|
||||||
因为我们现在已经有了必要的逐片段变量(和相关的uniform变量)来计算布林-冯氏光照(Blinn-Phong Lighting),我们不需要对光照代码做任何修改了。我们在延迟着色法中唯一需要改的就是获取光照输入变量的方法。
|
因为我们现在已经有了必要的逐片段变量(和相关的uniform变量)来计算布林-风氏光照(Blinn-Phong Lighting),我们不需要对光照代码做任何修改了。我们在延迟着色法中唯一需要改的就是获取光照输入变量的方法。
|
||||||
|
|
||||||
运行一个包含32个小光源的简单Demo会是像这样子的:
|
运行一个包含32个小光源的简单Demo会是像这样子的:
|
||||||
|
|
||||||
|
@@ -185,7 +185,7 @@
|
|||||||
|
|
||||||
## 02-02
|
## 02-02
|
||||||
|
|
||||||
- Phong Lighting Model:冯氏光照模型
|
- Phong Lighting Model:风氏光照模型
|
||||||
- Ambient Lighting:环境光照
|
- Ambient Lighting:环境光照
|
||||||
- Diffuse Lighting:漫反射光照
|
- Diffuse Lighting:漫反射光照
|
||||||
- Specular Lighting:镜面光照
|
- Specular Lighting:镜面光照
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
- Specular Intensity:镜面强度
|
- Specular Intensity:镜面强度
|
||||||
- Shininess:反光度
|
- Shininess:反光度
|
||||||
- Gouraud Shading:Gouraud着色
|
- Gouraud Shading:Gouraud着色
|
||||||
- Phong Shading:冯氏着色
|
- Phong Shading:风氏着色
|
||||||
|
|
||||||
## 02-03
|
## 02-03
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user