Sampling Spherical Light
გზების მიდევნების მეთოდში განათების შერჩევა გულისხმობს განათებისკენ მიმართული ვექტორების გენერირებას. განათების შერჩევა განსაკუთრებით ეფექტურია როდესაც ზედაპირის მოცემულ წერტილში განათების მიერ შედგენილი კუთხე არის მცირე და BRDF-ის შერჩევით განათების მოხვედრის ალბათობა მცირეა.განვიხილოთ სფერული განათების შერჩევის პროცესი. სფერული განათების შერჩევისას არსებული შემთხვევები შეგვიძლია გავყოთ 2 ნაწილად: როდესაც წერტილი ექცევა სფეროს შიგნით და როდესაც არის გარეთ. პირველ შემთხვევაში ნებისმიერი შერჩეული ვექტორი აუცილებლად განათებისკენაა მიმართული, ასე რომ საკმარისია მოვახდინოთ მიმართულების შემთხვევითი თანაბარი შერჩევა. ახლა განვიხილოთ შემთხვევა, როცა წერტილი განათების გარეთაა(იხილეთ ზემოთ მოცემული სურათი). სიმარტივისთვის შემთხვევა განვიხილოთ 2 განზომილებაში. წერტილი რომლისთვისაც ვახდენთ მიმართულებების შერჩევას აღვნიშნოთ P-თი, სფეროს ცენტრი O-თი ხოლო რადიუსი r-ით. პირველ რიგში უნდა დავითვალოთ სფეროს ცენტრამდე მანძილი d=|O-P|. შემდეგ უნდა გამოვთვალოთ სფეროს მიერ P წერტილის მიმართ შედგენილი კუთხე. კონუსის წვეროსთან არსებული კუთხე რომელსაც კონუსის მსახველი ადგენს ღერძთან აღვნიშნოთ α-თი. ნახაზიდან კარგად ჩანს რომ sin(α)=r/d; α=asin(r/d). ახლა, როცა უკვე ვიცით განათებისკენ მიმართული კონუსის წვეროსთან არსებული კუთხე α, შეგვიძლია მოვახდინოთ მიმართულებების შერჩევა კონუსში ლოკალურად. ეს ამოცანა განვიხილოთ ცალკე.
პირველი რაც თავში შეიძლება მოგივიდეთ ამ დრო არის ის, რომ სასურველი გაშლილობის მქონე კონუსში მიმართულებების გენერირება ადვილად შეიძლება გაკეთდეს სფერული კოორდინათთა სისტემის დახმარებით, თუმცა აქ არ უნდა დაგვავიწყდეს ერთი მნიშვნელოვანი მომენტი. სფერული კოორდინათთა სისტემაში Φ და Θ-ს თანაბარი შერჩევის დროს პოლუსებთან უფრო მეტი სიმკვრივით ხდება შერჩევა ამიტომ ეს პრობლემა უნდა მოვაგვაროთ. ცხადია ამისთვის Θ-ს შერჩევა თანაბრად არ უნდა მოხდეს.
//function calculates normalized uniform random vector directed within cone Vector3 uniformRandomDirectionWithinCone( double cosMaxTheta ) { Vector3 dir; const double Phi = TWO_PI*random01(); dir.z = cosMaxTheta+(1.0-cosMaxTheta)*random01(); double sinAlpha = sqrt(1.0-dir.z*dir.z); dir.x = cos(Phi)*sinAlpha; dir.y = sin(Phi)*sinAlpha; return dir; }ფუნქცია თავისმხრივ იოლი ნამდვილად არაა, რადგან შეიცავს თითო სინუს/კოსინუსს(რომლის გამოთვლაც ხდება ტეილორის მწკრივებით და საკმაოდ მძიმეა), ფესვის ამოღებას და 2 შემთხვევითი რიცხვის გენერაციას. შესაბამისად თუ თქვენთვის მიუკერძოებლობა ნაკლებად მნიშვნელოვანია შეგიძლიათ ხსვა ხერხს მიმართოთ.
Comments
Post a Comment