2013-07-08 78 views
1

我想用freeglut做一些opengl編程。假設一個在3D空間中移動的對象(彗星/飛機),並且我想將它描繪的路徑渲染爲點雲(代表飛機留下的白色痕跡)。我的問題是,每次調用glutDispFunc命令給飛機移動時(我使用鍵盤功能改變平面位置),我需要使用glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)清除屏幕。不過,我也需要顯示其繼續積累作爲平面moves.I點的數量龐大的使用opengl:如何顯示它所追蹤的彗星和路徑?

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

導致嚴重的性能下降的點數量的增加清晰的屏幕,但可以顯示已經嘗試移動的飛機以及點雲。任何人都知道如何處理這種情況?

回答

6

是的,你清除屏幕並重新繪製每一樣東西。這就是多少個遊戲引擎的工作原理。

但是我也需要顯示點的數量龐大,其繼續積累作爲moves.I已經使用

你可能會設法吸引太多的顆粒清晰的屏幕試過了飛機。 100個粒子(或幾百個,但不到一千個)應該足以繪製彗星蹤跡。只有200顆(BIG)顆粒,您可以創建非常令人信服的雲。

此外,你不需要點繪製彗星蹤跡。使用alpha混合,您可以使用三角形輕鬆繪製半透明的光劍狀線。

光軍刀狀,等離子等,火焰般應該使用的白色小色調任何顏色(RGB 255,10,10,例如),以及使用glBlendFunc(GL_SRC_ALPHA, GL_ONE)

以下是傳統上繪製幾個例子。示例顯示您應該使用的三角形網格。數字表示阿爾法。 0 - 完全透明,1 - 完全不透明。必要時,斜線表示三角測量。「|」和 「 - 」 表示面邊:

泛着線

0--0--0--0 
| \| | /| 
0--1--1--0 
| /| | \| 
0--0--0--0 

repeat 
0--0 
| | 
1--1 
| | 
0--0 
to add more segments 

厚灼熱線

0--0--0--0 
| \| | /| 
0--1--1--0 
| | | | 
0--1--1--0 
| /| | \| 
0--0--0--0 
repeat 
0--0 
| | 
1--1 
| | 
1--1 
| | 
0--0 
to add more segments. 

您可以使用類似的東西對彗星的蹤跡。並添加一些小顆粒火花什麼的。 也別忘了紋理。使用紋理,您可以輕鬆添加更多細節,而不是使用無紋理幾何繪製所有內容。

- 編輯 -

飛機的白色痕跡

要實現任何形式的煙霧......

  1. 你需要使用用「煙燻非常大的紋理顆粒「/」多雲「紋理。如果你谷歌的「煙霧粒子紋理」谷歌圖像,你會看到我在說什麼。
  2. 那些「大」顆粒不能使用點精靈(因爲它可以比屏幕在近距離更大),並要求「廣告牌」正常繪製。廣告牌是一個總是面向相機的廣場。
  3. 理想情況下,煙霧紋理的顏色通道應該是完全白色的(因此您可以使用頂點顏色對單個粒子進行着色),並且應在alpha上繪製「煙霧」。
  4. 當您繪製煙粒子時,應該按照深度對煙粒進行排序,並且應該從最遠到最近(從相機)進行渲染。插入排序算法適用於「部分排序」的數據。
  5. 煙霧顆粒應禁用深度寫入來呈現(glDepthMask(0),如果我記錯)
  6. 煙霧顆粒應該使用glBlendFunc(GL_SRC_ALPHA, GL_INV_SRC_ALPHA)共混。
  7. 但是,如果煙霧中有火焰,火焰應該使用glBlendFunc(GL_SRC_ALPHA, GL_ONE)。火焰粒子應該混合(即隨着深度分類),或者在煙霧之後抽取(如果它使用單獨的粒子系統)。
  8. 爲了讓煙霧變得逼真,將小的初始速度分配給所有的粒子,隨着時間的推移慢慢增加它們的大小,並使它們變得更加透明。當顆粒完全透明時,將它們從顆粒系統中移出。
  9. 繪製半透明alpha混合曲面時,啓用alpha測試並切斷alpha == 0的像素。這將加速渲染。 (重要,因爲你可以甚至不俗的硬件太多的煙霧粒子殺死幀率)採用了許多廣告牌煙霧粒子可以是昂貴的,特別是如果他們是非常密切的,所以如果你想以填補大面積的這種煙霧和顆粒
  10. 會變得很大並浮在眼睛的水平面上,多次覆蓋整個屏幕區域,並且可能需要研究一些其他體積霧技術。
  11. 請勿使用矩陣移動單個粒子。每次調用不要繪製一個粒子。一口氣繪製它們,這將會更快。
+0

謝謝你的回答。你的想法非常好,但是我意識到,如果我沒有弄錯,你只是想表現出彗星的短尾。我想要的東西就像飛機的白色線索一直保持着永恆。我可以給的另一個例子是繪畫應用程序。在畫圖時,我應該能夠顯示移動的畫筆以及油漆痕跡。希望你明白我想傳達的東西。我非常感謝你的努力和詳細的答案。我相信它將在未來幫助我! –

+0

完美!謝謝... –

1

如果你還沒有使用它們,你應該使用glDrawArrays進行繪製,例如,它需要一個點數組,然後用一個函數調用繪製所有的東西。它比即時繪圖API(glBegin和glEnd)快得多。

points[pointsCount][0] = object.x; 
points[pointsCount][1] = object.y; 
points[pointsCount][2] = object.z; 
pointsCount++; 

和:每個對象「產生」點(比如說,每幀),您可以添加其位置到數組時

float points[100][3]; 
int pointsCount = 0; 
glEnableClientState(GL_VERTEX_ARRAY); 
glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), points); 

然後:你可以設置它像這樣然後,他們畫像這樣:

glDrawArrays(GL_POINTS, 0, pointsCount); 

當然,你必須當數組填滿做一些事情,但你的想法。

還有一些VBOs,它可以提高速度甚至更多,但是更高級的功能。

編輯:是的,你應該用這種方法重繪所有東西。我會說它不會影響性能比glBegin/End多得多點。根據answers here,您應該可以使用glBufferData調整緩衝區的大小,但可能必須將當前數據存儲在您的陣列中,並在調整大小時將其傳回。

+0

非常感謝您的回覆!我剛剛閱讀了Vertex Arrays和VBOs。那麼你是否說我必須每一幀擦除屏幕並重新繪製所有內容?如果我使用頂點數組和VBO,它不會妨礙性能?我還讀到,在VBO中,我可以使用GL_DYNAMIC_DRAW_ARB來更新緩衝區。但我無法弄清楚如何增加緩衝區的大小。你能否提供更多的信息? –

1

是,大多數遊戲通過擦除屏幕重繪每一幀的工作。但是,也可能每幀少做更多的工作。屏幕上還有其他的東西嗎?這條路線應該多久?它是否必須在一段時間內保持恆定長度(而不是像老鼠蹤跡那樣隨着時間的推移逐漸消失)?

如果您可以負擔淡化您的足跡,則可以使用緩衝區反饋。該技術在屏幕(或對象+軌跡)上呈現半透明的四邊形,其具有將尾部的最遠部分逐漸淡化爲背景色的效果。然後將對象繪製在新的位置,再次創建最亮的尾部。這是一個相當常見的演示/可視化效果,並且可以創建非常美觀的尾部,並且每幀畫圖的開銷非常小。

這可能並不完全符合您的需求(我在寫清此事之前,您已將您的需求作爲對@ SigTerm答案的評論予以澄清),但我會將其留在此處,因爲其他人可能需要此類「跟蹤」 。