Faire un AOV d’occlusion avec la DiffuseColor dans Guerilla
Par Narann le samedi, 9 octobre 2021, 23:29 - Infographie 3D - Boulot - Lien permanent
Il y a plein de façons de faire de l’ambiant occlusion. :hehe: Certains sortent cette passe au moment du lighting pour donner de la flexibilité au compo ; pour assombrir les creux. D’autres sortent cette passe avant l’étape de rendu, au moment de l’animation, voir du layout ; pour du contrôle qualité. Dans chaque situation, le contenu de la passe d’ambiant occlusion est adapté au besoin ; pour du compo il faut qu’elle soit en niveaux de gris, pour du contrôle qualité on peut afficher chaque objet avec une couleur particulière, etc.
Quand le lookdev des assets est (enfin) disponible, il peut être intéressant d’avoir une ambiant occlusion générée avec les textures de lookdev plutôt que des couleurs uniformes. C’est ce que nous allons faire dans ce billet. :bravo:
Méthode de base
Avant de faire des choses compliquées, on peut s’appuyer sur ce que Guerilla propose, à savoir les AOVs Occlusion et Albedo. Voici une scène éclairée avec amour :petrus: :
Le lookdev des objets, c’est juste une texture colorée différente mise dans l’attribut « DiffuseColor » de leur « Surface2 » respectif. :siffle:
On lui ajoute les deux AOVs, Occlusion et Albedo :
Utiliser cette méthode implique de devoir recompositer les deux images en sortie de Guerilla (via un précomp, par exemple), mais ça nous oblige à gérer un processus externe. Ce serait quand même plus simple si Guerilla pouvait sortir l’ambiant occlusion en utilisant directement l’Albedo. :reflechi:
Ce n’est pas possible directement (on ne peut pas utiliser un AOV dans un autre AOV), mais on peut s’en rapprocher de façon détournée (disons).
Logique de récupération des shaders dans Guerilla
Petit rappel au cas où vous ne seriez pas au courant. :mayaProf:
Quand vous assignez un material dans un RenderGraph, Guerilla n’assigne en fait qu’un nom (ici, « Surface2 ») à l’attribut shader.surface. Pour vous donner une idée, sélectionnez un objet, faites « Shift+D » et regardez votre console pour voir la liste des attributs qui seront envoyées au moteur :
...
shade.opacity: 1
shade.opacitybakeres: {256,256}
shader.displacement: ""
shader.surface: "Surface2" << Notre assignation de shader de surface, ici.
shader.volume: ""
shade.scale: 1
shade.subshadersuseexternal: false
...
Au moment de l’envoi au moteur, Guerilla va chercher le material auquel correspond ce nom en suivant une logique assez particulière :
- Votre scène.
- La librairie.
Pour faire court, si un material nommé « Surface2 » est présent à la racine de votre scène, il sera utilisé à la place du Surface2 de la librairie :
Ici, c’est le Surface2 à gauche qui sera envoyé au moteur, prenant le pas sur celui de la librairie, à droite. :tuComprendRien:
Et comme vous le savez sûrement, il est possible de modifier le material importé dans votre scène. Ces deux particularités permettent, finalement, d’éditer le comportement d’un shader pour toute la scène. :idee:
Donc si on modifie notre Surface2 importé localement afin que sa seule sortie soit une occlusion multipliée par son attribut DiffuseColor, le calcul d’illumination de tous les objets sera l’ambiant occlusion utilisant ses propres textures.
Faisons donc ça ! :youplaBoum:
Méthode avancée
Créez un shader Surface2 à la racine (« Ctrl+Espace », « surface2 », « Entrée ») :
Le shader s’importe à la racine de votre scène :
Entrez à l’intérieur et supprimez tout ce que vous y trouvez !
Notez qu’un bug est présent en version 2.3.0, il faut laisser le nœud « Surface » pour avoir un rendu correct. Ce bug est corrigé en version 2.3.1.
Ajouter un nœud AOV (« Ctrl+Espace », « aov », « Entrée ») :
Renommer « Value » par un nom perso « ColoredAO » :
Mettre un nœud « Occlusion » et le connecter à « ColoredAO » :
Dans la RenderPass, créez un AOV. Vous pouvez le nommer comme vous voulez :
Dans cet AOV, mettez Accepted expression à [Technical] Primary et Shader Color à ColoredAO :
Si vous rendez à ce stade, vous aurez une occlusion tout simple :
Mais ce qu’on veut, c’est de la couleur ! :perplex:
Pour ça, il faut renommer le paramètre responsable de la couleur (ici, blanche) pour qu’il utilise la « DiffuseColor ». Sélectionnez votre nœud « Occlusion » et renommez l’attribut « SkyColor » en « DiffuseColor » :
Puis cochez « Exposed » :
Notez que vous pouvez le faire en cliquant sur l’attribut du nœud, directement dans le graph :
Et sous vos yeux ébahis :
Que pour les « Surface2 » ?
Si vous n’overridez que le Surface2 sur votre scène de production, vous allez vite vous rendre compte que ça ne fonctionne pas sur beaucoup de surfaces. En effet, il faut faire cet override sur tous les types de shader que vous utilisez dans vos scènes. Avec un peu de chance ça devrait se résumer aux Hair, Curve et Eye.
Il faut adapter le nom de l’attribut pour chaque type de shader. Si dans le cas du « Surface2 », l’attribute « DiffuseColor » fera très certainement l’affaire, dans le cas du shader de Hair ou de Curve, vous utiliserez sûrement la « Color » ou la « RootColor », suivant votre workflow. :pasClasse:
Notez que vous pouvez aussi multiplier les couleurs vous-même si le cœur vous en dit (je n’ai jamais testé) :
Le cas du shader de Eye
Le cas du Eye shader est plus compliqué, car il ne dispose pas d’attribut de shader défini, comme le « DiffuseColor » du « Surface2 ». :bete:
Pour que ça fonctionne, il faut l’évaluer totalement. Pour cela, connectez directement l’Albedo à occlusion, comme ici :
Ceci évalue tout le shader des yeux, mais comme ils ne sont pas particulièrement coûteux, on peut se le permettre.
Voilà ! En espérant que ça serve à quelqu’un !
À très bientôt !