Today, I spent another day on ray tracing, but obviously, I have gained a lot.
First, it took half an hour to push the form of Sphere reflection and refraction, and then changed the position of the light source. The first figure shown below is as follows:
I was completely shocked. Why did it suddenly become so good? (We can compare the figure of yesterday)
Whack reminded me that I pulled the light source down, so the above walls experienced a halo, increasing the sense of reality. Thus, I added a halo, and the brightness of the Halo decreased linearly with the distance:
Ohno, this halo is really ugly, so I changed it to the cosine function:
Well, it's pretty good!
Next, I constantly modify the parameters:
Well, the Sawtooth is very serious .. ~~~
You can look for details. One of the two pictures above is that I allow the reflection to have a recursive depth of 4, and the other is 6.
It took two hours to adjust the parameters. Then, when the code was reached, the texture task was completed!
It's hard to see how image files are read .. I only won't read the output. I asked the lrj teacher, checked the Wiki, and finally turned to the FHQ code. Finally, I realized how to read the BMP file.
The first picture posted! Thrilling! (Hey, isn't that a violation of the Authority ?)
This figure clearly shows the refraction, And the inverted solid phase shown in the glass ball on the right.
The first texture is successful, so, Me ------
Added a background, but the picture is too peacekeeping =!
Finally, I made the most satisfactory HD wallpaper! 1440*900! (Oh no, compressed! It looks like a gray layer ..)
Finally, post lengthy code
#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#define maxdepth 6#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;}double sqr(double x) {return x*x;}struct SJ{P p[4],X,Y,Z,o,color;int kind;double R,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};}double ttt,gr;struct BMP {#define a(i,j,k) data[((i)*((W*3+3)&~3))+(j)*3+(k)] int W,H; unsigned char* data; int readLong(FILE *fin){ int b0,b1,b2,b3; b0=fgetc(fin);b1=fgetc(fin);b2=fgetc(fin);b3=fgetc(fin); return b0 | (b1<<8) | (b2<<16) | (b3<<24); } void build(char *Fname) { FILE *fin=fopen(Fname,"rb"); if (!fin){fprintf(stderr,"error\n");return;} fseek(fin,0x12,0); W=readLong(fin); H=readLong(fin); fseek(fin,0x36,0); data=new unsigned char[((W*3+3)&~3)*H]; fread(data,1,((W*3+3)&~3)*H,fin); for (int i=0;H-1-i>=i;i++){ for (int j=0;j<W;j++){ swap(a(i,j,0),a(H-1-i,j,2)); swap(a(i,j,1),a(H-1-i,j,1)); swap(a(i,j,2),a(H-1-i,j,0)); }; }; fclose(fin); } P BMPcolor(double x,double y) { int i=(int)(x*H),j=(int)(y*W); if (i<0) i=0; if (j<0) j=0; if (i>=H) i=H-1; if (j>=W) j=W-1; return (P){a(i,j,0)/255.,a(i,j,1)/255.,a(i,j,2)/255.}; }};vector<BMP> pic(0);RAY get_f(SJ s,RAY r) { RAY ans; ans.a=(P){1e50,1e50}; if (s.indx>1e3) return ans; if (!s.kind) { r.b=r.b/(mo(r.b)); double dt=(r.b/s.o)-(r.b/r.a); P md=r.a+(r.b*dt); double dis=mo(md-s.o); if (C(dis-s.R)>=0) return ans; double kd=sqrt(s.R*s.R-dis*dis); if (C(dt+kd)<=0) return ans; if (C(dt-kd)>0) ans.a=md-(r.b*kd); else ans.a=md+(r.b*kd); P f=ans.a-s.o; f=f/(mo(f)); dt=r.b/f; ans.b=r.b-(f*(dt*2)); 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+!!(s.kind<0));i++) { P tt=(s.p[(i+1)&3]-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}; if (!s.kind) { r.b=r.b/(mo(r.b)); double dt=(r.b/s.o)-(r.b/r.a); P md=r.a+(r.b*dt); double dis=mo(md-s.o); if (C(dis-s.R)>=0) return ans; double kd=sqrt(s.R*s.R-dis*dis); if (C(dt+kd)<=0) return ans; if (C(dt-kd)>0) ans.a=md-(r.b*kd); else ans.a=md+(r.b*kd); P f=s.o-ans.a; f=f/(mo(f)); dt=r.b/f; double gm; if (C(zr-s.indx)) gm=mo(r.b)*s.indx; else gm=mo(r.b)/s.indx; gm=gm*gm-(sqr(mo(r.b))-dt*dt); if (C(gm)<=0) {ans.a=(P){1e50,1e50};return ans;} gm=sqrt(gm); if (dt<0) gm=-gm; ans.b=r.b+(f*(gm-dt)); 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; 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+!!(s.kind<0));i++) { P tt=(s.p[(i+1)&3]-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,double &light,double md) { 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; double idd=mo(c-a.a); if (C(idd-md)<0) light*=s[i].refr; if (idd<mo(d-a.a)) b=s[i],d=c; }; return b;}SJ makeSJ(P a,P b,P c) { SJ h; h.kind=1; 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)); double l=1,sundis=mo(sun-b); get_f(getclose(r,l,sundis),r).a; P f=a.Z; if (!a.kind) { f=b-a.o; f=f/(mo(f)); } else if (a.kind<0) { P nj=(P){b/a.X,b/a.Y,b/a.Z}; P fx=a.p[1]-a.p[0]; P fy=a.p[3]-a.p[0]; double mx=mo(fx),my=mo(fy); fx=fx/mx,fy=fy/my; nj=nj-a.p[0]; double dx=(nj.x*fy.y-nj.y*fy.x)/(fx.x*fy.y-fx.y*fy.x)/mx; double dy=(nj.x*fx.y-nj.y*fx.x)/(fx.y*fy.x-fx.x*fy.y)/my; a.color=pic[-1-a.kind].BMPcolor(dx,dy); }; l*=pow(abs(f/r.b),3); 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,ttt,ttt); P x; if(i.indx<1e3) { double refl=i.refl; double refr=i.refr; 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; } else x=(P){1e30,1e30}; P ncl=point_color+reflect_color+refract_color; r.b=r.b/(mo(r.b)); double sr=(r.b/r.a),dt=(r.b/sun)-sr; P jd=r.a+(r.b*dt); double rd=mo(jd-sun); if (rd<gr && dt>e && (mo(x)>1e30 || dt<((r.b/x)-sr))) { double l=cos(rd/gr*M_PI)/2+0.5; ncl=(ncl*(1-l))+(sunl*l); }; return ncl;}P shot(P s,P t) { RAY r=(RAY){s,t}; return trace_ray(0,r,1);}int main() { freopen("N_input_0.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); for (int i=1;i<=np;i++) { P h; scanf("%lf%lf%lf",&h.x,&h.y,&h.z); p.push_back(h); }; int mp; scanf("%d",&mp); if (np==1) { SJ h; h.kind=0; h.o=p[0]; scanf("%lf",&h.R); s.push_back(h); } else if (np==4 && mp==1) { BMP picture; char Fname[100]; scanf("%s",Fname); picture.build(Fname); pic.push_back(picture); SJ h=makeSJ(p[0],p[1],(p[2]+p[1])-p[0]); h.p[3]=change(p[2],h); h.kind=-((int)pic.size()); s.push_back(h); } else 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%lf",&gr,&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)); P cl=shot(cs,ns); if (0) { cl=cl+shot(cs,ns+(rs*.4)); cl=cl+shot(cs,ns-(rs*.4)); cl=cl+shot(cs,ns+(ds*.4)); cl=cl+shot(cs,ns-(ds*.4)); cl=cl/5; }; printf("%02x%02x%02x ",(int)(cl.x*255),(int)(cl.y*255),(int)(cl.z*255)); }; printf("\n"); }; }; return 0;}