Aide pour After Effect, techniques, expressions.

dimanche 31 janvier 2010

lampe anisotropique et son flare




Derrière cette recette délicieuse se cache simplement le même principe que la luminosité de Lux, mais appliqué à un flare.
Quelle est la différence à observer ?
Si la lumière volumétrique est bel et bien un phénomène lumineux qui varie selon l'angle avec la caméra, il reste en principe visible dans toutes les directions, même si la lampe est dos à la caméra.

Pour les flares, ça n'est pas le cas. Ils ne sont visibles que lorsque la lampe est en face de la caméra. C'est même dans la nature profonde des flares d'avoir des changements importants au moindre changement d'angle de la lumière.

On peut donc considérer qu'un flare ne commence à apparaître que lorsque la lampe est AU MOINS de profile par rapport à la caméra.

Souvenez vous du petit diagramme avec l'angle de la lampe qui tourne.
La valeur de profil correspond donc à la situation ou les 2 segments sont perpendiculaires.
Les segments valant chacun 1, le vecteur bleu mesure donc racine carré de 2, donc environ 1.4

Il nous suffit donc de modifier la dernière ligne pour que la valeur ne commence non pas à 0, mais à ...hmm ?
Alors alors, souvenez vous, le vecteur bleu va de 2 à 0.
Et on avait transformer ça en valeur qui va de 0 à 1.
C'était donc 1-x/2 pour arriver à ça.

1-1.4/2=0.3

Donc la dernière ligne est :

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

Et voilà. Votre flare n'apparaîtra qu'à partir du moment où la lampe est dirigée vers la caméra.
Et vous pouvez toujours jouer avec la variable "falloff" pour contraster son apparition

mardi 26 janvier 2010

remappage temporel de clef 2

Certains l'auront peut-être compris, cette technique de remappage de clefs peut également servir à la gestion de plusieurs valeur à la fois.
Par exemple, si vous avez une animation sur une position et sur une rotation, et que vous voulez changer la vitesse d'animation tout en gardant le même rapport entre la position et la rotation.
Imaginez par exemple un homme qui saute d'un plongeoir en faisant des figures. La rotation de son corps sera à priori toujours la même à une position donnée. Autre façon de le dire, la rotation est fonction de la position.

En gros, c'est exactement la même chose, sauf que bien entendu, on va créer la variable dans un calque à part, puisqu'il peut être destiné à plusieurs calques.
On appliquera donc l'expression

target=thisComp.layer("controle vitesse").effect("temps")("Curseur");
valueAtTime(target)

à toutes les valeurs dont on veut contrôler le déroulement.
Mais si vous vous souvenez de l'autre post (ou si vous relisez), nous avions relié la valeur du curseur (celui qui va de 0 à 100) à la valeur à modifier.
Vous pouvez toujours faire ça, mais à quelques conditions:
-la variable qui gère le curseur (la position dans le post précédent) doit avoir sa 1ère clef avant les 1eres clefs de toutes les autres variables (ou au même moment) et sa dernière clef doit être après les dernières clefs des autres variables.
C'est logique, puisque la valeur ne va varier le temps qu'entre les clefs de cette variable.

Ceux qui commence à avoir un peu de bouteille auront sans doute l'intuition qu'il y a d'autres façon de générer cette valeur de temps remappé.
En effet, on peut le voir de plein de façons différentes.
En voici une autre, que vous allez surement préférer dans le cas où il faut gérer plusieurs variables en même temps :

T=thisComp.duration;
linear(value,0,100,0,T)

Voilà, c'est vraiment tout bête.
T vaut la longueur de la composition (en seconde). Quand le curseur vaut 0, le temps vaut 0, et quand le curseur vaut 100, ça renvoie au code temporel de la dernière image de la compo.
Cette expression est plus valable dans le cas où on gère un ensemble de calques/variables, car il n'y a pas de raison pour qu'une variable rentre dans l'équation qui gère un ensemble de variables qui sont au même niveau hiérarchique que cette dernière.

Voilà, il vous suffit donc de bien copier l'expression dans toutes les variables animées que vous voulez.
Vous pourrez ainsi gérer l'ensemble de vos clefs d'une même composition !

Si c'est pas chouette quand même....

recherche

N'hésitez pas à utiliser le champ de recherche pour trouver un article qui traite d'un sujet particulier ou d'une fonction.

jeudi 21 janvier 2010

remappage temporel de clef
















Bonsoir à tous.

Ce soir, un petit outil très pratique qui va vous permettre de gérer la vitesse d'animation d'une valeur sans toucher à cette dernière.
Petit exemple:
Comme vous le savez, quand un objet va d'un point A à un point B, vous pouvez gérer la courbe de vitesse pour faire en sorte que l'objet accélère tout du long, ou freine juste à la fin, etc.

Mais c'est un peu plus compliqué quand l'objet décrit une trajectoire faite de 5 ou 256 points. On peut toujours mettre les points en mode "déplacement dans le temps", mais on ne gère que la vitesse globale et non local (à chaque instant).

Nous allons donc installer un système de remappage temporel, mais pour les clefs.
Vous allez voir, c'est assez simple.

J'explique d'abord ce que l'on va faire:
On va créer une valeur qui va de 0 à 100. Quan la valeur vaudra 0, on chargera la position qui est sur la 1er clef. Quand la valeur vaudra 100, on chargera la valeur qui est sur la dernière clef.

Créez votre objet, faites lui faire une petite trajectoire faite avec 4-5 clefs, qu'importe.
Ensuite, rajoutez lui un paramètre glissière et écrivez ceci :

n=position.numKeys;

On demande que n valle le nombre de clefs dans la valeur "position".

start=position.key(1).time;
end=position.key(n).time;

On crée 2 variables qui nous indiquent à quel code temporel se trouve la 1ere clef et la dernière clef (et oui, la clef "n" sera toujours la dernière. Vous pouvez rajouter des clefs, ça se mettra à jour tout seul).

linear(value,0,100,start,end);

Et voilà !
Il ne vous reste plus qu'à animer ce paramètre glissière en l'animant de 0 à 100.
Cela vous permet de gérer l'accélération/décélération de l'objet, ou vous pouvez aussi faire varier la valeur dans tous les sens pour faire une yoyo, ou même utiliser un wiggle pour aller de 0 à 100.

















A présent, écrivez ceci dans la position de l'objet :

p=effect("Paramètre glissière")("Curseur");
valueAtTime(p)

La position va donc charger la position à un moment différent, celle qui est dans le paramètre glissière.

Ça fonctionne évidemment pour toutes les propriétés.

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