此模型属于经验模型,主要用来简单模拟粗糙物体表面的光照现象
此模型假设物体表面为理想漫反射体(也就是只产生漫反射现象,也成为Lambert反射体),同时,场景中存在两种光,一种为环境光,一种为方向光,然后我们分别计算这两种光照射到粗糙物体表面所产生的光照现象,最后再将两个结果相加,得出反射后的光强值。
首先是计算环境光的公式:
I_ambdiff = K_d * I_a;
其中,K_d为粗糙物体表面材质对光的反射系数,这个系数由程序编写者在宿主程序中给出,I_a为环境光的光强,也就是环境光的颜色数值,一般是一个float3型的变量。
然后是计算方向光的公式:
I_ldiff = K_d * I_l * cosa;
其中I_l为方向光的光强,也就是其颜色值,一般是float3型的变量。这个公式与计算环境光的不同,对于环境光,我们不关心它的方向,因为环境光也没有方向,它给予物体的光照在各个顶点处均是一样的。而方向光则需要关注其方向,例如一个聚光灯,灯从不同的角度来照射物体所产生的效果也是不一样的,光线方向越靠近法线,漫反射出来的光就越强,反之则越弱。公式中的a就是光线方向与顶点法线的夹角,同时要注意,入射光的方向在这里定义为顶点到光源位置。但是计算cosa会比较麻烦,所以在这里要变换一下公式,方便程序的书写。假设N为顶点的单位法向量,L为入射光的单位法向量(再次提醒一下,L的方向是由顶点指向光源的)这样,由向量的点积公式可得:cosa = N﹒L,所以计算方向光的公式就变为:
I_ldiff = K_d * I_l * (N﹒L);
综上,得出漫反射后的光强为:
I_diff = K_d * I_a + K_d * I_l * (N﹒L);
下面给出使用Cg语言的Lambert漫反射光照模型顶点着色程序:
/******************************************************/
/*Lambert漫反射光照模型 */
/******************************************************/
struct vertex_In
{
float4 in_Position : POSITION;
float4 in_Normal : NORMAL;
};
struct vertex_Out
{
float4 out_Position : POSITION;
float4 out_Color : COLOR0;
};
void main_v(vertex_In vertexI,
out vertex_Out vertexO,
uniform float4*4 modelViewProj,
uniform float4*4 worldMatrix,
uniform float4*4 worldMatrix_IT,
uniform float3 globalAmbient,//全局光光强
uniform float3 lightPosition,
uniform float3 lightColor,
uniform float3 K_d//漫反射体反射系数
)
{
vertexO.out_Position = mul(modelViewProj , vertexI.in_Position);//进行投影变换
float3 worldPosition = mul(worldMatrix , vertexI.in_Position).xyz;//计算顶点的世界位置
float3 N = mul(worldMatrix_IT , vertexI.in_Normal).xyz;//计算顶点的法向量
N = normalize(N);//向量规范化
//计算方向光方向
float3 L = lightPosition - worldPosition;
L = normalize(L);//向量规范化
//计算环境光漫反射光强
float3 ambColor = Kd * globalAmbient;
//计算方向光漫反射光强
float3 dirColor = Kd * lightColor * max(dot(N , L) , 0);
vertexO.out_color.rgb = ambColor + dirColor;
vertexO.out_color.a = 1;
}