рдкреЛрд╕реНрдЯрдХрд╛рд░реНрдб рдХреЗ рдЖрдХрд╛рд░ рдХрд╛ рд░реЗ рдЯреНрд░реЗрд╕рд░ рдбрд┐рдХреНрд░рд┐рдкреНрд╢рди


"рдЙрдиреНрд╣реЛрдВрдиреЗ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдХрд┐рдпрд╛!" - рдкрд┐рдХреНрд╕рд░ рдлреНрд▓рд╛рдпрд░ [1] рдХреЗ рдкреАрдЫреЗ рджреЗрдЦрдиреЗ рдкрд░ рдпрд╣ рдкрд╣рд▓реА рдмрд╛рдд рд╣реИ, рдЬреЛ рдХреЛрдб рд╕реЗ рдкреВрд░реА рддрд░рд╣ рднрд░реА рд╣реБрдИ рдереАред рдПрдВрдбреНрд░рдпреВ рдХреЗрдиреНрд╕рд▓рд░ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рджреНрд╡рд╛рд░рд╛ рдирд┐рдЪрд▓реЗ рджрд╛рдПрдВ рдХреЛрдиреЗ рдореЗрдВ рдирд┐рд░реНрдорд╛рдг рдФрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдПрдХ рдХреНрд▓рд╕реНрдЯрд░ рдкрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд┐рдП рдЧрдП рдереЗред рдЬреЛ рд▓реЛрдЧ рдЙрд╕реЗ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рдЙрдирдХреЗ рд▓рд┐рдП рдореИрдВ рдХрд╣реВрдВрдЧрд╛: рдПрдВрдбреНрд░рдпреВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╣реИ, рдЬрд┐рд╕рдиреЗ 2009 рдореЗрдВ 1337-рдмрд╛рдЗрдЯ рдмрд┐рдЬрдиреЗрд╕ рдХрд╛рд░реНрдб рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рд░реЗ рдЯреНрд░реЗрд╕рд░ рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд┐рдпрд╛ рдерд╛ред

рдЗрд╕ рдмрд╛рд░, рдПрдВрдбреНрд░рдпреВ рдХреБрдЫ рдФрд░ рдЕрдзрд┐рдХ рдЪрдордХрджрд╛рд░ рдХреЗ рд╕рд╛рде рдЖрдпрд╛, рд▓реЗрдХрд┐рди рдмрд╣реБрдд рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рджреГрд╢реНрдп рдкрд░рд┐рдгрд╛рдо рдХреЗ рд╕рд╛рдеред рдЪреВрдВрдХрд┐ рдореИрдВрдиреЗ рд╡реБрд▓реНрдл 3 рдбреА рдФрд░ рдбреАрдУрдУрдПрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдкрдиреЗ рдЧреЗрдо рдЗрдВрдЬрди рдмреНрд▓реИрдХ рдмреБрдХреНрд╕ рдХреЛ рд▓рд┐рдЦрдирд╛ рд╕рдорд╛рдкреНрдд рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореЗрд░реЗ рдкрд╛рд╕ рдЗрд╕рдХреЗ рдЧреВрдврд╝ рдХреЛрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордп рдерд╛ред рдФрд░ рд▓рдЧрднрдЧ рддреБрд░рдВрдд, рдореИрдВ рд╕рдЪрдореБрдЪ рдЙрд╕рдХреА рдЦреЛрдЬ рдХреА рдЧрдИ рддрдХрдиреАрдХреЛрдВ рд╕реЗ рдореЛрд╣рд┐рдд рд╣реЛ рдЧрдпрд╛ рдерд╛ред рд╡реЗ "рдорд╛рдирдХ" рдХрд┐рд░рдг рдЕрдиреБрд░реЗрдЦрдХ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдВрдбреНрд░рдпреВ рдХреЗ рдкрд┐рдЫрд▓реЗ рдХрд╛рдо рд╕реЗ рдмрд╣реБрдд рдЕрд▓рдЧ рдереЗред рдореБрдЭреЗ рд░реЗ рдорд╛рд░реНрдЪрд┐рдВрдЧ, рд░рдЪрдирд╛рддреНрдордХ рд╡реЙрд▓реНрдпреВрдореЗрдЯреНрд░рд┐рдХ рдЬреНрдпрд╛рдорд┐рддрд┐ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ, рдореЛрдВрдЯреЗ рдХрд╛рд░реНрд▓реЛ рд░реЗрдВрдбрд░рд┐рдВрдЧ / рдкрд╛рде рдЯреНрд░реЗрд╕рд┐рдВрдЧ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдХрдИ рдЕрдиреНрдп рдЯреНрд░рд┐рдХреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдкреА рдереА, рдЬреЛ рдЙрд╕рдиреЗ рдХрд╛рдЧрдЬ рдХреЗ рдЗрддрдиреЗ рдЫреЛрдЯреЗ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдХреЛрдб рдХреЛ рдирд┐рдЪреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдерд╛ред



рд╕реНрд░реЛрдд рдХреЛрдб




рдлреНрд▓рд╛рдпрд░ рдХреЗ рд╕рд╛рдордиреЗ рдкрд┐рдХреНрд╕рд░ рднрд░реНрддреА рд╡рд┐рднрд╛рдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдЬреНрдЮрд╛рдкрди рд╣реИред рд░рд┐рд╡рд░реНрд╕ рд╕рд╛рдЗрдб рдкрд░ C ++ рдХреЛрдб рдХреЗ 2,037 рдмрд╛рдЗрдЯреНрд╕ рдЫрдкреЗ рд╣реИрдВ, рдЬреЛ рдЫреЛрдЯреА рд╕реЗ рдЫреЛрдЯреА рд╕рдВрднрд╛рд╡рд┐рдд рд╕рддрд╣ рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╛рдзрд┐рдд рд╣реИред

#include <stdlib.h> // card > pixar.ppm #include <stdio.h> #include <math.h> #define R return #define O operator typedef float F;typedef int I;struct V{F x,y,z;V(F v=0){x=y=z=v;}V(F a,F b,F c=0){x=a;y=b;z=c;}V O+(V r){RV(x+rx,y+ry,z+rz);}VO*(V r){RV(x*rx,y*r. y,z*rz);}FO%(V r){R x*r.x+y*r.y+z*rz;}VO!(){R*this*(1/sqrtf(*this%*this) );}};FL(F l,F r){R l<r?l:r;}FU(){R(F)rand()/RAND_MAX;}FB(V p,V l,V h){l=p +l*-1;h=h+p*-1;RL(L(L(lx,hx),L(ly,hy)),L(lz,hz));}FS(V p,I&m){F d=1\ e9;V f=p;fz=0;char l[]="5O5_5W9W5_9_COC_AOEOA_E_IOQ_I_QOUOY_Y_]OWW[WaOa_aW\ eWa_e_cWiO";for(I i=0;i<60;i+=4){V b=V(l[i]-79,l[i+1]-79)*.5,e=V(l[i+2]-79,l [i+3]-79)*.5+b*-1,o=f+(b+e*L(-L((b+f*-1)%e/(e%e),0),1))*-1;d=L(d,o%o);}d=sq\ rtf(d);V a[]={V(-11,6),V(11,6)};for(I i=2;i--;){V o=f+a[i]*-1;d=L(d,ox>0?f\ absf(sqrtf(o%o)-2):(o.y+=oy>0?-2:2,sqrtf(o%o)));}d=powf(powf(d,8)+powf(pz, 8),.125)-.5;m=1;F r=L(-L(B(p,V(-30,-.5,-30),V(30,18,30)),B(p,V(-25,17,-25),V (25,20,25))),B(V(fmodf(fabsf(px),8),py,pz),V(1.5,18.5,-25),V(6.5,20,25))) ;if(r<d)d=r,m=2;F s=19.9-py;if(s<d)d=s,m=3;R d;}IM(V o,V d,V&h,V&n){I m,s= 0;F t=0,c;for(;t<100;t+=c)if((c=S(h=o+d*t,m))<.01||++s>99)R n=!V(S(h+V(.01,0 ),s)-c,S(h+V(0,.01),s)-c,S(h+V(0,0,.01),s)-c),m;R 0;}VT(V o,V d){V h,n,r,t= 1,l(!V(.6,.6,1));for(I b=3;b--;){I m=M(o,d,h,n);if(!m)break;if(m==1){d=d+n*( n%d*-2);o=h+d*.1;t=t*.2;}if(m==2){F i=n%l,p=6.283185*U(),c=U(),s=sqrtf(1-c), g=nz<0?-1:1,u=-1/(g+nz),v=nx*ny*u;d=V(v,g+ny*ny*u,-ny)*(cosf(p)*s)+V( 1+g*nx*nx*u,g*v,-g*nx)*(sinf(p)*s)+n*sqrtf(c);o=h+d*.1;t=t*.2;if(i>0&&M(h +n*.1,l,h,n)==3)r=r+t*V(500,400,100)*i;}if(m==3){r=r+t*V(50,80,100);break;}} R r;}I main(){I w=960,h=540,s=16;V e(-22,5,25),g=!(V(-3,4,0)+e*-1),l=!V(gz, 0,-gx)*(1./w),u(gy*lz-gz*ly,gz*lx-gx*lz,gx*ly-gy*lx);printf("P\ 6 %d %d 255 ",w,h);for(I y=h;y--;)for(I x=w;x--;){V c;for(I p=s;p--;)c=c+T(e ,!(g+l*(xw/2+U())+u*(yh/2+U())));c=c*(1./s)+14./241;V o=c+1;c=V(cx/ox,c. y/oy,cz/oz)*255;printf("%c%c%c",(I)cx,(I)cy,(I)cz);}}// Andrew Kensler 

рдХреНрдпрд╛ рд╡рд╣ рдХрд╛рдо рднреА рдХрд░рддрд╛ рд╣реИ?




рдХреЛрдб рдХреЗ рд╕рд╛рде рдЗрд╕рдХреЗ рд▓реЙрдиреНрдЪ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд░реНрджреЗрд╢ рд╣реИред рд╡рд┐рдЪрд╛рд░ рдорд╛рдирдХ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдХрд┐рд╕реА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╣реИред рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ, рд╣рдо рдорд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрд╡рд░реВрдк рдПрдХ рдкрд╛рда рдЫрд╡рд┐ рдкреНрд░рд╛рд░реВрдк рд╣реИ рдЬрд┐рд╕реЗ рдиреЗрдЯрдкреАрдмреАрдПрдо [2] рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред

  $ clang -o card2 -O3 raytracer.cpp
 $ рд╕рдордп ред/card> pixar.ppm

 рд╡рд╛рд╕реНрддрд╡рд┐рдХ 2m58.524
 рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ 2m57.567s
 sys 0m0.415s 

рджреЛ рдорд┐рдирдЯ рдФрд░ рдЕрдбрд╝рддрд╛рд▓реАрд╕ рд╕реЗрдХрдВрдб [3] рдХреЗ рдмрд╛рдж, рдирд┐рдореНрди рдЫрд╡рд┐ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИред рдпрд╣ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд╣реИ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрд┐рддрдирд╛ рдХрдо рдХреЛрдб рдЖрд╡рд╢реНрдпрдХ рд╣реИред


рдЖрдк рдКрдкрд░ рдХреА рдЫрд╡рд┐ рд╕реЗ рдмрд╣реБрдд рдХреБрдЫ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред рдЧреНрд░рд┐рдЯ рдПрдХ "рдкрде рдЕрдиреБрд░реЗрдЦрдХ" рдХрд╛ рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╕рдВрдХреЗрдд рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реЗрдВрдбрд░рд░ рдХрд┐рд░рдгреЛрдВ рд╕реЗ рдЕрд▓рдЧ рд╣реЛрддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░рдХрд╛рд╢ рд╕реНрд░реЛрддреЛрдВ рддрдХ рдХрд┐рд░рдгреЛрдВ рдХрд╛ рдкрддрд╛ рдирд╣реАрдВ рдЪрд▓рддрд╛ рд╣реИред рдЗрд╕ рдкрджреНрдзрддрд┐ рдореЗрдВ, рдкреНрд░рддрд┐ рдкрд┐рдХреНрд╕реЗрд▓ рд╣рдЬрд╛рд░реЛрдВ рдХрд┐рд░рдгреЗрдВ рд╕реНрд░реЛрддреЛрдВ рд╕реЗ рдЙрддреНрд╕рд░реНрдЬрд┐рдд рд╣реЛрддреА рд╣реИрдВ рдФрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдЙрдирдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддрд╛ рд╣реИ, рдЙрдореНрдореАрдж рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рдкреНрд░рдХрд╛рд╢ рд╕реНрд░реЛрдд рдкрд╛рдПрдВрдЧреЗред рдпрд╣ рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рддрдХрдиреАрдХ рд╣реИ, рдЬреЛ рдХрд┐рд░рдг рдЕрдиреБрд░реЗрдЦрдг рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдмреЗрд╣рддрд░ рд╣реИ, рдкрд░рд┐рд╡реЗрд╢ рд░реЛрдбрд╝рд╛, рдирд░рдо рдЫрд╛рдпрд╛, рдХрд╛рд╕реНрдЯрд┐рдХ, рдФрд░ рд░реЗрдбрд┐рдпреЛрд╕рд┐рдЯреА рдХреЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХрддрд╛ рд╣реИред

рд╣рдо рдХреЛрдб рдХреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ рддреЛрдбрд╝ рджреЗрдВрдЧреЗ




CLION рдореЗрдВ рдЗрдирдкреБрдЯ рдкрд╛рд╕ рдХрд░рдирд╛ рдХреЛрдб рдХреЛ рдкреНрд░рд╛рд░реВрдкрд┐рдд рдХрд░рддрд╛ рд╣реИ ( рдпрд╣рд╛рдВ рдЖрдЙрдЯрдкреБрдЯ рджреЗрдЦреЗрдВ) рдФрд░ рдЗрд╕реЗ рдЫреЛрдЯреЗ рднрд╛рдЧреЛрдВ / рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рддреЛрдбрд╝ рджреЗрддрд╛ рд╣реИред

  #include <stdlib.h> // card> pixar.ppm 
  # рдЕрд▓рдЧ рдХрд░реЗрдВ 
  # рдкрд┐рди рдХрд░реЗрдВ <math.h> 

  # рдбреЗрдлрд┐рди рдЖрд░ рд╡рд╛рдкрд╕реА 
  # рдУрдлрд┐рди рд╣реЗ рдСрдкрд░реЗрдЯрд░ 
  typedef float F; рдЯрд╛рдЗрдкрдбреАрдл int int I; 
  рд╕рдВрд░рдЪрдирд╛ V {F x, y, z; V (F v = 0) {x = y = z = v;} V (F a, F b, F 
  c = 0) {x = a; y = b; z = c;} V O + (V r) {RV (x + rx, y + ry, z + rz);} VO * (V r) {RV; x * рдЖрд░рдПрдХреНрд╕, рд╡рд╛рдИ * рдЖрд░ред 
  y, z * rz);} FO% (V r) {R x * r.x + y * r.y + z * rzред} VO! () {R * this * (1 / sqrtf (* this%) * рдпрд╣) 
  );}}; 
  FL (F l, F r) {R l <r? L: r;} FU () {R (F) рд░реИрдВрдб () / RAND_MAX;} FB (V p, V l, V h) {l = p 
  + l * -1; h = h + p * -1; RL (L (L (Lx, hx), L (ly, hy)), L (lz, hz));}; 
  FS (V p, I & m) {F d = 1 \ 
  e9; V f = p; fz = 0; char l [] = "5O5_5W9W5_9_COC_AOEOA_E_IOQ_I_QOUOY_Y_] OWW [WaOa_aW \ _ 
  eWa_e_cWiO "; рдХреЗ рд▓рд┐рдП (I i = 0; рдореИрдВ <60; рдореИрдВ + = 4) {V b = V (l [i] -79, l [i + 1] -79) *ред 5, e = V (l [] i + 2] -79, рдПрд▓ 
  [i + 3] -79) *ред 5 + рдмреА * -1, рдУ = рдПрдл + (рдмреА + рдИ * рдПрд▓ (рдПрд▓ - (рдмреА + рдПрдл * -1)% рдИ / (рдИ% рдИ), 0), 1)) * - 1; d = L (d, o% o);} d = sq \ _ 
  rtf (d); V a [] = {V (-11.6), V (11.6)}, рдХреЗ рд▓рд┐рдП (I i = 2; i -;) {V o = f + a [i] * -1; рдбреА = рдПрд▓ (рдбреА, рдСрдХреНрд╕> 0? рдПрдл * 
  absf (sqrtf (o% o) -2) :( o.y + = oy> 0; -2: 2, sqrtf (o% o));} d = powf (powf (d, 8) + powf (pz) ред 
  8), 125) -ред 5; рдПрдо = 1; рдПрдл рдЖрд░ = рдПрд▓ (рдПрд▓ (рдмреА (рдкреА, рд╡реА -30, - 5, -30), рд╡реА (30,18,30), рдмреАред (рдкреА, рд╡реА (-25.17, -25), рд╡реА 
  (25,20,25))), B (V (fmodf (fbsf) (px), 8), py, pz), V (1.5,18.5, -25), V (6.5,20,25)) 
  , рдЕрдЧрд░ (r <d) d = r, m = 2; F s = 19.9-py; рдЕрдЧрд░ (s <d) d = s, m = 3; R d;}; 
  IM (V o, V d, V & h, V & n) {I m, s = 
  0; рдПрдл рдЯреА = 0, рд╕реА; рдХреЗ рд▓рд┐рдП (?; рдЯреА <100; рдЯреА + = рд╕реА) рдЕрдЧрд░ ((рд╕реА = рдПрд╕ (рдПрдЪ = рдУ + рдбреА * рдЯреА, рдПрдо)) <ред 01 || ++ s> 99) рдЖрд░ n =! рд╡реА (рдПрд╕ (рдПрдЪ + рд╡реА (.01,0) 
  ), s) -c, S (h + V (0, .01), s) -c, S (h + V (0,0, .01), s) -c), m; R 0;} 
  рд╡реАрдЯреА (рд╡реА рдУ, рд╡реА рдбреА) {рд╡реА рдПрдЪ, рдПрди, рдЖрд░, рдЯреА = 
  1, l (! V (.6, .6,1)); рдХреЗ рд▓рд┐рдП (I b = 3; b -;) {I m = M (o, d, h, n); if (! M) рдмреНрд░реЗрдХ , рдЕрдЧрд░ (m == 1) {d = d + n * ( 
  n% d * -2); o = h + d * .1; t = t * .2;} рдЕрдЧрд░ (m == 2) {F i = n% l, p = 6.283185 * U (), c = U (), s = sqrtf (1-c), 
  g = nz <0? -1: 1, u = -1 / (g + nz), v = nx *y * u; d = V (v, g + ny * ny * u, -ny) * (cosf) (p) * s) + V ( 
  1 + g * nx * nx * u, g * v, -g * nx) * (sinf (p) * s) + n * sqrtf (c); o = h + d * .1; t = t *ред 2; рдпрджрд┐ (i> 0 && M (h) 
  + n * .1, l, h, n) == 3) r = r + t * V (500,400,400)) * i;} рдЕрдЧрд░ (m == 3) {r = r + t * V (50,80,100) ; рд╡рд┐рд░рд╛рдо;}} 
  R r;} 
  I рдореБрдЦреНрдп () {I w = 960, h = 540, s = 16; V e (-22,5,25), g =! (((-3,4,0) + e * -1), l =! рд╡реА (gz, 
  0, -gx) * (1./w), u (gy * lz-gz * ly, gz * lx-gx * lz, gx * ly-gy * lx); printf ("P \") 
  6% d% d 255 ", w, h); рдХреЗ рд▓рд┐рдП (I y = h; y -;) рдХреЗ рд▓рд┐рдП (I x = w; x -;) {V c; рдХреЗ рд▓рд┐рдП (I p = s; p- -;) рд╕реА = рд╕реА + рдЯреА (рдИ) 
  ; (g + l * (xw / 2 + U ()) + u * (yh / 2 + U ()))); c = c * (1./s) + 14. / 241; V o = c + 1; c = V (cx / ox, c) 
  y / oy, cz / oz) * 255; рдкреНрд░рд┐рдВрдЯрдл ("% c% c% c", (I) cx, (I) рд╕рд╛рдЗрдмрд░, (I) cz);}) 
  // рдПрдВрдбреНрд░рдпреВ рдХреЗрд╕рд▓рд░ 

рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрднрд╛рдЧ рдХреЛ рд╢реЗрд╖ рд▓реЗрдЦ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
тЦа - рд╕рд╛рдзрд╛рд░рдг рдЪрд╛рд▓, тЦа - рд╡реЗрдХреНрдЯрд░ рд╡рд░реНрдЧ, тЦа - рд╕рд╣рд╛рдпрдХ рдХреЛрдб, тЦа - рдбреЗрдЯрд╛рдмреЗрд╕, тЦа - рд░реЗ рдорд╛рд░реНрдЪрд┐рдВрдЧ, тЦа - рдирдореВрдирд╛, тЦа - рдореБрдЦреНрдп рдХреЛрдбред

#Define рдФрд░ typedef рдХреЗ рд╕рд╛рде рд╕рд╛рдорд╛рдиреНрдп рдЯреНрд░рд┐рдХ




рдХреЙрдорди рдЯреНрд░рд┐рдХреНрд╕ рдХреЛрдб рдХреА рдорд╛рддреНрд░рд╛ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП #define рдФрд░ typedef рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдпрд╣рд╛рдВ рд╣рдо рдПрдл = рдлреНрд▓реЛрдЯ, рдЖрдИ = рдЗрдВрдЯ, рдЖрд░ = рд░рд┐рдЯрд░реНрди, рдФрд░ рдУ = рдСрдкрд░реЗрдЯрд░ рдХреЛ рджрд░реНрд╢рд╛рддреЗ рд╣реИрдВред рд░рд┐рд╡рд░реНрд╕ рдЗрдВрдЬреАрдирд┐рдпрд░рд┐рдВрдЧ рддреБрдЪреНрдЫ рд╣реИред

рдХрдХреНрд╖рд╛ рд╡реА




рдЗрд╕рдХреЗ рдмрд╛рдж рдХрдХреНрд╖рд╛ V рдЖрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ Vec рдХрд╛ рдирд╛рдо рджрд┐рдпрд╛ (рднрд▓реЗ рд╣реА, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдиреАрдЪреЗ рджреЗрдЦреЗрдВрдЧреЗ, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ RGB рдЪреИрдирд▓ рдХреЛ рдлрд╝реНрд▓реЛрдЯ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред

 struct Vec { float x, y, z; Vec(float v = 0) { x = y = z = v; } Vec(float a, float b, float c = 0) { x = a; y = b; z = c;} Vec operator+(Vec r) { return Vec(x + rx, y + ry, z + rz); } Vec operator*(Vec r) { return Vec(x * rx, y * ry, z * rz); } // dot product float operator%(Vec r) { return x * rx + y * ry + z * rz; } // inverse square root Vec operator!() {return *this * (1 / sqrtf(*this % *this) );} }; 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХреЛрдИ рдШрдЯрд╛рд╡ рдСрдкрд░реЗрдЯрд░ (-) рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП "X = A - B" рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрдЬрд╛рдп, "X = A + B * -1" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрд▓рдЯрд╛ рд╡рд░реНрдЧрдореВрд▓ рдмрд╛рдж рдореЗрдВ рд╡реИрдХреНрдЯрд░ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдЖрддрд╛ рд╣реИред

рдореБрдЦреНрдп рд╕рдорд╛рд░реЛрд╣




main () рдПрдХрдорд╛рддреНрд░ рдРрд╕рд╛ рдЪрд░рд┐рддреНрд░ рд╣реИ рдЬрд┐рд╕реЗ рдмрд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕реЗ libc рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ _start рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред рдкрд╣рд▓реЗ рдкрддреНрд░реЛрдВ рдХреЗ рдЕрд░реНрде рдирд┐рдХрд╛рд▓рдиреЗ рдореЗрдВ рдореБрдЭреЗ рдереЛрдбрд╝рд╛ рд╕рдордп рд▓рдЧрд╛, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдХреБрдЫ рдкрдардиреАрдп рдмрдирд╛рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред

 int main() { int w = 960, h = 540, samplesCount = 16; Vec position(-22, 5, 25); Vec goal = !(Vec(-3, 4, 0) + position * -1); Vec left = !Vec(goal.z, 0, -goal.x) * (1. / w); // Cross-product to get the up vector Vec up(goal.y * left.z - goal.z * left.y, goal.z * left.x - goal.x * left.z, goal.x * left.y - goal.y * left.x); printf("P6 %d %d 255 ", w, h); for (int y = h; y--;) for (int x = w; x--;) { Vec color; for (int p = samplesCount; p--;) color = color + Trace(position, !(goal + left * (x - w / 2 + randomVal())+ up * (y - h / 2 + randomVal()))); // Reinhard tone mapping color = color * (1. / samplesCount) + 14. / 241; Vec o = color + 1; color = Vec(color.x / ox, color.y / oy, color.z / oz) * 255; printf("%c%c%c", (int) color.x, (int) color.y, (int) color.z); } } 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдлреНрд▓реЛрдЯ рд▓рд┐рдЯрд░рд▓ рдореЗрдВ "рдПрдл" рдЕрдХреНрд╖рд░ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдЕрдВрддрд░рд┐рдХреНрд╖ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдВрд╢рд┐рдХ рднрд╛рдЧ рдХреЛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдиреАрдЪреЗ рдЙрд╕реА рдЪрд╛рд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдкреВрд░реНрдгрд╛рдВрдХ рднрд╛рдЧ рдЧрд┐рд░рд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдлреНрд▓реЛрдЯ x = .5)ред рдмреНрд░реЗрдХ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рдЕрдВрджрд░ рдбрд╛рд▓реА рдЧрдИ рдПрдХ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд╕рд╛рде рднреА рдЕрд╕рд╛рдорд╛рдиреНрдп "рдХреЗ рд▓рд┐рдП" рдирд┐рд░реНрдорд╛рдг рд╣реИред

рдпрд╣ рдПрдХ рдХрд┐рд░рдг / рдкрде рдЕрдиреБрд░реЗрдЦрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрдВрджрд░ рдорд╛рдирдХ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рд╣реИред рдХреИрдорд░рд╛ рд╡реИрдХреНрдЯрд░ рдпрд╣рд╛рдВ рд▓рдЧрд╛рдП рдЧрдП рд╣реИрдВ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдкрд┐рдХреНрд╕реЗрд▓ рдХреЗ рд▓рд┐рдП рдХрд┐рд░рдгреЗрдВ рдЙрддреНрд╕рд░реНрдЬрд┐рдд рд╣реЛрддреА рд╣реИрдВред рдХрд┐рд░рдг рдЕрдиреБрд░реЗрдЦрдХ рдФрд░ рдкрде рдЕрдиреБрд░реЗрдЦрдХ рдХреЗ рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдЯреАрдкреА рдореЗрдВ рдкреНрд░рддрд┐ рдкрд┐рдХреНрд╕реЗрд▓ рдХрдИ рдХрд┐рд░рдгреЗрдВ рдЙрддреНрд╕рд░реНрдЬрд┐рдд рд╣реЛрддреА рд╣реИрдВ, рдЬрд┐рдиреНрд╣реЗрдВ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд░реВрдк рд╕реЗ рдереЛрдбрд╝рд╛ рд╢рд┐рдлреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдлрд┐рд░ рдПрдХ рдкрд┐рдХреНрд╕реЗрд▓ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХрд┐рд░рдг рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдкреНрдд рд░рдВрдЧ рддреАрди рдлреНрд▓реЛрдЯ рдЪреИрдирд▓ рдЖрд░, рдмреА, рдЬреА рдореЗрдВ рдЬрдорд╛ рд╣реЛрддрд╛ рд╣реИред рдЕрдВрдд рдореЗрдВ, рд░рд┐рдЗрдирд╣рд╛рд░реНрдб рд╡рд┐рдзрд┐ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдЯреЛрдирд▓ рд╕реБрдзрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣рд┐рд╕реНрд╕рд╛ рдирдореВрдирд╛ рд╣реИ, рдЬреЛ рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдФрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП 1 рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣рд╛рдВ 1 рд╕реЗ 2048 рддрдХ рдХреЗ рдирдореВрдирд╛ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдирдореВрдирд╛ рд░реЗрдВрдбрд░рд┐рдВрдЧ рд╣реИрдВред

рд╕реНрдкрд╛рдпрд▓рд░ рд╣реЗрдбрд┐рдВрдЧ


1



2



4



8



16



32



64



128



256



512



1024



2048

рд╣реЗрд▓реНрдкрд░ рдХреЛрдб




рдХреЛрдб рдХрд╛ рдПрдХ рдФрд░ рд╕рд░рд▓ рдЯреБрдХрдбрд╝рд╛ рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдп рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рддреБрдЪреНрдЫ рдлрд╝рдВрдХреНрд╢рди рдорд┐рдирдЯ (), рдЕрдВрддрд░рд╛рд▓ рдореЗрдВ рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдореВрд▓реНрдп рдЬрдирд░реЗрдЯрд░ [0,1] рдФрд░ рдПрдХ рдмрд╣реБрдд рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рдмреЙрдХреНрд╕рдЯреЗрд╕реНрдЯ () рд╣реИ, рдЬреЛ рджреБрдирд┐рдпрд╛ рдХреЛ рдХрд╛рдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд┐рд╡ рд╕реЙрд▓рд┐рдб рдЬреНрдпрд╛рдорд┐рддрд┐ (рд╕реАрдПрд╕рдЬреА) рдкреНрд░рдгрд╛рд▓реА рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред CSG рдХреА рдЪрд░реНрдЪрд╛ рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ рд╣реИред

 float min(float l, float r) { return l < r ? l : r; } float randomVal() { return (float) rand() / RAND_MAX; } // Rectangle CSG equation. Returns minimum signed distance from // space carved by lowerLeft vertex and opposite rectangle // vertex upperRight. float BoxTest(Vec position, Vec lowerLeft, Vec upperRight) { lowerLeft = position + lowerLeft * -1; upperRight = upperRight + position * -1; return -min( min( min(lowerLeft.x, upperRight.x), min(lowerLeft.y, upperRight.y) ), min(lowerLeft.z, upperRight.z)); } 

рд░рдЪрдирд╛рддреНрдордХ рд╡реЙрд▓реНрдпреВрдореЗрдЯреНрд░рд┐рдХ рдЬреНрдпрд╛рдорд┐рддрд┐ рдХреЗ рдХрд╛рд░реНрдп




рдХреЛрдб рдореЗрдВ рдХреЛрдИ рдХреЛрдиреЗ рдирд╣реАрдВ рд╣реИрдВред рд╕рдм рдХреБрдЫ CSG рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдЙрдирдХреЗ рд╕рд╛рде рдЕрдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ, рддреЛ рдмрд╕ рдпрд╣ рдХрд╣реЗрдВ рдХрд┐ рдпреЗ рдРрд╕реЗ рдХрд╛рд░реНрдп рд╣реИрдВ рдЬреЛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╕рдордиреНрд╡рдп рд╡рд╕реНрддреБ рдХреЗ рдЕрдВрджрд░ рд╣реИ рдпрд╛ рдмрд╛рд╣рд░ред рдпрджрд┐ рдлрд╝рдВрдХреНрд╢рди рд╕рдХрд╛рд░рд╛рддреНрдордХ рджреВрд░реА рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рддреЛ рдмрд┐рдВрджреБ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдЕрдВрджрд░ рд╣реИред рдПрдХ рдирдХрд╛рд░рд╛рддреНрдордХ рджреВрд░реА рдЗрдВрдЧрд┐рдд рдХрд░рддреА рд╣реИ рдХрд┐ рдмрд┐рдВрджреБ рд╡рд╕реНрддреБ рдХреЗ рдмрд╛рд╣рд░ рд╣реИред рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдХрд╛рд░реНрдп рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕рд░рд▓реАрдХрд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдПрдХ рдХреНрд╖реЗрддреНрд░ рдФрд░ рджреЛ рдмрд┐рдВрджреБрдУрдВ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рд▓реЗрддреЗ рд╣реИрдВ, рдП рдФрд░ рдмреАред

рдЫрд╡рд┐

 // Signed distance point(p) to sphere(c,r) float testSphere(Vec p, Vec c, float r) { Vec delta = c - p; float distance = sqrtf(delta%delta); return radius - distance; } Vec A {4, 6}; Vec B {3, 2}; Vec C {4, 2}; float r = 2.; testSphere(A, C, r); // == -1 (outside) testSphere(B, C, r); // == 1 (inside) 

TestSphere () рдлрд╝рдВрдХреНрд╢рди A рдХреЗ рд▓рд┐рдП -1 рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИ (рдЬреЛ рдХрд┐, рдпрд╣ рдмрд╛рд╣рд░ рд╣реИ) рдФрд░ B рдХреЗ рд▓рд┐рдП 1 (рдпрд╛рдиреА рдпрд╣ рдЕрдВрджрд░ рд╣реИ)ред рджреВрд░рд┐рдпреЛрдВ рдкрд░ рд╕рдВрдХреЗрдд рд╕рд┐рд░реНрдл рдПрдХ рдЪрд╛рд▓ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЖрдк рдПрдХ рд╣реА рдореВрд▓реНрдп рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдПрдХ рдХреЗ рдмрдЬрд╛рдп рджреЛ рдЯреБрдХрдбрд╝реЛрдВ рдХреА рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ рд╕рдорд╛рди рдкреНрд░рдХрд╛рд░ рдХреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдПрдХ рд╕рдорд╛рдВрддрд░ рдЪрддреБрд░реНрднреБрдЬ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдмреЙрдХреНрд╕рдЯреЗрд╕реНрдЯ рдореЗрдВ рдРрд╕рд╛ рд╣реА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред


  // Signed distance point(p) to Box(c1,c2) float testRectangle(Vec p, Vec c1, Vec c2) { c1 = p + c1 * -1; c2 = c2 + position * -1; return min( min( min(c1.x, c2.x), min(c1.y, c2.y)), min(c1.z, c2.z)); } Vec A {3, 3}; Vec B {4, 6}; Vec C1 {2, 2}; Vec C2 {5, 4}; testRectangle(A, C1, C2); // 1.41 (inside) testRectangle(B, C1, C2); // -2.23 (outside) 

рдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдпрджрд┐ рдЖрдк рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рдХрд╛ рдЪрд┐рдиреНрд╣ рдлреНрд▓рд┐рдк рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрдЧрд╛ред


  // Signed distance point(p) to carved box(c1,c2) float testCarveBox(Vec p, Vec c1, Vec c2) { c1 = p + c1 * -1; c2 = c2 + position * -1; return -min( min( min(c1.x, c2.x), min(c1.y, c2.y)), min(c1.z, c2.z)); } Vec A {3, 3}; Vec B {4, 6}; Vec C1 {2, 2}; Vec C2 {5, 4}; testCarveBox(A, C1, C2); // == -1.41 (outside) testCarveBox(B, C1, C2); // == 2.23 (inside) 

рдЕрдм рд╣рдо рдХрд┐рд╕реА рдареЛрд╕ рд╡рд╕реНрддреБ рдХрд╛ рд╡рд░реНрдгрди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдкреВрд░реА рджреБрдирд┐рдпрд╛ рдХреЛ рдареЛрд╕ рдШреЛрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕рдореЗрдВ рдЦрд╛рд▓реА рдЬрдЧрд╣ рдХрд╛рдЯ рджреЗрддреЗ рд╣реИрдВред рдИрдВрдЯреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд░реВрдк рдореЗрдВ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рд╕рдВрдпреБрдХреНрдд рд╣реЛрдиреЗ рдкрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд░реВрдкреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░ рд╕рдХрддрд╛ рд╣реИред рддрд╛рд░реНрдХрд┐рдХ рдЬреЛрдбрд╝ рдСрдкрд░реЗрдЯрд░ (рдиреНрдпреВрдирддрдо рдлрд╝рдВрдХреНрд╢рди) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рдо рдЖрдпрддреЛрдВ рдХреА рдПрдХ рдЬреЛрдбрд╝реА рдХреЛ рдПрдХ рдХреЗ рдКрдкрд░ рдПрдХ рдХрд╛рдЯ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛ред


  // Signed distance point to room float testRoom(Vec p) { Vec C1 {2, 4}; Vec C2 {5, 2}; // Lower room Vec C3 {3, 5}; Vec C4 {4, 4}; // Upper room // min() is the union of the two carved volumes. return min(testCarvedBox(p, C1, C2), testCarvedBox(p, C3, C4)); } Vec A {3, 3}; Vec B {4, 6}; testRoom(A, C1, C2); // == -1.41 (outside) testRoom(B, C1, C2); // == 1.00 (inside) 

рдпрджрд┐ рдЖрдк рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрддреЗ рд╣реИрдВ, рддреЛ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдЬрд┐рд╕ рдХрдорд░реЗ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдирд┐рдЪрд▓рд╛ рдХрдорд░рд╛ рдмрд┐рд▓реНрдХреБрд▓ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ - рджреЛ рдХрдЯреЗ рд╣реБрдП рд╕рдорд╛рдирд╛рдВрддрд░ рдЪрддреБрд░реНрднреБрдЬреЛрдВ рдХреА рдорджрдж рд╕реЗред

рдЕрдм, CSG рдХреЗ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЬреНрдЮрд╛рди рдореЗрдВ рдорд╣рд╛рд░рдд рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдХреЛрдб рдкрд░ рд▓реМрдЯ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рдирд┐рдкрдЯрдирд╛ рд╕рдмрд╕реЗ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред

 #define HIT_NONE 0 #define HIT_LETTER 1 #define HIT_WALL 2 #define HIT_SUN 3 // Sample the world using Signed Distance Fields. float QueryDatabase(Vec position, int &hitType) { float distance = 1e9; Vec f = position; // Flattened position (z=0) fz = 0; char letters[15*4+1] = // 15 two points lines "5O5_" "5W9W" "5_9_" // P (without curve) "AOEO" "COC_" "A_E_" // I "IOQ_" "I_QO" // X "UOY_" "Y_]O" "WW[W" // A "aOa_" "aWeW" "a_e_" "cWiO"; // R (without curve) for (int i = 0; i < sizeof(letters); i += 4) { Vec begin = Vec(letters[i] - 79, letters[i + 1] - 79) * .5; Vec e = Vec(letters[i + 2] - 79, letters[i + 3] - 79) * .5 + begin * -1; Vec o = f + (begin + e * min(-min((begin + f * -1) % e / (e % e), 0), 1) ) * -1; distance = min(distance, o % o); // compare squared distance. } distance = sqrtf(distance); // Get real distance, not square distance. // Two curves (for P and R in PixaR) with hard-coded locations. Vec curves[] = {Vec(-11, 6), Vec(11, 6)}; for (int i = 2; i--;) { Vec o = f + curves[i] * -1; distance = min(distance, ox > 0 ? fabsf(sqrtf(o % o) - 2) : (oy += oy > 0 ? -2 : 2, sqrtf(o % o)) ); } distance = powf(powf(distance, 8) + powf(position.z, 8), .125) - .5; hitType = HIT_LETTER; float roomDist ; roomDist = min(// min(A,B) = Union with Constructive solid geometry //-min carves an empty space -min(// Lower room BoxTest(position, Vec(-30, -.5, -30), Vec(30, 18, 30)), // Upper room BoxTest(position, Vec(-25, 17, -25), Vec(25, 20, 25)) ), BoxTest( // Ceiling "planks" spaced 8 units apart. Vec(fmodf(fabsf(position.x), 8), position.y, position.z), Vec(1.5, 18.5, -25), Vec(6.5, 20, 25) ) ); if (roomDist < distance) distance = roomDist, hitType = HIT_WALL; float sun = 19.9 - position.y ; // Everything above 19.9 is light source. if (sun < distance)distance = sun, hitType = HIT_SUN; return distance; } 

рдЖрдк рдпрд╣рд╛рдВ рд╕рдорд╛рдВрддрд░ рдЪрддреБрд░реНрднреБрдЬ "рдХрдЯрд┐рдВрдЧ" рдХрд╛ рдХрд╛рд░реНрдп рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдкреВрд░реЗ рдХрдорд░реЗ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рджреЛ рдЖрдпрддреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рд╣рдорд╛рд░рд╛ рдорд╕реНрддрд┐рд╖реНрдХ рдмрд╛рдХреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдпрд╣ рджреАрд╡рд╛рд░реЛрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ)ред рдХреНрд╖реИрддрд┐рдЬ рд╕реАрдврд╝реА рд╢реЗрд╖ рд╡рд┐рднрд╛рдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ CSG рдлрд╝рдВрдХреНрд╢рди рд╣реИред рдФрд░ рдЕрдВрдд рдореЗрдВ, PIXAR рд╢рдмреНрдж рдПрдХ рдореВрд▓ рдФрд░ рдбреЗрд▓реНрдЯрд╛ рдЬреЛрдбрд╝реА рдХреЗ рд╕рд╛рде 15 рд▓рд╛рдЗрдиреЛрдВ рд╕реЗ рдмрдирд╛ рд╣реИ рдФрд░ P рдФрд░ R рдЕрдХреНрд╖рд░ рдореЗрдВ рдШрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рджреЛ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЗ рд╣реИрдВред

рд░реЗ рдорд╛рд░реНрдЪрд┐рдВрдЧ




рджреБрдирд┐рдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ CSG рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╣реЛрдирд╛, рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдореБрдЦреНрдп () рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЙрддреНрд╕рд░реНрдЬрд┐рдд рд╕рднреА рдХрд┐рд░рдгреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред рд░реЗ рдорд╛рд░реНрдЪрд┐рдВрдЧ рдбрд┐рд╕реНрдЯреЗрдВрд╕ рдлрдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдирдореВрдирд╛ рд╕реНрдерд┐рддрд┐ рдирд┐рдХрдЯрддрдо рдмрд╛рдзрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рджреВрд░реА рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рддреА рд╣реИред

 // Perform signed sphere marching // Returns hitType 0, 1, 2, or 3 and update hit position/normal int RayMarching(Vec origin, Vec direction, Vec &hitPos, Vec &hitNorm) { int hitType = HIT_NONE; int noHitCount = 0; float d; // distance from closest object in world. // Signed distance marching for (float total_d=0; total_d < 100; total_d += d) if ((d = QueryDatabase(hitPos = origin + direction * total_d, hitType)) < .01 || ++noHitCount > 99) return hitNorm = !Vec(QueryDatabase(hitPos + Vec(.01, 0), noHitCount) - d, QueryDatabase(hitPos + Vec(0, .01), noHitCount) - d, QueryDatabase(hitPos + Vec(0, 0, .01), noHitCount) - d) , hitType; // Weird return statement where a variable is also updated. return 0; } 

рджреВрд░реА рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд┐рд░рдг рдорд╛рд░реНрдЪрд┐рдВрдЧ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдирд┐рдХрдЯрддрдо рд╡рд╕реНрддреБ рдХреА рджреВрд░реА рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рдирд╛ рд╣реИред рдЕрдВрдд рдореЗрдВ, рдХрд┐рд░рдг рд╕рддрд╣ рдкрд░ рдЗрд╕ рдХрджрд░ рдкрд╣реБрдВрдЪ рдЬрд╛рдПрдЧреА рдХрд┐ рдЗрд╕реЗ рдШрдЯрдирд╛ рдХрд╛ рдмрд┐рдВрджреБ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХрд┐рд░рдг рдорд╛рд░реНрдЪрд┐рдВрдЧ рд╕рддрд╣ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдЪреНрдЪреЗ рдЪреМрд░рд╛рд╣реЗ рдХреЛ рд╡рд╛рдкрд╕ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдиреНрдирд┐рдХрдЯрдиред рдЗрд╕реАрд▓рд┐рдП d <0.01f рд╣реЛрдиреЗ рдкрд░ рдХреЛрдб рдореЗрдВ рдорд╛рд░реНрдЪрд┐рдВрдЧ рд░реБрдХ рдЬрд╛рддреА рд╣реИред

рдпрд╣ рд╕рдм рдПрдХ рд╕рд╛рде рд▓рд╛рдирд╛: рдирдореВрдирд╛ рд▓реЗрдирд╛




рдкрде рдЕрдиреБрд░реЗрдЦрдХ рдХреА рдЬрд╛рдВрдЪ рд▓рдЧрднрдЧ рдкреВрд░реА рд╣реЛ рдЪреБрдХреА рд╣реИред рд╣рдо рдПрдХ рдкреБрд▓ рдХреЛ рдпрд╛рдж рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬреЛ рдореБрдЦреНрдп () рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд┐рд░рдг рдорд╛рд░реНрдЪрд░ рд╕реЗ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдпрд╣ рдЕрдВрддрд┐рдо рднрд╛рдЧ, рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ "рдЯреНрд░реЗрд╕" рдХрд╛ рдирд╛рдо рджрд┐рдпрд╛, рд╡рд╣ "рдорд╕реНрддрд┐рд╖реНрдХ" рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХрд┐рд░рдгреЗрдВ рдЙрдЫрд╛рд▓ рдпрд╛ рд░реБрдХрддреА рд╣реИрдВ, рдЬреЛ рдЙрд╕ рдореБрдарднреЗрдбрд╝ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред

 Vec Trace(Vec origin, Vec direction) { Vec sampledPosition, normal, color, attenuation = 1; Vec lightDirection(!Vec(.6, .6, 1)); // Directional light for (int bounceCount = 3; bounceCount--;) { int hitType = RayMarching(origin, direction, sampledPosition, normal); if (hitType == HIT_NONE) break; // No hit. This is over, return color. if (hitType == HIT_LETTER) { // Specular bounce on a letter. No color acc. direction = direction + normal * ( normal % direction * -2); origin = sampledPosition + direction * 0.1; attenuation = attenuation * 0.2; // Attenuation via distance traveled. } if (hitType == HIT_WALL) { // Wall hit uses color yellow? float incidence = normal % lightDirection; float p = 6.283185 * randomVal(); float c = randomVal(); float s = sqrtf(1 - c); float g = normal.z < 0 ? -1 : 1; float u = -1 / (g + normal.z); float v = normal.x * normal.y * u; direction = Vec(v, g + normal.y * normal.y * u, -normal.y) * (cosf(p) * s) + Vec(1 + g * normal.x * normal.x * u, g * v, -g * normal.x) * (sinf(p) * s) + normal * sqrtf(c); origin = sampledPosition + direction * .1; attenuation = attenuation * 0.2; if (incidence > 0 && RayMarching(sampledPosition + normal * .1, lightDirection, sampledPosition, normal) == HIT_SUN) color = color + attenuation * Vec(500, 400, 100) * incidence; } if (hitType == HIT_SUN) { // color = color + attenuation * Vec(50, 80, 100); break; // Sun Color } } return color; } 

рдЕрдиреБрдордд рдмреАрдо рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреА рдЕрдзрд┐рдХрддрдо рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рдкреНрд░рдпреЛрдЧ рдХрд┐рдпрд╛ред рдорд╛рди "2" рдЕрдХреНрд╖рд░реЛрдВ рдХреЛ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд░реВрдк рд╕реЗ рд╕реБрдВрджрд░ рд▓реИрдХреНрдХреЗрд░реЗрдб рд╡реИрдиреНрдЯрдмреНрд▓реИрдХ рд░рдВрдЧ [4] рджреЗрддрд╛ рд╣реИ ред


1


2


3


4

рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╛рдл рд╕реНрд░реЛрдд рдХреЛрдб




рд╕рдм рдХреБрдЫ рдПрдХ рд╕рд╛рде рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕реНрд╡рдЪреНрдЫ рд╕реНрд░реЛрдд рдХреЛрдб рдмрдирд╛рдпрд╛ ред

рд╕рдВрджрд░реНрдн рд╕рд╛рдордЧреНрд░реА




[рез] рд╕реНрд░реЛрдд: f рдЕрдХреНрдЯреВрдмрд░ реирежрез le рдХреЛ рдЯреНрд╡рд┐рдЯрд░ рдкреЛрд╕реНрдЯ

[реи] рд╕реНрд░реЛрдд: рд╡рд┐рдХрд┐рдкреАрдбрд┐рдпрд╛: NetPBM рдЫрд╡рд┐ рдкреНрд░рд╛рд░реВрдк

[рей] рд╕реНрд░реЛрдд: рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдиреЗ рд╕рдмрд╕реЗ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдореИрдХрдмреБрдХ рдкреНрд░реЛ, реирежрез Visual рдкрд░ рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдпрд╛

[рек] рд╕реНрд░реЛрдд: рд╡рд┐рдХрд┐рдкреАрдбрд┐рдпрд╛

Source: https://habr.com/ru/post/hi434528/


All Articles