Search code examples
c++openglglslubuntu-18.04glfw

"GLSL 3.30 is not supported" when compiling GLSL shader on Ubuntu 18.04?


I am trying to draw a triangle on a GLFW window with OpenGL.

Here is my complete code:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;

static unsigned int compileShader ( unsigned int type, const string& source ){
    unsigned int id = glCreateShader ( type );
    const char* src = source.c_str();
    glShaderSource ( id, 1, &src, nullptr );
    glCompileShader ( id );
    
    int result = 0;
    glGetShaderiv ( id, GL_COMPILE_STATUS, &result );
    if ( result == GL_FALSE ){
        int length = 0;
        glGetShaderiv ( id, GL_INFO_LOG_LENGTH, &length );
        char* message = ( char* ) alloca ( length * sizeof ( char ) );
        glGetShaderInfoLog ( id, length, &length, message );
        cout << "Failed to compile " << ( type == GL_VERTEX_SHADER ? "vertex" : "fragment" ) <<  "shader" << endl;
        cout << message << endl;
        glDeleteShader ( id );
    }
    return id;
}
static int createShader ( const string& vertexShader, const string& fragmentShader ){
    unsigned int program = glCreateProgram();
    unsigned int vs = compileShader ( GL_VERTEX_SHADER, vertexShader );
    unsigned int fs = compileShader ( GL_FRAGMENT_SHADER, fragmentShader );
    
    glAttachShader ( program, vs );
    glAttachShader ( program, fs );
    glLinkProgram ( program );
    glValidateProgram ( program );

    glDeleteShader ( vs );
    glDeleteShader ( fs );

    return program;
}

int main(void)
{
    GLFWwindow* window;  
    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
   
    /* Make the window's context current */
    glfwMakeContextCurrent(window);
    if ( glewInit() != GLEW_OK ) 
        cout << "error" << endl;

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    cout << glGetString ( GL_VERSION ) << endl;

    float positions [ 6 ] = {
        -0.5f, -0.5f,
         0.0f,  0.5f,
         0.5f, -0.5f
    };
    unsigned int buffer;
    glGenBuffers ( 1, &buffer );
    glBindBuffer ( GL_ARRAY_BUFFER, buffer );
    glBufferData ( GL_ARRAY_BUFFER, 6 * sizeof ( float ),positions, GL_STATIC_DRAW );
    glEnableVertexAttribArray ( 0 );
    glVertexAttribPointer ( 0, 2, GL_FLOAT, GL_FALSE, sizeof ( float ) * 2, 0 );

    string vertexShader = 
        "#version 320 core\n"
        "\n"
        "layout ( location = 0 ) in vec4 position;"
        "\n"
        "void main(){\n"
            "gl_Position = position;\n"
        "}\n";
    string fragmentShader = 
        "#version 320 core\n"
        "\n"
        "layout ( location = 0 ) out vec4 color;"
        "\n"
        "void main(){\n"
            "color = vec4(1.0,0.0,0.0,1.0);\n"
        "}\n";
    unsigned int shader = createShader(vertexShader, fragmentShader );
    glUseProgram ( shader );


    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

    glDrawArrays ( GL_TRIANGLES, 0, 3 );

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;

}

...and here is the output I am getting:

3.0 Mesa 18.0.5
Failed to compile vertexshader
0:1(10): error: GLSL 3.20 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES, 3.00 ES, 3.10 ES, and 3.20 ES

Failed to compile fragmentshader
0:1(10): error: GLSL 3.20 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES, 3.00 ES, 3.10 ES, and 3.20 ES

I am using Ubuntu 18.04.

Here is the output of sudo glxinfo | grep "OpenGL":

OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 620 (Kaby Lake GT2) 
OpenGL core profile version string: 4.5 (Core Profile) Mesa 18.0.5
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 18.0.5
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 18.0.5
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:

Solution

  • Multiple issues:

    • #version 320 never existed, it went from #version 150 with GL 3.2 to #version 330 in GL 3.3.
    • Set your glfwWindowHint()s before calling glfwCreateWindow(). They only affect the next glfwCreateWindow() so calling them after creating your window doesn't do much for you.
    • In Core contexts you need to have a vertex array object (VAO) bound before drawing anything.
    • You need to have a VAO bound before glEnableVertexAttribArray() & glVertexAttribPointer() do anything useful.

    All together:

    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
    #include <iostream>
    using namespace std;
    
    static unsigned int compileShader( unsigned int type, const string& source )
    {
        unsigned int id = glCreateShader( type );
        const char* src = source.c_str();
        glShaderSource( id, 1, &src, nullptr );
        glCompileShader( id );
    
        int result = 0;
        glGetShaderiv( id, GL_COMPILE_STATUS, &result );
        if( result == GL_FALSE )
        {
            int length = 0;
            glGetShaderiv( id, GL_INFO_LOG_LENGTH, &length );
            char* message = (char*)alloca( length * sizeof( char ) );
            glGetShaderInfoLog( id, length, &length, message );
            cout << "Failed to compile " << ( type == GL_VERTEX_SHADER ? "vertex" : "fragment" ) << "shader" << endl;
            cout << message << endl;
            glDeleteShader( id );
        }
        return id;
    }
    
    static int createShader( const string& vertexShader, const string& fragmentShader )
    {
        unsigned int program = glCreateProgram();
        unsigned int vs = compileShader( GL_VERTEX_SHADER, vertexShader );
        unsigned int fs = compileShader( GL_FRAGMENT_SHADER, fragmentShader );
    
        glAttachShader( program, vs );
        glAttachShader( program, fs );
        glLinkProgram( program );
        glValidateProgram( program );
    
        glDeleteShader( vs );
        glDeleteShader( fs );
    
        return program;
    }
    
    int main( void )
    {
        GLFWwindow* window;
        /* Initialize the library */
        if( !glfwInit() )
            return -1;
    
        glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
        glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
        glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
    
        /* Create a windowed mode window and its OpenGL context */
        window = glfwCreateWindow( 640, 480, "Hello World", NULL, NULL );
        if( !window )
        {
            glfwTerminate();
            return -1;
        }
    
        /* Make the window's context current */
        glfwMakeContextCurrent( window );
        if( glewInit() != GLEW_OK )
            cout << "error" << endl;
    
        cout << glGetString( GL_VERSION ) << endl;
    
        GLuint vao = 0;
        glCreateVertexArrays( 1, &vao );
        glBindVertexArray( vao );
    
        string vertexShader =
            "#version 330 core\n"
            "\n"
            "layout ( location = 0 ) in vec4 position;"
            "\n"
            "void main(){\n"
            "gl_Position = position;\n"
            "}\n";
        string fragmentShader =
            "#version 330 core\n"
            "\n"
            "layout ( location = 0 ) out vec4 color;"
            "\n"
            "void main(){\n"
            "color = vec4(1.0,0.0,0.0,1.0);\n"
            "}\n";
        unsigned int shader = createShader( vertexShader, fragmentShader );
        glUseProgram( shader );
    
        float positions[ 6 ] = {
            -0.5f, -0.5f,
             0.5f, -0.5f,
             0.0f,  0.5f,
        };
        unsigned int buffer;
        glGenBuffers( 1, &buffer );
        glBindBuffer( GL_ARRAY_BUFFER, buffer );
        glBufferData( GL_ARRAY_BUFFER, 6 * sizeof( float ), positions, GL_STATIC_DRAW );
        glEnableVertexAttribArray( 0 );
        glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 2, 0 );
    
        /* Loop until the user closes the window */
        while( !glfwWindowShouldClose( window ) )
        {
            /* Render here */
            glClear( GL_COLOR_BUFFER_BIT );
    
            glDrawArrays( GL_TRIANGLES, 0, 3 );
    
            /* Swap front and back buffers */
            glfwSwapBuffers( window );
    
            /* Poll for and process events */
            glfwPollEvents();
        }
    
        glfwTerminate();
        return 0;
    }