Roman Cortes a apporté des roses rouges écrites en scripts javascript. Rose Made with Code est le meilleur cadeau de la Saint-Valentin donné à votre petite amie par des programmeurs impressionnants! (Conseil: l'effet de visualisation et la vitesse seront très différents sous différents navigateurs)
L'image est générée par le code, et l'utilisateur peut actualiser la page et répéter le processus de présentation pour regarder la rose.
Le code d'implémentation de 3D Rose est le suivant:
La copie de code est la suivante: avec (m = math) c = cos, s = sin, p = pow, r = aléatoire; c.width = c.Height = f = 500; h = -250; fonction P (a, b, c) {if (c> 60) return [s (a * 7) * (13 + 5 / (. 2 + p (b * 4,4))) - s (b) * 50, b * f + 50,625 + c (a * 7) * (13+ 5 / (. 2 + p (b * 4,4))) + b * 400, a * 1-b / 2, a]; a = a * 2-1; b = b * 2-1; if (a * a + b * b <1) {if (c> 37) {n = (j = c & 1) ? 6: 4; o = .5 / (a + .01) + c (b * 125) * 3-a * 300; w = b * h; return [o * c (n) + w * s (n) + j * 610-390, o * s (n) -w * c (n) + 550-j * 350,1180 + c (b + a) * 99-j * 300, .4-a * .1 + p (1-b * b, -H * 6) *. 15-a * b * .4 + c (a + b) / 5 + p (c ((((((((. o * (a + 1) + (b> 0? w: -w)) / 25), 30) *. 1 * (1-b * b), o / 1e3 + .7-o * w * 3e-6]} if (c> 32) {c = c * 1.16-.15; o = a * 45-20; w = b * b * h; z = o * s (c) + w * c (c) +620; retour [o * c (c) -w * s (c), 28 + c (b * .5) * 99-b * b * b * 60-z / 2-h, z, (b * b * .3 + p ((1- (a * a)), 7) *. 15 + .3) * b, b * .7]} o = a * (2-b) * (80-c * 2); w = 99-C (A) * 120-C (B) * (- HC * 4.9) + C (P (1-B, 7)) * 50 + C * 2; Z = O * S (C) + W * C (C) +700; retour [o * c (c) -w * s (c), b * 99-c (p (b, 7)) * 50-c / 3-z / 1.35 + 450, z, (1-b / 1.2) *. 9 + a * .1, P ((1-b), 20) /4+.05]}} setInterval ('for (i = 0; i <1e4; i ++) if (s = p (r (), r (), i% 46 / .74)) {z = s [2]; x = ~~ (s [0] * f / zh); y = ~~ (s [1] * f / zh); ;
Bien sûr, les personnes intéressées peuvent comprendre le processus de mise en œuvre suivant et les théories connexes:
L'effet de présentation de ce code tridimensionnel Rose utilise la méthode Monte Carlo, et le créateur a très apprécié la méthode Monte Carlo. Il a dit que la méthode Monte Carlo est un "outil incroyablement puissant" en termes d'optimisation fonctionnelle et d'échantillonnage. Pour la méthode Monte Carlo, veuillez vous référer à: Méthode Monte Carlo.
Opérations spécifiques:
Apparence d'échantillonnage d'effet de rendu
J'ai utilisé plusieurs diagrammes de forme différents pour former ce code Rose. Un total de 31 formes ont été utilisées: 24 pétales, 4 sépales, 2 feuilles et 1 tige de fleur, et chaque diagramme de forme a été représenté dans le code.
Tout d'abord, définissez une plage d'échantillonnage:
Surface de fonction (a, b) {// J'utilise A et B comme paramètres variant de 0 à 1.Return {x: a * 50, y: b * 50}; // cette surface sera un carré de 50x50 de taille}Ensuite, écrivez le code de délimitation de forme:
var canvas = document.body.appendChild (document.createElement ("canvas")), context = canvas.getContext ("2d"), a, b, position; // maintenant je vais goûter la surface à .1 intervalles pour a et b paramètres: pour (a = 0; a <1; a + = .1) {pour (b = 0; b <1; b + = .1) {position = surface (a, a, a, a, a; b <1; b + =. b); context.fillrect (position.x, position.y, 1, 1);}}Maintenant, essayez un intervalle d'échantillonnage plus dense:
Comme vous pouvez le voir maintenant, car les intervalles d'échantillonnage deviennent denses et plus proches, les points se rapprochent de plus en plus de la densité la plus élevée, la distance entre les points adjacents est inférieur à un pixel, et l'intervalle ne peut pas être vu par l'œil nu (voir 0,01). Afin de ne pas provoquer trop de différence visuelle, l'intervalle d'échantillonnage est encore réduit. À l'heure actuelle, la zone de dessin a été remplie (les résultats de comparaison sont de 0,01 et 0,001).
Ensuite, j'utilise cette formule pour dessiner un cercle: (x-x0) ^ 2 + (y-y0) ^ 2 <Radius ^ 2, où (x0, y0) est le centre du cercle:
Surface de la fonction (a, b) {var x = a * 100, y = b * 100, rayon = 50, x0 = 50, y0 = 50; if ((x - x0) * (x - x0) + (y - y0) * (y - y0) <rayon * rayon) {// à l'intérieur du circleTurn {x: x, y};} else {// en dehors du circlernet null;}Pour éviter un débordement, une condition d'échantillonnage doit être ajoutée:
if (position = surface (a, b)) {context.fillrect (position.x, position.y, 1, 1);}Il existe différentes façons de définir un cercle, dont certains ne nécessitent pas de rejet de l'échantillonnage. Je n'ai pas à utiliser celui pour définir un cercle, donc j'utilise une autre méthode pour définir un cercle:
Surface de fonction (a, b) {// Cercle en utilisant des coordonnées polaires angle = a * math.pi * 2, rayon = 50, x0 = 50, y0 = 50; return {x: math.cos (angle) * rayon * b + x0, y: math.sin (angle) * radius * b + y0};};(Cette méthode nécessite un échantillonnage dense pour le remplissage par rapport à la méthode précédente.)
Ok, maintenant laissez le cercle se déformer pour le faire ressembler davantage à un pétale:
Surface de la fonction (a, b) {var x = a * 100, y = b * 100, rayon = 50, x0 = 50, y0 = 50; if ((x - x0) * (x - x0) + (y - y0) * (y - y0) <rayon * rayon) {return {x: x, y: y * (1 + b) / 2 // déformation};} else {retour;}}Cela ressemble à un pétale de rose. Ici, vous pouvez également essayer de modifier certaines valeurs de fonction, et de nombreuses formes intéressantes apparaîtront.
Ensuite, ajoutez-y de la couleur:
Surface de la fonction (a, b) {var x = a * 100, y = b * 100, rayon = 50, x0 = 50, y0 = 50; if ((x - x0) * (x - x0) + (y - y0) * (y - y0) <rayon * radius) {return {x: x, y: y * (1 + b) / 2, r: 100 + math. Ajouter un gradientg: 50, b: 50};} else {return null;}} pour (a = 0; a <1; a + = .01) {for (b = 0; b <1; b + = .001) {if (point = Surface (a, b)) {context.fillstyle = "rgb (" + point.r + " ")"; context.fillrect (Point.x, point.y, 1, 1);}}}Un pétale coloré apparaît.
Projection de surface et de perspective 3D
La définition d'une surface tridimensionnelle est simple, par exemple, pour définir un objet tubulaire:
Surface de fonction (a, b) {var angle = a * math.pi * 2, rayon = 100, longueur = 400; return {x: math.cos (angle) * radius, y: math.sin (angle) * rayon, z: b * longueur - longueur / 2, // en soustrayant la longueur / 2 j'ai centré le tube à (0, 0) r: 0, g: g: math.floor (b * 255) 0};}Ajoutez ensuite une perspective de projection. Nous devons d'abord définir une caméra:
Comme indiqué ci-dessus, placez la caméra en position (0, 0, z) et la toile dans le plan x / y. Les points d'échantillonnage projetés sur la toile sont:
var px, py, // projeté sur Canvas X et Y CoordonatsPerspective = 350, Halfheight = Canvas.Height / 2, Halfwidth = Canvas.Width / 2, cameraz = -700; for (a = 0; a <1; a + = .001) {pour (b = 0; b <1; b + = .01) {if (Point = surface (b) = (point.x * perspective) / (Point.z - cameraz) + halfwidth; py = (point.y * perspective) / (Point.z - cameraz) + halfheight; context.fillstyle = "rgb (" + point.r + "," + point.g + "," + point.b + ")"; context.fillrect (px, py, 1, 1, 1);L'effet est:
zéro
Z-Buffer est une technique très courante en informatique. Lorsque l'ombrage des objets, le fonctionnement de "l'élimination de la surface cachée" est effectué afin que la pièce derrière les objets cachés ne soit pas affichée.
L'image ci-dessus est une rose traitée avec la technologie Z-Buffer. (Vous pouvez voir qu'il a déjà une trois dimensionnalité)
Le code est le suivant:
var zBuffer = [], zBufferIndex; pour (a = 0; a <1; a + = .001) {pour (b = 0; b <1; b + = .01) {if (point = surface (a, b)) {px = math.floor ((point.x * perspective) / (point.z - cameraz) + halfwidth); py = mathé / (Point.z - cameraz) + halfheight); zBufferIndex = py * canvas.width + px; if ((typeof zBuffer [zBufferIndex] === "Undefined") || (point.z <zBuffer [zBufferIndex])) {zBuffer [zBufferIndex] = point.z; Point.r + "," + point.g + "," + point.b + ")"; context.fillrect (px, py, 1, 1);}}}}Tourner
Vous pouvez utiliser n'importe quelle méthode de rotation vectorielle. Dans la création du code Rose, j'utilise la rotation d'Euler. Maintenant, faites pivoter l'objet tubulaire précédemment écrit pour tourner autour de l'axe Y:
Surface de fonction (a, b) {var angle = a * math.pi * 2, radius = 100, longueur = 400, x = math.cos (angle) * radius, y = math.sin (angle) * radius, z = b * longueur - longueur / 2, yaxisrotationangle = -.4, // en radians! Math.sin (yaxisrotationangle), rotatedz = x * -math.sin (yaxisrotationangle) + z * math.cos (yaxisrotationangle); return {x: rotatedx, y: y, z: rotatedz, r: 0, g: math.floor (b * 255), b: 0};}Effet:
Méthode Monte Carlo
En ce qui concerne le temps d'échantillonnage, trop grand et trop petit entraînera une expérience visuelle extrêmement mauvaise, donc un intervalle d'échantillonnage raisonnable doit être défini, et la méthode Monte Carlo est utilisée ici.
var i; window.setInterval (function () {for (i = 0; i <10000; i ++) {if (Point = Surface (math.random (), math.random ())) {px = math.floor ((point.x * perspective) / (Point.z - cameraz) + halfwidth); py = math.floor ((point. + halfheight); zBufferIndex = py * canvas.width + px; if ((typeof zBuffer [zBufferIndex] === "Undefined") || (point.z <zBuffer [zBufferIndex])) {zBuffer [zBufferIndex] = point.z; Point.g + "," + point.b + ")"; context.fillrect (px, py, 1, 1);}}}}, 0);Définissez A et B en tant que paramètres aléatoires et remplissage de surface complet avec un échantillonnage suffisant. Je dessine 10000 points à chaque fois et j'attends que l'écran termine la mise à jour.
Il convient également de noter que si un nombre aléatoire est incorrect, l'effet de remplissage de surface sera incorrect. Dans certains navigateurs, l'exécution de la random mathématique est linéaire, ce qui peut entraîner des erreurs dans les effets de remplissage de surface. À l'heure actuelle, vous devez utiliser quelque chose comme Mersenne Twister (un algorithme de nombre aléatoire) pour effectuer un échantillonnage PRNG de haute qualité pour éviter les erreurs.
Finition
Pour que chaque partie de la rose soit terminée et rendu en même temps, une fonctionnalité doit être ajoutée pour définir un paramètre pour chaque partie pour renvoyer la valeur de synchronisation. Et utiliser une fonction de segment pour représenter les différentes parties de la rose. Par exemple, dans la partie pétale, j'utilise la rotation et la déformation pour les créer.
Bien que la méthode d'échantillonnage de surface soit l'une des méthodes les plus célèbres et les plus anciennes pour créer des graphiques tridimensionnels, cette méthode d'ajout de Monte Carlo et de Z-Buffer à l'échantillonnage de surface n'est pas courante. Ce n'est peut-être pas très créatif pour la production de scénarios réels, mais sa simple implémentation de code et sa petite taille sont toujours satisfaisantes.
Espérons que cet article inspirera les amateurs d'infographie pour essayer différentes méthodes de présentation et en s'amuser. (Roman Cortes)
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.