Libgdx:"Fog of War"-效果的帧缓冲区

Libgdx: Framebuffer for "Fog of War"-Effect

我正在为 Android 编写一个 RTS 游戏,我希望对玩家的单位产生 "Fog of War" 效果。这种效果意味着每个单位周围只有 "circle" 显示背景地图,而在没有玩家单位的地方,屏幕应该是黑色的。我不想使用着色器。

我有它的第一个版本。我正在做的是将地图渲染到默认帧缓冲区,然后我有第二个完全黑色的帧缓冲区(类似于光技术)。在玩家的单位所在的位置,我然​​后批量绘制一个完全透明的纹理,中间有一个边缘模糊的白色圆圈。 最后,我使用 Gdx.gl.glBlendFunc(GL20.GL_DST_COLOR, GL20.GL_ZERO);

在第一个上绘制了第二个(浅色)FrameBuffer 的 colorTexture

现在的视觉效果是整个地图确实是黑色的,并且可以看到我的单位周围的一个圆圈 - 但是添加了很多白色。 原因很清楚,因为我为这样的单位绘制了光纹理:

lightBuffer.begin();
        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE);

        Gdx.gl.glEnable(GL20.GL_BLEND);

        Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        batch.setProjectionMatrix(camera.combined);
        batch.begin();

        batch.setColor(1f, 1f, 1f, 1f);
        for (RTSTroopAction i : unitList) {
                batch.draw(lightSprite, i.getX() + (i.getWidth() / 2) - 230, i.getY() + (i.getHeight() / 2) - 230, 460, 460); //, 0, 0, lightSprite.getWidth(), lightSprite.getHeight(), false, true);

        }

        batch.end();
        lightBuffer.end();

但是,我不想要原始纹理上的 "white stuff",我只想要原始背景透光。我怎样才能做到这一点?

我认为它正在使用 blendFuncs,但我还不能弄清楚要使用哪些值。

感谢 Tenfour04 指出了正确的方向,我得以找到解决方案。首先,问题不直接在 batch.end(); 内。问题是,精灵批次确实维护了自己的 blendFunc 设置。这些在 flush() 时得到应用;叫做。 (end() 也调用它)。 但是,当批处理绘制绑定到与先前 draw() 调用中使用的纹理不同的纹理的 TextureRegion 时,它也会调用 flush。

所以在我的原始代码中:当我调用 batch.draw(lightBuffer,...) 时,我设置的任何 blendFunc 总是被覆盖。解决方案是使用 spritebatch 的 blendFunc 而不是 Gdx.gl.blendFunc.

总的工作代码最终如下所示:

lightBuffer.begin();
        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        Gdx.gl.glEnable(GL20.GL_BLEND);          
// start rendering to the lightBuffer
// set the ambient color values, this is the "global" light of your scene
        Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// start rendering the lights 
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
// set the color of your light (red,green,blue,alpha values)
        batch.setColor(1f, 1f, 1f, 1f);
        for (RTSTroopAction i : unitList) {
            if (i.getOwnerId() == game.getCallback().getPlayerId()) {
                batch.draw(lightSprite, i.getX() + (i.getWidth() / 2) - 230, i.getY() + (i.getHeight() / 2) - 230, 460, 460); //, 0, 0, lightSprite.getWidth(), lightSprite.getHeight(), false, true);
            }
        }
        batch.end();
        lightBuffer.end();

// 现在我们将 lightBuffer 渲染为默认 "frame buffer" // 正确混合 !

        Gdx.gl.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
        batch.setProjectionMatrix(getStage().getCamera().combined);
        batch.enableBlending();
        batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
        batch.begin();

        Gdx.gl.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
        batch.draw(lightBufferRegion,0, 0, getStage().getWidth(), getStage().getHeight());
        batch.end();
        batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);