À l’époque, calculer le motion blur était très coûteux pour un ray tracer. Muni de nos passes de motion vector (en .tiff…), on bricolait au compo pour éviter de provoquer des crises d’épilepsie chez le spectateur (car à par les animateurs qui trouvent que l’effet stroboscopique d’un playplast est trop cool, tout le monde à mal au crâne).

C’était l’époque ou une roue ou une sphère tournant rapidement sur un plan n’augurait rien de bon… :triste:

S’il est intéressant de voir que les techniques à base de passes de motion vector au compo n’ont jamais complètement disparues, on ne peut, en revanche, pas ignorer que le motion blur 3D (c.à.d, rendu) arrive avec son lot de complications.

Ce billet part du principe que vous savez manipuler Yeti et Guerilla. :cayMal:

Guerilla et le motion blur

Il faut bien comprendre que Guerilla n’est pas un logiciel comme Maya qui va « sampler » la scène à des valeurs temporelles données. Il n’assume rien du sampling interne des éléments de la scène (Alembic, Realflow, etc.). Il récupère tout ce qui peut pour un shutter donné.

Ce mécanisme permet de faire coexister, dans une même scène, des Alembic exportés avec différentes valeurs de step (e.g. la majorité en 2 samples : 0.0-0.2 et les personnages rapides en 5 samples : 0.0-0.05-0.1-0.15-0.2, etc.).

Les procédurales RenderMan

Guerilla supporte les procédurales au format RenderMan. Une procédurale est un objet (une primitive plutôt) de votre scène de rendu qui déploie son contenu quand le moteur le demande (souvent, quand un rayon touche sa bounding box). À ce moment, le moteur appelle la procédurale avec ses paramètres. Chaque procédurale dispose de ses propres arguments, un peu comme une ligne de commande.

La procédurale Yeti

Pour que Yeti crache ses poils au moteur, il nécessite un fichier .fur généré par vous au moment de l’export Maya. Ce fichier contient tout ce qu’il faut à Yeti pour générer des poils :

  • Le graph Yeti (celui que vous manipuler dans Maya).
  • Les guides (courbes).
  • Le groom.
  • La géométrie animée (le scalp de votre personnage) et samplé (à 0.0 - 0.2 par exemple).
  • La géométrie en rest pose, utilisé comme référentiel pour la distribution des poils sur la surface. Il faut que sa topologie soit identique à celle du scalp.

La documentation du format de cache (.fur) est ici si vous voulez un peu plus d’information.

Au moment de l’appel de la procédurale, on lui donne ce fichier, ainsi que certain paramètres (density, width, thread, etc.) et elle fait ensuite son travail. :mechantCrash:

La documentation des paramètres de la procédurale Yeti se trouve ici. Si vous la regardez, vous remarquerez la présence de l’argument --samples. Comme expliqué, Yeti va cracher les samples de motion blur aux valeurs données dans cet argument.

Yeti dans Guerilla

Avant qu’un nœud Yeti d’interfaçage n’existe dans Guerilla, il fallait faire une RIB box contenant l’appel de la procédurale. Ce n’était pas super pratique, mais on avait un contrôle absolu sur l’appel (c’est nous qui donnions les arguments).

Le manque d’icône devrait vous donner une idée du côté user friendly…

Et toto.rib est le fichier ouvert par Guerilla.

Pour vous donner une idée de ce qu’on écrivait dans ce fichier :

Procedural "DynamicLoad" ["pgYetiPrmanRender" --density 1 --length 1 --width 1 --frame 1 --samples 0.0 0.2 --file "/path/to/my.fur"]

Du bonheur en boite ! :petrus:

Comme c’était un brin casse-pieds, un nœud Yeti a vu le jour :

Documentation du nœud ici.

Ce nœud encapsule la procédurale, ce qui lui permet de bénéficier du workflow de Guerilla (overrides notamment). Dès lors, il faut se demander quelles sont les valeurs que Guerilla passe à --samples ?

Et bien, par défaut, Guérilla demande deux samples, un au shutter open et l’autre au shutter close du projet. Rappelez-vous :

  • Guerilla ne peut pas savoir quels sont les samples présents dans le .fur.
  • La procédurale Yeti demande explicitement les samples à générer et ne permet pas de générer tout ce qu’elle a (ce pourrait être une demande légitime à faire au développeur).

Pour pallier à ça vous pouvez passer une liste explicite de samples dans l’attribut Motion Samples du nœud Yeti de Guerilla. À vous, toutefois, de vous assurer que ces valeurs sont cohérentes avec ce qu’il y a dans votre .fur ainsi qu’avec le shutter fourni à Guerilla.

J’espère avoir rendu tout ça moins opaque. :pasClasse:

Un tout petit écart pour vous dire que vous pouvez baker la procédurale en .ghostdata. Guerilla va générer le contenu de la procédurale et l’enregistrer, vous pouvez ensuite l’importer dans et Yeti n’est plus nécessaire. Ce sera lourd, mais dans le cas d’éléments statiques c’est très pratique.

Et bien entendu, vous pouvez scripter ça :

import guerilla
guerilla.Procedural.baketoarchive("/path/to/my.ghostdata")

Pensez-y si vous êtes ric-rac coté licences (et que vous avez vraiment beaucoup de stockage).

Fin de la parenthèse. :hehe:

Jouer avec les paramètres Yeti

Cette seconde partie s’apparente plus à du partage d’expérience sur le comportement de la procédurale Yeti elle-même.

Détail comme ça : Assurez-vous toujours que les valeurs de FPS sont identiques entre Maya et Guerilla. Évidant, mais comme un TD est amené à faire du support sur plusieurs projets, ce n’est pas inutile de le rappeler. Je me suis fait avoir lors d’un débogage sur un projet parallèle qui n’avait pas les mêmes FPS que le projet principal. :ideenoire:

Passons… :slow_clap:

Envisageons le scénario suivant : Le .fur Yeti est exporté sur 2 samples (0.0, 0.2). La trajectoire est donc linéaire :

Si Guerilla demande 0.0, 0.1, Yeti interpole correctement :

En revanche, si Guerilla demande 0.0, 0.3, Yeti « stop » le mouvement :

D’un côté, c’est logique, Yeti ne peut vraiment fournir l’information. Gardez ça à l’esprit si vous augmentez vos shutters sur un plan pour ajouter un peu de motion blur. et que vos poils sont en décalage de vos scalps.

Générer des bounding box pour ses .fur

pgYetiCacheInfo est une ligne de commande qui permet d’extraire quelques informations d’un .fur. La plus intéressante étant la bounding box.

En effet, comme le dit clairement la doc, Guerilla lui-même utilise pgYetiCacheInfo pour extraire la bounding box, mais de mécanisme par défaut est tellement lourd qu’un autre système est proposé.

Si un fichier .bbox existe à coté d’un .fur, Guerilla lira ce dernier pour en extraire la bounding box. L’idée est donc de générer ces fichiers au moment (enfin juste après) de la génération des .fur. Vous pouvez faire ça en farm. Gardez tout de mème à l’esprit que, sous le capot, pgYetiCacheInfo va générer le système de fur au complet. Donc les machines qui s’occupent de ça doivent en avoir dans le pantalon. :banaeyouhou:

Vous pouvez aussi bricoler cette bounding box vous-même depuis Maya en prenant celles des scalps que vous grossissez un peu, mais sur des systèmes de fur un peu complexe, vous risquez d’en faire une trop petite et payer la note au rendu.

Sachez également que l’argument –samples permet, comme pour la procédurale de prendre en compte les samples donnés pour la génération de la bounding box.

Conclusion

J’espère que ce billet vous aura plus, et que vous allez, etc. etc.

:marioCours: