I?Iaka?i?1?MfiIli(kdcos?i?kscosn?i)
其中,M表示对场景有贡献的点光源的总个数,ks为景物表面的镜面反射率,kd为景物表面的漫反射率,其它以i为下标的各参数项的意义与前面所述相同。?为光源入射角,?为视线与镜面反射方向的夹角。
在实际计算中,如果求出了景物表面各可见点处的单位法向量N、单位入射光线方向向量Li、单位视线向量V和Li的单位镜面反射向量Ri,就可由
cos?i?(Li?N),cos?i?(V?Ri)和Phong光照模型公式计算每一可
见点处的光亮度。由于(V?Ri)计算不方便,常用(N?Hi)来代替它,其中Hi是将入射光反射到观察者方向的理想镜面的法向量,即以Hi为法向量的镜面恰好能将入射光Li反射至Vi处,显然Hi即为
Li?V的单位向量(如图9.6)。 2
这样,Phong光照模型成为下式:
MI?Iaka?i?1?fiIli[kd(N?Li)?ks(N?Hi)n]
9.2.5 Phong局部光照模型的实现
在CReality类中添加Phong成员函数来实现Phong局部光照模型,其实现代码如下:
//Phong光照模型
void CReality::Phong(CDC *pDC)
{
int no = 0;
//景物表面三颜色分量的泛光反射率 double kra,kga,kba;
//景物表面三颜色分量的漫反射率 double krd,kgd,kbd;
//景物表面的三颜色分量的镜面反射率 double krs,kgs,kbs; //镜面高光指数 int n;
//理想镜面法向量 double hxn,hyn,hzn;
double cosnl;//景物表面单位法向量与入射光单位向量间夹角的余弦值 double cosnh;//景物表面单位法向量与理想镜面法向量夹角的余弦值 double ird,igd,ibd;//景物表面三角面反射的三颜色光强度 //循环处理每一个三角面
for (int i=0;i } if (ird<0) ird =0;if (ird>255) ird = 255; if (igd<0) igd =0;if (igd>255) igd = 255; if (ibd<0) ibd =0;if (ibd>255) ibd = 255; //计算三角面的投影 CPoint p[3]; p[0] = Projection(surface.p1); p[1] = Projection(surface.p2); p[2] = Projection(surface.p3); //绘制三角面 CPen pen(PS_SOLID,1,RGB((int)ird,(int)igd,(int)ibd)); CBrush brush(RGB((int)ird,(int)igd,(int)ibd)); pDC->SelectObject(&pen); pDC->SelectObject(&brush); pDC->Polygon(p,3); brush.DeleteObject(); pen.DeleteObject(); } } 在应用程序中添加一个新的菜单项“Phong局部光照模型”,在该菜单项的处理函数中输入如下代码: void CRealityDemoView::OnPhong() { // 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; param.krs = 0.3;param.kgs = 0.3;param.kbs = 0.3; param.n = 10; m_ball->SetParam(param); m_Reality.AddObject3D(m_ball);//添加景物 hxn,hyn,hzn); cosnh = pow(cosnh,n);//计算cosnh的n次幂 //累加计算景物表面在多个光源照射下的三颜色分量光强度 ird = ird + light.f * (krd * light.irl * cosnl + krs * light.irl * cosnh); igd = igd + light.f * (kgd * light.igl * cosnl + kgs * light.igl * cosnh); ibd = ibd + light.f * (kbd * light.ibl * cosnl + kbs * light.ibl * cosnh); 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);//设置泛光强度 //使用Phong局部光照模型进行绘制 m_Reality.Phong(this->GetDC()); delete m_ball; } 运行应用程序,其绘制结果如图9.7所示,可以看到球体表面因为镜面反射所形成的高光区。 我们也可以在绘制的时候添加多个光源,修改菜单项处理函数,输入如下代码: void CRealityDemoView::OnPhong() { // 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; param.krs = 0.3;param.kgs = 0.3;param.kbs = 1; param.n = 10; 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 = 0;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 = 255;light1.ibl = 255; light1.xn = -1;light1.yn = -0.5;light1.zn = 0.5; m_Reality.AddLight(light1);//添加光源2 m_Reality.SetIA(100,100,100);//设置泛光强度 //使用Phong局部光照模型进行绘制 m_Reality.Phong(this->GetDC()); delete m_ball; } 运行应用程序,结果如图9.8所示。 百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库使用MFC实现真实感图形绘制(4)在线全文阅读。
相关推荐: