С++ GLFW3 проблема с растяжкой в полноэкранном режиме в Linux

Я переношу одну из своих игр из Windows в Linux, используя GLFW3 для создания окна. Код работает отлично, когда я запускаю его в Windows (используя GLFW3 и opengl), но когда я компилирую и запускаю его в ubuntu 12.10, есть проблема в полноэкранном режиме (в оконном режиме он работает хорошо), где правая часть (около 25 %) кадра растягивается и уходит с экрана. Вот как я создаю окно GLFW:

window = glfwCreateWindow(1024, 768, "Chaos Shell", glfwGetPrimaryMonitor(), NULL);

И здесь мой код инициализации opengl:

glViewport(0, 0, 1024, 768);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-512.0f, 512.0f, -384.0f, 384.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Над кодом должен загружать игру в полноэкранном режиме с разрешением 1024 на 768. Когда я запускаю его, glfwCreateWindow изменяет разрешение экрана с моего текущего разрешения экрана (1366 на 768) до 1024 на 768, но правая часть кадра отключается. Если я вручную изменю разрешение на 1024 на 768, а затем запустим игру, все будет хорошо. Кроме того, запуск этого же кода в Windows не вызывает никаких проблем, независимо от того, каково мое текущее разрешение экрана. Он просто меняет разрешение на 1024 на 768, а затем все выглядит идеально. Если кто-то найдет, почему он действует странно в ubuntu, тогда я буду очень благодарен...

1 ответ

Вероятно, вы столкнулись с проблемой с диспетчером окон. Короче говоря, оконный менеджер не заметил изменения изменения разрешения и из-за полноэкранного флага расширяет окно до старого разрешения.

Или вы вообще не получили 1024 × 768, потому что ваш экран не поддерживает его и вместо этого получил меньшее разрешение 16: 9. Поэтому не используйте жестко заданные значения для установки окна просмотра.

Честно говоря: вы не должны менять разрешение экрана вообще! Вряд ли кто-нибудь использует дисплеи CRT. А для дисплеев с дискретными пикселями (LCD, AMOLED, DLP-проекторы, LCoS-проекторы) нет смысла запускать их ни в чем другом, кроме собственного разрешения. Поэтому просто создайте полноэкранное окно, чтобы система не изменила разрешение.

При настройке запроса видового экрана фактический размер окна из GLFW вместо того, чтобы полагаться на ваши жестко заданные значения (это фактически также может исправить вашу проблему с изменением разрешения).

Если вы хотите уменьшить нагрузку на GPU при рендеринге: используйте FBO для рендеринга текстуры требуемого разрешения и на последнем шаге потяните эту текстуру на полноэкранный квадрат, чтобы растянуть ее до размера дисплея. Он выглядит лучше, чем большинство производителей сканеров, и ваша игра не возится с остальной частью системы.

Обновление из-за комментария

Установка разрешения экрана в ответ на то, что игра не может справиться с разрешениями не 4: 3, - очень плохой стиль. Потребовалось достаточно много времени, чтобы крупные игровые студии приняли на широкие экраны. Это неприемлемо, потому что так легко исправить.

Не прикрывайте ошибки с помощью чего-то на пользователя, которого он может не захотеть. И если у пользователя есть хороший дисплей, дайте ему возможность фактически использовать его!

Ваша проблема не в разрешении экрана. Это жестко закодированная схема просмотра и проецирования. Вам нужно это исправить.

Чтобы устранить проблему "игра выглядит ужасно с разным разрешением", вам нужно установить видовое окно и проекцию в ответ на размер окна. Как это:

int window_width, window_height;
glfwGetWindowSize(&window_width, &window_height);

if( 0 == window_width
 || 0 == window_height) {
 /* window has no area, so there nothing to draw to */
 return;
}

float const window_aspect = (float)window_width / (float)window_height;

/* we want to draw with a total of 768 units vertically as if we
 * were drawing to a screen 768 pixels in height. */
float const projection_scale = 768./2;

glViewport(0, 0, window_width, window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( -aspect * projection_scale,
 aspect * projection_scale,
 -projection_scale, 
 projection_scale,
 0.0f,
 1.0f );

licensed under cc by-sa 3.0 with attribution.