天天看點

XNA中的RenderTarget

      RenderTarget也許是最容易讓新手誤解的技術之一. 打個比方, RenderTarget其實就像一塊畫布. 大多數情況下, 這塊畫布就是我們的backbuffer.  但很多時候, 我們需要生成一些中間紋理, 這就需要一塊新畫布, 也就是一塊RenderTarget.  從實體上來說, RenderTarget和backbuffer一樣, 是顯示卡中的一段連續顯存, 當RenderTarget被設定為目前的渲染目标時, 也就成了backbuffer, 實際上兩者沒有本質差别.

      不過XNA中的RenderTarget還要特别一些, 如果你熟悉DX, 你會發現兩者RenderTarget的行為不完全一樣. 這就涉及到Xbox和PC上GPU的差别了. 在PC的GPU上, 任何一塊顯存都能作為RenderTarget, 而在Xbox上, 隻有一塊10MB大小的EDRAM能作為RenderTarget. 說的形象一些, 假設我們有2個RenderTarget: RT1和RT2, 在pc上, RT1和RT2是顯存中兩個不同的區域, 我們可以先渲染RT1, 然後再跳到RT1的位址空間下繼續渲染. 而在Xbox上, 無論渲染RT1或者RT2, 使用的都是同一塊EDRAM, 也就是說渲染了RT1之後, 需要把RT1的資料拷貝到系統記憶體中, 然後再渲染RT2, 否則将會破壞RT1中已經渲染的内容. 當然, 不要因為這額外的拷貝就假想在Xbox上使用RenderTarget很慢, 在Xbox上做這樣的拷貝要比pc快的多.

      為了保證平台相容性和接口的統一, XNA中用RenderTargetUsage在建立時, 指定RenderTarget的行為. 具體的差別Shawn已經說的很詳細了, 這裡不在重複. 關鍵在于我們應該使用哪個RenderTargetUsage呢? Shawn建議DiscardContents, 在兩個平台上都能得到最好的性能和相容性. 可惜實踐中, DiscardContents似乎并沒有傳說中那麼好. 在pc上PreserveContents才是是最快的.  此外, 基于一開始的讨論, 你也許認為GraphicsDevice.ResolveBackBuffer() 和RenderTarget2D.GetTexture()性能相當,  然而實際情況是ResolveBackBuffer要比後者慢很多. 是以, 如果你有大量的post-process效果, 需要經常拷貝backbuffer資料, 那麼最好的選擇就是完全不要使用backbuffer.  一開始就在獨立的RenderTarget上繪制場景, 到渲染的最後階段, 再把場景渲染到backbuffer上.  另外, 前面說過在pc上, 每個RenderTarget都擁有獨立的顯存空間, 也就是說RenderTarget和GetTexture()之後得到的紋理所占的是同一顯存,是以即使在GetTexture之後修改了RenderTarget的資料, 相應Texture也會改變. 最後,由于RenderTarget隻存在于顯存中, 是以當device lost時, 将會丢失其中的資料.

繼續閱讀