for (int i=0;i
}
实现代码按照Lambert漫反射光照模型的计算公式计算了景物表面的光照,并按照计算结果进行了绘制。
函数Clear用于清除当前设置的景物和光源,以便可以开始新的真实感图形的绘制,其实现代码如下:
void CReality::Clear() {
m_SurfaceList.RemoveAll(); m_LightList.RemoveAll(); m_ParamList.RemoveAll(); m_count = 0; }
因为投影方向与视线方向有关,我们的演示程序中,投影方向是固定的,所以视线方向也采用了固定的方向。在CReality类的构造函数中初始化视线方向及其它需要初始化的成员变量,输入代码如下:
CReality::CReality() {
//初始化视线向量
lxn = -0.45;lyn = 0;lzn = 0.9; m_count = 0;
ira = 0;iga = 0;iba = 0; }
现在我们需要在应用程序中调用Lambert函数来完成使用Lambert漫反射光照模型绘制真实感图形。我们在应用程序中添加一个菜单项“Lambert漫反射光照模型”,在该菜单项的处理函数中完成使用Lambert漫反射光照模型绘制真实感图形。例如在该菜单项的处理函数中输入如下代码:
void CRealityDemoView::OnLambert() {
// TODO: Add your command handler code here m_Reality.Clear();//清除原有的景物和光源
CObject3D* m_ball = new CObject3D();//构造新的景物 m_ball->CreateBall(300,500,300,200);//创建一个球体 Param param;//构造景物参数
param.kra = 0.5;param.kga = 0.5;param.kba = 0.5; param.krd = 0.8;param.kgd = 0.8;param.kbd = 0.8; m_ball->SetParam(param);
m_Reality.AddObject3D(m_ball);//添加景物
LightParam light;//构造光源
light.c1 = 0.25;light.c2 = 0.01;light.c3 = 0.0001; light.m_distance = 30;
light.irl = 255;light.igl = 255;light.ibl = 255; light.xn = 0;light.yn = 0.5;light.zn = 0.5; m_Reality.AddLight(light);//添加光源
m_Reality.SetIA(100,100,100);//设置泛光强度 //使用Lambert漫反射光照模型进行绘制 m_Reality.Lambert(this->GetDC()); delete m_ball; }
其中m_Reality是在视图类中定义的一个CReality类对象。运行应用程序,选择“Lambert漫反射光照模型”菜单项,其真实感绘制结果如图9.3所示。
我们也可以添加多个光源,比如修改菜单项的处理函数,输入如下代码: void CRealityDemoView::OnLambert() {
// TODO: Add your command handler code here m_Reality.Clear();//清除原有的景物和光源
CObject3D* m_ball = new CObject3D();//构造新的景物 m_ball->CreateBall(300,500,300,200);//创建一个球体 Param param;//构造景物参数
param.kra = 0.3;param.kga = 0.5;param.kba = 0.2; param.krd = 0.3;param.kgd = 0.8;param.kbd = 0.6; m_ball->SetParam(param);
m_Reality.AddObject3D(m_ball);//添加景物
LightParam light;//构造光源1
light.c1 = 0.25;light.c2 = 0.01;light.c3 = 0.0001;
light.m_distance = 30;
light.irl = 0;light.igl = 255;light.ibl = 255; light.xn = 1;light.yn = 0.5;light.zn = 0.5; m_Reality.AddLight(light);//添加光源1
LightParam light1;//构造光源2
light1.c1 = 0.25;light1.c2 = 0.01;light1.c3 = 0.0001; light1.m_distance = 30;
light1.irl = 255;light1.igl = 0;light1.ibl = 0; light1.xn = -1;light1.yn = -0.5;light1.zn = 0.5; m_Reality.AddLight(light1);//添加光源2
m_Reality.SetIA(100,100,100);//设置泛光强度 //使用Lambert漫反射光照模型进行绘制 m_Reality.Lambert(this->GetDC()); delete m_ball; }
此时运行结果如图9.4所示。
此段代码添加了两个光源,且光源颜色不同。 9.2.4 Phong局部光照模型概述
Lambert漫反射模型并没有考虑镜面反射,而镜面反射在日常生活中随处可见。镜面反射光与漫反射光不同,它在空间的分布具有一定的方向性,它们朝空间一定方向会聚,所以景物表面上高光区域的位置随着观察者的方位不同而变
化。Phong光照模型充分考虑了镜面反射情况。
如图9.5所示,反射光线和入射光线对称地分布于表面法向的两侧。对于纯镜面,入射至表面上的光线严格地遵循光的反射定律单向地反射出去(如图9.5(a)所示),其单位反射方向为:
R?2N(N?L)?L
其中,N为表面单位法向量,L为单位入射光向量,R为单位反射光向量。
对于一般的景物表面,由于表面实际上是由许多具有不同朝向的微小平面组成的,其镜面反射光将分布于表面镜面反射方向R的周围(如图9.5(b)所示)。
对于一般镜面反射光的模拟,Phong模型采用了一种计算表面镜面反射光亮度的经验模型,即:
Is?IlW(?)cosn?
其中,W(?)为景物表面的镜面反射率,它是入射角和入射光波长的函数。在实际应用中,经常将W(?)取为常数ks,通常0?ks?1。n称为镜面高光指数,它用来模拟镜面反射光在空间的会聚程度。?为视线与镜面反射光线之间的夹角,Is即为表面投向视线方向的镜面反射光亮度。
上式表明投向观察者的镜面反射光不仅决定于入射光的强度,而且和观察者的观察方向有关。当观察者位于镜面反射方向附近时,观察者接受到的镜面反射光较强,当偏离这一方向时,镜面反射光就会迅速减弱甚至消失。同时,高光指数n越高,光的会聚程度越高,这时在表面上形成的高光越集中;相反,其镜面反射光呈发散状态。
将上面的镜面反射光的经验模型与Lambert漫反射模型结合起来,可得到下面的单一光源照射下的Phong光照模型的表达式:
I?Iaka?fiIl(kdcos??kscosn?)
对上式加以扩展,可得到在多个点光源照射下表面光亮度计算的Phong光照模型:
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库使用MFC实现真实感图形绘制(3)在线全文阅读。
相关推荐: