現在,我正在建模某種小型的OpenGL庫,以圖形化編程等方式矇混過關。因此,我使用類來包裝特定的OpenGL函數調用,如紋理創建,着色器創建等等, 到現在爲止還挺好。OpenGL對象創建
我的問題:
所有OpenGL調用必須由擁有創建OpenGL上下文的線程來完成(至少在Windows下,所有其他線程將什麼也不做,創建一個OpenGL錯誤)。所以,爲了獲得OpenGL上下文,我首先創建一個窗口類的實例(只是Win API調用的另一個包裝),最後爲該窗口創建一個OpenGL上下文。這聽起來對我來說很合邏輯。 (如果在我的設計中已經有一個讓你尖叫的缺陷,請告訴我...)
如果我想創建一個紋理,或任何其他需要OpenGL調用創建的對象,我基本上這樣做( OpenGL的對象調用的構造函數,例如):
opengl_object()
{
//do necessary stuff for object initialisation
//pass object to the OpenGL thread for final contruction
//wait until object is constructed by the OpenGL thread
}
所以,在的話,我創建一個對象,就像使用任何其他對象
opengl_object obj;
,然後在其構造器,把自己變成一個隊列的OpenGL對象將由OpenGL上下文線程創建。然後,OpenGL上下文線程調用一個虛擬函數,該函數在所有OpenGL對象中實現,幷包含必要的OpenGL調用以最終創建該對象。
我真的認爲,這種處理這個問題的方式會很好。但是,現在,我認爲我非常錯誤。
雖然上述方法迄今爲止工作得非常好,但在類層次更深時,我會遇到麻煩。例如(這不是完美的,但它表明我的問題):
比方說,我有一個名爲sprite的類,顯然表示一個Sprite。它對OpenGL線程有自己的創建函數,其中頂點和紋理座標被加載到圖形卡存儲器中等等。到目前爲止,這沒有問題。讓我們進一步說,我想有2種渲染精靈的方式。一個實例,一個通過另一種方式。所以,我最終會得到2個類,sprite_instanced和sprite_not_instanced。兩者都來自精靈類,因爲它們都是精靈,它們的渲染方式不同。但是,sprite_instanced和sprite_not_instanced在其create函數中需要進一步的OpenGL調用。
我的解決方案至今(我覺得真的很可怕呢!)
我有某種C++中工作以及它如何影響虛擬功能的理解如何對象生成。所以我決定只使用類精靈的虛擬創建函數來將頂點數據等加載到圖形內存中。然後,sprite_instanced的虛擬創建方法將進行準備以呈現該精靈實例。 所以,如果我想要寫
sprite_instanced s;
首先,精靈調用構造函數和一些初始化後,將構建線程傳遞對象到OpenGL的線程。在這一點上,傳遞的對象只是一個普通的精靈,所以sprite :: create將被調用,OpenGL線程將創建一個普通的精靈。之後,構造線程將調用sprite_instanced的構造函數,再次進行一些初始化並將對象傳遞給OpenGL線程。但是,這次是sprite_instanced,因此將調用sprite_instanced :: create。因此,如果我對上述假設是正確的,那麼至少在我的情況下,所有事情都應該發生,就像它應該發生的一樣。我花了最後一小時閱讀關於從構造函數調用虛函數以及v-table如何構建等等。我已經運行了一些測試來檢查我的假設,但這可能是編譯器特定的,所以我不會依賴它們100% 。另外,它感覺很糟糕,並且像一個可怕的黑客。
另一種解決方案
另一種可能性是在實施了OpenGL線程類工廠方法來採取照顧。所以我可以在這些對象的構造函數中完成所有的OpenGL調用。然而,在這種情況下,我需要很多功能(或者一種基於模板的方法),並且感覺像OpenGL線程需要做的事情可能會導致渲染時間的損失...
我的問題
可以按照我上面描述的方式處理它嗎?還是應該把這些東西丟掉,然後做點別的?
這對於所謂的「小型OpenGL庫」來說是一個巨大的複雜性。它甚至是不必要的多線程。您列出的數據組織不會特別有效。您希望「精靈」的概念比「紋理」和「網格」等概念更高級別。 _更高一級。 –
是的,它變得非常大......我想我只是在很多不同的方式好奇。但是,我沒有看到我所概述的數據組織將不會特別有效。你是用什麼方式表示的?性能?可維護性?還有其他什麼?也許這只是我在這裏簡化的一部分,但我想清除它... – Shelling
我發現(VS編譯器),如果構造函數調用虛函數,總是調用基實現。但是如果我從構造函數調用的虛函數中調用虛函數,這可以正常工作。 – Luca