OpenGL ES: what it is, architecture and application

Author: IT Sectr Published: 2026-05-03 Reading time: 11 min

OpenGL ES is a graphics API with an open specification designed for embedded and mobile systems. It provides hardware-accelerated 2D and 3D graphics rendering through a programmable shader pipeline. According to Khronos Group, 2025, OpenGL ES remains the most widespread graphics API on mobile devices, supporting over 10 billion installations worldwide. The library is used in games, mapping services, AR applications and interfaces on Android and iOS.

Key takeaways

  • OpenGL ES is a cross-platform graphics API for mobile and embedded devices, the de facto standard in the industry
  • Programmable pipeline includes vertex, fragment and compute shaders written in GLSL
  • Versions OpenGL ES 2.0, 3.0 and 3.2 define the set of available features — each subsequent version adds shader stages and performance improvements
  • EGL is an intermediate layer that connects OpenGL ES with the window system of a specific platform (Android, iOS, Windows)
  • Metal and Vulkan are lower-level alternatives that provide less overhead but require more code for initialization

What is OpenGL ES?

OpenGL ES (Open Graphics Library for Embedded Systems) is a subset of the desktop OpenGL API adapted for mobile devices, game consoles and embedded systems. The specification is developed by the Khronos Group consortium and is available free of charge to all manufacturers. Unlike desktop OpenGL, OpenGL ES removes legacy fixed-function pipeline features, leaving only the programmable shader pipeline — this reduces power consumption and simplifies drivers.

The main application area of OpenGL ES is real-time graphics rendering. The API is used in mobile games (Unity, Unreal Engine), navigation applications, AR solutions based on ARCore and ARKit, as well as in Android and iOS system interfaces. According to StatCounter, 2026, the share of devices with OpenGL ES 3.0+ support exceeds 92% among active smartphones.

The key advantage of OpenGL ES is cross-platform compatibility. The same application written with OpenGL ES can run on Android, iOS, Linux and Windows with minimal changes. This makes the API an optimal choice for projects targeting multiple platforms without rewriting the graphics engine.

Fixed vs programmable pipeline

Early versions of OpenGL (before 2.0) used a fixed pipeline — a set of predefined vertex and pixel processing stages. The developer could only configure parameters: light source positions, material properties, transformation matrices. Programmable pipeline, introduced in OpenGL ES 2.0, replaced fixed stages with shaders — small programs executed on the GPU. This gave developers full control over geometry rendering.

The transition to a programmable pipeline was a revolution for mobile graphics. Developers gained the ability to implement complex effects: PBR (Physically Based Rendering), dynamic shadows, post-processing and HDR. The fixed pipeline required less code but did not allow creating unique visual styles. Modern mobile games fully operate on the programmable pipeline.

OpenGL ES architecture: rendering pipeline

Graphics pipeline of OpenGL ES consists of several sequential stages, each transforming input data along the path from vertices to pixels on the screen. Understanding the pipeline architecture is critical for optimizing rendering performance on mobile devices with limited energy and thermal budgets.

Pipeline stagePurposeProgrammable
Vertex ShaderVertex transformation, applying model-view-projection matricesYes — GLSL
TessellationGeometry subdivision (ES 3.2 only)Yes — GLSL
Geometry ShaderGenerating new geometry from primitivesYes — GLSL
RasterizationConverting primitives into fragments (pixels)No — fixed
Fragment ShaderCalculating the color of each fragment, texturing, lightingYes — GLSL
Per-Fragment OperationsDepth test, stencil test, blending, scissor testParameter configuration

The first stage — vertex shader — processes each vertex independently. At this stage transformations are applied: translation from model local space to world space, then to camera space and finally to clip space. Transformations are set via MVP (Model-View-Projection) uniform matrices, which are updated every frame when the camera or objects move.

After primitive assembly (points, lines, triangles), rasterization is performed — the process of determining which screen pixels each primitive covers. Rasterizer generates fragments — potential pixels with interpolated attributes (color, normals, UV coordinates). The number of fragments directly depends on the screen resolution and the projection area of the primitive.

Fragment shader runs for each generated fragment. It calculates the final pixel color taking into account textures, light sources and materials. The fragment shader output goes through a series of per-fragment tests: depth test determines if the fragment is visible; stencil test restricts rendering by mask; blending mixes the fragment color with the color already written in the framebuffer.

OpenGL ES context states

OpenGL ES operates as a state machine: all settings — current shader, bound textures, enabled tests — are stored in the global state of the context. Changing state via glEnable, glBindTexture or glUseProgram affects all subsequent draw commands. Each state switch incurs driver overhead, so grouping draw calls by state is the primary optimization technique.

OpenGL ES versions and their capabilities

OpenGL ES 1.0 and 1.1 (released in 2003–2004) were based on a fixed pipeline. They supported transformations, texturing, lighting and blending, but did not allow programming shaders. The API was used in early mobile phones and devices based on Symbian and Windows Mobile. Today these versions are considered obsolete — modern devices do not support them.

OpenGL ES 2.0 (2007) introduced a programmable pipeline with vertex and fragment shaders in GLSL ES. This version became the standard for Android 2.2+ and iOS 5+ and is still supported by the vast majority of devices. OpenGL ES 2.0 is the minimum version required for Unity, Unreal Engine and Cocos2d-x on mobile platforms.

OpenGL ES 3.0 (2012) added several critical capabilities: multiple render targets (MRT), transform feedback, instancing, arbitrary format textures via ETC2/EAC. Rendering performance increased by 30–50% compared to version 2.0 by reducing the number of draw calls. OpenGL ES 3.1 (2014) introduced compute shaders and atomic buffer operations — this made it possible to execute not only graphics but also compute tasks on the GPU (post-processing, cloth simulation, physics calculations).

OpenGL ES 3.2 (2015) — the latest version of the specification — added tessellation and geometry shaders, as well as an extended set of float textures and blend modes. Despite the release of the more modern Vulkan in 2016, OpenGL ES 3.2 remains a relevant API due to the huge existing codebase and ease of porting applications between platforms.

VersionYearKey capabilitiesCompatibility (2026)
1.x2003Fixed pipeline, lighting, texturesObsolete
2.02007Programmable pipeline, GLSL ES99% devices
3.02012MRT, instancing, ETC2, transform feedback92% devices
3.12014Compute shaders, atomic buffers80% devices
3.22015Tessellation, geometry shaders65% devices

Shaders in OpenGL ES: GLSL and programmable pipeline

GLSL ES (OpenGL Shading Language for Embedded Systems) is a shader programming language based on C syntax with additional types for working with vectors and matrices. Each shader is a program compiled into GPU machine code at application initialization. Unlike CPU code, shaders execute massively in parallel: thousands of vertices or fragments are processed simultaneously.

Vertex shaders

Vertex shader processes each vertex of the mesh. Its main task is to compute the final vertex position in clip space by multiplying the input position by the MVP matrix. Additionally, the vertex shader can compute normals, UV coordinates, colors and pass them to the fragment shader via varying variables. Each vertex shader invocation works independently, allowing the GPU to process millions of vertices per frame.

glsl
// Simple vertex shader for 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;
}

Fragment shaders

Fragment shader determines the color of each pixel on the screen. It receives interpolated varying values from the vertex shader, samples texels from bound textures and applies lighting. For correct lighting, the Phong or Blinn-Phong model is used with diffuse, specular and ambient component calculations. Each fragment shader invocation corresponds to one pixel, so the total number of invocations equals the projection area of the object on screen.

glsl
// Simple fragment shader with texture and lighting
#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);
}

In the example above, the fragment shader samples a texel from a 2D texture by UV coordinates, computes diffuse lighting as the dot product of the normal and light direction, and multiplies the texel color by the lighting intensity. Mediump is the recommended precision for fragment shaders on mobile GPUs: it provides sufficient quality at minimal power consumption.

How to start working with OpenGL ES in mobile projects

To work with OpenGL ES on Android, you need to create an EGL context — a surface onto which graphics will be rendered. On iOS, the EAGL layer (similar to EGL) provided by the GLKit framework is used. In both cases, the initialization process includes creating a window surface, configuring context attributes and binding to the current rendering thread.

kotlin
// OpenGL ES 3.0 initialization on 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)
    }
}

After creating the context, the developer needs to set up buffers: the vertex buffer (VBO) contains vertex coordinates, normals and UV; the index buffer (EBO) defines the vertex traversal order for forming triangles. VAO (Vertex Array Object) combines all attribute configurations into one object, reducing the number of API calls when switching meshes.

EGL context setup

EGL (Native Platform Graphics Interface) is an intermediate layer between OpenGL ES and the window system. On Android, EGL manages the creation of the rendering surface, framebuffer configuration selection (color depth, stencil, MSAA) and vsync synchronization. A typical configuration requests RGBA8888 with a 24-bit depth buffer and 8-bit stencil buffer. On iOS, the role of EGL is performed by EAGL in conjunction with CAEAGLLayer.

Performance optimization for OpenGL ES on mobile devices includes several key practices. Use instancing (glDrawArraysInstanced) for rendering many identical objects — this reduces the number of draw calls. Apply texture pools and avoid texture switching between draw calls. Sort objects by shader, then by texture, then by mesh — such order minimizes context state switches.

OpenGL ES vs Metal vs Vulkan

Metal is a low-level graphics API from Apple, available on iOS and macOS starting from the A7 chip. Metal provides direct GPU access with minimal driver overhead, but works only on Apple devices. According to WWDC 2024, Metal delivers up to 40% higher performance compared to OpenGL ES on the same hardware by reducing runtime state checks.

Vulkan is a cross-platform successor to OpenGL ES, developed by Khronos Group. Vulkan uses explicit resource management: the developer allocates memory pools, creates command buffers and synchronizes GPU access. This gives maximum control over performance, but Vulkan initialization code is 3–4 times more verbose than for OpenGL ES. Vulkan is recommended for AAA games and demanding graphics applications on Android 7+.

The choice between OpenGL ES, Metal and Vulkan depends on target platforms and performance requirements. OpenGL ES remains the best choice for cross-platform projects where development speed matters. Metal is preferred for the iOS/macOS ecosystem with maximum performance. Vulkan is the choice for projects where every millisecond per frame matters and the development budget allows investing in low-level optimization.

CharacteristicOpenGL ESMetalVulkan
PlatformsAndroid, iOS, Windows, LinuxiOS, macOS onlyAndroid, Windows, Linux (no iOS)
API levelHigh (state machine)MediumLow (explicit)
Init code50–100 lines100–200 lines300–500 lines
Memory controlAutomaticSemi-automaticFully manual
PerformanceBaseline+20–40% vs ES+30–60% vs ES

Frequently asked questions

What is the difference between OpenGL and OpenGL ES?

OpenGL ES is a subset of desktop OpenGL from which legacy fixed-pipeline functions have been removed. OpenGL ES has a smaller specification volume, a simplified precision profile and is optimized for low power consumption of mobile devices.

Which version of OpenGL ES is supported on Android?

Android supports OpenGL ES 2.0 on all devices, 3.0 on Android 4.3+, 3.1 on Android 5.0+, 3.2 on selected devices with Android 7.0+. You can check the current support level via EGL_CONFIG_CAVEAT.

What language is used to write OpenGL ES shaders?

GLSL ES (OpenGL Shading Language for Embedded Systems) is a C-like language with vec2/vec3/vec4/mat4 types and built-in functions texture, normalize, dot. For ES 3.0+, the #version 300 es directive is used.

Should I learn OpenGL ES in 2026?

Yes, OpenGL ES remains relevant for cross-platform projects where development speed and broad device support are priorities. For the iOS ecosystem, better to learn Metal; for new projects with maximum performance, use Vulkan.

How to check the OpenGL ES version on a device?

On Android, call GLES30.glGetString(GLES30.GL_VERSION) after creating the context. The string contains the version number and vendor information. On iOS, use [EAGLContext currentContext] and the API property.

Summary

  • OpenGL ES is the primary graphics API for mobile devices, supported on over 10 billion installations
  • Programmable pipeline with vertex and fragment shaders in GLSL ES provides full control over rendering
  • Versions 2.0, 3.0, 3.1, 3.2 differ in the set of shader stages and available functionality
  • EGL connects OpenGL ES to the window system, managing the rendering surface and synchronization
  • Metal and Vulkan are higher performance alternatives but require more code and are platform-specific
  • Optimization includes instancing, sorting draw calls by state and texture pools
  • For cross-platform projects OpenGL ES remains the optimal choice due to its simplicity and mature ecosystem

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also