http://www.sdltutorials.com/sdl-opengl-tutorial-basics
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
Ces deux tutoriels utilisent des approches complètement différentes pour obtenir presque le même résultat. Le premier utilise des choses comme glBegin(GL_QUADS)
. La seconde utilise des trucs comme des vertexBufferObjects
shaders basés sur GLEW. Mais le résultat est le même: vous obtenez des formes de base.
Pourquoi ces différences existent-elles?
La première approche semble beaucoup plus facile à comprendre. Quel est l'avantage de la seconde approche compliquée?
opengl
architecture
Reynmar
la source
la source
glBegin
etglEnd
ont été déconseillés car ils sont extrêmement inefficaces pour les architectures graphiques actuellesRéponses:
OpenGL a quatre versions principales différentes, sans compter les versions pour les appareils mobiles et les systèmes intégrés (OpenGL | ES) et le Web via JavaScript (WebGL). Tout comme Direct3D 11 a une manière de faire différente de Direct3D 8, OpenGL 3 a une façon de faire différente de celle d’OpenGL 1. La grande différence est que les versions d’OpenGL ne sont généralement que des add-ons aux anciennes versions (mais pas entièrement).
Outre les différentes éditions et versions d'OpenGL, le principal OpenGL a également ajouté le concept de profils. À savoir le profil de compatibilité (qui active la prise en charge des API d'anciennes versions) et le profil principal (qui désactive ces anciennes API). Des choses comme
glBegin
tout simplement ne fonctionnent pas lorsque vous utilisez le profil principal, mais le seront quand vous utiliserez le profil de compatibilité (qui est le profil par défaut).Comme autre complication majeure, certaines implémentations d'OpenGL (comme celle d'Apple, entre autres) n'activeront les nouvelles fonctionnalités OpenGL que lorsque vous utilisez le profil principal. Cela signifie que vous devez cesser d'utiliser les anciennes API pour pouvoir utiliser les nouvelles API.
Vous vous retrouvez alors avec plusieurs scénarios très déroutants pour les tutoriels:
Des choses comme
glBegin
font partie de ce qu'on appelle parfois l'API en mode immédiat. C'est également très déroutant, car un mode retenu dans OpenGL et le "mode immédiat" avaient déjà une définition différente dans les graphiques. Il est bien mieux de se référer à celles-ci sous le nom d'API OpenGL 1.x, car elles sont obsolètes depuis OpenGL 2.1.L'API 1.x d'OpenGL soumettait immédiatement les sommets au pipeline graphique dans le passé. Cela fonctionnait bien lorsque la vitesse du matériel qui rendait les sommets était à peu près égale à celle du processeur générant les données du sommet. OpenGL à l'époque vient de décharger le rasterization du triangle et pas grand-chose d'autre.
De nos jours, le GPU peut parcourir de très nombreux sommets à très haute vitesse tout en effectuant une transformation avancée des vertex et des pixels et le processeur ne peut tout simplement pas suivre à distance. De plus, l'interface entre le processeur et le processeur graphique a été conçue autour de cette différence de vitesse, de sorte qu'il n'est même plus possible de soumettre des sommets au processeur graphique à la fois.
Tous les pilotes GL doivent émuler
glBegin
en allouant en interne un tampon de vertex, en plaçant les vertices soumis avecglVertex
dans ce tampon, puis en soumettant ce tampon entier dans un seul appel de dessin lorsqueglEnd
est appelé. Le surcoût de ces fonctions est bien plus important que si vous venez de mettre à jour vous-même le tampon de vertex, c’est pourquoi certaines documentations qualifient (par erreur!) Les tampons de vertex comme "une optimisation" (ce n’est pas une optimisation; c’est le seul moyen de parler au GPU).Différentes autres API ont été obsolètes ou obsolètes dans OpenGL au fil des ans. Le pipeline dit à fonction fixe est un autre exemple. Certaines documentations peuvent toujours utiliser ce pipeline ou se mélanger au pipeline programmable. Le pipeline à fonction fixe provient de l'ancien temps où les cartes graphiques codaient en dur tous les calculs utilisés pour le rendu des scènes 3D et que l'API OpenGL était limitée à la définition de valeurs de configuration pour ce calcul. De nos jours, le matériel utilise très peu de maths codés en dur et (tout comme votre CPU) exécute des programmes fournis par l'utilisateur (souvent appelés shaders).
Une fois encore, les pilotes doivent émuler l'ancienne API car les fonctionnalités à fonction fixe ne sont tout simplement plus présentes sur le matériel. Cela signifie que le pilote contient un ensemble de nuanceurs de compatibilité qui exécutent l'ancien calcul des jours à fonction fixe, utilisé lorsque vous ne fournissez pas vos propres nuanceurs. Les anciennes fonctions OpenGL qui modifient cet ancien état à fonction fixe (comme l'ancienne API d'éclairage OpenGL) utilisent en fait des fonctionnalités OpenGL modernes, telles que des tampons uniformes, pour transmettre ces valeurs aux shaders de compatibilité du pilote.
Les pilotes qui prennent en charge la compatibilité doivent faire beaucoup de travail en coulisse pour comprendre quand vous utilisez ces fonctionnalités obsolètes et vous assurer que vous pouvez les combiner avec des fonctionnalités modernes, ce qui augmente les frais généraux et complique grandement les tâches du pilote. C'est l'une des raisons pour lesquelles certains pilotes vous obligent à activer le profil principal pour obtenir de nouvelles fonctionnalités. cela simplifie grandement les internes de leurs pilotes en évitant de prendre en charge les anciennes et les nouvelles API utilisées simultanément.
Beaucoup de documentation peut vous recommander de commencer avec les anciennes API simplement parce qu'elles sont plus faciles à utiliser. Direct3D a résolu ce problème pour les débutants en proposant une bibliothèque complémentaire ( Kit DirectX Tool Kit ) qui fournit des API de dessin plus simples et des shaders pré-écrits pouvant être mélangés librement avec l'utilisation brute de Direct3D 11 à mesure que votre savoir-faire se développe. La communauté OpenGL au sens large s’est heurtée au profil de compatibilité pour les débutants, ce qui est malheureusement problématique, car il existe à nouveau des systèmes qui ne vous permettent pas de mélanger les anciennes API OpenGL avec les plus récentes. Il existe des bibliothèques et des outils non officiels pour un rendu plus simple du nouvel OpenGL avec différents niveaux de fonctionnalités, ainsi que des cas d'utilisation et des langues cibles ( MonoGame pour les utilisateurs .NET par exemple), mais rien n’a été officiellement approuvé ou largement accepté.
La documentation que vous trouvez peut ne même pas être pour OpenGL mais peut-être pour l'une des autres API similaires. OpenGL | ES 1.x avait un rendu à fonction fixe mais ne disposait pas des API OpenGL 1.x pour la soumission de vertex. OpenGL | ES 2.x + et WebGL 1+ ne possèdent aucune fonctionnalité à fonction fixe et il n'existe aucun mode de compatibilité avec les versions antérieures pour ces API.
Ces API ressemblent beaucoup à OpenGL principal; ils ne sont pas tout à fait compatibles, mais il existe des extensions officielles d'OpenGL que certains (pas tous) pilotes prennent en charge pour devenir compatibles avec OpenGL | ES (sur lequel WebGL est basé). Parce que les choses n'étaient pas assez déroutantes auparavant.
la source
La principale différence réside dans la mise à jour des stratégies. Le mode immédiat utilisé dans le premier tutoriel:
Est obsolète et non pris en charge sur les versions plus récentes.
L'utilisation de vertex buffers et shaders est la méthode actuelle de rendu avec OpenGL. Cela peut sembler plus compliqué, mais cela donne de bien meilleurs résultats. De plus, une fois que votre code de support encapsule les éléments OpenGL, les différences sont pour la plupart abstraites.
la source
Juste pour ajouter un peu plus de contexte aux autres excellentes réponses.
Le mode immédiat, tel que décrit dans le premier lien, est, comme d'autres l'ont déjà dit, du code hérité des premières versions d'OpenGL (1.1). Il était utilisé à une époque où les GPU n'étaient guère plus que des rasteriseurs triangulaires et l'idée de pipelines programmables n'existait pas. Si vous examinez le code source de certains des premiers jeux à accélération matérielle tels que GLQuake et Quake 2, par exemple, vous verrez que le mode immédiat est utilisé. En termes simples, la CPU envoie des instructions pour les sommets une par une au GPU pour commencer à dessiner des triangles à l'écran. Pour mémoire, GL_QUADS a le même résultat que GL_TRIANGLES, sauf que le GPU doit transformer ces quads en triangles lui-même à la volée.
Moderne (3.2+) OpenGL adopte une approche différente. Il met en mémoire tampon les données de vertex dans la mémoire du processeur graphique pour un accès rapide. Vous pouvez ensuite envoyer des instructions de dessin à l'aide de glDrawArrays ou de glDrawElements. Vous avez également le pipeline programmable (glUseProgram) qui vous permet de personnaliser la façon dont le GPU positionne et colore les sommets.
Le mode immédiat est déconseillé pour plusieurs raisons, principalement les performances. Comme Sean l'a dit dans sa réponse, les GPU peuvent maintenant traiter les données plus rapidement que le processeur ne peut les télécharger, ce qui constituerait un goulot d'étranglement pour les performances du GPU. Il y a une petite surcharge pour chaque appel à OpenGL que vous effectuez, il est minuscule, mais lorsque vous effectuez des dizaines de milliers d'appels, chaque image commence à s'accumuler. En termes simples, pour dessiner un modèle texturé en mode immédiat, vous avez besoin d’au moins 2 appels par sommet (glTexCoord2f et glVertex3f) par image. Avec OpenGL moderne, vous utilisez deux appels au début pour mettre les données en mémoire tampon. Vous pouvez ensuite dessiner le modèle entier, quel que soit le nombre de sommets qu’il contient, en utilisant seulement quelques appels pour lier l’objet de sommet, activer certains pointeurs d’attributs et puis un seul appel à glDrawElements ou glDrawArrays.
Quelle technique est la bonne? Cela dépend de ce que vous essayez de faire. Un simple jeu en 2D qui ne nécessite aucune technique de post-traitement sophistiquée ou des shaders fonctionnera parfaitement en mode immédiat et il sera probablement plus facile d'écrire le code. Cependant, un jeu 3D plus moderne aurait vraiment de la difficulté, et si vous envisagez d'apprendre le GLSL (langage des shader), alors apprenez définitivement la technique moderne.
la source