文章目錄
1,原理
由於從光源發出的光線有無窮多條,使得直接從光源出發對光線進行跟蹤變得非常困難。實際上,從光源發出的光線只有少數經由情境的反射和透射(折射)後到達觀察者的眼中。為此標準光線跟蹤演算法採用逆向跟蹤技術完成整個情境的繪製。
光線跟蹤思路:從視點出發,通過映像平面上每個像素中心向情境發出一條光線,光線的起點為視點,方向為像素中心和視點連線單位向量。光線與離視點最近的情境物體表面交點有三種可能:
- 當前交點所在的物體表面為理想漫射面,跟蹤結束。
- 當前交點所在的物體表面為理想鏡面,光線沿其鏡面發射方向繼續跟蹤。
- 當前交點所在的物體表面為規則透射面,光線沿其規則透射方向繼續跟蹤。
圖-1 三個半透明玻璃球情境跟蹤圖
-1中,情境中有三個半透明玻璃球,視點發出光線與情境最近交點為P1,使用任意局部光照模型(opengl使用的是phong模型)可以計算出P1點處的局部光亮度Ilocal,為了計算周圍環境在P1點處產生的鏡面發射光和規則折射光,光線1在P1點處衍生出兩支光線:反射光2和折射光3。P1處的光照由三部分組成:Ilocal + ks * I2 + kt * I3
I3 為折射光線3的顏色,Kt為折射率
I2 為反射光線2的顏色,Ks為反射率
I3 和I2 的計算需要遞迴。
2,虛擬碼
void TraceRay(const Vec3& start, const Vec3& direction, int depth, Color& color)<br />{<br />Vec3 intersectionPoint, reflectedDirection, transmittedDirection;<br />Color localColor, reflectedColor, transmittedColor;<br />if (depth >= MAX_DEPTH) {<br />color = Black; //#000<br />}<br />else {<br />Ray ray(start, direction); //取start起點,方向direction為跟蹤射線;<br />if ( !scene->HasIntersection(ray) )<br />color = BackgroundColor;<br />else {<br />計算理起始點start最近的交點intersectionPoint,<br />記錄相交物體intersectionObject,</p><p>// #1<br />Shade(intersectionObject, intersectionPoint, localColor);</p><p>// #2<br />if ( intersectionPoint所在面為鏡面 ) {<br />計算跟蹤光想S在intersectionPoint處的反射光線方向reflectedDirection,<br />TraceRay(intersectionPoint, reflectedDirection, depth+1, reflectedColor);<br />}<br />// #3<br />if ( intersectionPoint所在的表面為透明面 ) {<br />計算跟蹤光線S在intersectionPoint處的規則透射光線方向transmittedDirection,<br />TraceRay(intersectionPoint, transmittedDirection, depth+1, transmittedColor);<br />}<br />// #summarize<br />color = localColor + Ks * reflectedColor + Kt * transmittedColor;<br />}// else<br />} //else<br />}<br />// 局部光照模型計算交點intersectionPoint處的局部光亮度localColor<br />void Shade(const Object& intersectionObj, const Vec3& intersectionPoint, Color& localColor)<br />{<br />確定intersectionObj在intersectionPoint處的單位法向量N,<br />漫反射係數Kd,<br />鏡面反射係數Ks,<br />環境反射係數Ka;<br />localColor = Ka * Ia;//Ia為環境光線亮度<br />for ( 每一個點光源PointLight ) {<br />計算入射光線單位向量L和虛擬鏡面法向單位向量H,<br />// 由Phong模型計算光源PointLight在intersectionPoint處的漫反射和鏡面反射光亮度<br />localColor += ( Ipointlight * ( Kd * (N.dot(L)) + Ks * (N.dot(H))^n ) );<br />}<br />}