Відправка вершин до OpenGLES – РОЗРОБКА ІГОР ДЛЯ ОС ANDROID

Як ми опишемо місце розташування трьох вершин нашого першого трикутника Легко – припустимо, що наша система координат лежить в діапазоні від (0, 0, 1) до (320 480 -1) Тоді ми можемо зробити наступне:

Перші три рядки повинні бути вам вже знайомі Єдина цікава частина стосується того, скільки байт ми виділяємо У нас є три вершини, кожна з яких має положення, яке визначається координатами по осях х та у Кожна координата – це число з плаваючою точкою (f1oat), яке займає 4 байта Всі вершини мають дві координати, кожна з яких займає 4 байта, так що в цілому для нашого трикутника необхідно 24 байта

ПРИМІТКА

Ми можемо визначити вершини тільки за допомогою координат х і у, a OpenGL ES автоматично задасть z-координаті значення нуль

Далі копіюємо в буфер масив чисел типу float, що містить дані про вершини Наш трикутник починається в нижньому лівому кутку (0, 0), далі до правої межі видимої області / екрана (319 0), а потім до середини верхньої межі видимої області / екрана Оскільки ми вже вміємо користуватися буфером NIO, ми також застосовуємо метод f 1 i р до нашого буферу Таким чином, posi ti on буде 0, a limit буде 6 (памятаєте, що значення властивостей 1 imit і position FloatBuffer задаються в числах з плаваючою точкою, а не в байтах)

Як тільки наш буфер NIO готовий, ми можемо вказати OpenGL ES отрісовать його в поточному стані (наприклад, з областю перегляду і матрицею проекції) Це можна зробити за допомогою наступного фрагмента:

Виклик методу gl EnabledientState можна назвати рудиментарним Так ми повідомляємо OpenGL ES, що вершини, які ми збираємося намалювати, мають позиції Це трохи нерозумно по двох наступних причин: константа називається GL10 GL VERTEX ARRAY, дещо плутано Було б розумніше назвати її GL10GL P0SITI0N ARRAY неможливо намалювати те, у чого немає позиції, так що використовувати даний метод дещо зайве Ми проте застосуємо його для зручності роботи з OpenGL ES

Звертаючись до gl VertexPointerC, ми повідомляємо OpenGL ES, де можна знайти позиції вершин, а також деяку іншу додаткову інформацію Перший параметр повідомляє OpenGL ES, що кожна позиція вершини складається з двох координат, х і у Якби ви ввели х, у і z, координат було б три Другий параметр повідомляє OpenGL ES тип даних, в яких зберігається кожна координата У нашому випадку це GL10 GLFL0AT, який показує, що ми використовували f1oat по 4 байта кожен Третій параметр, stride (крок), повідомляє OpenGL, наскільки далеко в байтах вершини розташовані один від одного У попередньому випадку крок дорівнював нулю, тому що позиції розташовувалися дуже близько один до одного (вершина 1 (х у), вершина 2 (х у) і т д) Останнім параметром є FloatBuffer, щодо якого слід запамятати дві речі:

FloatBuffег є блоком памяті в нативної купі, так що він має початковий адресу позиція FloatBuffer – зсув щодо початкової адреси

OpenGL ES бере адресу початку буфера і додає до нього позицію буфера, щоб потрапити до того числа з плаваючою точкою, з якого почнеться зчитування вершин, коли ми вкажемо виконати отрисовку вмісту буфера Покажчик на вершини (який знову-таки правильніше називати покажчиком на місце розташування) – це стан OpenGL ES Поки ми не змінимо його (і контекст не загубиться), OpenGL ES памятатиме і використовувати його для всіх наступних запитів, що вимагають позицію вершин

І нарешті, розглянемо виклик gl DrawArraysC Цей метод Отріс наш трикутник Перший параметр визначає, елементарну фігуру якого типу ми збираємося малювати У даному випадку ми хочемо намалювати кілька трикутників, які визначаються GL10GLTRIANGLES Наступний параметр – це зсув щодо першої вершини на позначену в покажчику вершину Дане зсув вимірюється в вершинах, а не байтах або числах з плаваючою крапкою Якби ми описували більш ніж один трикутник, ми могли б використовувати цей фрагмент, щоб візуалізувати лише частину списку трикутників Наш останній аргумент повідомляє OpenGL ES, скільки вершин потрібно використовувати для візуалізації У нашому випадку це три вершини Зверніть увагу, що нам завжди необхідно визначити кількість, кратне трьом, якщо ми малюємо GL10 GLTRIANGLES Кожен трикутник складається з трьох вершин, так що це доцільно Для інших найпростіших фігур правила дещо відрізняються

Коли ми запускаємо команду gl VertexPoi nter, OpenGL ES передає місця розташування вершини графічному процесору і зберігає їх для всіх наступних команд візуалізації Кожен раз, коли ми вказуємо OpenGL ES візуалізувати вершини, їх місце розташування впізнається з даних, які ми визначили за допомогою gl VertexPoi nter

Кожна наша вершина може мати і інші властивості крім місця розташування Ще однією властивістю може бути колір вершини Зазвичай ці властивості називаються властивостями вершини

Може виникнути питання: як OpenGL ES дізнається, якого кольору зробити трикутник, якщо ми визначили тільки місце розташування Справа в тому, що OpenGL ES містить налаштування за замовчуванням для властивостей вершини, які ми самі не вказали Більшість даних властивостей можна налаштувати безпосередньо Наприклад, щоб встановити колір для всіх вершин, які малюємо, можна використовувати наступний метод:

Цей метод задасть колір за замовчуванням, використовуваний для всіх вершин, для яких ми не вказали колір окремо Даний колір вказується в значеннях RGB А в діапазоні від 0,0 до 1,0 – такий же діапазон ми вже застосовували при роботі з кольором вище Колір за замовчуванням, з якого починає OpenGL ES, – це (1 1 1 1), матовий білий

Ось і весь код, який нам потрібен для візуалізації трикутника в паралельній проекції за допомогою OpenGL ES Ці 16 рядків коду необхідні нам для очищення екрана, установки області перегляду і матриці проекції, створення буфера N10, в якому ми зберігаємо інформацію про становище вершин, і для отрисовки трикутника А тепер порівняйте це кількість коду з кількома сторінками, які пішли у мене на те, щоб пояснити все це Звичайно, я міг би опустити деякі деталі і виражатися простіше Проблема в тому, що OpenGL ES місцями досить складний, і для того, щоб не отримати після роботи порожній екран, краще спочатку вивчити все докладно, а не просто копіювати і вставляти код

Всі разом

Щоб підвести підсумки цього розділу, обєднаємо всі за допомогою реалізації GLGame і Screen У лістингу 75 показаний приклад того, як це зробити

Лістинг 75 FirstTriangleTestJava package combadogicandroidgamesglbasics

Клас FirstTriangleTest успадковує від GLGame і, відповідно, реалізує метод GamegetStartScreenO У цьому методі ми створюємо новий клас FirstTriangleScreen, який згодом буде викликатися GLGame, оновлюватися і відображатися Зверніть увагу, що, коли викликається цей метод, ми вже знаходимося в основному циклі або навіть скоріше в потоці візуалізації GLSurf aceVi ew, так що ми можемо використовувати методи OpenGL ES в конструкторі класу FirstTriangleScreen Розглянемо реалізацію класу Screen докладніше:

Клас FirstTriangleScreen містить два члена: екземпляр класу GLGraphics і наш перевірений буфер FloatBuf fег, який зберігає 20-положення трьох вершин нашого трикутника У конструкторі переносимо примірник класу GLGraphics з GLGame і створюємо FloatBuf fer у відповідності з нашим попереднім фрагментом коду Оскільки конструктор Sc reen отримує екземпляр класу Game, нам необхідно привести його до класу GLGame, щоб мати можливість викликати метод GLGamegetGLGraphics

Метод present відображає те, що ми з вами щойно обговорили: ми встановлюємо область перегляду, очищаємо екран, встановлюємо матрицю проекції, щоб можна було працювати в зміненій системі координат, задаємо колір за замовчуванням для вершин (у нашому випадку червоний), вказуємо, що у наших вершин будуть певні положення, повідомляємо OpenGL ES, де знаходиться інформація про ці положення вершин, і, нарешті, відображаємо наш маленький червоний трикутник

Залишилося частина коду – це просто шаблон У методі update ми перевіряємо, чи не заповнився чи наш буфер подій Залишилося частина коду взагалі нічого не робить

ПРИМІТКА

З цього моменту ми зосередимося тільки на самих класах Screen, так як що укладають їх похідні класи GLGame, такі як RrstTriangleTest, не зміняться Ми також трохи скорочуємо код, прибираючи всі непотрібні методи класу Screen Наступні приклади будуть відрізнятися тільки назвами елементів, конструкторів і методів презентації

На рис 77 показано, яке зображення вийшло в результаті попереднього прикладу

Розглянемо, що ж ми зробили не так в цьому прикладі з точки зору оптимальних методів роботи з OpenGL ES

Ми встановлювали одні й ті ж стану одним і тим же значенням знову і знову без будь-якої на те потреби Зміни станів в OpenGL ES займають багато памяті – деякі трохи більше, деякі трохи менше Ми завжди повинні прагнути скоротити кількість змін стану, які ми робимо за один кадр

Точка спостереження і матриця проекції ніколи не змінюються з моменту, як ми їх встановили Ми можемо перемістити цей код в метод resume, який викликається всього один раз, коли створюється (або створюється заново) поверхню OpenGL ES Тут же ми справляємося з втратою контексту OpenGL ES

Рис 77 Наш перший фрейдистський трикутник

Ми можемо також перемістити настройку кольору для очищення екрана і виконувану за замовчуванням установку кольору вершини в метод resume Ці два кольори також не змінюватися

Ми можемо перемістити методи gl Enabled ientState і gl VertexPoi nter в метод resume

Єдине, що треба викликати в кожному кадрі, – це методи glClearO і glDrawArrays Вони обидва використовують поточні стану OpenGL ES, які залишаються незайманими до тих пір, поки ми не змінимо їх або трапиться втрата контексту через те, що Activity була призупинена і запущена знову

Якщо виконати всі ці оптимізації, у нас буде тільки два виклики OpenGL ES в основному циклі

Щоб остаточно не заплутатися, ми поки не будемо використовувати дані оптимізації Однак коли ми перейдемо до нашої першій грі на OpenGL ES, нам доведеться дотримуватися даних рекомендацій як можна суворіше

Додамо ще кілька атрибутів до вершин нашого трикутника Для початку займемося кольором

ПРИМІТКА

Спостережні читачі, напевно, вже помітили, що у трикутника на рис 77 не вистачає пікселя в нижньому правому куті Можливо, це виглядає, як типова помилка заниження на одиницю, але насправді, це відбувається через те, що OpenGL ES Растеризує (малює пікселі) трикутника Існує особливе правило растрирования трикутника, яке викликає подібний огріх Однак не варто переживати Нас з вами хвилює візуалізація двомірних прямокутників (що складаються з двох трикутників), де цей ефект нівелюється

Джерело: Mario Zechner / Маріо Цехнер, «Програмування ігор під Android», пров Єгор Сидорович, Євген зазноби, Видавництво «Пітер»

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


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

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

Ваш отзыв

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

*

*