遊戲編程模式:輕量級(Flyweight)模式(Part II)

2、一千個實例

        爲了讓我們必須推送給GPU的數據量達到最小,我們想要能夠將共享數據——就是TreeModel類——只發送一次。然後,我們單獨地傳遞每一棵樹的實例的獨特數據——就是它的位置、顏色和縮放。最後,我們告訴GPU,“使用那一個模型來渲染每一個實例。”

        幸運的是,今天的圖形API和圖形卡正好支持這一點。相關的細節很fiddly,並且超出了本書的範圍,但是不論是Direct3D和OpenGL都可以做一種叫做instanced rendering的事情。

        在這兩類API中,你都要提供兩個數據流(streams of data)。第一個數據流就是那個會被渲染多次的公共數據——就是我們前面的森林例子中的網格和貼圖。第二個數據流就是一個列表,它由各個實例及其將要被用於在每次繪製第一部分數據時對其進行變動的參數所組成。只要調用一次draw函數,整片森林就長出來了。

        “這個API直接由圖形卡所實現”這一事實意味着輕量級模式可能是唯一一個需要實際的硬件支持的四人幫設計模式。


3、輕量級模式

        現在我們已經有了一個具體的例子了,那麼我可以向你介紹這種模式的一般形式了。輕量級,顧名思義,在你擁有一些需要變得更加輕量(lightweight)的對象的時候派上用場,而這通常是因爲它們的數量太多了。

        使用instanced rendering的時候,我們要處理的問題,與其說是耗費太多的內存,不如說是耗費太多的時間來將每一棵樹送到去往GPU的公交車上,但是基本的思路是一樣的。

        該模式解決問題的方式是將一個對象的數據分成兩類。第一類數據就是與該對象的單個的實例無關、並且可以被所有對象所共享的東西。四人幫把這叫做內在(intrinsic)狀態,但是我喜歡把它想成“與上下文無關”(context-free)的東西。在當前的例子中,這就是樹的幾何形狀和貼圖。

        剩下的數據就是外在(extrinsic)狀態,就是與實例有關的數據。在當前的例子中,那就是每棵樹的位置、縮放和顏色。就像上面的示例代碼所顯示的那樣,這個模式通過在有對象出現的每一個地方共享內在狀態的同一份拷貝的方式來節省內存。

        從我們目前看見的東西看來,這很像是基本的資源共享,很難值得被稱作是一個模式。其實這失之偏頗,因爲在我們的這個例子中,我們可以將被共享的狀態分離而得到一個清晰的個體:TreeModel類。

        我發現這個模式在用於沒有一個表示被共享對象的良好定義的個體的場合時不太明顯(也因此更加聰明)。在這些情形下,感覺上更像是一個對象魔術般地同一時刻出現在多個地方。讓我給你們看看另外一個例子。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章