轉載請注明出處:
EnigmaJJ
http://www.cnblogs.com/twjcnblog/p/5850648.html
術語
Canvas是Unity的原生組件,Unity的渲染系統使用Canvas來提供繪制在游戲世界中的分層幾何結構。
Canvas的職責是將他所包含的幾何體組合成batches,生成合適的渲染命令並將這些命令發送給Unity的圖形系統。所有這些都是由C++代碼完成的,被稱為rebatch或batch build。當Canvas被標記為需要rebatch時,該Canvas就被認為是dirty的。
幾何體是通過Canvas Renderer組件提供給Canvas的:
Sub-canvas是嵌套在Canvas組件中的另一個Canvas。Sub-canvas將他所包含的控件從他的父Canvas隔離。dirty Sub-canvas不會強制他的父Canvas去重構父Canvas中的幾何體,反之也一樣(有一些特殊的情況,例如當父Canvas引起Sub-canvas的尺寸發生變化,那么Sub-canvas就不得不重構他包含的幾何體)。
Graphic是Unity UI C#庫提供的一個基類。所有提供可繪制幾何體(例如Image、Text)到Canvas系統的Unity UI C#類都繼承自Graphic。絕大多數內置的Unity UI圖形都是通過Graphic的子類MaskableGraphic實現的,這些圖形可以通過MaskableGraphic實現的IMaskable接口來實現遮罩效果:
Layout組件用於控制RectTransform的尺寸和位置。Layout組件只依賴於RectTransform並且只對與自己相關的RectTransform的屬性有影響。Layout組件不依賴於Graphic類,能夠獨立於Unity UI的Graphic組件來使用。
Layout組件和Graphic組件都依賴於CanvasUpdateRegistry類。該類會追蹤需要被更新的Layout組件和Graphic組件,並且在這些組件相關的Canvas調用willRenderCanvases事件時觸發update。
Layout組件和Graphic組件的更新被稱為rebuild。
渲染細節
在使用Unity UI時,要記住所有由Canvas渲染的幾何體都是在Transparent隊列渲染的。也就是說,所有幾何體都是使用Alpha Blend按照從后往前的順序渲染的。從性能角度出發就意味着每個光柵化的像素都會被采樣,即使該像素會被其他的不透明幾何體完全覆蓋。在移動設備上,這種高水平的overdraw將會迅速超過GPU的fill-rate能力。
Canvas Batch構建過程
Batch構建過程是指Canvas組合他所包含的UI元素的網格並生成合適的渲染命令發送給Unity圖形管線的過程。構建過程的結果會被緩存起來並且被重用直到Canvas被標記為dirty,無論何時當組成Canvas的網格有任何一個發生變化時Canvas就會被標記為dirty。
Canvas使用的網格是從附加在Canvas上的Canvas Renderer組件中獲取的,但不會從Sub-canvas中獲取。
Batch的計算需要根據深度排序網格,需要檢測網格共享的材質等等。這個操作是多線程的,所以他的性能通常在不同的CPU架構上會有很大的不同,特別是在移動芯片(通常只有少量的CPU核心)以及桌面CPU(通常有4個甚至更多的CPU核心)之間性能區別很大。
Graphics重建過程
Graphics重建過程是指Unity UI C#圖形組件的網格和布局重新計算的過程。該過程是在CanvasUpdateRegistry類中通過函數PerformUpdate執行的。
PerformUpdate的執行過程分為三步:
1. Dirty Layout組件通過函數ICanvasElement.Rebuild重構他們的布局
2. 任何已注冊的裁剪組件(例如Masks)對可裁剪的組件進行裁切,這是通過函數ClippingRegistry.Cull完成的
3. Dirty Graphic組件對他們包含的圖形元素進行重建
Layout的重建分為三部分:PreLayout、Layout以及PostLayout。Graphic的重建分為兩部分:PreRender以及LatePreRender:
Layout重建
為了重新計算Layout組件所包含組件的位置和尺寸,以合適的的層級順序應用Layouts是十分必要的。靠近根節點的Layouts有可能會改變嵌套在他里面的Layouts的位置和尺寸,因此必須優先計算。
Unity UI會將dirty Layout組件根據他們在層級中的深度進行排序,層級高(也就是父Transform數量少)的Layout會被移到隊列的前面。
已排序的Layout組件接着會重建他們的布局,此時Layout組件所控制的UI元素的位置和尺寸會發生更改。
Graphic重建
當Graphic組件重建時,Unity UI使用ICanvasElement接口的Rebuild函數(可以見上圖第3步)。Graphic實現該接口,在重建過程的PreRender階段會執行兩個不同的重建步驟:
1. 如果頂點數據被標記為dirty(例如組件的RectTransform改變了尺寸),那么網格將被重建
2. 如果材質數據被標記為dirty(例如組件的材質或紋理發生了變化),那么附加到Canvas Renderer上的材質將被更新
Graphic重建不需要按任何特定的順序來遍歷Graphic組件,也不需要任何排序操作。