Ogre 渲染佇列(一)

2022-06-18 11:00:20 字數 3689 閱讀 7870

渲染佇列在

ogre

中是乙個重要的概念,在場景中的所有物體都會在繪製前被

ogre

放入到乙個特定的渲染佇列中。渲染佇列主要起兩個作用:

1.確保正確的繪製順序。比如先繪製天空盒再繪製一般物體,最後繪製介面。

2.提高渲染效率。

ogre

將具有相同

pass

的物體放在一起進行繪製,目的是盡可能減少渲染狀態的切換(

gpu切換渲染狀態效率低

)。一般使用者常用的是在

entity

中設定渲染佇列序號,其實整個渲染佇列的工作流程遠遠比這個複雜,但基本不需要終端使用者干預。這篇文章就是要把這部分不用干預的細節分析一下。

渲染佇列是構成

ogre

渲染流程和控制渲染效率的關鍵一環,所以應該深入學習和理解這個部分。我認為通過這個過程不僅可以學習到優秀開源庫的設計思想,而且了解實現原理可以幫助我們更好的使用它們。另外在整個

ogre

的渲染流程中有很多關鍵類與之有關聯,理解渲染佇列對進一步深入理解其它功能是大有好處的。

為了更好的講清楚這個內容我打算按以下的順序進行展開,希望能夠做到深入淺出。

1.渲染佇列的實現。

這個部分主要分析

ogre

中渲染佇列各個類之間的關係與實現細節,

2.ogre

的其它部分如何與渲染佇列互動。

這個部分主要分析誰在什麼時候操作渲染佇列。這部分有助於深入理解渲染佇列的各個部分是如何協作完成整個工作的。

3.使用者可以做什麼。

這個部分主要分析渲染佇列的留給我們多大的可操作空間。

渲染佇列的實現

要了解渲染佇列首先接觸到的類是

renderqueue

,從名字上乍一看很容易讓人產生誤解,其實

renderqueue

不是渲染佇列而是乙個管理器,負責管理一組名為

renderqueuegroup

的物件。

renderqueue

本身隸屬於場景管理器

(scenemanager)物件,

乙個場景管理器擁有乙個

renderqueue

物件。renderqueuegroup

表示具有固定編號的渲染佇列組。很明顯這個類也不是最終的渲染佇列,而同樣是乙個管理器,負責管理一組具有優先順序的

renderprioritygroup

物件。renderqueuegroup

的固定編號通過

ogre

中的renderqueuegroupid

列舉變數定義,如下:

enum

renderqueuegroupid

;每乙個

渲染佇列組物件擁有在上述列舉變數中的乙個值,用來標識這個渲染佇列組的處理優先順序。從列舉值上看編號越小的越先繪製,比如編號為

5的天空佇列組要先於編號為

100的介面疊加佇列組繪製。

renderqueue

這個類按照渲染佇列組的固定編號作為索引儲存每乙個

renderqueuegroup

物件。renderqueue

沒有提供建立

renderqueuegroup

物件的方法,只要提供編號就可以獲得乙個佇列組物件。內部會根據指定編號是否存在而自動建立對應物件,最終確保每乙個編號的渲染佇列組只有乙個。

renderqueue

類的內部使用固定編號作為

key的

map來儲存渲染佇列組物件,這樣做的好處是可以快速插入和獲取渲染佇列組物件。由於

map在插入時會自動排序,所以在繪製的時候可以按照順序從

map中依次取出渲染佇列組物件,而不用單獨再處理排序工作了。

renderqueuegroup

這個管理器本身的實現比較簡單,並提供了乙個稱之為優先順序編號的東西。每乙個優先順序編號對應乙個

renderprioritygroup

物件。其實這一層優先順序劃分是為了能基於上面的分組後提供更加精細的優先順序劃分。比如在編號為

1的天空盒渲染物件組中又可以劃分若干個優先順序。這個優先順序大部分情況都不需要設定,可以採用預設值。

下面我們來看看

renderqueuegroup

這個管理器負責管理的

renderprioritygroup

物件。實際上這還不是最終的渲染佇列,而又是乙個管理器,這個管理器管理著六個固定型別的渲染佇列。通過層層結構終於在這裡確定了渲染佇列的位置。至於渲染物件最終被放入哪個渲染佇列是由

renderprioritygroup

物件負責的。分類標準是基於渲染物件所關聯的

technique

資訊確定的。一般根據是否使用透明材質或是否開啟陰影等引數決定最終該渲染物件所屬的渲染佇列,其中具體的演算法就不在這裡詳細講解了。

renderprioritygroup

物件中管理的物件是

queuedrenderablecollection

類就是真正的渲染佇列,負責渲染物件的儲存和排序。目前渲染佇列支援三種排序方式:公升序、降序和按

pass

排序。排序方式必須在渲染隊列為空的時候確定,因為在向渲染佇列插入元素的時候依賴排序方式,所以集合不為空的時候是不能修改排序方式的。渲染佇列類內部有兩個用來儲存渲染物件的集合,如下:

passgrouprenderablemap

mgrouped

;renderablepasslist

msorteddescending

;第乙個集合負責儲存按照

pass

排序的集合,凡是屬於使用同乙個

pass

物件繪製的渲染物件被放在這乙個組中。

第二個集合負責按照渲染物件與攝像機的距離進行排序的集合。其實公升序和降序排列都使用這個集合,可以通過反向訪問達到反序的結果。

從原始碼中可以看出插入渲染物件時,根據當前渲染佇列設定的排序方式,將渲染物件分別放入上面描述的集合中。需要注意的是在元素插入的時候只是分組儲存而沒有進行真正的排序,排序工作觸發的時機將在後面分析。渲染佇列有

sort

方法完成的這個排序工作。

我們現在回過頭來看看整個渲染佇列是如何達到確保正確繪製順序和提高繪製效率的設計目標的。

首先來看繪製順序。帶固定編號的

renderqueuegroup

物件是確保繪製順序的第一步,將背景、物件和介面劃分開,確保渲染順序不會出問題。另外渲染佇列

queuedrenderablecollection

物件支援按距離公升序或降序排列,可以確保具有透明屬性的物件按照由遠及近的順序繪製,完成了確保繪製順序的第二步。

然後我們看渲染繪製效率。渲染佇列

queuedrenderablecollection

物件支援按照

pass

分組,在繪製的時候使用相同

pass

進行繪製的渲染物件會連續被繪製,大幅減少渲染狀態的切換。

至此大體上分析了渲染佇列功能的實現原理。系統共分為四層結構實現整個渲染佇列的功能,其中前三層都起到管理器的作用,最後一層儲存渲染物件。從組織結構來看是比較複雜的,我想只有通過應用的上下文才能更容易理解這樣乙個複雜的軟體結構,所以下一步我們來分析

ogre

中其它類是如何與渲染佇列互動的。本文章的第二篇將對互動這個部分進行分析。

轉 ogre 渲染流程

ogre渲染流程 1.fireframestarted 2.按某種優先順序更新所有渲染目標 2.1 firepreupdate 2.2 更新所有視口 2.2.1 fireviewportpreupdate 2.2.2 場景管理的渲染函式 2.2.2.1 更新陰影 2.2.2.2 更新動畫 2.2.2...

Ogre的渲染優化心得

做商業網路遊戲的話,效率是乙個不可避免的話題,為了留更多的空間給客戶端的邏輯,那麼渲染模組就應該盡量高效.小弟只 一下ogre的渲染優化,以大家熟悉的天龍八部為例.以網上流傳版本的天龍 來看,ogre和cegui部分的渲染都有嚴重的效能問題,ogre 地形的實現,乙個tile,只按材質做了批次優化,...

ogre渲染到動態紋理

材質指令碼 material screen texture unit bluescreen.jpg必須是blank white的影象,因為多重紋理混合預設是modulate。texture screen就是在程式裡面動態建立的二維影象。ogre textureptr screentex ogre t...