Roman Cortes brachte rote Rosen ein, die in JavaScript -Skripten geschrieben wurden. Rose mit Code gemacht ist das beste Geschenk zum Valentinstag, das Ihre Freundin von großartigen Programmierern gegeben hat! (Tipp: Der Betrachtungseffekt und die Geschwindigkeit sind unter verschiedenen Browsern sehr unterschiedlich)
Das Bild wird mit Code generiert, und der Benutzer kann die Seite aktualisieren und den Präsentationsprozess des Ansehens der Rose wiederholen.
Der Implementierungscode von 3D Rose lautet wie folgt:
Die Codekopie lautet wie folgt: mit (m = math) c = cos, s = sin, p = pow, r = random; c.width = c.Height = f = 500; H = -250; Funktion; 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 = 0,5/(a+.01)+c (b*125)*3-a*300; (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 ((c o*(a+1)+(b> 0? a*45-20; 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; Return [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/0,74)) {z = s [2]; x = ~~ (s [0]*f/zh); .
Natürlich können interessierte Personen den folgenden Implementierungsprozess und verwandte Theorien verstehen:
Der Präsentationseffekt dieses dreidimensionalen Codes Rose verwendet die Monte-Carlo-Methode, und der Schöpfer hat die Monte-Carlo-Methode hoch gelobt. Er sagte, dass die Monte -Carlo -Methode ein "unglaublich leistungsfähiges Werkzeug" in Bezug auf funktionale Optimierung und Probenahme ist. Für die Monte Carlo -Methode finden Sie unter: Monte Carlo -Methode.
Spezifische Operationen:
Aussehen Probenahme -Rendering -Effekt Zeichnung
Ich habe mehrere verschiedene Formdiagramme verwendet, um diesen Code Rose zu bilden. Insgesamt wurden 31 Formen verwendet: 24 Blütenblätter, 4 Kelchblätter, 2 Blätter und 1 Blütenstamm und jedes Formdiagramm wurden in Code dargestellt.
Definieren Sie zunächst einen Stichprobenbereich:
Funktionsoberfläche (a, b) {// Ich verwende A und B als Parameter zwischen 0 und 1.Return {x: a*50, y: b*50}; // Diese Oberfläche ist ein Quadrat von 50 x 50 Größeneinheiten}Schreiben Sie dann den Shape -Abgrenzungscode:
var canvas = document.body.AppendChild (document.createelement ("canvas")), context = canvas.getContext ("2d"), a, b, Position; // Jetzt werde ich die Oberfläche bei 0,1 Intervallen für A und B -Parameter: für (a = 0; a <1; a += .1) {{{b = (b = (b = (b = (b =) probieren (b = (b = (b = (b =). b); context.FillRect (Position.x, Position.Y, 1, 1);}}Versuchen Sie nun ein dichteres Abtastintervall:
Wie Sie jetzt sehen können, da die Stichprobenintervalle dichter und näher kommen, liegt die Punkte immer näher an der höchsten Dichte, der Abstand zwischen benachbarten Punkten ist weniger als ein Pixel, und das Intervall kann nicht von dem Nakedauge gesehen werden (siehe 0,01). Um nicht zu viel visuellen Unterschied zu verursachen, wird das Stichprobenintervall weiter reduziert. Zu diesem Zeitpunkt wurde der Zeichenbereich gefüllt (Vergleichsergebnisse betragen 0,01 und 0,001).
Als nächstes zeichne ich diese Formel, um einen Kreis zu zeichnen: (x-x0)^2 + (y-y0)^2 <radius^2, wobei (x0, y0) die Mitte des Kreises ist:
function surface(a, b) {var x = a * 100,y = b * 100,radius = 50,x0 = 50,y0 = 50;if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {// inside the circlereturn {x: x,y: y};} else {// outside the circlereturn null;}}Um Überlauf zu verhindern, muss eine Stichprobenerkrankung hinzugefügt werden:
if (Position = oberflächen (a, b)) {context.fillRect (Position.x, Position.Y, 1, 1);}Es gibt verschiedene Möglichkeiten, einen Kreis zu definieren, von denen einige keine Ablehnung der Probenahme erfordern. Ich muss nicht verwenden, welches einen Kreis definieren kann. Daher verwende ich eine andere Methode, um einen Kreis zu definieren:
Funktionsoberfläche (a, b) {// Kreis mit polaren Koordinatenvar Angle = a * math.pi * 2, radius = 50, x0 = 50, y0 = 50; return {x: math.cos (Winkel) * Radius * B + x0, y: math.sin (Winkel) * Radius * b +};};};};};};};}(Diese Methode erfordert eine dichte Abtastung für das Füllen im Vergleich zur vorherigen Methode.)
OK, lassen Sie den Kreis nun deformieren, damit er eher wie ein Blütenblatt aussieht:
function surface(a, b) {var x = a * 100,y = b * 100,radius = 50,x0 = 50,y0 = 50;if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {return {x: x,y: y * (1 + b) / 2 // deformation};} else {return null;}}Das sieht aus wie ein Rosenblatt. Hier können Sie auch versuchen, einige Funktionswerte zu ändern, und es werden viele interessante Formen erscheinen.
Als nächstes fügen Sie Farbe hinzu:
Funktionsoberfläche (a, b) {var x = a * 100, y = b * 100, radius = 50, x0 = 50, y0 = 50; if (x - x0) * (x - x0) + (y - y0) * (y - y0) <radius * radius) {return {x: y: y * (1 + b) / 2, r: 100 + math.floor (1 - 1 + b) / 2, r: 100 + math. a gradientg: 50, b: 50};} else {return null;}} für (a = 0; a <1; a + = 0,01) {für (b = 0; b <1; b + = 0,001) {if (point = oberflächen) (a, b)) {context.fillstyle = "rgb (" + point (" + Point.R +", " + Point.", ",", ",", "", "", "", "", "", "", "" " ")"; context.FillRect (point.x, point.y, 1, 1);}}}Ein farbiges Blütenblatt erscheint.
3D -Oberfläche und Perspektivprojektion
Das Definieren einer dreidimensionalen Oberfläche ist beispielsweise einfach, um ein tubuläres Objekt zu definieren:
function surface(a, b) {var angle = a * Math.PI * 2,radius = 100,length = 400;return {x: Math.cos(angle) * radius,y: Math.sin(angle) * radius,z: b * length - length / 2, // by subtracting length/2 I have centered the tube at (0, 0, 0)r: 0,g: Math.floor(b * 255),b: 0};}Fügen Sie dann eine Projektionsperspektive hinzu. Zuerst müssen wir eine Kamera definieren:
Wie oben gezeigt, platzieren Sie die Kamera in (0, 0, z) und die Leinwand in der X/Y -Ebene. Die auf die Leinwand projizierten Stichprobenpunkte sind:
var px, py, // auf Leinwand x und y Koordinaten projiziert = 350, halbheigheight = canvas.height / 2, Halfwidth = Canvas.Width / 2, Cameraz = -700; für (a = 0; a <1; a += 0,001) {für (b <= 0; b <1; b <1; b <1; b <1; b <1; b <1; b <1; b <1; b <1). (point.x * perspective) / (point.z - cameraz) + halfwidth; py = (point.y * perspective) / (point.z - cameraz) + halfheight; context.fillstyle = "rgb (" + point.r + "," + point.g + ", + Punkt, 1");Der Effekt ist:
Z-Puffer
Z-Buffer ist eine sehr häufige Technik in Computergrafiken. Beim Schattieren von Objekten wird die Arbeit "versteckter Oberflächenausscheidung" durchgeführt, so dass das Teil hinter den verborgenen Objekten nicht angezeigt wird.
Das Bild oben ist eine Rose, die mit Z-Puffer-Technologie verarbeitet wird. (Sie können sehen, dass es bereits dreidimensionalität hat)
Der Code ist wie folgt:
var zbuffer = [], zbufferIndex; für (a = 0; a <1; a += 0,001) {für (b = 0; b <1; b += 0,01) {if (point = oberen (a, b)) {px = math.floor ((point.x * perspective) / (point.z - cameraz). (point.z - cameraz) + halbheight); point.r + "," + point.g + "," + point.b + ")"; context.FillRect (px, py, 1, 1);}}}}Drehen
Sie können jede Vektorrotationsmethode verwenden. Bei der Erstellung des Code Rose verwende ich die Euler -Rotation. Drehen Sie nun das zuvor geschriebene röhrenförmige Objekt, um sich um die Y -Achse zu drehen:
Funktionsoberfläche (a, b) {var Angle = a * math.pi * 2, Radius = 100, Länge = 400, x = math.cos (Winkel) * Radius, y = math.sin (Winkel) * Radius, z = B * Länge - Länge / 2, yaxisrotika = -.4, // in Radians, rotatedx = x * math.cos (yaxisrottang) (rotatedx = x * math.cos (yaxisrotta Math.sin (yaxisRotationangle), rotatatedz = x * -math.sin (yaxisRotationangle) + z * math.cos (yaxisRotationangle); return {x: rotatatatedx, y: y, z: rotatedz, r: 0, g: math.floor (b * 255), b: 0};};Wirkung:
Monte Carlo -Methode
In Bezug auf die Stichprobenzeit verursacht zu groß und zu klein extrem schlechte visuelle Erfahrung, so dass ein vernünftiges Abtastintervall festgelegt werden muss, und hier wird die Monte -Carlo -Methode verwendet.
var i; window.setInterval (function () {für (i = 0; i <10000; i ++) {if (point = sasce (math.random (), math.random ()) {px = math.floor ((point.x * perspektive) / (point.z - cameraz) +halfwidth); halbwert); 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);Setzen Sie A und B als Zufallsparameter und komplette Oberflächenfüllung mit ausreichender Abtastung. Ich zeichne jedes Mal 10000 Punkte und warte darauf, dass der Bildschirm das Update abschließt.
Es sollte auch beachtet werden, dass der Oberflächenfüllungseffekt, wenn eine Zufallszahl falsch ist, falsch ist. In einigen Browsern ist die Ausführung von Mathematik linear, was zu Fehlern der Oberflächenfüllungseffekte führen kann. Zu diesem Zeitpunkt müssen Sie so etwas wie Mersenne Twister (ein Zufallszahlalgorithmus) verwenden, um eine qualitativ hochwertige PRNG-Stichprobe durchzuführen, um Fehler zu vermeiden.
Beenden
Damit jeder Teil der Rose gleichzeitig vervollständigt und rendert, muss eine Funktion hinzugefügt werden, um einen Parameter für jeden Teil festzulegen, um den Wert für die Synchronisation zurückzugeben. Und verwenden Sie eine Segmentfunktion, um die verschiedenen Teile der Rose darzustellen. Zum Beispiel verwende ich im Blattenteil Rotation und Verformung, um sie zu erstellen.
Obwohl die Oberflächenabtastmethode eine der bekanntesten und ältesten Methoden zur Erstellung von dreidimensionalen Grafiken ist, ist diese Methode zum Hinzufügen von Monte-Carlo und Z-Puffer zu Oberflächenabtastung nicht üblich. Dies ist möglicherweise nicht sehr kreativ für die Produktion von Szenarien im realen Szenario, aber seine einfache Code-Implementierung und kleine Größe sind immer noch zufriedenstellend.
Hoffentlich wird dieser Artikel Computergrafikbegeisterte dazu inspirieren, verschiedene Präsentationsmethoden auszuprobieren und Spaß daran zu haben. (Römische Kortier)
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.