IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Apprendre OpenGL moderne

Quatrième partie : OpenGL avancé


précédentsommairesuivant

IV. Suppression de faces (culling)

Essayez de visualiser mentalement un cube et comptez le nombre de faces que vous pouvez voir, et ce, dans n’importe quelle direction. Si votre imagination n’est pas trop débordante, vous devriez en compter au maximum trois. Pourquoi donc essayerons-nous de dessiner les trois autres faces alors qu’elles ne sont mêmes pas visibles ? Si nous pouvions les ignorer d’une façon ou d’une autre, nous économiserions plus de 50 % du temps d’exécution du fragment shader.

Nous disons plus de 50 % et non 50 %, car sous certains angles, seules deux, voire une seule face, sont visibles. Dans ce cas-là, nous évitons plus de 50 % du calcul.

C’est une superbe idée, mais il y a un problème à résoudre : comment savoir si la face d’un objet est visible ou non pour le spectateur ?
En imaginant n’importe quelle forme fermée, chacune de ses faces possède deux côtés. Chaque côté sera soit face au spectateur, soit dans l’autre sens. Quid de ne dessiner que les faces qui sont réellement dirigées vers le spectateur ?

C’est exactement ce que fait la technique de suppression des faces arrière (backface culling). OpenGL vérifie si les faces avant sont orientées vers le spectateur et ne dessine que celles-ci tout en ignorant celles qui sont orientées dans l’autre sens. Ainsi, on évite beaucoup d’appels au fragment shader (qui sont coûteux !). Nous devons indiquer à OpenGL quelles sont les faces avant et celles qui sont des faces arrière. Pour cela, OpenGL utilise une astuce en analysant l’ordre des sommets (winding order).

IV-A. Ordonnancement des sommets

Lorsque nous définissons les sommets d’un triangle, nous le faisons dans un certain ordre : soit dans le sens des aiguilles d’une montre, soit dans le sens inverse. Chaque triangle contient trois sommets et nous spécifions ces trois sommets dans l’un des sens suivant :

Ordre de définition des sommets d'un triangle OpenGL

Comme vous pouvez le voir dans l’image, nous définissons d’abord le sommet 1 et nous pouvons définir ensuite soit le sommet 2, soit le 3. Ce choix détermine l’ordre des sommets du triangle. Le code suivant met en application ce concept :

 
Sélectionnez
float vertices[] = {
    // sens horaire (clockwise)
    vertices[0], // sommet 1
    vertices[1], // sommet 2
    vertices[2], // sommet 3
    // sens anti-horaire (counter-clockwise)
    vertices[0], // sommet 1
    vertices[2], // sommet 3
    vertices[1]  // sommet 2  
};

Chaque ensemble de trois sommets formant un triangle contient donc un ordre. OpenGL utilise cette information lors du rendu de la primitive pour déterminer si le triangle fait face ou non à la caméra. Par défaut, les triangles avec les sommets ordonnés dans le sens inverse des aiguilles d’une montre sont traités comme la face avant du triangle.

Lors de la définition de vos sommets, vous devez visualiser le triangle comme s’il vous faisait face, afin que chaque triangle ait ses sommets dans le sens inverse des aiguilles d’une montre. Ainsi, l’ordre des sommets est calculé pendant la rasterization, donc après exécution du vertex shader. Les sommets sont ainsi vus comme du point de vue du spectateur.

Tous les sommets du triangle auxquels le spectateur fait face sont évidemment dans le bon sens, mais les sommets des triangles de l’autre côté du cube sont maintenant affichés d’une telle manière que l’ordre des sommets est différent. Le résultat est que les triangles devant nous présentent leur face avant alors que les triangles à l’arrière présentent leur face arrière. Voici un schéma pour montrer cela :

Image du spectateur voyant l'avant ou l'arrière des triangles

Dans les données des sommets, nous aurions dû définir des triangles avec le sens anti-horaire (le triangle de devant dans le sens 1, 2, 3 et le triangle à l’arrière avec le sens 1, 2 et 3, si nous voulions voir le triangle depuis l’avant). Par contre, du point de vue du spectateur, le triangle de derrière est affiché dans le sens inverse des aiguilles d’une montre si nous le dessinons dans l’ordre 1, 2, 3. Même si nous avons spécifié le triangle de derrière dans le sens anti-horaire, il est maintenant affiché dans le sens horaire. C’est exactement ce que nous voulons : éliminer (cull) les faces non visibles.

IV-B. Élimination des faces

Au début du tutoriel, nous avons dit qu’OpenGL peut éliminer la face arrière des triangles. Maintenant que nous savons comment définir l’ordre des sommets, nous pouvons commencer à utiliser l’option d’élimination des faces d’OpenGL, qui est désactivée par défaut.

Les données des sommets du cube du tutoriel précédent n’ont pas été définies en tenant compte de l’ordre des sommets. Du coup, j’ai mis en ligne les données définissant les sommets dans le sens inverse des aiguilles d’une montre. C’est une bonne pratique d’essayer de voir que ces sommets sont tous définis dans cet ordre.

Pour activer l’élimination des faces, nous devons juste activer l’option OpenGL GL_CULL_FACE :

 
Sélectionnez
glEnable(GL_CULL_FACE);

À partir de maintenant, toutes les faces qui ne sont pas des faces avant seront éliminées (essayez d’entrer dans le cube et voir l’intérieur des faces qui sont évidemment éliminées). Actuellement, on économise 50 % des calculs sur le rendu des fragments, mais notez que cela fonctionne uniquement avec les formes fermées, comme les cubes. Afin de voir les deux côtés, nous devons désactiver l’élimination des faces. C’est le cas pour les feuilles du tutoriel précédent.

OpenGL permet de changer quelles faces à éliminer. Par exemple, si nous voulons éliminer les faces avant et non les faces arrière. Nous pouvons définir ce comportement avec la fonction glCullFace() :

 
Sélectionnez
glCullFace(GL_FRONT);

La fonction glCullFace() a trois options possibles :

  • GL_BACK : élimine les faces arrière ;
  • GL_FRONT : élimine les faces avant ;
  • GL_FRONT_AND_BACK : éliminent les faces avant et arrière.

La valeur initiale de glCullFace() est GL_BACK. En plus de spécifier la face à éliminer, nous pouvons aussi indiquer à OpenGL que nous préférons considérer les faces définies dans le sens des aiguilles d’une montre comme face avant à la place des faces dans le sens anti-horaire avec la fonction glFrontFace() :

 
Sélectionnez
glFrontFace(GL_CCW);

La valeur par défaut est GL_CCW pour les faces dans le sens anti-horaire. L’autre option étant GL_CW.

Pour faire un simple test, nous pouvons inverser l’ordre en indiquant à OpenGL que les faces avant sont maintenant définie par l’ordre horaire à la place du sens anti-horaire.

 
Sélectionnez
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);

Le résultat est que seules les faces arrière sont affichées :

Image de l'élimination des faces avec l'ordre anti-horaire, et élimination des faces avant

Notez que vous pouvez créer le même effet en éliminant les faces avant avec l’ordonnancement anti-horaire par défaut.

 
Sélectionnez
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);

Comme vous pouvez le constater, l’élimination des faces est un outil puissant pour augmenter les performances de vos applications OpenGL avec un effort minimal. Vous devez auparavant déterminer les objets qui pourraient bénéficier de l’élimination des faces et ceux qui ne peuvent être optimisés.

IV-C. Exercices

  • Pouvez-vous redéfinir les données des sommets en spécifiant chaque triangle dans le sens horaire, puis afficher la scène en définissant les triangles horaires comme faces avant ? Solution.

IV-D. Remerciements

Ce tutoriel est une traduction réalisée par Alexandre Laurent dont l’original a été écrit par Joey de Vries et qui est disponible sur le site Learn OpenGL.


précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2019 Joey de Vries. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.