Lors de l’import d’une caméra Alembic, Nuke échantillonne l’animation à la frame. C.à.d qu’il lit les valeurs de l’Alembic à chaque frame. C’est la raison pour laquelle il demande un frame rate :

Interface Nuke d’import de caméra

C’est parfait dans le cas d’un Alembic de caméra samplées à la frame, car chaque frame Nuke correspondra à un sample de votre Alembic. Il y aura donc une correspondance directe entre les samples de la caméra exportée et ce que Nuke lira.

En pratique on peut travailler comme ça sur la plupart des projets, alors pourquoi s’embêter ? :perplex:

Pourquoi sur-sampler une caméra ?

Quand vous avez régulièrement des mouvements de caméras très rapides dans vos plans, le fait de faire un export Alembic à la frame perds la profondeur du mouvement dans le motion blur, au rendu.

L’exemple le plus évident concerne les shake cam. Quand un shake cam un peu ample est samplé à la frame, chaque image se retrouve avec une sorte de flou directionnel dont la direction est aléatoire, ce qui n’est pas du plus bel effet.

Sur-sampler la caméra permet de garder la profondeur du mouvement de shake.

Bien entendu (et c’est trop souvent le cas en production) si la fréquence du shake cam entre les frames est trop importante, vos samples internes seront quasi-aléatoires, et vous aurez l’équivalent de micro-vibrations à la frame, ce qui n’est pas du plus bel effet :

Courbes de caméras superposées

Ici, la belle courbe verte est le mouvement théorique du shake cam (le résultat de l’expression). On remarque que la fréquence est élevée entre les frames. La courbe orange est la courbe de l’Alembic exporté de cette caméra avec les samples (0, 0.125, 0.25, 0.375, 0.5) marqués en rouge. On remarque que la haute fréquence originale entraîne un sampling foireux du mouvement de caméra.

Par contre, un export de caméra sur-samplé d’un shake cam avec une fréquence faible entre les images (une demie période max) donnera une profondeur au motion blur.

Bref, on sur-sample pour les shake cam, mais uniquement si on arrive à garder leur fréquence a niveau de la frame… :tuComprendRien:

Un autre cas où le sur-sampling est justifié concerne les rotations de caméras rapides (un classique étant un objet qui passe devant la caméra très rapidement). Pour peu que cette rotation soit combinée à un déplacement et soyons fous, un shake cam, si vous ne sur-samplez pas, il y a fort à parier que le mouvement central soit une grosse bouilli, illisible.

Attention toutefois : Comme nous allons le voir, sur-sampler une caméra n’est pas gratuit et implique que tout ce qui utilisera ladite caméra soit capable d’interpréter correctement ces samples. Donc si votre projet n’a ni shake cams, ni mouvements rapides : Laissez tomber. Vous aurez sûrement d’autres problèmes à gérer.

Mais si vous êtes ici, c’est sûrement parce que vous avez déjà rencontré le problème, pas vrai ? :dentcasse:

Comportement de Nuke

Quand vous importez votre caméra Alembic dans Nuke avec le bon frame rate, ce dernier va créer une clef à chaque frame. Le comportement de Nuke est très con :

Il avance d’une frame. Prends la valeur des attributs dans l’Alembic, sans interpoler (nous y reviendrons), pose une clef pour ces attributs et passe à la frame suivante. C’est tout. :baffed:

Le problème

Une fois qu’on connaît le comportement de Nuke, vous comprenez aussi que si vous avez une caméra avec 5 samples (0, 0.125, 0.25, 0.375, 0.5), il ne lira et ne créera les clefs que sur le premier sample de chaque cycle (t=0). Il ne prendra ainsi pas compte des 4 samples intermédiaires (0.125, 0.25, 0.375, 0.5) ce qui peut être un vrai problème si vous souhaitez faire un rendu 3D dans Nuke, et si vous importez une caméra animée dans Nuke, c’est sûrement pour ça (je pense au matte painting).

Contourner le problème

Sachez qu’il existe un moyen détourné de forcer Nuke à lire tous les samples de notre Alembic et obtenir un mouvement de caméra sur-samplé (Merci à Vincent Glaize pour l’astuce). :gne:

Pour cela, il faut jouer sur la valeur de frame rate du nœud Nuke. L’idée est d’augmenter le frame rate de lecture de l’Alembic pour attraper tous les samples, pour ensuite scaler la vitesse de lecture suivant un ratio inverse.

Pas de panique, on va procéder par étapes. :hehe:

On a donc une caméra Alembic exporté en 24 fps, venant d’une scène en 24 fps (si je précise, c’est parce qu’il n’est pas rare de se faire avoir :gniarkgniark: ).

La caméra est exportée avec cette commande MEL :

AbcExport -j "-frameRange 1 2 -frameRelativeSample 0 -frameRelativeSample 0.125 -frameRelativeSample 0.25 -frameRelativeSample 0.375 -frameRelativeSample 0.5 -dataFormat ogawa -root |camera1 -file ma_super_cam.abc";

Voici la sortie de la commande abcls :

$ abcls -t ma_supe_cam.abc

Time Samplings:
0 Uniform Sampling. Start time: 0 Time per cycle: 1
Max Num Samples: 1
1 Cyclic Sampling. Time per cycle:0.0416667
Start cycle times: 0.0416667, 0.046875, 0.0520833, 0.0572917, 0.0625
Max Num Samples: 10

Au passage : Peu de gens le savent, mais un fichier Alembic stock ses samples en secondes, pas en frames.

Multipliez ses valeurs par le frame rate correspondant à votre export de caméra (ici 24) pour obtenir qu’équivalent en frame :

>>> samples = [0.0416667, 0.046875, 0.0520833, 0.0572917, 0.0625]
>>> [sample * 24 for sample in samples]
[1.0000008, 1.125, 1.2499992, 1.3750008, 1.5]

Si on fait fi des problèmes de précision dûes à la sortie de la commande abcls, on obtient : 1.0, 1.125, 1.25, 1.375, 1.5. On a donc bien nos 5 samples aux bonnes positions.

Voici les courbes d’animation du translate Y de ma caméra original et son équivalent Alembic, en superposées. La courbe verte est l’animation originale de la caméra, la courbe orange, celle de l’Alembic :

Notez que cette animation va de l’image 1 à 1.5, la position des samples est en rouge.

Si on amène ça dans Nuke à un frame rate de 24, on ne verra rien, car la position du sample sur l’image 1 (et 2) est à 0 :

Donc quelle valeur de frame rate mettre pour faire correctement apparaître ces samples dans Nuke ? :reflexionIntense:

L’écart entre chaque sample est : 0.125 × la durée d’une image. 1/0.125 = 8, il y a donc 8 samples par image. Il faut donc multiplier le frame rate original par 8 pour avoir tous les samples de façon précise : On va donc entrer une valeur de frame rate de 24 × 8 = 192 dans notre nœud Nuke :

Vous l’aurez compris, on dit à Nuke qu’il n’y a pas des samples tous les 1/24 secondes, mais 1/192 secondes. Il va donc aller chercher, dans l’Alembic, la valeur des attributs à ces temps-là en pensant que c’est une frame. :laClasse:

Aparté sur l’interpolation

Je vous disais que lorsque Nuke cherchait les valeurs des samples, il n’interpolait pas. Ça veut dire qu’il faut que Nuke tombe à l’endroit exact où vos samples sont placés. Multipliez la valeur de frame rate par 5 (192 × 5 = 960), et regardez la courbe :

Explication : Quand Nuke tombe sur un temps qui n’a pas de sample dédié, il remonte au sample précédent, sans interpoler, prends sa valeur, et mets la clef. Il fait une sorte d’écho du sample précédent.

D’où l’importance de tomber exactement sur les samples exportés. :nevroz:

Bon, on a réussi à avoir l’entièreté des sur-samples pris en compte par Nuke, mais notre animation de caméra est maintenant 8x plus lente… Il va falloir scaler le temps. Pour cela, nous allons recréer une caméra identique, mais nous allons reconnecter les attributs via une expression multipliant le temps par 8 pour l’attribut en question :

Ici, Camera_originale est mon nœud de caméra pointant sur l’Alembic et lu à un frame rate de 192.

Camera_mirror est une caméra vide créée manuellement avec des expressions pour relier chaque paramètre :

Par exemple :

Camera_originale.translate.y(t*8)

Ça fait pas mal de paramètres à reconnecter, mais vous pouvez faire ça via un script où le faire manuellement une fois et garder votre setup.

Une fois cela fait, mettez un nœud de rendu, ajouter quelques samples, calez votre shutter (ici, 0.0 - 0.5) :

En enfin, rendez :

Votre motion blur contient bien l’entièreté du mouvement. :banaeyouhou:

Limitations

Avant de finir il est important de garder quelques limitations en tête. Il est toujours assez difficile de faire des rendus cohérents à travers différents moteur, du fait des spécificités de chacun. Les moteurs de rendu de Nuke ont bien moins de features que les autres. Par exemple, votre contrôle sur la distribution des samples le long du shutter n’est pas pilotable ; dans la plupart des moteurs on peut alterner entre une distribution uniforme, en triangle, gaussienne, trapèze, etc.

Conclusion

Gardez à l’esprit qu’il n’est pas toujours nécessaire de s’embeter avec ça. Mais dès que ça bouge vite et que vous passez dans plusieurs logiciels de rendu pour un seul plan, vous risquez de ne pas pouvoir y couper.

J’espère que ce hack vous permettra de vous dépêtrer de quelques soucis fâcheux. :seSentCon:

À très bientôt !

:marioCours: