0

我正在使用以下方式更改我的着色器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$2.run(ex011MyGameMain.java:1292)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)

我只在我的桌面上看到这个,而不是在移动设备上。可能是什么问题?有没有另一种方法可以异步这些调用,这样我就不会收到错误?

如果我不使用异步方法,着色器始终正确设置,但我会得到一些 FPS 下降,我不希望这样。 (我正在使用与帧速率无关的运动。)

4

1 回答 1

1

您正在执行需要 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”将有效地做到这一点,所以也许这是最好的做法。)

于 2015-03-21T16:18:24.917 回答