1

I'm learning OpenGL so I was experimenting with drawing 2D images. I first put everything in the main function of my C++ program. It worked fine (2 triangles were drawn).

I decided to make the program clearer by making separate classes, ... But now it isn't working anymore. When I want to make the OpenGL Context, it fails. When I display the error I get :

Failed creating OpenGL context at version requested

In the tutorial I am reading they said this error is most likely due to the fact that the version of OpenGL isn't supported by your graphics card, but if this was the case, it shouldn't work when I put all the code in the main procedure.

This is the part where it goes wrong (context creation) :

bool OpenGL_Scene::initializeWindow() {
    // Initialize the SDL
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        cout << "Error while initializing the SDL : " << SDL_GetError() << endl;
        SDL_Quit();

        return false;
    }

    // Configure OpenGL

    // Use version 3.1
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); // OpenGL 3.x
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); // OpenGL x.1 --> OpenGL 3.1

    // Double buffering
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Use double buffering (0 to not use it)
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);  // Buffer has a depth of 24 bits

    // Make the window
    this->window = SDL_CreateWindow(this->windowTitle.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->windowWidth, this->windowHeight, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL); // SDL_WINDOW_OPENGL necessary to specify that the window will have an OpenGL context attached to it.

    if(this->window == 0) // Initialization failed
    {
        cout << "Error while creating the window : " << SDL_GetError() << endl;
        SDL_Quit();

        return false;
    }

    // Make the OpenGL context given the SDL window
    this->OpenGL_Context = SDL_GL_CreateContext(this->window);

    // Make sure the creation of the context succeeded. If not the problem is probably that the version of OpenGL isn't supported by the graphics card.
    if(this->OpenGL_Context == 0)
    {
        cout << "Could not create the OpenGL context : " << SDL_GetError() << endl;

        SDL_DestroyWindow(window);
        SDL_Quit();
        return false;
    }

    return true;
};

In the last few lines the error get displayed so the program results in :

Could not create the OpenGL context : Failed creating OpenGL context at version requested

I searched a lot to find a solution and found this : SO topic

So in the above code I tried :

// Configure OpenGL

// Use version 3.1
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); // OpenGL 3.x
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); // OpenGL x.1 --> OpenGL 3.1

// Double buffering
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);      // ADDING THIS AVOIDS THAT THE CONTEXT COULD NOT BE CREATED BUT THEN WHEN WE DRAW SOMETHING WE DON'T SEE ANYTHING

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Use double buffering (0 to not use it)
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);  // Buffer has a depth of 24 bits

Now when I run the program with this extra line, the context is created (without errors so OpenGL_Context != 0) but nothing is drawn. I omitted the part of the code where I am drawing, because it worked before and I didn't changed anything.

Does someone has an idea what could be the problem?

PS : I'm working on a Macbook Pro (OS X Yosemite (10.10.4)) and my graphics card is an NVIDIA GeForce GT 650M 1024 MB

EDIT : I tried debugging the code that draws the triangles but I really don't see the error (mainly because I'm really really new to OpenGL). Underneath you can find the drawing code. Notice that I don't initialize GLEW anymore as it isn't necessary (according to the comments).

void OpenGL_Scene::mainLoop() {
    bool end = false;

    // Make vertices (punten) in a table
    // !!! WARNING : Use 1 table for ALL vertices !!! Don't use a separate table for each of the forms, this would slow down the program because you have to send each of the tables to OpenGL !!!

    float vertices[] = {-0.5, -0.5,   0.0, 0.5,   0.5, -0.5,      // 3 Points for first triangle --> (-0.5, -0.5) , (0.0, 0.5) and (0.5, -0.5)  (All in (x, y) --> 2D)
                    -0.8, -0.8,   -0.3, -0.8,   -0.8, -0.3};  // 3 Points for second triangle

    // Before we start drawing, clear the screen
    glClear(GL_COLOR_BUFFER_BIT);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    glEnableVertexAttribArray(0); // Activate the table we passed to OpenGL using the identifier (index) passed to OpenGL (in this case 0)

    // Now that OpenGL knows which vertices it has to display we are going to specify what it has to do with these vertices
    glDrawArrays(GL_TRIANGLES, 0, 6); // Draw both triangles

    glDisableVertexAttribArray(0);   // Because it isn't necessary anymore
    SDL_GL_SwapWindow(this->window); // Refresh the screen

    while(!end) {
        // Listen to events and play with them
        SDL_WaitEvent(&this->events); // Will wait for an event and assign it to "events" variable

        if(this->events.window.event == SDL_WINDOWEVENT_HIDDEN)
            cout << "The user has hidden the window !" << endl;
        else if(this->events.window.event == SDL_WINDOWEVENT_CLOSE) {
            cout << "The user closed the window !" << endl;

            glClear(GL_COLOR_BUFFER_BIT); // Clear the screen
            SDL_GL_SwapWindow(this->window);    // Refresh the window

            end = true;
        }  
    }
    // Quitting the SDL and OpenGL properly is done by the destructor
}

So now when I execute the project, first I make the window (this is succesfull) and then I call the mainLoop procedure (from above). I stepped trough the drawing code using the debugger, all the procedures were called (glClear, ...) but nothing appears in the window (it stays black).

Community
  • 1
  • 1
Kevin
  • 2,813
  • 3
  • 20
  • 30
  • Does it work with any other version? Try 3.2 or 3.3. OpenGL 3.1 is a "special" OpenGL version that removed a lot of deprecated functionality from the OpenGL 3.0 spec. – Nasser Al-Shawwa Jul 21 '15 at 12:27
  • I tried 3.2 and 3.3 but they show the same problem – Kevin Jul 21 '15 at 12:30
  • The line that you added to your code forces to create OpenGL context in "Core Profile". Perhaps without the line "Deprecated Profile" was chosen by default, but creating deprecated profile was not possible with your drivers. However, I have no idea why your new code is not working. Try searching for an error elsewhere. – stgatilov Jul 21 '15 at 12:31
  • @stgatilov Thanks! As the code runs until the context creation I am looking for errors in the part before the context creation. But the only thing that happens before `initializeWindow` get called is the constructor of my "OpenGL_Scene" class. So I'm not getting it where could be the error, as my constructor is very simple : `OpenGL_Scene::OpenGL_Scene(string windowTitle, int windowHeight, int windowWidth):windowTitle(windowTitle), windowHeight(windowHeight), windowWidth(windowWidth) {};` – Kevin Jul 21 '15 at 12:45
  • @HyperZ You wrote that OpenGL context is created, but nothing is drawn. Perhaps some setup/draw code is wrong **after** context creation then? – stgatilov Jul 21 '15 at 12:47
  • @stgatilov I was thinking about omitting the line that I added that forces to create the context in "Core Profile" and searching for an error in the part before the context creation, but indeed if it is a compatibility problem I won't find anything... But can it be a compatibility problem if it works fine (without the line I added) when all the code is in the main function? However I will check the setup/draw code also. – Kevin Jul 21 '15 at 12:52
  • You may check out lazyfoo's tutorials and compare initialization code to see if you can spot some error. http://lazyfoo.net/tutorials/SDL/51_SDL_and_modern_opengl/index.php – Chemistpp Jul 21 '15 at 13:06
  • I compared with lazyfoo's tutorial (and others) and I presume the problem has something to do with the initialization of GLEW, so I edited the post. – Kevin Jul 21 '15 at 13:44
  • Well, I thought glut was used to manage your windows, but you're already using SDL. I did a lot with openGL and SDL1, but SDL2 I just started getting into. I don't think you need glut or glew, at least I didn't with SDL1. I thought both of those are just openGL context management libraries – Chemistpp Jul 21 '15 at 13:46
  • @Chemistpp Indeed, until now I didn't used GLEW or GLUT (as the only thing it would have done is make the `glutInit(&argc, argv);` call) and it worked fine. But now that I am facing this problem I think that not initializing GLEW/GLUT could maybe be the problem, because apart from that I don't see where could be the error, as the drawing code remained the same and worked before. – Kevin Jul 21 '15 at 13:50
  • @HyperZ Maybe you want to have a look at the open.gl (it's a url) tutorial. I do not think that you have to use GLUT, because GLUT is a library to create a window to render your OpenGL stuff in it. But you should use GLEW, because this initializes your OpenGL functions (There is a better explanation in the tutorial). – DanceIgel Jul 21 '15 at 14:02
  • 1
    See [this](https://open.gl/context#Onemorething). That's why you have to/should use GLEW. – DanceIgel Jul 21 '15 at 14:04
  • @DanceIgel The OP is using Mac OS. There's no need for GLEW. GLEW is useful on platforms where you need to load functions beyond OpenGL 1.1, like Windows and Linux. That's not the case on Mac OS. – Reto Koradi Jul 21 '15 at 15:13
  • @RetoKoradi Ok. Developing with MacOS is new for me, so thanks for the advise! :) – DanceIgel Jul 21 '15 at 15:23
  • @stgatilov I edited the post to add the drawing code. Tried to figure out what's wrong in there but couldn't find it. – Kevin Jul 23 '15 at 12:07
  • Given that you use *Core* profile, I suppose you have to specify some shaders also, but I'm not sure. – stgatilov Jul 23 '15 at 12:35

1 Answers1

7

I found the error. I was initializing OpenGL after initializing the SDL, this is why the context could not be created without forcing to go into "Core Profile".

The correct order in "initializeWindow" is :

// Configure OpenGL

// Use version 3.1
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); // OpenGL 3.x
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); // OpenGL x.1 --> OpenGL 3.1

// Double buffering
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Use double buffering (0 to not use it)
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);  // Buffer has a depth of 24 bits

// Initialize the SDL
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
    cout << "Error while initializing the SDL : " << SDL_GetError() << endl;
    SDL_Quit();

    return false;
}

Doing so the context is created successfully.

Kevin
  • 2,813
  • 3
  • 20
  • 30