5天没有继续学习和更新博客了,惭愧惭愧,继续今日的学习笔记吧
材质(Material)属性:用来模拟不同性质的物体,通俗的说就是给观察者一种贴近现实的真实感。
材质颜色(Material Color):由环境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和镜面光照(Specular Lighting)定义。
#version 330 core
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
uniform Material material;
访问并且设置材质分量:
void main()
{
// 环境光
vec3 ambient = lightColor * material.ambient;
// 漫反射
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = lightColor * (diff * material.diffuse);
// 镜面光
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = lightColor * (spec * material.specular);
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}
lightingShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.diffuse", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
lightingShader.setFloat("material.shininess", 32.0f);
一点小花样:让光源颜色随着时间变化
利用sin和glfwGetTime函数改变光源的环境光和漫反射颜色
glm::vec3 lightColor;
lightColor.x = sin(glfwGetTime() * 2.0f);
lightColor.y = sin(glfwGetTime() * 0.7f);
lightColor.z = sin(glfwGetTime() * 1.3f);
glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f); // 降低影响
glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // 很低的影响
lightingShader.setVec3("light.ambient", ambientColor);
lightingShader.setVec3("light.diffuse", diffuseColor);
想要使物体在不同的部件上都有不同的材质属性就需要用到光照贴图(Diffuse Map/Specular Map)
将纹理储存为Material结构体中的一个sampler2D,
将之前定义的vec3
漫反射颜色向量替换为漫反射贴图。
注意:sampler2D
是不透明类型(Opaque Type),也就是说不能将它实例化,只能通过uniform来定义它。
漫反射贴图(Diffuse Map):移除了环境光材质颜色向量,因为环境光颜色在几乎所有情况下都等于漫反射颜色,所以不需要将它们分开储存:
struct Material {
sampler2D diffuse;
vec3 specular;
float shininess;
};
...
in vec2 TexCoords;
//从纹理中采样片段的漫反射颜色值
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
//将环境光得材质颜色设置为漫反射材质颜色同样的值
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
镜面光贴图(Specular Map):
//渲染之前先把它绑定到合适的纹理单元上
lightingShader.setInt("material.specular", 1);
...
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
//接下来更新片段着色器的材质属性,让其接受一个sampler2D而不是vec3作为镜面光分量
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
//最后采样镜面光贴图,来获取片段所对应的镜面光强度
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));
FragColor = vec4(ambient + diffuse + specular, 1.0);
通过使用漫反射和镜面光贴图,可以给相对简单的物体添加大量的细节。甚至可以使用法线/凹凸贴图(Normal/Bump Map)或者反射贴图(Reflection Map)给物体添加更多的细节。