1
0
mirror of https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git synced 2025-08-23 20:55:27 +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

@@ -8,7 +8,7 @@
所以前面的材质系统对于除了最简单的模型以外都是不够的所以我们需要扩展前面的系统我们要介绍diffuse和specular贴图。它们允许你对一个物体的diffuse对于简洁的ambient成分来说它们几乎总是是一样的和specular成分能够有更精确的影响。
## 漫反射贴图
@@ -25,17 +25,17 @@
要记住的是sampler2D也叫做模糊类型这意味着我们不能以某种类型对它实例化只能用uniform定义它们。如果我们用结构体而不是uniform实例化就像函数的参数那样GLSL会抛出奇怪的错误这同样也适用于其他模糊类型。
我们也要移除amibient材质颜色向量因为ambient颜色绝大多数情况等于diffuse颜色所以不需要分别去储存它
```c++
struct Material
{
sampler2D diffuse;
vec3 specular;
float shininess;
};
...
struct Material
{
sampler2D diffuse;
vec3 specular;
float shininess;
};
...
in vec2 TexCoords;
```
如果你非把ambient颜色设置为不同的值不可不同于diffuse值你可以继续保持ambient的vec3但是整个物体的ambient颜色会继续保持不变。为了使每个原始像素得到不同ambient值你需要对ambient值单独使用另一个纹理。
注意,在像素着色器中我们将会再次需要纹理坐标所以我们声明一个额外输入变量。然后我们简单地从纹理采样来获得原始像素的diffuse颜色值
注意,在片段着色器中我们将会再次需要纹理坐标所以我们声明一个额外输入变量。然后我们简单地从纹理采样来获得原始像素的diffuse颜色值
```c++
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
```
@@ -43,28 +43,28 @@ vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords))
```c++
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
```
这就是diffuse贴图的全部内容了。就像你看到的这不是什么新的东西但是它却极大提升了视觉品质。为了让它工作我们需要用到纹理坐标更新顶点数据把它们作为顶点属性传递到像素着色器,把纹理加载,把纹理绑定到合适的纹理单元。
这就是diffuse贴图的全部内容了。就像你看到的这不是什么新的东西但是它却极大提升了视觉品质。为了让它工作我们需要用到纹理坐标更新顶点数据把它们作为顶点属性传递到片段着色器,把纹理加载,把纹理绑定到合适的纹理单元。
更新的顶点数据可以从这里找到。顶点数据现在包括了顶点位置,法线向量和纹理坐标,每个立方体的顶点都有这些属性。让我们更新顶点着色器来接受纹理坐标作为顶点属性,然后发送到像素着色器:
更新的顶点数据可以从这里找到。顶点数据现在包括了顶点位置,法线向量和纹理坐标,每个立方体的顶点都有这些属性。让我们更新顶点着色器来接受纹理坐标作为顶点属性,然后发送到片段着色器:
```c++
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoords;
...
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoords;
...
out vec2 TexCoords;
void main()
{
...
TexCoords = texCoords;
void main()
{
...
TexCoords = texCoords;
}
```
要保证更新的顶点属性指针不仅是VAO匹配新的顶点数据也要把箱子图片加载为纹理。在绘制箱子之前我们希望首选纹理单元被赋为material.diffuse这个uniform采样器并绑定箱子的纹理到这个纹理单元
```c++
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.diffuse"), 0);
...
glActiveTexture(GL_TEXTURE0);
...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
```
现在使用一个diffuse贴图我们在细节上再次获得惊人的提升这次添加到箱子上的光照开始闪光了名符其实。你的箱子现在可能看起来像这样
@@ -73,7 +73,7 @@ glBindTexture(GL_TEXTURE_2D, diffuseMap);
你可以在这里得到应用的全部代码。
## 镜面贴图
@@ -83,38 +83,38 @@ glBindTexture(GL_TEXTURE_2D, diffuseMap);
![](http://www.learnopengl.com/img/textures/container2_specular.png)
一个specular高光的亮度可以通过图片中每个纹理的亮度来获得。specular贴图的每个像素可以显示为一个颜色向量比如在那里黑色代表颜色向量vec3(0.0f)灰色是vec3(0.5f)。在像素着色器中我们采样相应的颜色值把它乘以光的specular亮度。像素越“白”乘积的结果越大物体的specualr部分越亮。
一个specular高光的亮度可以通过图片中每个纹理的亮度来获得。specular贴图的每个像素可以显示为一个颜色向量比如在那里黑色代表颜色向量vec3(0.0f)灰色是vec3(0.5f)。在片段着色器中我们采样相应的颜色值把它乘以光的specular亮度。像素越“白”乘积的结果越大物体的specualr部分越亮。
由于箱子几乎是由木头组成木头作为一个材质不会有镜面高光整个不透部分的diffuse纹理被用黑色覆盖黑色部分不会包含任何specular高光。箱子的铁边有一个修改的specular亮度它自身更容易受到镜面高光影响木纹部分则不会。
从技术上来讲木头也有镜面高光尽管这个闪亮值很小更多的光被散射影响很小但是为了学习目的我们可以假装木头不会有任何specular光反射。
使用Photoshop或Gimp之类的工具剪切一些部分非常容易变换一个diffuse纹理为specular图片以增加亮度/对比度的方式,可以把这个部分变换为黑色或白色。
###15.2.1 specular贴图采样
一个specular贴图和其他纹理一样所以代码和diffuse贴图的代码也相似。确保合理的加载了图片生成一个纹理对象。由于我们在同样的像素着色器中使用另一个纹理采样器我们必须为specular贴图使用一个不同的纹理单元查看纹理所以在渲染前让我们把它绑定到合适的纹理单元
一个specular贴图和其他纹理一样所以代码和diffuse贴图的代码也相似。确保合理的加载了图片生成一个纹理对象。由于我们在同样的片段着色器中使用另一个纹理采样器我们必须为specular贴图使用一个不同的纹理单元查看纹理所以在渲染前让我们把它绑定到合适的纹理单元
```c++
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.specular"), 1);
...
glActiveTexture(GL_TEXTURE1);
glUniform1i(glGetUniformLocation(lightingShader.Program, "material.specular"), 1);
...
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
```
然后更新像素着色器材质属性接受一个sampler2D作为这个specular部分的类型而不是vec3
然后更新片段着色器材质属性接受一个sampler2D作为这个specular部分的类型而不是vec3
```c++
struct Material
{
sampler2D diffuse;
sampler2D specular;
float shininess;
struct Material
{
sampler2D diffuse;
sampler2D specular;
float shininess;
};
```
最后我们希望采样这个specular贴图来获取原始像素相应的specular亮度
```c++
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
color = vec4(ambient + diffuse + specular, 1.0f);
```
通过使用一个specular贴图我们可以定义极为精细的细节物体的这个部分会获得闪亮的属性我们可以设置它们相应的亮度。specular贴图给我们一个附加的高于diffuse贴图的控制权限。
@@ -124,6 +124,6 @@ color = vec4(ambient + diffuse + specular, 1.0f);
![](http://www.learnopengl.com/img/lighting/materials_specular_map.png)
你可以在这里找到全部源码。也对比一下你的顶点着色器和像素着色器。
你可以在这里找到全部源码。也对比一下你的顶点着色器和片段着色器。
使用diffuse和specular贴图我们可以给相关但简单物体添加一个极为明显的细节。我们可以使用其他纹理贴图比如法线/bump贴图或者反射贴图给物体添加更多的细节。但是这些在后面教程才会涉及。把你的箱子给你所有的朋友和家人看有一天你会很满足我们的箱子会比现在更漂亮
使用diffuse和specular贴图我们可以给相关但简单物体添加一个极为明显的细节。我们可以使用其他纹理贴图比如法线/bump贴图或者反射贴图给物体添加更多的细节。但是这些在后面教程才会涉及。把你的箱子给你所有的朋友和家人看有一天你会很满足我们的箱子会比现在更漂亮