Skip to content

Commit a941eae

Browse files
committed
recursion to iteration (without russian roulette)
1 parent 069a876 commit a941eae

File tree

2 files changed

+44
-26
lines changed

2 files changed

+44
-26
lines changed

smallpt/main.cu

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,33 +54,51 @@ __device__ inline bool intersect(const int num_spheres, const Sphere* spheres, c
5454
for(int i=int(n);i--;) if((d=spheres[i].intersect(r))&&d<t){t=d;id=i;}
5555
return t<inf;
5656
}
57-
__device__ Vec radiance(const int num_spheres, const Sphere* spheres, const Ray &r, int depth, unsigned short *Xi, curandState* state){
57+
__device__ Vec radiance(const int num_spheres, const Sphere* spheres, Ray r, int depth, unsigned short *Xi, curandState* state){
5858
double t; // distance to intersection
5959
int id=0; // id of intersected object
60-
if(depth > 1) return Vec();
61-
if (!intersect(num_spheres, spheres, r, t, id)) return Vec(); // if miss, return black
62-
const Sphere &obj = spheres[id]; // the hit object
63-
Vec x=r.o+r.d*t, n=(x-obj.p).norm(), nl=n.dot(r.d)<0?n:n*-1, f=obj.c;
64-
double p = f.x>f.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl
65-
if (++depth>5) if (curand_uniform_double(state)<p) f=f*(1/p); else return obj.e; //R.R.
66-
if (obj.refl == DIFF){ // Ideal DIFFUSE reflection
67-
double r1=2*M_PI*curand_uniform_double(state), r2=curand_uniform_double(state), r2s=sqrt(r2);
68-
Vec w=nl, u=((fabs(w.x)>.1?Vec(0,1):Vec(1))%w).norm(), v=w%u;
69-
Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm();
70-
return obj.e + f.mult(radiance(num_spheres, spheres,Ray(x,d),depth,Xi,state));
71-
} else if (obj.refl == SPEC) // Ideal SPECULAR reflection
72-
return obj.e + f.mult(radiance(num_spheres, spheres,Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi,state));
73-
Ray reflRay(x, r.d-n*2*n.dot(r.d)); // Ideal dielectric REFRACTION
74-
bool into = n.dot(nl)>0; // Ray from outside going in?
75-
double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t;
76-
if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) // Total internal reflection
77-
return obj.e + f.mult(radiance(num_spheres, spheres,reflRay,depth,Xi,state));
78-
Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm();
79-
double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n));
80-
double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P);
81-
return obj.e + f.mult(depth>2 ? (curand_uniform_double(state)<P ? // Russian roulette
82-
radiance(num_spheres, spheres,reflRay,depth,Xi,state)*RP:radiance(num_spheres, spheres,Ray(x,tdir),depth,Xi,state)*TP) :
83-
radiance(num_spheres, spheres,reflRay,depth,Xi,state)*Re+radiance(num_spheres, spheres,Ray(x,tdir),depth,Xi,state)*Tr);
60+
61+
Vec s_e[10];
62+
Vec s_f[10];
63+
for(int i=0; i<10; i++){
64+
if (!intersect(num_spheres, spheres, r, t, id)) return Vec(); // if miss, return black
65+
const Sphere &obj = spheres[id]; // the hit object
66+
Vec x=r.o+r.d*t, n=(x-obj.p).norm(), nl=n.dot(r.d)<0?n:n*-1, f=obj.c;
67+
double p = f.x>f.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl
68+
if (i>5) {
69+
if (curand_uniform_double(state)<p) f=f*(1/p);
70+
else {
71+
Vec res = obj.e;
72+
Vec e,f;
73+
while(--i>=0){
74+
e = s_e[i];
75+
f = s_f[i];
76+
res = e + f.mult(res);
77+
}
78+
return res;
79+
}
80+
} //return obj.e; //R.R.
81+
s_e[i]=obj.e;
82+
s_f[i]=f;
83+
if (obj.refl == DIFF){ // Ideal DIFFUSE reflection
84+
double r1=2*M_PI*curand_uniform_double(state), r2=curand_uniform_double(state), r2s=sqrt(r2);
85+
Vec w=nl, u=((fabs(w.x)>.1?Vec(0,1):Vec(1))%w).norm(), v=w%u;
86+
Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm();
87+
r = Ray(x,d);
88+
continue;
89+
//return obj.e + f.mult(radiance(num_spheres, spheres,Ray(x,d),depth,Xi,state));
90+
} else if (obj.refl == SPEC) {r = Ray(x,r.d-n*2*n.dot(r.d)); continue;}
91+
Ray reflRay(x, r.d-n*2*n.dot(r.d)); // Ideal dielectric REFRACTION
92+
bool into = n.dot(nl)>0; // Ray from outside going in?
93+
double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t;
94+
if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) {r=reflRay; continue;} // Total internal reflection
95+
//return obj.e + f.mult(radiance(num_spheres, spheres,reflRay,depth,Xi,state));
96+
Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm();
97+
double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n));
98+
double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P);
99+
r = Ray(x,tdir);
100+
}
101+
return Vec();
84102
}
85103

86104
__global__ void render(const int num_spheres, const Sphere* spheres, Vec* c, int samps){

smallpt/rai_build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ commands:
1313
- /bin/bash -c "cp -r /src/* ."
1414
- cmake /src
1515
- make
16-
- ./cu_smallpt 4000
16+
- ./cu_smallpt 8000
1717
#- ./smallpt 100
1818
#- ./cuda-program ...
1919
#- Evaluate accelerated version ...

0 commit comments

Comments
 (0)