是否有一种廉价的方法从每帧的RenderTarget2D传输颜色数据?

时间:2012-03-07 15:54:48

标签: c# windows xna xna-4.0

直到最近,我们的游戏通过从场景的背景纹理的一部分获取颜色数据来检查碰撞。这非常有效,但随着设计的改变,我们需要检查多个纹理,并决定将这些纹理渲染到单个RenderTarget2D并检查其上的碰撞。

public bool TouchingBlackPixel(GameObject p)
    {
        /*
        Calculate rectangle under the player...
        SourceX,SourceY: Position of top left corner of rectangle
        SizeX,SizeY: Aproximated (cast to int from float) size of box
        */

        Rectangle sourceRectangle = new Rectangle(sourceX, sourceY,
                                                   (int)sizeX, (int)sizeY);

        Color[] retrievedColor = new Color[(int)(sizeX * sizeY)];

        p.tileCurrentlyOn.collisionLayer.GetData(0, sourceRectangle, retrievedColor,
                                                     0, retrievedColor.Count());

        /*
        Check collisions
        */
    }

我们遇到的问题是,自从转移到渲染目标后,我们的FPS大幅减少。

从我们读过的内容来看,问题似乎是为了从RenderTarget2D获取数据,您需要将数据从GPU传输到CPU,这很慢。我们需要两次运行相同的功能(每个玩家一次)并且无法保留相同的数据(它们可能不在同一个磁贴上),这更加复杂。

我们已经尝试将GetData调用移动到tile的Draw函数并将数据存储在成员数组中,但这似乎没有解决问题(因为我们仍然经常在tile上调用GetData - 从每次抽奖每次更新两次)。

你能给我们的任何帮助都会很棒,因为这个碰撞系统给我们提供的力量非常棒,但是引入目标的开销将使它无法保持。

2 个答案:

答案 0 :(得分:1)

简单的答案是:不要那样做

听起来像是将碰撞数据的合成卸载到GPU上是一种无效的性能优化 - 因此正确的行动方案是恢复更改。

您应该只在CPU上进行碰撞检查。我还会建议,多次运行碰撞算法并通过组合结果确定碰撞响应可能会更快,而不是将整个场景合成到一个图层上并运行一次碰撞检测。

如果您在进行碰撞之前使用渲染目标来支持变换,则尤其如此。

(对于简单的2D像素碰撞检测,请参阅this sample。如果您需要转换支持,请参阅this sample

答案 1 :(得分:0)

我想,你的瓷砖的碰撞层不会改变。或者至少不经常变化。因此,您可以将每个图块的颜色存储在数组或其他结构中。这会减少从GPU传输到CPU的数据量,但需要存储在RAM中的额外数据不会太大。