光线跟踪讲解及源代码_第1页
光线跟踪讲解及源代码_第2页
光线跟踪讲解及源代码_第3页
光线跟踪讲解及源代码_第4页
光线跟踪讲解及源代码_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

计算机图形学期末作业作业题目:RayTracing算法的实现学号:SRayTracing算法又叫光线跟踪算法,它能通过递归方法逐个计算每个像素点的光强,然后就可以绘制出高度真实感的图像,因此该方法在图形学领域得到了广泛的应用。RayTracing算法的思想还能应用到移动通信终端定位领域,该领域里的射线跟踪法与此算法思想类似。MFC是微软公司提供的一个类库,以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。MFC在处理Windows窗口应用程序方面具有很大的优势,因此,本文使用MFC在VC6.0里实现RayTracing算法,并给出了该算法的详细讲解。【关键词】Raytracing光线跟踪递归像素光强MFCC++目录TOC\o"1-5"\h\z\o"CurrentDocument"RayTracing算法概述1\o"CurrentDocument"l.lRayTracing算法简介1\o"CurrentDocument"1.2RayTracing算法的实现原理1\o"CurrentDocument"RayTracing算法的具体实现2\o"CurrentDocument"2.1算法的实现环境2\o"CurrentDocument"2.2实现算法的C++程序简介2\o"CurrentDocument"2.3算法的具体实现过程3\o"CurrentDocument"2.4程序运行结果11\o"CurrentDocument"3.总结11\o"CurrentDocument"3.1通过该算法学到的东西11\o"CurrentDocument"3.2本程序未完成的任务12\o"CurrentDocument"4.参考文献12RayTracing算法概述l.lRayTracing算法简介光线跟踪(Raytracing),又称为光迹追踪或光线追迹,它是来自于几何光学的一项通用技术,它通过跟踪与光学表面发生交互作用的光线从而得到光线经过路径的模型。它用于光学系统设计,如照相机镜头、显微镜、望远镜以及双目镜等。这个术语也用于表示三维计算机图形学中的特殊渲染算法,跟踪从眼睛发出的光线而不是光源发出的光线,通过这样一项技术将具有一定数学模型的场景显现出来。这样得到的结果类似于光线投射与扫描线渲染方法的结果,但是这种方法有更好的光学效果,例如对于反射与折射有更准确的模拟效果,并且效率非常高,所以在追求高质量结果时我们经常使用这种方法。在光线跟踪的过程中,我们要考虑许多因素。要跟踪的光线包括反射光线、散射光线和镜面反射光线,利用递归方法并且设定一定的阀值来跟踪;在计算光强度时,我们要考虑场景中物体的反射系数、漫反射系数和镜面反射系数,还有交点处的法向量,出射光线的方向向量;在求视线以及反射光线和场景中物体的交点时,要计算出离眼睛以及出射点最近的交点作为击中点,得到击中点之后,我们就可以计算出击中点的坐标。最终,通过三个公式计算出每一个像素点处三种光线的光强值,再将三个光强值相加,就得到了该像素点出的总光强值,最后将颜色缓冲器中的三种颜色值输出到屏幕上,就得到了我们需要的光线跟踪图像。1.2RayTracing算法的实现原理(1)对图像中的每一个像素,创建从视点射向该像素的光线;(2)初始化最近时间T为一个很大的值,离视点最近的物体指针设为空值;(3)对场景中的每一个物体,如果从视点出发的光线和物体相交,且交点处的时间t比最近时间T小,则将t的值赋给最近时间T,并设置该物体为最近物体,将物体指针指向该物体;(4)经过第三步的计算后,如果最近物体指针指向空值NULL,则用背景色填充该像素。如果该指针指向光源,则用光源的颜色填充该像素;(5)如果最近物体指针指向的既不是NULL也不是光源,则从交点向光源发出一条光线,并判断该光线在射向光源的过程中是否被遮挡,如果被遮挡,则该交点对光源不可见;(6)若第五步中的光线在射向光源的过程中没有被遮挡,则该交点对光源可见。那么从交点到光源做出一条入射光线,并将入射光线单位化。求出物体表面该交点处的法向量之后,我们就可以利用公式计算出该点的散射光强值、镜面反射光强值,并将它们加到总光强值上;(7)对于反射光线,我们先利用视线和交点处的法向向量求出视线的反射光线,并将其单位化。然后以交点为视点,以交点处的反射光线为视线递归地进行跟踪,直至达到最大递归深度,我们就得到了加上递归反射光强的总光强值;(8)最后,我们逐行逐个像素的将三种颜色值输出到屏幕上。至此,通过光线跟踪就得到了一幅质量很高的图像。RayTracing算法的具体实现2.1算法的实现环境(1)编程环境:MicrosoftVisualC++6.0;(2)图形类类库:MFC;(3)编程语言:C++;(4)显示设备:电脑显示器。2.2实现算法的C++程序简介该程序由C++编写而成,主要分为以下几个部分:(1)点和向量的定义及运算;(2)光线类的定义及操作;(3)场景中各种物体的材质特征定义和求交计算;(4)光线跟踪过程及图像绘制;

2.3算法的具体实现过程点和向量的定义及运算classCUector3public:CUector3();CUector3(floatx,floaty,floatz);uoidSet(floatx,floaty,floatz};uoidNormalize();FloatLength();uoiduoiduoidoperator+=operator-=operator*=operator*=(CUector3&u);(CUector3operator+=operator-=operator*=operator*=(CUector3&u);(CUector3&u)-(floatF);(CUector3&u);CUector3operator-friendfriendfriendfriendFriendFriendFriendCUector3CUector3CUector3CUector3CUectorS();operatoroperatoroperatoroperatoroperator(const(const(const(const(FloatCUector3&CUector3&CUector3&CUectorS&u1,constCUector3&u1,constCUector3&u,floatf);u1,constCUector3&f,constCU&ctor3&u):u2);u2);U2);floatDotProduct(constCUectorSKu1,constCUector3&u2);CUectorSCrossProduct(constCUector36:5,constCUector3ft;unionstruct<floatm_x,m_y,m_zstruct<floatrTgrb;同typedeftypedefCUector3CColor;CUector3typedeftypedefCVector类用来存储向量的坐标值,设置向量的三个坐标值,对向量进行求和、求差、点积、叉积运算,这些运算通过运算符重载来完成。使用typedef将CVector类重定义为CColor类和CPoint类,从而实现对像素点颜色和点的设置和运算。CVector类公用成员函数的声明不再详述。光线类的定义及操作classCRmypublic:CRayC);CRai^(CUector3&origin,CUectordirection);voidSetOrigin(CUector3&origin);voidSetDirection(CUector36:direction);CUector3&GetOrigin();CUector3&GetDirection();private:CUector3m_origin;m_direction;CUectorSCRaij;;CRa^r():m_origin(CUector3(L09O))9m_direction(CUector3C0,O90))CRay::CRayCCUector3&origin,CUector3&direction):moriginCorigin),mdirectionfdirection)5—5morigin=origin;|of—…indirection=direction;returnmorigin;returnindirection;m_direction;光线包含两个特征参数,即光线的起点和方向。以上程序段能实现对光线的起点和方向的设置和获取,由起点和方向能唯一地确定出一条光线,并能结合“时间”t写出该光线的方程,以用来进行求交计算。场景中各种物体的材质特征定义和求交计算镜面反射),-2);,0-5f镜面反射),-2);,0-5f));25.BF1;,0-5f));18_Bf);,1-0f));,0-6f);,1-0f));CMatGriJl();™CMateri^l();voidS^tColor(CColorfccolor);CColorC^tColor();voidSetDifFuse(floatdiffuse);floatCetDiFfuse();voidSetSpecular(Floatspecular);floatGetSpecular();voidSetReflection(FloatreFlection);floatGetReflection();private:CColormeo1or;floatmdiffuse;floatmspecular;floatmreflection;通过上面的程序段我们能设置和获取场景中各物体的散射系数、系数和反射系数,以用来计算各像素点处的光强值。index++;m_priniitiues[index]=neuCPlane1111(CUector3fB.BF,0.OF,1.BFm_priniitiues[index]->SetNa[ne("bacl<plane");m_priniitiues[index]->GetMaterial()->SetR?Flection(B.BF):m_primitiues[index]->GetMaterial()->SetSpecular(0.QF);m_primitlues[index]->GetMaterial()->SetDiFfuse(B.6F);m_primitlues[index]->GetMaterial()->SetColor(CColor(B.5F,B.3Findex++;mprimitiuesrindex]=neuCPlane3333(CUector3C1.BF.0.0F,0.0Fm_pri[iitiues[index]->SetNa[ie("Leftplane");m_priniitiues[index]->GetMaterial()->SetReFlection(Q.OF);m_primitiues[index]->GetMaterial()->SetSpecular(0.QF);m_primitlues[index]->GetMaterial()->SetDiFfuse(O.6F);m_primitlues[index]->GetMaterial()->SetColor(CColor(0.5F,B.3Findex++;m_priniitiues[index]=neuCSphere(CPoint3(15.BF,2_Bf,15.BF),m_priniitiues[index]->SetNa[ne("sphere1");m_primitlues[index]->GetMaterial()->SetReFlection(B.6F):m_primitiue5[index]>GetMaterial(J->SetSpecular(0.6T);m_primitlues[index]->GetMaterial()->SetDiFfuse(0.6F);m_primitiues[index]->GetMaterial()->SetColor(CColor(1.OF,1.BFindex++;m_priniitiues[index]=neuCSph?re(CPoint3(25.BF,28.BF,48.BF)m_priniitiues[index]->SetNa[ne("lightsource1">;m_priniitiues[index]->SetLight(true);m_primitiues[index]->GetMaterial()->SetColor(CColor(1.BF,1.BF通过上面的程序可以具体设置场景中每个物体的位置参数、散射系数、镜面反射系数和反射系数。对球体和光源来说,我们设置它的球心坐标和半径;对地面和多边形来说,我们设置它的单位法向量和距坐标原点的距离,这样以来,它们的位置就能够确定出来。CSphere::CSpherefCPointaficenter,floatradius)incenLef-Leuter;m_rdJiub=rddiub;CUectorS&CSphcrc::GctCentcr[)returnmcenter;ciipcrnrsi:%pftprp::GPtNnrmaI(i:Fnirinn)4returnCUDctorSCpacitinn-m_ccntcr>*(1.Gf/n_radiu5>;}~-上面的程序用来获得球体的球心和半径坐标,以及球面上position位置处的单位法向量。得到这三个值之后,我们就可以对球体进行求交计算。intCSphere::Intersect(CRaijEray,FloatKt)//d*L*2十b*L//H=U.UFloata=DorPrnmjrr(rAij.iiprDirpcrian(),ray.GPtDirprrinnf));ffn=?疝,-i;jfloatb=2*DDtPrDduct(ray.C9tDirectian(),(rj^.CptDrigin(}-m_center));//c-||0-C||"2-r"2~Floatc-(Float)pDLF(CUcctorO(ray.CetOriginf)-n_ccntDij).Lcngth(J,2)-m_radiu3xn_ijadius;//jl-b*2-4吓旺Floatdelta-b^b-k^a«c;intfesulL-HISS;IF[delta>0)<Floatt1=(-b-■jqrtl-tdPirA)),[7*a);FlnMt?=(-b*EqrtHnpEHJ*a);Lf(t2>3){if(t1<0){ifftZ<tl<L=L2;HPRHir=INFHIM;else{if(t1<t]retuLL-HIT;returnresult;上面程序的功能是针对某条射线对球体进行求交计算,返回的结果是“击中”或者“丢失”或者“光线起点在内部”。当delta大于0时,该光线和球体表面必有两个交点,击中时间分别为t1和t2,且t1<t2,当t1和t2均大于0时,光线起点必在球体外部,此时的击中时间为t1,返回值为“1”。当t1<0且t2>0时,光线起点在球体内部,此时的返回值为“-1”。当delta小于或者等于0时,我们认为光线与球体无交点,此时返回值为“0”。intCPlane::Intersect(CRay&ray,Floatst)Floatdot=DotProduct(m_normal,ray.GetDirection());if(dot==0)//parallelreturnMISS;else{//t=-(N*0+d)/(N*U);floatto=-CDotProduct(m_nornial,ray.GetOrigin())+nd)/dot;if(to>Bte<t)-一t=tfl;returnHIT;>elsereturnMISS;上面的程序实现了光线对地平面(无限大平面)的求交计算,当单位法向量和视线垂直时,dot=0,此时视线与平面平行,函数返回值为MISS=0。当单位法向量和视线不垂直时,视线和平面必有交点,可以通过公式计算出击中时间t0,当t0大于0且t0不是无穷大时,则把最近击中时间设置为t0,函数返回值为HIT=1。intGPlane1111::]ntei-5ect(CHayttray,fLcatGt)<^Pointspoint;//初燃M、:■■而氏女巨floatdut=DotPriBidluctCn_nurTiidlBtBy-GetDirection());iF(dot==returnMISS;else(//t-Float=-(motProductfninotniai,_GPtnrlgin(])■+/dot;if(tO>O£&tO<t)-'<t=tu;point.rai/.GetOrigin()■*ray.GetDircction()*t;"求交点坐标if(pointhr_x>-25&&point.n_x<-13&&point&&point.n_y《15)returnHU;elsereturnrnss;)elserpturnMISS;

上面的程序通过视线与无限大平面求交的方法来实现四边形的绘制,当求出击中时间t后,将t代入光线方程即可求出击中点的三维坐标值。以上面程序中多面体的后面为例,其单位法向量与z轴平行,所以我们只需要将击中点的x坐标值和y坐标值分别与四边形的范围进行比较,x值和y值中任何一个超出范围,就将该点抛弃;只有x值和y值均在四边形范围内时,我们才将该点的返回值设为HIT=0。通过这种方法我们能绘制出一个四边形。左面和底面的绘制原理与后面类似,在此不再赘述。光线跟踪过程及图像绘制CPrinitiue*CFayFracer::Raytrace(CRa^&ray?CColorKtatalCalcr,intdepth,FloatreFlactianlndexpFloatst)iF(depth>TRftCE_DEPTH)//停止递归returnNJLL;t=10O99CG.OF;GPiimitiue*primitive=NULL;intresult;intfornuni=m_pScene->GetPrinitiueHuni();…"intforCPrinitiue*currentPrinitiue=m_pScene->GetPriniitiye(i);intcirrentfiesult;currentResult=CLrrentPrinitiue->Intersect(ra^j,t);if(currentResult!=MISS)primitive=currentPrinitiue;result=currentResult;iF(prinitiue==NULL)H该光线和任何物体都没有交点return0;iF(prinitiue-JIsLightO)//该光线直接照射到光源上,所以将光源的两色曜该点(totalColor=prinitiue->GetHaterial()->CetColor();>Raytrace函数共有5个参数,分别为视线、交点处的总光强、递归深度、反射索引和最近击中时间t。当递归深度大于最大递归深度时函数停止运行。初始化物体指针使其指向NULL,然后通过一个循环遍历场景中的所有物体,依次对物体求交,则t的值会不断的变化,最终变成一个所有物体击中时间中的最小值。最后得到的物体指针指向最小t对应的物体,result为最小t对应的返回结果。如果物体指针指向空NULL,则该光线和场景中的任何物体都没有交点;如果物体指针指向光源,则将光源的颜色值赋给总光强。elseCPontSpoint;//诿光族与场景中距期最近的物林的豪卮„pout=■r^ji.GetDriginO*rg.&Et・irectig()■t;"求出诙乂点坐标intmin=mjpS.c:Bn@->teEPrfimitiu|DNui®£):Fut(inti-0;i<nun;i**)"逼历场号中的每一个物件.<ffrinltiw81p-n_p5cfne~>GetPriirlti^e(i);if0-MsLightO)〃如熟轴■指向光海(CFriiririue*plight-p;Dooluisibl?-trie;if(pLiyhL->Gi!LTypy()==CP-iiiitiuy::SPHERE1{_IWMtnrlrtirpnrinn:((ns^rrpKip]〉|:时而廿叶〔)-[ini丁*虽1「声工.‘:•「-.予floatt=fliK«tion.LMigUi(l:打尊向晕削*窟即从玄点割曲避瑜亡桥焉的#面间”tiliiutLijii.NurndlijHfJ:ff'-\,^:TM二后七CRajr-CRaj(poinr«directi9r«EFSILON,dirtction);m从交点向光!源,出—亲光投,*directicn«€PSILCttS-^)7殿窗舶捋麻面重各从而使独产生正臼值。■/For(intj-B;j<m_p如的叶外HPriraitiupHiim。;』**]/咧断页髓睡与场惠中的除』鲤也物休相吏,着相.则i免逢在M向光镰谶愀魂,那玄深点「光成可见>VDPririitiue#pl-n_pScBni?->GetPrindtiy&(j);if((pl•-plight)如(p1->[ntErEect(rpt)Intersect(rp和册措)不可见<^^'oi&ible=False;break;先利用上面求出的最近击中时间t求出交点坐标。然后从交点向光源中心发出一条光线,求出该光线的时间方程,然后判断该光线是否与场景中的除光源外的物体相交,若相交,则该光线在射向光源的途中被遮挡,则该交点对光源不可见。if(yisibie)CUectorSL-((CSptiere*)pLight)-JGetCenter(]-point;〃从交点射向光源的入射线L.NornalizcO;〃入射嬉的单位化CU^ctorSH=prinitiut->C?tNnrnal(paLnt]:〃求出物体表面上交点处的法向量口if(prLnitive->GEtNaterial()->GetDifFuse[]>。)『卅算散射光强(//k*I*(N•L)_DCalardiffuseColor=primitive->CetHaterial()->CetDiFfuse()〃散射系数pi1gnr->i;prriarpriai()->i;pti:oinr()〃之[肩就臣DotPrcductCH,L)〃法向重和R甫光线的点弟prinitlue->GetHaterial(j->GetColor();“物体材质颜色tutaLColar*=difFuseColor;〃誓散射光强加到怎耽强上if(prinitiup->CptNaterial()->CetSppcijLarO>心〃计算镜面反射光强CU?ctor3U=-ray.GetDirection[)//R-2«N«(HL)-LC^ctorSR-2.0f*N*DotPrDduct[H,L)-L;"入射光的反射光我i:i;nInr<jpprimri:nJnr=plignr->iiPtMarprlLu->iipri:nJnruprlrrttlue->Getnaterlal(j->Get5pecuiar(jpuwftSuLFrudLulfU.-R).36)MriniLiye->GeLlldlKridip->GeLCulur[);//;-写招.予j玄节町轴触式totaLColar*-wpEularCtJlDf;〃特榜;面反射光强加到总光强若该交点对光源可见,则从交点向光源发出一条光线当作入射线,然后求出交点处的单位法向量,然后通过函数调用分别得到该物体的散射系数和镜面反射系数,再通过两个公式分别计算出该交点处的散射光光强和镜面反射光光强,并把这两个光强值加到总光强上。〃计算三E翎振排勺光宜floatreflection=pri[nitiue->GEtMaterial()->CetReflectian();if((reflection〉B.9F]曲[depth<TRfiCE_DEPTH])<一CUector3H=prinitiue->GetNonnal(point);〃计算出交点处的■向童RUpctnrlriirpcHnn=raij.fiprD-irpnHnn()-?.flF*DntPsriiirHr珂-RFfDirpMinn[),N]*H;/_£CRapreFlectionRayCpolnt+direction*EPSILON,MrEctMV丛交点出发的反射光线CColorrEflECtionColar(0.9F,9.OF,9.6F);〃份詈弱杜线的希;floatt0;//goontracingthercricctcdragRaytrace(reFlectianRay,reFlectianColor,depth+1,reFlactionindex,t9);reflectinnCDlor=reflection*reFlectionCalor*primitiue->Cetl1aterial()->CetColor[]tatalCoLor,=refLectionCoLor;〃将反射光强加到总光强上反射光的光强通过递归的方法实现,先求出物体的反射系数,计算出交点处的单位法向量。然后计算出从视点射向交点的光线的反射光线。然后以该反射光线为视线,以反射光强为总光强继续进行光线跟踪,且达到递归深度后停止递归,将得到的总光强(即反射光光强)加到原来的总光强上。至此,该像素点处的总光强已求出,接下来就可以进行该像素点的绘制。booLCRayTracer::Render^)(if(n_currentLine>=n_height)〃噬行噎像素绘制returntrue;CPoint30(19.Bf,28.0F,10G.8F);"眼睛所在位置坐标for(intx=0;k

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论