3D зсередини, 3D Графіка, Графіка, статті

Дмитро Ситник, Мій Комп'ютер

Зараз важко знайти людину яка хоч раз в житті не грав би в тривимірні ігри. Більше того, я впевнений, що для багатьох це улюблене заняття. Але чи замислювався хтось, що стоїть за гарною картинкою на екрані? Як виходить тривимірне зображення в грі? У цій статті я хотів би відкрити завісу таємниці і розповісти про те, як влаштовані сучасні 3D-ігри. І зробити це я б хотів на прикладі популярної гри Quake 3 Arena.

Як відомо, вся тривимірна графіка в іграшці складається з полігонів. Полігон в іграшках – це опуклий багатокутник. Я сподіваюся, ви добре собі уявляєте, як виглядає багатокутник на площині екрану? Координата Х, координата Y, центр координат – верхній лівий кут … У тривимірному зображенні все те саме, тільки центр координат знаходиться в центрі екрана і додається ще одна – Z-Координата, яка йде вглиб екрана (має позитивний знак). Ось з таких-то полігонів і складається вся графіка в іграшці.

Будь опуклий полігон, в свою чергу, можна розбити на трикутники. Наприклад, ромб можна розбити на 2 або 4 трикутника. Все це відбувається в процесі побудови зображення. Навіщо це потрібно? Відповідь тривіальний – комп'ютера значно простіше зобразити на екрані трикутник, ніж складна опуклий полігон, що складається з n-ного кількості граней. Так що трикутники – це цеглинки тривимірної графіки (точніше, полігонної графіки – адже є й інші різновиди).

Тепер зрозуміло, з чого складаються рівні. Все це – десятки тисяч полігонів, які потім розбиваються на ще менші елементи – трикутники. Чим більше полігонів, тим більше гладким і деталізованим стає зображення, але тим більше гра "гальмує", відповідно, більше вимагає пам'яті – все має свою ціну. Навіть криві, і ті складаються з полігонів. Може бути, крім стилізації зображень, є і якісь інші методи економії полігонів. Стилізація стилізацією, але ж хочеться реалістичності, однак …

Невидимки

Тут стає питання про HSR – Hidden Surface Removal (видалення невидимих ​​поверхонь). В Quake це робиться за допомогою PVS – Potential Visibility Set (список потенційної видимості). Спробуємо пояснити фігурально. Наприклад, якщо ви стоїте будинку в кухні, то ви можете бачити, скажімо, тільки коридор і ванну. Спальню, більшу кімнату і балкон ви ніяк не можете бачити. І навпаки, стоячи на балконі, ви ніяк не можете бачити ні кухню, ні ванну. Так навіщо витрачати час на промальовування і розрахунок цих кімнат, якщо вони не потрапляють в межі своєї видимості? Список потенційно видимих ​​кімнат – це і є PVS, список потенційної видимості.

Гра теж складається з так званих кімнат – кластерів. Кластер – це, грубо кажучи, шматок рівня. Він складається з полігонів. Горезвісний PVS і є список видимих ​​кластерів, складений для кожного кластера окремо. Складання цього списку – справа різних утиліт, що використовуються на етапі проектування рівня. Зображення будується так: спочатку визначається кластер, в якому знаходиться гравець. Далі ми беремо полігони з потенційно видимих ​​кластерів і обробляємо їх. Таким чином, ми працюємо тільки з потрібними нам полігонами.

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

Дуже просто. Спочатку ми повинні додати (або відняти – все одно, просто поміняється напрям руху) до кожної координаті координати гравця. Таким чином, гравець завжди буде знаходитися в центрі координат. Потім здійснюється поворот – за формулами, відомим будь першокурснику. В результаті, ми отримаємо полігони, трансформовані щодо гравця. Відмінно! Вже півсправи зроблено. Залишається тільки визначити, які полігони потрапляють у наше поле зору.

Наприклад, ставши в кухні обличчям до стіни, ми не побачимо ні коридору, ні ванни. Ось чому одного списку потенційної видимості мало. Гра відсікає всі полігони, які знаходяться за спиною у гравця. Це здійснюється простою перевіркою – якщо всі координати вершин полігону Z менше нуля, значить, ми не побачимо цей полігон. Але й це ще не все. Виявляється, ми також можемо зменшити кількість зображуваних полігонів. Тут варто зауважити, що всі вершини полігонів рівня задані в одному напрямку – або за годинниковою стрілкою, або проти (див. малюнок).

Так от, обчисливши нормаль трансформованого полігону, ми можемо дізнатися, куди він, грубо кажучи, "дивиться". Адже нормалі – це напрямки. Якщо нормаль позитивна – значить, полігон дивиться на нас, якщо негативна, то полігон звернений "спиною" до нас. Таким чином, залишаються тільки ті полігони, які можуть бути видимі – вони-то і виводяться на екран. Але і тут виникає проблема. Ми знаємо, які полігони ми бачимо. Але як їх вивести на екран, адже далекі полігони можуть перекрити ближні, і вийде понівечене зображення?

Перспектива

Комп'ютеру все одно, які полігони знаходяться ближче, а які – далі. Для цього використовується один з алгоритмів промальовування тривимірних поверхонь. Наприклад, можна відсортувати полігони по їх середнім Z-координатах і вивести в цій послідовності на екран. Але цей спосіб не у всіх випадках може дати коректне зображення. Є ще один спосіб, в даний час має широке застосування на апаратній рівні. Знаючи координати кожної вершини в просторі, їх можна просто інтерполювати (про інтерполяції нижче) і дізнатися координати кожної точки полігону в тривимірному просторі. Нас поки цікавить тільки Z-координата, її ми і інтерполіруем.

Додатково до екранного буфера використовується ще один, таких же розмірів, в якому знаходяться дуже великі числа. Дізнавшись для даної інтерпольованої точки полігону Z-Координату, ми дивимося в цей позаекранного буфер. Якщо розташоване там число більше, ніж наша Z-Координата, то ми записуємо її туди, а на екран виводимо відповідний піксель текстури полігону. Якщо якийсь полігон і його конкретна точка в даному місці виявиться ближче, то ця точка і в буфері, і на екрані замінюється. Виглядає досить громіздко, а й OpenGL, І Glide, І Direct3D вміють все це робити на апаратному рівні, завдяки чому виходить цілком прийнятна швидкість. Раніше розробникам ігор залишалося тільки намалювати на екрані трикутники, наклавши на них конкретні текстури. Але зараз, після виходу Quake III, Технологія ускладнилася.

Текстура

Тепер на полігон може накладатися або звичайна текстура (для тих, хто не знає, текстура – це двомірне зображення, яке потім відображається на полігоні), або shader. Shader – це скриптова файл, в якому вказана послідовність "косметичних" перетворень даного полігону: змішання кількох текстур, анімація текстури, прозорість і т. п. Все це задається в текстовому форматі. Як же відбувається процес накладення текстур?

Скажімо так: полігон – площина, розташована в тривимірному просторі. Стало бути, кожній точці полігона, крім абсолютного значення в просторовій системі координат, притаманні відносні координати двовимірної системи – до них-то і прив'язується текстура. Тобто, такий-то точці полігону відповідає певний піксель текстури (10,10). Це здійснюється за простими формулами:

1. SREEN_X=X_RES/2+VDIST*(X/Z);

2. SREEN_Y=Y_RES/2+VDIST*(Y/Z);

де SCREEN_X, SCREEN_Y – Координати точки на екрані; X, Y, Z – Координати тривимірної точки; X_RES, Y_RES – Дозвіл екрану (наприклад, 640×480); VDIST – Спеціальна величина, масштабує зображення, або відстань від камери до початку координат по Z. Отримані двовимірні координати текстури і точки інтерполюються між собою, і на екрані виходить тривимірне зображення. Що таке інтерполяція?

Інтерполяція – це зміна числа від a до b за n кроків. Припустимо, нам треба інтерполювати 1 до 5 в 9 кроків. Ми отримуємо наступний ряд: 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5. Таким же чином, знаючи координати вершин, ми можемо, інтерполювати їх, отримати проміжні координати для кожної точки. Якщо комусь цікаво, то формула інтерполяції наступна:

3. rez = start+step*(end-start)/num_steps;

де rez – Результат інтерполяції; end, start – Перше і останнє число ряду; num_steps – Кількість кроків; step – Поточний крок, що знаходиться в інтервалі від 0 до num_steps.

При зображенні полігону може застосовується билинейная фільтрація-стандартний за теперішніх часів ефект розмиття пікселів при збільшенні полігонів. Раніше при наближенні до стін пікселі збільшувалися, і текстура виходила квадратної – одержувані в результаті інтерполяції нецілі координати полігону "усереднювалися" пікселями текстур. При білінійної фільтрації використовується наступний трюк. При отриманні якихось нецілих двовимірних координат точки ми знаходимо найближчі цілі пікселі текстури і інтерполіруем їх колір, використовуючи як поточного кроку інтерполяції неціле значення, отримане в поточній точці. Відбувається щось на зразок градієнтної розтяжки – для кожної точки ми отримуємо точне проміжне значення, а не округлене ціле.

Схожі статті:


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

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*