Ano ang ray tracing at kailangan ba natin ito sa mga laro? Rand() at data ng henerasyon ng mundo. Specialized accelerator para sa ray tracing

Kamakailan, sa Internet, nakita ko ang ray tracer sa business card ni Paul Huckbert. Para sa mga hindi nakakaalam, isa itong napakatanyag na problema, na orihinal na iminungkahi ni Paul Huckbert noong ika-4 ng Mayo, 1984 sa comp.graphics. Ang kakanyahan nito ay sumulat ng isang pagpapakita ng paraan ng paghahagis ng mga sinag, na... magkasya business card(magbasa nang higit pa tungkol dito sa seksyong Ray Tracing ng Graphics Gems IV)!

Ang bersyon ni Andrew Kensler ay isa sa mga pinaka-nakamamanghang at magagandang pagpapatupad ng problemang ito na nakita ko. Out of curiosity, I decided to look into it. Sa artikulong ito ay isusulat ko ang lahat ng naiintindihan ko sa aking sarili.

Reverse side ng business card

Ito ang hitsura ng code mismo:

#isama // card > aek.ppm #include #isama typedef int i;typedef float f;struct v( f x,y,z;v operator+(v r)(return v(x+r.x ,y+r.y,z+r.z);)v operator*(f r)(return v( x*r,y*r,z*r);)f operator%(v r)(return x*r.x+y*r.y+z*r.z;)v()()v operator^(v r) (ibalik v(y*r.z-z*r.y,z*r.x-x*r.z,x*r. y-y*r.x);)v(f a,f b,f c)(x=a;y=b;z=c ;)v operator!())(ibalik*ito*(1/sqrt(*ito%* ito));));i G=(247570,280596,280600, 249748,18578,18577,231184,16,16 ) ;f R())( return(f)rand()/RAND_MAX;)i T(v o,v d,f &t,v&n)(t=1e9;i m=0;f p=-o.z/d.z;if(. 01 0)(f s=-b-sqrt(q);if(s .01)t=s,n=!(p+d*t),m=2;))return m;)v S(v o,v d)(f t ;v n;i m=T(o,d,t, n);if(!m)return v(.7, .6,1)*pow(1-d.z,4);v h=o+d*t,l=!(v(9+R(),9 +R(),16)+h*-1),r=d+n*(n%d*-2);f b=l% n;if(b<0||T(h,l,t,n))b=0;f p=pow(l%r*(b >0),99);if(m&1)(h=h*.2;return((i)(ceil(h.x)+ceil(h.y))&1?v(3,1,1):v(3,3 ,3))*(b *.2+.1);)ibalik v(p,p,p)+S(h,r)*.5;)i main())(printf("P6 512 512 255 " );v g=!v (-6,-16,0),a=!(v(0,0,1)^g)*.002,b=!(g^a)*.002,c= ( a+b)*-256+g;for(i y=512;y--;) for(i x=512;x--;)(v p(13,13,13);for(i r =64;r - -;)(v t=a*(R()-.5)*99+b*(R()-.5)* 99;p=S(v(17,16,8)+t,!( t *-1+(a*(R()+x)+b *(y+R())+c)*16))*3.5+p;)printf("%c%c%c" ,( i )p.x,(i)p.y,(i)p.z);))

Ang code sa itaas ay mukhang... nakakatakot, ngunit ito ay nag-compile at tumatakbo nang walang problema! Maaari mong i-save ito sa iyong desktop bilang card.cpp, magbukas ng console at ilagay ang:

C++ -O3 -o card card.cpp ./card > card.ppm

Pagkatapos ng 27 segundo ang sumusunod na larawan ay lilitaw sa screen:

Mga Tampok ng Ray Tracer Business Card

Ang mga posibilidad ay kahanga-hanga lamang!

  • isang mundo na binubuo ng mahigpit na organisadong mga globo;
  • may texture na sahig;
  • kalangitan na may gradient;
  • malambot na mga anino;
  • OMG, depth of field! Nagbibiro ka ba?!

At lahat ng ito sa isang bahagi ng business card! Tingnan natin kung paano ito gumagana.

klase ng vector

Tingnan natin ang unang bahagi ng code:

#isama // card > aek.ppm #include #isama typedef int i;typedef float f;struct v( f x,y,z;v operator+(v r)(return v(x+r.x ,y+r.y,z+r.z);)v operator*(f r)(return v( x*r,y*r,z*r);)f operator%(v r)(return x*r.x+y*r.y+z*r.z;)v()()v operator^(v r) (ibalik v(y*r.z-z*r.y,z*r.x-x*r.z,x*r. y-y*r.x);)v(f a,f b,f c)(x=a;y=b;z=c ;)v operator!())(return*this*(1/sqrt(*this%* this));));

Ang pangunahing lansihin dito ay ang pagbabawas mga keyword int at float ang mga uri sa i at f gamit ang typedef . Ang isa pang trick na maaaring magamit upang bawasan ang dami ng code ay ang v class, na ginagamit hindi lamang bilang isang vector, kundi pati na rin para sa pagproseso ng mga pixel.

#isama // card > aek.ppm #include #isama typedef int i; // I-save ang espasyo sa pamamagitan ng pagbabawas ng int sa i typedef float f; // Makatipid ng higit pang espasyo gamit ang f sa halip na float // Vector class na may constructor at operator struct v( f x,y,z; // Tatlong vector coordinates v operator+(v r)(return v(x+r.x,y+r.y, z +r.z);) // Kabuuan ng mga vectors v operator*(f r)(return v(x*r,y*r,z*r);) // Scaling of vectors f operator%(v r)(return x* r.x +y*r.y+z*r.z;) // Dot product ng mga vectors v()() // Empty constructor v operator^(v r)(return v(y*r.z-z*r.y,z*r.x- x* r.z,x*r.y-y*r.x);) // Cross product ng mga vectors v(f a,f b,f c)(x=a;y=b;z=c;) // Constructor v operator!() )(return * this*(1 /sqrt(*this%*this));) // Vector normalization );

Rand() at data ng henerasyon ng mundo

i G=(247570,280596,280600, 249748,18578,18577,231184,16,16);f R())( return(f)rand()/RAND_MAX;)

Ang sumusunod na code ay nakakatipid din ng maraming espasyo sa pamamagitan ng pagdedeklara ng isang function R na nagbabalik ng random na halaga ng float sa pagitan ng 0 at 1. Ito ay kapaki-pakinabang para sa stochastic sampling, na ginagamit para sa mga blur effect at malambot na anino.

Ang array G ay naglalaman ng posisyon ng mga sphere sa mundo na naka-encode sa mga integer. Ang set ng lahat ng numero ay medyo vector ng 9 na row at 19 na column.

Narito ang code sa itaas, ngunit naka-format at may mga komento:

// Isang hanay ng mga posisyon ng globo na naglalarawan sa mundo // Ang lahat ng mga numerong ito ay mahalagang isang bit vector i G=(247570,280596,280600,249748,18578,18577,231184,16,16); // Random number generator na nagbabalik ng floating point number sa hanay na 0-1 f R())(return(f)rand()/RAND_MAX;)

Pangunahing paraan

i main())(printf("P6 512 512 255 ");v g=!v (-6,-16,0),a=!(v(0,0,1)^g)*.002,b = !(g^a)*.002,c=(a+b)*-256+g;for(i y=512;y--;) for(i x=512;x--;)(v p(13 , 13,13);for(i r =64;r--;)(v t=a*(R()-.5)*99+b*(R()-.5)* 99;p=S( v (17,16,8)+t,!(t*-1+(a*(R()+x)+b *(y+R())+c)*16))*3.5+p; ) printf("%c%c%c" ,(i)p.x,(i)p.y,(i)p.z);))

Pangunahing paraan ay gumagamit ng simple, kilalang text-based na PPM na format ng imahe. Ang larawan ay binubuo ng isang header ng form na P6 [Width] [Height] [Maximum Value] na sinusundan ng RGB value ng bawat pixel.

Para sa bawat pixel sa larawan, ang mga sample ng programa (S) ang kulay ng 64 ray, iniipon ang resulta at ilalabas ito sa stdout.

Bahagyang binabago din ng code na ito ang bawat ray origin coordinate at ang direksyon nito. Ginagawa ito upang lumikha ng epekto ng depth of field.

Narito ang code sa itaas, ngunit naka-format at may mga komento:

// Pangunahing pag-andar. Nagpapakita ng larawan. // Simple lang ang paggamit ng program: ./card > erk.ppm i main())( printf("P6 512 512 255 "); // PPM header // Ang "!" operator ay nag-normalize ng vector v g=!v( -6,- 16,0), // Direksyon ng camera a=!(v(0,0,1)^g)*.002, // Vector na responsable sa taas ng camera... b=!(g^a )*.002 , // Tamang vector na nakuha gamit ang cross product c=(a+b)*-256+g; // WTF? Dito https:// news.ycombinator.com/item?id=6425965 ito ay nakasulat tungkol dito nang mas detalyado. for(i y=512;y--;) // Para sa bawat column para sa(i x=512;x--;)( // Para sa bawat pixel sa row // Gumamit ng vector class para mag-imbak ang kulay sa RGB v p(13, 13,13); // Ang karaniwang kulay ng pixel ay halos itim // Magtapon ng 64 ray mula sa bawat pixel para sa(i r=64;r--;)( // Bahagyang palitan ang kaliwa/kanan at pataas /pababa sa mga coordinate ng simula ng ray (para sa lalim ng field effect) v t=a*(R()-.5)*99+b*(R()-.5)*99; // Italaga ang focal point ng camera sa v(17,16,8) at itapon ang beam / / Ipunin ang kulay na ibinalik sa variable t p=S(v(17,16,8)+t, // Simula ng ray!(t *-1+(a*(R()+x)+b*(y+R ())+c)*16) // Direksyon ng beam na may bahagyang pagbaluktot // para sa epekto ng stochastic sampling)*3.5+p ; // +p para sa akumulasyon ng kulay ) printf("%c%c%c",(i)p.x,(i)p.y,(i)p.z); ) )

Sampler

v S(v o,v d)(f t ;v n;i m=T(o,d,t,n);if(!m)return v(.7, .6,1)*pow(1-d.z,4) ;v h=o+d*t,l=!(v(9+R(),9+R(),16)+h*-1),r=d+n*(n%d*-2) ;f b=l% n;if(b<0||T(h,l,t,n))b=0;f p=pow(l%r*(b >0),99);if(m&1)(h=h*.2;return((i)(ceil(h.x)+ceil(h.y))&1?v(3,1,1):v(3,3 ,3))*(b *.2+.1);)ibalik v(p,p,p)+S(h,r)*.5;)

Ang Sampler S ay isang function na nagbabalik ng kulay ng isang pixel batay sa ibinigay na mga coordinate ng ray origin point o at ang direksyon nito d. Kung ito ay tumama sa globo, pagkatapos ay tinatawag nito ang sarili nito nang pabalik-balik, at kung hindi man (kung ang sinag ay walang mga hadlang sa landas nito) depende sa direksyon, ibinabalik nito ang alinman sa kulay ng langit o ang kulay ng sahig (batay sa checkered texture nito. ).

Tandaan ang tawag sa R ​​function kapag kinakalkula ang direksyon ng liwanag. Lumilikha ito ng epekto ng "malambot na mga anino".

Narito ang code sa itaas, ngunit naka-format at may mga komento:

// (S)sample ang mundo at ibalik ang kulay ng pixel sa pamamagitan ng // ray na nagsisimula sa punto o (Origin) at pagkakaroon ng direksyon d (Direksiyon) v S(v o,v d)( f t; v n; // Suriin kung ang ray bumangga sa isang bagay na i m=T(o,d,t,n); if(!m) // m==0 // Hindi nakita ang globo, at tumataas ang sinag: buuin ang sky color return v(.7 ,. 6,1)*pow(1-d.z,4); // Marahil ay dumampi ang sinag sa sphere v h=o+d*t, // h ang intersection coordinate l=!(v(9+R() ,9+R (),16)+h*-1), // "l" = liwanag na direksyon (na may bahagyang pagbaluktot para sa soft shadow effect) r=d+n*(n%d*-2); // r = half-vector / / Kalkulahin ang Lambert coefficient f b=l%n; // Kalkulahin ang lighting factor (Lambert coefficient > 0 o tayo ay nasa anino)? if(b<0||T(h,l,t,n)) b=0; // Рассчитываем цвет p (с учетом диффузии и отражения света) f p=pow(l%r*(b>0),99); if(m&1)( // m == 1 h=h*.2; // Hindi nahawakan ang globo, at bumaba ang beam sa sahig: buuin ang pagbabalik ng kulay ng sahig((i)(ceil(h.x)+ ceil(h.y ))&1?v(3,1,1):v(3,3,3))*(b*.2+.1); ) // m == 2 Natamaan ang globo: bumuo ng ang sinag na tumatalbog sa surface sphere return v(p,p,p)+S(h,r)*.5; // Humina ng 50% ang kulay habang tumatalbog ito sa ibabaw (*.5) )

Tracer

i T(v o,v d,f &t,v&n)(t=1e9;i m=0;f p=-o.z/d.z;if(.01 0)(f s=-b-sqrt(q);if(s .01)t=s,n=!(p+d*t),m=2;))ibalik m;)

Ang T (Tracer) function ay responsable para sa paghagis ng isang sinag mula sa isang naibigay na punto (o) sa isang partikular na direksyon (d). Nagbabalik ito ng integer na siyang code para sa resulta ng paghagis ng ray. 0 - ang sinag ay napunta sa langit, 1 - ang sinag ay napunta sa sahig, 2 - ang sinag ay tumama sa globo. Kung natamaan ang sphere, ina-update ng function ang mga variable t (ang parameter na ginamit upang kalkulahin ang distansya ng pagtawid) at n (ang kalahating vector kapag nagba-bounce sa sphere).

Narito ang code sa itaas, ngunit naka-format at may mga komento:

// Line Intersection Test // Return 2 kung natamaan ang sphere (pati na rin ang intersection distance t at half-vector n). // Ibalik ang 0 kung ang sinag ay hindi tumama sa anuman at umakyat sa langit // Ibalik ang 1 kung ang sinag ay hindi tumama sa anuman at bumaba sa sahig i T(v o,v d,f& t,v& n)( t=1e9; i m=0; f p=-o.z/d.z; if(.01 0)( // Oo. Kalkulahin ang distansya mula sa camera hanggang sa sphere f s=-b-sqrt(q); if(s) .01) // Ito ang pinakamababang distansya, i-save ito. At din // kalkulahin ang vector ng nagba-bounce na ray at isulat ito sa "n" t=s, n=!(p+d*t), m=2; ) ) ibalik m; )

Numero ng Leet

Sinubukan ng maraming programmer na bawasan pa ang code. Ang may-akda mismo ay nanirahan sa bersyon na ibinigay sa artikulong ito. Alam mo ba kung bakit?

Fabien$ wc card.cpp 35 95 1337 card.cpp - maraming matematika, ngunit ang lahat ay ipinaliwanag nang detalyado at malinaw.

Ang algorithm ay ganito ang hitsura: isang ray ay ibinubuga mula sa isang virtual na mata sa pamamagitan ng bawat pixel ng imahe at ang punto ng intersection nito sa ibabaw ng eksena ay matatagpuan (upang gawing simple ang pagtatanghal, hindi namin isinasaalang-alang ang mga volumetric na epekto tulad ng fog). Ang mga sinag na inilabas mula sa mata ay tinatawag na pangunahin. Sabihin nating ang pangunahing sinag ay nag-intersect sa isang partikular na bagay 1 sa puntong H1 (Larawan 1).

Figure 1. Ray tracing algorithm.

Susunod, kailangan mong matukoy para sa bawat pinagmumulan ng liwanag kung ang puntong ito ay makikita mula dito. Ipagpalagay natin sa ngayon na ang lahat ng pinagmumulan ng liwanag ay mga pinagmumulan ng punto. Pagkatapos, para sa bawat puntong pinagmumulan ng liwanag, isang shadow ray ang ibinubuga mula sa punto H1 hanggang dito. Binibigyang-daan ka nitong sabihin kung ang isang partikular na punto ay naiilaw ng isang partikular na pinagmulan. Kung ang shadow ray ay bumalandra sa iba pang mga bagay na matatagpuan na mas malapit kaysa sa pinagmulan ng kulay, nangangahulugan ito na ang puntong H1 ay nasa anino ng pinagmulang ito at hindi na kailangang iluminado. Kung hindi, kinakalkula namin ang pag-iilaw ayon sa ilang lokal na modelo (Fong, Cook-Torrance, atbp.). Ang pag-iilaw mula sa lahat ng nakikita (mula sa puntong H1) ay idinagdag nang magkasama. Dagdag pa, kung ang materyal ng bagay 1 ay may mapanimdim na mga katangian, ang isang sinasalamin na sinag ay ibinubuga mula sa punto H1 at ang buong pamamaraan ng pagsubaybay ay paulit-ulit na paulit-ulit para dito. Ang mga katulad na aksyon ay dapat gawin kung ang materyal ay may mga katangian ng repraktibo.

// Algorithmbakassinag

//

lumutang3 RayTrace (const Ray & ray )

{

float3 na kulay(0,0,0);

Hit hit = RaySceneIntersection(ray);

kung (!hit .exist)

ibalik ang kulay;

float3 hit_point = ray .pos + ray .dir *hit .t ;

para sa (int i = 0;i

kung (Nakikita (hit_point , mga ilaw ))

kulay += Shade(hit, lights);

kung (hit .material .reflection > 0)

{

Ray reflRay = reflect(ray, hit);

color += hit .material .reflection*RayTrace (reflRay );

}

kung (hit .material .refraction > 0)

{

Ray refrRay = refract(ray, hit);

color += hit .material .refraction *RayTrace ( refrRay );

}

bumalikkulay;

}

Listahan 1. Paatras na ray tracing algorithm.

Ipaliwanag natin ang fragment ng programa (Listing 1). Ang sinag ay kinakatawan ng dalawang vectors. Ang unang vector - pos - ay ang punto ng paglabas ng sinag. Ang pangalawa ay dir - ang normalized na direksyon ng ray. Ang kulay ay isang vector ng tatlong numero - asul, pula, berde. Sa simula pa lang ng function na RayTrace, binibilang namin ang intersection ng ray sa eksena (kinakatawan lamang bilang isang listahan ng mga bagay sa ngayon) at nag-iimbak ng ilang impormasyon tungkol sa intersection sa hit variable at ang distansya sa intersection sa hit .t variable. Susunod, kung ang ray ay nakaligtaan at walang intersection, kailangan mong ibalik ang kulay ng background (sa aming kaso, itim). Kung may nakitang intersection, kinakalkula namin ang hit_point intersection point gamit ang ray equation (katumbas ng line equation na may kundisyon t>0). Kapag nakalkula na namin ang intersection point sa mga coordinate ng mundo, nagsisimula kaming kalkulahin ang mga anino. Hayaang nasa hanay ng mga ilaw ang mga pinagmulan. Pagkatapos ay dumaan tayo sa buong array sa isang loop at para sa bawat ilaw na pinagmumulan ay tinitingnan natin (na may parehong ray tracing) kung ang ilaw na pinagmulan ay nakikita mula sa isang naibigay na hit_point. Kung nakikita, nagdaragdag kami ng pag-iilaw mula sa pinagmulang ito, na kinakalkula gamit ang ilang lokal na modelo (halimbawa, ang modelo ng Phong). Pagkatapos, kung ang materyal ng bagay na tinamaan ng sinag ay may mapanimdim o repraktibo na mga katangian, sinusubaybayan namin ang mga sinag nang pabalik-balik, i-multiply ang nagreresultang kulay sa kaukulang koepisyent ng pagmuni-muni o repraksyon at idagdag ito sa resultang kulay. Reflection at refraction coefficients ay maaaring monochrome o kulay. Ang lahat ay nakasalalay sa kung anong modelo ng matematika ang ginagamit upang kumatawan sa mga materyales.

Minsan ang mga sinag ng anino ay may kulay. Ang ganitong mga sinag ay ginagamit kung may posibilidad na ang isang bagay ay matakpan ng isa pang transparent na bagay. Sa kasong ito, ang kapal ng landas ng sinag ng anino sa loob ng transparent na bagay ay kinakalkula at ang anino ay maaaring makakuha ng anumang lilim (kung ang bagay ay may isa). Siyempre, ang mga anino na kinakalkula sa ganitong paraan ay tama lamang kung ang transparent na bagay na naghahagis ng anino ay may refractive index na napakalapit sa pagkakaisa (ipagpalagay namin na ang refractive index ng hangin ay 1).

Kung hindi ito ang kaso, kung gayon ang isang kumplikadong pattern na tinatawag na caustic ay bubuo sa ilalim ng transparent na bagay. Ang mga caustics ay kinakalkula nang hiwalay gamit ang paraan ng photon map. Ang isang tipikal na halimbawa ng caustic ay isang sinag ng araw mula sa isang baso ng tubig kapag ang araw ay sumisikat dito.

Dapat pansinin na ang back ray tracing gaya ng inilarawan dito ay hindi isang photorealistic rendering technique. Bukod dito, kumpara sa paraan ng rasterization, pinapayagan ka nitong kalkulahin nang tama lamang ang mga malinaw na pagmuni-muni, repraksyon, at alisin ang pag-alyas kapag mayroong isang malaking bilang ng mga ray bawat pixel (na mabagal). Upang makuha ang buong hanay ng mga nakikitang epekto, kinakailangan na gumamit ng mas kumplikadong mga algorithm, na, gayunpaman, ay partikular na nakabatay sa ray tracing.

Figure 2. Ray tracing image.

Kahit na may resolution ng larawan na 1024x768, ang bilang ng mga pangunahing ray ay 786432 - iyon ay, papalapit sa isang milyon. Ang bawat isa sa mga sinag na ito ay maaaring malalim sa recursion, na nagpapataas ng bilang ng mga sinag na sinag nang maraming beses. Ang dami ng mga kalkulasyon na kailangang gawin ay napakalaki at ang ray tracing ay kadalasang medyo mabagal. Bukod dito, ang malaking bahagi ng oras ng processor ay ginugugol sa paghahanap ng mga intersection. Samakatuwid, ang isyu ng pagganap ay nauuna dito. May mga klase ng mga algorithm na maaaring mapabilis ang paghahanap para sa mga intersection sa pamamagitan ng mga order ng magnitude. Ang ratio ng kalidad/bilis ay ang pangunahing criterion kapag pumipili ng ilang algorithm, ngunit ang epektibong mga algorithm sa anumang kaso ay subukang gamitin ang pagkakaugnay ng mga sinag sa isang anyo o iba pa. Para sa higit pang impormasyon tungkol sa kanila, tingnan ang seksyong "Fast Ray Tracing."

Mga Paraan ng Pagsubaybay sa Ray (Ray Pagsubaybay) Ngayon sila ay itinuturing na pinakamalakas at maraming nalalaman na pamamaraan para sa paglikha ng makatotohanang mga imahe. Maraming mga halimbawa ng pagpapatupad ng mga algorithm sa pagsubaybay para sa mataas na kalidad na pagpapakita ng mga pinakakumplikadong three-dimensional na eksena. Mapapansin na ang pagiging pandaigdigan ng mga pamamaraan ng pagsubaybay ay higit sa lahat dahil sa katotohanan na ang mga ito ay batay sa simple at malinaw na mga konsepto na sumasalamin sa ating karanasan sa pagkilala sa mundo sa paligid natin.

kanin. 8.12. Mga modelo ng pagninilay: a - perpektong salamin, b - hindi perpektong salamin, c - nagkakalat, d - kabuuan ng nagkakalat at specular, d - inverse, f - kabuuan ng nagkakalat, specular at inverse

Paano natin nakikita ang nakapaligid na katotohanan? Una, kailangan nating magpasya kung ano ang maaari nating makita. Ito ay pinag-aaralan sa mga espesyal na disiplina, at sa ilang lawak, ito ay isang pilosopikal na tanong. Ngunit dito ipagpalagay natin na ang mga nakapalibot na bagay ay may mga sumusunod na katangian na nauugnay sa liwanag:

    magningning;

    sumasalamin at sumipsip;

    dumaan sa kanilang sarili.

kanin. 8.13. Radiation – a – pare-pareho sa lahat ng direksyon, b – direksyon

Ang bawat isa sa mga katangiang ito ay maaaring ilarawan ng isang tiyak na hanay ng mga katangian. Halimbawa, ang radiation ay maaaring mailalarawan sa pamamagitan ng intensity, direksyon, spectrum. Ang radiation ay maaaring magmula sa isang medyo point source (isang malayong bituin) o mula sa isang pinagmumulan ng nagkakalat na liwanag (sabihin, mula sa tinunaw na lava na nagmumula sa bunganga ng bulkan). Maaaring magpalaganap ang radyasyon sa isang medyo makitid na sinag (nakatutok na laser beam) o sa isang kono (spotlight), o pantay-pantay sa lahat ng direksyon (Sun), o iba pa. Ang reflection property (absorption) ay maaaring ilarawan ng mga katangian ng diffuse scattering at specular reflection. Ang transparency ay maaaring ilarawan sa pamamagitan ng intensity attenuation at repraksyon.

Ang pamamahagi ng liwanag na enerhiya kasama ang mga posibleng direksyon ng mga light ray ay maaaring ipakita gamit ang mga diagram ng vector, kung saan ang haba ng mga vector ay tumutugma sa intensity (Larawan 8.12 - 8.14).

Sa mga nakaraang talata, naging pamilyar na tayo sa mga uri ng pagmuni-muni na madalas na binabanggit - specular at diffuse. Hindi gaanong madalas na binanggit sa panitikan ang reverse mirror o anti-salamin mula sapagkatalo, kung saan ang pinakamataas na intensity ng pagmuni-muni ay tumutugma sa direksyon patungo sa pinagmulan. Ang ilang mga uri ng mga halaman sa ibabaw ng Earth, na naobserbahan mula sa taas ng mga palayan, ay may reverse mirror reflection.

Dalawang matinding, idealized na mga kaso ng repraksyon ay ipinapakita sa Fig. 8.13.

Ang ilang mga tunay na bagay ay nagre-refract ng mga sinag sa mas kumplikadong mga paraan, tulad ng salamin na natatakpan ng yelo.

Ang isa at ang parehong bagay ng katotohanan ay maaaring perceived bilang isang pinagmumulan ng liwanag, o maaari itong, kapag tiningnan nang iba, ay ituring na isang bagay na sumasalamin lamang at nagpapadala ng liwanag. Halimbawa, ang isang simboryo ng maulap na kalangitan sa ilang three-dimensional na eksena ay maaaring imodelo bilang isang pinalawak (namahagi) na pinagmumulan ng liwanag, habang sa ibang mga modelo ang parehong kalangitan ay gumaganap bilang isang translucent na daluyan na iluminado mula sa direksyon ng Araw.

kanin. 8.14. Repraksyon a – perpekto, b – nagkakalat

Sa pangkalahatan, ang bawat bagay ay inilalarawan ng ilang kumbinasyon ng tatlong katangian sa itaas. Bilang isang ehersisyo, subukang magbigay ng isang halimbawa ng isang bagay na sabay-sabay na may tatlo sa mga katangiang ito - naglalabas ito ng liwanag at, sa parehong oras, sumasalamin at nagpapadala ng liwanag mula sa iba pang mga mapagkukunan. Ang iyong imahinasyon ay malamang na makabuo ng iba pang mga halimbawa kaysa, sabihin nating, red-hot glass.

Ngayon tingnan natin kung paano nabuo ang isang imahe ng isang eksena na naglalaman ng ilang spatial na bagay. Ipagpalagay natin na ang mga sinag ng liwanag ay lumalabas mula sa mga punto sa ibabaw (volume) ng mga ibinubuga na bagay. Matatawag nating pangunahin ang gayong mga sinag - pinaiilaw nila ang lahat ng iba pa.

Ang isang mahalagang punto ay ang pagpapalagay na ang isang light beam sa libreng espasyo ay nagpapalaganap sa isang tuwid na linya (bagaman sa mga espesyal na seksyon ng pisika ang mga dahilan para sa posibleng curvature ay pinag-aralan din). Ngunit sa geometric na optika Ipinapalagay na ang isang sinag ng liwanag ay kumakalat sa isang tuwid na linya hanggang sa makatagpo ito ng isang mapanimdim na ibabaw o ang hangganan ng isang repraktibo na daluyan. Kaya tayo ay maniniwala.

Ang hindi mabilang na mga pangunahing sinag ay nagmumula sa mga pinagmumulan ng radiation sa iba't ibang direksyon (kahit ang isang laser beam ay hindi maaaring ganap na nakatuon - gayon pa man, ang ilaw ay kumakalat hindi sa isang perpektong manipis na linya, ngunit sa isang kono, isang sinag ng mga sinag). Ang ilang mga sinag ay napupunta sa libreng espasyo, at ang ilan (mayroon ding hindi mabilang sa kanila) ay tumama sa iba pang mga bagay. Kung ang isang sinag ay tumama sa isang transparent na bagay, ito ay nagre-refract at naglalakbay pa, habang ang ilan sa liwanag na enerhiya ay nasisipsip. Katulad nito, kung ang isang specularly reflective surface ay nakatagpo sa landas ng beam, pagkatapos ay nagbabago din ito ng direksyon, at bahagi ng liwanag na enerhiya ay hinihigop. Kung ang bagay ay salamin at sa parehong oras transparent (halimbawa, ordinaryong salamin), pagkatapos ay magkakaroon na ng dalawang beam - sa kasong ito sinasabi nila na ang beam ay nahati.

Masasabi natin na bilang resulta ng epekto ng mga pangunahing sinag sa mga bagay, ang pangalawang sinag ay lumitaw. Hindi mabilang na pangalawang sinag ang napupunta sa libreng espasyo, ngunit ang ilan sa mga ito ay tumama sa iba pang mga bagay. Kaya, kapag nasasalamin at na-refracte nang maraming beses, ang mga indibidwal na sinag ng liwanag ay dumarating sa punto ng pagmamasid - ang mata ng tao o ang optical system ng isang kamera. Malinaw na ang ilan sa mga pangunahing sinag nang direkta mula sa mga pinagmumulan ng radiation ay maaari ding umabot sa punto ng pagmamasid. Kaya, ang imahe ng eksena ay nabuo sa pamamagitan ng isang tiyak na bilang ng mga light ray.

Ang kulay ng mga indibidwal na punto ng imahe ay tinutukoy ng spectrum at intensity ng mga pangunahing sinag ng mga pinagmumulan ng radiation, pati na rin ang pagsipsip ng liwanag na enerhiya sa mga bagay na nakatagpo sa landas ng kaukulang mga sinag.

kanin. 8.15. Paatras na ray tracing scheme

Ang direktang pagpapatupad ng modelong ito ng ray imaging ay tila mahirap. Maaari mong subukang bumuo ng isang algorithm para sa pagbuo ng isang imahe gamit ang tinukoy na paraan. Sa ganoong algorithm, kinakailangan na magbigay para sa isang enumeration ng lahat ng mga pangunahing ray at matukoy kung alin sa mga ito ang tumama sa mga bagay at sa camera. Pagkatapos ay umulit sa lahat ng pangalawang sinag, at isaalang-alang din ang mga tumama sa mga bagay at camera. At iba pa. Ang pamamaraang ito ay maaaring tawagin tuwid pagsubaybay sa sinag. Ang praktikal na halaga ng naturang pamamaraan ay magiging kaduda-dudang. Sa katunayan, kung paano isaalang-alang ang walang katapusang bilang ng mga sinag sa lahat ng direksyon? Ito ay malinaw na ang isang kumpletong paghahanap ng isang walang katapusang bilang ng mga sinag ay imposible sa prinsipyo. Kahit na bawasan natin ito sa isang tiyak na bilang ng mga operasyon (halimbawa, hatiin ang buong globo ng mga direksyon sa mga angular na sektor at gumana hindi sa mga walang katapusang manipis na linya, ngunit sa mga sektor), ang pangunahing disbentaha ng pamamaraan ay nananatili pa rin - maraming mga hindi kinakailangang operasyon. nauugnay sa pagkalkula ng mga sinag, na pagkatapos ay hindi ginagamit. Kaya, sa anumang kaso, lumilitaw ito sa kasalukuyang panahon.

Pamamaraan backtrace rays ay nagbibigay-daan sa iyo upang makabuluhang bawasan ang overkill ng light rays. Ang pamamaraan ay binuo noong 80s, ang mga pangunahing gawa ay isinasaalang-alang Witte-da At Kay. Ayon sa pamamaraang ito, ang mga sinag ay sinusubaybayan hindi mula sa mga pinagmumulan ng liwanag, ngunit sa kabaligtaran na direksyon - mula sa punto ng pagmamasid. Sa ganitong paraan, ang mga sinag lamang na nag-aambag sa pagbuo ng imahe ay isinasaalang-alang.

Tingnan natin kung paano ka makakakuha ng raster na imahe ng ilang 3D na eksena gamit ang backtracing. Ipagpalagay natin na ang projection plane ay nahahati sa maraming mga parisukat - mga pixel. Pumili tayo ng central projection na may nawawalang center sa isang tiyak na distansya mula sa projection plane. Gumuhit tayo ng isang tuwid na linya mula sa nawawalang sentro hanggang sa gitna ng parisukat (pixel) ng projection plane (Larawan 8.15). Ito ang magiging pangunahing back-trace ray. Kung ang tuwid na linya ng ray na ito ay tumama sa isa o higit pang mga bagay sa eksena, pagkatapos ay piliin ang pinakamalapit na intersection point. Upang matukoy ang kulay ng isang pixel ng imahe, kailangan mong isaalang-alang ang mga katangian ng bagay, pati na rin kung anong ilaw na radiation ang nahuhulog sa kaukulang punto ng bagay.

kanin. 8.16. Backtracing para sa mga bagay na may specular at refractive properties

Kung ang bagay ay nakasalamin (hindi bababa sa bahagyang), pagkatapos ay bumuo tayo ng pangalawang sinag - ang sinag ng insidente, kung isasaalang-alang ang nauna, pangunahin, sinusubaybayang sinag bilang ang sinag ng pagmuni-muni. Sa itaas, isinasaalang-alang namin ang specular reflection at nakakuha ng mga formula para sa vector ng reflected ray na ibinigay sa normal at incident ray vectors. Ngunit dito alam natin ang vector ng reflected ray, ngunit paano natin mahahanap ang vector ng incident ray? Upang gawin ito, maaari mong gamitin ang parehong specular reflection formula, ngunit tinutukoy ang kinakailangang incident ray vector bilang ang reflected ray. Ibig sabihin, kabaligtaran ang repleksyon.

Para sa isang perpektong salamin, sapat na upang masubaybayan lamang ang susunod na punto ng intersection ng pangalawang sinag na may ilang bagay. Ano ang ibig sabihin ng salitang "perpektong salamin"? Ipagpalagay natin na ang naturang salamin ay may perpektong pantay na pinakintab na ibabaw, kaya ang isang sinasalamin na sinag ay tumutugma lamang sa isang sinag ng insidente. Ang salamin ay maaaring madilim, iyon ay, sumipsip ng bahagi ng liwanag na enerhiya, ngunit ang panuntunan ay sinusunod pa rin: ang isang sinag ay insidente, ang isa ay makikita. Maaari mo ring isaalang-alang ang isang "hindi perpektong salamin." Nangangahulugan ito na ang ibabaw ay hindi pantay. Ang direksyon ng reflected ray ay tumutugma sa ilang incident rays (o vice versa, ang isang incident ray ay bumubuo ng ilang reflected rays), na bumubuo ng isang cone, posibleng asymmetrical, na may axis sa linya ng incident ray ng isang perpektong salamin. Ang kono ay tumutugma sa isang tiyak na batas ng pamamahagi ng intensity, ang pinakasimpleng kung saan ay inilarawan ng modelo ng Phong - ang cosine ng anggulo na nakataas sa isang tiyak na kapangyarihan. Ang isang hindi perpektong salamin ay lubos na nagpapahirap sa pagsubaybay - kailangan mong subaybayan ang hindi isa, ngunit maraming mga sinag ng insidente, at isaalang-alang ang kontribusyon ng radiation mula sa iba pang mga bagay na nakikita mula sa isang naibigay na punto.

Kung ang bagay ay transparent, pagkatapos ito ay kinakailangan upang bumuo ng isang bagong ray, isa na, kapag refracted, ay bubuo ng nakaraang traced ray. Dito maaari mo ring samantalahin ang reversibility, na totoo rin para sa repraksyon. Upang kalkulahin ang vector ng nais na ray, maaari mong ilapat ang mga formula na tinalakay sa itaas para sa vector ng refractive ray, sa pag-aakalang nangyayari ang repraksyon sa kabaligtaran na direksyon (Larawan 8.16).

Kung ang isang bagay ay may mga katangian ng nagkakalat na pagmuni-muni at repraksyon, kung gayon, sa pangkalahatang kaso, tulad ng para sa isang hindi perpektong salamin, kinakailangan upang subaybayan ang mga sinag na nagmumula sa lahat ng umiiral na mga bagay. Para sa diffuse reflection, ang intensity ng reflected light ay kilala na proporsyonal sa cosine ng anggulo sa pagitan ng ray vector mula sa light source at sa normal. Dito, ang pinagmumulan ng liwanag ay maaaring maging anumang bagay na nakikita mula sa isang partikular na punto na maaaring magpadala ng liwanag na enerhiya.

Kung ito ay lumabas na ang kasalukuyang backtracing ray ay hindi bumalandra sa anumang bagay, ngunit nakadirekta sa libreng espasyo, pagkatapos ay ang pagsubaybay para sa ray na ito ay nagtatapos.

Ang backtracing ray sa anyo kung saan namin ito isinasaalang-alang dito, bagama't binabawasan nito ang paghahanap, ay hindi nagpapahintulot sa amin na alisin ang walang katapusang bilang ng mga nasuri na ray. Sa katunayan, ang pamamaraang ito ay nagbibigay-daan sa amin na agad na makakuha ng isang pangunahing backtracing ray para sa bawat punto sa larawan. Gayunpaman, maaaring mayroon nang walang katapusang bilang ng mga pangalawang reflection ray. Kaya, halimbawa, kung ang isang bagay ay maaaring sumasalamin sa liwanag mula sa anumang iba pang bagay, at kung ang iba pang mga bagay na ito ay medyo malaki, kung gayon kung aling mga punto ng mga nagpapalabas na bagay ang kailangang isaalang-alang upang makabuo ng kaukulang mga sinag, halimbawa, sa nagkakalat na pagmuni-muni. ? Malinaw, ang lahat ng mga punto.

Sa praktikal na pagpapatupad ng paraan ng backtracing, ipinakilala ang mga paghihigpit. Ang ilan sa mga ito ay kinakailangan upang malutas ang problema ng synthesis ng imahe sa prinsipyo, at ang ilang mga paghihigpit ay maaaring makabuluhang mapabuti ang pagganap ng pagsubaybay. Mga halimbawa ng naturang mga paghihigpit.

1. Sa lahat ng uri ng mga bagay, ang ilan ay namumukod-tangi, na tatawagin natin pinagmumulan liwanag. Ang mga pinagmumulan ng liwanag ay maaari lamang maglabas ng liwanag, ngunit hindi ito maipapakita o mai-refract (isasaalang-alang lamang natin punto pinagmumulan ng liwanag).

2. Ang mga katangian ng mapanimdim na ibabaw ay inilarawan sa pamamagitan ng kabuuan ng dalawang bahagi - nagkakalat at specular.

3. Sa turn, ang specularity ay inilalarawan din ng dalawang bahagi. Una (pagmuni-muni) isinasaalang-alang ang mga pagmuni-muni mula sa iba pang mga bagay na hindi pinagmumulan ng liwanag. Isang specularly reflected beam lang ang binuo r para sa karagdagang pagsubaybay.Ikalawang bahagi ( Specular ) nangangahulugan ng liwanag na nagmumula sa mga pinagmumulan ng liwanag. Upang gawin ito, ang mga sinag ay nakadirekta sa lahat ng pinagmumulan ng liwanag at ang mga anggulo na nabuo ng mga sinag na ito na may specularly reflected back tracing ray ay tinutukoy. (r). Sa specular reflection, ang kulay ng isang punto sa ibabaw ay tinutukoy ng kulay ng kung ano ang sinasalamin. Sa pinakasimpleng kaso, ang salamin ay walang sariling kulay sa ibabaw.

4. Sa nagkakalat na pagmuni-muni, tanging mga sinag mula sa mga pinagmumulan ng liwanag ang isinasaalang-alang. Ang mga sinag mula sa specularly reflective surface ay hindi pinapansin. Kung ang sinag na nakadirekta sa isang ibinigay na pinagmumulan ng liwanag ay naharang ng isa pang bagay, kung gayon ang puntong ito ng bagay ay nasa anino. Sa pamamagitan ng nagkakalat na pagmuni-muni, ang kulay ng isang iluminado na punto sa isang ibabaw ay tinutukoy ng sariling kulay ng ibabaw at ang kulay ng mga pinagmumulan ng liwanag.

5. Para sa transparent (1gap5rage() bagay, ang pag-asa ng refractive index sa wavelength ay karaniwang hindi isinasaalang-alang. Minsan ang transparency ay karaniwang na-modelo nang walang repraksyon, iyon ay, ang direksyon ng refracted ray ako kasabay ng direksyon ng sinag ng insidente.

    Upang isaalang-alang ang pag-iilaw ng mga bagay sa pamamagitan ng liwanag na nakakalat ng iba pang mga bagay, isang bahagi ng background ang ipinakilala (sabient).

7. Upang makumpleto ang pagsubaybay, isang tiyak na paglilimita sa halaga ng pag-iilaw ay ipinakilala, na hindi na dapat mag-ambag sa resultang kulay, o ang bilang ng mga pag-ulit ay limitado.

Ayon kay Mga puting modelo ang kulay ng isang tiyak na punto ng isang bagay ay tinutukoy ng kabuuang intensity

ako() = KaIa()C() + KdId()C() + KsIs() + KrIr() + KtIt()

kung saan ang λ ay ang wavelength,

C (λ) - ang tinukoy na paunang kulay ng object point,

K a, K d, K s, K r ​​​​at K t - mga coefficient na isinasaalang-alang ang mga katangian ng isang partikular na bagay sa pamamagitan ng mga parameter ng background illumination, diffuse scattering, specularity, reflection at transparency,

ako a - intensity ng pag-iilaw sa background,

ako d - isinasaalang-alang ang intensity para sa nagkakalat na pagkalat,

ako s - intensity na isinasaalang-alang para sa specularity,

ako r - intensity ng radiation na dumarating kasama ang reflected beam,

ako t - intensity ng radiation na dumarating kasama ang refracted beam.

Ang intensity ng backlight (1 A ) para sa ilang bagay ay karaniwang isang pare-pareho. Sumulat tayo ng mga formula para sa iba pang intensidad. Para sa diffuse reflection

ako d =

saan ako i (λ) - intensity ng radiation i- ro pinagmumulan ng liwanag, θ i- ang anggulo sa pagitan ng normal sa ibabaw ng bagay at ang direksyon patungo i- vi Banayad na pinagmulan.

Para sa specularity:

ako d =

saan R- exponent mula isa hanggang ilang daan (ayon sa modelo ni Phong), α i-ang anggulo sa pagitan ng reflected ray (back tracing) at ang direksyon patungo sa r"th light source.

Ang intensity ng radiation na dumadaan kasama ang reflected beam ( ako r), pati na rin kasama ang isang refracted ray ( ako t ) , na pinarami ng isang kadahilanan na isinasaalang-alang ang pagpapahina ng intensity depende sa distansya na nilakbay ng sinag. Ang koepisyent na ito ay nakasulat sa anyo e - d saan d- layo ng nilakbay, - parameter ng pagpapalambing na isinasaalang-alang ang mga katangian ng daluyan kung saan ang beam ay nagpapalaganap.

Para sa pangunahing sinag, kinakailangang itakda ang direksyon na tumutugma sa napiling projection. Kung ang projection ay nasa gitna, kung gayon ang mga pangunahing sinag ay naghihiwalay mula sa isang karaniwang punto; para sa isang parallel na projection, ang mga pangunahing sinag ay parallel. Maaaring tukuyin ang ray, halimbawa, sa pamamagitan ng mga coordinate ng simula at pagtatapos ng segment, ang coordinate ng start point at direksyon, o sa ibang paraan. Ang pagtatakda ng pangunahing sinag ay natatanging tumutukoy sa projection inilalarawang eksena . Sa inverse ray tracing, anumang coordinate transformations ay hindi na kailangan. Ang projection ay awtomatikong nakuha - kabilang ang hindi lamang flat, ngunit din, halimbawa, cylindrical o spherical. Ito ay isa sa mga pagpapakita ng versatility ng paraan ng pagsubaybay.

Sa panahon ng ray tracing, kinakailangan upang matukoy ang mga intersection point ng isang tuwid na ray line na may mga bagay. Ang paraan para sa pagtukoy ng intersection point ay depende sa kung anong uri ng bagay ito at kung paano ito kinakatawan sa isang partikular na graphic system. Kaya, halimbawa, para sa mga bagay na ipinakita sa anyo ng polyhedra at polygonal meshes, maaari mong gamitin ang mga kilalang pamamaraan para sa pagtukoy ng punto ng intersection ng isang linya at isang eroplano, na isinasaalang-alang sa analytical geometry. Gayunpaman, kung ang gawain ay upang matukoy ang intersection ng isang ray na may mukha, kung gayon kinakailangan din na ang natagpuang intersection point ay nasa loob ng tabas ng mukha.

Mayroong ilang mga paraan upang suriin kung ang isang arbitrary na punto ay kabilang sa isang polygon. Isaalang-alang natin ang dalawang uri ng mahalagang parehong paraan (Larawan 8.17).

Unang paraan. Ang lahat ng mga punto kung saan ang tabas ay nagsalubong sa pahalang na linya, na tumutugma sa Y coordinate ng ibinigay na punto, ay matatagpuan. Pinagbukod-bukod ang mga intersection point sa pataas na pagkakasunud-sunod ng mga value ng X coordinate. Ang mga pares ng intersection point ay bumubuo ng mga segment. Kung ang puntong sinusuri ay kabilang sa isa sa mga segment (para dito, ang X coordinates ng ibinigay na punto at ang mga dulo ng mga segment ay inihambing), kung gayon ito ay panloob.

kanin. 8.17. Ang isang punto ay panloob kung: a - ang punto ay kabilang sa isang secant na segment, b - ang bilang ng mga intersection ay kakaiba

Pangalawang paraan. Ang isang punto ay tinutukoy na nasa parehong pahalang na linya gaya ng puntong sinusubok, at kinakailangan na ito ay nasa labas ng tabas ng polygon. Ang natagpuang panlabas na punto at ang pagsubok na punto ay ang mga dulo ng pahalang na segment. Ang mga intersection point ng segment na ito na may polygon contour ay tinutukoy. Kung ang bilang ng mga intersection ay kakaiba, nangangahulugan ito na ang nasubok na punto ay panloob.

Kung ang isang sinag ay nag-intersect sa ilang mga bagay, kung gayon ang pinakamalapit na punto sa direksyon ng kasalukuyang sinag ay pipiliin.

Gumawa tayo ng mga pangkalahatang konklusyon tungkol sa reverse ray tracing method.

Mga positibong katangian

1. Ang versatility ng pamamaraan, ang applicability nito para sa synthesis ng mga imahe ng medyo kumplikadong spatial scheme. Naglalaman ng maraming batas ng geometric na optika. Ang iba't ibang mga projection ay ipinatupad lamang.

2. Kahit na ang mga pinutol na bersyon ng paraang ito ay nagbibigay-daan sa iyo upang makakuha ng medyo makatotohanang mga imahe. Halimbawa, kung nililimitahan mo ang iyong sarili sa mga pangunahing sinag lamang (mula sa projection point), magreresulta ito sa pag-aalis ng mga hindi nakikitang punto. Ang pagsubaybay sa isa o dalawang pangalawang sinag ay nagbibigay ng mga anino, specularity, at transparency.

3. Ang lahat ng mga pagbabago sa coordinate (kung mayroon man) ay linear, kaya medyo madali itong gumana sa mga texture.

4. Para sa isang pixel ng isang raster na imahe, maaari mong i-trace ang ilang malapit na spaced ray, at pagkatapos ay i-average ang kanilang kulay upang maalis ang staircase effect (antialiasing).

5. Dahil ang pagkalkula ng isang punto ng imahe ay isinasagawa nang hiwalay sa iba pang mga punto, maaari itong epektibong magamit kapag ipinapatupad ang pamamaraang ito sa parallel computing system kung saan ang mga sinag ay maaaring masubaybayan nang sabay-sabay.

Bahid

1. Mga problema sa pagmomodelo ng nagkakalat na pagmuni-muni at repraksyon

2. Para sa bawat punto sa imahe, kinakailangan na magsagawa ng maraming mga pagpapatakbo ng computational. Ang pagsubaybay sa ray ay isa sa pinakamabagal na algorithm ng synthesis ng imahe.

Alam kong medyo nakakadismaya. Nasaan ang mga reflection, anino at maganda hitsura? Makukuha natin ang lahat, dahil kasisimula pa lang natin. Ngunit ito ay isang magandang simula - ang mga sphere ay mukhang mga bilog, na mas mahusay kaysa sa pagiging mukhang pusa. Hindi sila mukhang mga sphere dahil napalampas namin ang isang mahalagang bahagi na nagbibigay-daan sa mga tao na matukoy ang hugis ng isang bagay - kung paano ito nakikipag-ugnayan sa liwanag.

Pag-iilaw

Ang unang hakbang sa pagdaragdag ng "realismo" sa aming pag-render ng eksena ay gayahin ang pag-iilaw. Ang pag-iilaw ay isang hindi kapani-paniwalang kumplikadong paksa, kaya magpapakita ako ng isang napakasimpleng modelo na sapat para sa aming mga layunin. Ang ilang bahagi ng modelong ito ay hindi kahit isang pagtatantya ng mga pisikal na modelo, ang mga ito ay mabilis lamang at maganda ang hitsura.

Magsisimula tayo sa ilang nagpapasimpleng pagpapalagay na magpapadali sa ating buhay.

Una, idedeklara namin na ang lahat ng ilaw ay puti. Ito ay magpapahintulot sa amin na makilala ang anumang pinagmumulan ng liwanag sa pamamagitan ng isang tunay na numerong i, na tinatawag ningning pag-iilaw. Hindi ganoon kakomplikado ang paggaya ng may kulay na pag-iilaw (kailangan mo lang ng tatlong halaga ng liwanag, isa sa bawat channel, at pagkalkula ng lahat ng mga kulay at pag-iilaw sa bawat channel), ngunit para mapadali ang ating trabaho, hindi ko ito gagawin.

Pangalawa, aalisin natin ang kapaligiran. Nangangahulugan ito na ang mga ilaw ay hindi nagiging mas maliwanag, anuman ang kanilang saklaw. Ang pagpapahina ng liwanag ng liwanag depende sa distansya ay hindi rin masyadong mahirap ipatupad, ngunit para sa kalinawan ay laktawan natin ito sa ngayon.

Mga pinagmumulan ng ilaw

Ang liwanag ay dapat mula sa kung saan kumilos. Sa seksyong ito tutukuyin natin ang tatlong magkakaibang uri ng mga pinagmumulan ng liwanag.

Mga mapagkukunan ng punto

Point source naglalabas ng liwanag mula sa isang nakapirming punto sa kalawakan na tinatawag na nito posisyon. Ang liwanag ay ibinubuga nang pantay-pantay sa lahat ng direksyon; kaya naman tinawag din ito omnidirectional na pag-iilaw. Dahil dito, ang isang point source ay ganap na nailalarawan sa posisyon at liwanag nito.

Ang incandescent light bulb ay isang magandang halimbawa sa totoong mundo ng kung ano ang tinatayang pinagmumulan ng liwanag. Kahit na ang isang maliwanag na maliwanag na lampara ay hindi naglalabas ng liwanag mula sa isang punto at hindi ito ganap na omnidirectional, ang pagtatantya ay medyo maganda.

Tukuyin natin ang isang vector bilang direksyon mula sa punto P sa pinangyarihan hanggang sa pinagmumulan ng liwanag na Q. Ang vector na ito, ay tinatawag liwanag na vector, ay katumbas lamang ng . Tandaan na dahil ang Q ay naayos at ang P ay maaaring maging anumang punto sa eksena, sa pangkalahatan ay magkakaiba ito para sa bawat punto sa eksena.

Mga Direktang Pinagmumulan

Kung ang isang point source ay isang magandang approximation ng isang incandescent light bulb, kung gayon ano ang isang magandang approximation ng Araw?

Ito ay isang nakakalito na tanong at ang sagot ay depende sa kung ano ang gusto mong i-render.

Sa sukat ng Solar System, ang Araw ay maaaring ituring na isang point source. Pagkatapos ng lahat, naglalabas ito ng liwanag mula sa isang punto (kahit na medyo malaki) at naglalabas nito sa lahat ng direksyon, kaya umaangkop ito sa parehong mga kinakailangan.

Gayunpaman, kung ang iyong eksena ay naganap sa Earth, hindi ito isang napakahusay na pagtatantya. Ang araw ay napakalayo na ang bawat sinag ng liwanag ay talagang magkakaroon ng parehong direksyon (Tandaan: ang pagtatantya na ito ay nasa sukat ng lungsod, ngunit hindi sa mas malalayong distansya - sa katunayan, ang mga sinaunang Griyego ay nagawang kalkulahin ang radius ng Earth gamit ang kamangha-manghang katumpakan batay sa iba't ibang direksyon ng sikat ng araw sa iba't ibang lugar). Bagama't posible itong tantiyahin sa pamamagitan ng paggamit ng point source na napakalayo mula sa eksena, ang distansyang ito at ang distansya sa pagitan ng mga bagay sa eksena ay ibang-iba sa magnitude na maaaring mangyari ang mga error sa numerical precision.

Para sa mga ganitong kaso ay itatakda namin mga pinagmumulan ng ilaw sa direksyon. Tulad ng mga pinagmumulan ng punto, ang isang pinagmumulan ng direksyon ay may liwanag, ngunit hindi katulad nila, wala itong posisyon. Sa halip ay mayroon siya direksyon. Maaari mong madama ito bilang isang walang katapusan na malayong pinagmulan ng punto, na nagniningning sa isang tiyak na direksyon.

Sa kaso ng mga pinagmumulan ng punto, kailangan nating kalkulahin ang isang bagong light vector para sa bawat punto P sa eksena, ngunit sa kasong ito ay ibinigay. Sa eksena sa Araw at Lupa ito ay magiging katumbas ng .

Ambient lighting

Posible bang magmodelo ng anumang tunay na pag-iilaw sa mundo bilang isang punto o direksyong pinagmulan? Halos palaging oo (Tandaan: ngunit hindi ito kailangang maging madali; ang pag-iilaw ng lugar (mag-isip ng isang pinagmulan sa likod ng isang diffuser) ay maaaring tantiyahin ng maraming mga mapagkukunan ng punto sa ibabaw nito, ngunit ito ay kumplikado, mas mahal sa pagkalkula, at ang mga resulta ay hindi perpekto.). Sapat ba ang dalawang uri ng mapagkukunang ito para sa ating mga layunin? Sa kasamaang palad hindi.

Isipin kung ano ang nangyayari sa Buwan. Ang tanging mahalagang pinagmumulan ng liwanag sa malapit ay ang Araw. Iyon ay, ang "harap na kalahati" ng Buwan na may kaugnayan sa Araw ay tumatanggap ng lahat ng pag-iilaw, habang ang "likod na kalahati" ay nasa ganap na kadiliman. Nakikita natin ito mula sa iba't ibang anggulo sa Earth, at ang epektong ito ay lumilikha ng tinatawag nating "mga yugto" ng Buwan.

Gayunpaman, ang sitwasyon sa Earth ay medyo naiiba. Kahit na ang mga puntong hindi direktang tumatanggap ng liwanag mula sa pinagmumulan ng liwanag ay hindi ganap na nasa dilim (tingnan lamang ang sahig sa ilalim ng mesa). Paano naaabot ng mga sinag ng liwanag ang mga puntong ito kung ang "view" ng mga pinagmumulan ng liwanag ay naharang ng isang bagay?

Gaya ng nabanggit ko sa section Mga modelo ng kulay Kapag ang liwanag ay tumama sa isang bagay, ang ilan sa mga ito ay nasisipsip, ngunit ang iba ay nakakalat sa eksena. Nangangahulugan ito na ang liwanag ay maaaring dumating hindi lamang mula sa mga pinagmumulan ng liwanag, kundi pati na rin sa iba pang mga bagay na tumatanggap nito mula sa mga pinagmumulan ng liwanag at nakakalat ito pabalik. Ngunit bakit huminto doon? Ang nagkakalat na pag-iilaw, sa turn, ay nahuhulog sa ibang bagay, ang bahagi nito ay hinihigop, at ang bahagi nito ay nakakalat muli sa eksena. Sa bawat pagmuni-muni, nawawalan ng liwanag ang ilaw, ngunit sa teoryang maaari kang magpatuloy ad infinitum(Tandaan: Sa totoo lang hindi, dahil ang liwanag ay quantum sa kalikasan, ngunit sapat na malapit.)

Nangangahulugan ito na kailangan mong isaalang-alang ang pinagmumulan ng liwanag bawat bagay. Gaya ng maiisip mo, lubos nitong pinapataas ang pagiging kumplikado ng aming modelo, kaya hindi kami pupunta sa rutang iyon (Tandaan: ngunit maaari kang mag-google ng Global Illumination at tingnan ang magagandang larawan.).

Ngunit hindi pa rin namin nais na ang bawat bagay ay direktang naiilawan o ganap na madilim (maliban kung nagre-render kami ng modelo ng solar system). Upang malampasan ang balakid na ito, tutukuyin natin ang ikatlong uri ng mga pinagmumulan ng liwanag, na tinatawag na ilaw sa paligid, na nailalarawan lamang sa liwanag. Ito ay pinaniniwalaan na ito ay nagdadala ng walang kondisyong kontribusyon ng pag-iilaw sa bawat punto sa eksena. Ito ay isang malaking pagpapasimple ng sobrang kumplikadong pakikipag-ugnayan sa pagitan ng mga ilaw at mga ibabaw ng eksena, ngunit gumagana ito.

Pag-iilaw ng isang punto

Sa pangkalahatan, ang isang eksena ay magkakaroon ng isang ambient light source (dahil ang ambient light ay mayroon lamang isang brightness value, at anumang bilang ng mga ito ay magsasama-sama sa isang solong ambient light source) at isang arbitrary na bilang ng mga point at directional na ilaw.

Upang kalkulahin ang pag-iilaw ng isang punto, kailangan lang nating kalkulahin ang dami ng liwanag na naiambag ng bawat pinagmulan at idagdag ang mga ito upang makakuha ng isang numero na kumakatawan sa kabuuang halaga ng pag-iilaw na natanggap ng punto. Pagkatapos ay maaari nating i-multiply ang kulay ng ibabaw sa puntong iyon sa numerong ito upang makuha ang tamang kulay na naiilawan.

Kaya, ano ang mangyayari kapag ang isang sinag ng liwanag na may direksyon mula sa isang direksyon o pinagmumulan ng punto ay tumama sa punto P ng ilang bagay sa ating eksena?

Sa madaling paraan, maaari nating pag-uri-uriin ang mga bagay sa dalawang pangkalahatang klase batay sa kung paano kumilos ang mga ito nang may liwanag: "matte" at "makintab." Dahil ang karamihan sa mga bagay sa paligid natin ay maaaring ituring na "matte", magsisimula tayo sa kanila.

Nagkakalat na pagkalat

Kapag ang isang sinag ng liwanag ay bumagsak sa isang matte na bagay, dahil sa hindi pagkakapantay-pantay ng ibabaw nito sa antas ng mikroskopiko, sinasalamin nito ang sinag sa eksena nang pantay-pantay sa lahat ng direksyon, iyon ay, ang isang "nakakalat" ("nagkakalat") na pagmuni-muni ay nakuha. .

Upang i-verify ito, tingnang mabuti ang ilang matte na bagay, halimbawa, isang pader: kung lilipat ka sa dingding, hindi nagbabago ang kulay nito. Ibig sabihin, ang liwanag na nakikita mo mula sa isang bagay ay pareho kahit saan mo tingnan ang bagay.

Sa kabilang banda, ang dami ng nasasalamin na liwanag ay depende sa anggulo sa pagitan ng light beam at ng ibabaw. Ito ay intuitively malinaw - ang enerhiya na inilipat ng beam, depende sa anggulo, ay dapat na ipamahagi sa isang mas maliit o mas malaking ibabaw, iyon ay, ang enerhiya sa bawat unit area na makikita sa eksena ay magiging mas mataas o mas mababa, ayon sa pagkakabanggit:

Upang maipahayag ito sa matematika, kilalanin natin ang oryentasyon ng isang ibabaw sa pamamagitan nito normal na vector. Ang isang normal na vector, o simpleng "normal," ay isang vector na patayo sa ibabaw sa isang punto. Isa rin itong unit vector, ibig sabihin ang haba nito ay 1. Tatawagin natin itong vector .

Diffuse reflection modeling

Kaya, ang isang sinag ng liwanag na may direksyon at ningning ay bumabagsak sa ibabaw na may normal na . Anong bahagi ang makikita pabalik sa eksena bilang isang function ng , at ?

Para sa isang geometric na pagkakatulad, isipin natin ang liwanag ng liwanag bilang ang "lapad" ng sinag. Ang enerhiya nito ay ipinamamahagi sa ibabaw ng laki. Kapag at may parehong direksyon, iyon ay, ang sinag ay patayo sa ibabaw, na nangangahulugan na ang enerhiya na ipinapakita sa bawat yunit ng lugar ay katumbas ng enerhiya ng insidente sa bawat yunit ng lugar;< . С другой стороны, когда угол между и приближается к , приближается к , то есть энергия на единицу площади приближается к 0; . Но что происходит в промежутках?

Ang sitwasyon ay ipinapakita sa diagram sa ibaba. Alam namin, at; Nagdagdag ako ng mga anggulo at , pati na rin ang mga tuldok , at , upang gawing mas madali ang mga tala na nauugnay sa diagram na ito.

Dahil sa teknikal na sinag ng liwanag ay walang lapad, samakatuwid ay ipagpalagay natin na ang lahat ay nangyayari sa isang walang katapusang patag na lugar ng ibabaw. Kahit na ito ay ang ibabaw ng isang globo, ang lugar na pinag-uusapan ay napakaliit na halos patag na may kaugnayan sa laki ng globo, tulad ng Earth na lumilitaw na patag sa maliliit na kaliskis.

Ang isang sinag ng liwanag na may lapad ay tumatama sa isang ibabaw sa isang punto sa isang anggulo. Ang normal sa isang punto ay katumbas ng , at ang enerhiya na inilipat ng beam ay ipinamamahagi sa ibabaw . Kailangan nating kalkulahin.

Ang isa sa mga anggulo ay katumbas ng , at ang isa ay katumbas ng . Pagkatapos ang ikatlong anggulo ay katumbas ng . Ngunit dapat tandaan na bumubuo rin sila ng isang tamang anggulo, iyon ay, dapat din silang . Samakatuwid,:

Tingnan natin ang isang tatsulok. Ang mga anggulo nito ay katumbas ng , at . Ang panig ay pantay at ang panig ay pantay.

At ngayon... ang trigonometrya ay sumagip! A-priory ; palitan ng , at ng , at makukuha natin


kung ano ang na-convert sa
Malapit na tayong matapos. - ay ang anggulo sa pagitan ng at , iyon ay, maaaring ipahayag bilang
At sa wakas
Kaya, mayroon tayong napakasimpleng equation na nag-uugnay sa nasasalamin na bahagi ng liwanag sa anggulo sa pagitan ng normal sa ibabaw at sa direksyon ng liwanag.

Tandaan na sa mga anggulo higit na halaga nagiging negatibo. Kung gagamitin natin ang halagang ito nang walang pag-aalinlangan, ang resulta ay mga light source subtractive liwanag. Ito ay walang anumang pisikal na kahulugan; ang isang mas malaking anggulo ay nangangahulugan lamang na ang liwanag ay talagang umabot pabalik ibabaw, at hindi nakakatulong sa pag-iilaw ng iluminado na punto. Iyon ay, kung ito ay nagiging negatibo, pagkatapos ay itinuturing namin itong katumbas ng .

Diffuse Reflection Equation

Maaari na tayong bumalangkas ng equation para kalkulahin ang kabuuang dami ng liwanag na natanggap ng isang puntong may normal sa isang eksenang may ambient luminance at point o direksyong pinagmumulan ng liwanag na may luminance at light vector na kilala (para sa mga pinagmumulan ng direksyon) o kalkulado para sa P (para sa mga mapagkukunan ng punto):
Ito ay nagkakahalaga ng pag-uulit muli na ang mga tuntunin kung saan hindi dapat idagdag sa pag-iilaw ng punto.

Mga Sphere Normal

Ang kulang na lang dito ay saan nanggagaling ang mga normal?

Ang tanong na ito ay mas nakakalito kaysa sa tila, tulad ng makikita natin sa ikalawang bahagi ng artikulo. Sa kabutihang palad, para sa kaso na aming isinasaalang-alang mayroong isang napaka-simpleng solusyon: ang normal na vector ng anumang punto sa globo ay nasa isang tuwid na linya na dumadaan sa gitna ng globo. Iyon ay, kung ang sentro ng globo ay , kung gayon ang direksyon ng normal sa punto ay katumbas ng:

Bakit ko isinulat ang "normal na direksyon" at hindi "normal"? Bilang karagdagan sa pagiging patayo sa ibabaw, ang normal ay dapat na isang unit vector; ito ay magiging totoo kung ang radius ng globo ay katumbas ng , na hindi palaging totoo. Upang makalkula ang normal mismo, kailangan nating hatiin ang vector sa haba nito, kaya makuha ang haba:


Ito ay kadalasang may teoretikal na interes dahil ang ilaw na equation na nakasulat sa itaas ay nagsasangkot ng paghahati sa , ngunit ang isang magandang diskarte ay ang lumikha ng "totoo" na mga normal; Gagawin nitong mas madali ang ating trabaho sa hinaharap.

Pag-render na may diffuse reflection

Isalin natin ang lahat ng ito sa pseudocode. Una, magdagdag tayo ng ilang ilaw sa eksena:

Banayad ( uri = ambient intensity = 0.2 ) light ( type = point intensity = 0.6 position = (2, 1, 0) ) light ( type = directional intensity = 0.2 direksyon = (1, 4, 4) )
Tandaan na ang liwanag ay madaling ibinubuod sa , dahil ang illumination equation ay nagpapahiwatig na walang punto ang maaaring magkaroon ng liwanag na mas malaki kaysa sa isa. Nangangahulugan ito na hindi tayo mapupunta sa mga lugar na "na-expose nang labis."

Ang lighting equation ay medyo madaling i-convert sa pseudocode:

ComputeLighting(P, N) ( i = 0.0 para sa liwanag sa eksena. Mga ilaw ( kung light.type == ambient ( i += light.intensity ) iba pa ( kung light.type == point L = light.position - P else L = light.direction n_dot_l = tuldok(N, L) kung n_dot_l > 0 i += light.intensity*n_dot_l/(length(N)*length(L)) ) return i )
At ang tanging natitira ay ang paggamit ng ComputeLighting sa TraceRay. Papalitan namin ang string na nagbabalik ng kulay ng globo

Ibalik ang pinakamalapit na_sphere.color
sa fragment na ito:

P = O + pinakamalapit_t*D # kalkulahin ang intersection N = P - pinakamalapit na_sphere.center # kalkulahin ang normal ng globo sa intersection point N = N / length(N) return closest_sphere.color*ComputeLighting(P, N)
Para lang masaya, magdagdag tayo ng malaking dilaw na globo:

Sphere ( kulay = (255, 255, 0) # Yellow center = (0, -5001, 0) radius = 5000 )
Pinasisigla namin ang renderer, at narito, ang mga sphere sa wakas ay nagsimulang magmukhang mga sphere!

Pero teka, paano naging flat yellow floor ang malaking yellow sphere?

Hindi ito ang kaso, sadyang malaki ang kanyang kamag-anak sa iba pang tatlo, at ang camera ay napakalapit sa kanya na siya ay mukhang flat. Tulad ng ating planeta na mukhang flat kapag tayo ay nakatayo sa ibabaw nito.

Reflection mula sa isang makinis na ibabaw

Ngayon ay ibinaling natin ang ating pansin sa mga "makintab" na bagay. Hindi tulad ng mga bagay na "matte", nagbabago ang hitsura ng mga "makintab" na bagay kapag tiningnan mo sila mula sa iba't ibang anggulo.

Kumuha tayo ng billiard ball o kakahugas lang ng kotse. Ang mga bagay na ito ay nagpapakita ng isang partikular na pattern ng pagpapalaganap ng liwanag, kadalasang may mga maliliwanag na lugar na lumilitaw na gumagalaw kapag naglalakad ka sa paligid ng mga ito. Hindi tulad ng mga matte na bagay, kung paano mo nakikita ang ibabaw ng mga bagay na ito ay talagang depende sa iyong pananaw.

Tandaan na ang mga pulang bola ng bilyar ay mananatiling pula kung aatras ka ng ilang hakbang, ngunit ang maliwanag Puting batik, na nagbibigay sa kanila ng "makintab" na anyo, ay lumilitaw na gumagalaw. Nangangahulugan ito na hindi pinapalitan ng bagong epekto ang nagkakalat na pagmuni-muni, ngunit pinupunan ito.

Bakit ito nangyayari? Maaari tayong magsimula sa kung bakit ganito Hindi nangyayari sa mga matte na bagay. Tulad ng nakita namin sa nakaraang seksyon Kapag ang isang sinag ng liwanag ay tumama sa ibabaw ng isang matte na bagay, ito ay pantay na nakakalat pabalik sa eksena sa lahat ng direksyon. Sa madaling salita, ito ay dahil sa hindi pagkakapantay-pantay ng ibabaw ng bagay, iyon ay, sa antas ng mikroskopiko, mukhang maraming maliliit na ibabaw na nakadirekta sa mga random na direksyon:

Ngunit ano ang mangyayari kung ang ibabaw ay hindi gaanong hindi pantay? Gawin natin ang iba pang sukdulan - isang perpektong makintab na salamin. Kapag ang sinag ng liwanag ay tumama sa salamin, ito ay makikita sa isang direksyon, na simetriko sa anggulo ng saklaw na may kaugnayan sa normal ng salamin. Kung pangalanan natin ang direksyon ng sinasalamin na liwanag at sumasang-ayon na ito ay nagpapahiwatig sa ilaw na pinagmulan, nakukuha namin ang sumusunod na sitwasyon:

Depende sa antas ng "polishing" ng ibabaw, ito ay higit pa o mas kaunti tulad ng isang salamin; iyon ay, nakakakuha tayo ng "salamin" na pagmuni-muni (specular reflection, mula sa Latin na "speculum", iyon ay, "salamin").

Para sa perpektong makintab na salamin, ang sinag ng liwanag ng insidente ay makikita sa isang direksyon. Ito ang nagbibigay-daan sa atin na malinaw na makita ang mga bagay sa salamin: para sa bawat sinag ng insidente ay mayroong isang sinasalamin na sinag. Ngunit hindi lahat ng bagay ay perpektong pinakintab; Bagaman karamihan ng ang liwanag ay makikita sa direksyon, bahagi nito ay makikita sa mga direksyon na malapit sa; mas malapit sa , mas maraming liwanag ang makikita sa direksyong iyon. Tinutukoy ng "kinning" ng isang bagay kung gaano kabilis bumababa ang sinasalamin na liwanag habang lumalayo ito sa:

Interesado kaming malaman kung gaano karaming liwanag ang naipapakita pabalik sa aming pananaw (dahil iyon ang liwanag na ginagamit namin upang matukoy ang kulay ng bawat punto). Kung ang "view vector" ay tumuturo mula sa camera, at ang anggulo sa pagitan ng at , kung gayon ito ang mayroon tayo:

Kapag ang lahat ng liwanag ay naaninag. Hindi naaaninag ang liwanag. Tulad ng nagkakalat na pagmuni-muni, kailangan namin ng isang mathematical expression upang matukoy kung ano ang mangyayari sa mga intermediate na halaga ng .

Simulation ng "salamin" na pagmuni-muni

Tandaan kung paano ko nabanggit kanina na hindi lahat ng mga modelo ay nakabatay sa mga pisikal na modelo? Well, narito ang isang halimbawa nito. Ang modelo sa ibaba ay arbitrary, ngunit ginagamit dahil madali itong kalkulahin at maganda ang hitsura.

Kunin natin. Ito ay may magagandang katangian: , , at ang mga halaga ay unti-unting bumababa mula sa kahabaan ng napakagandang kurba:

Natutugunan ang lahat ng mga kinakailangan para sa pag-andar ng salamin, kaya bakit hindi ito gamitin?

Ngunit kulang tayo ng isa pang detalye. Sa pormulasyon na ito, lahat ng bagay ay kumikinang nang pantay. Paano baguhin ang equation para makuha iba't ibang grado sumikat?

Huwag kalimutan na ang pagtakpan na ito ay isang sukatan kung gaano kabilis bumababa ang function ng reflectance habang tumataas ka. Ang isang napakasimpleng paraan upang makakuha ng iba't ibang light curve ay ang pagkalkula ng kapangyarihan ng ilang positibong exponent. Dahil , ito ay malinaw na ; ibig sabihin, ito ay eksaktong kapareho ng , "na" lang. Narito ang para sa iba't ibang kahulugan :

Kung mas malaki ang value, magiging "mas makitid" ang feature sa kapitbahayan ng , at mas lumilitaw ang bagay.

Karaniwang tinatawag tagapagpahiwatig ng reflectance, at ito ay isang pag-aari ng ibabaw. Dahil ang modelo ay hindi batay sa pisikal na katotohanan, ang mga halaga ay maaari lamang matukoy sa pamamagitan ng pagsubok at pagkakamali, iyon ay, pagsasaayos ng mga halaga hanggang sa magsimula silang magmukhang "natural" (Tandaan: gumamit ng modelong batay sa pisika, tingnan ang two-beam reflectance function (DRF) )).

Pagsama-samahin natin ang lahat. Ang sinag ay nahuhulog sa ibabaw sa isang punto kung saan ang normal ay katumbas ng at ang reflection index ay . Gaano karaming liwanag ang masasalamin sa direksyon ng view?

Napagpasyahan na namin na ang halagang ito ay katumbas ng , kung saan ang anggulo sa pagitan ng at , na kung saan ay ipinapakita na may kaugnayan sa . Iyon ay, ang unang hakbang ay ang pagkalkula mula sa at .

Maaari tayong mabulok sa dalawang vectors at , tulad na , kung saan ay parallel at perpendicular:

Ito ay isang projection sa ; sa pamamagitan ng mga katangian ng produktong scalar at batay sa katotohanan na, ang haba ng projection na ito ay katumbas ng . Natukoy namin kung ano ang magiging parallel, kaya .

Since , makukuha natin agad .

Ngayon tingnan natin ang ; dahil ito ay simetriko tungkol sa , ang parallel na bahagi nito ay kapareho ng sa , at ang perpendikular na bahagi nito ay kabaligtaran ng sa ; yan ay :

Ang pagpapalit sa naunang nakuha na mga expression, nakukuha namin


at pinasimple ng kaunti, nakukuha namin

Ang kahulugan ng "salamin" na pagmuni-muni

Ngayon handa na kaming isulat ang equation ng reflection ng "mirror":

Tulad ng nagkakalat na pag-iilaw, maaari itong maging negatibo at muli ay dapat nating balewalain ito. Gayundin, hindi lahat ng bagay ay kailangang makintab; para sa mga naturang bagay (na kakatawanin natin sa pamamagitan ng ) ang halaga ng "specularity" ay hindi kakalkulahin sa lahat.

Nagre-render na may mga "specular" na pagmuni-muni

Idagdag natin ang "salamin" na mga pagmuni-muni na ginagawa natin sa eksena. Una, gumawa tayo ng ilang pagbabago sa mismong eksena:

Sphere ( center = (0, -1, 3) radius = 1 color = (255, 0, 0) # Red specular = 500 # Shiny ) sphere ( center = (-2, 1, 3) radius = 1 color = ( 0, 0, 255) # Blue specular = 500 # Shiny ) sphere ( center = (2, 1, 3) radius = 1 color = (0, 255, 0) # Green specular = 10 # Medyo makintab ) sphere ( color = (255, 255, 0) # Yellow center = (0, -5001, 0) radius = 5000 specular = 1000 # Very shiny )
Sa code, kailangan nating baguhin ang ComputeLighting upang makalkula nito ang halaga ng "specularity" kung kinakailangan at idagdag ito sa pangkalahatang pag-iilaw. Pansinin na nangangailangan ito ngayon at:

ComputeLighting(P, N, V, s) ( i = 0.0 para sa liwanag sa eksena. Mga ilaw ( kung light.type == ambient ( i += light.intensity ) iba pa ( kung light.type == point L = light.position - P else L = light.direction # Diffuse n_dot_l = dot(N, L) kung n_dot_l > 0 i += light.intensity*n_dot_l/(length(N)*length(L)) # Specularity if s != -1 ( R = 2*N*dot(N, L) - L r_dot_v = dot(R, V) kung r_dot_v >
Sa wakas, kailangan nating baguhin ang TraceRay upang maipasa nito ang mga bagong parameter ng ComputeLighting. halata; ito ay kinuha mula sa sphere data. Ngunit paano na? ay isang vector na tumuturo mula sa bagay patungo sa camera. Sa kabutihang palad, sa TraceRay mayroon na tayong vector na nakadirekta mula sa camera patungo sa object - ito ang direksyon ng traced ray! Ibig sabihin, simple lang.

Narito ang bagong TraceRay code na may "salamin" na pagmuni-muni:

TraceRay(O, D, t_min, t_max) ( closest_t = inf closest_sphere = NULL para sa sphere sa scene.Spheres ( t1, t2 = IntersectRaySphere(O, D, sphere) kung t1 sa at t1< closest_t closest_t = t1 closest_sphere = sphere if t2 in and t2 < closest_t closest_t = t2 closest_sphere = sphere } if closest_sphere == NULL return BACKGROUND_COLOR P = O + closest_t*D # Вычисление пересечения N = P - closest_sphere.center # Вычисление нормали сферы в точке пересечения N = N / length(N) return closest_sphere.color*ComputeLighting(P, N, -D, sphere.specular) }
At narito ang aming gantimpala para sa lahat ng juggling na ito sa mga vectors:

Mga anino

Kung saan may liwanag at bagay, dapat may mga anino din. Kaya't nasaan ang ating mga anino?

Magsimula tayo sa isang mas pangunahing tanong. Bakit dapat maging anino? Lumilitaw ang mga anino kung saan may liwanag, ngunit hindi maabot ng mga sinag nito ang bagay dahil may ibang bagay sa kanilang dinadaanan.

Mapapansin mo na sa nakaraang seksyon ay interesado kami sa mga anggulo at vector, ngunit isinasaalang-alang lamang namin ang pinagmumulan ng liwanag at ang punto na kailangan naming kulayan, at ganap na binalewala ang lahat ng iba pang nangyayari sa eksena - tulad ng isang bagay na pumapasok. ang daan.

Sa halip kailangan nating magdagdag ng ilang lohika na nagsasabing " kung mayroong isang bagay sa pagitan ng punto at ang pinagmulan, hindi na kailangang magdagdag ng ilaw na nagmumula sa pinagmulang ito".

Nais naming i-highlight ang dalawa mga sumusunod na kaso:

Mukhang mayroon kaming lahat ng mga tool na kailangan namin upang gawin ito.

Magsimula tayo sa pinagmumulan ng direksyon. Alam namin ; ito ang puntong interesado tayo. Alam namin ; bahagi ito ng pagtukoy sa pinanggagalingan ng liwanag. Ang pagkakaroon ng at , maaari nating tukuyin ang isang sinag, ibig sabihin, na pumasa mula sa isang punto patungo sa isang walang katapusan na malayong pinagmumulan ng liwanag. Nag-intersect ba ang sinag na ito sa isa pang bagay? Kung hindi, kung gayon walang anuman sa pagitan ng punto at ang pinagmulan, iyon ay, maaari nating kalkulahin ang pag-iilaw mula sa pinagmulang ito at idagdag ito sa kabuuang pag-iilaw. Kung ito ay tumawid, pagkatapos ay hindi namin pinapansin ang pinagmulang ito.

Alam na natin kung paano kalkulahin ang pinakamalapit na intersection sa pagitan ng isang ray at isang globo; ginagamit namin ito upang masubaybayan ang mga sinag mula sa camera. Maaari naming muli itong gamitin upang kalkulahin ang pinakamalapit na intersection sa pagitan ng light ray at ang natitirang bahagi ng eksena.

Gayunpaman, ang mga parameter ay bahagyang naiiba. Sa halip na magsimula mula sa camera, ang mga sinag ay ibinubuga mula sa . Ang direksyon ay hindi , ngunit . At kami ay interesado sa mga interseksyon sa lahat ng bagay pagkatapos sa isang walang katapusang distansya; nangangahulugan ito na at .

Maaari naming tratuhin ang mga mapagkukunan ng punto sa isang katulad na paraan, na may dalawang pagbubukod. Una, ang , ay hindi tinukoy, ngunit napakadaling kalkulahin mula sa posisyon ng pinagmulan at . Pangalawa, interesado kami sa anumang mga intersection simula sa , ngunit hanggang sa (kung hindi man, objects sa likod ang pinagmumulan ng liwanag ay maaaring lumikha ng mga anino!); ibig sabihin, sa kasong ito at .

May isang gilid na kaso na kailangan nating isaalang-alang. Kumuha tayo ng isang sinag. Kung maghahanap tayo ng mga intersection na nagsisimula sa , malamang na mahahanap natin ang sa , dahil nasa globo talaga ito, at ; sa madaling salita, ang bawat bagay ay maglalagay ng anino sa sarili nito (Tandaan: mas tiyak, gusto nating iwasan ang isang sitwasyon kung saan ang isang punto, at hindi ang buong bagay, ay naglalagay ng anino sa sarili nito; isang bagay na may hugis na mas kumplikado kaysa sa isang globo. (lalo na ang anumang malukong bagay) ay maaaring maglagay ng mga tunay na anino sa sarili nito!

Ang pinakasimpleng paraan upang harapin ito ay ang paggamit ng maliit bilang lower bound sa halip na . Sa geometriko, gusto naming tiyakin na ang sinag ay nagsisimula nang bahagya mula sa ibabaw, iyon ay, malapit sa , ngunit hindi eksakto sa . Iyon ay, para sa mga pinagmumulan ng direksyon ang pagitan ay magiging , at para sa mga mapagkukunan ng punto - .

Pag-render gamit ang mga anino

Gawin natin itong pseudocode.

SA nakaraang bersyon Kinakalkula ng TraceRay ang pinakamalapit na intersection ng ray-sphere at pagkatapos ay kinakalkula ang pag-iilaw sa intersection. Kailangan naming kunin ang pinakamalapit na intersection code dahil gusto naming gamitin itong muli upang kalkulahin ang mga anino:

ClosestIntersection(O, D, t_min, t_max) ( closest_t = inf closest_sphere = NULL para sa sphere sa scene.Spheres ( t1, t2 = IntersectRaySphere(O, D, sphere) kung t1 sa at t1< closest_t closest_t = t1 closest_sphere = sphere if t2 in and t2 < closest_t closest_t = t2 closest_sphere = sphere } return closest_sphere, closest_t }
Bilang resulta, ang TraceRay ay mas simple:

TraceRay(O, D, t_min, t_max) ( closest_sphere, closest_t = ClosestIntersection(O, D, t_min, t_max) kung closest_sphere == NULL return BACKGROUND_COLOR P = O + closest_t*D # Compute intersection N = P - closest_sphere.center # Compute sphere normal sa intersection N = N / length(N) return closest_sphere.color*ComputeLighting(P, N, -D, sphere.specular) )
Ngayon ay kailangan nating magdagdag ng shadow check sa ComputeLighting:

ComputeLighting(P, N, V, s) ( i = 0.0 para sa liwanag sa eksena. Mga ilaw ( kung light.type == ambient ( i += light.intensity ) iba pa ( kung light.type == point ( L = light. posisyon - P t_max = 1 ) iba pa ( L = light.direction t_max = inf ) # Suriin ang shadow shadow_sphere, shadow_t = ClosestIntersection(P, L, 0.001, t_max) kung shadow_sphere != NULL continue # Diffusion n_dot_l = tuldok(N, L ) kung n_dot_l > 0 i += light.intensity*n_dot_l/(length(N)*length(L)) # Specularity if s != -1 ( R = 2*N*dot(N, L) - L r_dot_v = tuldok(R, V) kung r_dot_v > 0 i += light.intensity*pow(r_dot_v/(length(R)*length(V)), s) ) ) ) return i )
Ito ang magiging hitsura ng aming muling na-render na eksena:


Source code at gumaganang demo >>

Ngayon May ginagawa na kami.

Pagninilay

Mayroon kaming makintab na mga bagay. Ngunit posible bang lumikha ng mga bagay na talagang kumikilos tulad ng mga salamin? Siyempre, ang kanilang pagpapatupad sa isang ray tracer ay talagang napaka-simple, ngunit maaari itong tila nakakalito sa simula.

Tingnan natin kung paano gumagana ang mga salamin. Kapag tumitingin tayo sa salamin, nakikita natin ang mga sinag ng liwanag na sinasalamin mula sa salamin. Ang mga ilaw na sinag ay sinasalamin nang simetriko na may kaugnayan sa normal na ibabaw:

Sabihin nating may sinag tayo at ang pinakamalapit na intersection ay salamin. Anong kulay ang sinag ng liwanag? Malinaw, hindi ito ang kulay ng salamin, ngunit anumang kulay na mayroon ang sinasalamin na sinag. Ang kailangan lang nating gawin ay kalkulahin ang direksyon ng sinasalamin na sinag at alamin kung ano ang kulay ng liwanag na nagmumula sa direksyong iyon. Kung mayroon lang tayong function na bumalik, para sa isang naibigay na sinag, ang kulay ng liwanag na bumabagsak mula sa direksyong iyon...

Oh teka, mayroon kaming isa: ito ay tinatawag na TraceRay.

Kaya magsisimula kami sa pangunahing TraceRay loop upang makita kung ano ang "nakikita" ng ray na ibinubuga mula sa camera. Kung matukoy ng TraceRay na ang ray ay nakakakita ng isang reflective object, kailangan lang nitong kalkulahin ang direksyon ng reflected ray at tawagan... mismo.

Sa puntong ito, iminumungkahi kong basahin mong muli ang huling tatlong talata hanggang sa maunawaan mo ang mga ito. Kung ito ang iyong unang pagkakataon na magbasa tungkol sa recursive ray tracing, maaaring kailanganin mong basahin ito ng ilang beses at mag-isip bago ka talaga maiintindihan mo.

Take your time, maghihintay ako.

Ngayon na ang euphoria ng kahanga-hangang sandali na ito Eureka! natulog ng kaunti, pormalin natin ito ng kaunti.

Ang pinakamahalagang bagay sa lahat ng recursive algorithm ay upang maiwasan ang isang walang katapusang loop. Ang algorithm na ito ay may malinaw na kondisyon sa paglabas: kapag ang sinag ay tumama sa isang bagay na hindi sumasalamin, o kapag wala itong natamaan. Ngunit mayroong isang simpleng kaso kung saan maaari tayong mahuli sa isang walang katapusang loop: ang epekto walang katapusang koridor. Nagpapakita ito kapag naglagay ka ng salamin sa harap ng isa pang salamin at nakakita ng walang katapusang mga kopya ng iyong sarili sa mga ito!

Mayroong maraming mga paraan upang maiwasan ang problemang ito. Papasok kami limitasyon ng recursion algorithm; kokontrolin niya ang "depth" kung saan siya makakapunta. Tawagan natin ito. Kapag , nakikita natin ang mga bagay, ngunit walang mga reflection. Kapag nakakita tayo ng ilang bagay at repleksyon ng ilang bagay. Kapag nakikita natin ang ilang mga bagay, mga pagmuni-muni ng ilang mga bagay at repleksyon ng ilang repleksyon ng ilang bagay. At iba pa. Sa pangkalahatan, hindi espesyal na kahulugan pumunta ng mas malalim kaysa sa 2-3 mga antas, dahil sa yugtong ito ang pagkakaiba ay halos hindi kapansin-pansin.

Gagawa tayo ng isa pang pagkakaiba. Hindi kailangang nangangahulugang "oo o hindi" ang "pagniningning"—ang mga bagay ay maaaring bahagyang mapanimdim at bahagyang may kulay. Magtatalaga kami sa bawat ibabaw ng isang numero mula hanggang , na tumutukoy sa pagiging mapanimdim nito. Pagkatapos nito ay paghaluin namin ang lokal na iluminado na kulay at ang masasalamin na kulay sa proporsyon sa numerong ito.

Sa wakas, kailangan nating magpasya kung anong mga parameter ang dapat matanggap ng recursive na tawag sa TraceRay? Ang sinag ay nagsisimula mula sa ibabaw ng bagay, isang punto. Ang direksyon ng sinag ay ang direksyon ng liwanag na sinasalamin mula sa ; sa TraceRay mayroon kaming , iyon ay, ang direksyon mula sa camera hanggang , kabaligtaran sa paggalaw ng liwanag, iyon ay, ang direksyon ng sinasalamin na sinag ay makikita na may kaugnayan sa . Katulad ng kung ano ang nangyayari sa mga anino, hindi namin gustong ipakita ng mga bagay ang kanilang mga sarili, kaya . Gusto naming makita ang mga bagay na nakalarawan kahit gaano kalayo ang mga ito, kaya . At panghuli, ang limitasyon ng recursion ay mas mababa ng isa kaysa sa limitasyon ng recursion na kasalukuyan nating nararanasan.

Pag-render na may pagmuni-muni

Magdagdag tayo ng reflection sa ray tracer code.

Tulad ng dati, una sa lahat ay binago natin ang eksena:

Sphere ( center = (0, -1, 3) radius = 1 color = (255, 0, 0) # Red specular = 500 # Shiny reflective = 0.2 # Bahagyang mapanimdim ) sphere ( center = (-2, 1, 3) radius = 1 kulay = (0, 0, 255) # Blue specular = 500 # Makintab na mapanimdim = 0.3 # Bahagyang mas mapanimdim ) sphere ( center = (2, 1, 3) radius = 1 kulay = (0, 255, 0) # Green specular = 10 # Medyo makintab na mapanimdim = 0.4 # Mas mapanimdim ) sphere ( color = (255, 255, 0) # Yellow center = (0, -5001, 0) radius = 5000 specular = 1000 # Very shiny reflective = 0.5# Half reflective)
Ginagamit namin ang formula na "reflection ray" sa ilang lugar, para maalis namin ito. Natatanggap nito ang sinag at ang normal, ibinabalik ang sinasalamin na kamag-anak:

ReflectRay(R, N) ( return 2*N*dot(N, R) - R; )
Ang tanging pagbabago sa ComputeLighting ay ang pagpapalit sa reflection equation ng isang tawag sa bagong ReflectRay na ito.

Isang maliit na pagbabago ang ginawa sa pangunahing pamamaraan - kailangan nating ipasa ang pinakamataas na antas ng TraceRay ng limitasyon sa pag-uulit:

Kulay = TraceRay(O, D, 1, inf, recursion_depth)
Ang recursion_depth constant ay maaaring itakda makatwirang halaga, halimbawa 3 o 5.

Ang tanging mahahalagang pagbabago ay nangyayari malapit sa dulo ng TraceRay, kung saan paulit-ulit naming kinakalkula ang mga reflection:

TraceRay(O, D, t_min, t_max, depth) ( closest_sphere, closest_t = ClosestIntersection(O, D, t_min, t_max) kung closest_sphere == NULL return BACKGROUND_COLOR # Kalkulahin ang lokal na kulay P = O + pinakamalapit_t*D # Kalkulahin ang intersection point N = P - pinakamalapit na_sphere.center # Compute ang normal sa sphere sa intersection point N = N / length(N) local_color = closest_sphere.color*ComputeLighting(P, N, -D, sphere.specular) # Kung naabot na namin ang recursion limit o hindi reflective ang object, tapos na kami r = closest_sphere.reflective kung depth<= 0 or r <= 0: return local_color # Вычисление отражённого цвета R = ReflectRay(-D, N) reflected_color = TraceRay(P, R, 0.001, inf, depth - 1) return local_color*(1 - r) + reflected_color*r }
Hayaang magsalita ang mga resulta para sa kanilang sarili:

Para mas maunawaan ang limitasyon sa lalim ng recursion, tingnan natin ang pag-render gamit ang:

At narito ang parehong naka-zoom-in na view ng parehong eksena, sa pagkakataong ito ay nai-render sa :

Tulad ng nakikita mo, ang pagkakaiba ay kung nakikita natin ang mga pagmuni-muni ng mga pagmuni-muni ng mga bagay, o mga pagmuni-muni lamang ng mga bagay.

Custom na camera

Sa simula pa lang ng aming talakayan tungkol sa ray tracing, gumawa kami ng dalawang mahalagang pagpapalagay: ang camera ay naka-fix at nakaturo sa, at ang "pataas" na direksyon ay . Sa seksyong ito, aalisin natin ang mga paghihigpit na ito upang mailagay natin ang camera saanman sa eksena at ituro ito sa anumang direksyon.

Magsimula tayo sa posisyon. Maaaring napansin mo na isang beses lang itong ginagamit sa buong pseudocode: bilang panimulang punto ng mga sinag na nagmumula sa camera sa top-level na pamamaraan. Kung gusto nating baguhin ang posisyon ng camera. yun ang tanging bagay ang kailangan mong gawin ay gumamit ng ibang halaga para sa .

Nakakaapekto ba ang pagbabago mga probisyon sa direksyon sinag? Hindi sa anumang paraan. Ang direksyon ng mga sinag ay ang vector na dumadaan mula sa camera patungo sa projection plane. Kapag ginalaw namin ang camera, gumagalaw ang projection plane kasama ang camera, ibig sabihin ay hindi nagbabago ang kanilang mga kamag-anak na posisyon.

Ibaling natin ngayon ang ating atensyon sa direksyon. Sabihin nating mayroon tayong rotation matrix na lumiliko sa nais na direksyon ng pagtingin, at - sa nais na "pataas" na direksyon (at dahil ito ay isang rotation matrix, sa pamamagitan ng kahulugan ay dapat itong gawin kung ano ang kinakailangan para sa ). Posisyon Hindi nagbabago ang camera kung paikutin mo lang ang camera. Ngunit nagbabago ang direksyon, sumasailalim lamang ito sa parehong pag-ikot ng buong camera. Iyon ay, kung mayroon kaming isang direksyon at isang rotation matrix, kung gayon ang pinaikot ay simple.

Tanging ang pinakamataas na antas ng function ang nagbabago:

Para sa x sa [-Cw/2, Cw/2] ( para sa y sa [-Ch/2, Ch/2] ( D = camera.rotation * CanvasToViewport(x, y) color = TraceRay(camera.position, D, 1, inf) canvas.PutPixel(x, y, kulay) ) )
Ganito ang hitsura ng aming eksena kapag tiningnan mula sa ibang posisyon at oryentasyon:

Kung saan ang susunod na pupuntahan

Tatapusin natin ang unang bahagi ng papel na may maikling pangkalahatang-ideya ng ilang kawili-wiling paksa na hindi pa natin ginalugad.

Pag-optimize

Gaya ng nakasaad sa panimula, tinitingnan namin ang pinakanaiintindihan na paraan upang ipaliwanag at ipatupad ang iba't ibang posibilidad. Samakatuwid, ang ray tracer ay ganap na gumagana, ngunit hindi partikular na mabilis. Narito ang ilang ideya na maaari mong tuklasin nang mag-isa para mapabilis ang iyong tracer. Para lamang sa kasiyahan, subukang sukatin ang oras ng pagpapatupad bago at pagkatapos ipatupad ang mga ito. Magugulat ka talaga!

Parallelization

Ang pinaka-halatang paraan upang mapabilis ang isang ray tracer ay ang pagsubaybay ng maraming sinag nang sabay-sabay. Dahil ang bawat ray na nagmumula sa camera ay independiyente sa lahat ng iba, at karamihan sa mga istruktura ay read-only, maaari nating masubaybayan ang isang ray sa bawat core ng CPU nang walang labis na kahirapan o kumplikado dahil sa mga isyu sa timing.

Sa katunayan, ang mga ray tracer ay kabilang sa isang klase ng mga algorithm na tinatawag lubhang kahanay tiyak dahil ang kanilang likas na katangian ay ginagawang napakadaling iparallelize ang mga ito.

Mga halaga ng pag-cache

Isaalang-alang ang mga halaga na kinakalkula ng IntersectRaySphere, kung saan karaniwang ginugugol ng ray tracer ang halos lahat ng oras nito:

K1 = tuldok(D, D) k2 = 2*tuldok(OC, D) k3 = tuldok(OC, OC) - r*r
Ang ilan sa mga value na ito ay pare-pareho sa buong eksena - kapag alam mo na kung paano nakaposisyon ang mga sphere, hindi na magbabago ang r*r at dot(OC, OC). Maaari mong kalkulahin ang mga ito nang isang beses habang naglo-load ng eksena at iimbak ang mga ito sa mga sphere mismo; kailangan mo lang itong bilangin kung ang mga sphere ay kailangang lumipat sa susunod na frame. dot(D, D) ay isang pare-pareho para sa isang naibigay na ray, kaya maaari mong kalkulahin ito sa ClosestIntersection at ipasa ito sa IntersectRaySphere .

Mga pag-optimize ng anino

Kung ang isang punto sa isang bagay ay nasa anino na may kaugnayan sa pinagmumulan ng liwanag dahil may ibang bagay na nakita sa daan, kung gayon ay may mataas na posibilidad na ang puntong katabi nito ay nasa anino din na may kaugnayan sa pinagmumulan ng liwanag dahil sa parehong bagay ( ito ay tinatawag na pagkakapare-pareho ng mga anino):

Ibig sabihin, kapag naghahanap tayo ng mga bagay sa pagitan ng isang punto at isang pinagmumulan ng liwanag, maaari muna nating suriin kung ang huling bagay na naglagay ng anino sa nakaraang punto na nauugnay sa parehong pinagmumulan ng liwanag ay naglalagay ng anino sa kasalukuyang punto. Kung gayon, pagkatapos ay maaari naming tapusin; kung hindi, pagkatapos ay patuloy lang naming suriin ang natitirang mga bagay sa karaniwang paraan.

Gayundin, kapag kinakalkula ang intersection sa pagitan ng isang sinag ng liwanag at mga bagay sa eksena, hindi talaga namin kailangan ang pinakamalapit na intersection - alam lang na mayroong kahit isang intersection. Maaari kaming gumamit ng isang espesyal na bersyon ng ClosestIntersection na nagbabalik ng resulta sa sandaling mahanap nito ang unang intersection (at para dito kailangan naming kalkulahin at ibalik hindi ang closest_t, ngunit isang boolean na halaga lamang).

Mga istrukturang spatial

Ang pagkalkula ng intersection ng ray sa bawat globo ay isang malaking pag-aaksaya ng mga mapagkukunan. Mayroong maraming mga istruktura ng data na nagbibigay-daan sa iyo upang itapon ang buong pangkat ng mga bagay sa isang mabilis na paglilipat nang hindi kinakailangang kalkulahin ang mga indibidwal na interseksyon.

Ang isang detalyadong pagsasaalang-alang sa mga naturang istruktura ay lampas sa saklaw ng aming artikulo, ngunit ang pangkalahatang ideya ay ito: ipagpalagay na mayroon kaming ilang mga sphere na malapit sa isa't isa. Maaari nating kalkulahin ang sentro at radius ng pinakamaliit na globo na naglalaman ng lahat ng mga globo na ito. Kung ang ray ay hindi bumalandra sa hangganang globo na ito, maaari mong tiyakin na hindi ito bumalandra sa anumang nakapaloob na globo, at ito ay maaaring gawin sa isang intersection check. Siyempre, kung nag-intersect ito sa isang globo, kailangan pa rin nating suriin kung nag-intersect ito sa alinman sa mga globo na nilalaman nito.

Maaari kang matuto nang higit pa tungkol dito sa pamamagitan ng pagbabasa tungkol sa hierarchy ng mga bounding volume.

Downsampling

Narito ang isang simpleng paraan upang gawing mas mabilis ang isang ray tracer: kalkulahin ang mga beses na mas kaunting mga pixel!

Sabihin nating sinusubaybayan natin ang mga ray para sa mga pixel at , at nahuhulog ang mga ito sa isang bagay. Maaari mong lohikal na ipagpalagay na ang ray para sa pixel ay mahuhulog din sa parehong bagay, laktawan ang paunang paghahanap para sa mga intersection sa buong eksena, at direktang pumunta sa pagkalkula ng kulay sa puntong iyon.

Kung gagawin mo ito sa pahalang at patayong direksyon, maaari kang magsagawa ng maximum na 75% na mas kaunting paunang pagkalkula ng intersection ng ray-scene.

Siyempre, madali itong makaligtaan ng isang napaka banayad na bagay: hindi tulad ng mga tinalakay kanina, ito ang "maling" pag-optimize, dahil ang mga resulta ng paggamit nito ay hindi. magkapareho sa kung ano ang matatanggap sana natin kung wala ito; sa isang kahulugan, tayo ay "dinadaya" sa mga pagtitipid na ito. Ang lansihin ay hulaan kung paano mag-save ng tama habang tinitiyak ang kasiya-siyang resulta.

Iba pang mga primitive

Sa mga nakaraang seksyon, ginamit namin ang mga sphere bilang mga primitive dahil madali silang manipulahin mula sa isang mathematical point of view. Ngunit sa pagkamit nito, maaari ka lamang magdagdag ng iba pang mga primitive.

Tandaan na mula sa pananaw ng TraceRay, maaaring gamitin ang anumang bagay hangga't dalawang value lang ang kailangang kalkulahin para dito: ang halaga para sa pinakamalapit na intersection sa pagitan ng ray at object, at ang normal sa intersection point. Ang lahat ng iba pa sa ray tracer ay hindi nakasalalay sa uri ng bagay.

Ang mga tatsulok ay isang mahusay na pagpipilian. Una kailangan mong kalkulahin ang intersection sa pagitan ng ray at ng eroplano na naglalaman ng tatsulok, at kung mayroong isang intersection, pagkatapos ay matukoy kung ang punto ay nasa loob ng tatsulok.

Nakabubuo block geometry

Mayroong isang napaka-kagiliw-giliw na uri ng bagay na medyo madaling ipatupad: isang Boolean na operasyon sa pagitan ng iba pang mga bagay. Halimbawa, ang intersection ng dalawang sphere ay maaaring lumikha ng isang bagay na mukhang isang lens, habang ang pagbabawas ng isang maliit na globo mula sa isang mas malaking globo ay maaaring lumikha ng isang bagay na kahawig ng Death Star.

Paano ito gumagana? Para sa bawat bagay, maaaring kalkulahin ang mga lokasyon kung saan pumapasok at lumabas ang sinag sa bagay; halimbawa, sa kaso ng isang globo, ang sinag ay pumapasok at lalabas sa . Sabihin nating kailangan nating kalkulahin ang intersection ng dalawang sphere; ang ray ay nasa loob ng intersection kapag nasa loob ito ng magkabilang globo, at nasa labas sa kabaligtaran na kaso. Sa kaso ng pagbabawas, ang sinag ay nasa loob kapag ito ay nasa loob ng unang bagay, ngunit hindi sa loob ng pangalawa.

Sa pangkalahatan, kung gusto nating kalkulahin ang intersection sa pagitan ng ray at (nasaan ang anumang Boolean operator), kailangan muna nating hiwalay na kalkulahin ang intersection ng ray- at ray- , na nagbibigay sa atin ng "internal" na pagitan ng bawat bagay at . Pagkatapos ay sinusuri namin ang , na nasa pagitan ng "panloob" . Kailangan lang nating hanapin ang unang halaga na nasa "panloob" na pagitan at ang pagitan na interesado sa atin:

Ang normal sa intersection point ay alinman sa normal ng bagay na lumilikha ng intersection o ang kabaligtaran nito, depende sa kung tayo ay tumitingin mula sa "labas" o "mula sa loob" ng orihinal na bagay.

Siyempre, hindi nila kailangang maging primitive; sila mismo ay maaaring ang mga resulta ng mga pagpapatakbo ng Boolean! Kung ipapatupad natin ito nang malinis, hindi na natin kailangang malaman paano ang mga ito ay hangga't maaari tayong makakuha ng mga intersection at normal mula sa kanila. Kaya, maaari kang kumuha ng tatlong sphere at kalkulahin, halimbawa, .

Aninaw

Hindi lahat ng bagay ay kailangang maging opaque; ang ilan ay maaaring bahagyang transparent.

Ang pagpapatupad ng transparency ay halos kapareho sa pagpapatupad ng reflection. Kapag ang isang sinag ay bumagsak sa isang bahagyang transparent na ibabaw, kami, tulad ng dati, ay kinakalkula ang lokal at sinasalamin na kulay, ngunit kinakalkula din namin ang isang karagdagang kulay - ang kulay ng liwanag na dumadaan. sa pamamagitan ng ang bagay na nakuha ng isa pang tawag sa TraceRay. Pagkatapos ay kailangan mong ihalo ang kulay na ito sa mga lokal at nakalarawan na mga kulay, na isinasaalang-alang ang transparency ng bagay, at iyon na.

Repraksyon

Sa totoong buhay, kapag ang isang sinag ng liwanag ay dumaan sa isang transparent na bagay, ito ay nagbabago ng direksyon (kaya naman kapag ang isang dayami ay inilubog sa isang baso ng tubig, ito ay lumilitaw na "sira"). Ang pagbabago ng direksyon ay nakasalalay sa refractive index bawat materyal ayon sa sumusunod na equation:
Saan at ang mga anggulo sa pagitan ng sinag at ng normal bago at pagkatapos magsalubong sa ibabaw, at at ang mga indeks ng repraktibo ng materyal sa labas at loob ng mga bagay.

Halimbawa, tinatayang katumbas ng , at tinatayang katumbas ng . Iyon ay, para sa isang sinag na pumapasok sa tubig sa isang anggulo na nakukuha natin




Huminto saglit at mapagtanto: kung magpapatupad ka ng constructive block geometry at transparency, maaari kang magmodelo ng magnifying glass (ang intersection ng dalawang sphere) na kumikilos na parang isang wastong magnifying glass!

Supersampling

Ang supersampling ay halos kabaligtaran ng subsampling, kung saan nagsusumikap kami para sa katumpakan sa halip na bilis. Ipagpalagay na ang mga sinag na tumutugma sa dalawang magkatabing pixel ay nahuhulog sa dalawang magkaibang bagay. Kailangan nating kulayan ang bawat pixel ng naaangkop na kulay.

Gayunpaman, huwag kalimutan ang tungkol sa pagkakatulad kung saan kami nagsimula: ang bawat sinag ay dapat magtakda ng "pagtukoy" ng kulay ng bawat isa parisukat"grid" kung saan tayo tumitingin. Gamit ang isang ray sa bawat pixel, karaniwan naming napagpasyahan na ang kulay ng sinag ng liwanag na dumadaan sa gitna ng parisukat ay tumutukoy sa buong parisukat, ngunit maaaring hindi ito ang kaso.

Ang solusyon sa problemang ito ay ang pagsubaybay sa maraming ray bawat pixel - 4, 9, 16, atbp., at pagkatapos ay i-average ang mga ito upang makuha ang kulay ng pixel.

Siyempre, ginagawa nitong 4, 9, o 16 na beses na mas mabagal ang ray tracer, sa parehong dahilan na ginagawang mas mabilis ng pag-downsampling. Sa kabutihang palad, mayroong isang kompromiso. Maaari naming ipagpalagay na ang mga katangian ng isang bagay ay nagbabago nang maayos sa ibabaw nito, ibig sabihin na ang paglabas ng 4 na ray sa bawat pixel na tumama sa parehong bagay sa bahagyang magkaibang mga punto ay hindi mapapabuti ang hitsura ng eksena. Samakatuwid, maaari tayong magsimula sa isang ray bawat pixel at ihambing ang mga kalapit na ray: kung mahulog ang mga ito sa iba pang mga bagay o ang kanilang kulay ay naiiba ng higit sa isang muling hinati na halaga ng threshold, pagkatapos ay ilalapat natin ang pixel subdivision sa pareho.

Ray tracer pseudocode

Nasa ibaba ang kumpletong bersyon ng pseudocode na ginawa namin sa mga kabanata ng ray tracing:

CanvasToViewport(x, y) ( return (x*Vw/Cw, y*Vh/Ch, d) ) ReflectRay(R, N) ( return 2*N*dot(N, R) - R; ) ComputeLighting(P, N, V, s) ( i = 0.0 para sa liwanag sa eksena. Mga ilaw ( kung light.type == ambient ( i += light.intensity ) iba pa ( kung light.type == point ( L = light.position - P t_max = 1 ) iba pa ( L = light.direction t_max = inf ) # Sinusuri ang mga anino shadow_sphere, shadow_t = ClosestIntersection(P, L, 0.001, t_max) kung shadow_sphere != NULL continue # Diffusion n_dot_l = dot(N, L) kung n_dot_l > 0 i += light.intensity*n_dot_l/(length(N)*length(L)) # Shine if s != -1 ( R = ReflectRay(L, N) r_dot_v = dot(R, V) kung r_dot_v > 0 i += light.intensity*pow(r_dot_v/(length(R)*length(V)), s) ) ) return i ) ClosestIntersection(O, D, t_min, t_max) (clost_t = inf closest_sphere = NULL para sa globo sa scene.Spheres ( t1, t2 = IntersectRaySphere(O, D, sphere) kung t1 sa at t1< closest_t closest_t = t1 closest_sphere = sphere if t2 in and t2 < closest_t closest_t = t2 closest_sphere = sphere } return closest_sphere, closest_t } TraceRay(O, D, t_min, t_max, depth) { closest_sphere, closest_t = ClosestIntersection(O, D, t_min, t_max) if closest_sphere == NULL return BACKGROUND_COLOR # Вычисление локального цвета P = O + closest_t*D # Вычисление точки пересечения N = P - closest_sphere.center # Вычисление нормали сферы в точке пересечения N = N / length(N) local_color = closest_sphere.color*ComputeLighting(P, N, -D, sphere.specular) # Если мы достигли предела рекурсии или объект не отражающий, то мы закончили r = closest_sphere.reflective if depth <= 0 or r <= 0: return local_color # Вычисление отражённого цвета R = ReflectRay(-D, N) reflected_color = TraceRay(P, R, 0.001, inf, depth - 1) return local_color*(1 - r) + reflected_color*r } for x in [-Cw/2, Cw/2] { for y in [-Ch/2, Ch/2] { D = camera.rotation * CanvasToViewport(x, y) color = TraceRay(camera.position, D, 1, inf) canvas.PutPixel(x, y, color) } }
At narito ang eksenang ginamit upang i-render ang mga halimbawa:

Viewport_size = 1 x 1 projection_plane_d = 1 sphere ( center = (0, -1, 3) radius = 1 color = (255, 0, 0) # Red specular = 500 # Shiny reflective = 0.2 # Bahagyang mapanimdim ) sphere ( center = (-2, 1, 3) radius = 1 kulay = (0, 0, 255) # Blue specular = 500 # Makintab na mapanimdim = 0.3 # Bahagyang mas mapanimdim ) sphere ( center = (2, 1, 3) radius = 1 kulay = (0. 5000 specular = 1000 # Very shiny reflective = 0.5 # Half reflective ) light ( type = ambient intensity = 0.2 ) light ( type = point intensity = 0.6 position = (2, 1, 0) ) light ( type = directional intensity = 0.2 direksyon = (1, 4, 4) )

Mga Tag: Magdagdag ng mga tag

Direktang pagsubaybay. Sa direktang paraan ng pagsubaybay, ang isang sinag ng mga sinag ay nabuo, na iniiwan ang pinagmulan sa lahat ng posibleng direksyon.

Karamihan sa mga sinag na ibinubuga ng pinagmulan ay hindi umaabot sa tatanggap, at samakatuwid ay hindi nakakaapekto sa imahe na nabuo dito. Isang napakaliit na bahagi lamang ng mga sinag, pagkatapos ng lahat ng mga pagmuni-muni at repraksyon, sa kalaunan ay nakarating sa receiver, na lumilikha ng isang imahe ng eksena sa mga receptor nito. Sa magaspang na ibabaw, maraming diffusely reflected ray ang lumilitaw. Ang lahat ng mga ito ay kailangang mabuo at masubaybayan sa pamamagitan ng program, na lubos na nagpapalubha sa gawain sa pagsubaybay.

Ang pagpasa ng isang sinag sa isang di-ideal na daluyan ay sinamahan ng pagkalat at pagsipsip ng liwanag na enerhiya sa mga microparticle nito. Ang mga pisikal na prosesong ito ay napakahirap na imodelo nang sapat sa isang computer na may limitadong mapagkukunan ng computing. Sa pagsasagawa, limitado ang mga ito sa paggamit ng attenuation coefficient ng enerhiya ng sinag sa bawat yunit ng distansya na nilakbay nito. Katulad nito, ang mga koepisyent ng pagbawas ng enerhiya ng sinag sa panahon ng pagmuni-muni at repraksyon nito sa interface sa pagitan ng media ay ipinakilala. Isinasaalang-alang ang mga coefficient na ito, ang pagbaba sa enerhiya ng lahat ng pangunahin at pangalawang sinag sa proseso ng kanilang paggala sa espasyo ng eksena ay sinusubaybayan. Sa sandaling ang enerhiya ng isang tiyak na sinag ay nagiging mas mababa sa isang tiyak na antas ng ganap o bumaba sa isang tiyak na bilang ng mga beses, ang pagsubaybay sa sinag na ito ay hihinto.

Kaya, ang pangunahing Mga disadvantages ng direct tracing method ay ang mataas na lakas ng paggawa at mababang kahusayan. Kapag ipinapatupad ang pamamaraan, ang karamihan sa mga gawain sa pagkalkula ng mga intersection ng mga sinag na may mga bagay ay lumabas na walang kabuluhan.

Backtrace. Ang pamamaraan ng traceback ay binuo noong 80s. Ang mga gawa nina Whitted at Kay ay itinuturing na pangunahing.

Upang putulin ang mga sinag na hindi umaabot sa tatanggap, sapat na upang isaalang-alang ang tagamasid bilang isang mapagkukunan ng mga sinag ng pagbabalik. Ang pangunahing sinag ay ituturing na sinag V mula sa nagmamasid hanggang sa anumang punto sa ibabaw ng bagay.

Gamit ang mga pamamaraan na tinalakay sa itaas, kinakalkula ang pangalawa, tersiyaryo, atbp. sinag. Bilang isang resulta, para sa bawat pangunahing sinag, isang tracing tree ang itinayo, ang mga sanga na bumubuo sa pangalawang sinag. Ang sangay ng ruta ay magtatapos kung:

● ang sinag ay lumampas sa eksena,

● ang sinag ay nakakatugon sa isang malabo na katawan na sumisipsip ng liwanag,

● tumama ang sinag sa pinagmumulan ng liwanag,

● bumababa ang intensity ng beam sa ilalim ng threshold ng sensitivity,

● nagiging masyadong malaki ang bilang ng pangunahing beam split para sa mga available na mapagkukunan ng makina.

Ang nagresultang direktang liwanag na enerhiya (kulay at intensity) na pumapasok sa receiver mula sa direksyon V, ay binubuo ng mga energies ng mga terminal vertices ng puno, na isinasaalang-alang ang kanilang mga pagkalugi sa panahon ng pagpapalaganap sa optical media.


Ang traceback na paraan ay aktwal na nag-iipon ng lahat ng mga sinag na aktwal na dumarating sa receiver mula sa isang partikular na direksyon, anuman ang kanilang pinagmulan. Binibigyang-daan ka nitong makita at ipakita sa screen:

● mga opaque na bagay na sumisipsip ng return rays;

● mga transparent na bagay kung saan nakikita ng nagmamasid ang ibang mga bagay dahil sa repraksyon;

● mga pagmuni-muni ng mga bagay sa ibabaw ng salamin, kabilang ang liwanag na tumutugma sa mga sinag ng pabalik na tumatama sa pinagmumulan ng liwanag;

● mga anino na nabuo sa mga punto sa ibabaw na natatakpan mula sa pinagmulan ng iba pang mga bagay;

● iba't ibang mga optical effect.

Ang bilang ng "probing" return rays na napapailalim sa pagsubaybay ay nalilimitahan ng bilang ng mga puntos sa ibabaw ng mga eksenang bagay na nakikita mula sa lokasyon ng nagmamasid at inilipat nang may huling hakbang depende sa resolution ng screen. Dahil dito, ang halaga ng mga gastos sa computational sa paraan ng backward tracing ay makabuluhang nabawasan kumpara sa forward tracing method. Posibleng pagsamahin ang parehong mga pamamaraan upang i-optimize ang mga algorithm at bawasan ang pagiging kumplikado ng mga ito.

Ang mga algorithm ng pagsubaybay ay isang recursive na pamamaraan na tumatawag sa sarili nito kapag may lumabas na pangalawang ray (ang nasuri na ray ay makikita o na-refracte). Karamihan sa mga kalkulasyon sa pagpapatupad ng mga pamamaraan ng pagsubaybay ay nahuhulog sa pagkalkula ng mga intersection ng mga sinag na may mga ibabaw, at samakatuwid ay ginagamit ang mga ito upang ipakita ang mga optical effect sa mga eksena na may isang maliit na bilang ng mga bagay.

Sa praktikal na pagpapatupad ng paraan ng back tracing, ang mga sumusunod na paghihigpit ay ipinakilala . Ang ilan sa mga ito ay kinakailangan upang malutas ang problema ng synthesis ng imahe sa prinsipyo, at ang ilang mga paghihigpit ay maaaring makabuluhang taasan ang bilis ng pagsubaybay.

Mga limitasyon ng pamamaraan ng pag-traceback:

1. Sa lahat ng uri ng mga bagay, i-highlight natin ang mga pinagmumulan ng liwanag. Maaari lamang silang maglabas ng liwanag, ngunit hindi ito maipapakita o mai-refract. Karaniwang isinasaalang-alang ang mga mapagkukunan ng punto.

2. Ang mga katangian ng mapanimdim na mga ibabaw ay inilarawan sa pamamagitan ng kabuuan ng dalawang bahagi: nagkakalat at specular.

3. Ang specularity naman, ay inilalarawan din ng dalawang bahagi. Isinasaalang-alang ng una (pagsalamin) ang pagmuni-muni mula sa iba pang mga bagay na hindi pinagmumulan ng liwanag. Isang specularly reflected beam lang ang binuo r para sa karagdagang pagsubaybay. Ang pangalawang bahagi (specular) ay nangangahulugan ng liwanag na nagmumula sa mga pinagmumulan ng liwanag. Upang gawin ito, ang mga sinag ay nakadirekta sa lahat ng mga mapagkukunan, ang mga anggulo na nabuo ng mga sinag na ito na may salamin sa likod na tracing ray ay tinutukoy ( r). Sa mirroring, ang kulay ng isang surface point ay tinutukoy ng kulay ng kung ano ang ipinapakita. Sa pinakasimpleng kaso, ang salamin ay walang sariling kulay sa ibabaw.

4. Sa nagkakalat na pagmuni-muni, tanging mga sinag mula sa mga pinagmumulan ng liwanag ang isinasaalang-alang. Ang mga sinag mula sa specularly reflective surface ay hindi pinapansin. Kung ang sinag na nakadirekta sa isang ibinigay na pinagmumulan ng liwanag ay naharang ng isa pang bagay, kung gayon ang puntong ito ng bagay ay nasa anino. Sa pamamagitan ng nagkakalat na pagmuni-muni, ang kulay ng isang iluminado na punto sa isang ibabaw ay tinutukoy ng sariling kulay ng ibabaw at ang kulay ng mga pinagmumulan ng liwanag.

5. Para sa mga transparent na bagay, ang dependence ng refractive index sa wavelength ay karaniwang hindi isinasaalang-alang. Minsan ang transparency ay na-modelo nang walang repraksyon sa lahat, i.e. direksyon ng refracted ray t kasabay ng direksyon ng sinag ng insidente.

6. Upang isaalang-alang ang pag-iilaw ng mga bagay sa pamamagitan ng liwanag na nakakalat ng iba pang mga bagay, isang bahagi ng background (ambient) ay ipinakilala.

7. Upang makumpleto ang pagsubaybay, ipinakilala ang isang tiyak na halaga ng pag-iilaw ng threshold, na hindi na dapat mag-ambag sa resultang kulay, o limitado ang bilang ng mga pag-ulit.

Mga positibong tampok ng pamamaraan ng pag-traceback:

● versatility, applicability para sa synthesis ng imahe ng medyo kumplikadong spatial na eksena. Naglalaman ng maraming batas ng optika. Iba't ibang mga projection ay simpleng natanto;

● kahit na ang mga pinutol na bersyon ng paraang ito ay ginagawang posible na makakuha ng medyo makatotohanang mga larawan. Halimbawa, kung nililimitahan natin ang ating sarili sa mga pangunahing sinag lamang (mula sa projection point), magreresulta ito sa pag-aalis ng mga hindi nakikitang punto. Ang pagsubaybay sa isa o dalawang pangalawang sinag lamang ay nagbibigay ng mga anino, specularity, at transparency;

● lahat ng mga pagbabago sa coordinate (kung mayroon man) ay linear, kaya medyo madaling gamitin ang mga texture;

● para sa isang pixel ng isang raster na imahe, maaari mong subaybayan ang ilang malapit na pagitan ng mga ray, at pagkatapos ay i-average ang kanilang kulay upang maalis ang epekto ng aliasing;

● dahil ang pagkalkula ng isang punto ng imahe ay isinasagawa nang hiwalay sa iba pang mga punto, maaari itong epektibong magamit kapag ipinapatupad ang pamamaraang ito sa parallel computing system kung saan ang mga sinag ay maaaring masubaybayan nang sabay-sabay.

Mga disadvantages ng traceback method:

● mga problema sa pagmomodelo ng nagkakalat na pagmuni-muni at repraksyon;

● para sa bawat punto sa larawan ay kinakailangan na magsagawa ng maraming pagpapatakbo ng pagkalkula. Ang pagsubaybay sa ray ay isa sa pinakamabagal na algorithm ng synthesis ng imahe.