Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do blending in LibGDX

I basically want to play around with blending modes in LibGDX but don't know how to do it. I found this image on internet. I want to do the same thing on LibGDX. Can someone teach me how.

enter image description here

I've been playing around using Scene2D. Here's my non-working snippet.

private class MyGroup extends Group {

    Image red, blue;

    public MyGroup() {
        Texture texture = new Texture(Gdx.files.internal("images/red.png"));
        texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
        red = new Image(texture);

        texture = new Texture(Gdx.files.internal("images/blue.png"));
        texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
        blue = new Image(texture);

        red.setX(-25);
        blue.setX(25);
    }
    @Override
    public void draw(Batch batch, float parentAlpha) {
        batch.end();
        batch.begin();
        batch.enableBlending();

        red.draw(batch, parentAlpha);

        Gdx.gl.glEnable(Gdx.gl20.GL_BLEND);
        Gdx.gl.glBlendFuncSeparate(
                Gdx.gl20.GL_DST_COLOR, 
                Gdx.gl20.GL_SRC_COLOR,
                Gdx.gl20.GL_ONE,
                Gdx.gl20.GL_ONE);

        blue.draw(batch, parentAlpha);
    }
}
like image 258
Ezekiel Baniaga Avatar asked Aug 17 '14 08:08

Ezekiel Baniaga


2 Answers

I realize this is not a new question, but I thought I would share some information for anyone else who makes it to this question/answer without knowing much about rendering in OpenGL (Knowing these terms helps a lot so you aren't just guessing mix-and-matching) Note that this site is how I learned most of this myself, so more complete information can be found there.

Destination Color: the color in the buffer, which will (eventually) be drawn unless it is modified or overwritten with new values.

Source Color: the color coming in from additional rendering commands, which may or may not interact with the destination color (depending on our settings)

The default blending equation: Final Color = (SourceColor*SourceBlendingFactor)+(DestinationColor*DestinationBlendingFactor) (This default equation can be changed, but I recommend reading my source link at the top for more information on that)

The two BlendingFactors are what we can mess with. We can set them to:

GL_ZERO: RGB(0,0,0) A(0)
GL_ONE: RGB(1,1,1) A(1)
GL_SRC_COLOR: RGB(sourceR, sourceG, sourceB) A(sourceA)
GL_ONE_MINUS_SRC_COLOR: RGB(1-sourceR, 1-sourceG, 1-sourceB) A(1-sourceA)
GL_DST_COLOR: RGB(destinationR, destinationG, destinationB) A(destinationA)
GL_ONE_MINUS_DST_COLOR: RGB(1-destinationR, 1-destinationG, 1-destinationB) A(1-destinationA)
GL_SRC_ALPHA: RGB(sourceA, sourceA, sourceA) A(sourceA)
GL_ONE_MINUS_SRC_ALPHA: RGB(1-sourceA, 1-sourceA, 1-sourceA) A(1-sourceA)
GL_DST_ALPHA: RGB(destinationA, destinationA, destinationA) A(destinationA)
GL_ONE_MINUS_DST_ALPHA: RGB(1-destinationA, 1-destinationA, 1-destinationA) A(1-destinationA)
GL_SRC_ALPHA_SATURATE: RGB(min(sourceA, 1-destinationA), min(sourceA, 1-destinationA), min(sourceA, 1-destinationA)) A(1)

The following also uses some predefined constant color, by default it is black
GL_CONSTANT_COLOR: RGB(constantR, constantG, constantB) A(constantA)
GL_ONE_MINUS_CONSTANT_COLOR: RGB(1-constantR, 1-constantG, 1-constantB) A(1-constantA)
GL_CONSTANT_ALPHA: RGB(constantA, constantA, constantA) A(constantA)
GL_ONE_MINUS_CONSTANT_ALPHA: RGB(1-constantA, 1-constantA, 1-constantA) A(1-constantA)

So all of these are just predefined float values that are being multiplied with either our source or destination, and then added to the other.

The easiest to observe from the image is GL_ZERO and GL_ONE. We end up with whichever image has the ONE.


Understanding GL_ZERO with GL_DST_COLOR

When GL_ZERO is on the destination, we are ignoring any color information currently in the buffer (because multiplying everything by zero). However, With GL_DST_COLOR also on the source image, we end up multiplying the r, g, b, a values of the source and destination.

This looks good in the image because of the nature of the example images. One acts as a solid color image, while the other grayscale image looks and acts almost like a beam of light to "reveal" the color out from our GL_ZERO setting.

Hopefully, this helps explain the images we can see above and helps everyone understand how those images are actually being blended together.

like image 183
DoubleDouble Avatar answered Oct 31 '22 11:10

DoubleDouble


Ok, to partly answer my question, here's the trick I used. Please let me know if I'm doing anything wrong. Note: This doesn't work on other function.Like when I combine GL_DST_COLOR and GL_ZERO, it doesn't output what I want. But others will. So just play around with it. I'm still watching for other answers here.

Here's the code:

private class MyGroup extends Group {

    Texture dst, src;

    public MyGroup() {
        dst = new Texture(Gdx.files.internal("images/dst.png"));
        dst.setFilter(TextureFilter.Linear, TextureFilter.Linear);

        src = new Texture(Gdx.files.internal("images/src.png"));
        src.setFilter(TextureFilter.Linear, TextureFilter.Linear);
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        // We need to cast to use blending function
        SpriteBatch sb = (SpriteBatch)batch;

        // draw our destination image
        sb.draw(dst, 0, 0);
        sb.end();

        // remember SpriteBatch's current functions
        int srcFunc = sb.getBlendSrcFunc();
        int dstFunc = sb.getBlendDstFunc();

        // Let's enable blending
        sb.enableBlending();
        sb.begin();

        // blend them
        b.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_SRC_ALPHA);
        sb.draw(src, 0, 0);

        // Reset
        sb.end();
        sb.begin();
        sb.setBlendFunction(srcFunc, dstFunc);

    }
}
like image 22
Ezekiel Baniaga Avatar answered Oct 31 '22 09:10

Ezekiel Baniaga