Utiliser plusieurs shaders

53

J'étudie actuellement les shaders ouverts, mais je ne peux pas comprendre quelque chose: comment appliquer différents shaders aux objets, par exemple une théière rendue avec toon shader et une autre dans la même scène en utilisant une surface très réfléchissante et d'autres distordues une fonction de bruit, comme dans cette vidéo

http://www.youtube.com/watch?v=1ogg4ZfdBqU

Une autre application consiste à appliquer un bloom shader dans une scène puis un flou de mouvement par la suite. Comment obtenir ces effets lorsque vous ne pouvez avoir qu'un seul vertex shader et un fragment shader? Existe-t-il une astuce telle que l’utilisation de plusieurs programmes de shader?

ibrabeicker
la source
Re bonnes réponses de Nathan et David, c’est la raison pour laquelle vous voyez le terme rendre passe ou passe shader ; plusieurs passes sont nécessaires pour composer l'image / le cadre final. Une des raisons pour lesquelles le traitement du processeur graphique est devenu si parallèle et donc si rapide est la nécessité de faire plusieurs passes par image. Retournez aux moteurs de rendu logiciel Quake II ou Half Life pour vous rappeler à quel point les passes de shader d'amour ajoutent à l'expérience graphique 3D.
Ingénieur

Réponses:

59

La réponse est simple: vous les changez entre chaque appel de tirage. Définissez un shader, dessinez une théière, définissez un autre shader, dessinez une autre théière.

Pour des tâches plus complexes où vous devez appliquer plusieurs shaders à un seul objet, tel que le flou, la lueur, etc. Vous avez essentiellement tout rendu en texture (s). Ensuite, vous rendez un quad sur tout votre écran avec cette texture appliquée tout en utilisant un autre shader.

Par exemple, si vous souhaitez créer un effet de rayonnement, vous devez d'abord rendre votre scène normale, puis ne restituer que la silhouette colorée du contenu que vous souhaitez appliquer à une texture, puis basculer vers un arrière-plan flou et restituer votre rendu. quad avec cette texture attachée sur votre scène non-rougeoyante.

Il existe une autre technique appelée Ombrage différé, qui consiste à rendre la scène sans éclairage et à l'appliquer ultérieurement dans l'espace écran. L'objectif principal est de réduire les dépenses d'éclairage par pixel.

Normalement, vous rendez un tampon de couleur qui est affiché à l'écran. Avec l'ombrage différé, vous créez à la place un tampon de couleur, ainsi qu'un tampon de profondeur et de normales dans une passe de shader (vous pouvez stocker les vecteurs normaux et la profondeur dans une texture, comme avec les mappages de hauteur et de normale).

Cela signifie que, pour chaque pixel, vous connaissez la position de la partie la plus proche de la géométrie non transparente (profondeur ou distance de l'œil), la couleur et la normale. De ce fait, vous pouvez appliquer un éclairage à chaque pixel de l'écran plutôt qu'à chaque pixel visible de chaque objet que vous rendez. N'oubliez pas que certains objets seront dessinés au-dessus d'autres objets si la scène n'est pas parfaitement restituée dans l'ordre inverse.

Pour les ombres, vous ne restituez que le tampon de profondeur du point de vue de votre lumière, puis utilisez ces informations de profondeur pour déterminer l’endroit où la lumière s’éclaire. Cela s'appelle le mappage des ombres (il existe également une autre approche appelée volumes des ombres qui élabore une silhouette de la géométrie et l’extrude, mais vous utiliserez toujours des ombreurs.).

Avec OpenGL (3.0+) plus moderne, vous utilisez un objet Framebuffer auquel sont attachés des objets Renderbuffers. Depuis les renderbuffers peuvent être traités comme une texture. Vous pouvez faire des choses comme avoir un rendu de shader à plusieurs rendus différents (de sorte que vous n’ayez pas à rendre votre texture à vos normales puis aux composants de lueur) mais la pratique sous-jacente reste la même.

Il est également souhaitable de minimiser autant que possible le nombre de commutateurs de shader pour économiser sur les frais généraux. Ainsi, certains moteurs regrouperont tout avec le même matériau afin que tout puisse être dessiné en même temps.

David C. Bishop
la source
16

Vous ne faites que lier un shader, rendre tous les objets à l'aide de ce shader, puis lier le shader suivant, rendre les objets à l'aide de celui-ci, etc.

Vous pouvez avoir autant d'objets de shader (les shaders chargés en mémoire et compilés) que vous le souhaitez. un seul peut être lié (actif) à la fois.

Nathan Reed
la source
5
En termes d’implémentation, j’utilise glUseProgram (1) et glUseProgram (2) pour modifier les shaders? Combien cela coûte-t-il pour la performance?
ibrabeicker
4
C'est un coût non négligeable (bien que moins sur les GPU récents que sur les précédents). C'est pourquoi la plupart des gens trient leurs objets par matériau, rendant tous les objets du même matériau ensemble. Mais vous pouvez certainement vous permettre de modifier les programmes des dizaines, des centaines de fois par image, voire davantage.
Nathan Reed
9

Utiliser plus d'un shader dans une scène est assez simple; changez le shader, définissez les valeurs correspondantes, puis restituez l'objet.

Attention, cependant, le changement de shaders peut être coûteux; Il existe plusieurs façons de réduire cet impact tout en obtenant tous les effets souhaités.

La première méthode, et généralement la plus souhaitable, consiste à ajouter les fonctionnalités de toutes vos techniques de shader à un seul shader et à utiliser les conditions que vous avez définies pour rendre chaque objet de manière différente avec le même shader. Je ne connais pas les shaders OpenGL et GLSL, mais avec les shaders HLSL et DirectX, ceux-ci peuvent être regroupés en une "technique" et vous pouvez définir la technique au lieu de changer de shader. Cela vous permet d’avoir plusieurs shaders différents de pixels et de sommets dans le même fichier.

La deuxième façon de réduire l'impact sur les performances consiste à définir le shader, à rendre chaque objet utilisant ce shader, puis à le répéter. En d'autres termes, le traitement par lots de votre rendu.

Si vous souhaitez appliquer deux effets différents au même objet (c'est-à-dire appliquer un shader toon puis un éclairage), vous pouvez le faire de deux manières différentes. La première consiste à écrire un shader qui applique plusieurs effets dans la même fonction. La deuxième méthode consiste à rendre le modèle une fois avec chaque shader et à mélanger les résultats en définissant différentes options de fusion. Cependant, cela représente beaucoup plus de travail et n'est pas réalisable dans toutes les circonstances. Par conséquent, la meilleure option consiste à combiner tous vos effets dans un shader.

OriginalDaemon
la source
7

Une autre manière de le faire est la sous-routine glsl, dans laquelle chaque type de shader est défini dans une fonction. Dans l'application OpenGL, nous pouvons définir le sous-programme actuel, dessiner le sommet d'un tampon, modifier le sous-programme et rendre un autre tampon

ibrabeicker
la source
4
Cela nécessite du matériel compatible avec GL 4.x, qui est un matériel de classe DX11.
Nicol Bolas