使用 TimerTask 更改着色器会导致 50% 的错误 - LIBGDX
Using TimerTask to change shader causes error 50% of the time - LIBGDX
我正在使用 TimerTask
:
更改我的着色器
public java.util.Timer ExplodeTimerTask = new Timer();
ExplodeTimerTask.schedule(new TimerTask() {
@Override
public void run(){
sprite_explosion.setRegion(textureAtlasExplosion.findRegion("spacesepxl0047"));
exploded = true;
game_upper_screen.TurnToSepiaForContrast();
}
}, 0);
public void TurnToSepiaForContrast(){
this.batch.setShader(shader_finish);
}
50% 的时间着色器被正确激活,否则会失败并出现此错误:
exploded one: oneException in thread "Timer-0"
java.lang.RuntimeException: No OpenGL context found in the current thread.
at org.lwjgl.opengl.GLContext.getCapabilities(GLContext.java:124)
at org.lwjgl.opengl.GL11.glBindTexture(GL11.java:651)
at com.badlogic.gdx.backends.lwjgl.LwjglGL20.glBindTexture(LwjglGL20.java:67)
at com.badlogic.gdx.graphics.GLTexture.bind(GLTexture.java:77)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.flush(SpriteBatch.java:955)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.setShader(SpriteBatch.java:1056)
at com.cryotrax.game._ex01MyGame.TurnToSepiaForContrast(_ex01MyGame.java:474)
at com.cryotrax.game.ex01MyGameMain.run(ex011MyGameMain.java:1292)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
我只在桌面上看到这个,在移动设备上看不到。可能是什么问题?有没有其他方法可以让这些调用异步化,这样我就不会收到错误消息?
如果我不使用异步方法,着色器始终会正确设置,但我会出现一些 FPS 下降,我不想这样。(我使用与帧率无关的移动。)
您正在执行需要 OpenGL 状态的操作(setShader
调用),因此这些操作 只能 从 Libgdx UI线程。参见 https://github.com/libgdx/libgdx/wiki/Threading。这可能会间歇性地失败,因为有时 UI 线程可能会处理计时器。
您可以使用 Application.postRunnable
:
来解决这个问题
Gdx.app.postRunnable(new Runnable() {
@Override
public void run(){
sprite_explosion.setRegion(textureAtlasExplosion.findRegion("spacesepxl0047"));
exploded = true;
game_upper_screen.TurnToSepiaForContrast();
}
});
没有延迟,它将在 UI 循环的下一次迭代中 运行。
然而,这与直接在 UI 线程中调用着色器 相同,所以你最好直接调用它,这将带回你的表现问题。
您是否可能每帧多次调用此方法?每次调用都会触发批量刷新,我怀疑这是昂贵的部分。如果您可以进行设置,以便此调用发生在您的批处理 being
/end
之外,它应该更便宜。 (而且 "postRunnable" 会有效地做到这一点,所以也许这是最好的做法。)
我正在使用 TimerTask
:
public java.util.Timer ExplodeTimerTask = new Timer();
ExplodeTimerTask.schedule(new TimerTask() {
@Override
public void run(){
sprite_explosion.setRegion(textureAtlasExplosion.findRegion("spacesepxl0047"));
exploded = true;
game_upper_screen.TurnToSepiaForContrast();
}
}, 0);
public void TurnToSepiaForContrast(){
this.batch.setShader(shader_finish);
}
50% 的时间着色器被正确激活,否则会失败并出现此错误:
exploded one: oneException in thread "Timer-0"
java.lang.RuntimeException: No OpenGL context found in the current thread.
at org.lwjgl.opengl.GLContext.getCapabilities(GLContext.java:124)
at org.lwjgl.opengl.GL11.glBindTexture(GL11.java:651)
at com.badlogic.gdx.backends.lwjgl.LwjglGL20.glBindTexture(LwjglGL20.java:67)
at com.badlogic.gdx.graphics.GLTexture.bind(GLTexture.java:77)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.flush(SpriteBatch.java:955)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.setShader(SpriteBatch.java:1056)
at com.cryotrax.game._ex01MyGame.TurnToSepiaForContrast(_ex01MyGame.java:474)
at com.cryotrax.game.ex01MyGameMain.run(ex011MyGameMain.java:1292)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
我只在桌面上看到这个,在移动设备上看不到。可能是什么问题?有没有其他方法可以让这些调用异步化,这样我就不会收到错误消息?
如果我不使用异步方法,着色器始终会正确设置,但我会出现一些 FPS 下降,我不想这样。(我使用与帧率无关的移动。)
您正在执行需要 OpenGL 状态的操作(setShader
调用),因此这些操作 只能 从 Libgdx UI线程。参见 https://github.com/libgdx/libgdx/wiki/Threading。这可能会间歇性地失败,因为有时 UI 线程可能会处理计时器。
您可以使用 Application.postRunnable
:
Gdx.app.postRunnable(new Runnable() {
@Override
public void run(){
sprite_explosion.setRegion(textureAtlasExplosion.findRegion("spacesepxl0047"));
exploded = true;
game_upper_screen.TurnToSepiaForContrast();
}
});
没有延迟,它将在 UI 循环的下一次迭代中 运行。
然而,这与直接在 UI 线程中调用着色器 相同,所以你最好直接调用它,这将带回你的表现问题。
您是否可能每帧多次调用此方法?每次调用都会触发批量刷新,我怀疑这是昂贵的部分。如果您可以进行设置,以便此调用发生在您的批处理 being
/end
之外,它应该更便宜。 (而且 "postRunnable" 会有效地做到这一点,所以也许这是最好的做法。)