Обработка изменения размера окна с помощью OpenGL и SDL
из кода у меня есть программа, которая рисует и двигает площадь вокруг окна приложения, у меня возникли проблемы при изменении размера окна приложения. Когда я обрабатываю изменение размера и соответственно изменяю состояния, все на экране, которое должно быть нарисовано и было до изменения размера, исчезает. Я понятия не имею, почему, потому что ни один из внутренних координат объектов не изменяется во время изменения размера окна.
мой вопрос в том, может ли кто-нибудь указать мне в правильном направлении, чтобы решить мою проблема.(Код компилируется отлично)
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();
}
основной цикл:
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();
}
все работает отлично, пока размер окна не будет изменен.
2 ответов
Я скопировал вставленный код, и я объясню, что происходит строка за строкой. Это должно помочь вам не только понять, почему экран становится пустым после изменения размера, но и помочь вам удалить вещи, которые вам не нужны.
void ResizeWindow()
{
эти строчки хороши! Вы получили новую ширину и высоту экрана из события resize. Я предполагаю, что событие доступно на данный момент в вашем коде.
screen_width = event.resize.w;
screen_height = event.resize.h;
я сомневаюсь, что вам нужен этот вызов SDL_SetViedoMode
. Я бы ожидайте, что он будет использоваться только при настройке окна OpenGL. У меня нет опыта использования SDL в настоящее время, поэтому я не могу быть уверен. Я быстро просмотрел документацию, и это, похоже, поддерживает ее использование так, как я ожидал.
SDL_SetVideoMode(screen_width, screen_height, bpp, SDL_OPENGL | SDL_RESIZABLE | SDL_DOUBLEBUF);
теперь мы переходим к интересным вещам GL. Вы изменили размер окна просмотра, что необходимо.
glViewport(0, 0, screen_width, screen_height);
теперь вы создаете новую проекционную матрицу для поддержания соотношения сторон (если я не ошибаюсь). Ты подменил матричный режим и настройка ортогональной проекционной матрицы, которая является разумной.
glMatrixMode(GL_PROJECTION);
glOrtho(0, screen_width, 0, screen_height, -1, 1);
теперь вы устанавливаете матрицу проекции в identity, перезаписывая старую матрицу проекции OpenGL и отменяя всю хорошую работу, которую вы сделали. Вот почему экран погас.
glLoadIdentity();
теперь вы переключаетесь на матрицу model-view и устанавливаете ее в identity, что на самом деле не обязательно, если вы устанавливаете ее правильно в другом месте.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
я сомневаюсь, что вы очень нужна следующая строчка. Почему вы хотите очистить экран после изменения размера, в любом случае? Вы хотите перерисовать его, но я уверен, что ваша функция рисования очистит экран и нарисует объект, который будет вызван автоматически после обновления.
glClear(GL_COLOR_BUFFER_BIT);
и вам определенно не нужно повторно устанавливать текущую матрицу представления модели на идентичность во второй раз. OpenGL все еще находится в режиме просмотра модели, и эта матрица уже установлена в identity! Помните, что OpenGL-это состояние машина!
glLoadIdentity();
}
одна проблема, вы, наверное, состоит в том, что при изменении размера окна с СДЛ нового контекста OpenGL, что означает, что все вещи, которые вы загрузили раньше (текстур, вершин, буферов объекты) и состояние установить (как вершина массива указателей) теряются. Вам нужно повторно инициализировать их при использовании SDL. Если вы хотите сохранить их, не используйте SDL для управления окнами. Я рекомендую GLFW.
этой
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();
}
является наиболее распространенным анти шаблон, найденный в начинающих OpenGL кода. Рисунок команды и управление состоянием, влияющие на чертеж, принадлежат функции чертежа. Это следующее:
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();
Если вы хотите, чтобы надежная программа OpenGL никогда не помещала их (только) в обработчик изменения размера. Они принадлежат другим командам рисования.