libgdx open gles 2.0模板alpha掩蔽

时间:2014-07-18 08:14:27

标签: libgdx opengl-es-2.0 stencil-buffer

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

我已经设法用模板缓冲区和着色器实现简单的alpha掩码,其中如果片段的alpha通道大于某个指定的值,则它会被放弃。这很好。

问题在于,当我想使用一些渐变图像蒙版或带有png蒙版时,我不会得到我想要的东西(我得到了#34;填充"没有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();

1 个答案:

答案 0 :(得分:1)

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

选项1

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

选项2

将您的面具贴花绘制为B& W对您的FrameBuffer不透明。然后将背景绘制到屏幕上。当您绘制任何可以遮罩的东西时,使用多纹理绘制它,乘以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;