Membuat gambar tanpa cacat di Photoshop mudah: potong gambar, ambil bagian kanan dan bawah yang dipangkas, lalu tempelkan ke kiri dan atas menggunakan alat Fade. Tetapi untuk implementasi yang tepat dari peta kebisingan mulus, Anda harus berpikir dengan hati-hati.Jika Anda memiliki pemahaman dasar tentang kebisingan Perlin , maka Anda tahu bahwa itu terdiri dari angka acak yang diinterpolasi. Ini terutama digunakan dalam dua dimensi. Tetapi ini juga berguna dalam satu dimensi (misalnya, ketika bergerak), dalam tiga dimensi (transformasi silindris dan bola benda 3D), dan bahkan dalam empat atau lima dimensi.Noise empat dimensi dapat digunakan untuk membuat gambar 2D yang mulus. Tidak umum bagi kita untuk berpikir dalam empat dimensi, jadi kita akan mengambil satu dimensi pada satu waktu.Dalam contoh saya, saya menggunakan noise simplex dua oktaf. Kebisingan simpleks lebih cepat dalam dimensi besar, dan karena sifatnya yang segitiga, ia terlihat lebih baik.Saya menulis fungsi kecil drawNoise
untuk membuat kanvas dan memproses array piksel dalam satu lingkaran.Suara mulus satu dimensi
Dalam satu dimensi, noise adalah garis halus tanpa batas (implementasi saya terhadap noise dimulai dengan dua, jadi saya menggunakan konstanta sebagai parameter kedua). Di sini kita melihat bahwa ini hanyalah angka acak yang diinterpolasi.
fNoiseScale = .02;
drawNoise(function(i,x,y){
var v = Simplex.noise(
123+x*fNoiseScale
,137
);
return v*iSize>y?255:0;
}).img();
Kebisingan satu dimensiAnda dapat menggunakan ini dalam animasi, menghitung ulang nilai kebisingan setiap milidetik, tetapi Anda juga dapat membuat lingkaran dan menghitung semua nilai di muka. Nilai-nilai pada gambar di atas tidak berputar di sekitar tepi. Tetapi menerapkan pengulangan cukup sederhana, hanya satu dimensi dan loop ... atau lingkaran, untuk itu.Lingkaran satu dimensi
Bagi sebagian besar dari Anda, kebisingan Perlin terlihat seperti gambar di bawah ini.Jika kita menggambar sebuah lingkaran di sini dan menghitung nilai noise pada lingkaran ini, kita akan mendapatkan loop satu dimensi.Noise with a circle untuk membuat loop satu dimensi.Dalam kode, tampilannya seperti ini:
drawNoise(function(i,x,y){
var fNX = x/iSize
,fRdx = fNX*2*Math.PI
,a = fRdsSin*Math.sin(fRdx)
,b = fRdsSin*Math.cos(fRdx)
,v = Simplex.noise(
123+a*fNoiseScale
,132+b*fNoiseScale
)
;
return v*iSize>y?255:0;
}).img().div(2);
Anda mungkin sudah mengerti apa yang akan kita lakukan. Untuk mengulang gambar dua dimensi, kita membutuhkan peta noise tiga dimensi (setidaknya).Kartu silinder
Noise Perlin pada awalnya dibuat untuk 3D-texturing kontinu (film "Tron"). Peta gambar bukan selembar kertas yang melilit objek, tetapi dihitung dengan lokasinya di bidang kebisingan tiga dimensi. Karena itu, ketika memotong objek, kita masih bisa menghitung peta untuk permukaan yang baru dibuat.Sebelum kita mencapai tujuan akhir dari gambar tanpa batas, pertama-tama kita membuat gambar yang menyatu dengan mulus ke kiri dan kanan. Ini mirip dengan lingkaran dua dimensi untuk loop satu dimensi, tetapi dengan satu dimensi tambahan: silinder.
drawNoise(function(i,x,y){
var fNX = x/iSize
,fRdx = fNX*2*Math.PI
,a = fRdsSin*Math.sin(fRdx)
,b = fRdsSin*Math.cos(fRdx)
,v = Simplex.noise(
123+a*fNoiseScale
,132+b*fNoiseScale
,312+y*fNoiseScale
)
;
return v*255<<0;
}).img().div(2);
Peta kebisingan silinderGambar peta bulat
Anda mungkin berpikir bahwa akan lebih mudah menggunakan bola untuk membuat gambar yang mulus, tetapi Anda salah.Saya akan membuat penyimpangan kecil dan menunjukkan bagaimana peta gambar bulat dihitung dan seperti apa.
document.body.addChild('h2').innerText = 'three dimensional spherical map';
fNoiseScale = .1;
var oSpherical = drawNoise(function(i,x,y){
var fNX = (x+.5)/iSize
,fNY = (y+.5)/iSize
,fRdx = fNX*2*Math.PI
,fRdy = fNY*Math.PI
,fYSin = Math.sin(fRdy+Math.PI)
,a = fRdsSin*Math.sin(fRdx)*fYSin
,b = fRdsSin*Math.cos(fRdx)*fYSin
,c = fRdsSin*Math.cos(fRdy)
,v = Simplex.noise(
123+a*fNoiseScale
,132+b*fNoiseScale
,312+c*fNoiseScale
)
;
return v*255<<0;
}).img();
Peta kebisingan bolaBulatkan dengan kebisinganPeta panorama kubik
Bola yang kami buat juga dapat digunakan sebagai panorama jika Anda menempatkan kamera di tengah bola. Tetapi cara terbaik adalah menggunakan panorama kubik, karena memiliki wajah yang jauh lebih sedikit. Bola diproyeksikan ke enam sisi kubus, seperti yang ditunjukkan dalam sketsa ini.Menumpangkan bola pada sebuah kubusUntuk setiap piksel pada permukaan kubus, kita perlu menghitung persimpangan antara sudut pandang C di tengah dan bola. Ini mungkin terlihat rumit, tetapi sebenarnya cukup sederhana.Kita dapat menganggap garis CA sebagai vektor. Dan vektor dapat dinormalisasi sehingga arahnya tidak berubah, tetapi panjangnya berkurang menjadi 1. Karena ini, semua vektor bersama-sama akan terlihat seperti bola.Normalisasi juga cukup sederhana, kita hanya perlu membagi nilai-nilai vektor dengan xyz dengan total panjang vektor. Panjang vektor dapat dihitung menggunakan teorema Pythagoras.Dalam kode di bawah ini, perhitungan normalisasi pertama kali dilakukan pada satu wajah. Kemudian noise dihitung secara bersamaan untuk keenam tepi, karena untuk mendapatkan posisi wajah berikutnya, Anda hanya perlu membalik nilai-nilai sepanjang xyz.
document.body.addChild('h2').innerText = '3D panoramical cube map';
var mCubemap = document.createElement('canvas')
,iW = 6*iSize;
mCubemap.width = iW;
mCubemap.height = iSize;
var iHSize = iSize/2
,oCtx = mCubemap.getContext('2d')
,oImgData = oCtx.getImageData(0,0,iW,iSize)
,aPixels = oImgData.data
,aa = 123
,bb = 231
,cc = 321
;
for (var i=0,l=iSize*iSize;i<l;i++) {
var x = i%iSize
,y = (i/iSize)<<0
,a = -iHSize + x+.5
,b = -iHSize + y+.5
,c = -iHSize
,fDistanceAB = Math.sqrt(a*a+b*b)
,fDistanceABC = Math.sqrt(fDistanceAB*fDistanceAB+c*c)
,fDrds = .5*fDistanceABC
,v = 1
;
a /= fDrds;
b /= fDrds;
c /= fDrds;
var aNoisePositions = [
[a,b,c]
,[-c,b,a]
,[-a,b,-c]
,[c,b,-a]
,[a,c,-b]
,[a,-c,b]
];
for (var j=0;j<6;j++) {
v = Simplex.noise(
aa + aNoisePositions[j][0]
,bb + aNoisePositions[j][1]
,cc + aNoisePositions[j][2]
);
var pos = 4*(y*iW+j*iSize+x);
aPixels[pos] = aPixels[pos+1] = aPixels[pos+2] = v*255<<0;
aPixels[pos+3] = 255;
}
}
oCtx.putImageData(oImgData,0,0);
document.body.addChild('img',{src:mCubemap.toDataURL("image/jpeg")});
Berikut adalah enam sisi dalam satu gambar, plus tangkapan layar tampilannya ketika dilihat dari kubus. Kode sumber memiliki contoh 3D yang ditulis dalam threejs .Peta panorama kubikGambar 2D mulus
Mungkin terlihat bahwa gambar 2D tanpa batas mudah untuk diimplementasikan, tetapi bagi saya ini adalah yang paling sulit dari yang dijelaskan dalam artikel, karena untuk memahaminya Anda perlu berpikir dalam empat dimensi. Hal yang paling dekat dengan ini adalah peta silindris (dengan pengulangan horizontal), jadi kami akan menganggapnya sebagai dasar. Dalam peta silindris, kami menggunakan posisi horizontal gambar untuk lingkaran; yaitu, posisi horizontal gambar memberi kita dua koordinat x dan y dalam bidang noise xyz. Posisi vertikal gambar sesuai dengan z dalam bidang derau.Kami ingin gambar menjadi mulus dan vertikal, jadi jika kami menambahkan dimensi lain, kami dapat menggunakannya untuk membuat lingkaran kedua dan mengganti nilai linier bidang z. Ini mirip dengan membuat dua silinder dalam bidang empat dimensi. Saya mencoba memvisualisasikan ini pada sketsa, itu tidak akurat, tetapi saya mencoba menyampaikan prinsip umum, dan tidak menggambar silinder empat dimensi.Sketsa dua silinder dalam empat dimensiKode ini cukup sederhana: ini hanya dua lingkaran dalam ruang kebisingan empat dimensi.
fNoiseScale = .003;
drawNoise(function(i,x,y){
var fNX = x/iSize
,fNY = y/iSize
,fRdx = fNX*2*Math.PI
,fRdy = fNY*2*Math.PI
,a = fRds*Math.sin(fRdx)
,b = fRds*Math.cos(fRdx)
,c = fRds*Math.sin(fRdy)
,d = fRds*Math.cos(fRdy)
,v = Simplex.noise(
123+a*fNoiseScale
,231+b*fNoiseScale
,312+c*fNoiseScale
,273+d*fNoiseScale
)
;
return (Math.min(Math.max(2*(v -.5)+.5,0),1)*255)<<0;
}).img().div(2,2);
Dan inilah hasilnya: