თუ თქვენ ხედავთ ამ შეტყობინებას, ესე იგი საიტზე გარე რესურსების ჩატვირთვისას მოხდა შეფერხება.

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

ძირითადი მასალა

პერლინის ხმაური

შემთხვევითი რიცხვების კარგი გენერატორი აწარმოებს რიცხვებს, რომლებიც არ არიან ერთმანეთთან დაკავშირებული და არ ემორჩილებიან ცხად კანონზომიერებას. როგორც ვხედავთ, მცირე დოზით შემთხვევითობის გამოყენება ხელსაყრელია ბუნებრივი ქცევების დაპროგრამებისას. მიუხედავად ამისა, შემთხვევითობა, როგორც ცალკეული საორიენტაციო წესი, არ არის აუცილებლად ბუნებრივი.
არსებობს ალგორითმი, რომელიც უფრო ბუნებრივ შედეგებს გვაძლევს და მას ვიცნობთ „პერლინის ხმაურის" სახელით. კენ პერლინმა შექმნა ხმაურის ფუნქცია ადრეულ 1980-იან წლებში, როცა მუშაობდა ფილმზე „ტრონი"; მან ის გამოიყენა პროცედურული სტრუქტურების შესაქმნელად კომპიუტერულად დაგენერირებული ეფექტებისთვის. 1997 წელს პერლინმა ამ ნამუშევრის გამო მოიგო აკადემიური ჯილდო ტექნიკურ მიღწევაში. პერლინის ხმაურის გამოყენება შესაძლებელია ბუნებრივი მახასიათებლების მქონე მრავალნაირი ეფექტის დასაგენერირებლად, როგორიცაა ღრუბლები, ლანდშაფტები და ორნამენტებიანი სტრუქტურები (მაგალითად, მარმარილო).
პერლინის ხმაურს აქვს უფრო ორგანული ვიზუალი, რადგან ის აწარმოებს ფსევდო-შემთხვევითი რიცხვების ბუნებრივად დალაგებულ („გლუვ") მიმდევრობას. ქვემოთ მოცემული გრაფიკი აჩვენებს პერლინის ხმაურს დროთა განმავლობაში, სადაც x ღერძი წარმოადგენს დროს; ყურადღება მიაქციეთ მრუდის სიგლუვეს.
ფიგურა I.5: ხმაური
შედარებისთვის, ქვემოთ მოცემული გრაფიკი გვაჩვენებს ნამდვილად შემთხვევით რიცხვებს დროის განმავლობაში.
ფიგურა I.6: შემთხვევითი
ProcessingJS-ს აქვს პერლინის ხმაურის იმპლემენტაციის ჩაშენებული ალგორითმი: ფუნქცია noise(). noise() ფუნქცია იღებს ერთ, ორ ან სამ არგუმენტს, რადგან ხმაური გამოითვლება ერთ, ორ ან სამ განზომილებაში. დავიწყოთ ერთგანზომილებიან ხმაურზე დაკვირვებით.

ხმაურის დეტალი

ხმაურის ცნობარი გვეუბნება, რომ ხმაური გამოითვლება რამდენიმე „ოქტავაზე“. noiseDetail() ფუნქციის გამოძახება შეცვლის ოქტავების რაოდენობასაც და მათ მნიშვნელობასაც ერთმანეთთან მიმართებით. ეს, თავის მხრივ, ცვლის ხმაურის (noise) ფუნქციის ქცევას.
განვიხილოთ წრის დახატვა ჩვენს ProcessingJS-ის ფანჯარაში შემთხვევითად შერჩეულ x მდებარეობაზე:
var x = random(0, width);
ellipse(x, 180, 16, 16);
ახლა კი, შემთხვევითი x მდებარეობის ნაცვლად, განვიხილოთ პერლინის ხმაურის x ადგილმდებარეობა, რომელიც არის უფრო „გლუვი“. შეიძლება, ფიქრობთ, რომ საკმარისია random()-ის noise()-ით შეცვლა, ანუ:
var x = noise(0, width);
ellipse(x, 180, 16, 16);
აზრობრივად ეს სწორედ ისაა, რისი გაკეთებაც გვსურს — გამოთვლა x ცვლადისა, რომლის მნიშვნელობაც არის 0-სა და სიგანეს შორის პერლინის ხმაურის მიხედვით — მაგრამ ეს არ არის სწორი იმპლემენტაცია. random() ფუნქციის არგუმენტები უთითებენ მნიშვნელობების დიაპაზონს მინიმუმსა და მაქსიმუმს შორის, მაგრამ noise() ასე არ მუშაობს. noise() ჩვენგან ელოდება არგუმენტს, რომელიც ნიშნავს „დროის მომენტს" და ყოველთვის აბრუნებს მნიშვნელობას 0-სა და 1-ს შორის. შეგვიძლია, 1-განზომილებიან პერლინის ხმაურზე ვიფიქროთ ისე, როგორც მნიშვნელობების წრფივ მიმდევრობაზე დროის განმავლობაში. მაგალითისთვის, აი, სანიმუშო შემავალი და დაბრუნებული მნიშვნელობები:
დროხმაურის მნიშვნელობა
00,469
0,010,480
0,020,492
0,030,505
0,040,517
ახლა, ProcessingJS-ში ამ ხმაურის მნიშვნელობებიდან რომელიმეზე წვდომისათვის უნდა გადავცეთ დროის კონკრეტული მომენტი noise() ფუნქციას. მაგალითად:
var n = noise(0{,}03);
ზემოთ მოცემული ცხრილის მიხედვით, noise() დააბრუნებს 0,505-ს 0,03 დროზე. შეგვიძლია, დავწეროთ პროგრამა, რომელიც ინახავს დროის ცვლადს და გამუდმებით მოითხოვს ხმაურის ამ მნიშვნელობას draw()-ში.
ზემოთ მოცემული კოდი შედეგად გვაძლევს ერთსა და იმავე მნიშვნელობის ბეჭდვას. ეს იმიტომ ხდება, რომ noise()-ის შედეგს ყოველთვის ვითხოვთ დროის ერთისა და იმავე მომენტისთვის.
მიუხედავად ამისა, თუ გავზრდით ხმაურის ცვლად t-ს, მივიღებთ განსხვავებულ შედეგს.
ტემპი, რომლითაც ვზრდით t-ს, აგრეთვე ზემოქმედებს ხმაურის სიგლუვეზე. თუ დროში დიდ ნახტომებს გავაკეთებთ, მაშინ წინ ვხტებით და მნიშვნელობები უფრო მეტად შემთხვევითი იქნება.
ფიგურა 1,7
სცადეთ ზემოთ მოცემული კოდის რამდენჯერმე გაშვება, t გაზარდეთ 0,01-ით, 0,02-ით, 0,05-ით, 0,1-ით, 0,0001-ით და ნახავთ განსხვავებულ შედეგებს.

ხმაურის ასახვა

ახლა მზად ვართ, ვუპასუხოთ შეკითხვას, რა უნდა ვქნათ ხმაურის მნიშვნელობით. როგორც კი გვაქვს მნიშვნელობა 0-სა და 1-ს შორის, ჩვენზეა დამოკიდებული, რა დიაპაზონს შევუსაბამებთ მას.
შეგვიძლია, უბრალოდ, გავამრავლოთ მაქსიმალურ რიცხვზე ამ დიაპაზონში, მაგრამ ეს აგრეთვე კარგი საშუალებაა ProcessingJS-ის map() ფუნქციის წარსადგენად, რომელიც უფრო მეტად დაგვეხმარება მომავალში. map() ფუნქცია იღებს ხუთ არგუმენტს. პირველი არის მნიშვნელობა, რომლის შესაბამისი მნიშვნელობის პოვნაც გვინდა ახალ დიაპაზონში (ამ შემთხვევაში, n). შემდეგ უნდა გადავცეთ ამ მნიშვნელობის მიმდინარე დიაპაზონი (მინიმუმი და მაქსიმუმი), შემდეგ კი — ჩვენთვის სასურველი დიაპაზონი.
ფიგურა I.8
ამ შემთხვევაში, ვიცით, რომ ხმაურს აქვს დიაპაზონი 0-სა და 1-ს შორის, მაგრამ გვინდა, დავხატოთ მართკუთხედი სიგანით 0-სა და მიმდინარე სიგანეს შორის.
შეგვიძლია, ზუსტად იგივე ლოგიკა გამოვიყენოთ ჩვენს შემთხვევითად მოხეტიალეზე და მის x-სა და y-ს მივანიჭოთ მნიშვნელობები პერლინის ხმაურის მიხედვით.
აღვნიშნოთ, რომ ზემოთ მოცემულ მაგალითს ესაჭიროება ცვლადების დამატებითი წყვილი: tx და ty. ეს იმიტომ, რომ თვალყური უნდა ვადევნოთ დროის ორ ცვლადს, ერთს Walker ობიექტის x მდებარეობისთვის და ერთს - y მდებარეობისთვის.
მაგრამ ამ ამ ცვლადებს რაღაც უცნაურობა ახასიათებთ. რატომ იწყება tx 0-ზე, ty კი — 10,000-ზე? ეს რიცხვები შემთხვევითადაა შერჩეული, მაგრამ ჩვენ ინიციალიზაცია გავუკეთეთ დროის ორ ცვლადს სხვადასხვა მნიშვნელობებით. ეს იმიტომაა, რომ ხმაურის ფუნქცია არის დეტერმინისტული: ის გაძლევთ იმავე მნიშვნელობას კონკრეტული t დროისათვის ყოველ ჯერზე. თუ მოვითხოვდით ხმაურის მნიშვნელობას იმავე t დროს x-ისა და y-ისთვის, მაშინ x და y ყოველთვის ერთმანეთის ტოლი იქნებოდა, რაც ნიშნავს, რომ Walker ობიექტი მხოლოდ დიაგონალურად იმოძრავებდა. ამის ნაცვლად, უბრალოდ, ვიყენებთ ხმაურის სივრცის ორ განსხვავებულ ნაწილს, რომელიც იწყება x-ისთვის 0-ზე და y-ისთვის 10,000-ზე, რათა x-ისა და y-ის მოქმედება ერთმანეთისაგან დამოუკიდებელი ჩანდეს.
ფიგურა I.9
სინამდვილეში, აქ დროის რეალურ კონცეფციას არ ვიყენებთ. ეს მხოლოდ კარგი მეტაფორაა იმისთვის, რომ გავიაზროთ, როგორ მუშაობს ხმაურის ფუნქცია, მაგრამ, რეალურად, გვაქვს სივრცე, დრო კი — არა. ზემოთ მოცემული გრაფიკი გამოსახავს ხმაურის მნიშვნელობების წრფივ მიმდევრობას ერთგანზომილებიან სივრცეში და შეგვიძლია, მოვითხოვოთ მნიშვნელობა კონკრეტულ x-მდებარეობაზე, როდესაც გვსურს. მაგალითებში t (დროის) ცვლადის სახელის ნაცვლად ხშირად იხილავთ ცვლადს სახელად xoff, რომელიც მიუთითებს x-წანაცვლებაზე ხმაურის გრაფიკის გაყოლებაზე (როგორც აღნიშნულია დიაგრამაზე).
შემდეგ ამოცანაში თქვენ ეცდებით, გამოიყენოთ ხმაური Walker-თან (მოხეტიალესთან) ოდნავ განსხვავებული გზით. იმხიარულეთ!
ეს „ბუნებრივი სიმულაციების" კურსი ეფუძნება დანიელ შიფმენის წიგნს "კოდის ბუნებას", ის გამოყენებულია ლიცენზიით Creative Commons Attribution-NonCommercial 3,0 Unported License.

გსურთ, შეუერთდეთ დისკუსიას?

პოსტები ჯერ არ არის.
გესმით ინგლისური? დააწკაპუნეთ აქ და გაეცანით განხილვას ხანის აკადემიის ინგლისურენოვან გვერდზე.