Главная » Программирование игр под Android » GLSURFACEVIEW: ОБЛЕГЧАЕТ ЖИЗНЬ С 2008 ГОДА

0

Первым делом нам понадобится определенный тип 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 снова возобновляет работу (а мы вызываем GLSurfaceView.onResume), GLSurfaceView создает экземпляр новой поверхности визуализации OpenGL ES и информирует нас об этом, вызывая наш метод слушателя onSurfaceCreated. Все было бы хорошо, если бы не одна проблема: все состояния OpenGL ES, которые мы устанавливаем, будут утеряны. Это также касается, в частности, текстур и многого другого, что в подобном случае придется перезагружать. Данная проблема также известна под названием потеря контекста. Термин контекст употребляется здесь потому, что OpenGL ES ассоциирует так называемый контекст с каждой поверхностью, которую создает и которая содержит текущее состояние. Когда мы удаляем поверхность, теряется также и контекст. Все не так плохо, как кажется, если при создании игры принять во внимание возможность потери контекста.

ПРИМЕЧАНИЕ

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

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

Листинг 7.1. GLSurfaceViewTest.java: Очистка экрана package com.badlogic.androidgames.glbasics:

Мы сохраняем ссылку на экземпляр класса GLSurfaceView как на член этого класса. В методе onCreate разворачиваем наше приложение на весь экран, создаем GLSurfaceView, реализуем Renderer и делаем GLSurfaceView просмотрщиком содержимого Activity.

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

Последняя часть кода – это реализация нашего Renderer. Он просто регистрирует некоторую информацию из методов onSurfaceCreated и onSurfaceChanged. Однако особого внимания заслуживает метод onDrawFrame.

Как мы уже говорили, экземпляр класса GL10 предоставляет доступ к API OpenGL ES. 10 в GL10 означает, что он предоставляет все функции, описанные в стандарте OpenGL ES 1.0. Пока ограничимся этим замечанием. Все методы этого класса имеют соответствующую С-функцию, описанную в стандарте. Каждый метод начинается с префикса 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», пер. Егор Сидорович, Евгений Зазноба, Издательство «Питер»

По теме:

  • Комментарии