Search code examples
libgdxglslshader

Shaders draw unexpected transparent background


I have a new class MyActor extended Actor, with applying shader into it.

However, the shader will fill up the transparent background unexpectedly.

draw() method codes inside MyActor as follow:

@Override
    public void draw(Batch batch, float parentAlpha) {
        if(shaderProgram!=null)
        {
            batch.setShader(shaderProgram);           
        }

        if(!drawParentAtBack)super.draw(batch, parentAlpha); // by default is false
        Color c = getColor(); // used to apply tint color effect
        batch.setColor(c.r, c.g, c.b, c.a * parentAlpha);
        if ( isVisible() )
        {            
                if(displayFrame !=null) // a textureregion
                {
                    batch.draw(displayFrame,
                            getX(),getY(),
                            getOriginX(),getOriginY(),
                            getWidth(),getHeight(),
                            getScaleX(),getScaleY(),
                            getRotation());
                }           
        }
        if(drawParentAtBack)super.draw(batch, parentAlpha);

        if(shaderProgram!=null)
        {
            batch.setShader(null);
        }
}


public void setShader(String vs, String fs){
        vertexShaderCode   =    Gdx.files.internal("shaders/" + vs + ".vs").readString();
        fragmentShaderCode = Gdx.files.internal("shaders/" + fs + ".fs").readString();
        shaderProgram = new ShaderProgram(vertexShaderCode, fragmentShaderCode);
        if (!shaderProgram.isCompiled())
        {
            d( "Shader compile error: " + shaderProgram.getLog() );
        }
    }

My definition goes like this:

     MyActor myActor1;myActor2;
     ..... // setting up myActor1 & myActor2
     myActor1.setShader("default","greyScale");
     myActor2.setShader("default","greyScale"); 

my simple shaderCodes from this tutorial:

#ifdef GL_ES
    precision mediump float;
#endif

varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform mat4 u_projTrans;

void main() {
        vec3 color = texture2D(u_texture, v_texCoords).rgb;
        float gray = (color.r + color.g + color.b) / 3.0;
        vec3 grayscale = vec3(gray);

        gl_FragColor = vec4(grayscale, 1.0);
}

My vertex shader codes from this tutorial:

#ifdef GL_ES
    precision mediump float;
#endif

varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform mat4 u_projTrans;

void main() {
        vec3 color = texture2D(u_texture, v_texCoords).rgb;
        float gray = (color.r + color.g + color.b) / 3.0;
        vec3 grayscale = vec3(gray);

        gl_FragColor = vec4(grayscale, 1.0);
}

My expected result images are gray color shapes with transparent background, BUT it turns out like this:

error image

sample shape image without shader:

sample shape assets without any shader

Any helps please.


Solution

  • In general transparency is achieved Alpha Blending. The alpha channel of the fragment controls the transparency and has to be set.

    In the fragment shader the alpha channel of the texture is omitted:

    gl_FragColor = vec4(grayscale, 1.0);
    

    Set the alpha channel of the texture (u_texture) to the alpha channel of the output (gl_FragColor.a):

    #ifdef GL_ES
        precision mediump float;
    #endif
    
    varying vec4 v_color;
    varying vec2 v_texCoords;
    uniform sampler2D u_texture;
    uniform mat4 u_projTrans;
    
    void main() {
    
            // read RGB color channels and alpha channel
            vec4 color = texture2D(u_texture, v_texCoords);
    
            float gray = (color.r + color.g + color.b) / 3.0;
            vec3 grayscale = vec3(gray);
    
            // write gray scale and alpha channel
            gl_FragColor = vec4(grayscale.rgb, color.a);
    }