Libgdx, Alpha Text using Shader not working

I have some trouble applying alpha in Text (with shaders) using Stage action. I’m using Group that add Window actor and Window add Label actor. My other actor in group working fine applying Actions alpha but my label (draw using shaders) not working, the different with other widget is my text label are applying shaders.

font.frag uniform sampler2D u_texture;

varying vec4 v_color;
varying vec2 v_texCoord;

const float smoothing = 0.2;

void main() {
    float distance = texture2D(u_texture, v_texCoord).a;
    float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance);
    gl_FragColor = vec4(texture2D(u_texture, v_texCoord).rgb, alpha);
}

font.vert

uniform mat4 u_projTrans;

attribute vec4 a_position;
attribute vec2 a_texCoord0;
attribute vec4 a_color;

varying vec4 v_color;
varying vec2 v_texCoord;

void main() {
    gl_Position = u_projTrans * a_position;
    v_texCoord = a_texCoord0;
    v_color = a_color;
}

my Label extends label from Libgdx to applying shaders,

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Batch;

public class Label extends com.badlogic.gdx.scenes.scene2d.ui.Label {
    boolean shaderActive = false;

    public Label(CharSequence text, LabelStyle style) {
        super(text, style);
        if(style.font.getScaleX() > 1f)
            shaderActive = true;
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        if(shaderActive) {
            batch.setShader(Assets.assetFont.fontShader);
        }
        super.draw(batch, parentAlpha);
        batch.setShader(null);          
    }
}

working code

private void initStage() {
    // TODO Stage Here
    stage = new Stage();
    stage.setViewport(viewport);

    Window w2 = new Window("",
            new WindowStyle(Assets.assetFont.blackBoldVSmall, Color.BLACK,
                    new Image(Assets.assetHUD.windowFrame).getDrawable()) );
    w2.setSize(1200, 675);
    w2.setPosition(40, 0);
    Label lbl2 = new Label("Touch here to Jump !", new LabelStyle(Assets.assetFont.goldBoldNormal, Color.GRAY));
    lbl2.setPosition(Settings.width/2, Settings.height/2);
    w2.add(lbl2);
    groupTouchHere.addActor(w2);    
    stage.addActor(groupTouchHere); 

    // sequence of action
    SequenceAction sequence = new SequenceAction(
        Actions.fadeIn(0.4f, Interpolation.circleOut), 
        Actions.fadeOut(0.4f, Interpolation.circleIn));
    SequenceAction sequenceTotal = new SequenceAction(sequence, Actions.repeat(4, sequence));
    groupTouchHere.addAction(sequenceTotal);

}

public void update(float deltaTime){
    stage.act();
}

Answer

I am not a shader expert but I have done this successfully in what I think is an easy way. (I may be very confused).

In my java code I have a variable in my Main function that holds alpha values (I only use one for gamestate transitions):

public static float newAlph = 1;

In my *.vert file I declared a uniform variable to take the alpha as an input and then set it’s value to a varying variable so the .frag file gets it.

...

uniform float u_newAlpha;
varying float v_newAlpha;

...

void main() {
    ...
    v_newAlpha = u_newAlpha;
}

Then in the .frag file i declare the same varying variable and simply multiply the alpha.

...
varying float v_newAlpha;
...

void main() {
    ...
    gl_FragColor = vec4(v_color.rgb, alpha*v_newAlpha);
}

Finally when calling the shader i set the alpha value(this you would do in your label class in the draw method)

sb.setShader(fontShader);
fontShader.setUniformf("u_newAlpha", Main.newAlph);

So even if the alpha of the rest of everything that is rendering is changing this shader will render whatever you are rendering with the alpha it has.

In mine I use a public variable from the main class but your draw method takes the alpha as an input so setting that to the uniform variable inside the .vert file should work.

Thus you would have:

public void draw(Batch batch, float parentAlpha) {
        if(shaderActive) {
            batch.setShader(Assets.assetFont.fontShader);
        }
        Assets.assetFont.fontShader.setUniformf("u_newAlpha", parentAlpha);
        super.draw(batch, parentAlpha);
        batch.setShader(null);          
    }

Let me know if that makes sense!

Leave a Reply

Your email address will not be published. Required fields are marked *