Triangle with shaders doesn't appear when using blending

Hi people. I started to study opengl through a tutorial and I have a need of rendering a semi-transparent triangle using shaders. I was able to draw a triangle, but as soon as I add blending, no matter the color, the triangle doesn’t get drawn anymore.

I wrote an example of the issue:

#include <glad/glad.h>
#include <GLFW/glfw3.h>

auto constexpr WIDTH = 800;
auto constexpr HEIGHT = 600;
auto constexpr TITLE = "Draft 4";

const char* vertexShaderSource = "#version 330 core\n"
                                 "layout (location = 0) in vec3 aPos;\n"
                                 "void main()\n"
                                 "{\n"
                                 "  gl_Position = vec4(aPos, 1.0);\n"
                                 "}\0";
const char* fragmentShaderSource = "#version 330 core\n"
                                   "out vec4 FragColor;\n"
                                   "uniform vec4 color;\n"
                                   "void main()\n"
                                   "{\n"
                                   "  FragColor = color;\n"
                                   "}\0";


void window_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

int main(int argc, char* argv[])
{
    glfwInit();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    auto window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, nullptr, nullptr);
    glfwSetWindowSizeCallback(window, window_size_callback);

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);

    // if the following two lines are present, the triangle isn't drawn at al 
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);
    // TODO: check for shader compilation errors

    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);
    // TODO: check for shader compilation errors

    unsigned int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    // TODO: check for shader linking errors

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);


    unsigned int VBO, VAO;
    float vertices[] = {
            -0.5, -0.5, 0.0f,
            0.5, -0.5, 0.0f,
            0.0, 0.5, 0.0f
    };

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*) 0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    int vertexColorLocation = glGetUniformLocation(shaderProgram, "color");
    glUniform4f(vertexColorLocation, 0.0, 0.0, 0.0, 1.0);

    bool running = true;
    while (running) {

        glfwPollEvents();

        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glfwSwapBuffers(window);

        if(glfwWindowShouldClose(window)){
            running = false;
        }
    }


    glDeleteProgram(shaderProgram);


    glfwSetWindowSizeCallback(window, nullptr);
    glfwWindowShouldClose(window);
    glfwTerminate();
    return 0;
}

Can you help me to spot the mistake? Thank you.

This:

is failing with GL_INVALID_OPERATION because there is no current program object. You need to call glUseProgram(shaderProgram) first.

The variable has the value (0,0,0,0) initially, which is fine if you aren’t using blending but will be completely transparent with GL_SRC_ALPHA blending.

1 Like

Thank you very much. Needless to say that I feel like an idiot because I had a lot of ways to notice my mistake (I should have experimented with other colors for instance in order to see that that call was failing…)

When developing, always:

either:

  1. The Easy Way, or
  2. The Hard Way

The Hard Way involves you periodically, repeatedly, polling OpenGL, asking it if it’s “seen any errors lately”? [“No, not yet. Keep checking through!”]

With The Easy Way, you tell OpenGL once to call “you” immediately when an error occurs.

Besides being easier, The Easy Way is even better because the GL driver will call you with expanded error messages as well as performance tips and usage warnings that you might want to know about to help improve the performance and robustness of your code.