OpenGL tiene cuatro versiones principales diferentes, sin contar las versiones para dispositivos móviles y sistemas integrados (OpenGL | ES) y la Web a través de JavaScript (WebGL). Al igual que Direct3D 11 tiene una forma diferente de hacer las cosas que Direct3D 8, también OpenGL 3 tiene una forma diferente de hacer las cosas que OpenGL 1. La gran diferencia es que las versiones de OpenGL son en su mayoría solo complementos a las versiones anteriores (pero no enteramente).
Además de las diferentes ediciones y versiones de OpenGL, el OpenGL principal también agregó el concepto de perfiles. A saber, el Perfil de compatibilidad (que habilita el soporte para API de versiones anteriores) y el Perfil principal (que deshabilita esas API antiguas). Cosas como glBegin
simplemente no funcionan cuando usa el Perfil principal, pero sí cuando usa el Perfil de compatibilidad (que es el predeterminado).
Como otra complicación importante, algunas implementaciones de OpenGL (como la de Apple, entre otras) solo habilitarán las funciones más nuevas de OpenGL cuando use el Core Profile. Esto significa que debe dejar de usar las API más antiguas para usar las más nuevas.
Luego terminas con varios escenarios muy confusos para tutoriales:
- El tutorial es antiguo y solo usa API obsoletas.
- El tutorial es nuevo y está bien escrito, y solo utiliza API compatibles con Core.
- El tutorial es nuevo, pero comete el error de suponer que está trabajando con un controlador que habilita todas las API en modo de compatibilidad y mezcla libremente tanto las API nuevas como las antiguas.
- El tutorial es para una edición diferente de OpenGL como OpenGL | ES que no admite ninguna de las API antiguas, en ninguna versión.
Cosas como glBegin
son parte de lo que a veces se llama la API de modo inmediato. Esto también es muy confuso porque no existe un modo retenido en OpenGL y el "modo inmediato" ya tenía una definición diferente en los gráficos. Es mucho mejor referirse a las API de OpenGL 1.x ya que han quedado obsoletas desde OpenGL 2.1.
La API 1.x de OpenGL enviaría vértices inmediatamente a la tubería de gráficos en los viejos tiempos. Esto funcionó bien cuando la velocidad del hardware que generaba los vértices era aproximadamente igual a la velocidad de la CPU que genera los datos de vértice. OpenGL entonces simplemente descargó la rasterización del triángulo y no mucho más.
En estos días, la GPU puede masticar grandes cantidades de vértices a velocidades muy altas mientras realiza una transformación avanzada de vértices y píxeles y la CPU simplemente no puede ni remotamente seguir el ritmo. Además de eso, la interfaz entre la CPU y la GPU se ha diseñado en torno a esta diferencia de velocidad, lo que significa que ya ni siquiera es posible enviar vértices a la GPU.
Todos los controladores GL deben emular glBegin
asignando internamente un búfer de vértices, colocando los vértices enviados glVertex
en este búfer y luego enviando todo el búfer en una sola llamada de extracción cuando glEnd
se llama. La sobrecarga de estas funciones es mucho mayor que si acaba de actualizar el búfer de vértices usted mismo, por lo que parte de la documentación (¡muy erróneamente!) Se referirá a los búferes de vértices como "una optimización" (no es una optimización; es la única forma de realmente hablar con la GPU).
Hay varias otras API que han quedado obsoletas u obsoletas en OpenGL a lo largo de los años. La llamada tubería de función fija es otra de esas piezas. Es posible que parte de la documentación todavía use esta tubería o se mezcle con la tubería programable. La canalización de funciones fijas proviene de los viejos tiempos cuando las tarjetas gráficas codificaban todas las matemáticas utilizadas para representar escenas 3D y la API de OpenGL se limitaba a establecer algunos valores de configuración para esas matemáticas. En estos días, el hardware tiene muy pocas matemáticas codificadas y (al igual que su CPU) ejecuta programas proporcionados por el usuario (a menudo llamados sombreadores).
Una vez más, los controladores deben emular la antigua API, ya que las funciones de función fija simplemente ya no están presentes en el hardware. Esto significa que el controlador tiene un montón de sombreadores de compatibilidad integrados que ejecutan las viejas matemáticas de los días de funciones fijas que se utilizan cuando no suministra sus propios sombreadores. Las antiguas funciones de OpenGL que modifican ese antiguo estado de función fija (como la antigua API de iluminación de OpenGL) en realidad están utilizando características modernas de OpenGL como buffers uniformes para alimentar estos valores a los sombreadores de compatibilidad del controlador.
Los controladores que admiten la compatibilidad tienen que hacer un montón de trabajo detrás de escena solo para descubrir cuándo estás usando estas funciones obsoletas y asegurarte de que puedas combinarlas con las funciones modernas sin problemas, lo que agrega sobrecarga y complica enormemente el controlador. Esta es una de las razones por las que algunos controladores lo obligan a habilitar el Core Profile para obtener nuevas funciones; simplifica enormemente sus componentes internos del controlador al no tener que admitir las API antiguas y nuevas que se usan simultáneamente.
Una gran cantidad de documentación puede recomendar que comience con las API antiguas simplemente porque es más fácil comenzar con ellas. Direct3D resolvió este problema para principiantes al ofrecer una biblioteca complementaria ( Kit de herramientas de DirectX ) que proporciona API de dibujo más simples y sombreadores preescritos que se pueden mezclar libremente con el uso directo de Direct3D 11 a medida que aumenta su experiencia. Desafortunadamente, la comunidad más amplia de OpenGL se ha quedado con el Perfil de compatibilidad para principiantes, lo cual es problemático ya que nuevamente hay sistemas que no le permiten mezclar las antiguas API de OpenGL con las más nuevas. Hay bibliotecas y herramientas no oficiales para una representación más simple en el nuevo OpenGL con diferentes niveles de características y casos de uso e idiomas de destino ( MonoGame para usuarios de .NET, por ejemplo), pero nada oficialmente respaldado o ampliamente aceptado.
La documentación que está encontrando puede que ni siquiera sea para OpenGL, pero puede ser para una de las otras API similares. OpenGL | ES 1.x tenía una representación de función fija pero no tenía las API de OpenGL 1.x para el envío de vértices. OpenGL | ES 2.x + y WebGL 1+ no tienen ninguna función de función fija y no hay modos de compatibilidad con versiones anteriores para esas API.
Estas API se parecen mucho a OpenGL principal; no son del todo compatibles, pero hay extensiones oficiales de OpenGL que algunos (no todos) los controladores admiten para ser compatibles con OpenGL | ES (en el que se basa WebGL). Porque las cosas no eran lo suficientemente confusas antes.