1

我正在寻找一种解决方案,用 open gles 2.0 在 libgdx 中使用模板缓冲区实现 alpha 屏蔽。

我已经设法使用模板缓冲区和着色器实现简单的 alpha 遮罩,如果片段的 alpha 通道大于某个指定值,它就会被丢弃。这很好用。

问题是当我想使用一些渐变图像蒙版或绑定 png 蒙版时,我没有得到我想要的(我得到没有 alpha 通道的“填充”矩形蒙版),而是我想要平滑淡出蒙版。

我知道问题是在模板缓冲区中只有 0 和 1,但我想写入模板一些其他值,这些值表示在片段着色器中传递的片段的实际 alpha 值,并以某种方式使用来自模板的值做一些混合。我希望我已经解释了我想要得到的东西,如果可能的话。

我最近开始玩OpenGL ES,所以我还是有一些误解。

我的问题是:如何设置和模板缓冲区来存储除 0 和 1 以外的值,以及如何在以后使用这些值进行 alpha 屏蔽?

提前Tnx。

这是目前我的模板设置:

    Gdx.gl.glClearColor(1, 1, 1, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_STENCIL_BUFFER_BIT |   GL20.GL_DEPTH_BUFFER_BIT);

    // setup drawing to stencil buffer
    Gdx.gl20.glEnable(GL20.GL_STENCIL_TEST);
    Gdx.gl20.glStencilFunc(GL20.GL_ALWAYS, 0x1, 0xffffffff);
    Gdx.gl20.glStencilOp(GL20.GL_REPLACE, GL20.GL_REPLACE, GL20.GL_REPLACE);
    Gdx.gl20.glColorMask(false, false, false, false);
    Gdx.gl20.glDepthMask(false);

    spriteBatch.setShader(shaderStencilMask);
    spriteBatch.begin();

    // push to the batch
    spriteBatch.draw(Assets.instance.actor1, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, Assets.instance.actor1.getRegionWidth(), Assets.instance.actor1.getRegionHeight());

    spriteBatch.end();

    // fix stencil buffer, enable color buffer
    Gdx.gl20.glColorMask(true, true, true, true);
    Gdx.gl20.glDepthMask(true);
    Gdx.gl20.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);

    // draw where pattern has NOT been drawn
    Gdx.gl20.glStencilFunc(GL20.GL_EQUAL, 0x1, 0xff);

    decalBatch.add(decal);
    decalBatch.flush();

    Gdx.gl20.glDisable(GL20.GL_STENCIL_TEST);

    decalBatch.add(decal2);
    decalBatch.flush();
4

1 回答 1

2

我能想到的唯一方法是使用 FrameBuffer。

选项1

将场景的背景(不会被遮盖的东西)绘制到 FrameBuffer。然后将没有蒙版的整个场景绘制到屏幕上。然后使用 FrameBuffer 的颜色附件将您的蒙版贴花绘制到屏幕上。这种方法的缺点是,在 Android 上的 OpenGL ES 2.0 中,FrameBuffer 可以具有 RGBA4444,而不是 RGBA8888,因此在颜色位深度发生变化的蒙版边缘会有可见的接缝。

选项 2

将遮罩贴花绘制为对 FrameBuffer 不透明的 B&W。然后将背景绘制到屏幕上。当你绘制任何可以被遮罩的东西时,用多重纹理绘制它,乘以 FrameBuffer 的颜色纹理。潜在的缺点是,任何可以被遮罩的东西都必须使用自定义着色器进行多纹理绘制。但是,如果您只是使用贴花,那么这实际上并不比选项 1 复杂。

以下内容未经测试...可能需要一些调试。

在这两个选项中,我将继承 CameraGroupStrategy 以在绘制蒙版贴花时与 DecalBatch 一起使用,并覆盖beforeGroups以设置第二个纹理。

public class MaskingGroupStrategy extends CameraGroupStrategy{

    private Texture fboTexture;

    //call this before using the DecalBatch for drawing mask decals
    public void setFBOTexture(Texture fboTexture){
        this.fboTexture = fboTexture;
    }

    @Override
    public void beforeGroups () {
        super.beforeGroups();
        fboTexture.bind(1);
        shader.setUniformi("u_fboTexture", 1);
        shader.setUniformf("u_screenDimensions", Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    }
}

在您的着色器中,您可以像这样获得 FBO 纹理颜色:

vec4 fboColor = texture2D(u_fboTexture, gl_FragCoord.xy/u_screenDimensions.xy);

然后对于选项1:

gl_FragColor = vec4(fboColor.rgb, 1.0-texture2D(u_texture, v_texCoords).a);

或对于选项 2:

gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
gl_FragColor.a *= fboColor.r;
于 2014-07-18T17:11:44.453 回答