PIXEL BENDER #3 espace normalisé
![]()
quand le repère est normalisé, l’espace de toute l’image est compris entre -1 et 1 en x et en y ( enfin si j’ai tout compris…).
ça peut paraître con mais point du tout.
une fois normalisé, on peut facilement faire des trucs trop bizarres qui ressemblent un peu à des fonctions mathématiques en plus tordues.
la base :
<languageVersion : 1.0;> kernel Distort < namespace : "net.nicoptere.filters"; vendor : "nicolas barradeau"; version : 1; description : "normalized coordinates"; > { input image4 src; output pixel4 dst; parameter float2 imageSize < minValue:float2( 2.0, 2.0 ); maxValue:float2( 256.0, 256.0 ); defaultValue:float2( 256.0, 256.0 ); >; parameter float2 center < minValue:float2( 0.0, 0.0 ); maxValue:float2( 256.0, 256.0 ); defaultValue:float2( 128.0, 128.0 ); >; void evaluatePixel() { //offsets the image float2 pos = outCoord() - center; //creates a normalized coordinates system float W = imageSize.x; float H = imageSize.y; float x = pos.x; float y = pos.y; float u = x / W; float v = y / H; float w = 0.0; //a couple of useful variables float pi = 3.14159265358979; float radian = ( pi / 180.0 ); float r = sqrt( u*u + v*v ); float a = atan( v, u ); //tweak here u = cos( a ) * dot( u,u ); v = sin( a ) * dot( v,v ); //stop tweaking //feedback loop if( u > 1.0 ) u -= floor( u ); if( v > 1.0 ) v -= floor( v ); if( u < -1.0 ) u += ceil( -u ); if( v < -1.0 ) v += ceil( -v ); //rescale u *= W; v *= H; dst = sampleNearest(src,float2(center.x+u, center.y+v )); } }
donc:
on commence par décaler le pixel à analyser:
//offsets the image float2 pos = outCoord() - center;
puis on le divise par la taille totale.
//creates a normalized coordinates system float u = pos.x / imageSize.x; float v = pos.y / imageSize.y;
on patouille, on patouille, en l’occurence:
u = cos( a ) * dot( u,u ); v = sin( a ) * dot( v,v );
on vérifie que les pixels soient dans la fenêtre: ça augmente la complexité
//feedback loop if( u > 1.0 ) u -= floor( u ); if( v > 1.0 ) v -= floor( v ); if( u < -1.0 ) u += ceil( -u ); if( v < -1.0 ) v += ceil( -v );
et puis hop on redimensionne (multiplier par la taille de l’image )
//rescale u *= imageSize.x; v *= imageSize.y;
ni vu ni connu on re décale:
dst = sampleNearest(src,float2(center.x+u, center.y+v ));
et zou.
je vois des sceptiques donc le code ci dessus donnera ça :
qu’est ce qu’on rigole!
bon alors si tu as tout compris, tu peux désormais utiliser les codes suivants sur cette image:
![]()
ce qui donnera pour:
u = cos( a ) * dot( u,u ); v = sin( a ) * dot( v,v );
![]()
avec
u = cos( a ) / r; v = sin( a ) / r;
![]()
NB il n’y a pas de random() dans PixelBender ce qui est nul.
en patouillant, j’ai trouvé un moyen de faire un truc à peu près aléatoire.
float mess = x * H + y; u = cos( mess / 180.0 * pi ) * 1.0/mess; v = sin( mess / 180.0 * pi ) * mess / r;
![]()
sur le site de mathCurve il y a pléthore de fonctions dont par exemple la courbe quintique:
//http://www.mathcurve.com/courbes2d/quintic/quintic.shtml u += ( r * sin( a ) ) / 1.0 + cos( a ) * cos( 2.0 * a ); v += ( r * sin( a ) ) / 1.0 + cos( a ) * cos( 2.0 * a );
![]()
le bifolium régulier:
//http://www.mathcurve.com/courbes2d/bifoliumregulier/bifoliumregulier.shtml u += 4.0 * r * sin( a ) * dot( cos( a ), cos( a ) ); v += 4.0 * r * sin( a ) * dot( cos( a ), cos( a ) );
![]()
je vous recommande d’ailleurs deux excellentes ressources:
- le site d’iñigo quilez: http://iquilezles.org/www/articles/deform/deform.htm
- (ce batard de) Mr Doob: http://mrdoob.com/blog/post/586
chez iñigo, il y a des fameuses distortions (c’est toujours la meme image de base)
u = x * cos( 2.0 * r ) - y * sin( 2.0 * r ); v = y * cos( 2.0 * r ) + x * sin( 2.0 * r );
![]()
r *= 2.0; u = 0.02 * y + cos( a*3.0)*r*r; v = 0.02 * x + sin( a*3.0)*r*r;
![]()
une autre page qui vaut des points c’est celle de Paul Bourke sur la géométrie:
mettons epicycloid s’écrira:
u += (r2 + r1) * cos(a) - r1 * cos( (r2 + r1) * a / r1); v += (r2 + r1) * sin(a) - r1 * sin( (r2 + r1) * a / r1);
et avec r1 = -.1 et r2 = -.3 on obtiendra:
![]()
on a aussi le folium simple :
r = 3.0 * cos(t) * sin(t) / (cos(t) * 3.0 + sin(t) * 3.0 ) ; u = cos( a ) * r; v = sin( a ) * r;
![]()
etc. etc.
bref c’est un peu foufou tout ça. je vous recommande de changer les largeurs / hauteurs de l’image.
je sais pas trop de quoi parleront les prochains posts. avec ça il y a de quoi s’amuser un moment.
si je trouve des trucs intéressants, je ferai peut être un billet tips and tricks un coup. par exemple stocker PI, PI2, radian en paramètres n’est pas idiot.
float i = ( y * W ) + x;
nous donne l’itération courante etc.
à suivre donc
Très très bon comme base pour faires des shaders !
merci ^^
il y a plus optimisé, j’y reviendrai peut être. tel quel, ça reste lisible et c’était un peu le but.