00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "whitted.h"
00025
00026 using namespace lux;
00027
00028
00029 WhittedIntegrator* WhittedIntegrator::clone() const
00030 {
00031 return new WhittedIntegrator(*this);
00032 }
00033
00034 Spectrum WhittedIntegrator::Li(const Scene *scene,
00035 const RayDifferential &ray, const Sample *sample,
00036 float *alpha) const {
00037 Intersection isect;
00038 Spectrum L(0.);
00039 bool hitSomething;
00040
00041 hitSomething = scene->Intersect(ray, &isect);
00042 if (!hitSomething) {
00043
00044 if (alpha) *alpha = 0.;
00045 for (u_int i = 0; i < scene->lights.size(); ++i)
00046 L += scene->lights[i]->Le(ray);
00047 if (alpha && !L.Black()) *alpha = 1.;
00048 return L;
00049 }
00050 else {
00051
00052 if (alpha) *alpha = 1.;
00053
00054
00055 BSDF *bsdf = isect.GetBSDF( ray);
00056
00057 const Point &p = bsdf->dgShading.p;
00058 const Normal &n = bsdf->dgShading.nn;
00059 Vector wo = -ray.d;
00060
00061 L += isect.Le(wo);
00062
00063 Vector wi;
00064 for (u_int i = 0; i < scene->lights.size(); ++i) {
00065 VisibilityTester visibility;
00066 Spectrum Li = scene->lights[i]->Sample_L(p, &wi, &visibility);
00067 if (Li.Black()) continue;
00068 Spectrum f = bsdf->f(wo, wi);
00069 if (!f.Black() && visibility.Unoccluded(scene))
00070 L += f * Li * AbsDot(wi, n) * visibility.Transmittance(scene);
00071 }
00072 if (rayDepth++ < maxDepth) {
00073
00074 Spectrum f = bsdf->Sample_f(wo, &wi,
00075 BxDFType(BSDF_REFLECTION | BSDF_SPECULAR));
00076 if (!f.Black()) {
00077
00078 RayDifferential rd(p, wi);
00079 rd.hasDifferentials = true;
00080 rd.rx.o = p + isect.dg.dpdx;
00081 rd.ry.o = p + isect.dg.dpdy;
00082
00083 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx +
00084 bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00085 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy +
00086 bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00087 Vector dwodx = -ray.rx.d - wo, dwody = -ray.ry.d - wo;
00088 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00089 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00090 rd.rx.d = wi -
00091 dwodx + 2 * Vector(Dot(wo, n) * dndx +
00092 dDNdx * n);
00093 rd.ry.d = wi -
00094 dwody + 2 * Vector(Dot(wo, n) * dndy +
00095 dDNdy * n);
00096 L += scene->Li(rd, sample) * f * AbsDot(wi, n);
00097 }
00098 f = bsdf->Sample_f(wo, &wi,
00099 BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR));
00100 if (!f.Black()) {
00101
00102 RayDifferential rd(p, wi);
00103 rd.hasDifferentials = true;
00104 rd.rx.o = p + isect.dg.dpdx;
00105 rd.ry.o = p + isect.dg.dpdy;
00106
00107 float eta = bsdf->eta;
00108 Vector w = -wo;
00109 if (Dot(wo, n) < 0) eta = 1.f / eta;
00110
00111 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx + bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00112 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy + bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00113
00114 Vector dwodx = -ray.rx.d - wo, dwody = -ray.ry.d - wo;
00115 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00116 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00117
00118 float mu = eta * Dot(w, n) - Dot(wi, n);
00119 float dmudx = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdx;
00120 float dmudy = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdy;
00121
00122 rd.rx.d = wi + eta * dwodx - Vector(mu * dndx + dmudx * n);
00123 rd.ry.d = wi + eta * dwody - Vector(mu * dndy + dmudy * n);
00124 L += scene->Li(rd, sample) * f * AbsDot(wi, n);
00125 }
00126 }
00127 --rayDepth;
00128 }
00129 return L;
00130 }
00131 SurfaceIntegrator* WhittedIntegrator::CreateSurfaceIntegrator(const ParamSet ¶ms)
00132 {
00133 int maxDepth = params.FindOneInt("maxdepth", 5);
00134 return new WhittedIntegrator(maxDepth);
00135 }