OpenGL ES è un'API grafica con specifica aperta progettata per sistemi embedded e mobili. Fornisce rendering 2D e 3D accelerato via hardware attraverso un pipeline programmabile di shader. Secondo Khronos Group, 2025, OpenGL ES rimane l'API grafica più diffusa sui dispositivi mobili, con oltre 10 miliardi di installazioni in tutto il mondo. La libreria viene utilizzata in giochi, servizi di mappatura, applicazioni AR e interfacce su Android e iOS.
Punti chiave
OpenGL ES (Open Graphics Library for Embedded Systems) è un sottoinsieme dell'API OpenGL desktop adattato per dispositivi mobili, console di gioco e sistemi embedded. La specifica è sviluppata dal consorzio Khronos Group ed è disponibile gratuitamente per tutti i produttori. A differenza di OpenGL desktop, OpenGL ES rimuove le funzionalità legacy del pipeline fisso, lasciando solo il pipeline programmabile degli shader — ciò riduce il consumo energetico e semplifica i driver.
L'area di applicazione principale di OpenGL ES è il rendering grafico in tempo reale. L'API viene utilizzata in giochi mobili (Unity, Unreal Engine), applicazioni di navigazione, soluzioni AR basate su ARCore e ARKit, nonché nelle interfacce di sistema Android e iOS. Secondo StatCounter, 2026, la percentuale di dispositivi con supporto OpenGL ES 3.0+ supera il 92% tra gli smartphone attivi.
Il vantaggio chiave di OpenGL ES è la compatibilità multipiattaforma. La stessa applicazione scritta con OpenGL ES può funzionare su Android, iOS, Linux e Windows con modifiche minime. Ciò rende l'API la scelta ottimale per progetti che mirano a più piattaforme senza riscrivere il motore grafico.
Le prime versioni di OpenGL (prima della 2.0) utilizzavano un pipeline fisso — un insieme di fasi predefinite di elaborazione di vertici e pixel. Lo sviluppatore poteva solo configurare parametri: posizioni delle sorgenti luminose, proprietà dei materiali, matrici di trasformazione. Pipeline programmabile, introdotto in OpenGL ES 2.0, ha sostituito le fasi fisse con shader — piccoli programmi eseguiti sulla GPU. Questo ha dato agli sviluppatori il controllo totale sul rendering della geometria.
La transizione al pipeline programmabile è stata una rivoluzione per la grafica mobile. Gli sviluppatori hanno ottenuto la capacità di implementare effetti complessi: PBR (Physically Based Rendering), ombre dinamiche, post-elaborazione e HDR. Il pipeline fisso richiedeva meno codice ma non permetteva di creare stili visivi unici. I giochi mobili moderni operano interamente sul pipeline programmabile.
Pipeline grafico di OpenGL ES consiste in diverse fasi sequenziali, ciascuna delle quali trasforma i dati di input nel percorso dai vertici ai pixel sullo schermo. Comprendere l'architettura del pipeline è fondamentale per ottimizzare le prestazioni di rendering sui dispositivi mobili con budget energetico e termico limitati.
| Fase del pipeline | Scopo | Programmabile |
|---|---|---|
| Vertex Shader | Trasformazione dei vertici, applicazione delle matrici modello-vista-proiezione | Sì — GLSL |
| Tassellazione | Sudddivisione della geometria (solo ES 3.2) | Sì — GLSL |
| Geometry Shader | Generazione di nuova geometria da primitive | Sì — GLSL |
| Rasterizzazione | Conversione di primitive in frammenti (pixel) | No — fisso |
| Fragment Shader | Calcolo del colore di ogni frammento, texturing, illuminazione | Sì — GLSL |
| Operazioni per frammento | Depth test, stencil test, blending, scissor test | Configurazione parametri |
La prima fase — vertex shader — elabora ogni vertice indipendentemente. In questa fase vengono applicate le trasformazioni: passaggio dallo spazio locale del modello allo spazio mondo, poi allo spazio camera e infine allo spazio di ritaglio (clip space). Trasformazioni sono impostate tramite matrici uniform MVP (Model-View-Projection), che vengono aggiornate ogni frame quando la telecamera o gli oggetti si muovono.
Dopo l'assemblaggio delle primitive (punti, linee, triangoli), viene eseguita la rasterizzazione — il processo di determinazione di quali pixel dello schermo ogni primitiva copre. Rasterizzatore genera frammenti — pixel potenziali con attributi interpolati (colore, normali, coordinate UV). Il numero di frammenti dipende direttamente dalla risoluzione dello schermo e dall'area di proiezione della primitiva.
Il fragment shader viene eseguito per ogni frammento generato. Calcola il colore finale del pixel tenendo conto di texture, sorgenti luminose e materiali. L'uscita del fragment shader passa attraverso una serie di test per frammento: depth test determina se il frammento è visibile; stencil test limita il rendering per maschera; blending mescola il colore del frammento con il colore già scritto nel framebuffer.
OpenGL ES funziona come una macchina a stati: tutte le impostazioni — shader corrente, texture collegate, test attivati — sono memorizzate nello stato globale del contesto. Cambiare lo stato tramite glEnable, glBindTexture o glUseProgram influisce su tutti i comandi di disegno successivi. Ogni cambio di stato causa overhead nel driver, quindi raggruppare le chiamate di draw per stato è la principale tecnica di ottimizzazione.
OpenGL ES 1.0 e 1.1 (rilasciate nel 2003–2004) erano basate su pipeline fisso. Supportavano trasformazioni, texturing, illuminazione e blending, ma non permettevano di programmare shader. L'API era utilizzata nei primi telefoni cellulari e dispositivi basati su Symbian e Windows Mobile. Oggi queste versioni sono considerate obsolete — i dispositivi moderni non le supportano.
OpenGL ES 2.0 (2007) ha introdotto un pipeline programmabile con shader di vertice e frammento in GLSL ES. Questa versione è diventata lo standard per Android 2.2+ e iOS 5+ ed è ancora supportata dalla stragrande maggioranza dei dispositivi. OpenGL ES 2.0 è la versione minima richiesta per Unity, Unreal Engine e Cocos2d-x sulle piattaforme mobili.
OpenGL ES 3.0 (2012) ha aggiunto diverse capacità critiche: multiple render target (MRT), transform feedback, instancing, texture di formato arbitrario tramite ETC2/EAC. Le prestazioni di rendering sono aumentate del 30–50% rispetto alla versione 2.0 riducendo il numero di draw call. OpenGL ES 3.1 (2014) ha introdotto shader di compute e operazioni atomiche con buffer — ciò ha permesso di eseguire sulla GPU non solo attività grafiche ma anche di calcolo (post-elaborazione, simulazione di tessuti, calcoli fisici).
OpenGL ES 3.2 (2015) — l'ultima versione della specifica — ha aggiunto shader di tassellazione e geometria, oltre a un insieme esteso di texture float e modalità di blending. Nonostante il rilascio del più moderno Vulkan nel 2016, OpenGL ES 3.2 rimane un'API rilevante grazie all'enorme base di codice esistente e alla facilità di portabilità tra piattaforme.
| Versione | Anno | Capacità principali | Compatibilità (2026) |
|---|---|---|---|
| 1.x | 2003 | Pipeline fisso, illuminazione, texture | Obsoleta |
| 2.0 | 2007 | Pipeline programmabile, GLSL ES | 99% dispositivi |
| 3.0 | 2012 | MRT, instancing, ETC2, transform feedback | 92% dispositivi |
| 3.1 | 2014 | Shader di compute, buffer atomici | 80% dispositivi |
| 3.2 | 2015 | Tassellazione, shader di geometria | 65% dispositivi |
GLSL ES (OpenGL Shading Language for Embedded Systems) è un linguaggio di programmazione di shader basato sulla sintassi C con tipi aggiuntivi per lavorare con vettori e matrici. Ogni shader è un programma compilato in codice macchina GPU nella fase di inizializzazione dell'applicazione. A differenza del codice CPU, gli shader vengono eseguiti massivamente in parallelo: migliaia di vertici o frammenti vengono elaborati simultaneamente.
Vertex shader elabora ogni vertice della mesh. Il suo compito principale è calcolare la posizione finale del vertice nel clip space moltiplicando la posizione di ingresso per la matrice MVP. Inoltre, il vertex shader può calcolare normali, coordinate UV, colori e passarli al fragment shader tramite variabili varying. Ogni invocazione del vertex shader funziona indipendentemente, consentendo alla GPU di elaborare milioni di vertici per frame.
// 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 shader determina il colore di ogni pixel sullo schermo. Riceve valori varying interpolati dal vertex shader, campiona texel dalle texture collegate e applica l'illuminazione. Per un'illuminazione corretta viene utilizzato il modello Phong o Blinn-Phong con calcolo delle componenti diffuse, specular e ambient. Ogni invocazione del fragment shader corrisponde a un pixel, quindi il numero totale di invocazioni è uguale all'area di proiezione dell'oggetto sullo schermo.
// 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);
}
Nell'esempio sopra, il fragment shader campiona un texel da una texture 2D per coordinate UV, calcola l'illuminazione diffusa come prodotto scalare della normale e della direzione della luce, e moltiplica il colore del texel per l'intensità dell'illuminazione. Mediump è la precisione raccomandata per i fragment shader su GPU mobili: fornisce qualità sufficiente con consumo energetico minimo.
Per lavorare con OpenGL ES su Android, è necessario creare un contesto EGL — una superficie su cui verrà resa la grafica. Su iOS viene utilizzato il layer EAGL (simile a EGL) fornito dal framework GLKit. In entrambi i casi, il processo di inizializzazione include la creazione di una superficie finestra, la configurazione degli attributi del contesto e il collegamento al thread di rendering corrente.
// 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)
}
}
Dopo aver creato il contesto, lo sviluppatore deve configurare i buffer: il buffer dei vertici (VBO) contiene coordinate dei vertici, normali e UV; il buffer degli indici (EBO) definisce l'ordine di attraversamento dei vertici per formare triangoli. VAO (Vertex Array Object) combina la configurazione di tutti gli attributi in un unico oggetto, riducendo il numero di chiamate API quando si cambia mesh.
EGL (Native Platform Graphics Interface) è un livello intermedio tra OpenGL ES e il sistema di finestre. Su Android, EGL gestisce la creazione della superficie di rendering, la selezione della configurazione del framebuffer (profondità colore, stencil, MSAA) e la sincronizzazione con vsync. Una configurazione tipica richiede RGBA8888 con buffer di profondità a 24 bit e buffer stencil a 8 bit. Su iOS, il ruolo di EGL è svolto da EAGL in combinazione con CAEAGLLayer.
L'ottimizzazione delle prestazioni di OpenGL ES sui dispositivi mobili include diverse pratiche chiave. Utilizzare instancing (glDrawArraysInstanced) per rendere molti oggetti identici — questo riduce il numero di draw call. Applicare pool di texture ed evitare il cambio di texture tra draw call. Ordinare gli oggetti per shader, poi per texture, poi per mesh — questo ordine minimizza i cambi di stato del contesto.
Metal è un'API grafica di basso livello di Apple, disponibile su iOS e macOS a partire dal chip A7. Metal fornisce accesso diretto alla GPU con overhead minimo del driver, ma funziona solo su dispositivi Apple. Secondo WWDC 2024, Metal offre fino al 40% di prestazioni superiori rispetto a OpenGL ES sullo stesso hardware riducendo i controlli di stato in fase di esecuzione.
Vulkan è il successore multipiattaforma di OpenGL ES, sviluppato da Khronos Group. Vulkan utilizza la gestione esplicita delle risorse: lo sviluppatore alloca pool di memoria, crea buffer di comandi e sincronizza l'accesso alla GPU. Questo dà il massimo controllo sulle prestazioni, ma il codice di inizializzazione di Vulkan è 3–4 volte più esteso di quello di OpenGL ES. Vulkan è raccomandato per giochi AAA e applicazioni grafiche esigenti su Android 7+.
La scelta tra OpenGL ES, Metal e Vulkan dipende dalle piattaforme target e dai requisiti di prestazioni. OpenGL ES rimane la scelta migliore per progetti multipiattaforma dove la velocità di sviluppo è importante. Metal è preferito per l'ecosistema iOS/macOS con prestazioni massime. Vulkan è la scelta per progetti dove ogni millisecondo per frame conta e il budget di sviluppo consente di investire in ottimizzazione di basso livello.
| Caratteristica | OpenGL ES | Metal | Vulkan |
|---|---|---|---|
| Piattaforme | Android, iOS, Windows, Linux | Solo iOS, macOS | Android, Windows, Linux (no iOS) |
| Livello API | Alto (state machine) | Medio | Basso (esplicito) |
| Codice inizializzazione | 50–100 righe | 100–200 righe | 300–500 righe |
| Controllo memoria | Automatico | Semiautomatico | Completamente manuale |
| Prestazioni | Base | +20–40% vs ES | +30–60% vs ES |
Domande frequenti
OpenGL ES è un sottoinsieme di OpenGL desktop da cui sono state rimosse le funzionalità legacy del pipeline fisso. OpenGL ES ha un volume di specifica inferiore, un profilo di precisione semplificato ed è ottimizzato per il basso consumo energetico dei dispositivi mobili.
Android supporta OpenGL ES 2.0 su tutti i dispositivi, 3.0 su Android 4.3+, 3.1 su Android 5.0+, 3.2 su dispositivi selezionati con Android 7.0+. Il livello di supporto attuale può essere verificato tramite EGL_CONFIG_CAVEAT.
GLSL ES (OpenGL Shading Language for Embedded Systems) è un linguaggio simile a C con tipi vec2/vec3/vec4/mat4 e funzioni integrate texture, normalize, dot. Per ES 3.0+, viene utilizzata la direttiva #version 300 es.
Sì, OpenGL ES rimane rilevante per progetti multipiattaforma dove la priorità è la velocità di sviluppo e il supporto di un'ampia gamma di dispositivi. Per l'ecosistema iOS è meglio imparare Metal; per nuovi progetti con massime prestazioni, utilizzare Vulkan.
Su Android, chiamare GLES30.glGetString(GLES30.GL_VERSION) dopo aver creato il contesto. La stringa contiene il numero di versione e le informazioni sul fornitore. Su iOS, utilizzare [EAGLContext currentContext] e la proprietà API.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.