3.4 使用SpriteBatch类时的性能考虑

问题

当使用SpriteBatch类不当,绘制大量图像时程序会变得很慢。

解决方案

教程3-1已经提到,每帧创建一个新的SpriteBatch类,或绘制每张图像时开启和关闭SpriteBatch类会极大地影响性能。但是还有更多微妙的东西需要考虑到。

工作原理

性能优化:Sprite Sorting Modes

SpriteBatch类的Begin方法让你可以设置SpriteSortMode。在讨论到不同模式前,你需要知道显卡喜欢的工作方式是什么,不喜欢的是什么。

在屏幕上绘制一张2D图像是通过绘制两个三角形并将它们填充为从一张纹理采样的颜色实现的。显卡喜欢一次性地绘制大量的三角形不要被打搅。但是当你需要改变纹理时,你就打搅了显卡。换句话说,从同一张纹理绘制100张图像比从100张纹理绘制100张图像快得多。所以,尽可能少地改变当前纹理可以改进性能。

有了这个概念,下面你可以学习可以作为SpriteBatch . Begin方法的一个参数指定的sprite排序模式了:

使用前四个模式,只有在调用SpriteBatch . End方法时,sprite才会被排序,渲染状态被设置,三角形和纹理被传送到显卡。这让你可以使用多个SpriteBatch 类对象,以随机顺序添加新sprite,甚至是使用相同渲染状态的3D对象。但在使用Immediate模式时,渲染状态会在调用SpriteBatch. Begin方法时调用,sprite会在调用SpriteBatch . Draw方法之后被绘制。这意味着你可以在两个方法间改变渲染状态!通过这种方式,你可以访问更多的alpha混合模式或使用一个自定义的pixel shader 绘制sprite!但是使用Immediate模式绘制图像时,你无法在绘制其他东西,例如一个3D对象,因为这时你可能会改变渲染状态。当你想用SpriteBatch继续绘制sprite时,渲染状态还没有复位,因此你将使用3D物体的渲染状态和pixel shader 绘制sprite。

性能优化:在一个图像文件中排序多个图像

如前所述,当绘制大量sprite时你想尽可能少地改变当前纹理。SpriteSortingMode. Texture可以帮很多忙,但在一个完整的游戏中你往往需要几百张不同的图像,这会导致显卡在纹理间切换几百次。

一个有用的方法是将互相联系的图像存储在一张大图像中,如图3-4的左图所示。通过这种方式,你可以使用SpriteBatch . Draw 方法的sourceRectangle参数指定绘制大图像中的哪一部分,如教程3-3的代码所示。

如图3-4所示,每张子图像为40 × 40像素。教程3-3的代码定义了一些矩形表示在大图像中的位置。将这些矩形作为SpriteBatch . Draw方法的第三个参数导致在屏幕上只绘制这个子图像。

使用多个SpriteBatche

SpriteBatch是一个强大的对象,你可以将整个游戏的图像一次性地添加到一个单独的SpriteBatch中,进行排序并绘制。但是,有些情况中你可能还想使用多个SpriteBatch类。

例如创建一个空战游戏,飞机间互射导弹。当然你有多个种类的飞机和导弹。你可以将飞机和导弹的所有旋转情况存储在一张大纹理中,这可以减少所需纹理的数量。

你还想在飞机引擎的后部有烟雾,并会慢慢消散,在导弹轨迹上也有大量的烟雾。如果使用一个SpriteBatch绘制所有这些图像,会遇到一个问题:你想让所有图像根据纹理排序获得优化的性能。但是,飞机和导弹应该首先绘制,这样才能之后绘制烟雾sprite。而这需要 sprite根据深度排序!

解决方法是使用两个SpriteBatch类对象:planeBatch和smokeBatch。在Draw方法的开头,调用两个SpriteBatch类的Begin方法。然后,对每个飞机和导弹,将飞机和导弹图像添加到planeBatch中,飞机和导弹之后的烟雾图像添加到smokeBatch中。

planeBatch排序模式是Texture,smokeBatch使用BackToFront模式。当所有图像添加到batch之后,首先调用planeBatch的End方法,这个会让所有的飞机和导弹根据纹理排序,会以最优的性能绘制到屏幕。然后。调用smokeBatch的End方法,这会导致烟雾sprite很好地混合在图像上。

这样,你以优化的性能绘制了飞机,而且混合正确。


发布时间:2009/10/9 14:15:34  阅读次数:8037

2006 - 2023,推荐分辨率1024*768以上,推荐浏览器Chrome、Edge等现代浏览器,截止2021年12月5日的访问次数:1872万9823 站长邮箱

沪ICP备18037240号-1

沪公网安备 31011002002865号