Home > Back-end >  Why isn't OpenGL rendering my red triangle?
Why isn't OpenGL rendering my red triangle?

Time:04-09

After several tests I still don't see my red triangle, what am I doing wrong?. It's funny because it is not the first time for me to work with opengl, and I am pretty sure I am not missing any setup step. Here is a code snippet:

    GLFWwindow* window;
    glfwSetErrorCallback(onError);

    if ( !glfwInit() ) {
        std::cout << "glfwInit() failed." << std::endl;
        return;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    window = glfwCreateWindow( GetWindowWidth(), GetWindowHeight(), "The Game", NULL, NULL );
    if ( !window )
    {
        std::cout << "couldn't create a proper window, exiting." << std::endl;
        glfwTerminate();
        return;
    }

    glfwSetKeyCallback( window, handleKeysEvents );

    glfwMakeContextCurrent( window );
    gladLoadGL(); // no glfwGetProcAddress required

    glfwSwapInterval(1);



    /// init opengl things ...

    GLuint VAO, VBO, program;
    GLuint VertexShader, FragmentShader;

    VertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(VertexShader, 1, &vertex_shader_text, NULL);
    glCompileShader(VertexShader);

    GLint isCompiled = 0;
    glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &isCompiled);
    if(isCompiled == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(VertexShader, GL_INFO_LOG_LENGTH, &maxLength);
        std::cout << "ERROR IN COMPILING VERTEX SHADER." << std::endl;


        // The maxLength includes the NULL character
        std::vector<GLchar> errorLog(maxLength);

        glGetShaderInfoLog(VertexShader, maxLength, &maxLength, &errorLog[0]);
                    
        for ( int i = 0; i < errorLog.size();   i )
            std::cout << errorLog[i];

        glDeleteShader(VertexShader); // Don't leak the shader.
        return;
    }

    FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(FragmentShader, 1, &fragment_shader_text, NULL);
    glCompileShader(FragmentShader);

    isCompiled = 0;
    glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &isCompiled);
    if(isCompiled == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(FragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
        std::cout << "ERROR IN COMPILING VERTEX SHADER." << std::endl;

        // The maxLength includes the NULL character
        std::vector<GLchar> errorLog(maxLength);

        glGetShaderInfoLog(FragmentShader, maxLength, &maxLength, &errorLog[0]);
                    
        for ( int i = 0; i < errorLog.size();   i )
            std::cout << errorLog[i];

        glDeleteShader(FragmentShader); // Don't leak the shader.
        return;
    }

    program = glCreateProgram();
    glAttachShader(program, VertexShader);
    glAttachShader(program, FragmentShader);
    glLinkProgram(program);
            

    // Note the different functions here: glGetProgram* instead of glGetShader*.
    GLint isLinked = 0;
    glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
    if (isLinked == GL_FALSE)
    {
        
        std::cout << "ERROR IN LINKING PROGRAM." << std::endl;

        GLint maxLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);

        // The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
        
        // We don't need the program anymore.
        glDeleteProgram(program);
        // Don't leak shaders either.
        glDeleteShader(VertexShader);
        glDeleteShader(FragmentShader);

        // Use the infoLog as you see fit.
        for ( int i = 0; i < infoLog.size();   i )
            std::cout << infoLog[i];
        
        // In this simple program, we'll just leave
        return;
    }

    glDeleteShader(VertexShader);
    glDeleteShader(FragmentShader);
    
    glGenBuffers(1, &VBO);

    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_VERTEX_ARRAY, VBO);
    glBufferData(GL_VERTEX_ARRAY, sizeof(vertices), reinterpret_cast<const void*>(vertices), GL_STATIC_DRAW);
    glBindBuffer(GL_VERTEX_ARRAY, 0);

    glBindBuffer(GL_VERTEX_ARRAY, VBO);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);

    glBindBuffer(GL_VERTEX_ARRAY, 0);
    glBindVertexArray(0);

    glEnable(GL_DEPTH_TEST);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    while( !glfwWindowShouldClose(window) )
    {
        Float wWidth = GetWindowWidth();
        Float wHeight = GetWindowHeight();

        glViewport(0, 0, (GLsizei)wWidth, (GLsizei)wHeight);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        

        glUseProgram(program);

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


        glfwSwapBuffers(window);
        glfwPollEvents();
    }


    glfwDestroyWindow(window);
    glfwTerminate();

    std::cout << "closing the game." << std::endl;
    return;

and here are the shaders: Vertex Shader:

#version 460 core
layout (location = 0) in vec3 aPos;
void main()
{
    gl_Position = vec4(aPos, 1.0f);
}

And fragment shader:

#version 460 core

out vec4 FragCol;
void main()
{
    FragCol = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}

OpenGL context is created, in fact clearing the screen with a specific color works just fine. I just don't get to see my triangle on the screen, any suggestions?

CodePudding user response:

GL_VERTEX_ARRAY is not a valid buffer type. GL_VERTEX_ARRAY is a client-side capability (fixed function attribute, legacy OpenGL). The buffer type for vertex attributes is GL_ARRAY_BUFFER:

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), reinterpret_cast<const void*>(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);

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