最终效果
多光源
- 原理:
- 所有投光物分别计算,对当前片段的影响,再+求和,渲染出物体的材质效果
- 每个投光物:根据冯氏光照(环境,漫反射,镜面)分解计算对片段的强度影响,再与当前片段颜色值(单一颜色 / 纹理颜色)* 相乘
- 每个投光物也会对(环境,漫反射,镜面)有不同的影响程度
- 通过struct和函数,进行整理归纳,比如绘制多个点光源,有不同的位置,之间把每次的位置传入点光源结构体中
Fragment_glsl
#version 330 core
layout(location = 0) out vec4 FragColor;
//in
in vec3 v_Position;
in vec2 v_TexCoord;
in vec3 v_Normal;
//材质
struct Material {
//
sampler2D texture1;
sampler2D texture2;
//
sampler2D specular_Texture;
//光泽度
float shininess;
};
//平行光
struct DirLight {
vec3 direction;//位置
//冯氏光照
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
//点光
struct PointLight {
vec3 position;
vec3 color;
//冯氏光照
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
//聚光
struct SpotLight {
//聚光范围
float cutOff;
float outerCutOff;
//冯氏光照
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct ConstVal{
//camera
vec3 camera_Position;
vec3 camera_Direction;
//衰减
float constant;
float linear;
float quadratic;
};
//
uniform Material material;
uniform DirLight dirLight;
uniform PointLight pointLights[10];
uniform SpotLight spotLight;
uniform ConstVal constVal;
// function prototypes声明在此处,main可以用
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
//
void main()
{
vec3 viewPos = normalize(constVal.camera_Position - v_Position);
vec3 norm = normalize(v_Normal);
vec3 result = CalcDirLight(dirLight, norm, viewPos);
for(int i = 0; i < 10; i++)
result += CalcPointLight(pointLights[i], norm, v_Position, viewPos);
result += CalcSpotLight(spotLight, norm, v_Position, viewPos);
FragColor = vec4(result, 1.0);//最终片段颜色
}
//
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 * mix(texture(material.texture1, v_TexCoord), texture(material.texture2, v_TexCoord), 0.0).rgb;
vec3 diffuse = light.diffuse * diff * mix(texture(material.texture1, v_TexCoord), texture(material.texture2, v_TexCoord), 0.0).rgb;
vec3 specular = light.specular * spec * vec3(texture(material.specular_Texture, v_TexCoord));
return (ambient + diffuse + specular);
}
//
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 / (constVal.constant + constVal.linear * distance + constVal.quadratic * (distance * distance));
//计算影响
vec3 ambient = light.ambient * mix(texture(material.texture1, v_TexCoord), texture(material.texture2, v_TexCoord), 0.0).rgb;
vec3 diffuse = light.color * light.diffuse * diff * mix(texture(material.texture1, v_TexCoord), texture(material.texture2, v_TexCoord), 0.0).rgb;
vec3 specular = light.color * light.specular * spec * vec3(texture(material.specular_Texture, v_TexCoord));
ambient *= attenuation;
diffuse *= attenuation ;
specular *= attenuation ;
return (ambient + diffuse + specular);
}
//
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(constVal.camera_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(constVal.camera_Position - fragPos);
float attenuation = 1.0 / (constVal.constant + constVal.linear * distance + constVal.quadratic * (distance * distance));
// 范围
float theta = dot(lightDir, normalize(-constVal.camera_Direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
//计算影响
vec3 ambient = light.ambient * mix(texture(material.texture1, v_TexCoord), texture(material.texture2, v_TexCoord), 0.0).rgb;
vec3 diffuse = light.diffuse * diff * mix(texture(material.texture1, v_TexCoord), texture(material.texture2, v_TexCoord), 0.0).rgb;
vec3 specular = light.specular * spec * vec3(texture(material.specular_Texture, v_TexCoord));
ambient *= attenuation * intensity;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return (ambient + diffuse + specular);
}
标签:OpenGL3.3,float,Windows,light,material,C++,specular,vec3,TexCoord
From: https://blog.csdn.net/sengyongan/article/details/139697367