Devrais-je appeler glEnable et glDisable chaque fois que je dessine quelque chose?

StackOverflow https://stackoverflow.com/questions/802079

  •  03-07-2019
  •  | 
  •  

Question

À quelle fréquence devrais-je appeler des fonctions OpenGL telles que glEnable () ou glEnableClientState () et leurs équivalents glDisable correspondants? Sont-ils censés être appelés une fois au début de l'application ou dois-je les laisser désactivés et n'activer que les fonctionnalités dont j'ai immédiatement besoin pour dessiner quelque chose? Y a-t-il une différence de performance?

Était-ce utile?

La solution

"Cela dépend".

Si l'ensemble de votre application n'utilise qu'une seule combinaison d'états d'activation / de désactivation, configurez-la simplement au début et continuez.

La plupart des applications du monde réel doivent mélanger, puis vous devez appeler glEnable () pour activer un ou plusieurs états particuliers, effectuer les appels de tirage, puis glDisable ( ) à nouveau lorsque vous avez terminé "effacer l'étape".

Le tri d’états, le suivi des états et de nombreux schémas d’optimisation en découlent, la commutation d’états étant parfois coûteuse.

Autres conseils

Si vous constatez que vous vérifiez souvent la valeur des variables d'état et que vous appelez ensuite glEnable / glDisable, vous pourrez peut-être nettoyer un peu en utilisant la pile d'attributs (glPushAttrib / glPopAttrib).

La pile d'attributs vous permet d'isoler des zones de votre code et que les modifications apportées à l'attribut dans une section n'affectent pas l'état de l'attribut dans les autres sections.

void drawObject1(){
  glPushAttrib(GL_ENABLE_BIT);

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);    

  /* Isolated Region 1 */

  glPopAttrib();
}        

void drawObject2(){
  glPushAttrib(GL_ENABLE_BIT);

  glEnable(GL_FOG);
  glEnable(GL_GL_POINT_SMOOTH);    

   /* Isolated Region 2 */

  glPopAttrib();
}    

void drawScene(){
  drawObject1();
  drawObject2();
}

Bien que GL_LIGHTING et GL_DEPTH_TEST soient définis dans drawObject1, leur état n'est pas conservé dans drawObject2. En l'absence de glPushAttrib, cela ne serait pas le cas. Notez également qu’il n’est pas nécessaire d’appeler glDisable à la fin des appels de fonction, glPopAttrib fait le travail.

En ce qui concerne les performances, les frais généraux liés aux appels de fonction individuels à glEnable / glDisable sont minimes. Si vous devez gérer de nombreux états, vous devrez probablement créer votre propre gestionnaire d'état ou passer de nombreux appels à glGetInteger ... et agir en conséquence. Les machines et le flux de contrôle ajoutés pourraient rendre le code moins transparent, plus difficile à déboguer et plus difficile à gérer. Ces problèmes peuvent rendre plus difficiles d'autres optimisations plus fructueuses.

La pile d'attribution peut aider à conserver des couches d'abstraction et à créer des régions d'isolation.

glPushAttrib manpage

Tout d’abord, quelle version d’OpenGL utilisez-vous? Et quelle génération de matériel graphique votre groupe cible a-t-il? Sachant cela, il serait plus facile de donner une réponse plus correcte. Ma réponse suppose OpenGL 2.1.

OpenGL est une machine à états, ce qui signifie que chaque fois qu'un état est modifié, cet état est rendu "courant". jusqu’à ce qu’il soit à nouveau modifié explicitement par le programmeur avec un nouvel appel API OpenGL. Des exceptions à cette règle existent, telles que les appels de tableau d'état client rendant la couleur de sommet actuelle non définie. Mais ce sont les exceptions qui définissent la règle.

" une fois au début de l'application " Cela n'a pas beaucoup de sens, car il est parfois nécessaire de détruire votre contexte OpenGL pendant que l'application est toujours en cours d'exécution. Je suppose que vous voulez dire juste après chaque création de fenêtre. Cela fonctionne pour l'état que vous n'avez pas besoin de changer plus tard. Exemple: si tous vos appels de dessin utilisent les mêmes données de tableau de sommets, vous n'avez pas besoin de les désactiver avec glDisableClientState par la suite.

De nombreux états d'activation / désactivation sont associés à l'ancien pipeline à fonction fixe. La rédemption facile pour ceci est: Utilisez des shaders! Si vous ciblez une génération de cartes d’au plus cinq ans, cela imitera probablement le pipeline à fonction fixe avec des shaders. En utilisant des shaders, vous avez un contrôle plus ou moins total de ce qui se passe pendant les étapes de transformation et de rastérisation, et vous pouvez créer vos propres "états". avec des uniformes, qui sont très bon marché pour changer / mettre à jour.

Le fait de savoir qu'OpenGL est une machine à état, comme je l'ai dit plus haut, devrait indiquer clairement qu'il faut s'efforcer de limiter les changements d'état au minimum, aussi longtemps que cela est possible. Cependant, il y a très probablement d'autres facteurs qui ont une incidence sur les performances bien plus que l'activation / la désactivation des appels d'état. Si vous voulez en savoir plus, lisez-le.

Le coût de l'état non associé aux anciens appels d'état à fonction fixe et qui n'est pas un simple état d'activation / désactivation peut différer considérablement en termes de coût. En particulier, les shaders de liaison et les noms de liaison ("noms" de textures, programmes, objets tampons) sont généralement assez coûteux. C'est pourquoi beaucoup de jeux et d'applications ont l'habitude de trier l'ordre d'affichage de leurs maillages en fonction de la texture. De cette façon, ils n'ont pas à lier deux fois la même texture. De nos jours cependant, il en va de même pour les programmes de shader. Vous ne voulez pas lier deux fois le même programme de shader si vous n’y êtes pas obligé. De plus, toutes les fonctionnalités d'une version OpenGL particulière ne sont pas accélérées matériellement sur toutes les cartes, même si les fournisseurs de ces cartes affirment qu'elles sont compatibles avec OpenGL. Etre conforme signifie qu'ils respectent les spécifications, mais pas nécessairement qu'ils exécutent tous les tests de manière efficace. Certaines fonctions telles que glHistogram et glMinMax de GL__ ARB __imaging doivent être rappelées à cet égard.

Conclusion: À moins d’une raison évidente de ne pas le faire, utilisez des shaders! Cela vous évite de nombreux appels d'état non nécessaires puisque vous pouvez utiliser des uniformes à la place. Les shaders OpenGL existent depuis environ six ans, vous savez. En outre, la surcharge de l'activation / désactivation des modifications d'état peut être un problème, mais l'optimisation d'autres modifications d'état plus coûteuses présente généralement un avantage supplémentaire, comme glUseProgram, glCompileShader, glLinkprogram, glBindBuffer et glBindTexture.

P.S: OpenGL 3.0 a supprimé les appels d'activation / désactivation de l'état du client. Ils sont implicitement activés car les tableaux de dessin sont le seul moyen de dessiner dans cette version. Le mode immédiat a été supprimé. Les appels gl..Pointer ont également été supprimés, car il suffit de disposer de glVertexAttribPointer.

Une règle empirique qui m'a été enseignée disait qu'il était presque toujours moins cher d'activer / désactiver à volonté plutôt que de vérifier l'état actuel et de ne changer que si nécessaire.

Cela dit, la réponse de Marc est quelque chose qui devrait absolument fonctionner.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top