OpenGL ES — это графический API с открытой спецификацией, предназначенный для встраиваемых и мобильных систем. Он предоставляет аппаратно-ускоренный рендеринг 2D и 3D графики через программируемый конвейер шейдеров. По данным Khronos Group, 2025, OpenGL ES остаётся самым распространённым графическим API на мобильных устройствах, поддерживая более 10 миллиардов установок по всему миру. Библиотека используется в играх, картографических сервисах, AR-приложениях и интерфейсах на Android и iOS.
Главное
OpenGL ES (Open Graphics Library for Embedded Systems) — это подмножество настольного OpenGL API, адаптированное для мобильных устройств, игровых консолей и встраиваемых систем. Спецификация разрабатывается консорциумом Khronos Group и доступна бесплатно для всех производителей. В отличие от настольного OpenGL, OpenGL ES удаляет устаревшие функции фиксированного конвейера, оставляя только программируемый конвейер шейдеров — это снижает энергопотребление и упрощает драйверы.
Основная сфера применения OpenGL ES — рендеринг графики в реальном времени. API используется в мобильных играх (Unity, Unreal Engine), навигационных приложениях, AR-решениях на базе ARCore и ARKit, а также в системных интерфейсах Android и iOS. По данным StatCounter, 2026, доля устройств с поддержкой OpenGL ES 3.0+ превышает 92% среди активных смартфонов.
Ключевое преимущество OpenGL ES — кроссплатформенность. Одно и то же приложение, написанное на OpenGL ES, может работать на Android, iOS, Linux и Windows с минимальными изменениями. Это делает API оптимальным выбором для проектов, ориентированных на множество платформ без переписывания графического движка.
Ранние версии OpenGL (до 2.0) использовали фиксированный конвейер — набор предопределённых этапов обработки вершин и пикселей. Разработчик мог лишь настроить параметры: положение источников света, свойства материалов, матрицы трансформации. Программируемый конвейер, введённый в OpenGL ES 2.0, заменил фиксированные стадии шейдерами — небольшими программами, выполняемыми на GPU. Это дало разработчикам полный контроль над отображением геометрии.
Переход на программируемый конвейер стал революцией для мобильной графики. Разработчики получили возможность реализовывать сложные эффекты: PBR (Physically Based Rendering), динамические тени, постобработку и HDR. Фиксированный конвейер требовал меньше кода, но не позволял создавать уникальные визуальные стили. Современные мобильные игры полностью работают на программируемом конвейере.
Графический конвейер OpenGL ES состоит из нескольких последовательных стадий, каждая из которых преобразует входные данные на пути от вершин к пикселям на экране. Понимание архитектуры конвейера критически важно для оптимизации производительности рендеринга на мобильных устройствах с ограниченным бюджетом энергии и тепловыделения.
| Стадия конвейера | Назначение | Программируется |
|---|---|---|
| Vertex Shader | Трансформация вершин, применение матриц модели-вида-проекции | Да — GLSL |
| Tessellation | Подразделение геометрии (только ES 3.2) | Да — GLSL |
| Geometry Shader | Генерация новой геометрии из примитивов | Да — GLSL |
| Rasterization | Преобразование примитивов во фрагменты (пиксели) | Нет — фиксировано |
| Fragment Shader | Расчёт цвета каждого фрагмента, текстурирование, освещение | Да — GLSL |
| Per-Fragment Operations | Depth test, stencil test, blending, scissor test | Настройка параметров |
Первая стадия — вершинный шейдер — обрабатывает каждую вершину независимо. На этом этапе применяются трансформации: перевод из локального пространства модели в мировое пространство, затем в пространство камеры и, наконец, в усечённое пространство (clip space). Трансформации задаются через uniform-матрицы MVP (Model-View-Projection), которые обновляются каждый кадр при движении камеры или объектов.
После сборки примитивов (точек, линий, треугольников) выполняется растеризация — процесс определения, какие пиксели экрана покрывает каждый примитив. Растеризатор генерирует фрагменты — потенциальные пиксели с интерполированными атрибутами (цветом, нормалями, UV-координатами). Количество фрагментов напрямую зависит от разрешения экрана и площади проекции примитива.
Фрагментный шейдер выполняется для каждого сгенерированного фрагмента. Он рассчитывает итоговый цвет пикселя с учётом текстур, источников света и материалов. На выходе фрагментного шейдера проходит серия per-fragment тестов: depth test определяет, виден ли фрагмент; stencil test ограничивает рендеринг по маске; blending смешивает цвет фрагмента с цветом, уже записанным в буфере кадра.
OpenGL ES работает как конечный автомат (state machine): все настройки — текущий шейдер, привязанные текстуры, включённые тесты — хранятся в глобальном состоянии контекста. Изменение состояния через glEnable, glBindTexture или glUseProgram влияет на все последующие команды отрисовки. Каждое переключение состояния вызывает накладные расходы в драйвере, поэтому группировка draw-вызовов по состоянию — основной приём оптимизации.
OpenGL ES 1.0 и 1.1 (выпущены в 2003–2004 годах) базировались на фиксированном конвейере. Они поддерживали трансформации, текстурирование, освещение и blending, но не позволяли программировать шейдеры. API использовался в ранних мобильных телефонах и устройствах на базе Symbian и Windows Mobile. Сегодня эти версии считаются устаревшими — современные устройства их не поддерживают.
OpenGL ES 2.0 (2007) ввёл программируемый конвейер с вершинными и фрагментными шейдерами на языке GLSL ES. Эта версия стала стандартом для Android 2.2+ и iOS 5+ и поддерживается подавляющим большинством устройств до сих пор. OpenGL ES 2.0 — минимальная версия, необходимая для работы Unity, Unreal Engine и Cocos2d-x на мобильных платформах.
OpenGL ES 3.0 (2012) добавил несколько критических возможностей: множественные render targets (MRT), трансформ-фидбек, instancing, текстуры произвольного формата через ETC2/EAC. Производительность рендеринга выросла на 30–50% по сравнению с версией 2.0 за счёт снижения количества draw-вызовов. OpenGL ES 3.1 (2014) ввёл вычислительные шейдеры (compute shaders) и атомарные операции с буферами — это позволило выполнять на GPU не только графические, но и вычислительные задачи (постобработка, симуляция тканей, расчёт физики).
OpenGL ES 3.2 (2015) — последняя версия спецификации — добавила тесселяционные и геометрические шейдеры, а также расширенный набор float-текстур и blend modes. Несмотря на выход более современного Vulkan в 2016 году, OpenGL ES 3.2 остаётся актуальным API благодаря огромной базе существующего кода и простоте портирования приложений между платформами.
| Версия | Год | Ключевые возможности | Совместимость (2026) |
|---|---|---|---|
| 1.x | 2003 | Фиксированный конвейер, освещение, текстуры | Устаревшая |
| 2.0 | 2007 | Программируемый конвейер, GLSL ES | 99% устройств |
| 3.0 | 2012 | MRT, instancing, ETC2, трансформ-фидбек | 92% устройств |
| 3.1 | 2014 | Вычислительные шейдеры, атомарные буферы | 80% устройств |
| 3.2 | 2015 | Тесселяция, геометрические шейдеры | 65% устройств |
GLSL ES (OpenGL Shading Language for Embedded Systems) — язык программирования шейдеров, основанный на синтаксисе C с дополнительными типами для работы с векторами и матрицами. Каждый шейдер — это программа, компилируемая в машинный код GPU на этапе инициализации приложения. В отличие от CPU-кода, шейдеры выполняются массово-параллельно: тысячи вершин или фрагментов обрабатываются одновременно.
Вершинный шейдер обрабатывает каждую вершину сетки. Его основная задача — вычислить итоговую позицию вершины в clip space путём умножения входящей позиции на матрицу MVP. Кроме того, вершинный шейдер может рассчитывать нормали, UV-координаты, цвета и передавать их во фрагментный шейдер через varying-переменные. Каждый вызов вершинного шейдера работает независимо, что позволяет GPU обрабатывать миллионы вершин в кадр.
// Простой вершинный шейдер для OpenGL ES 3.0
#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_normal;
layout(location = 2) in vec2 a_texCoord;
uniform mat4 u_mvpMatrix;
out vec3 v_normal;
out vec2 v_texCoord;
void main() {
gl_Position = u_mvpMatrix * a_position;
v_normal = mat3(u_mvpMatrix) * a_normal;
v_texCoord = a_texCoord;
}
Фрагментный шейдер определяет цвет каждого пикселя на экране. Он принимает интерполированные varying-значения из вершинного шейдера, выбирает тексели из привязанных текстур и применяет освещение. Для корректного освещения используется модель Фонга или Блинна-Фонга с расчётом diffuse, specular и ambient компонент. Каждый вызов фрагментного шейдера соответствует одному пикселю, поэтому общее количество вызовов равно площади проекции объекта на экране.
// Простой фрагментный шейдер с текстурой и освещением
#version 300 es
precision mediump float;
in vec3 v_normal;
in vec2 v_texCoord;
uniform sampler2D u_texture;
uniform vec3 u_lightDir;
out vec4 fragColor;
void main() {
vec4 texel = texture(u_texture, v_texCoord);
vec3 normal = normalize(v_normal);
float diffuse = max(dot(normal, u_lightDir), 0.0);
fragColor = vec4(texel.rgb * diffuse, texel.a);
}
В приведённом примере фрагментный шейдер выбирает тексель из 2D-текстуры по UV-координатам, вычисляет diffuse-освещение как скалярное произведение нормали и направления света, и умножает цвет текселя на интенсивность освещения. Mediump — рекомендуемая точность для фрагментных шейдеров на мобильных GPU: она даёт достаточное качество при минимальном энергопотреблении.
Для работы с OpenGL ES на Android требуется создать EGL-контекст — поверхность, на которую будет выводиться графика. На iOS используется EGL-подобный слой EAGL, предоставляемый фреймворком GLKit. В обоих случаях процесс инициализации включает создание оконной поверхности, конфигурацию атрибутов контекста и привязку к текущему потоку рендеринга.
// Инициализация OpenGL ES 3.0 на Android
class MyGLRenderer : GLSurfaceView.Renderer {
private val vertexShaderCode = "#version 300 es\n..."
private val fragmentShaderCode = "#version 300 es\n..."
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
GLES30.glClearColor(0.1f, 0.1f, 0.2f, 1.0f)
GLES30.glEnable(GLES30.GL_DEPTH_TEST)
}
override fun onDrawFrame(gl: GL10?) {
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT or GLES30.GL_DEPTH_BUFFER_BIT)
// bind VBO, set uniforms, draw elements
}
override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
GLES30.glViewport(0, 0, width, height)
}
}
После создания контекста разработчику необходимо настроить буферы: вершинный буфер (VBO) содержит координаты вершин, нормали и UV; индексный буфер (EBO) определяет порядок обхода вершин для формирования треугольников. VAO (Vertex Array Object) объединяет конфигурацию всех атрибутов в один объект, сокращая количество вызовов API при смене мешей.
EGL (Native Platform Graphics Interface) — это промежуточный слой между OpenGL ES и оконной системой. На Android EGL управляет созданием поверхности отрисовки, выбором конфигурации framebuffer (глубина цвета, stencil, MSAA) и синхронизацией с vsync. Типичная конфигурация запрашивает RGBA8888 с 24-битным depth-буфером и 8-битным stencil-буфером. На iOS роль EGL выполняет EAGL в связке с CAEAGLLayer.
Оптимизация производительности OpenGL ES на мобильных устройствах включает несколько ключевых практик. Используйте инстансинг (glDrawArraysInstanced) для рендеринга множества одинаковых объектов — это сокращает количество draw-вызовов. Применяйте пулы текстур и избегайте переключения текстур между draw-вызовами. Сортируйте объекты по шейдеру, затем по текстуре, затем по мешу — такой порядок минимизирует переключения состояния контекста.
Metal — низкоуровневый графический API от Apple, доступный на iOS и macOS начиная с A7-чипа. Metal предоставляет прямой доступ к GPU с минимальными накладными расходами драйвера, но работает только на устройствах Apple. По данным WWDC 2024, Metal обеспечивает до 40% более высокую производительность по сравнению с OpenGL ES на том же оборудовании за счёт уменьшения количества проверок состояния в рантайме.
Vulkan — кроссплатформенный преемник OpenGL ES, разработанный Khronos Group. Vulkan использует явное управление ресурсами: разработчик сам выделяет пулы памяти, создаёт командные буферы и синхронизирует доступ к GPU. Это даёт максимальный контроль над производительностью, но код инициализации Vulkan в 3–4 раза объёмнее, чем для OpenGL ES. Vulkan рекомендуется для AAA-игр и приложений с требовательной графикой на Android 7+.
Выбор между OpenGL ES, Metal и Vulkan зависит от целевых платформ и требований к производительности. OpenGL ES остаётся лучшим выбором для кроссплатформенных проектов, где важна скорость разработки. Metal предпочтителен для iOS/macOS-экосистемы с максимальной производительностью. Vulkan — выбор для проектов, где критичен каждый миллисекундный кадр, а бюджет разработки позволяет инвестировать в низкоуровневую оптимизацию.
| Характеристика | OpenGL ES | Metal | Vulkan |
|---|---|---|---|
| Платформы | Android, iOS, Windows, Linux | iOS, macOS только | Android, Windows, Linux (iOS нет) |
| Уровень API | Высокий (state machine) | Средний | Низкий (explicit) |
| Код инициализации | 50–100 строк | 100–200 строк | 300–500 строк |
| Контроль памяти | Автоматический | Полуавтоматический | Полностью ручной |
| Производительность | Базовая | +20–40% vs ES | +30–60% vs ES |
Часто задаваемые вопросы
OpenGL ES — это подмножество настольного OpenGL, из которого удалены устаревшие функции фиксированного конвейера. OpenGL ES имеет меньший объём спецификации, упрощённый профиль точности и оптимизирован для низкого энергопотребления мобильных устройств.
Android поддерживает OpenGL ES 2.0 на всех устройствах, 3.0 — на Android 4.3+, 3.1 — на Android 5.0+, 3.2 — на избранных устройствах с Android 7.0+. Актуальный уровень поддержки можно проверить через EGL_CONFIG_CAVEAT.
GLSL ES (OpenGL Shading Language for Embedded Systems) — C-подобный язык с типами vec2/vec3/vec4/mat4 и встроенными функциями texture, normalize, dot. Для ES 3.0+ используется директива #version 300 es.
Да, OpenGL ES остаётся актуальным для кроссплатформенных проектов, где приоритет — скорость разработки и поддержка широкого спектра устройств. Для iOS-экосистемы лучше изучать Metal, для новых проектов с максимальной производительностью — Vulkan.
На Android вызовите GLES30.glGetString(GLES30.GL_VERSION) после создания контекста. Строка содержит номер версии и информацию о вендоре. На iOS используйте [EAGLContext currentContext] и свойство API.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.