9 c# xna texture2d render-to-texture
XNA noob在这里,每天都在学习.我刚刚研究了如何使用RenderTarget2D将多个纹理合成为一个.然而,虽然我可以将RenderTarget2D用作Texture2D用于大多数目的,但是有一个关键的区别:当后缓冲区调整大小时这些渲染的纹理会丢失(毫无疑问,在其他情况下,例如内存不足的图形设备).
目前,我只是将完成的RenderTarget2D复制到一个新的非易失性Texture2D对象中.不过,我这样做的代码非常难看.有没有更优雅的方式来做到这一点?也许我只是累了,但我无法在Google或SO上找到答案.
略有简化:
public static Texture2D MergeTextures(int width, int height, IEnumerable<Tuple<Texture2D, Color>> textures)
{
RenderTarget2D buffer = new RenderTarget2D(_device, width, height);
_device.SetRenderTarget(buffer);
_device.Clear(Color.Transparent);
SpriteBatch spriteBatch = new SpriteBatch(_device);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied);
// Paint each texture over the one before, in the appropriate color
Rectangle rectangle = new Rectangle(0, 0, width, height);
foreach (Tuple<Texture2D, Color> texture in textures)
spriteBatch.Draw(texture.Item1, rectangle, texture.Item2);
spriteBatch.End();
_device.SetRenderTarget((RenderTarget2D)null);
// Write the merged texture to a Texture2D, so we don't lose it when resizing the back buffer
// This is POWERFUL ugly code, and probably terribly, terribly slow
Texture2D mergedTexture = new Texture2D(_device, width, height);
Color[] content = new Color[width * height];
buffer.GetData<Color>(content);
mergedTexture.SetData<Color>(content);
return mergedTexture;
}
Run Code Online (Sandbox Code Playgroud)
我想我应该检查IsContentLost并根据需要重新渲染,但这发生在我的主绘图循环中间,当然你不能嵌套SpriteBatches.我可以维护一个"渲染TODO"列表,在主SpriteBatch结束后处理那些,然后它们可用于下一帧.这是首选策略吗?
这个代码只被调用了几次,因此性能不是问题,但我想学习如何做正确的事情.
实际上,如果您在正常加载内容(游戏开始、关卡更改、房间更改等)时在一次性过程中生成纹理,那么您的代码并没有那么糟糕。您正在 CPU 和 GPU 之间传输纹理,这与加载普通纹理相同。这很简单而且有效!
如果您更频繁地生成纹理,并且它开始成为每帧成本,而不是加载时间成本,那么您将需要担心其性能,并可能将它们保留为渲染目标。
您不应该参与ContentLost绘图,因此您可以安全地响应该事件并重新创建渲染目标。或者您可以检查IsContentLost它们中的每一个,最好是在渲染其他任何内容之前在帧开始时检查。无论哪种方式,在开始之前都应该检查一切SpriteBatch。
(通常,当使用渲染目标时,无论如何,您都会在每一帧重新生成它们,因此在这种情况下您不需要检查它们。)
| 归档时间: |
|
| 查看次数: |
4405 次 |
| 最近记录: |