【问题标题】:How do I draw a rectangle from one render target onto another without losing data?如何在不丢失数据的情况下从一个渲染目标绘制一个矩形到另一个渲染目标?
【发布时间】:2012-03-10 12:44:35
【问题描述】:

我在本周早些时候提出了一个问题 (here),关于将数据从渲染目标传输到 CPU,以便可以在其上测试冲突。根据我收到的回复,我决定将渲染目标的一部分绘制到一个较小的渲染目标,然后检索该数据将是一个有效的解决方案并尝试实现它。

绘制完整尺寸的渲染目标 (1280x1024) 后,我将活动渲染目标切换为较小的渲染目标(59X47 - 我的玩家的碰撞大小),并尝试绘制大渲染目标中落在玩家下方的部分到较小的目标上。起初,我认为这行得通,但后来我注意到碰撞有时会非常不准确。

我将较小的渲染目标绘制到屏幕上以检查其内容,发现它在任何时候都只占用了少数像素,而且这些像素始终位于左上角。

            // Render rectangle under player from foreground to collision layer
            Rectangle sourceRectangle = new Rectangle(sourceX, sourceY,
                                                       (int)sizeX, (int)sizeY);
            gd.SetRenderTarget(collisionLayer[i]);
            gd.Clear(Color.Transparent);
            spriteBatch.Draw(foregroundLayer, collisionLayer[i].Bounds,
                                                sourceRectangle, Color.White);
            gd.SetRenderTarget(null);

将完整的大型渲染目标绘制到较小的目标会导致数据成功传递(尽管显然是缩放的),所以我不确定出了什么问题。

            // Render full target onto collision layer
            gd.SetRenderTarget(collisionLayer[i]);
            gd.Clear(Color.Transparent);
            spriteBatch.Draw(foregroundLayer,new Vector2(0.0f),Color.White);
            gd.SetRenderTarget(null);

下图显示了大目标,小目标叠加在左上角。大目标的完整数据似乎绘制正确。

【问题讨论】:

  • 图片显示的东西不工作吗?它对我来说看起来相当正确 - 小图像似乎很好地代表了大图像。您将从 1280x1024 降低到 59x47。当比例变化如此之大时,您不能指望完美的小图像。
  • 如果问题不清楚,我很抱歉。问题是,在复制完整图像作品时,我不能只抓住播放器下方的矩形。如果我使用第一个代码 sn-p,那么在这种情况下左上角的图片应该是空白的,因为没有玩家坐在黑色墨水上(纸张纹理不可碰撞)并且包含映射 1- 的黑色像素如果他们在墨迹的顶部,则将图像放在播放器下方。我实际得到的似乎与那里的数据无关,因为我只是在 (0,0) 附近得到了几个黑色像素。
  • 我看不出您显示的代码有任何明显错误。我想我的第一个预感是你的 sourceRectangle 不是你期望的那样。您是否尝试过将矩形硬编码到您知道墨水上方的某个位置并查看结果如何?
  • 我没有,因为我很确定它是正确的,但我只是尝试了 (900,450),它在黑色墨水的中间很舒服,我只是像以前一样得到一个小黑点.

标签: c# xna xna-4.0


【解决方案1】:

您没有显示您的 spriteBatch.BeginspriteBatch.End 呼叫,但您似乎需要移动它们。具体来说,您在调用 spriteBatch.End 之前将渲染目标设置为 null,或者至少在示例代码中是这样。

我设置了一个示例项目,当我执行以下操作时,一切都按预期工作......

  GraphicsDevice.SetRenderTarget(target);
  GraphicsDevice.Clear(Color.Transparent);
  spriteBatch.Begin();
  spriteBatch.Draw(texture, target.Bounds, new Rectangle(50, 500, 100, 100), Color.White);
  spriteBatch.End();

  GraphicsDevice.SetRenderTarget(null);
  GraphicsDevice.Clear(Color.CornflowerBlue);
  spriteBatch.Begin();
  spriteBatch.Draw(texture, new Rectangle(0, 0, 640, 480), texture.Bounds, Color.White);
  spriteBatch.Draw(target, Vector2.Zero, target.Bounds, Color.White);
  spriteBatch.End();

但是如果我在SetRenderTarget(null) 之后移动spriteBatch.End,我的渲染目标是空的。

【讨论】:

  • 精灵批处理很久以前就开始了,并且在它的来源之后结束的时间更长,但我看不出有什么理由不能改变它,以便渲染过程的不同部分开始和根据需要结束批处理。我直到明天才离开这个项目,但我会尝试一下,如果可行,我会接受你的回答。感谢您的帮助。
  • 结束 SpriteBatch 是实际绘制的内容,因此在更改渲染目标后结束它,您要么绘制到错误的渲染目标,要么绘制调用丢失 - 不是确定哪个。实际上,SpriteBatch 可能会跟踪它绘制到的渲染目标,但 End 调用仍然会刷新绘制调用,因此如果您不调用它,则绘制不会发生。
  • 我只是移动了结尾并开始调用(将平局分成几批),它运行良好。非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-16
  • 2015-05-21
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多