OpenGL: Змінення розміру дисплея та glOrtho / glViewport


16

Я досліджував це питання з декількох джерел і досі не знайшов твердої відповіді, де сказано, що "так, це правильне мислення" або "ні, ось як це робиться".

Я намагаюся забезпечити незалежність резолюції за допомогою ренделінгу OpenGL. Я думаю, що мені слід було б це зробити, це створити проекцію, використовуючи glOrthoте, що я хочу, щоб були світові координати. Наприклад, glOrtho(-50.0, 50.0, -50.0, 50.0, 1.0, -1.0). Далі встановіть область перегляду на роздільну здатність екрана , тобто - glViewport(0, 0, 800, 600). Нарешті, щоразу, коли вікно буде змінено повторно, телефонуйте glViewportз оновленою роздільною здатністю екрана. Це дозволить масштабувати ваші цифри.

Це правильний спосіб забезпечити, щоб моделі займали однакову пропорцію екрану при різних роздільних здатностях? Чи повинен я використовувати проекцію, рівну дозволу? Я знайшов відповіді, де говорилося, що glOrthoслід використовувати роздільну здатність вашого вікна, а інші сказали, що це має / може бути іншим.

Думки?

Відповіді:


19

Те, що ви описали, цілком адекватне і доречне для забезпечення незалежності резолюції. Все, що ви малюєте, дійсно завжди займе однакову частину вашого вікна.

Однак якщо ви нічого не зробите з цим, у вас виникнуть проблеми зі співвідношенням сторін . Наприклад, з огляду на числа, які ви написали, якщо ви намалюєте коло, воно буде скошене - ширше, ніж високе, оскільки ваша горизонтальна шкала становить 800 / (50 + 50) = 8, а ваша вертикальна шкала - 600 / (50+ 50) = 6.

Не може бути автоматичного рішення цієї проблеми ; вам доведеться вибрати графічний результат, який ви хочете, і врахувати його вплив на ігровий процес. Деякі поширені приклади:

  • У 3D-програмі з перспективою-проекцією без HUD звичайним простим рішенням (доступним у OpenGL як частина gluPerspective) є виправлення поля зору проекції відносно вертикального виміру . Це означає, що в такій грі, якщо змінити розмір вікна по горизонталі, ви побачите більш-менш сцену і середня частина зображення взагалі не зміниться.

    Ця ж ідея може бути застосована і до перегляду 2D / 2.5D.

    (Зверніть увагу, що це дозволяє гравцеві збільшити поле зору зору горизонтально, зробивши широке, але не високе вікно. Це може бути небажаним у конкурентній багатокористувацькій грі.)

  • Якщо у вас графіка із заповненням перегляду з фіксованим співвідношенням сторін (наприклад, 2D карта, що не прокручується, або декоративна рамка), або якщо ви іншим чином не можете змінити макет, вам потрібно зробити щось на кшталт наявності чорних смуг на двох сторони, щоб заповнити невикористаний простір.

    Або ви можете зробити графіку з тематично узгодженим наповнювальним матеріалом по краях, щоб їх можна було обрізати для розміщення дисплея, не завдаючи шкоди геймплею.

  • Якщо у вас є HUD поверх іншої графіки, ви можете вирішити, що кожен елемент HUD закріплений на частині вікна (лівий верхній, нижній центр тощо) та обчислити його координати; "розтягування" змін співвідношення сторін поглинається "білим простором" між елементами HUD.

Що стосується конкретних математики питання, враховуючи , що ви робите резолюцію незалежність, все , що вам потрібно , щоб почати з цим співвідношенням сторін, єдиним число: width / height. Наприклад, якщо вікно квадратне, воно буде 1; якщо вона 800 на 600, це буде 800/600 = 4/3 = 1.333̅.

Наприклад, припустимо, що ви хочете, щоб написана вами ортографічна проекція отримала додаткове місце зліва та справа, якщо вікно буде розширене. Ви можете зробити це так:

float aspect = width / height;
glViewport(0, 0, width, height);
glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);

Це гарантує, що для вікон, щонайменше настільки ж широких, як вони високі, буде видно все, що ви намалюєте з координатами x та y в межах від -50 до 50.

З іншого боку, якщо вікно вужче, ніж воно високе, діапазон від -50 до 50 буде відрізаний. Скажімо, ви хотіли переконатися, що він завжди видно (щоб ваш вміст був максимальним розміром, якщо вікно квадратне, але меншим інакше); у такому випадку ви просто зробите те ж саме на висоту замість ширини.

float aspect = width / height;
glViewport(0, 0, width, height);
if (aspect >= 1.0)
  glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);
else
  glOrtho(-50.0, 50.0, -50.0 / aspect, 50.0 / aspect, 1.0, -1.0);

Зауважимо, що у другому випадку ми ділимо, а не множимо. Це просто тому, що ми обчислили пропорції, width / heightа не height / width; будьте взаємними, якщо вам легше це зрозуміти.

Знову ж таки, це не єдиний спосіб управління співвідношенням сторін; це просто дуже простий варіант, щоб переконатися, що ваш вміст не розбивається і не відрізається. З’ясуйте, що ви хочете статися, коли ваше вікно широке, високе чи що завгодно; потім опрацюйте математику цього.


Дякую за ДУЖЕ проникливу відповідь. На моє запитання відповіли недостатньо.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.