Search code examples
openglglslglblendfunc

glBlendFunc Disables Shader


I have a very simple shader (just sets a background square to green) and this works perfectly.
I recently added in some quads that have a texture applied to them. This texture has some alpha values so I use this to call it:

    glEnable (GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_TEXTURE_2D); 
    glBindTexture(GL_TEXTURE_2D, textureID);

    //draw quad

    glDisable(GL_TEXTURE_2D); 
    glBlendFunc (GL_ONE, GL_ZERO);
    glDisable (GL_BLEND);
    glBindTexture(GL_TEXTURE_2D, 0); //remove texture

The quad displays fine with the transparency - but the shader in the background is now gone. It's still being drawn but it is not displaying.

Now I removed both of the glBlendFunc(...) lines and the shader appears again (but I lose the alpha blending). However, whenever I call that function the shader seems to just stop working.

Any ideas on why this could be happening?

Image with glBlendFunc removed:
glBlendFunc

Image with glBlendFunc used:
glBlendFunc removed

Shader loading code:

    //create shaders
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    //grab the char so we can send it to gfx card
    const char* vShadData = loadFile(vertexShaderFile);
    const char* fShadData = loadFile(fragShaderFile);

    //send data to gfx card
    glShaderSource(vertexShader, 1, (const GLchar **)&vShadData, NULL);
    glShaderSource(fragmentShader, 1, (const GLchar **)&fShadData, NULL);

    //check if compiled
    GLint compiled;

    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compiled);
    if(compiled==FALSE)
    {
        //doesn't get here
    }
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compiled);
    if(compiled==FALSE)
    {
        //doesn't get here
    }

    //finally, create shader program
    shaderProgram = glCreateProgram();

    //attach shaders to program
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);

    glLinkProgram(shaderProgram);

    GLint linkStatus;
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, (GLint *)&linkStatus);
    if(linkStatus==FALSE)
    {
        //doesn't get here
    }

Vert Shader (very simple):

void main(void)
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Frag Shader:

void main(void)
{
    gl_FragColor = vec4(0.0, 0.3, 0.0, 0.0);
}

Solution

  • In your fragment shader you set the color (0, 0.3, 0, 0), which is a dark green color with an alpha of 0. With blending enabled and the standard glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) the alpha basically represents the opacity of the color and an opacity of 0 means, well, a perfectly transparent background.

    So just change the background's alpha to 1 and you should see it again.

    gl_FragColor = vec4(0.0, 0.3, 0.0, 1.0);
    

    But keep in mind to render your background first, before the other shapes for them to correctly blend onto the background. You might also just disable blending when rendering the background and only enable it for the textured objects. But anyway using an alpha of 1 is the conceptually right way to say that your background is fully opaque.