original in es Antonio Castro
es to en Miguel A Sepulveda
en to fr Iznogood
Les animations ont été réalisées en basse résolution à 15 images par seconde au format JPEG. En limitant la résolution et la taille de l'animation, nous espérons éviter de surcharger le disque dur et de ne pas rendre cet article trop lent à télécharger. Néanmoins, comme toujours, les sources pour ces images sont aussi fournies pour les lecteurs qui ont accès à l'outil « pov » (dont nous avons parlé dans l'article précédent) qui rendra les images à la résolution souhaitée ou qui permettra aux lecteurs de les modifier et d'expérimenter.
Si vous n'avez pas encore installé Povray sur votre système, veuillez suivre les conseils de l'article précédent de cette série où nous donnons suffisamment d'informations sur la localisation des sources, l'installation et la configuration de POVRAY.
Dans le précédent article, nous avons brièvement mentionné la notion de lancer de rayon. Nous allons maintenant explorer ce sujet plus en détail.
Le rendu est la technique la plus complète pour réaliser une image synthétique. Il tente d'émuler l'influence de la lumière et de ses effets sur les objets de la manière la plus réaliste possible.
Dans notre précédent article, nous avons mentionné que le rendu calcule le nombre de rayons de lumière mais paradoxalement la source de lumière de ce modèle se comporte comme un puits et non comme une source alors que la caméra agit comme source des rayons. La raison de cette inversion des rôles est simple : si les rayons partaient de la source de lumière, il y aurait alors un gaspillage de temps de calcul car de tous les rayons qui quittent la source de lumière, seul un petit nombre atteint réellement la caméra. En suivant les points de l'image depuis la caméra, nous réduisons le nombre de rayons à ceux qui sont appropriés à l'image. Chacun des points de l'image correspond à un point hypothétique d'un film photosensible de notre caméra virtuelle. Chaque point est alors traité indépendamment. Nous avons configuré Povray pour construire l'image et la visualiser avec un programme externe. Si nous avions configuré Povray pour SVGA, alors nous pourrions remarquer qu'il est possible de voir l'image comme pendant son calcul. Ceci se réalise pixel par pixel, de la gauche vers la droite, du haut vers le bas de l'écran. L'ordre n'est pas le fruit d'une coïncidence car c'est celui du format de sortie le plus habituel de Povray, à savoir le TGA 24 bits, qui est construit précisément dans cet ordre.
Si quelqu'un est intéressé par la configuration de Povray pour SVGA (je ne l'ai pas moi-même réalisé), la première chose que vous apprendrez est que la vitesse du rendu dépend de la région de l'image ; les régions complexes nécessitent plus de temps que les régions les plus simples. Les zones avec plusieurs objets prennent plus de temps à calculer que celles avec un seul ou aucun. Pour chaque impact de rayon sur un objet, le moteur de rendu calcule l'effet sur l'éclairage en regard de la position et de la couleur de la source de lumière, sa position relative par rapport à la surface des objets, ainsi que la texture de l'objet et autres caractéristiques physiques. Le résultat de ce calcul est spécifié dans trois valeurs RGB qui définissent la couleur et l'intensité du point dans l'image.
Une visite rapide
Le format TGA 24 bits prend beaucoup d'espace mais est facile à générer et à traiter.
Chaque pixel se voit attribuer trois nombres de 8 bits qui codifient le paquet
RGB.
8 bits *3 = 24 bits; 2^24 = 16777216 (16 millions de couleurs)
|
Cette information devrait être suffisante pour traiter des images et réaliser quelques effets intéressants. Si le lecteur possède un peu d'expérience en programmation, nous lui proposons l'exercice suivant :
1) Éclairer/Assombrir une image (les pixels blancs sont 255,255,255 et les
noirs 0,0,0) ;
2) Disposer une image avec un fond noir en surimpression sur une autre en utilisant le noir
comme valeur tranparente ;
3) Mélanger deux images en effectuant une moyenne des valeurs de couleur ;
5) Augmenter/réduire une couleur donnée ;
6) Obtenir l'histogramme de couleur d'une image (la liste des couleurs et leur
fréquence).
Toutes ces opérations peuvent être accomplies en utilisant des programmes auxiliaires souvent disponibles sur Internet. Néanmoins, dans certaines occasions, nous pouvons être obligés d'appliquer une transformation non triviale à l'image et ce format TGA de 24 bits est facilement gérable.
Fin du détour
Les rayons partent d'un point du film de la caméra virtuelle mais pour calculer la couleur à obtenir, chaque rayon détermine s'il intercepte des objets de la scène. Si c'est le cas, l'algorithme de lancer de rayon analyse les caractéristiques de l'objet dans la zone atteinte par le rayon. Il existe alors une technique d'optimisation de conception d'objets complexes très efficace. Elle consiste à définir un nouvel objet invisible qui contient le premier objet complexe. Généralement, le conteneur le plus utilisé est une sphère mais les boîtes sont aussi populaires. Ici, le but premier est d'utiliser le conteneur pour forcer le moteur de rendu à se rapprocher de l'objet complexe en utilisant plutôt le conteneur, pour que les rayons rebondissent sur le conteneur sphérique invisible. Cela permet de supprimer une bonne partie du calcul. La primitive utilisée est "bounce_by" et elle est expliquée ensuite pour illustrer la manière efficace dont travaille le moteur de rendu. Nous verrons un exemple, plus loin dans cet article lors du traitement des figures complexes.
Comme illustration des sujets explorés jusqu'ici, analysons une image créée en utilisant plusieurs techniques et détaillons-les une par une.
Cette scène est intitulée les "7 Erreurs"
Veuillez noter que quelques caractéristiques de la scène sont étranges :
À ce moment, nous ne pouvons réellement expliquer les détails des nombreuses techniques utilisées. Le but de cet exemple est de montrer au lecteur que les moteurs de rendu tentent d'imiter les phénomènes naturels mais ils ne respectent pas totalement les lois naturelles de la physique car le prix à payer en terme de temps de calcul pour un rendu plus réaliste est très élevé. Certaines techniques sont plutôt bonnes pour atténuer les défauts produits par d'autres. L'essentiel est de trouver un juste équilibre entre le résultat final et le temps de calcul.
Cette série sur Povray ne peut aller au delà d'une présentation superficielle de ses possibilités. Le langage Povray est beaucoup trop étendu pour être traité en profondeur dans cette série. Pour cette raison, nous devons nous contenter, pour l'instant, de quelques remarques sur les fonctionalités les plus importantes du langage.
Povray permet souvent l'utilisation de différentes formes grammaticales pour obtenir le même résultat. C'est en partie dû à la genèse de Povray, la syntaxe actuelle de Povray ayant profondément changé de versions en versions. La syntaxe courante est très améliorée et ne changera sans doute pas autant dans le futur. Pour des raisons de compatibilité, les particularités de syntaxe des anciennes versions sont préservées dans les versions récentes soit dans leur forme originale, soit dans une forme légèrement modifiée. Un exemple de flexibilité de la syntaxe concerne les rotations que nous allons examiner bièvement.
Il existe une option de compilation qui permet de traiter le fichier source en entrée en utilisant des versions antérieures de Povray.
Par exemple :
|
Bizarrement, cela permet au développeur de mélanger du code écrit avec Povray 1.0, 2.0 ou 3.0
Il existe un excellent manuel pour Povray, veuillez vous y référer. Nous allons gagner du temps ici en ne parlant que des fonctionalités les plus importantes.
Commentaires, Déclarations, fichiers Include
Les commentaires sont écrits en respectant le style C++.
Exemple:
|
Les éléments commençant par '#' sont reconnus comme Directives de langage. Les directives les plus communes sont « #declare » et « #include ».
|
Exemple:
|
L'instruction « #declare » peut être utilisée pour stocker une grande variété d'éléments : rotation, texture, couleur, objet, valeurs numériques...
Un autre élément crucial est l'instruction include qui permet d'inclure des fragments de code source précédemment sauvegardés dans d'autres fichiers.
Par défaut, la directive include cherche le fichier dans le répertoire local. Si le fichier n'est pas trouvé, c'est le Library_Path qui va servir à la recherche.
Library_Path=${POVRAY}/include // Pour les fichiers include de Povray
Library_Path=${HOMEPOV}/include // Pour les fichiers include utilisateurs
C'est pourquoi j'ai intégré dans la nouvelle version du script « pov », un moyen de générer un fichier d'initialisation adapté. Nous y reviendrons.
Il existe un ensemble de fichiers include qui doivent vous être familiers afin d'obtenir le maximum de Povray. C'est une bibliothèque de ressources qui peut être intégrée à notre code et adaptée aux goûts des développeurs.
|
Povray possède également des directives qui permettent d'effectuer des boucles et des branchements conditionnels. Les premières versions de Povray manquaient de directives pour les boucles ou pour les conditions, en plus d'une description d'éléments dans la scène qui pouvaient apparaitre dans n'importe quel ordre, en ayant pour résultat un gros effort intellectuel de la part du développeur par rapport aux langages de programmation traditionnels. L'ordre de déclaration des éléments dans la scène est toujours hors de propos mais les boucles peuvent dispenser le développeur d'écrire une multitude de lignes semblables et les branchements conditionnels permettent de définir une scène en fonction de la valeur de « l'hologe » utilisée dans les animations, par exemple. Lorsque nous parlerons d'images composites dans le prochain article, nous donnerons un exemple de branchements conditionnels.
Il existe beaucoup d'autres directives de langage (commençant par '#') mais insistons sur le fait que les deux présentées ici ('#declare' et '#include') sont de loin les plus usitées.
J'éviterai les caractéristiques du langage qui sont très similaires aux autres langages de programmation telles que les constantes de différents types, les opérateurs logiques, les opérateurs relationnels, les opérateurs pour les vecteurs, les fonctions prédéfinies, etc..
Il est conseillé d'utiliser au moins un caractère en majuscule pour les étiquettes de manière à les distinguer des mots réservés du langage.
Parler de ce sujet si tôt mérite une brève explication.
Il est souvent dit qu'une image vaut mieux que mille mots et c'est d'autant plus vrai si nous tentons d'expliquer la fonctionalité d'un lanceur de rayon. Nous allons essayer d'illustrer abondamment chaque concept, sinon, le lecteur sera contraint d'écrire du code pour tester les explications en utilisant ses propres exemples de manière à suivre l'article. C'est une des raisons principales de l'inclusion de tant d'images dans la série Povray. Notre espoir est que la consultation des images puisse suffire à rappeler au lecteur les concepts étudiés sans qu'il soit nécessaire de revenir au texte. Une image est parfois insuffisante et, à la place, nous avons besoin d'une séquence entière pour constater les petites différences entre les images et les effets spéciaux. C'est la raison pour laquelle nous pensons qu'il est justifié d'en parler maintenant.
Povray se limite lui-même à la génération d'une séquences d'images et les sauvegarde une par une sur le disque. C'est une méthode très simple qui nous intéresse pour le moment. Le lanceur de rayon sera exécuté plusieurs fois, avec un nombre passé en paramètre qui sélectionne l'image dans la séquence devant être produite. De manière à relancer Povray plusieurs fois, il existe quelques bonnes options qui peuvent être ajoutées au fichier *.ini spécialement conçu pour générer des animations :
|
Puisque dans notre précédent article, nous avions proposé un programme simple pour générer des fichiers *.ini rendant ainsi Povray simple et pratique, mettons-le à jour de manière à permettre la génération d'animations.
Le nouveau script possède un nouveau répertoire d'include qui peut être partagé par plusieurs projets, '$HOME/dat/pov/include'. Ce sera l'emplacement idéal pour placer les bibliothèques utilisateurs.
|
De temps en temps, nous emploierons des utilitaires externes à Povray. Par exemple, pour visualiser les animations, nous allons utiliser "animate" et "convert" d'imagemagick.
Un jour, j'ai demandé à Enrique Zanardi, le mainteneur du paquet Povray sous Debian s'il y avait un modeleur pour Povray. Il a écrit :
J'ai utilisé ScEd (aussi disponible sous Debian). Une fois que vous en avez pris l'habitude, c'est très facile à utiliser. Il peut être compilé en utilisant un interpréteur Scheme de telle manière que les utilisateurs puissent définir leurs propres "jetons", sans se préoccuper de la complexité. Certains recommandent aussi Ac3D mais je crois que ce n'est pas un produit libre.
Il existe une autre méthode pour générer des animations. Cette méthode était très populaire avec les premières versions de Povray et elle est encore acceptable. Elle consiste en un programme externe qui génére une boucle qui lance Povray plusieurs fois. A chaque itération de la boucle, le programme génére un fichier devant être intégré par une instruction '#include' dans le source principal, chacun de ces fichiers contenant des informations sur l'heure courante.
Vous pouvez trouver ici un fragment de code C qui démontre la seconde méthode :
-------------8<------------------------------------
for(Frame=1; Frame < UltimoFrame; Frame++){ fi=fopen("pajaro.inc", "w"); fprintf(fi, "#declare PosX_pajaro1 = %d\n", FuncionPosX_pajaro1(Frame)); fprintf(fi, "#declare PosY_pajaro1 = %d\n", FuncionPosY_pajaro1(Frame)); fprintf(fi, "#declare AnguloAlas_p1 = %d\n", FuncionAngAlas_p1(Frame)); fclose(fi); sprintf(comando,"povray -ipajaro.pov -opajaro%04d.tga",Frame); system(comando); }-------------8<------------------------------------ |
Dans la section suivante, nous examinons un exemple d'animation qui illustre les spécifications des rotations et des translations.
La position d'un objet est déterminée par ses coordonnées <x,y,z >. Il est de pratique courante de définir les objets centrés sur l'origine des coordonnées.
Tout objet peut être déplacé de sa position initiale vers une zone définie <x,y,z > en utilisant une translation. La meilleure manière de représenter les données d'une translation se fait par le biais de vecteurs. Les vecteurs sont très souvent utilisés dans POVRAY. Une notation raccourcie courante pour un vecteur avec des composants x, y et z est <x, y, z> ; si tous les composants sont identiques alors <24, 24, 24> = <24>. POVRAY prédéfinit trois vecteurs : x=<1,0,0> y=<0,1,0> et z=<0,0,1>. Alors 3*y = <0,3,0> et -2*x = <-2,0,0>.
Il est souvent nécessaire de travailler avec un papier et un stylo pour planifier la position des objets dans une scène. Cela aide aussi à démarrer à partir d'une idée de base et à utiliser POVRAY pour générer des images à basse résolution et à faible qualité pour qu'après plusieurs tentatives et erreurs, nous puissions déterminer la meilleure situation des objets.
Les transformations 3D disponibles avec POVRAY sont :
rotate <VECTOR>
scale <VECTOR>
translate <VECTOR>
Les transformations de translations et de rotations sont très utiles pour les animations de même que pour définir des objets dans une scène complexe.
Tous les objets peuvent être déplacés vers une zone différente en ajoutant un vecteur qui est calculé en soustrayant les coordonnées initiales des coordonnées de l'emplacement final. Géometriquement, ce vecteur de translation peut être visualisé comme une flèche partant de la zone initiale vers la destination. Vous avez ici un exemple :
sphere { <2, 2, 2>, 10
pigment { White }
translate <-3> // Remember <-3> = <-3, -3, -3>
}
Le résultat est une sphère d'un rayon de 10 centré sur <-1,-1,-1>
Les objets pivotent autour d'un axe passant par le centre des coordonnées. C'est une convention habituelle pour exprimer les rotations et comme les objets (qui devraient être représentés centrés sur l'origine) pivotent d'abord avec l'orientation appropriée et subissent ensuite une translation vers leur destination finale. Notez que l'ordre inverse d'opération (d'abord la translation puis la rotation) ne donnerait pas le même résultat.
Une rotation doit être définie en spécifiant un axe de rotation et un angle de rotation autour de cet axe. Le sens de rotation suit la règle de la main gauche (prenez votre main gauche avec le pouce pointant dans la direction positive de l'axe et fermez votre poing, la direction de déplacement du poignet fermé montre la direction de rotation).
Il existe deux manières pour définir une rotation dans POVRAY : "axes * degrés" ou "<n,n,n>" qui représente trois rotations sur les axes X, Y et Z. Voici quelques exemples :
rotate x * 45 = rotate <45, 0, 0>
rotate <45, -30, 20> = rotate x*45 rotate y*-30 rotate z*20
rotate 20*z = rotate z*20
rotate y*90 x*90 = rotate <0, 90, 0> rotate <90, 0, 0>
rotate y*90 x*90 != rotate <90, 90, 0>
Le dernier exemple ne constitue pas une égalité et c'est un cas qui mène souvent à des erreurs. L'ordre des rotations est très important. Lors de l'utilisation de la notation <n,n,n> les rotations sont effectuées dans l'ordre X, Y et Z et lorsqu'un ordre différent est nécessaire, on doit concaténer plusieurs instructions de rotation. Nous utiliserons de préférence la notation "axe * degrés". Si le développeur le souhaite, il peut utiliser les angles en radians avec la fonction "radians". Il existe de nombreuses fonctions mathématiques dans POVRAY qui facilitent l'évaluation d'arithmétique mathématique.
La taille des objets peut être modifiée en utilisant le dimensionnement. Trois nombres sont utilisés pour changer l'échelle des directions X, Y et Z d'un objet. Ceci permet de grossir, de réduire ou d'applatir un objet.
Les translations et les dimensionnements peuvent être effectués dans n'importe quel ordre. Néanmoins, la présence d'une simple opération de rotation est suffisante pour casser la commutativité des opérations et donc l'ordre devient très important. Vous avez ici un exemple simple pour illustrer l'importance de l'ordre dans les transformations 3D. C'est une sphère bleue pivotant autour de son centre et d'un point externe. L'axe de rotation au centre de la sphère est en déclinaison légère par rapport à l'horizon.
----------------------------------8<------------------------------ #include "colors.inc" #include "textures.inc" //##### Pour lancer l'éxecution de l'animation : ###### //# pov PlanetAzul 4 9 1 100 1 360 # //############################### #declare RY1 = clock * 5; #declare RZ1 = 25; #declare T1 = <5 ,0 ,0 >; #declare RY2 = clock; camera { light_source { <-15, 15, 15> color White} sphere { <0, 0, 0> 4 |
Pour lancer l'animation, nous utilisons une nouvelle version de « pov » et exécutons :
./pov PlanetAzul 4 9 1 100 1 360
C'est ce que ces paramètres signifient :
Nous montrons ensuite quelques tableaux de l'animation. Ce n'est pas suffisamment bon pour un modèle réaliste de la planète Terre mais c'est suffisant comme métaphore.
Exemple planetblue.jpg:
Les sources de lumière sont modélisées comme des sources de points dans l'espace. Le point de la source de lumière n'a pas de dimension et il est invisible dans le sens où le focus d'une caméra pointé dessus ne montrera rien. Une source de lumière est seulement perçue par ses effets sur les objets proches. Par défaut, ce point diffuse de la lumière dans toutes les directions, bien qu'il soit possible de définir des rayons de lumière (lumière irradiée de manière conique). La couleur par défaut est blanche et cet attribut peut aussi être changé de même que l'intensité de la lumière.
Une scène peut avoir une ou plusieurs sources de lumière afin de produire l'éclairage et les ombres appropriés. Néanmoins, augmenter le nombre de sources de lumière signifie aussi augmenter le temps CPU utilisé pour générer l'image.