C#XNA 2D轨迹效果优化

目前,作为我游戏中的一种线索效果,我每5帧就有一个精灵的半透明纹理副本被添加到一个List 的路径中。

这些轨迹的alpha值每帧递减,绘制函数遍历列表并绘制每个纹理。 一旦它们达到0 alpha,它们就会从List 中删除。

结果是移动实体背后的一个很好的小尾迹效果。 问题是大约100多个实体,帧速率开始急剧下降。

所有的跟踪纹理来自同一个精灵表,所以我不认为它是批处理问题。 我描述了代码,并且在FPS下降峰值期间CPU强度较低然后它处于正常FPS,所以我认为这意味着它的GPU限制?

有没有办法更有效地实现这种效果?

下面是使用的通用代码:

// fade alpha m_alpha -= (int)(gameTime.ElapsedGameTime.TotalMilliseconds / 10.0f); // draw if (m_alpha > 0) { // p is used to alter RGB of the trails color (m_tint) depending on alpha value float p = (float)m_alpha/255.0f; Color blend = new Color((int)(m_tint.R*p), (int)(m_tint.G*p), (int)(m_tint.B*p), m_alpha); // draw texture to sprite batch Globals.spriteBatch.Draw(m_texture, getOrigin(), m_rectangle, blend, getAngle(), new Vector2(m_rectangle.Width/2, m_rectangle.Height/2), m_scale, SpriteEffects.None, 0.0f); } else { // flag to remove from List m_isDone = true; } 

我想我应该注意,给予trail类的m_texture是对所有路径共享的全局纹理的引用。 我注意为每条路径创建一个硬拷贝。

编辑:如果我只是注释掉SpriteBatch.Draw调用,即使我为数百个对象分配每个帧的新路径也没有帧丢失……必须有更好的方法来做到这一点。

通常对于轨迹而言,不是在每个帧上清除屏幕,而是在绘制当前帧之前绘制透明的屏幕大小的矩形。 因此,前一帧是“暗淡的”或“颜色模糊”,而较新的帧是完全“清晰”和“明亮”。 当重复这一过程时,将从所有先前帧生成跟踪,这些帧从未被清除但是“变暗”。

这种技术非常有效,可用于着名的Flurry屏幕保护程序(www.youtube.com/watch?v=pKPEivA8x4g)。

为了使轨迹更长,您只需增加用于清除屏幕的矩形的透明度。 否则,你会使它变得更不透明以缩短踪迹。 但请注意,如果通过使矩形过于透明而使轨迹过长,则可能会留下由于Alpha混合导致的轨迹的一些光迹,即使经过很长时间也可能无法完全擦除。 Flurry屏幕保护程序遭受这种伪影,但有一些方法可以弥补它。

根据您的具体情况,您可能需要调整技术。 例如,您可能希望有多个绘图图层允许某些对象留下痕迹而其他对象不生成轨迹。

对于长距离而言,这种技术比尝试重新绘制精灵数千次作为当前方法更有效。

另一方面,我认为代码中的瓶颈是以下行:

 Globals.spriteBatch.Draw(m_texture, getOrigin(), m_rectangle, blend, getAngle(), new Vector2(m_rectangle.Width/2, m_rectangle.Height/2), m_scale, SpriteEffects.None, 0.0f); 

拥有数千个像Draw()这样的GPU调用效率很低。 如果在缓冲区中有多边形列表,其中每个多边形位于正确的位置并且具有与之一起存储的透明度信息,则效率会更高。 然后,通过对Draw()的SINGLE调用,您可以渲染具有正确纹理和透明度的所有多边形。 对不起,我无法为您提供此代码,但如果您想继续使用您的方法,这可能是您的方向。 简而言之,你的GPU当然可以一次绘制数百万个多边形,但它不能多次调用Draw()……