Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- %!PS-Adobe-2.0
- %%BoundingBox: 0 0 400 400
- %%Page: 1 1
- 1.5 setlinewidth
- /width 400 def % Largeur du dessin
- % point de fuite du dessin (Changez `y` pour voir le dessin se transformer, ex : 150)
- /perspectivex width 2 div def
- /perspectivey 165 def
- % Note : On suppose l'horizon à 140 pour le reste du programme (tout les calculs lié sont déjà fait)
- % Note : On suppose la hauteur constante pour une determination des constantes "magiques" plus facile, alors que le programme s'adapte en largeur (cependant pas de maniere parfaite)
- % Il est recommandé de lire les fonctions dans le sens dans lequelles elles sont dessinées (voir tout en bas du fichier)
- /pavage { % Pavage (lignes bleues sur le sol)
- gsave
- % Clip sur le rectangle du bas
- newpath
- 0 0 moveto
- width 0 rlineto
- 0 140 rlineto % 140 -> horizon
- 0 width sub 0 rlineto
- closepath
- clip
- 18 1 40 { % Lignes horizontales, je commence a 18 car les lignes d'avants sont hors du cadre
- /i exch def
- /i i dup mul def % i = i^2
- % y = 250*(1 - 323.395 / i), la constante magique "323.395" a été determinée à la main en faisant de petits changements
- % Mais ce qui est interessant c'est que la distance entres les lignes horizontales est proportionnelle à 1/x comme d'apres les loi de la perspective
- /y 250 1 323.395 i div sub mul def
- newpath
- 0 y moveto
- width 0 rlineto
- closepath
- 37 255 div % r = (37) / 255 (Le color picker que j'utilisais pour trouver les couleurs me les donnait dans le format entier)
- 132 y 2 div add 255 div % g = (132 + y/2) / 255 (g tend vers 255 quand y tends vers +inf)
- 1 % b = 1
- setrgbcolor
- 4 y 75 div sub setlinewidth % width = 4 - y/75 (les lignes sont de plus en plus fines quand y augmente)
- stroke
- } for
- -10 1 20 { % Lignes verticales (qui partent du point de perspective et vont vers l'infini)
- /i exch def
- % x = -295 + i*90, autrement dit chaque ligne est espacée de 90 pixels au niveau de y = 0 (c'est le deuxième point)
- /x -295 i 90 mul add def
- /lastx perspectivex def
- /lasty perspectivey def
- % Le for suivant est une technique pour faire une ligne en couleur dégradée
- % On décompose la ligne en sous parties (ici de 1% de la taille de base) que l'on dessine bout par bout avec une couleur qui varie
- 0 .01 1.01 {
- /ratio exch def % ratio correspond à l'étape (il varie entre 0 et 1 par step de 0.01)
- /newx perspectivex 1 ratio sub mul x ratio mul add def % new = perspectivex * (1-ratio) + x * ratio, interpolation linéaire (car c'est une droite) entre x et perspectivex
- /newy perspectivey 1 ratio sub mul def % idem entre 0 et perspectivey
- newpath
- lastx lasty moveto
- newx newy lineto
- closepath % On dessine le petit bout..
- 37 255 div % r = 37 / 255
- 132 newy 100 div 50 mul add 255 div % g = (132 + 50*newy/100) (même formule que pour les lignes horizontales)
- 1 % b = 1
- setrgbcolor
- 2.5 newy 140 div sub setlinewidth % linewidth = 2.5 - newy/140 (La taille des lignes diminue quand y augmente)
- stroke
- /lastx newx def % On se rappelle des coordonnées actuelles
- /lasty newy def
- } for
- } for
- grestore
- } def
- /arbre { % utilisation : x y x2 y2 recur arbre luminance
- /luminance exch def % Eclaircissement de l'arbre
- 5 dict begin % On fait un dict car on va utiliser "arbre" recursivement, donc on veut définir les variables comme locales
- /recur exch def % Valeur de recursion, qui baisse de branche en branche
- /y2 exch def % Point d'arrivée
- /x2 exch def
- /y exch def % Point de départ
- /x exch def
- /diffx x2 x sub def % Vecteur de différence (arrivee-depart)
- /diffy y2 y sub def
- /normx 0 diffy sub def % Normal au ve cteur de différence (utilisé pour les branches filles)
- /normy diffx def
- newpath % On set le path avec les coordonnées données
- x y moveto
- x2 y2 lineto
- closepath
- % Pour le dessin de la branche je le décompose en deux strokes, l'exterieur et l'interieur qui ont deux couleurs différente
- /linewidth 3 recur add def % linewidth = 3 + recur .. quand recur est grand c'est qu'on est haut dans l'arbre (pres du tronc), donc les lignes sont plus epaisses
- gsave
- linewidth setlinewidth
- 232 luminance add 255 div % r = (232 + luminance) / 255 On voit que luminance est utilisé pour ajuster la luminosité (une grande valeur va rendre l'arbre plus blanc
- 45 luminance add 255 div % g = ( 45 + luminance) / 255
- 89 luminance add 255 div % b = ( 89 + luminance) / 255
- setrgbcolor
- stroke % Premier trait (trait exterieur)
- grestore
- linewidth 1.5 div setlinewidth % Taille du second trait = 2/3*linewidth
- 50 recur 25 mul add luminance add 255 div % r = ( 50 + recur*25 + luminance) / 255 Les feuilles sont moins rouge que le tronc
- 255 recur 25 mul sub luminance add 255 div % g = (255 - recur*25 + luminance) / 255 Les feuilles sont plus vertes que les branches
- 50 luminance add 255 div % b = ( 50 + luminance) / 255 on garde la meme teinte de bleu
- setrgbcolor
- stroke
- recur 0 ge % On recursionne si recur >= 0
- {
- % On définit les coordonnées "d'envoie" en faisant la moyenne du vecteur de différence et de la normale, ce qui est censé donner un angle de 45 degrés
- % Note : On fait une petite multiplication par 0.95 pour faire un arbre un peu plus compact (la taille de la branche d'après décroit exponentiellement)
- /sendx x2 diffx normx add 2 div 0.95 mul add def % sendx = x2 + (diffx + normx) / 2 * 0.95
- /sendy y2 diffy normy add 2 div 0.95 mul add def % sendy = y2 + (diffy + normy) / 2 * 0.95
- x2 y2 sendx sendy recur 1 sub luminance arbre % On fait la branche avec une recursion = recursion-1
- /normx 0 normx sub def % On oppose la normale pour faire une branche dans l'autre sens
- /normy 0 normy sub def % normey = -normey
- /sendx x2 diffx normx add 2 div 0.95 mul add def % sendx = x2 + (diffx + normx) / 2 * 0.95 (meme calcul)
- /sendy y2 diffy normy add 2 div 0.95 mul add def % sendy = y2 + (diffy + normy) / 2 * 0.95
- x2 y2 sendx sendy recur 1 sub luminance arbre % On envoie la deuxieme branche
- } if
- end % On relache les variables locales
- } def
- /arbres {
- % Pour aligner les arbres selon la perspective (Et donc faire une sorte d'allée) j'ai utilisé le meme code que le tracé des lignes verticales pour le pavage.
- /i 2 def % On prend la deuxieme ligne
- /x -295 i 90 mul add def
- /lastx perspectivex def
- /lasty perspectivey def
- /size 10 def % Taille de l'arbre
- .25 .35 1.01 { % Meme code que les lignes.. sauf qu'on mets 3 arbres au lieu de 100 petits bouts
- /ratio exch def
- /newx perspectivex 1 ratio sub mul x ratio mul add def
- /newy perspectivey 1 ratio sub mul def
- /size size 30 add def % Les arbres qui sont plus pres de nous sont plus gros
- newx newy newx newy size add 5 ratio 5 mul add 105 size sub arbre % On note le recur = 5 + ratio * 5, les arbres plus pres de nous sont plus complexes
- % Ainsi que le luminance = 105 - size, les arbres plus petits sont plus clairs (ils sont aussi plus loin)
- } for
- /i 9 def % On fait exactement le meme code pour une autre rangée (ici la 9e)
- /x -295 i 90 mul add def
- /lastx perspectivex def
- /lasty perspectivey def
- /size 10 def
- .25 .35 1 {
- /ratio exch def
- /newx perspectivex 1 ratio sub mul x ratio mul add def
- /newy perspectivey 1 ratio sub mul def
- /size size 30 add def
- newx newy newx newy size add 5 ratio 5 mul add 105 size sub arbre
- } for
- } def
- /spirale {
- /size exch def % Nombre d'itérations a effectuer (angle total)
- /speed exch def % Inverse de la vitesse à laquelle la spirale s'éloigne du centre
- /baseangle exch def % Décalage d'angle
- /basey exch def % Point centrale de la spirale
- /basex exch def
- gsave
- basex basey moveto % On va au point centrale
- /dist 0 def % On est a 0 du centre au début
- /lastangle 0 def
- /lastdist 0 def
- 0 3 size { % On itere en degré 3 par 3
- /angle exch baseangle add def % Angle = baseangle + stack (qui correspond a l'iteration)
- /dist angle speed div def % dist = angle / speed
- newpath
- basex lastangle cos lastdist mul add % x = basex + cos(lastangle)*lastdist
- basey lastangle sin lastdist mul add % y = basey + sin(lastangle)*lastdist
- moveto
- basex angle cos dist mul add % x = basex + cos(angle)*dist
- basey angle sin dist mul add % y = basey + sin(angle)*dist
- lineto
- closepath
- 2 setlinewidth % Largeur de la spirale
- /ratio 1 angle size div sub def % Le ratio correspond a la distance du centre
- ratio .05 le {/ratio 0 def} if % if(ratio < 0.05) ratio = 0
- /ratio ratio dup dup mul mul def % ratio = ratio^3 (la transition est donc cubique pour un dégradé plus agréable)
- /y basey angle sin dist mul add def % y = basey + sin(angle)*dist
- % y est utilisé pour le calcul des couleurs
- % Calcul de la couleur de la spirale par interpolation en utilisant ratio
- % r = ratio*couleur + (1-ratio)*couleur2
- % Ici couleur est une constante et couleur2 correspond a la couleur de fond
- % Ainsi, plus la spirale s'éloigne du centre plus elle prend la couleur du fond (ratio tends vers 0)
- 238 255 div ratio mul % r = 238 / 255 (couleur au centre de la spirale)
- .1 170 y sub 170 div y 50 mul sin 50 div add add 1 ratio sub mul % Couleur de fond qui dépend de y
- % Voir la fonction "fond" pour la formule traduite en infix
- add
- % Idem pour le bleu
- 98 255 div ratio mul
- .1 1 ratio sub mul % Couleur de fond
- add
- % Et pour le vert
- 139 255 div ratio mul
- 188 255 108 sub y 300 div mul sub 255 div 1 ratio sub mul % Couleur de fond
- add
- setrgbcolor
- stroke % On dessine le petit bout
- /lastangle angle def
- /lastdist dist def
- } for
- grestore
- } def
- /aureole { % Correspond à la spirale derrière le soleil
- gsave
- newpath % On clip sur la partie supérieur
- 0 400 moveto
- width 0 rlineto
- 0 -260 rlineto
- 0 width sub 0 rlineto
- closepath
- clip
- width 2 div 170 0 50 12000 spirale % On dessine la spirale avec comme paramètres :
- % x (centre) = width/2
- % y (centre) = 170
- % baseangle = 0
- % speed = 50
- % size = 12000 (l'angle va varier de 0 à 12000)
- grestore
- } def
- /point % Dessine un point sur le dessin aux coordonnées x, y
- {
- /y exch def % Arguments
- /x exch def
- newpath
- x y moveto
- x .5 add y lineto
- closepath % Petite ligne horizontale de taille 0.5
- 1 setgray
- .5 setlinewidth
- stroke
- } def
- /couleurfond { % Renvoie la couleur de fond en fonction de y
- 1 dict begin
- /y exch def
- .1 200 y sub 200 div y 50 mul sin 30 div add add
- %r = (200 - y)/200 + sin(y*50)/30 + .1
- %C'est un dégradé classique avec une subtilité grace au sin
- .1
- %g = .1
- 188 255 108 sub y 300 div mul sub 255 div
- %b = (188-(255-108)*(y/300))/255
- % Dégradé classique b part de 188 puis tends vers 0 quand y augmente (mais plus lentement que le rouge
- end
- } def
- /soleil { % Dessin du soleil
- /basey 170 def % Hauteur du soleil (ici un peu au dessus de l'horizon)
- -29 1 60 { % On dessine le soleil ligne à ligne (permet de faire un dégradé)
- /y exch def % le for donne la valeur de la hauteur relative à la base
- % width = 60*sqrt(1-(y/60)^2) Largeur de la ligne en fonction de la hauteur
- % Formule obtenue grâce au fait que la fonction y=sqrt(1-x^2) dessine un demi cercle
- /sunwidth 60 1 y 60 div dup mul sub sqrt mul def
- newpath
- width 2 div sunwidth sub % x = width/2 - sunwidth (rappel : width correspond à la largeur de la fenetre)
- basey y add % y = basey+y
- moveto
- sunwidth 2 mul % decalagex = 2*sunwidth
- 0 % decalagey = 0
- rlineto
- closepath
- 1.5 setlinewidth
- /ratio y 30 add 90 div def % ratio = (y + 30)/90, ratio correspond au pourcentage de soleil dessiné
- % Ce ifelse permet de faire les "trous" dans le soleil, en dessinant le fond à la place du soleil selon une fonction qui devient négative sur les intervalles que je voulais.
- % C'est donc pour ça qu'il y a un 0 le (<= 0) à la fin
- % La fonction dépend de la hauter et est donc
- % sin(y*((y / 2) + 50) + 20) + .2 (rappel : sin est en degré)
- % Visualisation de la fonction :
- % https://www.google.fr/?q=sin(pi*(y*((y+%2F+2)+%2B+50)+%2B+20)%2F180)+%2B+.2
- y 50 y 2 div add mul 20 add sin .2 add 0 le
- y 15 le and % On ne coupe que si y <= 15
- {
- basey y add couleurfond % On rempli le trou avec la couleur de fond (pour écraser la spirale derrière le soleil)
- }
- {
- % Pour la couleur du soleil en lui meme on fait juste une interpolation linéaire entre deux couleurs prises à la main
- % couleur1 = 254, 246, 0 (une sorte de violet)
- % couleur2 = 255, 45, 149 (un jaune)
- 254 255 div ratio mul
- 255 255 div 1 ratio sub mul
- add
- 246 255 div ratio mul
- 45 255 div 1 ratio sub mul
- add
- 0 255 div ratio mul
- 149 255 div 1 ratio sub mul
- add
- }
- ifelse
- setrgbcolor % on applique donc la couleur choisis
- stroke
- } for
- } def
- /fond { % Fonction qui dessine le dégradé de fond
- 0 0 moveto
- 0 1 width { % On dessine ligne à ligne
- /y exch def
- gsave
- newpath
- 0 y moveto
- width 0 rlineto
- closepath % On mets le path pour la ligne
- y couleurfond
- setrgbcolor
- stroke
- grestore
- } for
- } def
- /etoiles { % Dessin des étoiles en haut de l'image
- % Pour le dessin des étoiles, on coupe le ciel en 10 parties, puis plus on est haut dans le ciel plus cette partie à d'étoiles, celon la relation nb d'étoiles = (numéro_partie)^2
- 0 1 11 { % on boucle sur les parties
- /i exch def
- /basey 200 i 20 mul add def % Le y de base vaut donc 200 + i*20 (la hauteur de l'image vaut 400 en tout, et les étoiles partent du millieu)
- i i mul { % On boucle i^2 fois
- /x rand width mod def % On prend x au hasard entre 0 et width (x=rand(0, width))
- /y basey rand 20 mod add def % On prend y = basey + rand(0, 20)
- x y point % On dessine l'étoile
- } repeat
- } for
- } def
- % Pipeline de render
- fond % Couleur de fond
- aureole % Spirale derrière le soleil
- pavage % Pavage en perspective
- soleil % Dessin du soleil
- arbres % Dessin des arbres en allée
- etoiles % Dessin des étoiles en haut de l'écran
- showpage
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement