OpenGL ES
OpenGL ES - графический API для 2D- и 3D-рендеринга на мобильных устройствах. В Android его используют для игр, эффектов камеры и собственной отрисовки, когда нужен контроль над геометрией, шейдерами и текстурами.
Основы OpenGL ES
Базовая архитектура
OpenGL ES - API с состоянием: код на CPU настраивает буферы, шейдеры, текстуры и вызовы отрисовки, а графический драйвер и GPU обрабатывают команды. EGL связывает контекст OpenGL ES с поверхностью для отрисовки.
GLSurfaceView управляет потоком рендеринга и настройкой EGL в типичных сценариях. Его Renderer получает вызовы onSurfaceCreated(), onSurfaceChanged() и onDrawFrame(). Для приведённого ниже синтаксиса шейдеров OpenGL ES 2.0 вызови setEGLContextClientVersion(2). SurfaceView, TextureView и прямая работа с EGL дают другие способы интеграции, но требуют больше внимания к жизненному циклу.
Создавай GL-ресурсы после появления контекста, обновляй состояние сцены и отправляй команды отрисовки. При потере EGL-контекста ресурсы, например текстуры и буферы, становятся недействительными; пересоздавай их в onSurfaceCreated(). Обрабатывай паузу и возобновление View и не меняй состояние GL напрямую из произвольного UI-потока.
Вершинный буфер
Объект вершинного буфера (VBO) хранит атрибуты вершин: позиции, текстурные координаты, нормали и цвета - в памяти под управлением GL. Он позволяет не отправлять неизменные массивы заново при каждой отрисовке; API не гарантирует конкретного физического размещения данных.
Позиции вершин треугольника до загрузки:
Для VBO создай объект через glGenBuffers(), привяжи его, загрузи данные через glBufferData() и задай формат атрибутов через glVertexAttribPointer(). Передача прямого FloatBuffer в Android GLES API - ещё один вариант; VBO не обязателен для каждой команды отрисовки.
Вершинный шейдер
Вершинный шейдер выполняется для каждой вершины. Он преобразует позицию, обычно из локальных координат в пространство отсечения, и передаёт атрибуты следующим стадиям. В этом примере для OpenGL ES 2.0 используется матрица модели, вида и проекции (MVP):
attribute vec4 aPosition;
uniform mat4 uMvpMatrix;
void main() {
gl_Position = uMvpMatrix * aPosition;
}
Фрагментный шейдер
Фрагментный шейдер вычисляет цвет образованных фрагментов. После него фрагмент ещё может быть отброшен проверкой глубины или трафарета и не попасть в буфер кадра.
Сложные вычисления, выборка текстур и избыточная отрисовка могут сделать обработку фрагментов дорогой. Перед оптимизацией измеряй производительность на целевых устройствах.
Текстура
Текстура - изображение или данные под управлением GL, которые считывают шейдеры. Её используют для спрайтов, материалов, шрифтов, кадров камеры и постобработки. Размеры и формат влияют на расход памяти и стоимость загрузки. Фильтры уменьшения и увеличения управляют выборкой; mipmap-уровни могут улучшить качество уменьшенной текстуры, но требуют дополнительной памяти и подходящей фильтрации.
Системы координат
При отрисовке позиция обычно проходит через локальное пространство объекта, мировое пространство, пространство камеры и пространство отсечения. После деления на перспективную компоненту нормализованные координаты преобразуются через viewport в координаты окна:
Основные преобразования задают матрицы модели, вида и проекции. Координаты касаний, bitmap и текстур могут иметь разные начала отсчёта; преобразуй их явно.
Конвейер рендеринга
В упрощённом вызове OpenGL ES CPU подготавливает состояние и отправляет команду отрисовки; вершинный шейдер и сборка примитивов обрабатывают геометрию; растеризация создаёт фрагменты; фрагментный шейдер вычисляет значения; проверки фрагментов и смешивание определяют обновление буфера кадра; затем поверхность выводится на экран. Точный порядок некоторых операций с фрагментами может отличаться.
При поиске проблем производительности оценивай количество вызовов отрисовки и вершин, стоимость фрагментов, избыточную отрисовку, пропускную способность текстур и синхронизацию CPU/GPU. Для локальных эффектов интерфейса без собственной геометрии смотри AGSL и RuntimeShader.