材料
在OpenGL中,材料(Material)是用于描述物体表面特性和光照交互的属性集合。材料属性决定了物体在光照条件下的外观和反射行为
在现实世界中,每个物体对光都有不同的反应。例如,钢制物品通常比粘土花瓶更闪亮,而木制容器对光的反应与钢制容器不同。一些物体反射光而没有太多散射,导致镜面高光较小,而其他物体散射很多,使高光半径更大。
材料属性:
- 环境光颜色(ambient color)
- 反射颜色(diffuse color)
- 镜面反射颜色(specular color)
- 反射率(shininess)
- 发光颜色(emission color)光源的颜色
创建材料属性:
材料属性 可以理解位一个属性变量, 在用的时候对其赋值即可, 所以就可以用到GLGS 中的制服来创建。
#version 330 core
//材料
struct Material {
vec3 ambient; 环境光
vec3 diffuse; 反射光
vec3 specular; 镜面反射
float shininess; 反射率
};
//光源
struct Light {
vec3 position; //光源位置
vec3 ambient; //环境光
vec3 diffuse; //反射
vec3 specular;//镜面反射
};
uniform Material material;
uniform Light light;
设置材料属性:
代码实现:
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);
// 通过改变光的环境和漫反射颜色来轻松地随时间改变光的颜色
lightingShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
lightingShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); // darken diffuse light a bit
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
GLGS实现:
#version 330 core
out vec4 FragColor;
in vec3 Normal;
in vec3 FragPos;
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform vec3 viewPos;
uniform Material material;
uniform Light light;
void main()
{
// ambient
//材质的环境色*光源的环境色
vec3 ambient = material.ambient * light.ambient;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
//材质的反射光*光源的反射光
vec3 diffuse = (diff * material.diffuse) * light.diffuse;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
//材质的镜面反射光*光源的镜面反射光
vec3 specular = (material.specular * spec) * light.specular;
vec3 result = (ambient + diffuse + specular);
FragColor = vec4(result, 1.0);
}