2009-10-28 32 views
3

我读过一些地方,当渲染大量的3D对象时,可以将它们合并成一个巨大的网格,这样只有一个绘制调用会被制作。因此,让我们引用:“GPU做它的魔力”,而CPU对于其他调用而言是免费的。XNA - 合并精灵以获得更好的绘图性能?

所以我的问题,这会是一个2D环境性能考虑是否可行?例如,假设我们有一个简单的贴图系统,而不是为视图中的每个贴图进行绘制调用,而是将合并为所有贴图以形成一个大的精灵,然后调用绘图函数。

任何对此事的洞察 - 无论是提示,链接还是什么 - 都非常感谢,因为我没有以前的图形性能经验。

编辑:对不起,我的差解释。我正在创建一个用于个人使用的tileengine,并希望它尽可能多功能。所以我想优化一下,以防万一我在不久的将来要抽取大量的瓷砖。

使用瓷砖,但我的意思是如果合并所有要从工作表绘制到新的Texture2D瓷砖将获得性能。例如:

我们有128x72的瓷砖在屏幕上绘制。我们不是遍历所有拼贴,而是为每个要绘制的拼贴调用draw,我们将所有拼贴合并成一个新的1280x720精灵并绘制它。这样draw()方法将只被称为每帧一次。我的问题是如果这样可以提高性能,因为它会在做3D时将3D对象合并到单个网格中。

因为我收集的信息是调用draw()是一个性能猪,应该尽可能少地调用。任何人确认或否认? :)

回答

10

我对XNA和3D没有任何经验,但我会给你一些关于2D游戏的建议。今年年初,我花了一些时间在XNA创建一个tile引擎,并想知道同样的事情。我认为这里的简短答案是肯定的,如果你担心性能问题,将你的图块合并成一个更大的精灵是一个好主意。然而,如果你有兴趣,答案会更长。

一般来说,当谈到性能优化时,答案几乎总是“不要这样做”。如果您确定需要优化性能,下一个答案几乎总是“不要这样做”。最后,如果您尝试优化性能,您可以做的最重要的事情就是使用基准来收集更改前后的性能的精确度量。没有这个,你不知道你是否成功了!

现在,与2D游戏相关的更多,我了解到,我看到了我的瓷砖引擎中更好的性能,更少的开关纹理。例如,假设我有一块草地砖和一块砾石砖。如果这些是内存中的两个独立纹理,并且我绘制草地砖,然后是砾石砖,然后将草地砖绘制到屏幕上,GPU将加载草纹理,然后将其切换为加载砾石纹理,然后切换草纹理回来绘制另一块草坪。这真的很快就会杀死你!解决这个问题的最简单方法是制作一个spritesheet,在这里你可以将你的草地和砾石砖放到一个纹理中,并且每次只告诉SpriteBatch从同一纹理的不同区域绘制。

要考虑的另一件事是你要在屏幕上一次绘制多少瓦片。我不记得具体,但我一次画数千瓦(在缩小视图)。我注意到,当我使用更大的瓷砖并提取更少的瓷砖时,正如您在问题中所暗示的那样,该性能也得到了改善。这并不像我在最后一段所描述的那样有很大的改进,我仍然会鼓励你衡量由不同实现产生的性能变化。另外,如果您只绘制了十几张或几百张图片,则可能不值得尝试优化目前的图片(请参阅第2段)。

就这么你知道我并没有完全做到这一点,这里是一个链接到肖恩哈格里夫斯的纹理交换,spritesheets等职位。有可能更好的帖子在XNA论坛以及肖恩哈格里夫斯的博客如果你搜索的话题。

http://forums.xna.com/forums/p/24254/131437.aspx#131437

更新:

既然你更新你的问题,让我更新我的职务。我决定只对一些样本进行基准测试,以便了解性能差异可能会有哪些。在我的Draw()函数,我有以下:

 GraphicsDevice.Clear(Color.CornflowerBlue); 

     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 

     spriteBatch.Begin(); 

#if !DEBUG 
     spriteBatch.Draw(tex, new Rectangle(0, 0, 
         GraphicsDevice.Viewport.Width, 
         GraphicsDevice.Viewport.Height), 
         Color.White);    
#else 
     for (int i = 0; i < 128; i++) 
      for (int j = 0; j < 72; j++) 
      { 
       Rectangle r = new Rectangle(i * 10, j * 10, 10, 10); 
       spriteBatch.Draw(tex, r, r, Color.White); 
      } 
#endif 
     spriteBatch.End(); 

     sw.Stop(); 

     if (draws > 60) 
     { 
      numTicks += sw.ElapsedTicks; 
     } 
     draws++; 

     if (draws % 100 == 0) 
      Console.WriteLine("avg ticks: " + numTicks/(draws - 60)); 

     base.Draw(gameTime); 

刚落感叹号的声明,这两种方法之间进行切换的“#if DEBUG!”。我跳过了前60次抽签,因为他们包含了一些初始设置(不确定是什么),并且使平均值偏差。我下载了一张1280x720的图片,并且为了顶级测试案例,我只画了一次。对于最底层的测试用例,我用瓷砖绘制了一个源图像,128x72就像您在问题中询问的那样。结果如下。

绘制一幅图像:

avg ticks: 68566 
avg ticks: 73668 
avg ticks: 82659 
avg ticks: 81654 
avg ticks: 81104 
avg ticks: 84664 
avg ticks: 86626 
avg ticks: 88211 
avg ticks: 87677 
avg ticks: 86694 
avg ticks: 86713 
avg ticks: 88116 
avg ticks: 89380 
avg ticks: 92158 

绘制128x72瓷砖:

avg ticks: 7902592 
avg ticks: 8052819 
avg ticks: 8012696 
avg ticks: 8008819 
avg ticks: 7985545 
avg ticks: 8028217 
avg ticks: 8046837 
avg ticks: 8291755 
avg ticks: 8309384 
avg ticks: 8336120 
avg ticks: 8320260 
avg ticks: 8322150 
avg ticks: 8381845 
avg ticks: 8364629 

正如你所看到的,有幅度差的一对夫妇为了在那里,所以这是很显著。测试这种事情非常简单,我建议您针对特定设置运行自己的基准测试,以考虑可能错过的内容。

+0

很多很好的信息,但是我可能说我的问题很差。 *更新我的原始问题* – Vectovox 2009-11-03 14:29:53

+0

我添加了一些测试数据,以便您可以了解两种不同方法的性能优势。 – Venesectrix 2009-11-04 06:14:16

+0

非常感谢你。我肯定会自己做一些基准测试,因为你的结果是最有趣的。 (直到现在才完全知道)。 – Vectovox 2009-11-14 13:50:44

3

图形卡切换纹理的效果越差越好。如果你喜欢,你可以通过SpriteBatch.Begin()方法中的Texture进行排序,以便图形卡尽可能少地切换纹理。

我把我的瓷砖/精灵放入工作表中,这很有意义。例如,一个角色可能在一张纸上,而一层地砖可能在同一张纸上。迄今为止这工作得很好。

我会说,不要优化,直到你必须但。如果你的游戏运行速度足够快,那么为什么还要进行优化。

+0

那么,我正在做一个瓷砖引擎(供个人使用),我希望它在任何时候都具有尽可能多的性能。至于表单,我已经在使用表单,而我的问题其实并不是真的。然而,我说我的原始问题不好,现在已经更新了。 – Vectovox 2009-11-03 14:42:32

0

表演不是上帝的普遍迫切或命令;这是达到目的的一种手段。如果你有足够好的表现,你从改善其表现上来看没有任何好处。 “始终保持最佳性能”是过早优化的定义,它会导致比预防更多的麻烦。

+0

我原来的问题与优化我写的软件无关。如果有更好的绘图方法,它必须处理。调用Draw()非常昂贵!其次,我正在编写一个标题引擎,因此我需要考虑可伸缩性。绘制20k的标题几乎可以比绘制一个更高的性能。我现在知道有一种更好的方式,没有它,游戏就不会像现在这样美丽。因此,我已经从优化中获益,对不起。 所以,是的,你的答案是在那里的标志。 – Vectovox 2010-08-22 14:50:42

1

Rectangle r = new Rectangle(i * 10,j * 10,10,10);

创建许多新对象将调用垃圾收集,这会减慢很多! 你不应该在大循环中分配新的对象:

+2

矩形是一个结构,一个值类型,因此不受GC支配。一旦超出范围,值类型将从堆栈中拉出。代码可以变得更有效率,当然,但额外的混乱是不值得的。 此外,我认为您的评论应该作为您提到的答案的实际评论,而不是作为回答。 – Vectovox 2012-12-02 11:38:27