2014-12-07 74 views
0

我任務是優化下面的射線追蹤:優化光線追蹤

void Scene::RayTrace() 
{ 

    for (int v = 0; v < fb->h; v++) // all vertical pixels in framebuffer 
    { 
     calculateFPS(); // calculates the current fps and prints it 

     for (int u = 0; u < fb->w; u++) // all horizontal pixels in framebuffer 
     { 

      fb->Set(u, v, 0xFFAAAAAA); // background color 
      fb->SetZ(u, v, FLT_MAX); // sets the Z values to all be maximum at beginning 
      V3 ray = (ppc->c + ppc->a*((float)u + .5f) + ppc->b*((float)v + .5f)).UnitVector(); // gets the camera ray 

      for (int tmi = 0; tmi < tmeshesN; tmi++) // iterates over all triangle meshes 
      { 
       if (!tmeshes[tmi]->enabled) // doesn't render a tmesh if it's not set to be enabled 
        continue; 
       for (int tri = 0; tri < tmeshes[tmi]->trisN; tri++) // iterates over all triangles in the mesh 
       { 
        V3 Vs[3]; // triangle vertices 
        Vs[0] = tmeshes[tmi]->verts[tmeshes[tmi]->tris[3 * tri + 0]]; 
        Vs[1] = tmeshes[tmi]->verts[tmeshes[tmi]->tris[3 * tri + 1]]; 
        Vs[2] = tmeshes[tmi]->verts[tmeshes[tmi]->tris[3 * tri + 2]]; 
        V3 bgt = ppc->C.IntersectRayWithTriangleWithThisOrigin(ray, Vs); // I don't entirely understand what this does 

        if (bgt[2] < 0.0f || bgt[0] < 0.0f || bgt[1] < 0.0f || bgt[0] + bgt[1] > 1.0f) 
         continue; 
        if (fb->zb[(fb->h - 1 - v)*fb->w + u] < bgt[2]) 
         continue; 

        fb->SetZ(u, v, bgt[2]); 
        float alpha = 1.0f - bgt[0] - bgt[1]; 
        float beta = bgt[0]; 
        float gamma = bgt[1]; 
        V3 Cs[3]; // triangle vertex colors 
        Cs[0] = tmeshes[tmi]->cols[tmeshes[tmi]->tris[3 * tri + 0]]; 
        Cs[1] = tmeshes[tmi]->cols[tmeshes[tmi]->tris[3 * tri + 1]]; 
        Cs[2] = tmeshes[tmi]->cols[tmeshes[tmi]->tris[3 * tri + 2]]; 
        V3 color = Cs[0] * alpha + Cs[1] * beta + Cs[2] * gamma; 
        fb->Set(u, v, color.GetColor()); // sets this pixel accordingly 

       } 

      } 


     } 
     fb->redraw(); 
     Fl::check(); 
    } 

} 

兩件事情:

  1. 我並不完全瞭解ppc->C.IntersectRayWithTriangleWithThisOrigin(ray, Vs);一樣。任何人都可以用光線追蹤來解釋這一點嗎?這是我的「平面針孔攝像頭」類中的功能(該功能是給我):

    V3 V3::IntersectRayWithTriangleWithThisOrigin(V3 r, V3 Vs[3]) 
    { 
    
        M33 m; // 3X3 matrix class 
        m.SetColumn(0, Vs[1] - Vs[0]); 
        m.SetColumn(1, Vs[2] - Vs[0]); 
        m.SetColumn(2, r*-1.0f); 
        V3 ret; // Vector3 class 
        V3 &C = *this; 
        ret = m.Inverse() * (C - Vs[0]); 
        return ret; 
    
    } 
    

這樣做的基本步驟是顯而易見的,我只是不明白它實際上

  1. 我該如何去優化這個光線追蹤器?我在網上發現了關於「kd樹」的內容,但我不確定它們有多複雜。有沒有人有一些優化這個簡單的解決方案的好資源?我解釋了那裏有什麼困難。

謝謝!

+0

出於某種原因,我不能拿到第二個功能正確地「編碼」。對於那個很抱歉。 – Jestus 2014-12-07 21:07:27

+0

好像您需要列表中的代碼塊的兩個級別的縮進。否則,對於一般格式幫助HTML評論''總是作爲休息。 (用於分隔兩個直接相連的代碼塊 – 2014-12-07 21:20:12

+0

可能最好的答案是關於該函數的目的是從詢問優化此代碼的人,我個人不會碰到某人如果他們沒有做任何記錄,尤其是在一個像光線追蹤器那樣複雜的程序中,則需要使用10英尺的極點代碼 – user2867288 2014-12-07 21:30:41

回答

0

可能是迄今爲止最大的優化是使用某種bounding volume hierarchy。現在代碼將所有光線與所有對象的所有三角形相交。有了BVH,我們會問:「給出這條射線,哪個三角形相交?」這意味着對於每條光線,通常只需測試與少數基元和三角形的交集,而不是場景中的每個三角形。

+0

您說這是多麼複雜的解決方案?在閱讀時,它似乎只是圍繞對象的邊界框。我的場景只有一個對象,所以我認爲它會相當簡單? – Jestus 2014-12-07 21:38:08

+0

實現這種結構的難度與現場的複雜性無關。儘管[kd trees](http://en.wikipedia.org/wiki/K-d_tree)爲了便於實現,我建議使用[octree](http://en.wikipedia.org/wiki/Octree)如果執行得當,往往會表現得更好。 – 2014-12-07 21:42:00

+0

我想我有點困惑。 如果我錯了,糾正我,但似乎BVH本質上是圍繞每個對象放置一個2D邊界框,然後將它插入八叉樹(或k-d樹)中。如果只有一個對象,那麼八叉樹/ k-d樹不是不必要的嗎? – Jestus 2014-12-08 14:49:00

0
  1. IntersectRayWithTriangleWithThisOrigin

    • 從查找它
    • 它創建逆從三​​角形邊變換矩陣(三角形基本向量是X,Y)
    • 沒有得到Z軸我會期望光線方向存在,而不是像素位置(光線原點)
    • 但可能會誤解某些東西
    • 反正逆矩陣計算是
    • 您正在計算它爲每個像素每個三角形這是一個很大
    • 更快將具有計算逆光線追蹤(一次)之前轉換的每個三角形的矩陣
    • 其中X的最大問題,Y是基礎,Z是垂直面對總是相同的方向相機
    • 他們的攤位,然後只需將您的光線進入,並檢查是否有交集的限制
    • ,這只是matrix*vector很少if!而非逆矩陣計算
    • 另一種方式是代數方式解決射線與平面交叉口
    • ,這應有助於更簡單的公式,然後矩陣求逆後
    • 是,只是一個必然的基礎載體的母校檢查
+0

這真的很有幫助,謝謝! 「你的意思是不要Z軸我期望光線的方向,而不是像素的位置(光線的起源)?」你究竟只做一次逆矩陣計算?它需要不同的射線,如上圖所示:'V3射線=(ppc-> c + ppc-> a *((float)u + .5f)+ ppc-> b *((float)v + .5f ))。UnitVector();' – Jestus 2014-12-08 14:53:00

+0

@Jestus現在你的Z軸由'r * -1.0f'設置,這對我來說毫無意義(這很可能是一些代數方法的結果),如果你使用矩陣相對於三角形而不是相對於射線,那麼矩陣對於所有射線將是恆定的(Z軸是正常的)。但是您需要添加結果計算,因爲此逆矩陣只是從世界座標轉換爲三角形。所以只需計算z = 0的射線的x,y值(全部在三角形座標中)並檢查x,y是否在裏面 – Spektre 2014-12-08 21:09:30