目前,作为我的游戏中的一个拖尾效果,我每5帧就会有一个半透明的精灵纹理副本被添加到拖尾的List<>中。
这些轨迹的alpha值每一帧都会递减,绘制函数会迭代列表并绘制每个纹理。一旦它们达到0α,它们就会从List<>中删除。
结果是在移动实体后面产生了一个很好的小轨迹效果。问题是对于100+实体来说,帧速率开始急剧下降。
所有的轨迹纹理都来自相同的雪碧表,所以我不认为这是批处理的问题。我分析了代码,CPU强度在FPS下降尖峰期间较低,然后在正常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是对所有trail共享的全局纹理的引用。我注意到为每条轨迹创建一个硬拷贝。
编辑:如果我简单地注释掉SpriteBatch.Draw调用,即使我为成百上千的对象分配了每一帧的新轨迹,帧中也没有丢失……一定有更好的方法来做到这一点。
发布于 2012-03-29 13:23:58
通常,对于轨迹,您只需在绘制当前帧之前绘制一个透明的屏幕大小的矩形,而不是清除每个帧上的屏幕。因此,前一帧是“暗淡的”或“颜色模糊的”,而较新的帧是完全“清晰”和“明亮”的。当重复此操作时,将从所有先前的帧生成轨迹,这些帧永远不会被清除,而是“变暗”。
这种技术非常有效,它被用在著名的Flurry屏幕保护程序中(www.youtube.com/watch?v=pKPEivA8x4g)。
为了使轨迹更长,只需增加用于清除屏幕的矩形的透明度即可。否则,将使其变得更不透明,从而使轨迹更短。但是,请注意,如果通过使矩形太透明而使轨迹太长,则可能会留下一些由于alpha混合而留下的轻微痕迹,即使在很长一段时间后也可能无法完全清除。遭受了这类伪像的影响,但有一些方法可以补偿它。
根据您的情况,您可能必须适应该技术。例如,您可能希望有多个绘制层,允许某些对象留下轨迹,而其他对象则不生成轨迹。
对于长途旅行,这种技术比尝试像当前方法一样重绘一个精灵数千次更有效。
另一方面,我认为代码中的瓶颈是下面这行:
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(),就可以使用正确的纹理和透明度渲染所有多边形。很抱歉,我不能为您提供这方面的代码,但如果您想继续您的方法,这可能是您的方向。简而言之,你的GPU当然可以一次绘制数百万个多边形,但它不能调用Draw()那么多次……
https://stackoverflow.com/questions/9916570
复制相似问题