¿Qué encontrarás en este post?
ToggleOpenGL ES
Es un API de C para producir gráficos 3D y existe desde 1992. Desde entonces, el hardware gráfico ha cambiado mucho y en OpenGL aun hay muchas antiguallas que hoy son inútiles y sub-óptimas. En general es difícil encontrar una fuente de información moderna sobre OpenGL en internet.
Parte de OpenGL se ejecuta en la GPU y parte en la CPU y se encarga de pasar datos de un procesador a otro.
OpenGL ES para iOS
La ES significa Embedded Systems y soporta un subconjunto de todo OpenGL 2.0. Lo de embedded system (sistema empotrado) puede ir desde una nevera hasta la aviónica de un Typhoon, pero lo más normal es que lo lleves en el bolsillo en forma de iPhone.
GLKit
Es una framework introducida en iOS5 que facilita enormemente muchas tareas comunes en OpenGL. Implementa la filosofía de Apple: que lo común sea trivial y lo difícil, factible.
OpenCL
No tiene mucho que ver con OpenGL y es una confusión común. OpenCL (Open Computing Language) es un lenguaje (muy parecido a C) que se utiliza para describir algoritmos paralelos que se ejecutan en la GPU. Nos permite utilizar la potencia de la GPU para cálculos de coma flotante que no tienen necesariamente nada que ver con gráficos.
Se está usando mucho en HFT (High Frequency Trading) desde hace algunos años desde la explosión de pequeñas empresas de trading automático causada por los cambios de legislación en EEUU.
De cierta forma es similar a CUDA, aunque es abierto y multiplataforma, mientras que CUDA es propietario de Nvidia.
Cuando programamos con OpenCL, creamos una serie de ficheros en su lenguaje (llamados kernels) que se compilan en el cliente, según el hardware gráfico que tenga.
A fecha de hoy no es posible (que yo sepa) usar OpenCL en iOS, lo cual es una pena. Pongo el iPhone en el fuego que Apple sí que lo usa, o la velocidad de los dispositivos no se explica, pero aun no lo hace disponible a los mortales. En OSX, sí que se puede usar OpenCL.
La mejor explicación de lo que se puede hacer con una GPU y la diferencia con la CPU, la dieron, como no, los chicos de Mythbusters:
Renderizado
El crear una imagen a partir de sus datos 3D se llama renderizado.
Cuellos de Botella y Optimización
Hoy por hoy, el principal cuello de botella en un programa OpenGL está en copiar datos de o a memoria. Por lo tanto, la copia de datos se debe de minimizar. Hay en OpenGL formas arcaicas e ineficientes de copiar memoria que han sido eliminados en OpenGL ES.
Si tienes un MBA, probablemente estés muy orgulloso de lo rápido que es tu SSD, pero lamento decirte que sigue siendo más lento que el caballo del malo cuando viene de Bonanza. Lo mismo se aplica a la RAM.
Aunque no tengo datos, juraría que la diferencia de velocidad entre los procesadores y la RAM se ha ido incrementando con el tiempo (los procesadores avanzaron mucho más deprisa).
El acceso a memoria es muy lento, si lo comparamos con la velocidad del procesador. A fecha de hoy, unos datos aproximados serían:
- CPU: Mil millones de operaciones por segundo.
- GPU: Varios miles de millones de operaciones por segundo.
- Memoria: 200 millones de accesos por segundo.
Es fácil que una CPU (y mucho más aún, una GPU) se queden “atascados” a la espera de datos de memoria (“data starved”), así que es fundamental proporcionar datos al procesador de la forma más eficiente posible, para así sacar provecho del hardware.
Forma Óptima de Proporcionar Datos: Buffers
Un buffer es un área continua de memoria bajo control de la GPU, que se utiliza para la entrada y salida de datos de la forma más eficiente posible. La GPU procesa los datos en los buffers de forma paralela y asíncrona, es decir, mientras la GPU trabaja, la CPU está libre para seguir atendiendo la aplicación.Uso de los búffers
- Crear: OpenGL crea un ID único para identificar el buffer.
- Enlazar : Se asigna el buffer a OpenGL para que pueda usarlo.
- Inicializar: Se asigna memoria y copian datos (a menudo sacándolos de la cache del procesador).
- Activar y desactivar : Indicarle a OpenGL que pase a usar o deje de usar un buffer para un renderizado.
- Asignar tipo : Indicar a OpenGL el tipo de los datos en el buffer y los offsets para acceder a los datos.
- Dibujar: Decirle a OpenGL que renderice todo o parte de una escena usando los buffers enlazados y activos.
- Eliminar : Eliminar un buffer y liberar su memoria
Lo ideal es que una vez creado, un buffer sea reutilizado a lo largo de la vida de la aplicación. El generar, inicializar y destruir buffers a menudo causa retrasos por sincronización entre CPU y GPU (antes de eliminar un buffer, la GPU ha de terminar todas las tareas pendientes para dicho buffer, y puede tener a la CPU esperando).
Buffers de Salida: Frame Buffers
Reciben los resultados de una renderización (la imagen) . Al contrario de los buffers de entrada, no necesitan ser inicializados, ya que se sobreescriben con los nuevos datos de cada renderización. Por lo demás, funcionan de la misma manera que los demás buffers.
Hay dos Frame Buffers especiales:
- Front Frame Buffer: el que muestra la imagen previamente renderizada
- Back Frame Buffer: el que está recibiendo los datos de la actual renderización.
Cuando se termina la renderización, los dos buffers se intercambian.
Contexto de OpenGL
Contiene todo el estado necesario para la renderización: frame buffer de salida, buffers de entrada, texturas, colores, y demás. Es similar al contexto de Core Graphics.
Sistema de Coordenadas
El sistema de coordenadas por defecto de OpenGL es el Cartesiano. Aunque a veces nos podrá resultar más cómodo utilizar coordenadas polares para ciertas escenas, al final tendremos que convertir a cartesiano para su procesamiento.
Vectores
Las GPUs son procesadores de vectores de números de coma flotante, masivamente paralelos. Por lo tanto, la entrada de un programa OpenGL será una serie de vectores que definen los vértices (puntos) de una escena.
Ahora que lo pienso, es una lástima que no exista nada de más alto nivel que compile a OpenCL. Algún año de estos me haré millonario y tendré tiempo para portar *Lisp a OpenCL. Un año de éstos…
Vértices, puntos, lineas y triángulos
OpenGL ES usa datos de vértices para determinar puntos, segmentos y triángulos:
- Punto: un vértice.
- Segmento: dos vértices
- Triángulo: 3 vértices
OpenGL sólo renderiza estos tres conceptos, así que toda imagen estará compuesta por puntos, segmentos o triángulos.
Conclusión
A medida que el tiempo me lo permita, iré creando otros artículos sobre cómo empezar a usar OpenGL ES en Cocoa y sobre todo, como unir OpenGL y Core Animation para generar interfaces “ribolusionarias”.
Por otro lado, en Noviembre voy a impartir en Epe el curso “Advanced iOS” del Big Nerd Ranch, donde se verá OpenGL ES y mucho más.
También tengo pensado impartir un workshop en Barcelona en diciembre sobre OpenGL ES y GLKit. Iré dando más detalles a medida que los tenga.