今天是个特殊的日子,因为是笔者第一次完成DEMO没有经过漫长的调试(其实并不能说明什么,因为演示程序的确太简单了,如果这样的一个程序还要纠结几天,我可能也要怀疑自己智商问题,不过还是小有成就,毕竟表示我对D3D有了进一步了解,以及明白了光照模型的实现原理(现在是越来越爱Shader了,和Fixed Pipeline Say 拜拜吧)。
关于镜面光照方程,基本上就是按PHONE的那个公式来的。 IS = IL · KS · Cos@^n
IS 为镜面反射光的强度,IL为入射光光强,KS为镜面反射常量,Cos@^n中n值越大,代表反射表面越光滑
下面是代码:
// File name : SpecularLighting.vsh
//
// Author : Dormy.X.C
//
// Description :
//
matrix viewMat;
matrix worldViewProjMat;
vector lightDir;
vector eyePosition;
vector ambientMtrl;
vector diffuseMtrl;
vector specularMtrl;
// 定义环境光及,镜面光照强度
vector ambientLightingIntensity = {0.5f, 0.5f, 0.5f, 0.0f};
vector diffuseLightingIntensity = {1.0f, 0.0f, 1.0f, 0.0f};
vector specularLightingIntensity = {1.0f, 1.0f, 1.0f, 0.0f};
// 输入结构
struct VS_INPUT
{
vector position : POSITION;
vector normal : NORMAL;
};
// 输出结构
struct VS_OUTPUT
{
vector position : POSITION;
vector color : COLOR;
};
// 主函数
VS_OUTPUT Specular(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.position = mul(input.position, worldViewProjMat);
lightDir.w = 0.0f;
input.normal.w = 0.0f;
mul(lightDir, viewMat);
mul(input.normal, viewMat);
vector vertexWorldPos = normalize(mul(input.position, viewMat));
// 计算观察方向
vector viewDirection = normalize(eyePosition - vertexWorldPos);
// 计算法线与入射光线(即光照方向)的值
float s = saturate( dot( input.normal, lightDir) );
if( s < 0.0f )
s = 0.0f;
// 计算镜面反射向量
vector reflect = normalize(2 * s * input.normal - lightDir);
// 表示反射面光滑程度(反射系数)
vector specularIntensity = pow( saturate(dot(reflect, viewDirection)), 25.0f);
output.color = (ambientMtrl * ambientLightingIntensity) + // 环境光
((ambientMtrl * diffuseLightingIntensity) * s) + // 散射光
(specularMtrl * specularIntensity * specularLightingIntensity); // 镜面光
return output;
}