
前言
上一節(jié)我們大致上過了一遍sceneView::cull()函數(shù),通過研究,我們發(fā)現(xiàn)上圖中的這一部分的代碼才是整個cull過程的核心部分。所以今天我們來仔細的研究一下這一部分。
sceneView::cull()函數(shù)核心部分
1、cullVisitor->pushStateSet函數(shù):
?????? A、_currentStateGraph = _currentStateGraph->find_or_insert(ss); 判斷傳入的渲染狀態(tài) ss 是否已經(jīng)存在于這個狀態(tài)節(jié)點中,如果存在則返回找到的那個ss,如果不存在新建一個包含了 ss 的狀態(tài)節(jié)點。
B、創(chuàng)建渲染樹,這個過程必須得滿足三個條件。1)設(shè)置了渲染細節(jié)useRenderBinDetails()并且滿足BinName不為空(只能為“RenderBin”或“DepthSortedBin”);2)渲染狀態(tài)沒有采用覆蓋渲染細節(jié)(OVERRIDE_RENDERBIN_DETAILS)的方式(_numberOfEncloseOverrideRenderBinDetails==0);3)使用 setRenderBinDetails 設(shè)置了渲染細節(jié),如果滿足這三個條件將嘗試轉(zhuǎn)到指定的節(jié)點或者新建一個渲染元(RenderBin::find_or_insert 的工作),并使用堆棧記錄上一次在渲染樹中的位置。此外,渲染樹的構(gòu)建過程中只生成空的渲染元(RenderBin)節(jié)點,向其中納入狀態(tài)節(jié)點和渲染葉的任務(wù)將在后面的工作中完成。
2、向cullVisitor中設(shè)置MVP矩陣,然后通過cullVisitor->traverse(*_camera);?(實際上就是調(diào)用CullVisitor::apply 函數(shù)函數(shù)(在遍歷節(jié)點時調(diào)用))來負責(zé)根據(jù)不同的節(jié)點類型,在不同的時機調(diào)用cullVisitor->pushStateSet函數(shù)以及cullVisitor-> popStateSet函數(shù)。(下一節(jié)將會進行展開說明)
3、cullVisitor-> popStateSet函數(shù):
A、_numberOfEncloseOverrideRenderBinDetails減一,然后還是上面介紹的cullVisitor->pushStateSet函數(shù)介紹的三種情況,判斷是否使用了RenderBinDetails。然后還是從堆棧中取出上一次渲染樹中所處的渲染元節(jié)點,并跳轉(zhuǎn)到這一位置。
?????? B、狀態(tài)樹從當(dāng)前位置跳轉(zhuǎn)到其父節(jié)點,即:
1_currentStateGraph = _currentStateGraph->_parent;<br><br>
本節(jié)小結(jié)
通過簡單的對cullVisitor->pushStateSet函數(shù)以及cullVisitor-> popStateSet函數(shù)的介紹,可以了解到在遍歷場景節(jié)點樹時,使用 pushStateSet 將某個節(jié)點的渲染狀態(tài)置入,然后再將它的子節(jié)點的渲染狀態(tài)置入,直到遍歷完成。當(dāng)結(jié)束這個子樹的遍歷時,則依次使用 popStateSet 彈出_currentRenderBin 和_currentStateGraph,直到返回初始位置為止。這么整個過程就是構(gòu)建起渲染后臺的狀態(tài)樹和渲染樹。并且,假如在篩選(CULL)過程中我們判斷某個節(jié)點(及其子樹)應(yīng)當(dāng)被剔除掉時,只要跳過 pushStateSet 和 popStateSet的步驟,直接返回,就不會在進行渲染操作。這就是我們下一步要討論的CullVisitor 的工作。
CullVisitor根本上就是NodeVisitor的子類,所以他的執(zhí)行過程可以按照節(jié)點訪問器(NodeVisitor)的工作原理來理解。

當(dāng)我們執(zhí)行節(jié)點的 accept(NodeVisitor* nv)函數(shù)時,當(dāng)前節(jié)點自動調(diào)用 NodeVisitor::apply方法,將自身的信息傳遞給節(jié)點訪問器 nv,由它負責(zé)執(zhí)行相應(yīng)的處理工作;然后節(jié)點將自動執(zhí)行 Node::traverse 函數(shù),調(diào)用所有子節(jié)點的 accept 函數(shù),從而實現(xiàn)了節(jié)點樹的遍歷。在遍歷的過程中每個節(jié)點都會調(diào)用 NodeVisitor::apply 將自身的指針傳遞給訪問器,因此NodeVisitor 的每個派生類都會重載針對各個節(jié)點的 apply 函數(shù),以實現(xiàn)針對不同類型節(jié)點的訪問操作。
下一節(jié)我們就要對CullVisitor的 apply 重載函數(shù)進行探究。