3
\$\begingroup\$

How to remove (cut-out) a transparent rectangle in a Texture, so that the hole will be translucent.

On Android I would use the Xfermodes approach:

https://stackoverflow.com/questions/8115732/how-to-use-masks-in-android

But in libgdx I will have to use opengl. So far I almost achieved what I was looking for, by using the the glBlendFunc From this nice and very helpful page I learend that

glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

should solve my problem, but I tried it out, and it did not quite work as expected:

batch.end();
batch.begin();

batch.setBlendFunction(GL20.GL_ZERO,
        GL20.GL_ONE_MINUS_SRC_ALPHA);
// Draw the background
super.draw(batch, x, y, width, height);
// draw the foreground
mask.draw(batch, x + innerButtonTable.getX(), y
        + innerButtonTable.getY(), innerButtonTable.getWidth(),
        innerButtonTable.getHeight());
// result = {foreground}*{0,0,0,0} +
// {background}*(1-sourceAlpha)

batch.end();
batch.setBlendFunction(GL20.GL_SRC_ALPHA,
        GL20.GL_ONE_MINUS_SRC_ALPHA);
batch.begin();

It is just making the mask area plain black, whereas I was expecting transparency, any ideas.

This is what I get:

Mask will be drawn black

This is what I expected:

Mask area should be transparent

\$\endgroup\$
6
  • \$\begingroup\$ Is there any particular reason your first 'batch.setBlendFunction()' is inside 'batch.begin(); ... batch.end();' and your second call is outside of the ''batch.begin(); ... batch.end();'? \$\endgroup\$ Mar 8, 2013 at 17:34
  • \$\begingroup\$ Also, to me it looks like the second 'batch.setBlendFunction()'s parameters should be used before drawing the mask (since it mentions the alpha source) rather than after. Maybe try switching the two calls you make. \$\endgroup\$ Mar 8, 2013 at 17:35
  • \$\begingroup\$ thanks for the comment, but it did not help, I updated my code above, maybe I just missunderstood something. \$\endgroup\$
    – joecks
    Mar 8, 2013 at 20:56
  • \$\begingroup\$ um this may sound silly, but you are enabling Blend right? batch.glEnable(GL_BLEND); \$\endgroup\$ Mar 8, 2013 at 21:59
  • \$\begingroup\$ I just tried with: Gdx.gl.glEnable(GL20.GL_BLEND);, same same \$\endgroup\$
    – joecks
    Mar 9, 2013 at 11:55

1 Answer 1

4
\$\begingroup\$

I solved my problem by using the stencil buffer:

Gdx.gl.glClear(GL_STENCIL_BUFFER_BIT);
batch.end();
//disable color mask
Gdx.gl.glColorMask(false, false, false, false);
Gdx.gl.glDepthMask(false);
//enable the stencil
Gdx.gl.glEnable(GL20.GL_STENCIL_TEST);
Gdx.gl.glStencilFunc(GL20.GL_ALWAYS, 0x1, 0xffffffff);
Gdx.gl.glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

batch.begin();
//draw the mask
mask.draw(batch, x + innerButtonTable.getX(), y
        + innerButtonTable.getY(), innerButtonTable.getWidth(),
        innerButtonTable.getHeight());

batch.end();
batch.begin();

//enable color mask 
Gdx.gl.glColorMask(true, true, true, true);
Gdx.gl.glDepthMask(true);
//just draw where outside of the mask
Gdx.gl.glStencilFunc(GL_NOTEQUAL, 0x1, 0xffffffff);
Gdx.gl.glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
//draw the destination texture
super.draw(batch, x, y, width, height);
batch.end();
//disable the stencil
Gdx.gl.glDisable(GL20.GL_STENCIL_TEST);
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .