Android Libgdx:Framebuffer for";“战争的迷雾”-影响

Android Libgdx:Framebuffer for";“战争的迷雾”-影响,android,opengl-es,libgdx,framebuffer,blending,Android,Opengl Es,Libgdx,Framebuffer,Blending,我正在为Android写一个RTS游戏,我希望玩家的单位能有“战争之雾”的效果。这种效果意味着只有一个围绕着每个单位的“圆圈”显示背景地图,而在没有球员单位的地方,屏幕应该是黑色的。我不想使用着色器 我有一个第一个版本的工作。我要做的是将贴图渲染到默认的帧缓冲区,然后我有第二个完全黑色的帧缓冲区(类似于light Technologies)。在玩家的单位所在的地方,我然后批量绘制一个完全透明的纹理,中间有一个带模糊边缘的白色圆圈。 最后,我使用Gdx.gl.glBlendFunc(GL20.gl

我正在为Android写一个RTS游戏,我希望玩家的单位能有“战争之雾”的效果。这种效果意味着只有一个围绕着每个单位的“圆圈”显示背景地图,而在没有球员单位的地方,屏幕应该是黑色的。我不想使用着色器

我有一个第一个版本的工作。我要做的是将贴图渲染到默认的帧缓冲区,然后我有第二个完全黑色的帧缓冲区(类似于light Technologies)。在玩家的单位所在的地方,我然后批量绘制一个完全透明的纹理,中间有一个带模糊边缘的白色圆圈。 最后,我使用Gdx.gl.glBlendFunc(GL20.gl_DST_COLOR,GL20.gl_ZERO)在第一个帧缓冲区上绘制第二个(轻)帧缓冲区的彩色纹理

现在的视觉效果是,整个地图确实是黑色的,我的单位周围有一个圆圈是可见的,但是添加了很多白色。 原因很清楚,因为我为如下单位绘制了灯光纹理:

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();
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();
然而,我不希望原始纹理上有“白色的东西”,我只希望原始的背景照透。我怎样才能做到这一点


我认为这是在玩弄blendFuncs,但我还不能确定要使用哪些值。

多亏Tenfour04指向了正确的方向,我才找到了解决方案。首先,问题不直接存在于batch.end();。问题是,实际上,sprite批处理维护自己的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);

        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();
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渲染为默认的“帧缓冲区” //与正确的混合

        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);

您应该查看glsl着色器的用法或粒子。请注意,当您调用
batch.end()
时,直接设置
glBlendFunc
会被分配给SpriteBatch的任何混合函数覆盖。我不清楚为什么要加白色。如果您使用的是
Gdx.gl.glBlendFunc(GL20.gl_DST_COLOR,GL20.gl_ZERO),颜色只能变得更暗,因为您只是在倍增。但是,如果你用一个精灵批将帧缓冲区的纹理绘制到屏幕上,那可能不是你实际使用的混合函数。