光照-04.光照贴图(Lighting maps)-1
- UID
- 1066743
|
光照-04.光照贴图(Lighting maps)-1
漫反射贴图(Diffuse maps)
使用一张图片覆盖住物体,以便我们为每个原始像素索引独立颜色值。在光照场景中,通过纹理来呈现一个物体的diffuse颜色,这个做法被称做漫反射贴图(Diffuse map)(因为3D建模师就是这么称呼这个做法的)。注:它基本就是一个纹理。我们其实是使用同一个潜在原则下的不同名称。
为了演示漫反射贴图,我们将会使用下面的图片,它是一个有一圈钢边的木箱:
在着色器中使用漫反射贴图和纹理教程介绍的一样。这次我们把纹理以sampler2D类型储存在Material结构体中。我们使用diffuse贴图替代早期定义的vec3类型的diffuse颜色。
要记住的是sampler2D也叫做模糊类型,这意味着我们不能以某种类型对它实例化,只能用uniform定义它们。如果我们用结构体而不是uniform实例化(就像函数的参数那样),GLSL会抛出奇怪的错误;这同样也适用于其他模糊类型。
我们也要移除amibient材质颜色向量,因为ambient颜色绝大多数情况等于diffuse颜色,所以不需要分别去储存它:
struct Material // 储存物体的材质属性
{
sampler2D diffuse;
vec3 specular;
float shininess;
};
in vec2 TexCoords;
如果你非把ambient颜色设置为不同的值不可(不同于diffuse值),你可以继续保留ambient的vec3,但是整个物体的ambient颜色会继续保持不变。为了使每个原始像素得到不同ambient值,你需要对ambient值单独使用另一个纹理。(???)
注意,在片段着色器中我们将会再次需要纹理坐标,所以我们声明一个额外输入变量。然后我们简单地从纹理采样,来获得原始像素的diffuse颜色值:
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
同样,不要忘记把ambient材质的颜色设置为diffuse材质的颜色:
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
这就是diffuse贴图的全部内容了。就像你看到的,这不是什么新的东西,但是它却极大提升了视觉品质。为了让它工作,我们需要用到纹理坐标更新顶点数据,把它们作为顶点属性传递到片段着色器,把纹理加载并绑定到合适的纹理单元。
更新的顶点数据可以从这里找到。顶点数据现在包括了顶点位置,法线向量和纹理坐标,每个立方体的顶点都有这些属性。让我们更新顶点着色器来接受纹理坐标作为顶点属性,然后发送到片段着色器:
#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;
}
要保证更新的顶点属性指针,不仅是VAO匹配新的顶点数据,也要把箱子图片加载为纹理。在绘制箱子之前,我们希望首选纹理单元被赋为material.diffuse这个uniform采样器,并绑定箱子的纹理到这个纹理单元:
glActiveTexture (GL_TEXTURE0); // 激活纹理单元
glBindTexture (GL_TEXTURE_2D, diffuseMap); // 绑定纹理diffuseMap到当前激活的纹理单元
glUniform1i (glGetUniformLocation (lightingShader.Program, "material.diffuse"), 0); // 定义采样器material.diffuse对应这个纹理单元
--------------------- |
|
|
|
|
|