参考书籍 OpenGL ES 2.0 游戏开发 上卷
材质的放射系数,在这里既是物体原本的颜色
环境光照射结果 = 材质的反射系数 * 环境光强度
散射光 p160
散射光照结果 = 材质的反射系数 * 散射光强度 * Max(cos(入射角),0)
注意: 入射角 a*b = |a||b| * cos(入射角) 因为 |a| |b| 为单位向量,实际上,Max(a*b,0)
实际开发中往往分两步进行计算,此时公式被拆解为如下情况
散射光最终强度 = 散射光强度 * Max(cos(入射角),0)
散射光照射结果 = 材质的反射 * 散射光最终强度
镜面光 p163
镜面光与散射光不同,镜面光的最终强度还依赖于观察者的位置。
镜面光照射结果 = 材质的反射系数 * 镜面光强度 * max(0,(cos(半向量与法向量的夹角)))
光照 可以在 顶点着色器中 进行计算,也可以在片元着色器中进行计算,由于片元着色器调用的次数更多,所以如果性能许可,在片元中计算光照,效果更佳细腻。
定位光与定向光
1.定位光可以理解为光的方向不一,取决于光源的位置与照射点。
2.定向光的方位唯一。
如果是定向光的话,应该是固定的唯一的。
vec3 vp= normalize(lightDirection); //lightDirection 由外部输入
vp=normalize(vp);//格式化vp
下面的代码即为 定位光,因为光源的方向不唯一,
vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz);
vp=normalize(vp);//格式化vp
法向量的计算 分点面法向量,面法向量
1.点面法向量 更适合 曲面物体
法向量 为 面法向量的平均法向量
2.面法向量 适合菱角分明的 的物体
认为该顶点属于某个面,该面的法向量,即是该顶点的法向量
疑惑:
计算顶点法向量 为何是 aPosition + normal 然后再进行矩阵变换呢? aPosition+normal 代表了什么
uniform mat4 uMVPMatrix; //总变换矩阵
uniform mat4 uMMatrix; //变换矩阵
uniform vec3 uLightLocation;//光源位置
uniform vec3 uCamera; //摄像机位置
attribute vec3 aPosition; //顶点位置
attribute vec3 aNormal; //法向量
varying vec3 vPosition;//用于传递给片元着色器的顶点位置
varying vec4 vAmbient;//用于传递给片元着色器的环境光分量
varying vec4 vDiffuse;//用于传递给片元着色器的散射光分量
varying vec4 vSpecular;//用于传递给片元着色器的镜面反射光分量
//定位光光照计算的方法
void pointLight( //定位光光照计算的方法
in vec3 normal, //法向量
inout vec4 ambient, //环境光最终强度
inout vec4 diffuse, //散射光最终强度
inout vec4 specular, //镜面光最终强度
in vec3 lightLocation, //光源位置
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);
//计算从表面点到光源位置的向量vp
vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz);
vp=normalize(vp);//格式化vp
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; //计算镜面光的最终强度
}
void main()
{
//根据总变换矩阵计算此次绘制此顶点位置
gl_Position = uMVPMatrix * vec4(aPosition,1);
vec4 ambientTemp=vec4(0.0,0.0,0.0,0.0);
vec4 diffuseTemp=vec4(0.0,0.0,0.0,0.0);
vec4 specularTemp=vec4(0.0,0.0,0.0,0.0);
pointLight(normalize(aNormal),ambientTemp,diffuseTemp,specularTemp,uLightLocation,vec4(0.15,0.15,0.15,1.0),vec4(0.8,0.8,0.8,1.0),vec4(0.7,0.7,0.7,1.0));
vAmbient=ambientTemp;
vDiffuse=diffuseTemp;
vSpecular=specularTemp;
//将顶点的位置传给片元着色器
vPosition = aPosition;
}