La bande annonce

Ce post mortem contient évidemment son lot de spoil. Je considère que vous avez déjà vu le film. Si vous ne l’avez pas fait, franchement faites-le. Le montage est rapide et on ne s’ennuie pas et vous lâcherez sûrement une petite larme. Dans tous les cas, voici la bande annonce :

Mon poste

J’ai eu plusieurs casquettes durant le projet (comme d’hab’ en fait…). C’était du pip’, du pip’, du pip’. Voici une liste non exhaustive de ce que j’ai fait :

  • Lookdev (Guerilla)
  • Lighting (Guerilla)
  • Renderfarm (Qube)
  • Hair/Végétation (Maya/Yeti)

Un démarrage difficile

Sans rentrer dans les détails, le studio appartenait aux producteurs du film. C’était leur premier long-métrage. Le projet a connu un certain nombre de difficultés et a dû “recommencer” en cours de route. Je suis arrivé alors que le projet avait été mis en pause et une bonne partir des équipes, mise à pied. Il n’y avait pas (plus en fait) d’outils, pas de pipeline. Nous n’étions pas nombreux dans le studio (moins de dix). La R&D commençait le pipeline et le département artistique continuait ses recherches. Il était d’ailleurs difficile de se dire, en arrivant le matin, qu’un film allait sortir de tout ça. La masse de travail abattu lors des premiers mois fut importante.

Shotgun

Le temps et les ressources disponibles étant limitées, nous avons opté pour Shotgun pour gérer l’intégralité de notre base de données (comprenez qu’il n’y avait aucune autre base de données que Shotgun, même pas un petit MySQL, planqué sur un serveur en loucedé près des toilettes, rien !). C’est (très) cher mais au vu de la configuration du studio et de ce que Shotgun propose, je pense, avec du recul, que c’était un bon choix.

Une grosse partie du travail de départ concernait les template de chemin de fichier de Shotgun pour réussir à publier en utilisant Shotgun mais notre propre structure de fichier.

Viens ensuite la suppression des step/task de Shotgun au profit d’un système maison. C’est vraiment un truc idiot, dans Shotgun, que les steps et les tasks puissent être créées et modifiées par les coordinateurs, car on ne peut, du-coup, pas s’appuyer dessus en termes d’infrastructure. Il fallait donc les remplacer pour faire la même chose mais en plus robuste.

Comme tout changeait tout le temps, les chemins de fichier n’utilisaient pas les noms des assets et des plans mais leurs ids, donnant des chemins de fichier difficile à lire. Bien que ça puisse paraître dangereux, cela n’a posé aucun souci majeur en pratique car tout était fait pour éviter aux personnes d’avoir à naviguer dans la structure des dossiers.

Shotgun est lent. Quand le builder est arrivé (voir plus bas) on s’est retrouvé à littéralement mettre Shotgun à terre avec des requêtes importantes (en gros, notre hiérarchie de scène c’était Shotgun…). Après pas mal d’optimisation de leur part, on a aussi mis un système de cache basé sur Redis. Redis est un système de cache sur serveur. Le principe est de stocker, dans Redis, le résultat des requêtes demandées à Shotgun pour éviter d’avoir à les refaire :

  • Notre code fait une requête.
  • Il vérifie, dans Redis, si le résultât de la requête existe.
  • S’il existe, il l’utilise.
  • S’il n’existe pas, notre code fait la requête dans Shotgun, attends (looooooooongtemp…), récupère le résultât de la requête, le met dans Redis, puis l’utilise.

Vous l’aurez compris : Redis c’est bon, mangez-en ! :sourit:

Modeling, Rigging et Lookdev commencent

Ces trois départements ont commencé rapidement et fonctionné en parallèle presque immédiatement, ce qui nécessitait, du fait de l’impossibilité d’anticiper, un nombre conséquent d’aller-retour. Il fallait être continuellement vigilant sur ce que chaque département livrait/récupérait. Ce fut épuisant pour tout le monde mais, et c’est peut être du fait des Québécois, personne ne râlait quand il fallait repasser sur un certain nombre de choses (chapeau aux modeleurs pour le nombre incroyable de retake techniques). Souvent nous comprenions tous pourquoi tel ou tel chose devait être modifié. L’ambiance générale était très bonne malgré les journées de travail éreintantes (c’est peut-être lié). Ça été ça pendant vraiment longtemps, doute-investigation-stresse-correction-test-avance.

Tout override !

guerilla.png
Note : Il faudra que je prenne le temps, un jour, d’expliquer le principe du lighting par override. Bien que cette pratique soit très utilisée en long-métrage et série, tout le monde ne la connaît pas nécessairement.

Guerilla est un superbe outil, je le crie à qui veut l’entendre. La logique mise en place sur Ballerina a été la suivante :

Un RenderGraph initial pour mettre les paramètres par défaut. Par exemple, appliquer un shader gris-neutre sur tous les objets, assigner un shader de curve sur les objets de type curve, modifier des paramètres en fonction des tags assignés sur les objets, etc.

Le second RenderGraph était appliqué par asset. Ce sont les RenderGraphs que les artistes du lookdev faisaient et publiaient. Il assignait des séquences d’UDIM par attribut du shader (spéculaire, couleur diffuse, etc.) et modifiait les paramètres ne nécessitant pas de textures. Le tout en s’accrochant aux tags des objets.

Enfin venaient les RenderGraphs du Lighting séparés en trois : Un pour la séquence, un pour un groupe de plan et le dernier pour le plan.

Chacun de ces RenderGraph changeait (overridait) les paramètres du RenderGraph précédent.

Cette liste ne s’est pas faite d’un coup. Par exemple, les lighters ont longtemps travaillé qu’avec un RenderGraph de plan unique, les RenderGraph de séquence sont arrivés plus tard, tout comme les RenderGraph de groupe de plan arrive quasiment à la fin.

Recrutement des TDs

modus_fx_logo.jpg

Ceci n’est pas un fournisseur d’accès internet. :trollface:

On a eu de la chance (dira-t-on), Modus FX a fermé ses portes au moment où on cherchait des TDs. On s’est donc récupéré énormément de TD expérimentés. Avec le recul, il aurait été difficile de sortir le pipeline sans leur aide, ils ont vraiment fait du bon boulot. Chaque TD avait la responsabilité d’un (ou plusieurs) département, mais nous codions dans le même repo git avec les mêmes standards de code. Il était d’ailleurs vraiment impressionnant de pouvoir sauter dans le code de ses collègues sans avoir l’impression d’être largué. Cette approche (très rigide à l’entrée) a réussi à créer une cohésion entre les TD qui a vraiment permis une « avancée de front ». Au passage : PEP 8 est un compromis, pas un standard.

Mon travail concernait principalement le lookdev. Nous avons utilisé Mari et Guerilla. Comme la hiérarchie n’était pas fixe, nous nous sommes appuyé sur les tags. C’est un peu fastidieux et contre productif au premier abord, car les graphistes doivent placer leurs tags dans Maya, exporter leur abc et faire leur surfacing dans Guerilla. Mais il faut bien garder à l’esprit que la hiérarchie changeait constamment à cette période (rien n’était encore décidé en rig) il fallait donc trouver un moyen au lookdev de livrer sans dépendre d’autres départements. Ça été, je pense, une bonne décision.

Le travail consistait grossièrement à travailler dans Mari, exécuter un script qui sortait en .tif les UDIMs des channels sélectionnés, puis faire un Update dans Guerilla qui transformait ses mêmes .tif en .tex pour le rendu. C’était fastidieux et nous aurions pu améliorer la détection des updates pour éviter beaucoup de temps perdu, notamment lors de petites retakes. Notez que seul les .tex étaient publiés. Cela n’a pas posé de soucis en pratique.

Builder

Le builder (layout), c’est la colonne vertébrale d’un pipeline d’un film. Il permet la relation entre les informations de plan en base de donne et les logiciels. Un des gros chantiers de tout long-métrage c’est la capacité à construire les plans, si possible dans n’importe quel logiciel. Je ne me suis pas occupé du Builder du côté de la base de donne, mais de son intégration dans Guerilla. C’est d’ailleurs quand les plans ont commencé à se builder sans trop de soucis que j’ai réellement pris confiance en notre capacité à sortir le projet. Tant que vous n’avez pas le moyen de reconstruire des plans, à jour, en partant de rien, vous êtes dans une situation difficile (et si vous avez des équipes qui travaillent sur des plans avant d’avoir cet outil vous êtes franchement dans la m… Ouai nan… Faites un builder avant toute chose…). Du builder découla les quality check d’animation (Ambiant Occlusion) et leur automatisation sur la render farm.

Instanciation implicite

Une fois que vous avez un builder, vous construisez des plans de plus en plus gros, jusqu’à ce qu’ils ne rendent plus. L’intérieur de l’opéra (entre autres) montait anormalement en mémoire. On a donc creusé un peu pour se rendre compte que le modeling appliquait systématiquement un combo reset transforms/freeze transforms sur tous les objets, garantissant au rig que tous les objets étaient au centre du monde, ce qui simplifiait leur travail. Cela avait pour effet, lors de l’export en alembic, de casser les instances implicites.

C’est quoi

Le principe est simple : Quand deux shapes sont identiques, on considère qu’elles sont en instance. Ce qui définit une shape c’est (entre autres) la position de ces points par rapport à son centre. Si chaque objet a un centre différent, leurs points, une fois dans l’alembic, sont à des positions différentes. Ainsi, si vous dupliquez mille fois un objet, que vous écrasez les transforms de tous les objets, chaque objet a son centre au centre du monde, et donc, chaque objet a un centre différent de celui du voisin, et donc, tous les point qui compose un objet sont différents de ceux du voisin.

Note : Maya fait une distinction entre le centre géométrique et le point de pivot. Il est donc possible de déplacer le point de pivot sans déplacer le centre géométrique.

Comment résoudre ça

On était très avancé en modeling, il fallait une solution simple sans trop d’intervention humaine. L’approche prise est pragmatique et pas super mathématique : On avait remarqué que la topologie des objets étaient conservés. Nous avions donc la garantie que les deux premières arêtes connectées au premier point étaient les même sur tous les objets. S’ensuit un peu d’algèbre linéaire (produit vectoriel, scalaire, merci PyMEL) et on avait un algo capable de récupérer les objets qui pouvaient être implicitement instancié et récupérer un centre identique. Une UI plus tard les modeleurs pouvaient repasser sur les gros sets pour récupérer l’instanciation implicite des objets en quelques cliques.

Il n’empêche que malgré cet outil, il fallait quand même rouvrir tous les assets pour repasser dessus. Un travail assez laborieux et ingrats. Il y eut quelques tensions autour de ça (parce qu’il a déjà fallu repasser sur presque tous les assets auparavant pour des histoires de hiérarchie). J’avoue avoir pas mal forcé auprès de la prod pour que ce soit fait. Ce n’est jamais très apprécié de faire du forcing de la sorte, mais je pense que tout le monde a bien compris qu’on allait avoir de gros soucis si on ne le faisait pas.

Effet indirect

On a remarqué qu’en plus de diminuer drastiquement la consommation mémoire de Guerilla, les gros assets, en particulier les buildings, se chargeaient bien plus vite et étaient bien plus fluide à la navigation dans Mari.

Hiérarchie des assets

Comme je vous le disais, le rig n’était pas défini. Il a donc fallu repasser sur tous les assets pour conformer leur hiérarchie. On a donc fait des petites boucles qui ouvraient tous les assets du film pour passer un sanity check et savoir exactement quels assets devaient être rouverts. Mais on est allé plus loin : Avec les modeleurs, on a identifié les cas de “correction scriptable” pour le faire automatiquement. Après que les modeleurs aient teste la méthode sur quelques assets, on envoyait ça sur tous les assets de la prod. Si envoyer une boucle qui ouvre tous les assets pour faire passer un sanity check n’engage à rien. Le fait de modifier, en batch, des centaines d’assets est extrêmement risqué. On a fait la procédure et le suivi à deux, l’un à côté de l’autre pendant plusieurs jours ce qui permettait une réflexion et une remise en question continue (ne jamais laisser une seule personne faire du batch qui modifie les scènes toute seul). Car derrière l’apparente simplicité, le risque de casser des centaines d’asset est réel. On a donc fait ça avec le sérieux et le professionnalisme qui s’imposait, on a relu plusieurs fois notre code, on a fait des tests et forcement, on a tout pété! :baffed:

Bon, on a été malin, le commentaire de publication utilisé pour mettre à jour les assets contenait un mot très particulier. Il a donc été assez simple de rechercher les publications puis de les omettre dans Shotgun. Mais bon, je me rappelle qu’à ce moment, l’état d’esprit de la production c’était : :mitraille: :enerve: :tuComprendRien: :injures: :casseTeteMur: :nervous: :grenadelauncher:

Un petit fix, on a relancé la boucle et c’était bon… :siffle:

Hair

Les hairs ont été faits avec Yeti. Du fait des autres chantiers, les hairs sont restés longtemps sans personne (en R&D) pour leur assurer un pipeline propre. On savait qu’on allait le payer et ça n’a pas raté. La liste des problèmes rencontrés est très longue et, il faut bien l’avouer, assez misérables. Le rig n’était pas recentre, c’est-à-dire que plus les personnages étaient loin du centre, plus la géométrie avait des problèmes de précision (J’entends souvent que « c’est le B-A BA » mais je n’ai jamais vu son application sur un long. Le rigs étant souvent trop complexe).

En pratique les soucis de précision n’auraient pas dû être un problème car dans tous les cas, nous recentrions les scènes. C’était sans compter sur la boite noire qu’était Yeti. Nous n’avons jamais eu la confirmation de quoi que ce soit (les échanges de mail étant assez improductif) mais je soupçonne que Yeti essai de se rattacher à la surface d’une distance au prorata de la densité de point. C’est-à-dire que plus il y a de point, moins Yeti va chercher la surface. Le problème que cela posait était le suivant : Afin de pouvoir générer un vecteur de motion blur, chaque point de chaque courbe qui compose les hairs doit être présent deux fois à t et t+0.5. Sauf que si Yeti n’arrivait pas à retrouver une surface lors d’un des samples, il ne calculait pas la courbe, le nombre de point devenait donc inconsistant entre t et t+0.5. Sans un nombre consistant de point, Guerilla ne pouvait générer les motion vectors, il ne lui restait donc qu’à cacher la partie des hairs qui posait problème en affichant un warning. La solution ? Recentrer les hairs avant l’export de la simulation, sauvegarder l’offset et l’appliquer dans Guerilla avant rendu B-D. Je vous passe les détails mais ça été un beau bordel. Toutefois, le truc cool en code c’est qu’à force d’effort et d’acharnement, ça finit par marcher mais ça été long et fastidieux.

La végétation

Une autre de mes taches sur le projet a été de faire un outil pour gérer la végétation, en particulier les arbres et les buissons. La première question est pourquoi ne pas utiliser Yeti ? C’est difficile à expliquer si on ne sait pas comment fonctionne un pipeline. Yeti génère des .fur tout-en-un qui sont “déroulés” dans Guerilla au moment du rendu. Cette étape est très longue, la mémoire prise par Yeti lors de la génération des primitives est énorme, la bounding box est globale, l’instanciation compliquée et surtout : Une mise à jour d’un des assets nécessite un reexport du système de .fur entier. Dans une logique de pipeline d’animation, chaque département n’est supposé publier que le minimum de ce qui est nécessaire. Dans le cas de la végétation seul des informations de position/rotation/échelle ainsi que l’id de l’asset à placer (avec ses attributs de variations) sont nécessaires. Ainsi, dans Guerilla, on amène l’alembic contenant uniquement les positions des assets, la géométrie source de l’asset (que l’on cache), un script pour lier chaque position à la source et c’est terminé. On avait quelques soucis de performances, isolé dans ticket, résolu par les gars de Mercenaries (les développeurs de Guerilla) dans la semaine et on avait un système d’instance très léger, qui rendait immédiatement.

L’outil a été un peu long à écrire, mais on l’a étendu à un certain nombre de plans, notamment pour placer des personnages en instance sur les vues d’ensemble.

Mon seul regret de technophile à poil dur fut la demande de diminuer le nombre d’arbres “parce qu’il y en avait trop” alors qu’on avait virtuellement aucune limite.

Lighting

La production a fait du bon boulot, car Le Petit Prince venait de se terminer et on a pu embaucher bon nombre de lighters déjà formé sous Guerilla. Je me rappelle avoir présenté le pipeline à une juniore qui, après m’avoir écouté déclarer mon amour pour les overrides, me fit comprendre qu’elle connaissait déjà tout ça. Tous les lighters étaient à l’aise avec Guerilla. Ils avaient travaillé avec une ancienne version pendant un long-métrage entier et découvrait également que beaucoup de leurs soucis avaient été résolus depuis.

Publier

On a choisi de versionner les séquences d’image de manière granulaire, à l’AOV (pass/layer/aov/<version>). Comme nous avions beaucoup d’AOV, il y avait énormément de versions à publier à chaque fois. On a fait une UI tout-en-un pour simplifier le travail de gestion des rendus des lighter (et aussi éviter qu’ils aillent se perdre et tout casser dans la hiérarchie de dossier :P). Sous le capot, l’interface était threadé à mort. Il fallait, en effet, s’assurer que le lighter voit, quand une séquence était incomplète, quelles images manquaient (et il y avait beaucoup de séquences). Le gros problème venait de Shotgun qui lâchait parfois prise et bloquait les publications sans raisons apparente, il fallait donc reprendre là ou il s’était arrêté (heureusement les cas d’arrêt pendant la copie d’une séquence d’image était rare).

Override à la séquence, par groupe de plan, puis par plan

Il est intéressant de constater qu’une des feature du pipeline qui permet d’économiser énormément de temps n’est arrivé que lors des six/sept derniers mois du projet. C’est quelque chose qui a été discuté très tôt, avant même l’arrivée du modeling. C’est un des trucs dont je suis le plus fier et qui a réellement augmenté la vitesse de sortie des plans. Le principe est de pouvoir overrider à la séquence mais surtout par groupe de plan. Dans la pratique, le lighter pouvait grouper les plans d’une même séquence similaires (exemple : champ/contre-champ) et appliquer des overrides pour chacun des groupes puis de propager sur toute la séquence. Ainsi, les lighter ne travaillaient plus au plan mais à la séquence. Les seniors ont rapidement sauté dessus. De manière surprenante, certains juniors ont également vite emboîté le pas. Ce n’était pas parfait, les rigs de light devaient toujours être propage manuellement et la UI de gestion des groupes n’était pas terrible, mais les séquences passaient en revu en entier très rapidement après avoir été commencé. La vitesse gagne en lighting sur certaines séquences simples était vraiment énorme.

Shot group

Il y avait deux façons de publier un rendergraph de lighting : À la séquence, et au plan. Le rendergraph de plan overridant le rendergraph de séquence. L’idée était que, quand un graphiste commençait une séquence, il remonte toutes les modifications nécessaires sur toute la séquence dans le rendergraph de séquence pour ne laisser dans le rendergraph de plan que les modifications spécifiques au plan. C’est une approche assez conventionnelle quand on travaille avec des overrides, car bien souvent, le pipeline permet de publier des choses à la séquence ou au plan. Mais elle laisse un trou énorme : Que faire quand on souhaite éclairer deux plans similaires. :reflechi:

Si par exemple votre séquence se compose de quelques plans d’intro (souvent large), puis d’un enchainement de champ/contre champ, identique en termes de lighting, puis trois plans de sortie, vous avez 4 groupes de plan :

  • intro (2 plans)
  • part_1_char_1 (4 plans)
  • part_2_char_2 (5 plans)
  • outro (3 plans)

Chaque studio semble faire sa tambouille mais après quelques semaines de travail, on a commencé à réfléchir a un moyen de publier des choses « par groupe de plan ». Et ne croyez pas que c’est évidant. Sur un plan purement ingénierie, cette approche est « anti-hiérarchique » dans un pipeline, car si la hiérarchie « studio/projet/séquence/plan/cam » est fixe, les groupes de plan peuvent être défini différemment suivant qu’on est en lighting ou en animation (ou autre). Il s’agissait donc d’une structure par séquence (il fallait bien la mettre quelque part) non connu à l’avance, donc difficilement structurable.

Les lighters avait donc moyen, par séquence, de faire des groupes de plan. Ils visualisaient la séquence et commençait déjà à réfléchir comment ils allaient publier chacun de leur rendergraph.

Au moment de construire le plan, on récupérait le rendergraph publié au plan, puis on demandait le groupe dans lequel était le plan en cours, puis on récupérait le rendergraph publié dans ce groupe. Les rendergraph s’enchainaient dans cet ordre : « sequence/shot group/shot ».

Cette méthode est arrivée très tard sur le film (je dirais le dernier quart en termes de planning) mais elle a permis quelque chose d’énorme : Les lighteurs pouvaient prendre et éclairer des séquences complètes. Ça prenait un peu plus de temps à démarrer (comparé à un éclairage au plan) mais quand ils avaient fini, ils envoyaient toute leur séquence en rendu et l’itération se faisait par séquence.

Un autre effet fut que l’éclairage était beaucoup plus cohérent entre les plans. Très souvent, les éclairages au plan tendent à casser l’homogénéité de la séquence. Ce sont les lead qui veillent constamment a l’homogénéité de l’ensemble (éclairage, couleur, etc.), mais malgré ça, ça se voit toujours. Le fait de repousser la modification par plan aussi loin que possible permettait de sucrer une bonne partie des retakes d’homogénéité. Au final, le rendergraph de plan était quasiment vide d’information d’éclairage.

J’avoue ne jamais avoir vu de système semblable aussi pousse. Bien entendu, ce n’est pas parce que je n’en ai pas vu que ça n’existe pas. Mais bien souvent ce sont des outils de propagation qui permettent d’envoyer l’éclairage d’un plan dans un autre plan, pas une publication entre la séquence et le plan.

Render farm

Disons-le clairement, la gestion de la render farm n’était vraiment (mais alors vraiment) pas quelque chose qui m’attirait. Et pourtant, ça été très intéressant. Et pour cause, la render farm ne concerne pas uniquement le rendu. C’est de la puissance disponible pour de l’automatisation de tâche. Et on en a bien usé:

  • Génération des alembic en sortie du modeling, de l’animation et des fx.
  • Export automatique des séquences de .fur (Yeti) en sortie du département d’animation.
  • Build et calcul des ambiant occlusion pour le contrôle de qualité des animations.
  • Trigger lors des validations.
  • Mise à jour automatique des plans de lighting avant rendu.
  • Build et rendu des precomps.
  • Et bien entendu : Rendu des images

On a utilisé Qube. Un truc qu’il faut savoir concernant les gestionnaires de ferme de rendu c’est le “bruit réseaux” qu’ils produisent. Le nombre de machine augmentant (certaines n’étaient pas situe dans la boite mais à plusieurs une centaine de mètres du studio), il peut arriver qu’une quantité non négligeable des accès réseau ne soit prise que par le gestionnaire de ferme de rendu qui communique avec ses clients. Le problème apparaît lorsqu’il y a congestion ou chaque client a besoin de contacter le serveur sans que ce dernier ne soit capable de répondre, s’ensuit un effondrement des performances générales. Certains gestionnaires, plein de fonctionnalités qui se veulent pro-actifs (vérifier que toutes les images sont sorties, qu’elles ne sont pas corrompues, etc.) sont capables, de par leur activité, minime mais intrusive, de mettre à terre un réseau déjà bien occupé à charger des gigas de données. C’est un détail à prendre en compte quand on commence à monter en charge. Au-delà de ça, Qube a une API assez soviétique sur les bords, on sent le logiciel mature, stable et tu le payes par une API complexe.

Matte Painting

On ne peut pas vraiment parler de pipeline pour le département de matte painting, mais de support. C’était rafraîchissant : Transfert de caméras de projection entre Guerilla et Nuke (avec ce sentiment de satisfaction quand on attend enfin le pixel-perfect). J’ai également pu constater à quel point Nuke était mauvais en 3D et à quel point un “vrai” logiciel de matte painting manquait. Je ne parle bien évidemment pas pour la peinture digitale mais pour la gestion de la 3D (projection et manipulation de la géométrie).

Commentaire de plan

Sur un long-métrage, chaque plan a une histoire. Entre le nombre de département qui passe dessus (modeling, layout, animation, rendu, compositing) et les allez-retours de validation entre chaque étape, chaque personne ayant travaillé sur le projet a une d’histoire à raconter. En revoyant le film, je me suis dit que j’avais envie de commenter les plans. C’est parti !

Voici un plan typique d’arbres et d’herbe. Je pense qu’il y a eu une difficulté de communication autour du placement des arbres. Aucun décor breton (et français d’une manière générale) ne ressemble a ça, les arbres sont supposés délimiter les champs alors qu’ils sont placés de manière très aléatoire ici. Je soupçonne que l’esthétisme a été privilégié mais du-coup ça manque un peu de vie. Autre remarque sur Yeti : On l’a aussi utilisé pour placer des branches et des cailloux, mais on se retrouvait avec des bounding box énormes pour finalement peu de géométrie, ce qui a pas mal ralenti le rendu.

Le décor de l’orphelinat, l’un de mes préférés.

Il est à noter que cette pièce est utilise à la fois pour la cuisine et pour le dortoir. Les lits remplaçant les tables. Ça passe super bien dans le film et ça a permis de se focaliser sur une seule pièce.

Je ne peux plus vérifier, mais je crois que ce plan a été rendu dans les derniers, quand la farm était quasi vide et mettait 14 h l’image :aupoil: . Si je me rappelle bien, on savait que c’était lié à tous les rochers et branches par terre, mais on a décidé de ne pas trop chercher plus loin.

La boite à musique, ou comment un plan totalement anodin peut rendre fou. Dans Maya les sous frames de l’animation étaient parfaites, mais une fois exporte en alembic puis réimporte, le motion blur explosait certaines pièces (notamment le triskèle). C’était devenu un running gag… Je ne sais même plus comment on a fini par résoudre le souci, mais je ne serais pas surpris qu’on ait totalement désactivé le motion blur 3d sur ce plan.

Les escaliers sont souvent une tanne à rendre, mais je trouve que l’équipe lighting s’en est sorti à merveille.

J’adore cette séquence de nuit. Le fait d’avoir une seule source principale de lumière (celle de la moto) donne à la séquence un aspect dramatique. Encore une fois, je pense qu’on a trop négligé le placement des arbres, ça manque de vie.

Notez le renfoncement de la route sur toute cette séquence. L’objectif, vous vous en doutez, est d’éviter d’avoir à travailler l’horizon sur l’ensemble des plans.

Et voila un keyshot. Le principe d’un « keyshot » (ou « plan-clef ») sur un long-métrage (et en animation 3d d’une manière générale) est de valider l’éclairage type d’une séquence (couleur, ombres et tout ce qu’il est possible de définir dès cette étape en fait). Ils sont donc souvent plus travaillés que les autres et permettent aussi de mettre le doigt sur les problèmes techniques avant d’entamer le travail à la séquence. Ce sont souvent les seniors qui font ses plans. L’objectif est de se représenter l’intégralité de la séquence et comment tous les plans vont être fait et de « passer la main » aux graphistes juniors qui (en principe mais là on rêve un peu) ajuste un éclairage donné sans se prendre la tête.

Le train a été utilisé pour faire quelque chose d’assez peu courant (longue explication en approche): Sur ce projet, le layout avait la possibilité de bouger les contrôleurs de certains objets des assets pour éviter la répétition. Un bon exemple sont les volets des maisons, les portes, les tables, etc. Le problème c’est que du-coup, les assets en questions ne sont plus vraiment en position d’origine ce qui est assez problématique, car vous ne pouvez plus simplement considérer, dans votre base de donne, qu’un shot contient une instance d’asset place a tel endroit, il faut aussi avoir la liste des modifications de placement quelque part. Très souvent (enfin j’ai vu ça partout jusqu’à présent), la solution retenue face à ce dilemme est : « Si ce n’est pas juste un déplacement du contrôleur global, c’est de l’animation » et donc, c’est exporté avec l’alembic d’animation du plan (qui contient les personnages et les props déplacés). Mais avouez que c’est bête d’imposer l’export par plan d’un asset au complet quand seul un des objets qui le compose (un volet, une porte, etc.) est modifie… On a donc décidé de se lancer dans une quête un peu folle consistant à récupérer les modifications de placement des sous objets au layout pour pouvoir les appliquer sur l’asset original lors de la construction du plan au rendu. Pour être honnête, on eut pas vraiment le choix, le layout avait fait un gros travail de placement (il y a des contrôleurs, ils les bougent, c’est normal) quasiment plus aucun asset ne correspondait a sa position d’origine… Il fallait donc, pour les assets en questions, stocker la position des objets qui ne sont pas à leur placement d’origine. Sauf qu’il peut y avoir une différence entre le placement d’un contrôleur (que le layout déplace) et le placement de la géométrie qu’il contrôle. Le rig garantie (en principe, mais ce n’est pas le problème ici) que la relation de position entre un contrôleur et la géométrie qu’il contrôle est toujours la même. Mais il ne garantit pas que l’origine de la géométrie en question soit constante entre les versions de rig. Pas grave me diriez-vous, c’est pas le truc qui change souvent… Et devinez quoi ? Oui, c’est ce qui c’est passé, l’origine des géométries bougeait entre les versions de rig :smileFou: . Rappelez-vous, le rig n’a été défini que très tard sur le projet et chaque choix se confrontait a ce qui était déjà en place. On ne pouvait donc pas s’appuyer sur la position des géométries mais uniquement sur celle des contrôleurs… Bon, on a les positions des contrôleurs modifiant un asset au plan, mais comment je connais la relation avec la géométrie ? C’est ici que les histoires sérieuses de sanity check on commencées. Il a fallu être extrêmement rigoureux sur la façon dont les contrôleurs « non-déformant » étaient connectées aux objets qu’ils contrôlaient. De sorte qu’il n’y eut qu’une simple matrice (intitulée sobrement offset matrice ou « matrice de décalage ») à appliquer sur la position en espace monde du contrôleur pour obtenir la position en espace monde de la géométrie (matrice du contrôleur + offset matrice = position identique dans Maya et Guerilla !). Il fallait donc stocker, par publication de rig, l’offset matrice de chaque contrôleur « non-déformant » puis l’utiliser lors de l’import d’un asset dans un plan. Mais attendez ! Attendez ! C’est même pas fini en plus lol ! Certains objets nécessitaient une hiérarchie de contrôleurs non-déformant et il fallait que mon bordel fonctionne avec eux aussi ! XD Il fallait donc stocker des numéros indiquant la profondeur du contrôleur pour appliquer les offset matrice dans le bon sens ! :aupoil: Le wagon était le premier assez du genre. La porte du wagon étant coulissante et compose d’un second objet (la serrure de la-dite porte). Je me rappelle de ma scène Guerilla que je passais mon temps a builder en tournant mon wagon et les contrôleurs de la porte et de la serrure dans tous les sens, a tous les niveaux de la hiérarchie en croisant les doigts pour obtenir le même résultât. J’ai du y passer une ou deux semaines à plein temps en mode chien méchant mais ça été super robuste car c’est une partie du code que je n’ai plus du tout touche par la suite.

Cette séquence dans le wagon me fait toujours rire car Victor allume et éteint une lampe à huile en la touchant vaguement et certaines pommes sont posées sur des surfaces plates sans bouger alors que les plans subissent un shake cam pour simuler le mouvement des wagons :sourit: .

Éclairer le contenu d’une boite fermée… Tout un programme. Si je me souviens bien les planches du fond et du dessus n’étaient pas visible des lights. Vous pouvez le remarquer sur les cheveux et le bras de Félicie. Les pommes étaient faites en particule. Je me rappelle avoir bossé sur un moyen de faire des variations de teinte sur le lookdev des pommes suivant un attribut de particule. Un effet subtil de variation de teinte.

Un des money shot du film. Un money shot (qui peut se traduire de deux façons suivant qu’on l’achète ou suivant qu’on le budget :hihi: ) est un plan qui est caractérisé par le cout nécessaire a sa fabrication et par l’effet Woaw ! qu’il est supposé engendrer chez le spectateur. Celui-ci part du pont d’Iéna, passe entre les fondations de la tour Eiffel puis fini sur une vue d’ensemble. C’était LE plan test du builder. Beaucoup de bâtiment, beaucoup de géométrie, beaucoup de personnages, beaucoup de spéculaire, beaucoup de textures, beaucoup de matte painting, etc. Paradoxalement, le fait d’anticiper ces plans très tôt (dès le layout tu te fais une idée de la difficulté) fait qu’au final il n’a pas pose de problèmes majeurs. Les problèmes vraiment contraignant arrivent souvent sur des plans totalement anodins.

Celui-là je ne mets pas parce qu’il est joli ( :trollface: ) mais pour la petite histoire : Pour une raison qu’on ignore totalement, la texture des bouées (sur les bords du bateau) popait au rendu. On a jamais compris pourquoi et malgré tous nos tests (hashing des textures, hashing des uvs, compression, etc.) on a pas eu le temps de régler le souci suffisamment rapidement. Du-coup (et après discussion) elles ont été supprimées du bateau. Notez que ce n’est pas la règle. On ne supprime pas un truc à chaque fois qu’il nous embête, simplement qu’il faut constamment prioritiser les choses à faire, et parfois il faut trancher. Mais ce n’est jamais fait de gaité de cœur.

Ce plan (et la séquence d’une manière générale) fut le plan de test. On y est reste longtemps pour affiner nos méthodes d’exports d’alembic, de rendu sur la farm, déterminer quels AOVs on sort… Bref, pousser le pipeline pour faire, ce que j’appelle, la première boucle (un pipeline qui marche du début jusqu’au plan final composite). À l’époque il n’y avait pas de lighters ni de compositeurs, seuls les superviseurs de ces deux départements étaient présents. C’est, je trouve, un des plans les plus travaillé du film. La subtilité du rendu du sol ne se retrouve sur aucun plan. Il est aussi moins sature que le reste des plans.

Le plan qui suit. Notez la qualité du SSS de la peau, assez différente du reste du film.

Juste pour préciser qu’il n’existe aucun axe dans Paris qui permet cette vue sur l’opéra. :jdicajdirien:

Encore un plan de cette séquence que je trouve magnifique. C’est exactement comme Paris : Des pavés luisants avec un petit brouillard de fond. Ce cadrage est repris plusieurs fois dans le film mais le rendu n’a rien à voir.

Les pavés sont 100 % displacement. On a essayé en normal map et tout mais vers la fin du plan, le sol apparaissait beaucoup trop plat.

Anecdote intéressante, le temps de rendu de l’AOV des pavés sur ce plan prenait énormement de temps car, étant en displacement ET de biais, les rayons de la caméra faisaient des tests d’intersections sur beaucoup de triangles avant d’en toucher un. Ce n’est pas forcément une bonne tactique d’avoir de gros temps de rendu sur des plans comme ceux-là qui risquent d’exiger beaucoup d’itérations avant d’être validé.

Ce décor a été fait sur plan. On avait énormément de livres au studio sur l’Opéra de Paris et même une petite maquette carton. Ce fut aussi un des candidats pour l’outil de récupération d’instance implicite car nombre d’objets se répètent. J’ajoute qu’il ne fut pas simple du tout à éclairer. Sur des plans rapprochés, on remplaçait les lights hors cadre chacun des lampadaires (4-5 par lampadaire, sans compter les bougies) par une seule light, plus grosse, mais a l’intensité et la couleur globale similaire. Cette méthode de « dégrossissement » du lighting permettait de diminuer le nombre de lights sur un plan (et donc diminuer le temps de rendu et le grain) sans modifier le retour visuel. Donc oui, gros travail sur ce décor.

Je vous présente mon personnage favori sur ce film : Odette. J’avais très peur que ses vêtements à base de laine ne passent pas ou mal à l’écran. Au final je trouve que ce sont les vêtements les mieux réussi du film. L’écharpe et le petit drape sur les épaules sont faits en displacement pour l’épaisseur de la laine. Ça fait toute la différence.

J’ai remarqué un truc sur les longs-métrages : L’attachement des différentes personnes travaillant sur le projet aux personnages du film est réel et souvent révélateur de la profondeur du film. Si sur un projet, aucun personnage ne semble intéresser les gens ou donner envie d’en savoir plus, c’est que quelque chose n’est pas bien passe. Je ne parle pas d’animation, mais de chara-design : Le faciès, l’attitude, la voix et l’histoire du personnage doivent questionner, donner envie que le personnage réussisse (ou perde dans le cas du méchant). C’est assez caractéristique dans les films « commerciaux » ; il faut réussir à développer suffisamment de personnage pour qu’une cible de spectateurs puisse s’identifier. Merante avait aussi une histoire très développée.

Les plans de nuit sont rares dans les films d’animation. Pourtant, une grande partie de Ballerina se passe la nuit ce qui donne des effets super intéressants. L’éclairage du visage d’Odette par la lampe (blanche et froide vous aurez remarqué) de la grande méchante, ainsi que l’alternance classique bleu marin/orange cache une décision plus rationnelle : À l’origine, énormément de plans devait se dérouler dans les rues de Paris. Une des premières décisions fut de s’arranger pour que ces plans se passent de nuit de manière à diminuer le nombre de personnage secondaires. C’est encore plus tard que presque tous les plans de Paris disparurent au profit de plans dans la cour intérieure.

L’éclairage des escaliers se révèle toujours assez compliqué. En effet, il faut beaucoup de lumières éclairant différentes parties distinctes, mais le path tracer a souvent du mal à deviner quelle lumière éclaire quelle partie, ce qui amène facilement du grain.

Ce plan fut assez compliqué à faire en raison du nombre de miroir et d’AOV nécessaire a la recomposition de l’image. En effet, quand on a une réflexion pure (un miroir) il faut trouver un moyen de propager les AOV dans la réflexion pour pouvoir les sortir séparément. Ensuite, il faut recompositer chacun des miroirs pour finalement les intégrer au plan. Bon, le problème vient du fait qu’il fallait aussi fournir une Z de qualité pour la version stéréo. Il fallait donc aussi propager la Z.

Ce plan fut mon plan de test pour les outils de projection en matte painting. J’avoue ne plus me rappeler du tout pourquoi la projection était nécessaire mais que j’étais trop fier quand mes petits calculs me rendaient une projection « pixel-perfect » du rendu dans Nuke !

Le directeur de l’Opéra fut le premier adulte en lookdev. Il a été utilisé pour par mal d’expérimentation concernant le rendu des visages et en particulier le nez qui devait avoir des bords bien définis. L’origine remonte a une décision de rig qui avait demande au modeling de diminuer la complexité des maillages des visages, cassant ainsi les bordures du nez. Je pense qu’on aurait pu faire différemment, mais je n’avais pas mon mot à dire. Bref, donc : À la charge du rendu d’afficher quelque chose de convaincant. On est naturellement parti sur des normales mais le problème du normal mapping basse fréquence c’est qu’il commence à devenir bizarre en gros plan, quand l’axe de la caméra devient tangent à la surface (en faisant apparaitre une sorte de liseré sur la couche de réflexion). J’ai donc dû me pencher sur un peu de math pour proposer un moyen de switcher du normal map au displacement suivant les plans. Pour être honnête, je ne suis pas sûr que le displacement fut utilise sur beaucoup de plans.

Il a eu un truc de vraiment problématique avec les intérieurs de l’Opéra de Paris et en particulier ce plan : Tout est plat et répétitif. Je me rappelle d’un couloir tellement basique que le DA était assis près du superviseur ligthing pendant plusieurs jours pour réussir a faire un truc « regardable ». Au final, la réalisation et l’animation des personnages prends le dessus et on y attache peu d’importance mais oui, éclairer des murs plats ce n’est pas la joie.

Cette pièce est le premier « gros » intérieur qui a été préparé pour le rendu. Il apparait en effet sur beaucoup de plans du teaser. Lui aussi était dur à aborder car si on enlève les parquets, il y a peu de zones vraiment intéressantes en termes d’éclairage. Notez aussi que tout l’éclairage est diffus et il y a peu d’éclairage direct. Anecdote intéressante : Un grand miroir se situe au centre de la pièce mais posait pas mal de soucis autant techniques que narratifs. Au final, un grand drap a été mis dessus ni vu ni connu.

Ici, la manche de Victor est en gros plan. Le lighting a donc choisi d’appliquer du displacement pour ajouter du détail et de la nuance dans la forme. Mais comme le rig n’était pas recentrable, les vertices de la géométrie vibraient légèrement. En soi, ce n’est pas trop problématique quand les vertices sont éloignés les uns des autres. Mais quand on displace, il y a un vertice tous les deux/trois pixels, du-coups le flickering commence à se voir (sous la forme d’un léger « bourdonnement » de la manche). Comment régler ce souci comme un vrai pro ? On prend la scène d’anim, on décale le personnage d’une distance particulière en vu de le rapprocher du centre (2000 en x par exemple), on ré-exporte l’alembic, on met à jour l’alembic dans Guerilla, puis on décale le personnage de 2000 en x dans l’autre sens. :aupoil:

Ce plan séquence fut surement le plus compliqué du film. Il a pris plus d’un mois a un graphiste senior à plein temps pour en venir à bout. Chaque personnage était présent deux à trois fois dans la scène et le layout les a faits s’alterner pour donner l’impression d’une continuation. L’éclairage était un cauchemar (extérieur, intérieur puis extérieur) du-coup beaucoup de choses ont été séparé ce qui est très risqué car cela entraine souvent de la mauvaise intégration et une difficulté à garder un éclairage cohérent (c’est souvent le cas sur les plans « sur-composités »). Et pourtant, j’avoue ne pas lui trouver de défauts. Franchement le boulot est impeccable de bout en bout.

Regardez les variations de positionnement des volets. C’est à ça qu’a servi le travail que je vous exposais plus haut avec l’histoire de la porte du wagon. Vous allez me dire que tout le monde s’en fout mais tous les objets ont bénéficié d’un travail de cadrage (on parle souvent de « set-dressing ») de la part du layout et je pense vraiment que ça rend l’image plus naturelle.

Cette séquence fut une des premières à être éclaire en utilisant le principe des shot groups, par un seul graphiste. L’ensemble est hyper homogène.

Hahaha ! Je me rappelle bien cette séquence : L’échelle du projet était de 1 unité = 10 cm. C’est peut-être peu commode mais ça résolvait pas mal de soucis. C’était un bon compromis. Le FX guy avait mal configuré son échelle de décimation. Du-coup, le premier export des volumétriques de ce plan était monstrueusement énorme, genre un triangle par pixel ! Mais le pire c’est qu’on avait mis en place un système qui appliquait une subdivision de 1 a tous les mesh :IFuckTheWorld: . Resultat.

Le toit de l’opéra était un des assets les plus massifs en termes de travail pour les textures. Les instances implicites ont eu un gros impact sur le quotidien des graphistes travaillant sur cet asset.

L’atelier fut le plan de test ultime pour la builder. Il y a des objets partout, dans toutes les positions. Si ça build correctement, tout le film devrait marcher (pas vrai ? :siffle: ).

Dans le bar breton, un des drapeaux fait référence à l’endroit où ce film a été fabriqué. Saurez-vous trouver lequel?

Un plan pour lequel je me serai beaucoup battu, mais qui aura eu raison de moi. Je ne sais pas si vous avez déjà fait des soirées (nuits ?) à Paris mais la réflexion des éclairages publiques sur les pavés (très sombres) est très présent, quand bien même il n’a pas plu. Sur ce plan la réflexion des pavés était trop plate, car la normal map semblait devenir neutre après quelques mètres, donnant un effet tout lisse. Malgré mes tentatives pour redonner un peu de consistance au sol, la réflexion a été très atténuée pour pouvoir livrer à temps. Au final il passe très bien dans le film. J’ai juste un blocage personnel dessus.

OK, j’avoue, ce projet a développé en moi un fétichisme pour les vieux parquets bien lustrés… :pasClasse:

Pour faire valider les diamants de la couronne de ce personnage, les lookdev a dû honteusement tricher en augmentant l’intensité de ces derniers aux points qu’ils créaient de la lumière. Path tracer oblige, on se retrouvait avec des points blancs sur les plans ou ce personnage apparaissait. On a mis un peu de temps à trouver, mais des petits points blancs dans un plan (appelés fireflies) sont souvent dû à un shader qui renvoi une haute valeur.

Comme bien souvent avec les « trucs à plume », la poule est un asset qui a demande beaucoup de travail, avec du Yeti et quelques morceaux de shader écris pour l’occasion. Un des running gag original du film consistait à la faire revenir plusieurs fois a l’écran tout au long du film.

Ce plan est très différent des autres en termes de colorimétrie. On est beaucoup plus sur des teintes Pixar/Illumination. Au passage, le personnage de la mère de Félicie fut la favorite d’une partie de l’équipe pendant longtemps mais le fait qu’elle apparaisse qu’une seule fois (sur un plan fait vers la fin de la production), n’a, je pense, pas permis aux différentes personnes intervenants dessus d’y passer le temps nécessaire.

Tu passes une prod à régler les soucis de hairs des personnages, les uns après les autres. Au bout d’un moment tout marche, tu penses que les problèmes de hair c’est fini, tu as déjà fêté ça il y a deux mois et BAM ! Tu as un nouveau plan qui tombe un peu avant la fin du projet. Avec au programme, un nouveau perso, visible uniquement sur ce plan, en gros plan avec les cils et les sourcils qui flickent !

Je vais finir ce commentaire avec deux plans et un petit mot concernant l’animation. On l’entend souvent, l’animation est le truc le plus important et c’est vrai : Si les personnages ne sont pas « vivants », c’est terminé. Le lighting et le compo n’y pourront pas grand-chose. Le chara-design de Ballerina c’est pas le plus simple à aborder. Pour une raison qui m’échappe (je ne m’occupais pas du département anim), je trouve l’animation sur le projet inégal, mais il faut avouer que certains plans sont de belles réussites. Le plan du dessus est le tout dernier d’une séquence qui monte en puissance ou Félicie, malgré n’avoir plus aucune chance de devenir ballerine enfile ses chaussons, commence quelques pas puis fait des gestes de plus en plus complexe pour finir sur une pirouette plein plan le regard vers le dos de la caméra (Paris) avec deux sentiments en même temps sur son visage. Un sentiment clair, c’est bien pour du cartoon. Mais ce qui rend un personnage en 3d humain c’est en grande partie la manière dont il exprime (ou tente de cacher) l’ambivalence de ses sentiments. Ce sont des attitudes qu’on retrouve fréquemment dans le film. Disney excellait dans sa capacité à le faire en 2d et peu de films y arrivent vraiment. Je trouve que Ballerina s’en sort très bien là-dedans.

Conclusion

Il est bien évident que tout ceci est un effort collectif, nous n’étions jamais seuls à faire des choix et c’est sûrement ce qui a permis au projet d’aboutir. Je n’ai pas nommé les personnes, mais il me semble important de rappeler que c’est pourtant avec de l’humain que tout se joue, du haut de la hiérarchie jusqu’au graphiste parfois derrière des tableaux à vérifier que l’intégralité des retakes des plans ont été faites (et pour qui je peux vous garantir que ce n’est pas la tasse de café). Si personne ne le veut, le film ne sort pas, c’est aussi simple que ça.

Je ne parle pas d’aller se tailler les veines à faire des heures supplémentaires pendants des mois pour le plaisir de montrer qu’on souffre à la tâche mais au contraire d’une volonté farouche que tout ce passe pour le mieux à tous les niveaux et sur la longueur. Je n’ai dû faire qu’une vingtaine d’heures supplémentaires (pour finir et peaufiner le builder si ne me souvient bien car « Pas d’builder : Pas d’projet… »). Le fait de voir qu’il y a une volonté générale de réussite du projet et de bienveillance mutuel (OK je m’enflamme peut-être un peu sur le dernier mais quand même c’est l’idée) pousse les gens à fournir l’effort supplémentaire nécessaire à la sortie d’images propre et livrées dans les temps. La peur de se faire virer n’est pas déterminante, chacun sait qu’une fois le projet fini on passe (presque tous) à la porte. À partir de là, ce qui compte pour chacun c’est de faire un travail dont il est fier. À quoi bon livrer des images, sensé divertir les gens qui les regarde, faites dans la tension et dont tous le monde garde un gout amer ? À mes yeux, et malgré un double démarrage difficile, Ballerina semble également avoir réussi sur ce terrain et pour un premier long-métrage, c’est la classe ! :laClasse:

À bientôt !

Dorian

:marioCours: