2
votes

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);
}
2
Could you show some images what it looks like and what it should look like. It sounds like a depth-ordering problem, but I'm not sure.Christian Rau
Images added. I've rearranged the ordering of the drawing functions (so that the background is rendered last instead of first), but still no difference. Also, if it means anything: the shader was actually quite different, drawing some noise instead of a solid colour. I changed it to draw just the static green colour when I discovered it wasn't displaying. (It can still display the noise image if glBlendFunc isn't used)Andrew
Are you sure your shader is still enabled when drawing the background in the version where glBlendFunc is used ?neodelphi
Yes, the shader is still compiling, enabled (with valid GLuint id), and being draw. But not displaying.Andrew
Can you post more code? And the shaderBЈовић

2 Answers

3
votes

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.

0
votes

The code for drawing a quad is like this:

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

glBegin(GL_TRIANGLE_FAN);
    glTexCoord2f(0.0f, 0.0f);
    glVertex2f(-1.0f, 1.0f);    
    glTexCoord2f(1.0f, 0.0f);
    glVertex2f( 1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex2f( 1.0f,-1.0f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex2f(-1.0f,-1.0f);
glEnd();
glDisable(GL_TEXTURE_2D); 
glBlendFunc (GL_ONE, GL_ZERO);
glDisable (GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0); //remove texture

Now for both the shader quad and the textured quad I use the same code. However, I never load a texture for the shader quad, so the textureID I send to opengl is -1.
After changing this code to NOT bind textureID if it is == to -1 the shader works the way it should, and I still get transparency on my textured quads.

However Christian Rau's answer found a bug in my code - which is probably the main reason why this failed.