物体表面的颜色由 自发光(emissive), 环境反射(ambient), 漫反射(diffuse) 和 镜面反射(specular)等光作用的总和。
emissive 自发光
表面所发出的光,独立于所有的光源。
emissive = K. k代表材质的放射光颜色。
ambient 环境反射
光在一个场景经过多次折射后就像来自西面八方。
ambient = K * globalAmbient。 globalAmbient 是入射环境光颜色。
diffuse 漫反射
从表面相等的向所有方向反射出去的方向光。
diffuse = K * lightColor * max(N.L, 0);
specular 镜面反射
受观察者位置影响
specular = K * lightColor * (max(N.H),0) shininess(up) || 0 (if N.L < 0)
Ks 是材质的镜面反射颜色
lightColor 是入射镜面反射光的颜色
N 是表面法向量
V 是 指向视点的单位向量
L 是 指向光源的单位向量
上面几种光照模型的Cg代码实现:
void basiclight(float4 position: POSITION,
float3 normal : NORMAL,
out float4 oPosition : POSITION
out float4 color : COLOR,
uniform float4x4 modelViewProj,
uniform float3 globalAmbient,
uniform float3 lightColor,
uniform float3 lightPosition,
uniform float3 eyePosition,
uniform float3 Ke,
uniform float3 Ka,
uniform float3 Kd,
uniform float3 Ks,
uniform float shininess)
{
oPosition = mul(modelViewProj, position);
float3 P = position.xyz;
float3 N = normalize(normal);
// compute the emissive term 自发光项
float3 emissive = Ke;
// compute the ambient term 环境反射项
// ambiemt.x = Ka.x * globalAmbient.x; (y,z)
float3 ambient = Ka * globalAmbient;
//compute the diffuse term 漫反射项
// dot 计算两向量夹角的余弦值,如果为负数,取0
float3 L = normalize(lightPosition - P);
float3 diffuseLight = max(dot(N,L), 0);
float3 diffuse = Kd * lightColor * diffuseLight;
//compute the specular term 计算镜面反射项
float3 V = normalize(eyePosition - P);
float3 H = normalize(L + V);
float specularLight = pow(max(dot(N,H),0),shiniess);
if(diffuseLight <= 0) specularLight = 0;
float3 specular = Ks * lightColor * specularLight;
//
color.xyz = emissive + ambient + diffuse + specular;
color.w = 1;
}
拓展项:
距离衰减:
强度随距离减少的光源,这个性质即距离衰减。在OpenGL 或
Direct3D中,任意给定的衰减使用如下公司进行模拟:
衰减因子 可用于调整公司的漫反射和镜面反射项
lighting = emissive + ambient + attenuationFactor * (diffuse + specular)
attenuationFactor = 1/ Kc+KL d + KQ d2
创建一个光照函数:
Cg中函数通常是内嵌的,即没有函数调用的开销。
参考:
《The Cg Tutorial:The Definitive Guide to Programmable Real-Time Graphics》 Chapter 5 lighting