Roman Cortes membawa mawar merah yang ditulis dalam skrip JavaScript. Rose Made With Code adalah hadiah Hari Valentine terbaik yang diberikan kepada pacar Anda oleh programmer yang luar biasa! (Tip: Efek dan kecepatan tampilan akan sangat berbeda di bawah browser yang berbeda)
Gambar dihasilkan oleh kode, dan pengguna dapat menyegarkan halaman dan mengulangi proses presentasi menonton mawar.
Kode implementasi 3D Rose adalah sebagai berikut:
Salinan kode adalah sebagai berikut: dengan (m = matematika) c = cos, s = sin, p = pow, r = acak; c.width = c.height = f = 500; h = -250; fungsi 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; return [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; Kembalikan [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 ('untuk (i = 0; i <1e4; i ++) if (s = p (r (), r (), i%46/.74)) {z = s [2]; x = ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ {z = S [S [S [S [S [S [0] (S [S [S [0]*F/Z); (! M [q = y*f+x] | m [q]> z) m [q] = z, a.fillstyle = "rgb ("+~ (s [3]*h)+","+~ (s [4]*h)+","+~ (s [3]*s [3]*-80)+")", a.fillrrrect (s [3]*s [3]*-80)+")") ", A.
Tentu saja, orang yang tertarik dapat memahami proses implementasi berikut dan teori terkait:
Efek presentasi dari kode tiga dimensi ini Rose menggunakan metode Monte Carlo, dan pencipta sangat memuji metode Monte Carlo. Dia mengatakan bahwa metode Monte Carlo adalah "alat yang sangat kuat" dalam hal optimasi dan pengambilan sampel fungsional. Untuk metode Monte Carlo, silakan merujuk ke: Metode Monte Carlo.
Operasi spesifik:
Penampilan pengambilan sampel rendering efek efek
Saya menggunakan beberapa diagram bentuk yang berbeda untuk membentuk kode ini mawar. Sebanyak 31 bentuk digunakan: 24 kelopak, 4 sepal, 2 daun dan 1 batang bunga, dan setiap diagram bentuk digambarkan dalam kode.
Pertama, tentukan rentang pengambilan sampel:
Permukaan fungsi (a, b) {// Saya menggunakan A dan B sebagai parameter berkisar dari 0 hingga 1.Return {x: a*50, y: b*50}; // Permukaan ini akan menjadi kuadrat ukuran 50x50 unit}Kemudian, tulis kode Delineasi Bentuk:
var canvas = document.body.appendChild (document.createElement ("canvas")), context = canvas.getContext ("2d"), a, b, position; // Sekarang saya akan mencicipi permukaan pada interval .1 untuk parameter a dan b: untuk (a = 0; a <1; a += .1) {for (b = (a = 0; a <1; a += .1) {b = b = b = b = 0; a; b); context.fillrect (position.x, position.y, 1, 1);}}Sekarang, cobalah interval pengambilan sampel yang lebih padat:
Seperti yang dapat Anda lihat sekarang, karena interval pengambilan sampel semakin padat dan lebih dekat, titik -titik semakin dekat dan lebih dekat ke kepadatan tertinggi, jarak antara titik yang berdekatan kurang dari satu piksel, dan interval tidak dapat dilihat oleh mata telanjang (lihat 0,01). Agar tidak menyebabkan terlalu banyak perbedaan visual, interval pengambilan sampel semakin berkurang. Pada saat ini, area gambar telah diisi (hasil perbandingan adalah 0,01 dan 0,001).
Selanjutnya, saya menggunakan rumus ini untuk menggambar lingkaran: (x-x0)^2 + (y-y0)^2 <radius^2, di mana (x0, y0) adalah pusat lingkaran:
permukaan fungsi (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) {// di dalam sirklereTurn {x: x, y: y};Untuk mencegah overflow, kondisi pengambilan sampel harus ditambahkan:
if (position = permukaan (a, b)) {context.fillrect (position.x, position.y, 1, 1);}Ada berbagai cara untuk mendefinisikan lingkaran, beberapa di antaranya tidak memerlukan penolakan pengambilan sampel. Saya tidak harus menggunakan yang mana untuk mendefinisikan lingkaran, jadi saya menggunakan metode lain untuk menentukan lingkaran:
fungsi fungsi (a, b) {// lingkaran menggunakan koordinat polar sudut = a * math.pi * 2, radius = 50, x0 = 50, y0 = 50; return {x: math.cos (sudut) * radius * b + x0, y: math.sin (sudut) * radius * b + y0};}(Metode ini membutuhkan pengambilan sampel padat untuk mengisi dibandingkan dengan metode sebelumnya.)
Oke, sekarang biarkan lingkaran cacat membuatnya terlihat lebih seperti kelopak:
permukaan fungsi (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 /2Ini terlihat seperti kelopak mawar. Di sini Anda juga dapat mencoba memodifikasi beberapa nilai fungsi, dan banyak bentuk yang menarik akan muncul.
Selanjutnya, tambahkan warna ke dalamnya:
permukaan fungsi (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, radius) {return {x: x, y: y * (1 + b) / 2, radius) {return {x: x, y: y * (1 + b) / 2, radius) {return {x: x, y: y * (1 + b) / 2, radius Tambahkan gradientg: 50, b: 50};} else {return null;}} untuk (a = 0; a <1; a + = .01) {for (b = 0; b <1; b + = .001) {if (point = permukaan (a, b)) {context.fillstyle = "rgb (" + point.r. "" "", "", "" "," point. "" "" " ")"; context.fillrect (point.x, point.y, 1, 1);}}}Petal berwarna muncul.
Permukaan 3D dan proyeksi perspektif
Mendefinisikan permukaan tiga dimensi sederhana, misalnya, untuk menentukan objek tubular:
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};}Kemudian tambahkan perspektif proyeksi. Pertama kita perlu mendefinisikan kamera:
Seperti yang ditunjukkan di atas, tempatkan posisi kamera (0, 0, z) dan kanvas di bidang x/y. Titik pengambilan sampel yang diproyeksikan ke kanvas adalah:
var px, py, // diproyeksikan pada kanvas x dan y koordinatperspecte = 350, Halfheight = Canvas.height / 2, Halfwidth = Canvas.width / 2, Cameraz = -700; untuk (a = 0; a <1; a += .001) {untuk (b = 0; b <1; a <1; a += .001) {untuk (b = 0; b <1; a <1; a += .001) {for (b = 0; b <1; {px = (point.x * perspektif) / (point.z - cameraz) + Halfwidth; py = (point.y * perspektif) / (point.z - cameraz) + Halfheight; context.fillstyle = "rgb (" + point.r + "," + point.g + "," + point.b + ")"; 1);}}}Efeknya adalah:
z-buffer
Z-buffer adalah teknik yang sangat umum dalam grafik komputer. Saat mengarahkan benda, pekerjaan "eliminasi permukaan tersembunyi" dilakukan sehingga bagian di belakang objek tersembunyi tidak akan ditampilkan.
Gambar di atas adalah mawar yang diproses dengan teknologi z-buffer. (Anda dapat melihat bahwa ia sudah memiliki tiga dimensi)
Kodenya adalah sebagai berikut:
var zbuffer = [], zbufferIndex; untuk (a = 0; a <1; a += .001) {for (b = 0; b <1; b += .01) {if (point = permukaan (a, b) (pointz) pointz) (point.x; point.x; point.x * perspektif) / (point.z - cameraz (pointz); / (point.z - cameraz) + Halfheight); zbufferIndex = py * canvas.width + px; if ((typeof zbuffer [zbufferIndex] === "tidak terdefinisi") || (point.z <zbuffer [zbufferIndex])) {zbuffer [zbuffer = pointzer (zbuffers.pointlex. + point.r + "," + point.g + "," + point.b + ")"; context.fillrect (px, py, 1, 1);}}}}Memutar
Anda dapat menggunakan metode rotasi vektor apa pun. Dalam pembuatan kode Rose, saya menggunakan rotasi Euler. Sekarang putar objek tubular yang ditulis sebelumnya untuk diputar tentang sumbu Y:
Permukaan fungsi (a, b) {var sudut = a * math.pi * 2, radius = 100, panjang = 400, x = math.cos (sudut) * radius, y = math.sin (sudut) * radius, z = b * panjang - panjang / 2, yaxisrotationangle = -.4, // dalam radian! Rotatedx = matematika. Math.sin (yaxisrotationangle), rotedz = x * -math.sin (yaxisrotationangle) + z * math.cos (yaxisrotationangle); return {x: rotatedx, y: y, z: rotedz, r: 0, g: math.floor (b * 255), b: 0};Memengaruhi:
Metode Monte Carlo
Mengenai waktu pengambilan sampel, terlalu besar dan terlalu kecil akan menyebabkan pengalaman visual yang sangat buruk, sehingga interval pengambilan sampel yang masuk akal perlu ditetapkan, dan metode Monte Carlo digunakan di sini.
var i; window.setInterval (function () {for (i = 0; i <10000; i ++) {if (point = permukaan (math.random (), math.random ())) {px = math.floor (point.x * perspektif) / (point.z - cameraz)+setengah pya (point. + Halfheight); zBufferIndex = py * canvas.width + px; if ((tipe dari zbuffer [zbufferIndex] === "tidak terdefinisi") || (point.z <zbuffer + point. "," point.z; "point.", "point." " point.g + "," + point.b + ")"; context.fillrect (px, py, 1, 1);}}}}, 0);Atur A dan B sebagai parameter acak dan pengisian permukaan lengkap dengan pengambilan sampel yang cukup. Saya menggambar 10000 poin setiap kali dan menunggu layar untuk menyelesaikan pembaruan.
Perlu juga dicatat bahwa jika angka acak salah, efek pengisian permukaan akan salah. Di beberapa browser, pelaksanaan matematika. Random linier, yang dapat menyebabkan kesalahan dalam efek pengisian permukaan. Pada saat ini, Anda harus menggunakan sesuatu seperti Mersenne Twister (algoritma bilangan acak) untuk melakukan pengambilan sampel PRNG berkualitas tinggi untuk menghindari kesalahan.
Menyelesaikan
Agar setiap bagian mawar dapat menyelesaikan dan merender pada saat yang sama, fitur perlu ditambahkan untuk mengatur parameter untuk setiap bagian untuk mengembalikan nilai sinkronisasi. Dan gunakan fungsi segmen untuk mewakili berbagai bagian mawar. Misalnya, di bagian kelopak, saya menggunakan rotasi dan deformasi untuk membuatnya.
Meskipun metode pengambilan sampel permukaan adalah salah satu metode paling terkenal dan tertua untuk membuat grafik tiga dimensi, metode ini untuk menambahkan Monte Carlo dan Z-buffer ke pengambilan sampel permukaan tidak umum. Ini mungkin tidak terlalu kreatif untuk produksi skenario kehidupan nyata, tetapi implementasi kode sederhana dan ukuran kecil masih memuaskan.
Semoga artikel ini akan menginspirasi penggemar grafis komputer untuk mencoba berbagai metode presentasi dan bersenang -senang darinya. (Cortes Romawi)
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.