1. 程式人生 > >【一步步學OpenGL 29】-《3D拾取》

【一步步學OpenGL 29】-《3D拾取》

教程 29

三維拾取

http://ogldev.atspace.co.uk/

背景

3D拾取指的是將滑鼠在螢幕上點選的位置匹配到3d遊戲場景中的某個圖元上,該圖元投影到螢幕上的畫素恰好就是滑鼠點選的畫素。3D場景在很多互動情境中有重要作用,使開發者的應用能夠將使用者的點選對應到場景空間中的物體上。例如:使用者可以通過點選選中某個物體或者物體的某一部分進行刪除等後續操作。在這個教程中的demo中,我們將渲染幾個物體,並且展示如何使用紅色標記選中的三角形圖元使其突出顯示。

為了實現3D拾取,我們將用到第23章陰影貼圖教程中介紹的OpenGL特性:幀快取物件(FBO)。之前我們使用FBO只用作深度緩衝,因為我們感興趣的是從不同角度來比較畫素的深度。而在3D拾取中,我們將既使用深度緩衝又要使用顏色緩衝,來儲存渲染的三角形的索引值。

3D拾取背後的技巧很簡單,對每一個三角形在程式執行時附加一個索引,並讓片段著色器輸出每個畫素所在三角形的索引值。結果是我們將得到一個顏色緩衝,但是並不包含顏色值,而是畫素所在的圖元的索引值。當滑鼠點選在視窗上,我們將根據滑鼠的點選位置來獲得這個索引並將這個三角形渲染成紅色。由於有深度測試,所以能夠保證當片元之間相互覆蓋時也可以得到最頂部的片元的索引(離相機最近的)。

上面就是3D拾取的概念和原理了,下面在進入程式碼之前,我們需要做一些設計上的決策。例如,如何處理多物體的情況?如何處理一個物體多次draw call渲染的情況?我們需要為每個物體設定遞增的圖元索引使場景中每一個圖元都有唯一的索引,還是為每一個物體都重置其索引?

這篇教程的程式碼採用了一種普遍的方法,可以根據需要進行簡化,會為每一個畫素渲染三級索引:

  1. 第一級是畫素所在物體的索引值,場景中的每一個物體都會得到一個唯一的索引;
  2. 物體的draw call的索引,這個索引會在開始渲染新物體時重置;
  3. 每個draw call中圖元的索引值,每次新的draw call開始時該索引會重置。

在我們讀取每個畫素的索引時實際上我們就將獲取到上面的三級索引資料了。之後我們將對特定的圖元進行相應的處理。

我們需要渲染場景兩次。一次叫做“紋理拾取”,紋理包含圖元索引資料。另一次則直接渲染到實際的顏色緩衝。因此,主渲染迴圈會有一個拾取的階段和一個渲染階段。

注:這裡的demo中使用的蜘蛛模型來自於Asssimp的資源包。它包含多個VB,可以幫助我們測試這裡的例子。

原始碼詳解

見原文。