GLSURFACEVIEW: ПОЛЕГШУЄ ЖИТТЯ З 2008 РОКУ

Насамперед нам знадобиться певний тип View, який дозволить нам малювати за допомогою OpenGL ES У Android API такий View є Він називається GLSurfaceView і є нащадком класу SurfaceView, який ми вже застосовували для отрисовки світу містера Нома

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

Метод onSurfaceCreated викликається кожного разу, коли створюється GLSurfaceView У перший раз це відбувається, коли ми запускаємо Activity, а потім кожен раз, коли ми повертаємося до Activity з режиму паузи Даний метод використовує два параметри: примірник GL10 і EGLConfig Примірник GL10 дозволяє давати команди OpenGL ES У свою чергу, EGLConfig просто повідомляє нам атрибути поверхні, наприклад глибину кольору Як правило, ця інформація ігнорується Ми встановимо геометрію і текстури в методі onSurfaceCreated

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

У методі onDrawFrame відбувається найцікавіше Він чимось схожий на наш метод Screen render, який викликається якомога частіше потоком візуалізації, який встановив для нас GLSurfaceView У цьому методі відбувається вся візуалізація

Крім реєстрації слухача Renderer нам також необхідно викликати метод GLSurfaceView onPause / onResume в методі onPause / onResume нашої активності Причина цього проста GLSurfaceView запустить потік візуалізації у своєму методі onResume і призупинить його в методі onPause Це означає, що наш слухач не буде викликатися до тих пір, поки Activity стоїть на паузі, так як потік візуалізації, направляючий виклики нашому слухачеві, також стоїть на паузі

Однак тут ми стикаємося з головною проблемою: кожен раз, коли Acti vi ty ставиться на паузу, поверхня GLSurfaceView знищується Коли Activity знову відновлює роботу (а ми викликаємо GLSurfaceViewonResume), GLSurfaceView створює екземпляр нової поверхні візуалізації OpenGL ES та інформує нас про це, викликаючи наш метод слухача onSurfaceCreated Все було б добре, якби не одна проблема: всі стани OpenGL ES, які ми встановлюємо, будуть втрачені Це також стосується, зокрема, текстур і багато чого іншого, що в подібному випадку доведеться перезавантажувати Дана проблема також відома під назвою втрата контексту Термін контекст вживається тут тому, що OpenGL ES асоціює так званий контекст з кожною поверхнею, яку створює і яка містить поточний стан Коли ми видаляємо поверхню, втрачається також і контекст Все не так погано, як здається, якщо при створенні гри взяти до уваги можливість втрати контексту

ПРИМІТКА

Взагалі, це EGL відповідає за створення і видалення контексту і площині EGL – це ще один стандарт Khronos Group Він описує, як працюють користувальницький інтерфейс операційної системи і OpenGL ES, а також як операційна система відкриває OpenGL доступ до графічного устаткуванню Він також регламентує створення площині і керування контекстом Оскільки GLSurfaceView обробляє все, що стосується EGL, ми можемо спокійно ігнорувати більшість ситуацій, повязаних з EGL

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

Лістинг 71 GLSurfaceViewTestjava: Очищення екрану package combadlogicandroidgamesglbasics:

Ми зберігаємо посилання на екземпляр класу GLSurfaceView як на член цього класу У методі onCreate розгортаємо наш додаток на весь екран, створюємо GLSurfaceView, реалізуємо Renderer і робимо GLSurfaceView переглядачем вмісту Activity

У методах onResumeO і onPause викликаємо суперметоди, а також відповідні методи GLSurfaceView Вони почнуть і перервуть роботу потоку візуалізації GLSurfaceView, який в свою чергу запустить методи зворотного виклику реалізації Renderer у відповідний час

Остання частина коду – це реалізація нашого Renderer Він просто реєструє деяку інформацію з методів onSurfaceCreated і onSurfaceChanged Однак особливої ​​уваги заслуговує метод onDrawFrame

Як ми вже говорили, екземпляр класу GL10 надає доступ до API OpenGL ES 10 в GL10 означає, що він надає всі функції, описані в стандарті OpenGL ES 10 Поки обмежимося цим зауваженням Всі методи цього класу мають відповідну С-функцію, описану в стандарті Кожен метод починається з префікса gl, що є старою доброю традицією OpenGL ES

Перший метод OpenGL ES, який ми викликаємо, – етод1С1еагСоог Ви, напевно, вже здогадуєтеся, що він робить Він встановлює колір, який буде використовуватися, коли ми дамо команду очистити екран Кольори в OpenGL ES майже завжди представляються у форматі RGBA, де кожен компонент має діапазон від 0 до 1 Існують способи описати колір у форматі RGB565, але давайте поки будемо користуватися поданням у вигляді числа з плаваючою крапкою Можна всього одного разу налаштувати колір для заповнення екрану після очищення і OpenGL ES запамятає цей колір Колір, який ми задаємо за допомогою glClearColor, є одним з станів OpenGL ES

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

У OpenGL ES він називається буфером кольору Щоб повідомити OpenGL ES, що ми хочемо очистити даний конкретний буфер, ми вказуємо константу GL10 GL C0L0R BUFFER BIT

OpenGL ES має безліч констант, які визначені як статичні загальнодоступні елементи інтерфейсу GL10 Як і методи, все константи мають префікс GL

Це було наше перше додаток на OpenGL ES З вашого дозволу я не буду розміщувати тут скріншот, так як ви, напевно, знаєте, як усе має виглядати

ПРИМІТКА

Чи не викликай OpenGL ES з іншого потоку Це перша і найважливіша заповідь Справа в тому, що 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>

*

*