Opengl es光照
1. OpenGL 里面的光照基本由 环境光、散射光、镜面光。
其中涉及的基本公式如下:
A.环境光:
环境光照射结果 = 材质的反射系数 X 环境光强度
例如:
vAmbient = vec4(0.5,0.5,0.5,0);
gl_FragColor=finalColor*vAmbient;
B. 散射光:
上面介绍的环境光是没有位置概念的。但是散射光有位置。
散射光代表的是显示世界中粗糙的物体表面被光照射时,反射光在各个方向上基本均匀(也称漫反射),
当光源的位置发生变化时,散射光的效果会发生明显变化。主要体现为当光垂直照射物体表面比斜照时要亮。
公式为:
散射光照射结果 = 材质的反射系数 X 散射光强度 X max(cos(入射角),0);
实际开发中,一般分为两步计算,
散射光最终强度 = 散射光强度 X max(cos(入射角),0);
散射光照射结果 = 材质的反射系数 X 散射光最终强度;
例如:在顶点着色器里面,对球面上的点进行计算散射光可以如下:
void pointLight ( //散射光光照计算的方法
in vec3 normal, //法向量
inout vec4 diffuse, //散射光计算结果
in vec3 lightLocation, //光源位置
in vec4 lightDiffuse //散射光强度
){
vec4 realp = uMMatrix * vec4(aPosition,1);
vec4 pl = vec4(lightLocation,1) - realp;
vec4 normalizepl = normalize(pl);
vec4 normalizenor = normalize(vec4(normal,1));
float nd = max(0.0,dot(normalizepl,normalizenor));
diffuse = lightDiffuse * nd;
}
C.镜面光:
现实生活中,当光滑的表面被照射时,会有方向很集中的发射光,这就是镜面光.
其中,镜面光 不仅依赖光源的位置,还依赖观察者的位置。如果从摄像机到被照射点的向量不在反射光方向集中的范围内,观察者将不会看到镜面光。
具体公式为:
镜面光照射结果 = 材质的反射系数 X 镜面光强度 X max(0,(cos(半向量与法向量的夹角))粗糙度);
实际开发中,一般分两步进行计算:
镜面光最终强度 = 镜面光强度 X max(0,(cos(半向量与法向量的夹角))粗糙度);
镜面光照射结果 = 材质的反射系数 X 镜面光最终强度;
其中,半向量指的是 从被照射点到光源的向量 与 被照射点与观察点 向量的平均向量 。
例如:
void pointLight( //定位光光照计算的方法
in vec3 normal, //法向量
inout vec4 specular, //镜面反射光分量
in vec3 lightLocation, //光源位置
in vec4 lightSpecular //镜面光强度
){
vec4 realp = uMMatrix * vec4(aPosition,1);
vec4 pl = vec4(lightLocation,1) - realp;
vec4 pv = vec4(uCamera,1) - realp;
vec4 normalize_pl = normalize(pl);
vec4 normalize_pv = normalize(pv);
vec4 halfv = normalize_pl + normalize_pv;
vec4 normalize_halfv = normalize(halfv);
//粗糙度,越小越光滑
float shininess=50.0;
// vec3 nn = normalize(aNormal);
// vec4 normalize_nor = vec4(nn,1);
// 需要注意向量和点
vec4 normalize_nor = normalize(vec4(aNormal,0));
float nDotViewHalfVector = dot(normalize_nor , normalize_halfv);
float powerFactor = max(0.0,pow(nDotViewHalfVector,shininess));
specular=lightSpecular*powerFactor; //最终的镜面光强度
}
---------------------------------------
如果将三种光合成起来,就是:
gl_FragColor=finalColor*vAmbient + finalColor*vDiffuse + finalColor*vSpecular;
2.定位光与定向光
上面介绍的 散射光 和 镜面光都是属于定位光,光源有固定的位置, 但是现实生活中的阳光,则是平行光,即场景中不同位置的物体反映出的光照效果完全一致。
象太阳这样的光,就是定向光,与光源位置无关,只与方向有关.
void directionalLight( //定向光光照计算的方法
in vec3 normal, //法向量
inout vec4 ambient, //环境光最终强度
inout vec4 diffuse, //散射光最终强度
inout vec4 specular, //镜面光最终强度
in vec3 lightDirection, //定向光方向
in vec4 lightAmbient, //环境光强度
in vec4 lightDiffuse, //散射光强度
in vec4 lightSpecular //镜面光强度
){
ambient=lightAmbient; //直接得出环境光的最终强度
vec3 normalTarget=aPosition+normal; //计算变换后的法向量
vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz;
newNormal=normalize(newNormal); //对法向量规格化
//计算从表面点到摄像机的向量
vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz);
vec3 vp= normalize(lightDirection); //规格化定向光方向向量
vec3 halfVector=normalize(vp+eye); //求视线与光线的半向量
float shininess=50.0; //粗糙度,越小越光滑
float nDotViewPosition=max(0.0,dot(newNormal,vp)); //求法向量与vp的点积与0的最大值
diffuse=lightDiffuse*nDotViewPosition; //计算散射光的最终强度
float nDotViewHalfVector=dot(newNormal,halfVector); //法线与半向量的点积
float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess)); //镜面反射光强度因子
specular=lightSpecular*powerFactor; //计算镜面光的最终强度
}
对于上面需要说明的是, 对于定向光的计算 和 定位光的计算类似,只需将定位光的位置,换成 定向光的方向,由于定向光方向一定,所以不需要和被照射点计算。直接将方向规格化即可。
对于定向光,也是包含 环境光、散射光、镜面光三个通道。计算方式类似。
注意:以上的计算都是在顶点着色器里面进行计算的光照,如果想要更加细腻的效果,可以将其在片元着色器里面进行计算。

浙公网安备 33010602011771号