OpenGL学习笔记六——光照
原理介绍
我们在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的(Reflected)颜色。换句话说,那些不能被物体所吸收(Absorb)的颜色(被拒绝的颜色)就是我们能够感知到的物体的颜色。
将光运用到图形学中,实现方式也比较简单,就是在物体基础颜色上乘以光的颜色
光的类型
- 直射光
计算方式比较简单
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// 漫反射着色
float diff = max(dot(normal, lightDir), 0.0);
// 镜面光着色
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.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));
return (ambient + diffuse + specular);
}
- 区域光
区域光带有衰变,如图:中心区颜色最亮,边缘渐变为黑色
- 点光源
计算方式比较复杂,向周围720度带有光照颜色衰减
参考实现
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// 漫反射着色
float diff = max(dot(normal, lightDir), 0.0);
// 镜面光着色
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// 衰减
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance +
light.quadratic * (distance * distance));
// 合并结果
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));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
逐顶点光照
在顶点着色器阶段乘上光照就是逐顶点光照
逐像素光照
在片元着色器阶段乘上光照就是 逐像素光照
因为定点数量远远小于像素数量,因此逐像素光照更加耗时,且有更好的表现
OpenGL中实现光照
首先需要使用GLM库,在之前有介绍:
glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
glm::vec3 baseColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * baseColor; // = (1.0f, 0.5f, 0.31f);
lightColor代表光的颜色,baseColor代表物体的颜色,result为光照后物体的颜色。
很简单吧
实战代码——实现逐片元光照
顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
片元着色器
#version 330 core
out vec4 FragColor;
uniform vec3 objectColor;
uniform vec3 lightColor;
void main()
{
FragColor = vec4(lightColor * objectColor, 1.0);
}