2015-06-14 59 views
5

我建了一個2D圖形引擎,我創建了一個批處理系統,所以,如果我有1000個精靈具有相同的紋理,我可以用一個單一的通話吸引他們OpenGL的。呈現在OpenGL多個模型與一個單一的繪製調用

這是通過把在一個單一的VBO頂點數組的所有子畫面的所有頂點具有相同的織構來實現。

而不是「打印這些頂點,打印這些頂點,打印這些頂點」我願意「把所有的頂點toghether,打印」,只是要非常清楚。 足夠簡單,但現在我試圖在3D中實現同樣的功能,而且我遇到了一個很大的問題。

問題是我正在使用模型視圖投影矩陣來放置和渲染我的模型,這是在3D空間中渲染模型的常用方法。

有關屏幕的每個模型,我需要的MVP矩陣傳遞給着色器,這樣我可以用它來每個頂點變換到正確的位置。

如果我想在着色器之外進行轉換,它將由cpu執行,我不是一個好主意,原因很明顯。

但問題在於那裏。我需要將矩陣傳遞給着色器,但是對於每個模型矩陣都是不同的。

所以我不能做我的2D精靈做同樣的,因爲改變着色均勻,需要一場平局每次。

我希望我已經清楚,也許你有一個好主意,我沒有或者你已經有同樣的問題。我知道有一個事實,那就是某個地方有解決方案的原因,因爲在像Unity這樣的引擎中,可以爲多個模型使用相同的着色器,並且只需一次繪製調用便可脫身

回答

7

存在與您所看到的完全相同的功能因爲,它叫實例。通過實例化,您可以將n矩陣(或其他任何您需要的)存儲在統一緩衝區中,並呼叫glDrawElementsInstanced繪製n副本。在着色器中,您會得到一個額外的輸入gl_InstanceID,您可以使用該輸入索引到均勻緩衝區中,以獲取該特定實例所需的矩陣。

你可以閱讀更多關於此實例化:https://www.opengl.org/wiki/Vertex_Rendering#Instancing

+0

太棒了!我努力實現類似自己的事情,但我真的不知道如何,這正是我所尋找的 – Ryno

1

答案取決於每個項目的頂點數據是否相同或不同。如果是,您可以使用實例化,如@ orost的答案,在頂點着色器中使用glDrawElementsInstancedgl_InstanceID,並且該方法應該是首選。但是,如果每個3D模型都需要不同的頂點數據(通常是這種情況),您仍然可以使用一次繪製調用來渲染它們。要做到這一點,您可以使用glVertexAttribPointer(和glEnableVertexAttribArray)將另一個流添加到頂點數據中。這個額外的流將包含頂點在渲染時應使用的統一緩衝區內的矩陣索引 - 因此,VBO中的每個網格在額外的流中將具有相同的索引。統一緩衝區包含與實例設置中相同的數據。

注意,如果您需要重做批處理,則此方法可能需要一些額外的CPU處理 - 例如,批處理中的對象不應再呈現。如果這個過程經常需要,應該確定配料項目是否真的有益。

+0

最好的答案,我到目前爲止,它真的幫助我瞭解如何處理它...也許我會嘗試編寫一個自動選擇實例化或者這種方法的系統......我可以和網格一起保存它的頂點數量。然後,每當我給系統添加一個網格時,如果數字與之前的網格相同,我保留一個bool isInstance = true,但只要我得到不同數量的頂點,我就將它設置爲假。 在框架結束時,我使用一種或另一種方法渲染,取決於布爾值 – Ryno

+0

似乎對您合理嗎? – Ryno

+0

@ user3578051它不僅是重要的頂點數量,它還是實際的內容。實例化基本上只是多次繪製相同的網格。想必你會改變實例之間的統一數據。在這種方法中,頂點緩衝區數據的內容在實例之間可以完全不同。可以處理兩者(並且更喜歡實例化)的系統可能是正確的方法,除非說批次改變每一幀。 – MuertoExcobito

0

除了實例和添加另一頂點屬性一些對象ID,我想也提到另外一個策略(這需要現代的OpenGL,雖然):

(因爲GL 4.3核心)擴展ARB_multi_draw_indirect增加間接繪圖命令。這些命令直接從另一個緩衝區對象獲取它們的參數(頂點的數量,起始索引等)。通過這些功能,可以通過一次繪製調用繪製許多不同的對象。

但是,由於您仍然希望像轉換矩陣這樣的每個對象狀態,該功能是不夠的。但是與ARB_shader_draw_parameters(不在覈心GL中)結合使用,您將獲得參數,在一個多畫面間接調用中,每個對象的參數將遞增1。這樣,您可以索引到存儲每個對象數據的某個UBO,TBO或SSBO(或其他)。

相關問題