5. OpenGL ES
• OpenGL for Embedded Systems
• API de gráficos 3D de bajo nivel
• Permite especificar la geometría y propiedades de objetos
(color, iluminación, texturas)
• Subconjunto de OpenGL
6. Versiones de OpenGL ES
Hardware Dispositivos OpenGL
iPhone
OpenGL ES
Función fija iPhone 3G 1.5
1.1 iPod touch
OpenGL ES Programable
iPhone 3G S 2.0
2.0 (shaders)
7. Un mundo de vértices
• Los objetos se definen mediante conjuntos de vértices
• Cada vértice puede tener asociada información de color y
textura
• Los vértices se agrupan en primitivas: triángulos, puntos,
líneas, tiras de triángulos, etc.
8. Primitivas
Primitiva Descripción
Conjunto de puntos
GL_POINTS
(N vértices → N puntos)
Conjunto de segmentos conectados
GL_LINE_STRIP
(N vértices → N-1 segmentos)
Conjunto cíclico de segmentos conectados
GL_LINE_LOOP
(N vértices → N segmentos)
Conjunto de segmentos desconectados
GL_LINES
(N vértices → N/2 segmentos)
Tira de triángulos
GL_TRIANGLE_STRIP
(N vértices → N-2 triángulos)
Abanico de triángulos
GL_TRIANGLE_FAN
(N vértices → N-2 triángulos)
Conjunto de triángulos
GL_TRIANGLES
(N vértices → N/3 triángulos)
10. Anatomía de una aplicación 3D
(simplificada)
Plantilla “OpenGL ES Application” de XCode
1. Inicializar OpenGL ES
1.1. Crear un contexto OpenGL ES (EAGLContext)
1.2. Asociar el contexto a una vista (EAGLView)
2. Bucle (cada frame):
2.1. Actualizar estado de la aplicación
2.2. Dibujar
12. Borrar la pantalla
• Pinta todo el buffer de un único color
• Se hace (al menos) al inicio de cada frame
13. Borrar la pantalla
• Pinta todo el buffer de un único color
• Se hace (al menos) al inicio de cada frame
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
14. Borrar la pantalla
• Pinta todo el buffer de un único color
• Se hace (al menos) al inicio de cada frame
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
15. Dibujar primitivas
• Los vértices se almacenan en un array y se dibujan con
glDrawArrays
16. Dibujar primitivas
• Los vértices se almacenan en un array y se dibujan con
glDrawArrays
glEnableClientState(GL_VERTEX_ARRAY);
17. Dibujar primitivas
• Los vértices se almacenan en un array y se dibujan con
glDrawArrays
glEnableClientState(GL_VERTEX_ARRAY);
const GLfloat vertices[] = {
-0.5f, -0.5f,
0.5f, -0.5f,
-0.5f, 0.5f,
0.5f, 0.5f,
};
glVertexPointer(2, GL_FLOAT, 0, vertices);
18. Dibujar primitivas
• Los vértices se almacenan en un array y se dibujan con
glDrawArrays
glEnableClientState(GL_VERTEX_ARRAY);
const GLfloat vertices[] = {
-0.5f, -0.5f,
0.5f, -0.5f,
-0.5f, 0.5f,
0.5f, 0.5f,
};
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
19. Seleccionar un color
• El color se define en RGBA
• Por defecto, las operaciones que utilizan color utilizan el
último color seleccionado
20. Seleccionar un color
• El color se define en RGBA
• Por defecto, las operaciones que utilizan color utilizan el
último color seleccionado
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
21. Seleccionar un color
• El color se define en RGBA
• Por defecto, las operaciones que utilizan color utilizan el
último color seleccionado
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1
dibujaObjeto1();
22. Seleccionar un color
• El color se define en RGBA
• Por defecto, las operaciones que utilizan color utilizan el
último color seleccionado
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1
dibujaObjeto1();
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
23. Seleccionar un color
• El color se define en RGBA
• Por defecto, las operaciones que utilizan color utilizan el
último color seleccionado
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1
dibujaObjeto1();
glColor4f(1.0f, 0.0f, 0.0f, 1.0f); 2
dibujaObjeto2();
24. Seleccionar un color
• El color se define en RGBA
• Por defecto, las operaciones que utilizan color utilizan el
último color seleccionado
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1
dibujaObjeto1();
glColor4f(1.0f, 0.0f, 0.0f, 1.0f); 2
dibujaObjeto2();
dibujaObjeto3(); 3
26. El mundo 3D en OpenGL
• OpenGL representa el mundo 3D a través de matrices a las
que se aplican transformaciones (multiplicaciones)
• Dos matrices fundamentales:
‣ Modelo-vista (GL_MODELVIEW)
‣ Proyección (GL_PROJECTION)
• Las transformaciones se aplican sobre la matriz activa
27. Analogía cámara fotográfica
• Elección de la posición de la cámara
Matriz modelo-vista
• Elección de la disposición de los objetos
• Elección de la lente Matriz de proyección
28. La matriz modelo-vista
• Define la posición y orientación de los objetos
• Tres operaciones: traslación, rotación y escalado
Traslación Rotación Escalado
33. La matriz de proyección
• Determina cómo se va a proyectar la geometría 3D sobre la pantalla 2D
• Planos de corte (clipping)
Ortográfica Perspectiva
35. Ejemplo: Perspectiva
void glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
GLfloat near, GLfloat far)
void glFrustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top,
GLfixed near, GLfixed far)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float aspect = width / height;
float fov = 50.0f;
float near = 0.5f;
float far = 20.0f;
float top = near * tan(fov * PI / 360.0f);
float bottom = -top;
float left = bottom * aspect;
float right = top * aspect;
glFrustumf(left, right, bottom, top, near far);
36. Anatomía de una aplicación 3D
(actualizada)
1. Inicializar OpenGL ES
1.1. Crear un contexto OpenGL ES (EAGLContext)
1.2. Asociar el contexto a una vista (EAGLView)
1.3. Inicializar la matriz de proyección con glOrtho o glFrustum
2. Bucle (cada frame):
2.1. Actualizar estado de la aplicación
2.2. Dibujar utilizando OpenGL
- Borrar la pantalla con glClear
- Situar la cámara transformando la matriz modelo-vista
- Para cada objeto:
Situar el objeto transformando la matriz modelo-vista
Dibujar las primitivas del objeto
38. Texturas
• Imágenes 2D que se dibujan sobre las primitivas
• Son un aspecto crítico en aplicaciones 3D para iPhone por su
tamaño en memoria y tiempo de carga
39. Cargar una textura
1. Cargar la imagen con CGBitmapContextCreate (ver clase Texture2D, ejemplo “Crash Landing”)
2. Definir los parámetros de filtrado
3. Crear un objeto textura en OpenGL con glTexImage2D
img = cargarImagen(“imagen.png”);
GLuint texName;
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgWidth, imgHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, img);
free(img);
40. Utilizar una textura
1. Activar las texturas con glEnable(GL_TEXTURE_2D)
2. Definir las coordenadas de la textura, que afectan a cómo se acopla la textura a los vértices
3. Dibujar la primitiva
41. Utilizar una textura
1. Activar las texturas con glEnable(GL_TEXTURE_2D)
2. Definir las coordenadas de la textura, que afectan a cómo se acopla la textura a los vértices
3. Dibujar la primitiva
glEnable(GL_TEXTURE_2D); /* sólo una vez */
42. Utilizar una textura
1. Activar las texturas con glEnable(GL_TEXTURE_2D)
2. Definir las coordenadas de la textura, que afectan a cómo se acopla la textura a los vértices
3. Dibujar la primitiva
glEnable(GL_TEXTURE_2D); /* sólo una vez */
glBindTexture(GL_TEXTURE_2D, texName);
43. Utilizar una textura
1. Activar las texturas con glEnable(GL_TEXTURE_2D)
2. Definir las coordenadas de la textura, que afectan a cómo se acopla la textura a los vértices
3. Dibujar la primitiva
glEnable(GL_TEXTURE_2D); /* sólo una vez */
glBindTexture(GL_TEXTURE_2D, texName);
glVertexPointer(3, GL_FLOAT, 0, vertices);
44. Utilizar una textura
1. Activar las texturas con glEnable(GL_TEXTURE_2D)
2. Definir las coordenadas de la textura, que afectan a cómo se acopla la textura a los vértices
3. Dibujar la primitiva
glEnable(GL_TEXTURE_2D); /* sólo una vez */
glBindTexture(GL_TEXTURE_2D, texName);
glVertexPointer(3, GL_FLOAT, 0, vertices);
GLfloat texCoordinates[] = {
0, 1.0f,
0, 0,
1.0f, 0,
1.0f, 1.0f
};
glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates);
45. Utilizar una textura
1. Activar las texturas con glEnable(GL_TEXTURE_2D)
2. Definir las coordenadas de la textura, que afectan a cómo se acopla la textura a los vértices
3. Dibujar la primitiva
glEnable(GL_TEXTURE_2D); /* sólo una vez */
glBindTexture(GL_TEXTURE_2D, texName);
glVertexPointer(3, GL_FLOAT, 0, vertices);
GLfloat texCoordinates[] = {
0, 1.0f,
0, 0,
1.0f, 0,
1.0f, 1.0f
};
glTexCoordPointer(2, GL_FLOAT, 0, texCoordinates);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
47. Shaders
• Programas ejecutados por la GPU
• OpenGL ES 2.0 incluye dos tipos:
‣ Vertex shaders: manipulan vértices
‣ Fragment shaders: manipulan píxeles
• Se programan en OpenGL ES Shading Language
48. Vertex shaders
• Procesan los vértices especificados con glDrawArrays
• El shader está formado por el conjunto de operaciones que se
aplicarán a cada vértice
• Aplicaciones típicas:
- Deformación de superficies
- Suavizado de elementos articulados para animación de
personajes
- Etc.
49. Fragment shaders
• Procesan el color de los píxeles (pixel shaders)
• Aplicaciones típicas:
- Bump mapping
- Reflejos
- Cartoon-shading
- Etc.
50. Creación de shaders
• Se crea un nuevo objeto shader y se compila el código
• También se puede cargar el shader precompilado (ShaderBinary)
const char *shaderFiles[] = {
“shader1.glsl”,
“shader2.glsl”,
};
const int shaderFilesLength[] = {
NULL,
NULL,
};
uint shader = CreateShader(VERTEX_SHADER); /* o FRAGMENT_SHADER */
ShaderSource(shader, 2, shaderFiles, shaderFilesLength);
CompileShader(shader);
51. Utilización de shaders
• Los shaders se agrupan en una entidad común llamada programa
• Una vez se ha creado el programa y añadido los shaders, se ejecuta con
UseProgram
uint program = CreateProgram();
AttachShader(program, shader);
LinkProgram(program);
UseProgram(program);
52. Más información
• OpenGL ES Programming for iPhone, iPhone Reference Library,
http://developer.apple.com/iphone
• OpenGL ES, http://www.khronos.org/opengles
• T. Akenine-Möller, E. Haines and N. Hoffman, Real-Time
Rendering, A. K. Peters Ltd., 3rd edition
53. ¡Gracias!
Manuel R. Freire
manuel@interactive-fan.com