球光照模型

先根据经纬度计算出球面上各点,再把球分成很多小三角形,其中两极除外的四边形也分成上下二个三角形,画三角形(设为P0P1P2),每个点计算该面本身(pl),下面(Pdown),右面(Pright),右下面(Pdownright),求光照时,根据每个点到光源位置的经衰减后得到光线颜色,再分别计算环境光,漫反射光,镜面反射光,加点该点的颜色上(点的颜色是该点右下面的颜色,与距离衰减系数(f[i]=1.0/(c0+c1*dist[i]+c2*dist[i]*dist[i]))和面相对光源的正对率(dCosc=Dot(Lv,N1))成正比,计算时也要检测光源是否能够照到该点上,如果光照不到点上则比率为0),然后再将三维点投影到二维平面上,再根据该面是否消隐来填充三角形.

不过该程序中可能存在问题: 程序中的Lv是从原心(0,0,0)到光源lightP的一个向量,光源的点坐标.改进方法是:对四个面,每个面添加一个中心(或其中某个点)M,Lv=lightP-M即可.不过,程序把照到各面上的光当成平行光也未尝不可.

 

 

 

 

球光照模型_第1张图片 

 

画三角形的源代码如下:

void CTestView::Triangle(CDC *mdc,P3d *p,bool First)//三角形面片

{

    Vector vP10(P1[0]),vP11(P1[1]),vP12(P1[2]);//三角形平面片点矢量

    Vector vPd0(Pdown[0]),vPd1(Pdown[1]),vPd2(Pdown[2]);

    Vector vPr0(Pright[0]),vPr1(Pright[1]),vPr2(Pright[2]);

    Vector vPdr0(Pdownright[0]),vPdr1(Pdownright[1]),vPdr2(Pdownright[2]);

    Vector VectorN1=NormalVector(vP10,vP11,vP12);//主面片法矢量

    Vector VectorNd=NormalVector(vPd0,vPd1,vPd2);//下面片法矢量

    Vector VectorNr=NormalVector(vPr0,vPr1,vPr2);//右面片法矢量

    Vector VectorNdr=NormalVector(vPdr0,vPdr1,vPdr2);//下右面片法矢量

    Vector N1,Nd,Nr,Ndr;

    N1=VectorN1.Unit();Nd=VectorNd.Unit();Nr=VectorNr.Unit();Ndr=VectorNdr.Unit();

    Vector LPosition(lightP.position),Lv=LPosition.Unit();//光源向量

    MyRGB Ambientc=lightP.ambient;

    MyRGB Ambientd=lightP.ambient;

    MyRGB Ambientdr=lightP.ambient;

    MyRGB Ambientr=lightP.ambient;

    Vector vP0(p[0]),Uv;

    Vector VisualP(R*k[5],R*k[6],R*k[4]);//视点矢量球坐标

    Vector VisualV=VisualP-vP0;//视矢量

    Uv=VisualV.Unit();

    if(Chk1)//环境光

    {

       if(First)

       {

           p[0].c=Ambientc;

           p[1].c=Ambientd;

           p[2].c=Ambientr;

       }

       else

       {

           p[0].c=Ambientd;

           p[1].c=Ambientdr;

           p[2].c=Ambientr;

       }

    }

    double c0,c1,c2,dist[3];//c0常数衰减因子,c1线性衰减因子,c2二次衰减因子,dist定点与光源的距离 

    double  f[3];

    c0=0.65;c1=0.00002;c2=0.000001;

    for(int i=0;i<3;i++)

    {

       dist[i]=sqrt((p[i].x-Positionx)*(p[i].x-Positionx)

                   +(p[i].y-Positiony)*(p[i].y-Positiony)

                  +(p[i].z-Positionz)*(p[i].z-Positionz));

       f[i]=1.0/(c0+c1*dist[i]+c2*dist[i]*dist[i]);//衰减后的光系数

       f[i]=Min(f[i]);

    }

    double dCosc,dCosd,dCosr,dCosdr;

    dCosc=Dot(Lv,N1);dCosd=Dot(Lv,Nd);dCosr=Dot(Lv,Nr);dCosdr=Dot(Lv,Ndr);

    dCosc=(dCosc<0.0f)?0.0f:dCosc;//如果<=0表明光照不到该面上,故为0

    dCosd=(dCosd<0.0f)?0.0f:dCosd;

    dCosr=(dCosr<0.0f)?0.0f:dCosr;

    dCosdr=(dCosdr<0.0f)?0.0f:dCosdr;

    MyRGB Diffusec=lightP.diffuse*dCosc;

    MyRGB Diffused=lightP.diffuse*dCosd;

    MyRGB Diffuser=lightP.diffuse*dCosr;

    MyRGB Diffusedr=lightP.diffuse*dCosdr;

    if(Chk2)//漫反射光

    {     

       if(First) //计算每个点的右下平面所接收到的光

       {

p[0].c=Ambientc+Diffusec*f[0];                    p[1].c=Ambientd+Diffused*f[1];

           p[2].c=Ambientr+Diffuser*f[2];

       }

       else

       {

           p[0].c=Ambientd+Diffused*f[0];

           p[1].c=Ambientdr+Diffusedr*f[1];

           p[2].c=Ambientr+Diffuser*f[2];

       }

    }

    if(Chk3)//镜面反射光

    {

       double sCosc,sCosd,sCosdr,sCosr;

       Vector Hvector,Hv;

       Hvector=(LPosition+VisualV)*0.5;//平分矢量

       Hv=Hvector.Unit();

       sCosc=Dot(Hv,N1);sCosd=Dot(Hv,Nd);sCosr=Dot(Hv,Nr);sCosdr=Dot(Hv,Ndr);

       for(int i=0;i<n;i++)//计算n次方

       {

           sCosc*=sCosc;

           sCosd*=sCosd;

           sCosr*=sCosr;

           sCosdr*=sCosdr;

       }

       sCosc=(dCosc<0.0f)?0.0f:sCosc;

       sCosd=(dCosd<0.0f)?0.0f:sCosd;

       sCosr=(dCosr<0.0f)?0.0f:sCosr;

       sCosdr=(dCosdr<0.0f)?0.0f:sCosdr;     

       MyRGB Specularc=lightP.specular*sCosc;

       MyRGB Speculard=lightP.specular*sCosd;

       MyRGB Specularr=lightP.specular*sCosr;

       MyRGB Speculardr=lightP.specular*sCosdr;

       if(First)

       {

           p[0].c=Ambientc+Diffusec*f[0]+Specularc*f[0];

           p[1].c=Ambientd+Diffused*f[1]+Speculard*f[1];

           p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];

       }

       else

       {

           p[0].c=Ambientd+Diffused*f[0]+Speculard*f[0];

           p[1].c=Ambientdr+Diffusedr*f[1]+Speculardr*f[1];

           p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];

       }

    }

   

    for(int k=0;k<3;k++)

    {

       Project(p[k]);             

       Point[k].x=ScreenP.x;

       Point[k].y=ScreenP.y;

       Point[k].c=ScreenP.c;

    }

    if(Dot(Uv,N1)>=0)//根据数量积正负消隐

    {

       CreatBucket();//初始化桶

       Et();//用于建立边表 

       SphereFill(mdc);//进行填充

    }

 }

你可能感兴趣的:(c,vector,ini)