【问题标题】:Where to call SetRenderTarget?在哪里调用 SetRenderTarget?
【发布时间】:2013-02-16 03:12:51
【问题描述】:

我想在 SpriteBatch.BeginSpriteBatch.End 之间更改我的 RenderTargets。我已经知道这是可行的:

GraphicsDevice.SetRenderTarget(target1);
SpriteBatch.Begin()
SpriteBatch.Draw(...)
SpriteBatch.End()
GraphicsDevice.SetRenderTarget(target2);
SpriteBatch.Begin()
Spritebatch.Draw(...)
SPriteBatch.End()

但我真的很想完成这项工作:

SpriteBatch.Begin()
GraphicsDevice.SetRenderTarget(target1);
SpriteBatch.Draw(...)
GraphicsDevice.SetRenderTarget(target2);
Spritebatch.Draw(...)
SpriteBatch.End()

我见过有人这样做,但我没有找到任何原因。

编辑:关于我为什么要这样做的更多信息:

在我的项目中,我使用 SpriteSortMode.Immediate(以便能够在需要时更改 BlendState),并且我只需遍历一个排序的精灵列表,然后将它们全部绘制出来。 但是现在我想在一些精灵上应用多通道着色器,但不是全部!我对着色器很陌生,但据我了解,我必须使用第一遍将我的精灵绘制在中间精灵上,并使用第二遍在最终渲染目标上绘制中间精灵。 (我使用的是高斯模糊像素着色器)。 这就是为什么我想在我想要的目标上绘制,使用所需的着色器,而不必重新开始/结束。

【问题讨论】:

  • 那么,第二段代码有效吗?如果是的话,它和第一个一样快吗?
  • @user1306322 不,它不起作用......结果有点奇怪,就像我的第一个绘图调用最终还是在当前的 RenderTarget 上绘图
  • 然后你找到了它不起作用的原因。当您调用SptireBatch.End() 时,从Begin 调用到现在为止累积的整批精灵被发送到当前渲染目标。假设它应该像那样工作。
  • @user1306322 好的,但即使我使用的是 SpriteSortMode.Immediate?它不应该在每次绘制调用时立即在渲染目标上绘制吗?
  • Immediate 将在Begin 中设置适当的渲染状态后分别发送每个精灵。它是唯一不进行批处理的排序模式(在End 中执行所有操作)。

标签: xna xna-4.0 pixel-shader spritebatch rendertarget


【解决方案1】:

问题是:为什么要在那里更改渲染目标?

您不会有任何性能改进,因为当渲染目标(或任何其他渲染状态)发生变化时,无论如何都必须拆分批处理。

SpriteBatch 尝试按通用属性对精灵进行分组,例如使用SpriteSortMode.Texture 时的纹理。这意味着共享纹理的精灵将在相同的draw call(批处理)中绘制。减少批次可以提高性能。但是您不能在绘图调用期间更改 GPU 状态。因此,当您更改渲染目标时,无论如何您都必须使用两个绘制调用。

因此,即使第二个示例可行,批次的数量也会相同。

【讨论】:

  • 感谢您的回答。我刚刚编辑了我的帖子,并试图解释我为什么要这样做。
  • 好的,现在我知道你从哪里来了。你有没有对这件事做过任何分析?您是否再次致电Begin 测试了您的性能成本?我认为从长远来看,您应该考虑从SpriteSortMode.Immediate 切换到SpriteSortMode.Texture 之类的东西。使用 immediate 绘制的每个精灵都会发出自己的绘制调用,这可能会浪费批处理。如果只是混合状态发生变化,请考虑预先排序并使用Begin / Endper BlendState。但是您必须对更改进行概要分析才能确定。
猜你喜欢
  • 2015-08-11
  • 2019-11-06
  • 2012-03-13
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 2013-11-01
  • 2013-11-20
相关资源
最近更新 更多