仅供个人学习使用,请勿转载,勿用于任何商业用途。
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时, 将会丢失其中的数据.