Optimize Triangle Mesh Vertex

來源:互聯網
上載者:User

Optimize Triangle Mesh Vertex    

僅供個人學習使用,請勿轉載,勿用於任何商業用途。
    
    對同一個triangle mesh,用TriangleList還是TriangleStrip渲染比較快,快在哪裡?大部分人都會不加思索的認為strip比較快,原因在於strip有更好的緩衝。這樣的回答其實是完全錯誤的。對以相同方式排列的mesh來說,strip唯一的優點只在於需要的索引比較少,對n個三角形只需要n+2個索引,而list需要n*3個。雖然較少的資料意味著更低的頻寬佔用,但實際情況下,卻對渲染影響不大,無論list和strip,索引本身的資料量就不大(與vertex相比),因此微小的優勢幾乎很難察覺出來。

    那麼對同一個mesh,不同的渲染方法會不會有差別,如果有,差別在哪裡呢?答案顯然是肯定的,否則就不會有這篇文章的存在。真正決定一個mesh渲染效率的是其索引相片順序或者說三角形排列順序,優秀的相片順序可以明顯減少頂點和像素處理的操作。

    這就要從硬體的構架上說起了,顯卡上除了眾所周知的顯存外,在GPU晶片上還有一塊非常快的緩衝,根據資源類型的不同,這塊緩衝又分為紋理緩衝,頂點緩衝等等。這裡我們主要關心頂點緩衝。是nvidia G80構架之前的GPU流水線:

    可以看到頂點緩衝有兩塊(vCache),一塊稱為pre-T&L cache另一塊稱為Post-T&L Cache。Pre-cache中儲存了待處理的頂點,post cache中儲存了經過變換(也就是Vertex shader之後)的頂點。正是由於這兩塊緩衝的存在,才讓最佳化成為了可能。兩塊cache都是FIFO的隊列,假設要渲染如所示的三角形mesh:

 頂點索引為:

1,2,15|15,2,16|2,3,16|16,3,17 …………  15,16,29|29,16,30………………..

vcache的狀態如下:

1,2,15 ---> 1,2,15,16 ---> 1,2,15,16,3----> 1,2,15,16,3,17 ---> …………--->xx,xx,xx,15,16,29 ----> xx,xx,15,16,29,30--->…………….

      同一個頂點只會在vcache中出現一次,當渲染第二個三角形時,頂點15和2已經在pre-cache中, GPU不需要對他們做進一步尋找,只需請求把頂點16載入到pre-cache中,降低了頻寬需求,減小了vertex fetch的延遲。這還不是最重要的,更大的加速在於當GPU準備處理頂點15和2時,發現這2個頂點已經存在於post-cache中,於是它會完全跳過vertex shader的計算,直接使用post-cache中的結果!通過對封閉mesh的分析可以發現通常一個頂點會被5~6個三角形共用(比中的頂點16),這意味著在最理想的索引方式下,這個頂點只會被處理一次,當然最糟的情況則是6次,兩者之間有巨大的差別。由於vcache容量的限制,可以看到當渲染第二排三角形時,頂點15,16已經被彈出了緩衝,因此GPU將進行重複計算。

       我們已經知道了vcache的原理,如何充分利用他計算出最優的三角形索引順序呢?以上面的規則三角形網格為例,理想的索引應該是這樣的:

1,2,3|4,5,6|7,8,9|10,11,12|13,14,14| + |1,2,15|15,2,16|2,3,16|………………………

         為了方便討論,我把索引寫成了2段。如果你細心的話就會發現第一段實際上是一系列退化三角形,他們並不會產生任何圖形,但恰好把第一排的頂點全部放入了緩衝中。當渲染實際三角形時,每一排的頂點將依次載入到vcache中:

vcache state after degenerate triangle:1,2,3,4,5,6,7,8,9,10,11,12,13,14;
vcache state after first line of triangle:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23……….29;
vcache state after second line:15,16,17,18,19,20,21……….29,30,31,32……..44

       顯然,這就是最理想的索引順序,所有頂點都被完全複用。不過實際情況要複雜的多,顯然,這裡假設vcache至少能容納28個頂點,此外這個演算法嚴重依賴於vcache大小,最後,這個演算法只對規則mesh比較有效(非常適合於地形J)。對於第一個問題,在dx9上可以通過IDirect3DQuery9查詢VCACHE獲得實際vcache的大小,不過ati的卡從來不支援這個查詢。對於dx10來說,在beta的時候有一個類似查詢函數,可惜在後面的版本中刪除了。不過我們可以確定的是對於nvidia Geforce 4~7系列的顯卡,vcache大小至少為24,8系列至少為32。而對於ati來說,除dx10層級的卡以外,大部分的vcache只有14:( 。顯然,對於vcache只有24的情況來說,上面網格的索引計算就變得有些複雜了,一種可行的方法是把網格分為兩個子列來渲染,對於複雜模型來說,前人們已經發明了很多優秀的演算法Hoppe的研究成果產生了dx中optimizeMesh這樣的函數,Forsyth還發明出了一種不依賴於vcache大小的演算法。最後由於triangle list索引本身的靈活性,更容易排列出最優的三角形順序。

     上面只討論了mesh最佳化的一方面,稱為頂點級最佳化,還有一種近年來伴隨early-z出現的像素級最佳化。不過由於這種演算法本身比較複雜,這裡只介紹基本原理。對於同一個mesh來說,假設有a,b兩個朝向相同,但是相互遮擋的面,假設a擋住b,那麼在渲染時,如果先渲染a,就可以讓b所產生的像素被early-z剔除,避免無用的pixel shader計算。
   
      頂點最佳化的作用和意義是明顯的,可以在基本不修改現有程式的情況下,得到顯著性能提升。那麼我們應該如果最佳化呢?幸運的是已經有這樣的最佳化工具了,前面提到的OptimizeMesh以及nvidia的NvTriStrip工具都實現了頂點級的最佳化,而ati的Tootle工具不但實現了頂點最佳化,還採用了一些更先進的演算法進行模型遮擋最佳化。

         最後需要說明的是上面的討論大部分基於dx9層級的硬體構架,對於dx10層級的顯卡來說,由於統一構架帶來的優點,硬體本身有更好的緩衝機制,但無論如何,在模型預先處理過程中,最佳化頂點都是非常值得的。回到開頭的問題,其實無論list還是strip,索引儲存方式本身並不會帶來很大區別,而索引本身的組織方式才是關鍵,由於list更容易最佳化,所以對現代硬體來說,最佳化之後的list通常更快。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.