Création de traces dans la neige dans Unreal Engine 4


Si vous jouez à des jeux AAA modernes, vous avez peut-être remarqué une tendance à utiliser des paysages enneigés. Par exemple, ils sont dans Horizon Zero Dawn , Rise of the Tomb Raider et God of War . Dans tous ces jeux, la neige a une caractéristique importante: vous pouvez y laisser des traces!

Grâce à cette interaction avec l'environnement, l'immersion du joueur dans le jeu est améliorée. Cela rend l'environnement plus réaliste, et soyons honnêtes - c'est juste intéressant. Pourquoi passer de longues heures à créer un mécanicien curieux si vous pouvez simplement laisser le joueur tomber au sol et faire des anges de neige?

Dans ce didacticiel, vous apprendrez ce qui suit:

  • Créez des empreintes à l'aide de la capture de scène pour masquer des objets proches du sol
  • Utilisez un masque avec un matériau de terrain pour créer de la neige déformable
  • Pour optimiser, afficher les empreintes dans la neige uniquement à côté du joueur

Remarque: il est entendu que vous connaissez déjà les bases de l'utilisation d'Unreal Engine. Si vous êtes nouveau, consultez notre série de didacticiels Unreal Engine pour les débutants .

Se rendre au travail


Téléchargez le matériel pour ce tutoriel. Décompressez-les, accédez à SnowDeformationStarter et ouvrez SnowDeformation.uproject . Dans ce tutoriel, nous allons créer des traces à l'aide d'un personnage et de plusieurs cases.


Avant de commencer, vous devez savoir que la méthode de ce didacticiel n'enregistrera les traces que dans une zone donnée, et non dans le monde entier, car la vitesse dépend de la résolution du rendu cible.

Par exemple, si nous voulons stocker des traces sur une grande surface, nous devrons augmenter la résolution. Mais cela augmente également l'impact de la capture de scène sur la vitesse du jeu et la taille de la mémoire pour le rendu cible. Pour l'optimisation, vous devez limiter la portée et la résolution.

Après avoir réglé cela, découvrons ce qu'il faut pour réaliser les empreintes de pas dans la neige.

Mise en place d'empreintes dans la neige


La première chose dont vous avez besoin pour créer des traces est le rendu cible . La cible de rendu sera un masque en niveaux de gris, dans lequel le blanc indique la présence d'une trace et le noir indique son absence. Ensuite, nous pouvons projeter le rendu cible sur le sol et l'utiliser pour mélanger les textures et décaler les sommets.


La deuxième chose dont nous avons besoin est un moyen de masquer uniquement les objets affectant la neige. Cela peut être implémenté en rendant d'abord les objets dans la profondeur personnalisée . Vous pouvez ensuite utiliser la capture de scène avec le matériau de post-traitement pour masquer tous les objets rendus dans la profondeur personnalisée. Vous pouvez ensuite afficher le masque dans le rendu cible.

Remarque: la capture de scène est essentiellement une caméra avec la possibilité de produire un rendu cible.

La partie la plus importante de la capture d'une scène est son emplacement. Voici un exemple de rendu cible capturé à partir d'une vue de dessus . Ici, un personnage à la troisième personne et des cases sont masqués.


À première vue, une capture avec une vue de dessus nous convient. Les formulaires semblent appropriés aux maillages, donc il ne devrait pas y avoir de problème, non?

Pas vraiment. Le problème de la capture à partir d'une vue de dessus est qu'elle ne capture rien sous le point le plus large. Voici un exemple:


Imaginez que les flèches jaunes vont jusqu'au sol. Dans le cas d'un cube et d'un cône, la pointe de flèche restera toujours à l'intérieur de l'objet. Cependant, dans le cas d'une sphère, le point en émerge à l'approche de la terre. Mais selon la caméra, la pointe est toujours à l'intérieur de la sphère. Voici à quoi ressemblera la sphère de la caméra:


Par conséquent, le masque de sphère sera plus grand qu'il ne devrait, même si la zone de contact avec la terre est petite.

De plus, ce problème est complété par le fait qu'il nous est difficile de déterminer si l'objet concerne le terrain.


Pour faire face à ces deux problèmes, vous pouvez utiliser la capture par le bas .

Poignée inférieure


La capture ci-dessous est la suivante:


Comme vous pouvez le voir, la caméra capture maintenant le côté inférieur, c'est-à-dire celui qui touche le sol. Cela élimine le problème de la "zone la plus large" qui apparaît lors de la capture par le haut.

Pour déterminer si un objet touche le sol, vous pouvez utiliser un matériau de post-traitement pour effectuer un contrôle de profondeur. Il vérifie si la profondeur de l'objet est supérieure à la profondeur de la terre et si elle est inférieure à un décalage prédéterminé. Si les deux conditions sont remplies, nous pouvons masquer ce pixel.


Voici un exemple à l'intérieur d'un moteur avec une zone de capture de 20 unités au-dessus du sol. Notez que le masque n'apparaît que lorsque l'objet passe par un certain point. Notez également que le masque devient plus blanc lorsque l'objet s'approche du sol.


Tout d'abord, créez un matériau de post-traitement pour effectuer un contrôle de profondeur.

Création d'un matériau de test de profondeur


Pour effectuer un contrôle de profondeur, vous devez utiliser deux tampons de profondeur - l'un pour le sol, l'autre pour les objets affectant la neige. Puisque la capture de la scène ne voit que la terre, la profondeur de la scène déduira la profondeur de la terre. Pour obtenir la profondeur des objets, nous allons simplement les rendre en profondeur personnalisée .

Remarque: pour gagner du temps, j'ai déjà rendu le caractère et les cases en profondeur personnalisée. Si vous souhaitez ajouter d'autres objets qui affectent la neige, vous devez activer le Render CustomDepth Pass pour eux.

Tout d'abord, vous devez calculer la distance de chaque pixel au sol. Ouvrez Materials \ PP_DepthCheck et créez ce qui suit:


Ensuite, vous devez créer une zone de capture. Pour ce faire, ajoutez les nœuds en surbrillance:


Maintenant, si le pixel est à moins de 25 unités de la terre, il apparaîtra dans le masque. La luminosité du masquage dépend de la proximité du pixel avec le sol. Cliquez sur Appliquer et revenez à l'éditeur principal.

Ensuite, vous devez créer une capture de scène.

Créer une capture de scène


Tout d'abord, nous avons besoin d'un rendu cible pour capturer une capture de scène. Accédez au dossier RenderTargets et créez une nouvelle cible de rendu appelée RT_Capture .

Créons maintenant une capture de scène. Dans ce tutoriel, nous ajouterons la capture de scène au plan, car plus tard, nous aurons besoin d'un script pour cela. Ouvrez Blueprints \ BP_Capture et ajoutez le composant de capture de scène 2D . Nommez-le SceneCapture .


Nous devons d'abord régler le tour de capture de sorte qu'il regarde le sol. Accédez au panneau Détails et définissez la rotation sur (0, 90, 90) .


Vient ensuite le type de projection. Étant donné que le masque est une représentation 2D de la scène, nous devons nous débarrasser de la distorsion en perspective. Pour ce faire, définissez Projection \ Type de projection sur Orthographique .


Ensuite, nous devons indiquer à la capture de scène dans quel rendu cible enregistrer. Pour ce faire, sélectionnez la valeur de RT_Capture pour Capture de scène \ Cible de texture .


Enfin, nous devons utiliser du matériel de vérification de la profondeur. Ajoutez PP_DepthCheck aux fonctions de rendu \ Matériaux post-traitement . Pour que le post-traitement fonctionne, nous devons également changer la capture de scène \ source de capture en couleur finale (LDR) en RVB .


Maintenant que la capture de scène est configurée, nous devons spécifier la taille de la zone de capture.

Définition de la taille de la zone de capture


Puisqu'il est préférable d'utiliser de faibles résolutions pour le rendu cible, nous devons utiliser l'espace efficacement. Autrement dit, nous devons choisir quelle zone un pixel couvrira. Par exemple, si les résolutions de la zone de capture et du rendu cible sont identiques, nous obtenons un rapport 1: 1. Chaque pixel couvrira une zone 1 × 1 (en unités du monde).

Pour les pistes dans la neige, un rapport de 1: 1 n'est pas requis, car nous n'aurons probablement pas besoin de tels détails. Je recommande d'utiliser des ratios plus importants car cela vous permettra d'augmenter la taille de la zone de capture à basse résolution. Mais ne faites pas le rapport trop grand, sinon les détails commenceront à se perdre. Dans ce tutoriel, nous utiliserons un rapport 8: 1, c'est-à-dire que la taille de chaque pixel sera de 8 × 8 unités du monde.

Vous pouvez redimensionner la zone de capture en modifiant la propriété Scene Capture \ Ortho Width . Par exemple, si vous souhaitez capturer une zone de 1024 × 1024, définissez la valeur sur 1024. Étant donné que nous utilisons un rapport 8: 1, définissez la valeur sur 2048 (la résolution par défaut du rendu cible est 256 × 256).


Cela signifie que la capture de scène capturera la zone de 2048 × 2048 . Elle mesure environ 20 × 20 mètres.

Le matériau au sol doit également avoir accès à la taille de capture pour projeter correctement le rendu cible. Pour ce faire, la méthode la plus simple consiste à enregistrer la taille de capture dans la collection de paramètres de matériau . Il s'agit essentiellement d'une collection de variables auxquelles tout matériel peut accéder.

Enregistrement de la taille de capture


Revenez à l'éditeur principal et accédez au dossier Matériaux . Créez une collection de paramètres de matériau qui sera dans Matériaux et textures . Renommez-le en MPC_Capture et ouvrez-le.

Créez ensuite un nouveau paramètre scalaire et nommez-le CaptureSize . Ne vous inquiétez pas de définir sa valeur - nous le ferons en toute franchise.


Revenez à BP_Capture et ajoutez les nœuds en surbrillance à l' événement BeginPlay . Définissez Collection sur MPC_Capture et Nom du paramètre sur CaptureSize .


Désormais, tout matériau peut obtenir la valeur de la largeur ortho en la lisant dans le paramètre CaptureSize . Jusqu'à présent, avec la capture de la scène, nous avons terminé. Cliquez sur Compiler et revenez à l'éditeur principal. L'étape suivante consiste à projeter le rendu cible sur le sol et à l'utiliser pour déformer le paysage.

Déformation du paysage


Ouvrez M_Landscape et accédez au panneau Détails. Définissez ensuite les propriétés suivantes:

  • Pour Deux faces, sélectionnez activé . Puisque la capture de la scène «regardera» d'en bas, elle ne verra que les faces inverses de la terre. Par défaut, le moteur ne rend pas les faces arrière des maillages. Cela signifie qu'il ne stockera pas la profondeur de la terre dans le tampon de profondeur. Pour résoudre ce problème, nous devons dire au moteur de rendre les deux côtés du maillage.
  • Pour la pavage D3D11, sélectionnez Pavage plat (les triangles PN peuvent également être utilisés). La tessellation divisera les triangles maillés en plus petits. Essentiellement, cela augmente la résolution du maillage et nous permet d'obtenir des détails plus fins lors du déplacement des sommets. Sans cela, la densité des pics sera trop faible pour créer des traces crédibles.


Une fois les pavages activés, le Multiplicateur mondial de déplacement et de pavage s'allume.


Le multiplicateur de pavage contrôle la quantité de pavage. Dans ce didacticiel, nous ne connecterons pas ce nœud, c'est-à-dire que nous utilisons la valeur par défaut ( 1 ).

Le déplacement mondial obtient une valeur vectorielle qui décrit dans quelle direction et à quelle distance déplacer le sommet. Pour calculer la valeur de ce contact, nous devons d'abord projeter le rendu cible sur le sol.

Rendu cible du projet


Pour projeter le rendu cible, vous devez calculer ses coordonnées UV. Pour ce faire, créez le schéma suivant:


Que se passe-t-il ici:

  1. Nous devons d'abord obtenir la position XY du sommet actuel. Puisque nous capturons par le bas, la coordonnée X est retournée, vous devez donc la retourner (si nous devions capturer par le dessus, nous n'en aurions pas besoin).
  2. Cette partie effectue deux tâches. Premièrement, il centre le rendu cible de telle manière que son milieu se trouve dans les coordonnées (0, 0) de l' espace mondial. Elle convertit ensuite les coordonnées de l'espace mondial en espace UV.

Ensuite, créez les nœuds sélectionnés et combinez les calculs précédents comme indiqué ci-dessous. Pour Échantillon de texture, sélectionnez RT_Capture .


Cela projettera le rendu cible au sol. Cependant, tous les sommets situés en dehors de la zone de capture échantillonneront les bords du rendu cible. Il s'agit en fait d'un problème car le rendu cible ne doit être utilisé que pour les sommets de la zone de capture. Voici à quoi cela ressemble dans un jeu:


Pour résoudre ce problème, nous devons masquer tous les UV qui se trouvent en dehors de la plage de 0 à 1 (c'est-à-dire la zone de capture). Pour cela, j'ai créé la fonction MF_MaskUV0-1 . Il renvoie 0 si les UV transmis sont en dehors de la plage de 0 à 1 et renvoie 1 s'il se trouve à l'intérieur. En multipliant le résultat par le rendu cible, nous effectuons le masquage.

Maintenant que nous avons projeté le rendu cible, nous pouvons l'utiliser pour mélanger les couleurs et déplacer les sommets.

Utilisation du rendu cible


Commençons par mélanger les couleurs. Pour ce faire, nous connectons simplement 1-x à Lerp :


Remarque: si vous ne comprenez pas pourquoi j'utilise 1-x , je vais vous expliquer - cela est nécessaire pour inverser le rendu cible, afin que les calculs deviennent un peu plus faciles.

Maintenant que nous avons une trace, la couleur de la terre devient brune. S'il n'y a pas de couleur, il reste blanc.

L'étape suivante est le déplacement des sommets. Pour ce faire, ajoutez les nœuds sélectionnés et connectez tout comme suit:


Cela fera monter toutes les zones de neige de 25 unités. Les zones sans neige ont un décalage nul, ce qui créera un sentier.

Remarque: vous pouvez modifier la hauteur de déplacement pour augmenter ou diminuer les niveaux de neige. Notez également que DéplacementHauteur est la même valeur que le décalage de capture. Quand ils ont la même signification, cela nous donne la déformation exacte. Mais il y a des cas où vous devez les changer individuellement, alors je les ai laissés comme paramètres séparés.

Cliquez sur Appliquer et revenez à l'éditeur principal. Créez une instance BP_Capture au niveau et donnez-lui les coordonnées (0, 0, -2000) pour la placer sous terre. Cliquez sur Play et déambulez avec les touches W , A , S et D pour déformer la neige.


La déformation fonctionne, mais il ne reste aucune trace! Cela est dû au fait que la capture écrase le rendu cible à chaque exécution de la capture. Nous avons besoin d'un moyen de rendre les pistes permanentes .

Création de traces permanentes


Pour créer la persistance, nous avons besoin d'un autre rendu cible ( tampon constant ), dans lequel tout le contenu de la capture sera enregistré avant l'écrasement. Ensuite, nous ajouterons un tampon constant à la capture (après l'avoir écrasé). Nous obtenons une boucle dans laquelle chaque rendu cible écrit dans un autre. C'est ainsi que nous créerons une trace permanente.


Tout d'abord, nous devons créer un tampon constant.

Création d'un tampon persistant


Accédez au dossier RenderTargets et créez une nouvelle cible de rendu appelée RT_Persistent . Dans ce didacticiel, nous n'avons pas à modifier les paramètres de texture, mais dans votre propre projet, vous devrez vous assurer que les deux rendus cibles utilisent la même résolution.

Ensuite, nous avons besoin de matériel qui copiera la capture dans un tampon permanent. Ouvrez Materials \ M_DrawToPersistent et ajoutez un nœud d' échantillon de texture . Sélectionnez la texture RT_Capture et connectez-la comme suit:


Maintenant, nous devons utiliser le matériau d'étirage. Cliquez sur Appliquer , puis ouvrez BP_Capture . Tout d'abord, créez une instance dynamique du matériau (plus tard, nous devrons lui transmettre des valeurs). Ajoutez les nœuds en surbrillance à l' événement BeginPlay :


Clear Render Target Les nœuds 2D effacent chaque rendu cible avant utilisation.

Ouvrez ensuite la fonction DrawToPersistent et ajoutez les nœuds en surbrillance:


Ensuite, nous devons nous assurer que le dessin dans le tampon constant est effectué dans chaque image, car la capture a lieu dans chaque image. Pour ce faire, ajoutez DrawToPersistent à la coche d' événement .


Enfin, nous devons ajouter un tampon persistant au rendu de capture cible.

Enregistrez pour capturer


Cliquez sur Compiler et ouvrez PP_DepthCheck . Ajoutez ensuite les nœuds en surbrillance. Pour Échantillon de texture, définissez la valeur sur RT_Persistent :


Maintenant que la cible se transcrit en écriture, nous obtenons des traces qui restent. Cliquez sur Appliquer , puis fermez le matériau. Cliquez sur Play et commencez à laisser des pistes!


Le résultat est superbe, mais le circuit résultant ne fonctionne que pour une seule zone de la carte. Si vous allez au-delà de la zone de capture, les traces cesseront d'apparaître.


Vous pouvez résoudre ce problème en déplaçant la zone de capture avec le lecteur. Cela signifie que des traces apparaîtront toujours autour de la zone dans laquelle se trouve le joueur.

Remarque: lorsque la capture se déplace, toutes les informations en dehors de la zone de capture sont supprimées. Cela signifie que si vous retournez dans la zone où il y avait déjà des traces, elles disparaîtront déjà. Dans le didacticiel suivant, je vais vous montrer comment créer des pistes partiellement conservées.

Capture de mouvement


Vous pouvez décider qu'il est assez simple de lier la position de capture XY à la position XY du joueur. Mais si vous le faites, le rendu cible commencera à devenir flou. En effet, nous déplaçons le rendu cible avec un pas inférieur à un pixel. Lorsque cela se produit, la nouvelle position des pixels se situe entre les pixels. Par conséquent, un pixel est interpolé par plusieurs pixels. Voici à quoi ça ressemble:


Pour résoudre ce problème, nous devons déplacer la capture par étapes discrètes. Nous calculons la taille des pixels dans le monde , puis déplaçons la capture à des étapes égales à cette taille. Ensuite, chaque pixel ne sera jamais entre les autres, donc le flou n'apparaîtra pas.

Pour commencer, créons un paramètre dans lequel l'emplacement de capture sera stocké. Le matériau terrestre en aura besoin pour effectuer des calculs de projection. Ouvrez MPC_Capture et ajoutez un paramètre vectoriel appelé CaptureLocation .


Ensuite, vous devez mettre à jour le matériau terrestre pour utiliser le nouveau paramètre. Fermez MPC_Capture et ouvrez M_Landscape . Modifiez la première partie des calculs de projection comme suit:


Maintenant, le rendu cible sera toujours projeté sur l'emplacement de capture. Cliquez sur Appliquer et fermez le matériau.

Ensuite, nous allons faire le mouvement de capture avec une étape discrète.

Mouvement de capture de pas discret


Pour calculer la taille des pixels dans le monde, vous pouvez utiliser l'équation suivante:

(1 / RenderTargetResolution) * CaptureSize 

Pour calculer la nouvelle position, nous utilisons l'équation ci-dessous pour chaque composante de la position (dans notre cas, pour les coordonnées X et Y).

 (floor(Position / PixelWorldSize) + 0.5) * PixelWorldSize 

Maintenant, utilisez-les dans la capture de plans. Pour gagner du temps, j'ai créé la macro SnapToPixelWorldSize pour la deuxième équation. Ouvrez BP_Capture , puis ouvrez la fonction MoveCapture . Ensuite, créez le diagramme suivant:


Il calculera le nouvel emplacement, puis enregistrera la différence entre le nouvel emplacement et l'emplacement actuel dans MoveOffset . Si vous utilisez une résolution autre que 256 × 256, modifiez la valeur en surbrillance.

Ensuite, ajoutez les nœuds sélectionnés:


Ce circuit déplace la capture avec le décalage calculé. Elle enregistrera ensuite le nouvel emplacement de capture dans MPC_Capture afin qu'il puisse être utilisé par le matériel au sol.

Enfin, nous devons effectuer une mise à jour de position dans chaque image. Fermez la fonction et ajoutez-la à la coche d' événement avant DrawToPersistent MoveCapture .


Déplacer une capture n'est que la moitié de la solution. Nous devons également déplacer le tampon constant. Sinon, la capture et le tampon persistant seront désynchronisés et produiront des résultats étranges.


Déplacement de tampon permanent


Pour déplacer un tampon constant, nous devons passer le décalage de déplacement calculé. Ouvrez M_DrawToPersistent et ajoutez les nœuds en surbrillance:


Pour cette raison, le tampon constant sera décalé de la valeur du décalage transmis. Comme dans le matériau de la terre, nous devons inverser la coordonnée X et effectuer le masquage. Cliquez sur Appliquer et fermez le matériau.

Ensuite, vous devez transférer le décalage. Ouvrez BP_Capture , puis ouvrez la fonction DrawToPersistent . Ensuite, ajoutez les nœuds en surbrillance:


C'est ainsi que nous convertissons MoveOffset en espace UV, puis le passons dans le matériau de dessin.

Cliquez sur Compiler , puis fermez le plan. Cliquez sur Play et courez au contenu de votre cœur! Peu importe la distance parcourue, les traces resteront toujours autour de vous.


Où aller ensuite?


Le projet terminé peut être téléchargé ici.

Il n'est pas nécessaire d'utiliser les pistes créées dans ce didacticiel uniquement pour la neige. Vous pouvez même les utiliser pour des choses comme l'herbe concassée (dans le prochain tutoriel, je montrerai comment créer une version avancée du système).

Si vous souhaitez travailler avec des paysages et des rendus cibles, je vous recommande de regarder la vidéo de Chris Murphy Building High-End Gameplay Effects with Blueprint . Ce tutoriel vous montrera comment créer un énorme laser qui brûle la terre et l'herbe!

Source: https://habr.com/ru/post/fr416703/


All Articles