C#XNA 2D轨迹效果优化

时间:2012-03-28 22:27:58

标签: c# optimization xna 2d sprite

目前,作为我游戏中的追踪效果,我每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调用,即使我为数百个对象分配每个帧的新路径也没有帧丢失......必须有更好的方法来做到这一点

1 个答案:

答案 0 :(得分:3)

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

此技术非常高效,可用于着名的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()......