1
0
mirror of https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git synced 2025-08-23 12:45:29 +08:00

校对02/03 修改前后文的“像素着色器”为“片段着色器”

This commit is contained in:
Geequlim
2015-07-31 08:52:50 +08:00
parent f7b2a455c4
commit 8e1b38db0a
5 changed files with 150 additions and 143 deletions

View File

@@ -49,7 +49,7 @@ void main()
你可能记得在[变换教程](http://learnopengl-cn.readthedocs.org/zh/latest/01%20Getting%20started/07%20Transformations/)里我们知道两个单位向量的角度越小它们点乘的结果越倾向于1。当两个向量的角度是90度的时候点乘会变为0。这同样适用于θθ越大光对片段颜色的影响越小。
!!! Important
注意我们使用的是单位向量长度是1的向量取得两个向量夹角的余弦值所以我们需要确保所有的向量都被标准化另一方面点乘返回的不仅是余弦查看[变换](http://learnopengl-cn.readthedocs.org/zh/latest/01%20Getting%20started/07%20Transformations/))。
点乘返回一个标量,我们用它计算光线对片段颜色的影响力,基于不同片段所朝向光源的方向的不同,这些片段被照亮的情况也不同。
@@ -82,10 +82,10 @@ glEnableVertexAttribArray(0);
我们只想使用每个顶点的前三个浮点数忽略后三个浮点数所以我们只需要把步长参数改成GLfloat尺寸的6倍。
!!! Important
发光物着色器顶点数据的不完全使用看起来有点低效但是这些顶点数据已经从立方体对象载入到GPU的内存里了所以GPU内存不是必须再储存新数据。相对于重新给发光物分配VBO实际上却是更高效了。
所有光照的计算需要在片段着色器里进行,所以我们需要把法线向量由顶点着色器传递到像素着色器。我们这么做:
所有光照的计算需要在片段着色器里进行,所以我们需要把法线向量由顶点着色器传递到片段着色器。我们这么做:
```c++
out vec3 Normal;
@@ -104,7 +104,7 @@ in vec3 Normal;
### 计算环境光照
每个顶点现在都有了法线向量,但是我们仍然需要光的位置向量和片段的位置向量。由于光的位置是一个静态变量,我们可以简单的在像素着色器中把它声明为uniform
每个顶点现在都有了法线向量,但是我们仍然需要光的位置向量和片段的位置向量。由于光的位置是一个静态变量,我们可以简单的在片段着色器中把它声明为uniform
```c++
uniform vec3 lightPos;
@@ -122,7 +122,7 @@ glUniform3f(lightPosLoc, lightPos.x, lightPos.y, lightPos,z);
```c++
out vec3 FragPos;
out vec3 Normal;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
@@ -137,7 +137,7 @@ void main()
in vec3 FragPos;
```
现在,所有需要的变量都设置好了,我们可以在像素着色器中开始光照的计算了。
现在,所有需要的变量都设置好了,我们可以在片段着色器中开始光照的计算了。
我们需要做的第一件事是计算光源和片段位置之间的方向向量。前面提到,光的方向向量是光的位置向量与片段的位置向量之间的向量差。你可能记得,在变换教程中,我们简单的通过两个向量相减的方式计算向量差。我们同样希望确保所有相关向量最后都转换为单位向量,所以我们把法线和方向向量这个结果都进行标准化:
@@ -199,7 +199,7 @@ Normal = mat3(transpose(inverse(model))) * normal;
!!! Attention
对于着色器来说逆矩阵也是一种开销比较大的操作因此无论何时在着色器中只要可能就应该尽量避免逆操作因为它们必须为你场景中的每个顶点进行这样的处理。以学习的目的这样做很好但是对于一个对于效率有要求的应用来说在绘制之前你最好用CPU计算出法线矩阵然后通过uniform把值传递给着色器和模型矩阵一样
## 镜面光(Specular)
如果你还没被这些光照计算搞得精疲力尽,我们就再把镜面高光加进来,这样冯氏光照才算完整。
@@ -216,12 +216,12 @@ Normal = mat3(transpose(inverse(model))) * normal;
我们选择在世界空间world space进行光照计算但是大多数人趋向于在观察空间view space进行光照计算。在观察空间计算的好处是观察者的位置总是(0, 0, 0),所以这样你直接就获得了观察者位置。可是,我发现出于学习的目的,在世界空间计算光照更符合直觉。如果你仍然希望在视野空间计算光照的话,那就使用观察矩阵应用到所有相关的需要变换的向量(不要忘记,也要改变法线矩阵)。
为了得到观察者的世界空间坐标我们简单地使用摄像机对象的位置坐标代替它就是观察者。所以我们把另一个uniform添加到像素着色器,把相应的摄像机位置坐标传给像素着色器:
为了得到观察者的世界空间坐标我们简单地使用摄像机对象的位置坐标代替它就是观察者。所以我们把另一个uniform添加到片段着色器,把相应的摄像机位置坐标传给片段着色器:
```c++
uniform vec3 viewPos;
GLint viewPosLoc = glGetUniformLocation(lightingShader.Program, "viewPos");
GLint viewPosLoc = glGetUniformLocation(lightingShader.Program, "viewPos");
glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
```
@@ -267,9 +267,9 @@ color = vec4(result, 1.0f);
!!! Important
早期的光照着色器,开发者在顶点着色器中实现冯氏光照。在顶点着色器中做这件事的优势是,相比片段来说,顶点要少得多,因此会更高效,所以(开销大的)光照计算频率会更低。然而,顶点着色器中的颜色值是只是顶点的颜色值,片段的颜色值是它与周围的颜色值的插值。结果就是这种光照看起来不会非常真实,除非使用了大量顶点。
![](http://learnopengl.com/img/lighting/basic_lighting_gouruad.png)
在顶点着色器中实现的冯氏光照模型叫做Gouraud着色而不是冯氏着色。记住由于插值这种光照连起来有点逊色。冯氏着色能产生更平滑的光照效果。
现在你可以看到着色器的强大之处了。只用很少的信息,着色器就能计算出光照,影响到为我们所有物体的片段颜色。[下一个教程](http://learnopengl-cn.readthedocs.org/zh/latest/02%20Lighting/03%20Materials/),我们会更深入的研究光照模型,看看我们还能做些什么。
@@ -283,4 +283,3 @@ color = vec4(result, 1.0f);
在观察空间中计算冯氏光照:[解决方案](http://learnopengl.com/code_viewer.php?code=lighting/basic_lighting-exercise2)。
尝试实现一个Gouraud光照来模拟冯氏光照[解决方案](http://learnopengl.com/code_viewer.php?code=lighting/basic_lighting-exercise3)