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