Éclairage personnalisé dans Shader Graph : Élargir vos graphiques en 2019

ALEX LINDMAN / UNITY TECHNOLOGIESContributor
Jul 31, 2019|13 Min
Éclairage personnalisé dans Shader Graph : Élargir vos graphiques en 2019
Cette page a été traduite automatiquement pour faciliter votre expérience. Nous ne pouvons pas garantir l'exactitude ou la fiabilité du contenu traduit. Si vous avez des doutes quant à la qualité de cette traduction, reportez-vous à la version anglaise de la page web.

Avec la sortie de Unity Editor 2019.1, le package Shader Graph est officiellement sorti de la prévisualisation ! Aujourd'hui, dans la version 2019.2, nous apportons encore plus de caractéristiques et de fonctionnalités à Shader Graph.

Qu'est-ce qui change en 2019 ?
Amélioration des fonctions personnalisées et des sous-graphes

Pour maintenir un code personnalisé à l'intérieur de votre graphique de shaders, vous pouvez désormais utiliser notre nouveau nœud de fonctions personnalisées. Ce nœud vous permet de définir vos propres entrées et sorties personnalisées, de les réorganiser et d'injecter des fonctions personnalisées soit directement dans le nœud lui-même, soit en faisant référence à un fichier externe.

Les sous-graphes ont également été améliorés : vous pouvez désormais définir vos propres sorties pour les sous-graphes, avec différents types, des noms personnalisés et des ports réorganisables. En outre, le tableau noir des sous-graphes prend désormais en charge tous les types de données que le graphique principal prend en charge.

Modes de couleur et modes de précision

L'utilisation du Shader Graph pour créer des shaders puissants et optimisés vient de devenir un peu plus facile. Dans la version 2019.2, vous pouvez désormais définir manuellement la précision des calculs dans votre graphique, soit pour l'ensemble du graphique, soit pour chaque nœud. Nos nouveaux modes de couleur permettent de visualiser rapidement et facilement le flux de précision, la catégorie de nœuds ou d'afficher des couleurs personnalisées pour votre propre usage !

Voir la documentation Shader Graph pour plus d'informations sur ces nouvelles fonctionnalités.

Exemple de projet

Pour vous aider à utiliser le nouveau flux de travail des fonctions personnalisées, nous avons créé un projet d'exemple accompagné d'instructions étape par étape. Téléchargez le projet à partir de notre dépôt et suivez-le ! Ce projet vous montrera comment utiliser le nœud Custom Function pour écrire des shaders d'éclairage personnalisés pour le Lightweight Render Pipeline (LWRP). Si vous souhaitez suivre le processus en utilisant un nouveau projet, assurez-vous que vous utilisez l'éditeur 2019.2 et la version 6.9.1 du paquet LWRP ou une version plus récente.

Obtenir des données de la lumière principale

Pour commencer, nous devons obtenir des informations de la lumière principale de notre scène. Commencez par sélectionner Create > Shader > Unlit Graph pour créer un nouveau graphique d'ombrage non éclairé. Dans le menu Créer un nœud, localisez le nouveau nœud Fonction personnalisée et cliquez sur l'icône en forme de roue dentée en haut à droite pour ouvrir le menu du nœud.

Dans ce menu, vous pouvez ajouter des entrées et des sorties. Ajoutez deux ports de sortie pour Direction et Couleur, et sélectionnez Vecteur 3 pour les deux. Si vous voyez un drapeau d'erreur "undeclared identifier", ne vous inquiétez pas ; cela disparaîtra lorsque nous commencerons à ajouter notre code. Dans le menu déroulant Type, sélectionnez Chaîne. Mettez à jour le nom de votre fonction - dans cet exemple, nous utilisons "MainLight". Nous pouvons maintenant commencer à ajouter notre code personnalisé dans la zone de texte.

Image

Tout d'abord, nous allons utiliser un drapeau appelé `#ifdef SHADERGRAPH_PREVIEW`. Parce que les boîtes de prévisualisation sur les nœuds n'ont pas accès aux données lumineuses, nous devons indiquer au nœud ce qu'il doit afficher sur les boîtes de prévisualisation dans le graphique. `#ifdef` indique au compilateur d'utiliser un code différent dans des situations différentes. Commencez par définir vos valeurs de repli pour les ports de sortie.

Ensuite, nous utiliserons `#else` pour indiquer au compilateur ce qu'il doit faire lorsqu'il n'y a pas de prévisualisation. C'est là que nous obtenons nos données lumineuses. Utilisez la fonction intégrée `GetMainLight()` du paquetage LWRP. Nous pouvons utiliser ces informations pour attribuer les sorties Direction et Couleur. Votre fonction personnalisée devrait maintenant ressembler à ceci :

Il est conseillé d'ajouter ce nœud à un groupe afin de pouvoir noter ce qu'il fait. Cliquez avec le bouton droit de la souris sur le nœud, sélectionnez Créer un groupe à partir de la sélection, puis renommez le titre du groupe pour décrire l'activité de votre nœud. Ici, nous avons saisi "Get Main Light".

Image

Maintenant que nous disposons des données relatives à la lumière, nous pouvons calculer l'ombrage. Nous allons commencer par un éclairage lambertien standard, ce qui signifie que nous allons prendre le produit du point du vecteur normal du monde et de la direction de la lumière. Passez-la dans un nœud de saturation et multipliez-la par la couleur de la lumière. Branchez-le dans le port Couleur du nœud Unlit Master, et votre aperçu devrait être mis à jour avec un ombrage personnalisé !

Image
Utilisation du mode fichier de la fonction personnalisée

Puisque nous savons maintenant comment obtenir des données lumineuses à l'aide du nœud Custom Function, nous pouvons développer notre fonction. La fonction suivante permet d'obtenir les valeurs d'atténuation de la lumière principale en plus de la direction et de la couleur. Comme il s'agit d'une fonction plus complexe, passons en mode fichier et utilisons un fichier d'inclusion HLSL. Cela vous permet de créer des fonctions plus compliquées dans un éditeur de code approprié avant de les injecter dans le graphique. Cela signifie également que nous disposons d'un emplacement unifié pour déboguer le code. Commencez par ouvrir le fichier include `CustomLighting` dans le dossier Assets > Include du projet. Pour l'instant, nous nous concentrerons uniquement sur la fonction `MainLight_half`. La fonction se présente comme suit :

Cette fonction inclut de nouvelles données d'entrée et de sortie, retournons donc à notre nœud de fonction personnalisée et ajoutons-les. Ajouter deux nouvelles sorties pour DistanceAtten (atténuation de la distance) et ShadowAtten (atténuation de l'ombre). Ensuite, ajoutez la nouvelle entrée pour WorldPos (position du monde) . Maintenant que nous avons nos entrées et sorties, nous pouvons référencer le fichier include. Changez le menu déroulant Type en Fichier. Dans l'entrée Source, naviguez jusqu'au fichier d'inclusion et sélectionnez l'actif à référencer. Nous devons maintenant indiquer au nœud quelle fonction utiliser. Dans le champ Nom, nous avons saisi "MainLight".

Image

Vous remarquerez que le fichier include contient `_half` à la fin du nom de la fonction, ce qui n'est pas le cas de notre option de nom. En effet, le compilateur de Shader Graph ajoute le format de précision à chaque nom de fonction. Puisque nous définissons notre propre fonction, nous avons besoin du code source pour indiquer au compilateur le format de précision utilisé par notre fonction. Dans le nœud, cependant, nous n'avons besoin de référencer que le nom de la fonction principale. Vous pouvez créer une copie de la fonction qui utilise des valeurs "float" pour compiler en mode de précision "float". Le mode de couleur "Précision" vous permet de suivre facilement la précision définie pour chaque nœud du graphique, le bleu représentant la valeur flottante et le rouge la moitié.

Nous voudrons probablement réutiliser cette fonction ailleurs, et la façon la plus simple de rendre cette fonction personnalisée réutilisable est de l'envelopper dans un sous-graphe. Sélectionnez le nœud et son groupe, puis cliquez avec le bouton droit de la souris pour trouver Convert to Sub-graph (Convertir en sous-graphe). Nous avons appelé le nôtre "Get Main Light". Dans le sous-graphe, il suffit d'ajouter les ports de sortie requis au nœud de sortie du sous-graphe et de brancher la sortie du nœud sur la sortie du sous-graphe. Ensuite, nous ajouterons un nœud de position mondiale à brancher sur l'entrée.

Image

Enregistrez le sous-graphe et revenez à notre graphique non éclairé. Nous allons ajouter deux nouveaux nœuds de multiplication à notre logique existante. Il faut d'abord multiplier les deux sorties d'atténuation. Il faut ensuite multiplier ce résultat par la couleur de la lumière. Nous pouvons multiplier ce chiffre par NdotL pour calculer correctement l'atténuation dans notre ombrage de base.

Image
Création d'un nuanceur spéculaire direct

Le shader que nous avons créé est parfait pour les objets mats, mais que faire si nous voulons de la brillance ? Nous pouvons ajouter nos propres calculs spéculaires à notre nuanceur ! Pour cette étape, nous utiliserons un autre nœud de fonction personnalisée enveloppé dans un sous-graphe, appelé Direct Specular. Regardez à nouveau le fichier include `CustomLighting`, et voyez que nous faisons maintenant référence à une autre fonction du même fichier :

Cette fonction effectue des calculs spéculaires simples. Si vous êtes curieux, vous pouvez en savoir plus à ce sujet ici. Le sous-graphe de cette fonction comprend également des entrées sur le tableau noir :

Image

Assurez-vous que votre nouveau nœud dispose de tous les ports d'entrée et de sortie appropriés pour correspondre à la fonction. L'ajout de propriétés au tableau noir est simple : il suffit de cliquer sur l'icône Ajouter (+) en haut à droite et de sélectionner le type de données. Double-cliquez sur la pilule pour renommer l'entrée et faites glisser la pilule pour l'ajouter au graphique. Enfin, mettez à jour le port de sortie de votre sous-graphe et enregistrez-le.

Maintenant que le calcul spéculaire est configuré, nous pouvons retourner au graphique non éclairé et l'ajouter via le menu Create Node (Créer un nœud). Connectez la sortie Atténuation à l'entrée Couleur du sous-graphe spéculaire direct. Ensuite, connectez la sortie Direction de la fonction Get Main Light à l'entrée Direction du sous-graphe spéculaire. Ajoutez le résultat de NdotL*Atténuation à la sortie du sous-graphe spéculaire direct et insérez-le dans la sortie Couleur.

Image

Maintenant, nous avons un peu d'éclat !

Travailler avec des éclairages multiples

La lumière principale du LWRP fait référence à la lumière directionnelle la plus brillante par rapport à l'objet, qui est généralement le soleil. Afin d'améliorer les performances sur le matériel de base, le LWRP calcule séparément la lumière principale et toutes les lumières supplémentaires. Pour s'assurer que notre shader calcule correctement pour toutes les lumières de la scène, et pas seulement pour la lumière directionnelle la plus brillante, vous devez créer une boucle dans votre fonction. Pour obtenir les données supplémentaires sur la lumière, nous avons utilisé un nouveau sous-graphe pour envelopper un nouveau nœud de fonction personnalisée. Jetez un œil à la fonction `AdditionalLight_float` dans le fichier include `CustomLighting` :

Comme précédemment, utilisez la fonction `AdditionalLights` dans la référence de fichier du nœud Custom Function, et assurez-vous que vous avez créé toutes les entrées et sorties appropriées. Veillez à exposer la couleur spéculaire et la douceur spéculaire dans le tableau noir du sous-graphe dans lequel le nœud est intégré. Utilisez les nœuds Position, Vecteur normal et Direction de la vue pour insérer la position du monde, la normale du monde et la direction de la vue de l'espace mondial dans le sous-graphe.

Après avoir mis en place la fonction, utilisez-la ! Tout d'abord, prenez votre graphique principal non éclairé de l'étape précédente et réduisez-le à un sous-graphe. Sélectionnez les nœuds et cliquez avec le bouton droit de la souris sur Convertir en sous-graphe. Retirez le dernier nœud Add et branchez les sorties dans les ports de sortie du sous-graphe. Nous vous recommandons de créer également des propriétés d'entrée pour Specular et Smoothness.

Image

Vous pouvez maintenant combiner vos calculs de lumière principale et vos calculs de lumière additionnelle. Dans le graphique principal non éclairé, créez un nouveau nœud pour les calculs de la lumière additionnelle, à côté des calculs de la lumière principale. Additionnez les sorties Diffuse et Specular de la lumière principale et des lumières additionnelles. C'est très simple !

Image
Création d'un nuanceur Toon simple
Image

Vous savez maintenant comment obtenir les données de tous les feux d'une scène pour un projet LWRP, mais que pouvez-vous en faire ? L'une des utilisations les plus courantes de l'éclairage personnalisé dans les shaders est un shader toon classique !

Avec toutes les données relatives à la lumière, la création d'un shader de toon est assez simple. Tout d'abord, prenez tous les calculs de lumière que vous avez effectués jusqu'à présent et enveloppez-les une fois de plus dans un sous-graphe. Cela facilitera la lisibilité de l'ombre finale. N'oubliez pas de supprimer le dernier nœud Add et d'alimenter Diffuse et Specular dans des ports de sortie distincts sur le nœud de sortie Sub Graph.

Il existe de nombreuses méthodes pour créer l'ombrage des toons, mais dans cet exemple, nous utilisons l'intensité lumineuse pour rechercher des couleurs à partir d'une texture de rampe. Cette technique est généralement appelée éclairage par rampe. Nous avons inclus quelques exemples du type de texture nécessaire pour l'éclairage par rampes dans le projet d'exemple. Vous pouvez également échantillonner un gradient pour utiliser des rampes dynamiques dans l'éclairage par rampe. La première étape consiste à convertir l'intensité du diffus et du spéculaire des valeurs RVB en valeurs HSV. Cela nous permet d'utiliser l'intensité de la couleur de la lumière (les valeurs HSV) pour déterminer la luminosité du shader, et nous aide à échantillonner la texture à différents endroits le long de l'axe horizontal de l'objet. Utiliser une valeur statique pour le canal Y des UV afin de déterminer, de haut en bas, quelle partie de l'image doit être échantillonnée. Vous pouvez utiliser cette valeur statique comme index pour référencer plusieurs rampes d'éclairage du projet dans une seule texture.

Image

Une fois les valeurs UV définies, utilisez un nœud Sample Texture 2D LOD pour échantillonner la texture de la rampe. Le LOD de l'échantillon est important ; si nous utilisons un nœud 2D d'échantillon de texture ordinaire, la rampe est automatiquement modifiée dans une scène, et les objets plus éloignés auront des comportements différents en matière d'éclairage. L'utilisation d'un nœud Sample Texture 2D LOD nous permet de déterminer manuellement le niveau de mip. En outre, comme la texture de la rampe n'a que 2 pixels de hauteur, nous avons créé notre propre état d'échantillonnage pour les textures. Pour s'assurer que la texture est échantillonnée correctement, nous réglons le filtre sur Point et l'enveloppement sur Clamp. Nous avons exposé cette propriété dans le tableau noir afin que vous puissiez modifier les paramètres en cas de changement de l'actif de texture.

Image

Enfin, nous multiplions l'échantillon de rampe issu des calculs de diffusion par une propriété de couleur, Diffuse, afin de pouvoir modifier les couleurs de l'objet. Ajoutez l'échantillon de rampe des calculs spéculaires à la sortie Diffuse, et insérez la couleur finale dans le nœud Maître.

Image
Extension de l'éclairage personnalisé
Image

Cette simple configuration d'éclairage personnalisée peut être étendue et appliquée à une grande variété de cas d'utilisation dans toutes sortes de scènes. Dans notre projet d'exemple, nous avons inclus une scène complète configurée avec des shaders qui utilisent notre configuration d'éclairage personnalisée. Il contient également des animations de vertex, une approximation simple de la diffusion sous la surface, ainsi que des réfractions et des colorations qui utilisent la profondeur. Téléchargez le projet et consultez nos exemples d'actifs pour explorer des méthodes plus avancées !

Continuez à apprendre !

Si vous voulez discuter de Shader Graph, et des shaders que vous pouvez créer avec, venez faire un tour dans notre tout nouvel espace forum! Vous pouvez également trouver des membres de la communauté et (parfois) quelques développeurs dans le Discord de la communauté!

N'oubliez pas de garder un œil sur les enregistrements de nos sessions SIGGRAPH 2019, où nous allons encore plus en détail sur l'utilisation de Shader Graph pour l'éclairage personnalisé !