2014-03-25 106 views
1

我正在創建基於SDL2庫的簡單遊戲渲染引擎。我的設計看起來類似於這個ASCII圖。SDL2:渲染引擎​​設計

DrawTarget  RenderTarget 
    |    | 
    |    | 
    +---> Window <---+ 

DrawTarget是適合於SDL_Surface blitting的繪圖目標的抽象類。 RenderTarget是適合SDL_Texture渲染目標的抽象類。 Window是派生類,管理SDL_Window,SDL_Renderer和所有繪製和繪製函數。

Renderable 
    | | | 
    | | | 
    | | +-> Player 
    | |  ^
    | |   | 
    | +----> Animation 
    |   ^
    |   | 
    +-------> Texture 

Renderable是一切,它可以渲染到屏幕或其他RenderTarget。 Texture是SDL_Texture實現。紋理不應該知道自己的位置。 Animation有一個私人紋理成員,允許設置動畫幀。動畫本身不應該知道渲染的位置。 Player有私人動畫成員。玩家應該知道當前的位置。

在這個時候,我有一個SDL_Renderer每個窗口,並通過它所有紋理,動畫等紋理與SDL_Renderer知識回報在屏幕上。但我不認爲始終調用Texture-> draw(x,y)是有效的並且緩存友好。

我喜歡SFML呈現的方式。所有可渲染對象都有draw方法,它只調用窗口的繪製方法。我想實施類似的系統。

這將破壞我的需求一些Renderable對象知道他們的渲染位置,有些不會。

例如class Player不應該有render(x, y)方法,因爲它知道它的位置。另一方面,Texture類不應該有render(void)方法,因爲它沒有它的位置。

我的問題如下:如何設計SDL2合適的渲染引擎儘可能少的開銷?

+1

我認爲你的問題太寬泛了,你想在這裏解決什麼具體問題? – paulm

+0

你可以讓對象畫自己,或者渲染器畫對象。我會建議後者根據經驗。您可以將弱指針存儲到容器中的可繪製對象,並在需要時讓渲染器遍歷它。 – OMGtechy

+0

@paulm我想創建通用的渲染引擎,它應該能夠渲染位置(播放器)或沒有位置(紋理,動畫)的對象。 – Lorin

回答

2

在我看來,你所說的是你希望實體只知道他們的位置,但是爲了渲染你想讓它完全分離。每個實體都需要存儲某種渲染數據。我會說你應該看看基於組件的實體系統。有不同類別的位置,renderdata,輸入等。嘗試Component Based Entity System

+0

我不知道我喜歡這種創建對象的方式。它需要大量的開銷 - 每當對象需要組件或沒有時,檢查基於使用組件的反應等。告訴我,如果我錯了。另一方面,我很可能會將它用於遊戲實體(NPC,Player,...)。 – Lorin

+0

@洛林嗯,我的意思是實體。每個實體可以具有相同的組件,或者您可以擁有一定數量的組件。每個組件可能有一個ID?總的來說,我認爲你可以像這樣保存內存。然後你可以給每個實體一個指向AI對象的指針或其他東西。 –

+0

我會試試看。謝謝你提出一個有趣的想法。 – Lorin

3

回答你的問題:「我的問題如下:如何設計SDL2合適的渲染引擎儘可能少的開銷?

一個可擴展的,懶惰的渲染方案的最小化SDL2渲染開銷快速的解釋:

「層」包括所有具有相同的Z屬性的紋理。 只要該圖層中的紋理被修改,圖層就會被標記爲無效。 當渲染器運行時,圖層以設定的幀速率進行管理。 跟蹤最大層和最高無效層。渲染器 從最高無效層開始並在最高層結束。每個圖層都是 設置爲渲染器目標並清除。然後將上一層複製到當前層的 。然後它遍歷圖層中的每個紋理, 重繪那些標記爲無效的紋理,並將每個紋理複製到當前的 圖層的頂部。結果是前一層是背景,而當前層則繪製在背景上。當 圖層被標記爲無效時,該紋理被緩存並失效。在運行任何無效圖層後,將渲染目標設置回默認值(空),將最高紋理複製到屏幕 並存在。

在具有圖層用戶界面類型的環境中,上面是 可伸縮和懶惰。在我的低端賽揚n2830我的測試應用閒置在 0%的CPU使用率。即使我添加了一百個測試圖層,它或多或少仍然保持這種方式。由於它只是從哪個層向上改變,並且所有 變化都以合理的幀率排隊,所以實際上很少做工。遍歷無效層到最大層出現 漸近友好,然後遍歷所有層每次運行。以設定的時間間隔運行 渲染器並完成所有繪圖,然後有助於節省時間 ,因爲它會忽略無法看到的過度變化。 使用一些應用程序代碼來避免必須繪製 材質和複製紋理是值得的。如果檢查和 屬性查找往往需要更長的時間。

請注意,此設計旨在用於2D層,如用戶界面。一些原則在其他環境中可能不會很好地工作。

另外上面只支持紋理而不支持曲面。混合兩個 對我來說不值得複雜。讓sdl2渲染器繪製到一個特定的紋理花了一些搞清楚,但單獨服務於我的需要足夠好 。如果混合使用這兩者,似乎很難避免一些額外的工作。 加上紋理受益於GPU,這增加了效率在 cpu時間方面的勝利。

在我的系統中,窗口對象有一個繪製方法。此方法使用渲染器排隊繪製 操作,而不是立即繪製它們。窗口 對象具有區域屬性。要支持不具有區域 屬性的對象,也許可以應用圍繞您的對象執行的包裝,而該包裝不包含 。這樣,當提示一個區域時,它仍然可以提供一個,即使在 內部也沒有。或者,也可以使用將您的對象映射到某個區域的表格,或者調用任何對象跟蹤其紋理的方法。我不確定這種限制的性質。

請注意,此繪製方法是繪製對象的渲染器和繪製對象的對象的混合方法。這些對象似乎是自己繪製的,而渲染器實際上完成了這項工作。

簡而言之:

  • 紋理signficantly快於表面
  • 排隊借鑑和複製操作批處理
  • 緩存紋理時,他們正在複製所有紋理給他們後製定
  • 高速緩存層
  • 使用高速緩存來避免渲染除無效層以外的所有層到最高層