光線跟蹤講解及源代碼_第1頁
光線跟蹤講解及源代碼_第2頁
光線跟蹤講解及源代碼_第3頁
光線跟蹤講解及源代碼_第4頁
光線跟蹤講解及源代碼_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

計算機圖形學(xué)期末作業(yè)作業(yè)題目:RayTracing算法的實現(xiàn)學(xué)號:SRayTracing算法又叫光線跟蹤算法,它能通過遞歸方法逐個計算每個像素點的光強,然后就可以繪制出高度真實感的圖像,因此該方法在圖形學(xué)領(lǐng)域得到了廣泛的應(yīng)用。RayTracing算法的思想還能應(yīng)用到移動通信終端定位領(lǐng)域,該領(lǐng)域里的射線跟蹤法與此算法思想類似。MFC是微軟公司提供的一個類庫,以C++類的形式封裝了Windows的API,并且包含一個應(yīng)用程序框架,以減少應(yīng)用程序開發(fā)人員的工作量。其中包含的類包含大量Windows句柄封裝類和很多Windows的內(nèi)建控件和組件的封裝類。MFC在處理Windows窗口應(yīng)用程序方面具有很大的優(yōu)勢,因此,本文使用MFC在VC6.0里實現(xiàn)RayTracing算法,并給出了該算法的詳細(xì)講解?!娟P(guān)鍵詞】Raytracing光線跟蹤遞歸像素光強MFCC++目錄TOC\o"1-5"\h\z\o"CurrentDocument"RayTracing算法概述1\o"CurrentDocument"l.lRayTracing算法簡介1\o"CurrentDocument"1.2RayTracing算法的實現(xiàn)原理1\o"CurrentDocument"RayTracing算法的具體實現(xiàn)2\o"CurrentDocument"2.1算法的實現(xiàn)環(huán)境2\o"CurrentDocument"2.2實現(xiàn)算法的C++程序簡介2\o"CurrentDocument"2.3算法的具體實現(xiàn)過程3\o"CurrentDocument"2.4程序運行結(jié)果11\o"CurrentDocument"3.總結(jié)11\o"CurrentDocument"3.1通過該算法學(xué)到的東西11\o"CurrentDocument"3.2本程序未完成的任務(wù)12\o"CurrentDocument"4.參考文獻(xiàn)12RayTracing算法概述l.lRayTracing算法簡介光線跟蹤(Raytracing),又稱為光跡追蹤或光線追跡,它是來自于幾何光學(xué)的一項通用技術(shù),它通過跟蹤與光學(xué)表面發(fā)生交互作用的光線從而得到光線經(jīng)過路徑的模型。它用于光學(xué)系統(tǒng)設(shè)計,如照相機鏡頭、顯微鏡、望遠(yuǎn)鏡以及雙目鏡等。這個術(shù)語也用于表示三維計算機圖形學(xué)中的特殊渲染算法,跟蹤從眼睛發(fā)出的光線而不是光源發(fā)出的光線,通過這樣一項技術(shù)將具有一定數(shù)學(xué)模型的場景顯現(xiàn)出來。這樣得到的結(jié)果類似于光線投射與掃描線渲染方法的結(jié)果,但是這種方法有更好的光學(xué)效果,例如對于反射與折射有更準(zhǔn)確的模擬效果,并且效率非常高,所以在追求高質(zhì)量結(jié)果時我們經(jīng)常使用這種方法。在光線跟蹤的過程中,我們要考慮許多因素。要跟蹤的光線包括反射光線、散射光線和鏡面反射光線,利用遞歸方法并且設(shè)定一定的閥值來跟蹤;在計算光強度時,我們要考慮場景中物體的反射系數(shù)、漫反射系數(shù)和鏡面反射系數(shù),還有交點處的法向量,出射光線的方向向量;在求視線以及反射光線和場景中物體的交點時,要計算出離眼睛以及出射點最近的交點作為擊中點,得到擊中點之后,我們就可以計算出擊中點的坐標(biāo)。最終,通過三個公式計算出每一個像素點處三種光線的光強值,再將三個光強值相加,就得到了該像素點出的總光強值,最后將顏色緩沖器中的三種顏色值輸出到屏幕上,就得到了我們需要的光線跟蹤圖像。1.2RayTracing算法的實現(xiàn)原理(1)對圖像中的每一個像素,創(chuàng)建從視點射向該像素的光線;(2)初始化最近時間T為一個很大的值,離視點最近的物體指針設(shè)為空值;(3)對場景中的每一個物體,如果從視點出發(fā)的光線和物體相交,且交點處的時間t比最近時間T小,則將t的值賦給最近時間T,并設(shè)置該物體為最近物體,將物體指針指向該物體;(4)經(jīng)過第三步的計算后,如果最近物體指針指向空值NULL,則用背景色填充該像素。如果該指針指向光源,則用光源的顏色填充該像素;(5)如果最近物體指針指向的既不是NULL也不是光源,則從交點向光源發(fā)出一條光線,并判斷該光線在射向光源的過程中是否被遮擋,如果被遮擋,則該交點對光源不可見;(6)若第五步中的光線在射向光源的過程中沒有被遮擋,則該交點對光源可見。那么從交點到光源做出一條入射光線,并將入射光線單位化。求出物體表面該交點處的法向量之后,我們就可以利用公式計算出該點的散射光強值、鏡面反射光強值,并將它們加到總光強值上;(7)對于反射光線,我們先利用視線和交點處的法向向量求出視線的反射光線,并將其單位化。然后以交點為視點,以交點處的反射光線為視線遞歸地進(jìn)行跟蹤,直至達(dá)到最大遞歸深度,我們就得到了加上遞歸反射光強的總光強值;(8)最后,我們逐行逐個像素的將三種顏色值輸出到屏幕上。至此,通過光線跟蹤就得到了一幅質(zhì)量很高的圖像。RayTracing算法的具體實現(xiàn)2.1算法的實現(xiàn)環(huán)境(1)編程環(huán)境:MicrosoftVisualC++6.0;(2)圖形類類庫:MFC;(3)編程語言:C++;(4)顯示設(shè)備:電腦顯示器。2.2實現(xiàn)算法的C++程序簡介該程序由C++編寫而成,主要分為以下幾個部分:(1)點和向量的定義及運算;(2)光線類的定義及操作;(3)場景中各種物體的材質(zhì)特征定義和求交計算;(4)光線跟蹤過程及圖像繪制;

2.3算法的具體實現(xiàn)過程點和向量的定義及運算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類用來存儲向量的坐標(biāo)值,設(shè)置向量的三個坐標(biāo)值,對向量進(jìn)行求和、求差、點積、叉積運算,這些運算通過運算符重載來完成。使用typedef將CVector類重定義為CColor類和CPoint類,從而實現(xiàn)對像素點顏色和點的設(shè)置和運算。CVector類公用成員函數(shù)的聲明不再詳述。光線類的定義及操作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;光線包含兩個特征參數(shù),即光線的起點和方向。以上程序段能實現(xiàn)對光線的起點和方向的設(shè)置和獲取,由起點和方向能唯一地確定出一條光線,并能結(jié)合“時間”t寫出該光線的方程,以用來進(jìn)行求交計算。場景中各種物體的材質(zhì)特征定義和求交計算鏡面反射),-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;通過上面的程序段我們能設(shè)置和獲取場景中各物體的散射系數(shù)、系數(shù)和反射系數(shù),以用來計算各像素點處的光強值。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通過上面的程序可以具體設(shè)置場景中每個物體的位置參數(shù)、散射系數(shù)、鏡面反射系數(shù)和反射系數(shù)。對球體和光源來說,我們設(shè)置它的球心坐標(biāo)和半徑;對地面和多邊形來說,我們設(shè)置它的單位法向量和距坐標(biāo)原點的距離,這樣以來,它們的位置就能夠確定出來。CSphere::CSpherefCPointaficenter,floatradius)incenLef-Leuter;m_rdJiub=rddiub;CUectorS&CSphcrc::GctCentcr[)returnmcenter;ciipcrnrsi:%pftprp::GPtNnrmaI(i:Fnirinn)4returnCUDctorSCpacitinn-m_ccntcr>*(1.Gf/n_radiu5>;}~-上面的程序用來獲得球體的球心和半徑坐標(biāo),以及球面上position位置處的單位法向量。得到這三個值之后,我們就可以對球體進(jìn)行求交計算。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;上面程序的功能是針對某條射線對球體進(jìn)行求交計算,返回的結(jié)果是“擊中”或者“丟失”或者“光線起點在內(nèi)部”。當(dāng)delta大于0時,該光線和球體表面必有兩個交點,擊中時間分別為t1和t2,且t1<t2,當(dāng)t1和t2均大于0時,光線起點必在球體外部,此時的擊中時間為t1,返回值為“1”。當(dāng)t1<0且t2>0時,光線起點在球體內(nèi)部,此時的返回值為“-1”。當(dāng)delta小于或者等于0時,我們認(rèn)為光線與球體無交點,此時返回值為“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;上面的程序?qū)崿F(xiàn)了光線對地平面(無限大平面)的求交計算,當(dāng)單位法向量和視線垂直時,dot=0,此時視線與平面平行,函數(shù)返回值為MISS=0。當(dāng)單位法向量和視線不垂直時,視線和平面必有交點,可以通過公式計算出擊中時間t0,當(dāng)t0大于0且t0不是無窮大時,則把最近擊中時間設(shè)置為t0,函數(shù)返回值為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;"求交點坐標(biāo)if(pointhr_x>-25&&point.n_x<-13&&point&&point.n_y《15)returnHU;elsereturnrnss;)elserpturnMISS;

上面的程序通過視線與無限大平面求交的方法來實現(xiàn)四邊形的繪制,當(dāng)求出擊中時間t后,將t代入光線方程即可求出擊中點的三維坐標(biāo)值。以上面程序中多面體的后面為例,其單位法向量與z軸平行,所以我們只需要將擊中點的x坐標(biāo)值和y坐標(biāo)值分別與四邊形的范圍進(jìn)行比較,x值和y值中任何一個超出范圍,就將該點拋棄;只有x值和y值均在四邊形范圍內(nèi)時,我們才將該點的返回值設(shè)為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函數(shù)共有5個參數(shù),分別為視線、交點處的總光強、遞歸深度、反射索引和最近擊中時間t。當(dāng)遞歸深度大于最大遞歸深度時函數(shù)停止運行。初始化物體指針使其指向NULL,然后通過一個循環(huán)遍歷場景中的所有物體,依次對物體求交,則t的值會不斷的變化,最終變成一個所有物體擊中時間中的最小值。最后得到的物體指針指向最小t對應(yīng)的物體,result為最小t對應(yīng)的返回結(jié)果。如果物體指針指向空NULL,則該光線和場景中的任何物體都沒有交點;如果物體指針指向光源,則將光源的顏色值賦給總光強。elseCPontSpoint;//諉光族與場景中距期最近的物林的豪卮?pout=■r^ji.GetDriginO*rg.&Et?irectig()■t;"求出詼乂點坐標(biāo)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殿窗舶捋麻面重各從而使獨產(chǎn)生正臼值。■/For(intj-B;j<m_p如的葉外HPriraitiupHiim。;』**]/咧?jǐn)囗撍杷c場惠中的除』鯉也物休相吏,著相.則i免逢在M向光鐮讖愀魂,那玄深點「光成可見>VDPririitiue#pl-n_pScBni?->GetPrindtiy&(j);if((pl?-plight)如(p1->[ntErEect(rpt)Intersect(rp和冊措)不可見<^^'oi&ible=False;break;先利用上面求出的最近擊中時間t求出交點坐標(biāo)。然后從交點向光源中心發(fā)出一條光線,求出該光線的時間方程,然后判斷該光線是否與場景中的除光源外的物體相交,若相交,則該光線在射向光源的途中被遮擋,則該交點對光源不可見。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()〃散射系數(shù)pi1gnr->i;prriarpriai()->i;pti:oinr()〃之[肩就臣DotPrcductCH,L)〃法向重和R甫光線的點弟prinitlue->GetHaterial(j->GetColor();“物體材質(zhì)顏色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玄節(jié)町軸觸式totaLColar*-wpEularCtJlDf;〃特榜;面反射光強加到總光強若該交點對光源可見,則從交點向光源發(fā)出一條光線當(dāng)作入射線,然后求出交點處的單位法向量,然后通過函數(shù)調(diào)用分別得到該物體的散射系數(shù)和鏡面反射系數(shù),再通過兩個公式分別計算出該交點處的散射光光強和鏡面反射光光強,并把這兩個光強值加到總光強上?!ㄓ嬎闳鼸翎振排勺光宜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叢交點出發(fā)的反射光線CColorrEflECtionColar(0.9F,9.OF,9.6F);〃份詈弱杜線的希;floatt0;//goontracingthercricctcdragRaytrace(reFlectianRay,reFlectianColor,depth+1,reFlactionindex,t9);reflectinnCDlor=reflection*reFlectionCalor*primitiue->Cetl1aterial()->CetColor[]tatalCoLor,=refLectionCoLor;〃將反射光強加到總光強上反射光的光強通過遞歸的方法實現(xiàn),先求出物體的反射系數(shù),計算出交點處的單位法向量。然后計算出從視點射向交點的光線的反射光線。然后以該反射光線為視線,以反射光強為總光強繼續(xù)進(jìn)行光線跟蹤,且達(dá)到遞歸深度后停止遞歸,將得到的總光強(即反射光光強)加到原來的總光強上。至此,該像素點處的總光強已求出,接下來就可以進(jìn)行該像素點的繪制。booLCRayTracer::Render^)(if(n_currentLine>=n_height)〃噬行噎像素繪制returntrue;CPoint30(19.Bf,28.0F,10G.8F);"眼睛所在位置坐標(biāo)for(intx=0;k

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論