光線追蹤試玩

來源:互聯網
上載者:User

經過LRJ大大的指點,我今天花了一天時間寫成了我第一個光線追蹤!!

先暫時上點成果示範,因為我還想繼續添加一點新元素,比如加進球體,貼圖什麼的。

首先上一個有鏡子的:

然後,再上一個有折射的

(還有全反射現象哦!)

呃 ~~~鋸齒是不是非常嚴重?去偷學了個消除鋸齒的技能,還是有一點效果的拉:

還有這個,消除鋸齒的對比(代碼寫的好醜。。渲染下面這個圖就用了10分鐘)

好吧,承認我消除鋸齒寫的很渣。。。。。

接下來計劃添加貼圖,還有加進球體。(橢球有沒有這玩意?)

代碼(各種三維~~其實比殺菌計劃還要短一點呢)

#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#define maxdepth 2#define e 1e-8using namespace std;struct P{double x,y,z;};P operator +(P a,P b) {return (P){a.x+b.x,a.y+b.y,a.z+b.z};}P operator -(P a,P b) {return (P){a.x-b.x,a.y-b.y,a.z-b.z};}P operator *(P a,double b) {return (P){a.x*b,a.y*b,a.z*b};}P operator /(P a,double b) {return a*(1/b);}P operator *(P a,P b) {return (P){a.y*b.z-a.z*b.y,a.z*b.x-b.z*a.x,a.x*b.y-a.y*b.x};}double operator /(P a,P b) {return a.x*b.x+a.y*b.y+a.z*b.z;}double mo(P a) {return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);}int C(double a) {return (a<-e)?-1:a>e;}struct SJ{P p[4],X,Y,Z,color;double refl,refr,indx;};struct RAY{P a,b;};P change(P a,SJ b) {return (P){a/b.X,a/b.Y,a/b.Z};}RAY get_f(SJ s,RAY r) {  RAY ans;  ans.a=(P){1e50,1e50};  if (s.indx>1e3) return ans;  P a=change(r.a,s);  P b=change(r.b,s);  if (!C(b.z)) return ans;  double dt=(s.p[0].z-a.z)/b.z;  if (C(dt)<=0) return ans;  a=a+(b*dt);  for (int i=0;i<3;i++) {    P tt=(s.p[i+1]-s.p[i])*(a-s.p[i]);    if (C(tt.z)<0) return ans;  };  b.z=-b.z;  P dx=(P){1,0,0};  P dy=(P){0,1,0};  P dz=(P){0,0,1};  dx=change(dx,s);  dy=change(dy,s);  dz=change(dz,s);  dx=dx/(mo(dx));  dy=dy/(mo(dy));  dz=dz/(mo(dz));  ans.a=(P){a/dx,a/dy,a/dz};  ans.b=(P){b/dx,b/dy,b/dz};  return ans;}RAY get_z(SJ s,RAY r,double zr) {  RAY ans;  ans.a=(P){1e50,1e50};  P a=change(r.a,s);  P b=change(r.b,s);  if (!C(b.z)) return ans;  double dt=(s.p[0].z-a.z)/b.z;  if (C(dt)<=0) return ans;    double gm;  if (C(zr-s.indx)) gm=mo(b)*s.indx;               else gm=mo(b)/s.indx;  a=a+(b*dt);  for (int i=0;i<3;i++) {    P tt=(s.p[i+1]-s.p[i])*(a-s.p[i]);    if (C(tt.z)<0) return ans;  };  P dx=(P){1,0,0};  P dy=(P){0,1,0};  P dz=(P){0,0,1};  dx=change(dx,s);  dy=change(dy,s);  dz=change(dz,s);  dx=dx/(mo(dx));  dy=dy/(mo(dy));  dz=dz/(mo(dz));  gm=gm*gm-b.x*b.x-b.y*b.y;  if (C(gm)<=0) return ans;  gm=sqrt(gm);  if (b.z>0) b.z=gm; else b.z=-gm;  ans.a=(P){a/dx,a/dy,a/dz};  ans.b=(P){b/dx,b/dy,b/dz};  return ans;}vector<SJ> s(0);SJ getclose(RAY a) {  SJ b;  b.indx=1e9;  P c,d=(P){1e30,1e30};  for (int i=0;i<(int)s.size();i++) {    c=get_f(s[i],a).a;    if (mo(c-a.a)<mo(d-a.a)) b=s[i],d=c;  };  return b;}SJ makeSJ(P a,P b,P c) {  SJ h;  h.p[0]=h.p[3]=a;  h.p[1]=b, h.p[2]=c;  h.Z=(b-a)*(c-a);  h.X=(b-a)*h.Z;  h.Y=h.Z*h.X;  h.X=h.X/(mo(h.X));  h.Y=h.Y/(mo(h.Y));  h.Z=h.Z/(mo(h.Z));  for (int i=0;i<4;i++) h.p[i]=change(h.p[i],h);  return h;}P sun,sunl;double amb;P get_point_color(SJ a,P b) {  RAY r=(RAY){b,sun-b};  r.b=r.b/(mo(r.b));  P x=get_f(getclose(r),r).a;  double l;  if (C(mo(b-x)-mo(sun-b))>=0) {    l=abs(a.Z/r.b);  } else l=0;  l=amb+(1-amb)*l;  a.color.x*=sunl.x;  a.color.y*=sunl.y;  a.color.z*=sunl.z;  return a.color*l;}P trace_ray(int depth, RAY r,double zr) {  P point_color=(P){0,0,0},reflect_color=(P){0,0,0},refract_color=(P){0,0,0};  if (mo(r.a)>1e20) return point_color;  SJ i=getclose(r);  if(i.indx<1e3) {    double refl=i.refl;    double refr=i.refr;    P x=get_f(i,r).a;    point_color=get_point_color(i,x) * (1-refl-refr);    if(depth<maxdepth && C(refl)>0)      reflect_color=trace_ray(depth+1, get_f(i,r),zr) * refl;    if(depth<maxdepth && C(refr)>0)      refract_color=trace_ray(depth+1, get_z(i,r,zr),(!C(zr-1))?i.indx:1) * refr;  }  return point_color+reflect_color+refract_color;}int main() {  freopen("N_input_6.txt","r",stdin);  freopen("image.txt","w",stdout);  s.clear();  int n;  scanf("%d",&n);  while (n--) {    int np;    vector<P> p(0);    scanf("%d",&np);    while (np--) {      P h;      scanf("%lf%lf%lf",&h.x,&h.y,&h.z);      p.push_back(h);    };    int mp;    scanf("%d",&mp);    for (int i=1;i<=mp;i++) {      int a,b,c;      scanf("%d%d%d",&a,&b,&c);      s.push_back(makeSJ(p[a],p[b],p[c]));    };    P color;    scanf("%lf%lf%lf",&color.x,&color.y,&color.z);    double refl,refr,idx;    scanf("%lf%lf%lf",&refl,&refr,&idx);    for (int i=1;i<=mp;i++) {      s[s.size()-i].color=color;      s[s.size()-i].refl=refl;      s[s.size()-i].refr=refr;      s[s.size()-i].indx=idx;    };  };  scanf("%lf%lf%lf",&sun.x,&sun.y,&sun.z);  scanf("%lf",&amb);  scanf("%lf%lf%lf",&sunl.x,&sunl.y,&sunl.z);  int np;  scanf("%d",&np);  while (np--) {    P cs,ct,cu;    scanf("%lf%lf%lf",&cs.x,&cs.y,&cs.z);    scanf("%lf%lf%lf",&ct.x,&ct.y,&ct.z);    scanf("%lf%lf%lf",&cu.x,&cu.y,&cu.z);    ct=ct-cs;    P cl=ct*cu;    cu=cu/mo(cu);    cl=cl/mo(cl);    ct=ct/mo(ct);    double fov;    int w,d;    scanf("%lf",&fov);    scanf("%d%d",&w,&d);    printf("%d %d\n",w,d);    double ld=tan(fov/180*M_PI/2)/(w*.5);    P rs=cl*ld,ds=cu*(-ld);    P ss=ct-(rs*(w*.5))-(ds*(d*.5));    for (int i=1;i<=d;i++) {      for (int j=1;j<=w;j++) {        if (!((i*w+j)%500))fprintf(stderr,"loading....   %.2lf%%\n",((i-1.)*w+j)/(d*w)*100);        P ns=ss+(rs*(j-.5))+(ds*(i-.5));        RAY go=(RAY){cs,ns};        P cl=trace_ray(0,go,1);        printf("%02x%02x%02x ",(int)(cl.x*255),(int)(cl.y*255),(int)(cl.z*255));        //printf("%lf %lf %lf ",cl.x,cl.y,cl.z);      };      printf("\n");    };  };  return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.