http://www.sdltutorials.com/sdl-opengl-tutorial-basics
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
Estos dos tutoriales utilizan enfoques completamente diferentes para obtener casi el mismo resultado. El primero usa cosas como glBegin(GL_QUADS)
. El segundo usa cosas como vertexBufferObjects
sombreadores basados en GLEW. Pero el resultado es el mismo: obtienes formas básicas.
¿Por qué existen estas diferencias?
El primer enfoque parece mucho más fácil de entender. ¿Cuál es la ventaja del complicado segundo enfoque?
opengl
architecture
reynmar
fuente
fuente
glBegin
yglEnd
han quedado en desuso porque son extremadamente ineficientes para las arquitecturas gráficas actualesRespuestas:
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:
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 enviadosglVertex
en este búfer y luego enviando todo el búfer en una sola llamada de extracción cuandoglEnd
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.
fuente
La principal diferencia es cuán actualizadas están las estrategias. El modo inmediato utilizado en el primer tutorial:
Está desactualizado y no es compatible con las versiones más recientes.
El uso de buffers y sombreadores de vértices es el método actual de renderizado con OpenGL. Puede parecer más complicado, pero funciona considerablemente mejor. Además, una vez que tenga su código de soporte envolviendo el material de OpenGL, las diferencias se abstraen en su mayor parte.
fuente
Solo para agregar un poco más de contexto a las otras excelentes respuestas.
El modo inmediato como se describe en el primer enlace es, como han dicho otros, código heredado de las primeras versiones de OpenGL (1.1). Se usó cuando las GPU eran poco más que rasterizadores triangulares y no existía la idea de tuberías programables. Si observa el código fuente de algunos de los primeros juegos acelerados por hardware como GLQuake y Quake 2, por ejemplo, verá el modo inmediato en uso. En términos simples, la CPU envía instrucciones para los vértices de uno en uno a la GPU para comenzar a dibujar triángulos en la pantalla. Para el registro, GL_QUADS tiene el mismo resultado que GL_TRIANGLES, excepto que la GPU tiene que convertir esos quads en triángulos sobre la marcha.
OpenGL moderno (3.2+) tiene un enfoque diferente. Almacena los datos de vértice en la memoria de la GPU para un acceso rápido, y luego puede enviar instrucciones de dibujo utilizando glDrawArrays o glDrawElements. También tiene la tubería programable (glUseProgram) que le permite personalizar cómo la GPU coloca y colorea los vértices.
Hay algunas razones por las cuales el modo inmediato fue desaprobado, la razón principal es el rendimiento. Como dijo Sean en su respuesta, hoy en día las GPU pueden procesar los datos más rápido de lo que la CPU puede cargarlos, por lo que estaría obstaculizando el rendimiento de la GPU. Hay una pequeña sobrecarga por cada llamada a OpenGL que realice, es minúsculo, pero cuando realiza decenas de miles de llamadas en cada trama, comienza a acumularse. En pocas palabras, para dibujar un modelo texturizado usando el modo inmediato, necesita al menos 2 llamadas por vértice (glTexCoord2f y glVertex3f) por fotograma. Con OpenGL moderno, utiliza un par de llamadas al principio para almacenar en búfer los datos, luego puede dibujar todo el modelo, independientemente de cuántos vértices contenga, utilizando solo unas pocas llamadas para vincular el objeto de matriz de vértices, habilitar algunos punteros de atributos y luego una sola llamada a glDrawElements o glDrawArrays.
¿Qué técnica es la correcta? Bueno, eso depende de lo que intentes hacer. Un juego 2D simple que no requiere ninguna técnica de post-procesamiento o sombreadores sofisticados funcionará bien usando el modo inmediato y probablemente será más fácil escribir el código. Sin embargo, un juego 3D más moderno realmente tendría dificultades, y si estás planeando aprender GLSL (lenguaje de sombreado), definitivamente aprenderás la técnica moderna.
fuente