Обработка изменения размера окна с помощью 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 никогда не помещала их (только) в обработчик изменения размера. Они принадлежат другим командам рисования.