Resizing a window using OpenGL and SDL

From the code that I have a program that draws and moves a square around the application window, I am having problems resizing the application window. When I process the size and change the state accordingly, everything on the screen, which should be drawn before it was resized, disappears. I don’t know why, because not one of the internal coordinates of the objects changes during window resizing.

My question is: can someone point me in the right direction to solve my problem. (The code compiles fine)

void ResizeWindow() { screen_width = event.resize.w; screen_height = event.resize.h; SDL_SetVideoMode(screen_width, screen_height, bpp, SDL_OPENGL | SDL_RESIZABLE | SDL_DOUBLEBUF); glViewport(0, 0, screen_width, screen_height); glMatrixMode(GL_PROJECTION); glOrtho(0, screen_width, 0, screen_height, -1, 1); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); } 

The main loop:

 while (running == true) { while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_VIDEORESIZE: ResizeWindow(); break; // resizing called here case SDL_QUIT: running = false; break; case SDL_KEYDOWN: square.Handle_Input(down); break; case SDL_KEYUP: square.Handle_Input(up); break; } } square.Move(); square.Check_Collision(); glClear(GL_COLOR_BUFFER_BIT); square.Draw(); SDL_GL_SwapBuffers(); } 

Everything works fine until the window changes.

+6
source share
2 answers

I copied your code and I will explain what happens line by line. This should help you see not only why the screen goes blank after resizing, but also helps you remove unnecessary things.

 void ResizeWindow() { 

These next lines are good! You got the new width and height of the screen from the resize event. I assume the event is available at this point in your code.

  screen_width = event.resize.w; screen_height = event.resize.h; 

I doubt you need this call to SDL_SetViedoMode . I expect it to be used only when setting up an OpenGL window. I have no experience using SDL at this time, so I cannot be sure. I quickly looked through the documentation and seems to support it the way I expected.

 SDL_SetVideoMode(screen_width, screen_height, bpp, SDL_OPENGL | SDL_RESIZABLE | SDL_DOUBLEBUF); 

Now we get into the interesting GL material. You have resized the viewport, which is necessary.

  glViewport(0, 0, screen_width, screen_height); 

Now you are creating a new matrix of projections to support an aspect ration (unless I am mistaken). You switched the matrix mode and set up the orthographic projection matrix, which is reasonable.

  glMatrixMode(GL_PROJECTION); glOrtho(0, screen_width, 0, screen_height, -1, 1); 

Now you set the projection matrix to a personality, overwrite the old OpenGL projection matrix, and destroy all the good work you have done. It is for this reason that the screen disappeared.

  glLoadIdentity(); 

Now you switch to the model matrix and set it to a personality, which is actually not necessary if you set it correctly in another place.

  glMatrixMode(GL_MODELVIEW); glLoadIdentity(); 

I doubt you really need the next line. Why do you want to clear the screen after resizing? You want to redraw it, but I'm sure your drawing function will clear the screen and draw an object that will be called automatically after the update is complete.

  glClear(GL_COLOR_BUFFER_BIT); 

And you definitely don't need to reinstall the current model view matrix a second time. OpenGL is still in model view mode, and this matrix is ​​already set up for identity! Remember that OpenGL is a state machine.

  glLoadIdentity(); } 
+13
source

One of the problems that you probably have is that when you resize the window with the SDL, a new OpenGL context is created, which means that all the things you downloaded earlier (textures, vertex buffer objects) and the state that you set (for example, pointers to an array of vertices) lost. You must reinitialize them if using SDL. If you want to save them, do not use SDL to manage windows. I recommend GLFW.

it

 void ResizeWindow() { screen_width = event.resize.w; screen_height = event.resize.h; SDL_SetVideoMode(screen_width, screen_height, bpp, SDL_OPENGL | SDL_RESIZABLE | SDL_DOUBLEBUF); glViewport(0, 0, screen_width, screen_height); glMatrixMode(GL_PROJECTION); glOrtho(0, screen_width, 0, screen_height, -1, 1); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); } 

is the most common anti-pattern found in OpenGL code for beginners. The drawing and state commands that affect the drawing belong to the drawing function. This is the following:

 glViewport(0, 0, screen_width, screen_height); glMatrixMode(GL_PROJECTION); glOrtho(0, screen_width, 0, screen_height, -1, 1); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); 

If you want a reliable OpenGL program to never put them (only) in a resize handler. They belong to other drawing teams.

+1
source

Source: https://habr.com/ru/post/907629/


All Articles