【发布时间】:2022-01-03 18:04:48
【问题描述】:
一段时间以来,我一直在开发一款使用 libgdx 和 box2d 制作烟花表演的游戏。
游戏由一个编辑器组成,允许放置和调整每个烟花表演。 另一部分是奇观部分,一排排的烟花发射。
每个烟花都由一个以一定速度喷射的物体组成,该物体附有一个粒子效果,允许模拟轨迹(最多 40 个活动粒子)。 在其高峰期,踪迹消失,炸弹的主体被摧毁。 此时另一个效果开始了,以模拟炸弹的爆炸(50 到 100 个活性粒子)。 此外,几个物体(8 到 16 之间)向不同方向喷射,以模拟附有粒子效果的恒星,以模拟它们的轨迹(10 到 50 之间)。 在旅程的最后,每颗恒星都有一个粒子效果(8 到 20 之间),以模拟它们的爆炸。
问题在于,当同时激活 10 个以上的烟花时,Android 上 fps 的数量会大幅下降,下面是截图,以了解渲染:
我显然使用了一个池来避免重新创建粒子效果。此外,我确保在开始游戏时我已经有一些效果在里面。 这个池是位于我的 ParticleManager 类中的一个内部类,它允许启动、更新和渲染效果。
我所有的纹理都包含在一个图集中(包括粒子)。所有粒子都有相同的精灵。
对于我的粒子的渲染,当创建新效果时,我确保每个效果在使用以下指令渲染后避免刷新批次:
setEmittersCleanUpBlendFunction (false);
这是我的 ParticleManager 类的渲染方法:
public void render (SpriteBatch sb) {
if (effects.size == 0) return;
// Manually change blendFunction.
sb.setBlendFunction (GL20.GL_SRC_ALPHA, GL20.GL_ONE);
// Render all effects.
for (int i = 0; i <effects.size; i ++)
effects.get(i).draw(sb);
// Manually reset blendFunction to his initial state.
sb.setBlendFunction (GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
}
我在我的主要关卡类中使用两台摄像机,一台用于渲染我的场景,一台用于渲染 HUD,所以我调用函数:sb.setProjectionMatrix(); 两次,这导致两次刷新批处理,当效果处于活动状态时会刷新三次是由于位于我的 ParticlesManager 类的渲染方法中的sb.setBlendFunction(); 方法。
所以我来了3个drawCalls。
这是我的 Level 类的渲染方法的代码,没有多余的功能:
public void render (float dt) {
update(dt);
Gdx.gl.glClearColor (0, 0, 0, 1);
Gdx.gl.glClear (GL20.GL_COLOR_BUFFER_BIT);
// First draw call.
sb.setProjectionMatrix (camera.combined);
sb.begin ();
backgroundManager.render (sb);
worldManager.render (sb);
// Second draw call if an effect is active.
if (run)
particlesManager.render (sb);
// Second draw call if no effects, or third otherwise.
sb.setProjectionMatrix (hud.getCamera (). combined);
hud.render (sb);
sb.end ();
}
因此,如果可以进行一些优化,我看不出我最终可以进行哪些优化。 提前感谢您的帮助。
【问题讨论】:
-
FWIW,有一本关于 Android 中 OpenGL 的好书,它设置了类似的场景 --> pragprog.com/titles/kbogla/opengl-es-2-for-android 。我在那本书中实现了粒子系统,它的响应速度非常快。