Ejemplo n.º 1
0
Archivo: Main.java Proyecto: merxbj/src
 public static Vec radiance(Ray r, int depth, int[] Xi) {
   double t[] = {0.0}; // distance to intersection
   int id[] = {0}; // id of intersected object
   if (!intersect(r, t, id)) return new Vec(); // if miss, return black
   Sphere obj = spheres[id[0]]; // the hit object
   Vec x = r.o.add(r.d.multiply(t[0]));
   Vec n = (x.substract(obj.p)).norm();
   Vec nl = n.dot(r.d) < 0 ? n : n.multiply(-1);
   Vec f = obj.c;
   double p = f.x > f.y && f.x > f.z ? f.x : f.y > f.z ? f.y : f.z; // max refl
   if (++depth > 5)
     if (erand48(Xi) < p) f = f.multiply(1 / p);
     else return obj.e; // R.R.
   if (obj.refl == Refl_t.DIFF) { // Ideal DIFFUSE reflection
     double r1 = 2 * Math.PI * erand48(Xi), r2 = erand48(Xi), r2s = Math.sqrt(r2);
     Vec w = nl;
     Vec u = ((Math.abs(w.x) > .1 ? new Vec(0, 1) : new Vec(1)).modulo(w)).norm();
     Vec v = w.modulo(u);
     Vec d =
         (u.multiply(Math.cos(r1))
                 .multiply(r2s)
                 .add(v.multiply(Math.sin(r1)).multiply(r2s))
                 .add(w.multiply(Math.sqrt(1 - r2))))
             .norm();
     return obj.e.add(f.mult(radiance(new Ray(x, d), depth, Xi)));
   } else if (obj.refl == Refl_t.SPEC) { // Ideal SPECULAR reflection
     return obj.e.add(
         f.mult(radiance(new Ray(x, r.d.substract(n.multiply(2 * n.dot(r.d)))), depth, Xi)));
   }
   Ray reflRay =
       new Ray(x, r.d.substract(n.multiply(2 * n.dot(r.d)))); // Ideal dielectric REFRACTION
   boolean into = n.dot(nl) > 0; // Ray from outside going in?
   double nc = 1, nt = 1.5, nnt = into ? nc / nt : nt / nc, ddn = r.d.dot(nl), cos2t;
   if ((cos2t = 1 - nnt * nnt * (1 - ddn * ddn)) < 0) // Total internal reflection
   return obj.e.add(f.mult(radiance(reflRay, depth, Xi)));
   Vec tdir =
       (r.d.multiply(nnt).substract(n.multiply((into ? 1 : -1) * (ddn * nnt + Math.sqrt(cos2t)))))
           .norm();
   double a = nt - nc, b = nt + nc, R0 = a * a / (b * b), c = 1 - (into ? -ddn : tdir.dot(n));
   double Re = R0 + (1 - R0) * c * c * c * c * c,
       Tr = 1 - Re,
       P = .25 + .5 * Re,
       RP = Re / P,
       TP = Tr / (1 - P);
   return obj.e.add(
       f.mult(
           depth > 2
               ? (erand48(Xi) < P
                   ? // Russian roulette
                   radiance(reflRay, depth, Xi).multiply(RP)
                   : radiance(new Ray(x, tdir), depth, Xi).multiply(TP))
               : radiance(reflRay, depth, Xi)
                   .multiply(Re)
                   .add(radiance(new Ray(x, tdir), depth, Xi).multiply(Tr))));
 }