Aide pour After Effect, techniques, expressions.

lundi 18 janvier 2010

ombre et shine

Bonjour à tous.

Tout d'abord, sachez que ce post est la suite du précédent, donc si ce n'est déjà fait, lisez le, car il y a ici plein de choses que je ne réexplique pas.

Suite au post précédent, il est assez logique de voir comment continuer dans la même direction, à savoir que des éléments lumineux soient fonction d'angles.
Nous avons vu comment faire en sorte que la puissance volumétrique d'une lampe soit fonction de son angle par rapport à la caméra.

Voyons à présent le même principe appliqué aux ombres volumétrique.
Vous vous souvenez parfaitement du toComp et ses copains, que nous avions vu ici.
Nous y avions vu comment transformer un point 3d en un point 2, pour l'utiliser par exemple sur un effet.
Dans la 2ème vidéo, on voyait clairement que le "yes we can" avait un shine noir dont la source suivait les coordonnées 3d de la lampe.

Nous allons faire exactement la même chose, mais ce coup-ci, nous allons faire varier la puissance du shine selon l'angle de la lumière avec l'objet.
Et oui, c'est logique, le shine noir (l'ombre) donc, n'apparaît que quand la lumière éclaire l'objet.
De manière générale, il n'y a pas d'ombre sans lumière; un peu de philosophie ne fait jamais de mal.

On comprend donc qu'on va avoir le même type de travail :
Plus la lampe pointe l'objet, plus le shine noir est fort.














J'ai volontairement ici laissé la lampe sans l'effet que nous avons vu précédemment, pour isoler le problème du jour.
Comme vous le voyez, ça fonctionne, avec quelques limites dont je parlerai à la fin.

Voyons ce petit diagramme, qui ressemble un peu au précédent :












L'objet est en haut, la lumière tourne, et on comprend ce qui se passe :
Le shine noir apparaît bien uniquement quand le cône de la lumière passe sur l'objet. Tout ça va donc être fonction du cône de la lumière et de son angle.
J'ai volontairement placé un cercle trigo, car ça va nous servir.

Créez votre petite scène, vous ètes des grands maintenant.
Pour ce qui est du shine, il y a celui de Trapcode donc, mais d'autres éditeurs propose le même effet.
En ce qui concerne celui de Trapcode, il faudra donc mettre "one color" avec du noir ou une couleur foncée, mettre le tout en mode "Multiply".
Créons donc une expression pour "Shine opacity".

P=position;
L=thisComp.layer("Lumière 1");
la=L.position;
lb=L.pointOfInterest;
lv=sub(lb,la);

C'est la même chose que dans le post précédent, la seule différence est qu'on a remplacé la caméra par l'objet.
L'autre différence, c'est que dans l'autre post, on réglait la diminution de la puissance en jouant sur la courbe qui va de 0 à 1.
Ici, on va utiliser l'angle du cone de la lumière.

cone=Math.PI/2-degreesToRadians ( thisComp.layer("Lumière 1").lightOption.coneAngle)/2;

Hou la vilaine ligne !!
Alors, c'est quoi ce truc. C'est assez simple, je vous explique comment ça va se passer.
Nous allons garder nos vecteurs qui nous permettent d'avoir une valeur qui va de 0 à 1.
Ensuite, nous allons transformer cette valeur pour qu'elle aille de 0 à PI/2 (c'est à dire le "haut" du cercle). Nous somme obligéé d'introduire la notion d'angle puisque nous allons devoir en introduire un.
Nous allons donc uniquement travailler avec le quart supérieur droit du cercle trigo, qui va donc bien de 0 à PI/2, PI/2 correspondant à une lumière qui point exactement l'objet.
Sauf que ce coup-ci, quand l'angle vaut 0 (et donc que la lumière est parfaitement dos à l'objet), la valeur vaut bien 0, mais doit y rester pour tous les angles environnant.
Et oui, les seuls valeurs non nulles ne doivent apparaître que lorsque la valeur approche PI/2, et plus exactement Pi/2-angleDuCone.













Regardez le schéma, et notamment les angles arcs rose et vert (qui sont égaux)
Le vert représente l'angle du cône de la lumière. Le rose représente l'angle de la lumière avec l'objet.
On comprend bien que quand l'angle lumière-objet vaut PI/2-angleCone, la valeur du shine noir va commencer à augmenter.
Continuons :

P_la=normalize ( sub(la,P) );
delta=add(P_la,lvn);
val=1-length(delta)/2;

Même chose que dans le post précédent donc, à l'exception de la caméra remplacer par l'objet.
val varie bien de 0 à 1, faisons le varier de 0 à PI/2.

angle=linear(val,0,1,0,Math.PI/2);

Voilà qui est fait.
A présent, la dernière ligne :

ease(angle,cone,Math.PI/2,0,100);

cone est bien notre valeur minimum, qui correspond donc bien à 0, et Math.PI/2 à la valeur maximum.
L'utilisation du ease plutôt que du linear est subjective elle permet juste de lisser un peu les transition.

Vous pouvez bien entendu remplacer le 100 par une variable.

A présent, voyons les limites de l'effet.
Comme d'habitude, la seule chose qui est prise en compte est le point d'ancrage de l'objet (donc pour un texte, penser bien à ce qu'il soit centré, et non aligné à gauche ou à droite). Ca ne prend donc pas en compte la largeur ou la hauteur du calque, et l'effet sera appliqué à l'ensemble du calque, même s'il n'y a que la moitié du calque qui est dans la lumière.

A cause de cela, rajoutons un paramètre glissière au calque appelé "correction", et écrivons ceci :

P=position;
L=thisComp.layer("Lumière 1");
la=L.position;
lb=L.pointOfInterest;
lv=sub(lb,la);
lvn=normalize(lv);
cone=Math.PI/2-degreesToRadians ( thisComp.layer("Lumière 1").lightOption.coneAngle);
correction=degreesToRadians ( effect("correction")("Curseur"));

P_la=normalize ( sub(la,P) );
delta=add(P_la,lvn);
val=1-length(delta)/2;

angle=linear(val,0,1,0,Math.PI/2);
ease(angle,cone-correction,Math.PI/2,0,100);

Voilà, comme ça , vous pourrez virtuellement augmenter ou diminuer l'angle du cône, pour que la puissance du shine noir se maintienne sur un angle plus ou moins large par rapport à l'angle réel.

vendredi 15 janvier 2010

éclairage volumétrique anisotropique

Bonjour à tous,

ça fait un bail, je vous l'accorde, mais comme je n'avais pas écrit de nouvelles expressions, je n'allais pas venir et raconter rien du tout.

Quand j'ai un problème technique dans After Effect, je cherche une solution, et quand la solution contient des expressions, ça vient logiquement s'échouer ici.
C'est le cas aujourd'hui, j'ai essayé de corriger une lacune du plugin Lux de Trapcode.

Ce plugin relavement connu est très pratique, puisqu'il vous permet de simuler un éclairage volumétrique, à savoir que la lumière soit filtrée par les particules dans l'air.

Vous trouverez tous les renseignements ici :
Trapcode Lux

Peut être existe-il d'autres éditeurs qui proposent un effet équivalent, mais je n'en connais pas d'autre.
En général, j'essaye d'éviter de parler de plugin, car ça ne concerne pas tout le monde, mais celui ci est assez connu.
Venons en au fait :
Le "défaut" de Lux (qui sera je l'espère corrigé dans un théorique 2.0 ?....) est que la puissance n'est que fonction de la puissance de la lampe, et non de l'angle de la lampe avec la caméra.

avec Lux :













avec Lux+saucisse:












Et oui, quand vous êtes dans une ambiance poussiéreuse, le faisceau filtré par les particules est beaucoup plus puissant (pour vous) quand la lumière est dans votre direction.

La raison en est simple, il faut considérer la poussière comme un volume à part entière, comme de la cire par exemple. La cire, ça n'est pas vraiment transparent, mais la lumière passe quand même à l'intérieur. Elle se diffuse même.
C'est cette diffusion qui nous intéresse, car elle n'est pas égale dans toutes les directions.
Envoyez un faisceau laser vers de la cire, la lumière va se diffuser, mais avec une nette préférence pour la direction initiale de la lumière.

C'est la même chose avec la poussière.

C'est ce qu'on appelle une diffusion anisotropique, par opposition à isotropique, qui veut dire "égale dans toutes les directions".

Bref, tout ce blabla pour dire qu'on va faire en sorte que la puissance de la lumière (de Lux) soit fonction de l'angle de la lumière avec la caméra.

Ça va pas être très compliqué, alors allons y.
Voyons ce petit schéma :

















Nous avons donc une caméra (dont la source s'appelle "ca") et une lumière dont nous appelleront la source "la" et la cible "lb")
En gros, la lumière sera au plus fort quand elle sera exactement dans l'axe de la camera, c'est à dire que le vecteur (ca,la) sera dans le meme axe que le vecteur (la,lb), mais dans la direction opposée.

Est-ce aussi simple que ça cela ?
On pourrait en effet créer un modèle beaucoup plus compliqué, en prenant en compte par exemple l'angle du cône de la lumière. En effet, plus le cône est large, plus l'intensité restera forte sur une plage angulaire importante. Cela mériterait en effet d'entrer dans l'équation.
Mais nous allons faire sans (et également sans la focale de la camera), et nous verrons à la fin pourquoi. Ne vous inquiétez pas, il ne s'agit en rien d'une quelconque paresse.

Commencez par créer votre petite scène, avec votre caméra, votre spot, et votre calque Lux.
Ensuite, rajoutez 3 paramètres glissière au même calque Lux :
-falloff
-val min
-val max

Ensuite, revenez dans l'effet Lux, aller dans spot Lights, et créez une expression pour "Intensity"

Commençons par créer nos variables :

falloff=effect("falloff")("Curseur");
min=effect("val min")("Curseur");
max=effect("val max")("Curseur");

Ensuite :

ca=thisComp.layer("Caméra 1").transform.position;
la=thisComp.layer("Lumière 1").transform.position;
lb=thisComp.layer("Lumière 1").transform.pointOfInterest;
lv=sub(lb,la);
lvn=normalize(lv);

Pas grand chose à expliquer à des gens aussi fort que vous, on définit la position de la caméra, la position de la lampe, puis le vecteur qui donne la direction de la lampe.
Pour rappelle, quand on veut créer un vecteur AB, on écrit sub(B,A);
Je ne me souviens plus si on a déjà vu le normalize, alors dans le doute, il permet de transformer un vecteur donné(qui je vous rappelle, a 2 composantes : une direction, et une longueur) en un vecteur de même direction, mais de longueur 1. On le normalise quoi....
Pourquoi fait-on ça ? Car nous allons le comparer au vecteur (camera,lampe). Et comme la distance entre la lampe et sa cible peut prendre n'importe quelle valeur et qu'elle n'intervient pas dans le calcul (seul la direction nous intéresse), on normalise.

Vous suivez ? On continue.
Créons le vecteur (camera,lampe):


ca_la=normalize ( sub(la,ca) );

J'aurais pu l'écrire en 2 lignes (une pour la création du vecteur, l'autre pour la normalisation).
Nous avons à présent 2 vecteurs de taille égale à 1, avec chacun une direction différente (à priori)

On comprend donc que si on fait vecteur1+vecteur2, on va obtenir un 3ème vecteur qui aura une taille donnée. C'est la taille de ce vecteur qui va nous dire à quel point les 2 vecteurs ont des directions différentes.
Imaginez que la lampe soit exactement dos à la caméra. Si on additionne les deux vecteurs, comme ils sont dans la même direction, on a donc un 3ème vecteur d'une taille de 2.
Si la lampe est pile poil dans l'axe de la camera, ça fait 1-1=0.
Si les deux vecteurs sont perpendiculaires, on obtient donc un troisième vecteur égale à racine de 2.




Trouvons le vecteur bleu :

delta=add(ca_la,lvn);

On a bien additionné le vecteur qui va de la caméra à la lumière avec le vecteur allant de la lumière à la cible de la lumière. Chaque vecteur est égal à 1, le vecteur bleu varie bien de 0 à 2.
Attention, sur le petit schéma, ne pensez pas que la ligne blanche correspond à l'axe de la caméra, ça n'est pas du tout le cas. Il s'agit bien du vecteur (caméra,lampe).

Revenons à la base, on est en train de régler l'intensité. Il nous faut donc une variable qui va de 0 à 1.
Transformons donc delta qui va de 2 à 0 pour qu'il aille de 0 à 1:

angle=1-length(delta)/2;

C'est maintenant que la finesse se passe. On a bien notre variable qui va de 0 à 1. Il suffit par exemple de multiplier cette valeur par 100, et on a notre effet.
Sauf qu'il nous manque un petit réglage. En effet, on ne peut pas régler la façon dont on va de 0 à 1. Pour le moment, c'est linéaire.
Par exemple, quand la lumière passe de "face" à "profile",on passe de 1 à 1-1.4 (en gros) de façon linéaire, et même chose pour "profile" à "dos".
Sauf que ça n'est pas ce qu'on veut. Quand la lumière est de face, on est à 100%, et plus la lumière s'écarte, plus la puissance baisse vite. La courbe est donc exponentielle.
Il faut donc qu'on casse cette ligne droite qui va de 0 à 1. Pour parler intuitivement, il faut que la courbe ait du mal à arriver à 1, que 1 soit un pic, un roc ou ce que vous voulez.

C'est pour cela qu'on a créé la variable "falloff".

Voici la ligne suivante :

courbe=Math.pow(angle,falloff);

On va donc avoir notre variable qui va de 0 à 1 à la puissance falloff.
Et comme on est entre 0 et 1, on reste entre 0 et 1. Plus falloff est grand, plus la courbe est prononcée, plus l'angle devra être "parfait" pour atteindre 1.
Vous comprenez maintenant la valeur qui défile dans la vidéo, il s'agit de la puissance de la lampe, vous pouvez ainsi voir que la valeur ne commence à augmenter réellement qu'à proximité de l'axe de la caméra.

Voilà pourquoi je n'ai pas créé de variable pour le cone de la lampe ou autre.
Tout se fait avec la variable falloff qui vous permettra de régler votre effet. Plus vous voulez une lumière directionnelle, plus il faudra augmenter la valeur. En gros, vos valeurs iront de 5 à 100, pour vous donnez un ordre de grandeur.

Il ne manque plus que la dernière ligne :

ease(courbe,0,1,min,max)

Voilà, il ne vous reste plus qu'à mettre des valeurs dans val min et val max (comme 10 et 100 par exemple), et le tour est joué.

Voilà, c'était long car je voulais bien expliquer la petite réflexion qui permet d'arriver à ça, car en suite, l'expression est simplissime, on a fait 10 fois pire ensemble.
Si on enlève les lignes de création de variable, il n'y a que 5-6 lignes.


Encore une petite précision tout de même. Vous risquez d'avoir un problème si votre lampe a un parent. En effet, After Effect va modifier les valeurs de position et de point cible en fonction du parent. Le problème vient du fait que pour les expressions, AE récupère les valeurs de chaque variable sans prendre en compte les parents. Vous obtiendrez donc des valeurs erronées.
Je parle de ça car il est assez commun qu'une lampe ait un parent, pour par exemple pouvoir déplacer les deux points de la lampe en même temps.

La solution est de définir la position ainsi :

position=objet.position+parent.position

jeudi 10 décembre 2009

toujours à la hauteur !

Comme Chatton me tane, allons y...

En plus, c'était mon prochain article prévu donc bon...
Je parle bien entendu de faire en sorte qu'un calque se déforme pour toujours avec la taille correspondant une distance donnée, comme dans l'exemple de fin de "look me in 2d"

Voilà comment faire, c'est vraiment tout bête:

Imaginons que nous avons une barre dont le point d'ancrage est à une extrémité.
Nous voulons que l'autre extrémité soit toujours "accrochée" à un autre calque (ou point de l'espace), que nous appellerons "target".

Voilà la démarche, on va prendre un exemple avec des chiffres, c'est plus simple à comprendre.
Imaginez que vous ayez un calque qui fasse 300 pixels de haut. Mais vous voulez qu'il ne fasse que 100. On comprend donc qu'il faut trouver le rapport entre ces 2 nombres.
Là c'est simple, le rapport est égal à 1/3, il faut que le calque soit à 33% (environ)
Il faut donc diviser la distance voulue par la hauteur du calque. Et oui, si le calque a la bonne taille à la base, on a bien 1/1=1.
Et comme c'est un pourcentage, il faut multiplier le tout par 100.

C'est donc super simple, ça donne ça :

poslook=comp("target Comp 1").layer("target").transform.position;
pos=transform.position;
dist=length(pos,poslook);

x=scale[0];
y=(dist/height)*100;

[x,y]

Ici on garde l'échelle sur X constante, et c'est Y qui va suivre la distance voulue.

Voilà, votre calque peut faire 10 et 1526 en hauteur, il sera toujours bien calé.

A vous de trouver comment ça peut vous servir !
Bonsoir à tous

mardi 17 novembre 2009

un peu de pub...

Allez, un peu de pub, une fois n'est pas coutume.

Guillaume Tel, série écrite et réalisée par votre serviteur, est enfin en ligne !
Le pilote (en bas) + les 3 premiers épisodes sont disponibles, puis ça sera un par semaine, pour un total de 17 épisodes.


GUILLAUME TEL

A bientot !

mercredi 16 septembre 2009

freezeur de composition

Un petit truc très rapide, qui peut servir à beaucoup de choses.
Vous avez besoin de bloquer une vidéo, ou une composition, sur une image donnée.
Comme vous le savez, vous pouvez faire clic droit sur un calque, "instant", "geler l'image".
Sauf qu'une fois que c'est fait, vous ne pouvez pas changer l'image en question. Pour ce faire, vous devez desactiver le remappage temporel, et refaire l'opération.

Voici une astuce pour choisir en un clin d'oeil l'image que vous voulez.

Créez un marqueur sur le calque. Pour se faire, vous pouvez appuyer sur la touche * avec le calque selectionné. Ensuite, clic droit dessus, paramètre, et nommez le 1 par exemple (autant avoir quelque chose de simple)

Ensuite, activez le remappage temporel du calque, et créez une expression dedans :

marker.key("1").time

On demande donc que le temps soit celui du marqueur qui s'appelle "1".

Et voilà ! L'image bloquée sera celle du marqueur. Déplacez le marqueur, et vous changerez l'image choisie.

Cela peut également servir pour une composition qui contient une image/photo différente à chaque frame.
A vous de voir à quel moment ça peut vous servir.

lundi 14 septembre 2009

le fil de téléphone

Bonjour à tous,

voici enfin l'explication de la dernière animation, le fil de téléphone.
Je vais aller relativement vite, car il n'y a ici rien de nouveau en terme d'outil.
Toute la difficulté est de découper le processus :
Nous voulons qu'un fil soit tendu par ses 2 extrémités, mais quand les extrémités sont trop proches l'une de l'autre, le fil se détend, et dessine une courbe vers le bas :













Créez votre petite scène : 2 ronds bleus (oui maintenant j'impose des contraintes), un petit rond blanc (au dessus des bleus), et un Null appelé "controle"
Pour le calque "controle", rajoutez 3 paramètre glissière, et nommez les "taille", "diametre" et "frequence". Merci.

"taille" va définir la taille du fil, c'est à dire la taille sous laquelle il commencera à fléchir, ça arrive aux meilleurs.
"diamètre" et "fréquence" nous serviront pour la spirale, pour la suite.

Créez également un Null "sol" à mettre sous le rond blanc. Vous connaissez le principe, on l'a déjà vu.
Ouvrez l'expression de position du rond blanc, et on y va :

plafond=thisComp.layer("controle");
I=index-plafond.index;
sol=thisComp.layer("sol");
nombre=sol.index-plafond.index-1;

Tout ça, c'est du déjà vu, j'explique pas.
Réfléchissons un peu. En gros, on veut que plus un rond est loin de chaque extrémité (donc au centre de la ligne), plus il va descendre selon la distance entre les 2 ronds bleus.
Il faut donc qu'on crée un valeur qui varie de 0 à 1. 0 correspond à un rond blanc à la même position qu'un rond bleu, et 1 au calque qui est pile poil au milieu.

pos=linear(I,1,nombre,0,1);
possin=ease(pos,0,1,0,Math.PI);
trigopos=Math.sin(possin);

pos vaut donc la position linéaire de chaque rond.
possin crée le sinus de pos. Visualisez le cercle trigo. Quand pos=0, possin=0, et quand pos=1, possin=Math.PI.
possin correspond donc à un arc de cercle allant de 0 à 180.
On comprend donc que trigopos vaut 1 quand possin vaut 0,5.

Rappelez vous de cette technique, c'est pratique pour crée un index en forme de bosse.
Pour possin, j'ai utiliser ease et non linear, ça évite que les premiers ronds blancs ne tombe tout de suite.
Bref, trigopos nous indique la distance des ronds blancs par rapport aux extrémités, en fonction de leur position dans la timeline (et non par rapport à leur distance réelle).

Créons ensuite les variables du calque "controle", ça sera fait :

taille=thisComp.layer("controle").effect("taille")("Curseur");
diametre=thisComp.layer("controle").effect("diamètre")("Curseur");
freq=thisComp.layer("controle").effect("freqence")("Curseur");

Commençons à placer les ronds. Je ne fais que reprender le même exercice qu'ici.


A=thisComp.layer("A").transform.position;
B=thisComp.layer("B").transform.position;
V=sub(B,A);

Les calques A et B sont évidemment mes ronds bleus.

ligne=A+V*pos;

On réutilise donc la position linéaire des calques pour les placer de la ligne.
Maintenant, occupons nous de la déformation :

dist=length(A,B);

Voilà, comme ça on a la distance entre les ronds bleus. Maintenant, nous devons la comparer à la "taille" :

delta=ease(dist,0,taille,Math.PI/2,0);

on a donc une valeur "delta" qui vaut 0 quand les ronds bleus sont aussi loin que "taille" (ou plus), et qui vaut Math.PI/2 quand les ronds bleus sont confondus.

G=(Math.sin(delta)*taille/2)*trigopos;

G est la valeur qui fait descendre nos ronds blancs :
Quand les ronds bleus sont confondus, on peut considérer que le fil est plié en 2, donc que le rond le plus bas sera descendu de taille/2 (c'est évidemment une approximation sans aucune prétention physique).
Quand delta=0, G=0 et n'est donc pas pris en compte.

Finalement, nous créons des potentiomètres, comme pour les lampes. On crée des variables qui vont de "éteind" à "allumé", et on se donne le droit d'utiliser les variables intermédiaire:
trigopos est l'interrupteur fonction de la position des ronds blancs.
delta est l'interrupteur fonction de la postion des ronds bleus.

courbe=ligne+ [0,G];

La déformation vaut donc la ligne, +G en Y.
Et voilà, vous avez votre fil qui se déforme. Vous pouvez multipliez votre ronds blancs, ça marche.

Passons à la spirale.
Alors alors, qu'est ce qu'on veut faire ici...
Nous voulons en fait créer une autre ligne, qui va suivre la 1ere, mais en forme de spirale.
C'est un peu comme si on collait un bout de plastique sur le rayon d'un vélo :
Quand le vélo avance, le bout de plastique suit la même trajectoire que le vélo, mais en suivant une spirale, ça s'appelle une cycloïde.
La différence, c'est qu'ici, ça n'est pas le mouvement qui fait faire des cercles au bout de plastique, mais la position des ronds, ce qui revient au même.

Vous pouvez vous entrainer en faisant ceci:
Créez un solide, utiliser cos en X et sin en Y, et faite varier l'angle avec son index.
Si vous dupliquez le solide, vous allez donc obtenir un cercle, nous avons déjà vu ça en long en large et en travers.
Mais si vous rajoutez une variable qui fait augmenter X en fonctione de l'index, vous aurez votre spirale.
C'est exactement ce que nous allons faire.


spiralX=Math.cos (pos*freq )*diametre;
spiralY=Math.sin (pos*freq )*diametre;

Simplissime, vous connaissez déjà tout ici.
Dernière ligne:

courbe+ [spiralX,spiralY]

Et voilà !
Vous remarquerez comme nous avons tout bien segmenté :

ligne+courbe+spirale.

C'est un bon moyen pour s'y retrouver et faire du travail propre.
J'avais dit que j'avais fait court, ça va quand même, c'est pas trop long.

Encore une fois, c'est évidemment du système D, mais ça fait la blague.
Par exemple, nous n'avons pas fait en sorte que la spirale suive le tracé, et aucun délai n'a été créé pour les ronds du milieu.
Mais si vous cherchez, je suis sur que vous trouverez...

dimanche 30 août 2009

telephone

Après le SOS de Fred, j'ai trouvé la problématique intéressante, et relativement concrète.
Voici donc ma solution :














Je posterai la solution surement la semaine prochaine, parce que là, pas trop le temps (et oui, l'expression n'est pas très compliquée (environ 35 lignes, ya pire), mais écrire l'article, c'est un peu plus long...)