颜色
现实中所有物体都有颜色,在Opengl中我们可以通过三个分量来设置一个颜色。在自然界中·我们看到的物体的颜色时它反射的颜色
颜色的反射规律在OpenGL中两个三维坐标相乘是三个分量逐步分量,用这个我们可以模拟物体颜色的反射。
※不等比缩放会破坏法向量,而且法向量用于光照计算也要转到相应的世界坐标里,这里就用到了正规矩阵,在opengl中通过
光照基础
冯氏光照模型(Phone Light Model)
why:现实中光照我们无法模拟
what:对现实生活中的光照进行模拟
how:由三个基本的元素组成环境(Ambient),漫反射(Diffuse光),镜面(Specular)光照。
参考
环境光照
why:全局照明(物体不止会受到直射光的影响,还会受到非直射光的影响)的算法复杂开销大,所以我们将用到简化模型,环境照明。
what:物体自身所带的光
how:用光的颜色乘环境因子的到环境光照
漫反射光照
what:投射到粗糙表面的一种反射现象,是该模型的显著部分,面向光源比较亮。
how:用光照方向,乘以法向量,来模拟why(向量点乘相乘,夹角越小值越大,夹角为90°点乘为0影响最小)
镜面光照
what:光投射到光滑表面的一种反射现象,出现的亮点。
how:根据观察角度,用反射后的光照向量点乘观察者角度向量
然后把计算的每个光照乘以这个模型的颜色,然后输入到片段着色器中。
材质
why:在真实世界,不同材质的物体,对光照有不同的反应,比如花瓶陶瓷材质在光照下会变得亮闪闪,而木头箱子对光照的反应微乎其微。
what:材质和光照一样,他也需要相应的元素来定义它的属性,就比如,环境光照,漫反射光照,镜面光照,和高光散射。
how:定义结构体,然后将相应的光照模型乘以材质模型即可。
光照贴图
把前面学的贴图和这一张结合起来。材质里的结构体改成贴图类型,然后赋值。
投光物
光的种类又分为 点光源,平行光,手电筒,每一个物体的受光情况根据之前提出的光照模型(环境光,漫反射光照,镜面反射光照)。
平行光:(what)光源发出的光每一条都是平行的,每一条光线独立于光源位置。(why)模拟太阳光。(how)设置光的 颜色和方向即可。然后根据光照模型计算。
点光源:(what)向所有位置发光,但是根据据光源的距离增加逐渐减弱。
(why)模拟场景中的灯泡等。(how)设置光的位置方向颜色,衰减。
衰减(attenuation)how:通过数学公式
手电筒(聚光):(what)他结合了前面两种光源的特点,某一方向照射,随着物体距离光源的距离的增加而减弱。(why)模拟手电筒或者聚光灯。(how)设置光的位置方向颜色,衰减,以及光的内角度(在内角度内的光照强度相同),外角度(内角度到外角度之间的光照逐渐减弱),这两者用来软化边缘。
点光源和手电筒算出的衰减和边缘软化,最后都要乘以光照模型的diffuse和specular来达到效果,
以下是源码
片段着色器
#version 330 core
in vec4 vertexColor;
in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoord;
struct Material
{
vec3 ambient;
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct LightPoint
{
vec3 pos;
vec3 color;
vec3 dirToLight;
float constant;
float linear;
float quadratic;
};
struct LightDirectional
{
vec3 pos;
vec3 color;
vec3 dirToLight;
};
struct LightSpot
{
vec3 pos;
vec3 color;
vec3 dirToLight;
float constant;
float linear;
float quadratic;
float CosPhyInner;
float CosPhyOutter;
};
uniform Material material;
uniform LightDirectional lightD;
uniform LightPoint lightP0;
uniform LightPoint lightP1;
uniform LightPoint lightP2;
uniform LightPoint lightP3;
uniform LightSpot lightS;
uniform vec3 objColor;
uniform vec3 ambientColor;
uniform vec3 cameraPos;
out vec4 FragColor;
vec3 CalcLightDirctional(LightDirectional light,vec3 uNormal,vec3 dirToCamera)
{
//diffuse
float diffIntensity = max(dot(light.dirToLight,uNormal),0);
vec3 diffColor = diffIntensity*light.color *texture(material.diffuse,TexCoord).rgb;
//specular
vec3 R = normalize(reflect(-light.dirToLight,uNormal));
float specIntensity = pow(max(dot(R,dirToCamera),0),material.shininess);
vec3 specColor = specIntensity*light.color*texture(material.specular,TexCoord).rgb;
vec3 result = diffColor +specColor;
return result;
}
vec3 CalcLightPoint(LightPoint light,vec3 uNormal,vec3 dirToCamera)
{
//attenuation
float dist = length(light.pos-FragPos);
float attenuation = 1/(light.constant+light.linear*dist+light.quadratic*(dist*dist));
//diffuse
float diffIntensity = max(dot(normalize(light.pos-FragPos),uNormal),0)*attenuation;
vec3 diffColor = diffIntensity*light.color *texture(material.diffuse,TexCoord).rgb;
//specular
vec3 R = normalize(reflect(-normalize(light.pos-FragPos),uNormal));
float specIntensity = pow(max(dot(R,dirToCamera),0),material.shininess);
vec3 specColor = specIntensity*light.color*texture(material.specular,TexCoord).rgb;
vec3 result = diffColor+specColor;
return result;
}
vec3 CalcLightSpot(LightSpot light,vec3 uNormal,vec3 dirToCamera)
{
float dist = length(light.pos-FragPos);
float attenuation = 1/(light.constant+light.linear*dist+light.quadratic*(dist*dist));
float spotRation = 0;
float CostTheta = dot(normalize(FragPos-light.pos),-light.dirToLight);
if(CostTheta>light.CosPhyInner)
{
spotRation = 1.0f;
}
else if(CostTheta>light.CosPhyOutter)
{
spotRation = (CostTheta-light.CosPhyOutter)/(light.CosPhyInner-light.CosPhyOutter);
}
else
{
spotRation = 0;
}
//diffuse
float diffIntensity = max(dot(normalize(light.pos-FragPos),uNormal),0)*attenuation*spotRation;
vec3 diffColor = diffIntensity*light.color *texture(material.diffuse,TexCoord).rgb;
//specular
vec3 R = normalize(reflect(-normalize(light.pos-FragPos),uNormal));
float specIntensity = pow(max(dot(R,dirToCamera),0),material.shininess);
vec3 specColor = specIntensity*light.color*texture(material.specular,TexCoord).rgb*attenuation*spotRation;
vec3 result = diffColor+specColor;
return result;
}
void main(){
vec3 finalResult = vec3(0,0,0);
vec3 uNormal = normalize(Normal);
vec3 dirToCamera = normalize(cameraPos-FragPos);
/* finalResult += CalcLightDirctional(lightD,uNormal,dirToCamera);
finalResult += CalcLightPoint(lightP0,uNormal,dirToCamera);
finalResult += CalcLightPoint(lightP1,uNormal,dirToCamera);
finalResult += CalcLightPoint(lightP2,uNormal,dirToCamera);
finalResult += CalcLightPoint(lightP3,uNormal,dirToCamera);*/
finalResult += CalcLightSpot(lightS,uNormal,dirToCamera);
FragColor = vec4(finalResult,1.0f);
}