我正在寻找一种解决方案,使用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();
答案 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;