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
00026 #include "stdafx.h"
00027 #include "integrator.h"
00028 #include "scene.h"
00029 #include "intersection.h"
00030 #include "montecarlo.h"
00031
00032
00033 Integrator::~Integrator() {
00034 }
00035
00036
00037
00038
00039 Spectrum UniformSampleAllLights(const Scene *scene,
00040 const Renderer *renderer, MemoryArena &arena, const Point &p,
00041 const Normal &n, const Vector &wo, float rayEpsilon,
00042 float time, BSDF *bsdf, const Sample *sample, RNG &rng,
00043 const LightSampleOffsets *lightSampleOffsets,
00044 const BSDFSampleOffsets *bsdfSampleOffsets) {
00045 Spectrum L(0.);
00046 for (uint32_t i = 0; i < scene->lights.size(); ++i) {
00047 Light *light = scene->lights[i];
00048 int nSamples = lightSampleOffsets ?
00049 lightSampleOffsets[i].nSamples : 1;
00050
00051 Spectrum Ld(0.);
00052 for (int j = 0; j < nSamples; ++j) {
00053
00054 LightSample lightSample;
00055 BSDFSample bsdfSample;
00056 if (lightSampleOffsets != NULL && bsdfSampleOffsets != NULL) {
00057 lightSample = LightSample(sample, lightSampleOffsets[i], j);
00058 bsdfSample = BSDFSample(sample, bsdfSampleOffsets[i], j);
00059 }
00060 else {
00061 lightSample = LightSample(rng);
00062 bsdfSample = BSDFSample(rng);
00063 }
00064 Ld += EstimateDirect(scene, renderer, arena, light, p, n, wo,
00065 rayEpsilon, time, bsdf, rng, lightSample, bsdfSample,
00066 BxDFType(BSDF_ALL & ~BSDF_SPECULAR));
00067 }
00068 L += Ld / nSamples;
00069 }
00070 return L;
00071 }
00072
00073
00074 Spectrum UniformSampleOneLight(const Scene *scene,
00075 const Renderer *renderer, MemoryArena &arena, const Point &p,
00076 const Normal &n, const Vector &wo, float rayEpsilon, float time,
00077 BSDF *bsdf, const Sample *sample, RNG &rng, int lightNumOffset,
00078 const LightSampleOffsets *lightSampleOffset,
00079 const BSDFSampleOffsets *bsdfSampleOffset) {
00080
00081 int nLights = int(scene->lights.size());
00082 if (nLights == 0) return Spectrum(0.);
00083 int lightNum;
00084 if (lightNumOffset != -1)
00085 lightNum = Floor2Int(sample->oneD[lightNumOffset][0] * nLights);
00086 else
00087 lightNum = Floor2Int(rng.RandomFloat() * nLights);
00088 lightNum = min(lightNum, nLights-1);
00089 Light *light = scene->lights[lightNum];
00090
00091
00092 LightSample lightSample;
00093 BSDFSample bsdfSample;
00094 if (lightSampleOffset != NULL && bsdfSampleOffset != NULL) {
00095 lightSample = LightSample(sample, *lightSampleOffset, 0);
00096 bsdfSample = BSDFSample(sample, *bsdfSampleOffset, 0);
00097 }
00098 else {
00099 lightSample = LightSample(rng);
00100 bsdfSample = BSDFSample(rng);
00101 }
00102 return (float)nLights *
00103 EstimateDirect(scene, renderer, arena, light, p, n, wo,
00104 rayEpsilon, time, bsdf, rng, lightSample,
00105 bsdfSample, BxDFType(BSDF_ALL & ~BSDF_SPECULAR));
00106 }
00107
00108
00109 Spectrum EstimateDirect(const Scene *scene, const Renderer *renderer,
00110 MemoryArena &arena, const Light *light, const Point &p,
00111 const Normal &n, const Vector &wo, float rayEpsilon, float time,
00112 const BSDF *bsdf, RNG &rng, const LightSample &lightSample,
00113 const BSDFSample &bsdfSample, BxDFType flags) {
00114 Spectrum Ld(0.);
00115
00116 Vector wi;
00117 float lightPdf, bsdfPdf;
00118 VisibilityTester visibility;
00119 Spectrum Li = light->Sample_L(p, rayEpsilon, lightSample, time,
00120 &wi, &lightPdf, &visibility);
00121 if (lightPdf > 0. && !Li.IsBlack()) {
00122 Spectrum f = bsdf->f(wo, wi, flags);
00123 if (!f.IsBlack() && visibility.Unoccluded(scene)) {
00124
00125 Li *= visibility.Transmittance(scene, renderer, NULL, rng, arena);
00126 if (light->IsDeltaLight())
00127 Ld += f * Li * (AbsDot(wi, n) / lightPdf);
00128 else {
00129 bsdfPdf = bsdf->Pdf(wo, wi, flags);
00130 float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);
00131 Ld += f * Li * (AbsDot(wi, n) * weight / lightPdf);
00132 }
00133 }
00134 }
00135
00136
00137 if (!light->IsDeltaLight()) {
00138 BxDFType sampledType;
00139 Spectrum f = bsdf->Sample_f(wo, &wi, bsdfSample, &bsdfPdf, flags,
00140 &sampledType);
00141 if (!f.IsBlack() && bsdfPdf > 0.) {
00142 float weight = 1.f;
00143 if (!(sampledType & BSDF_SPECULAR)) {
00144 lightPdf = light->Pdf(p, wi);
00145 if (lightPdf == 0.)
00146 return Ld;
00147 weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);
00148 }
00149
00150 Intersection lightIsect;
00151 Spectrum Li(0.f);
00152 RayDifferential ray(p, wi, rayEpsilon, INFINITY, time);
00153 if (scene->Intersect(ray, &lightIsect)) {
00154 if (lightIsect.primitive->GetAreaLight() == light)
00155 Li = lightIsect.Le(-wi);
00156 }
00157 else
00158 Li = light->Le(ray);
00159 if (!Li.IsBlack()) {
00160 Li *= renderer->Transmittance(scene, ray, NULL, rng, arena);
00161 Ld += f * Li * AbsDot(wi, n) * weight / bsdfPdf;
00162 }
00163 }
00164 }
00165 return Ld;
00166 }
00167
00168
00169 Spectrum SpecularReflect(const RayDifferential &ray, BSDF *bsdf,
00170 RNG &rng, const Intersection &isect, const Renderer *renderer,
00171 const Scene *scene, const Sample *sample, MemoryArena &arena) {
00172 Vector wo = -ray.d, wi;
00173 float pdf;
00174 const Point &p = bsdf->dgShading.p;
00175 const Normal &n = bsdf->dgShading.nn;
00176 Spectrum f = bsdf->Sample_f(wo, &wi, BSDFSample(rng), &pdf,
00177 BxDFType(BSDF_REFLECTION | BSDF_SPECULAR));
00178 Spectrum L = 0.f;
00179 if (pdf > 0.f && !f.IsBlack() && AbsDot(wi, n) != 0.f) {
00180
00181 RayDifferential rd(p, wi, ray, isect.rayEpsilon);
00182 if (ray.hasDifferentials) {
00183 rd.hasDifferentials = true;
00184 rd.rxOrigin = p + isect.dg.dpdx;
00185 rd.ryOrigin = p + isect.dg.dpdy;
00186
00187 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx +
00188 bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00189 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy +
00190 bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00191 Vector dwodx = -ray.rxDirection - wo, dwody = -ray.ryDirection - wo;
00192 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00193 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00194 rd.rxDirection = wi - dwodx + 2 * Vector(Dot(wo, n) * dndx +
00195 dDNdx * n);
00196 rd.ryDirection = wi - dwody + 2 * Vector(Dot(wo, n) * dndy +
00197 dDNdy * n);
00198 }
00199 PBRT_STARTED_SPECULAR_REFLECTION_RAY(const_cast<RayDifferential *>(&rd));
00200 Spectrum Li = renderer->Li(scene, rd, sample, rng, arena);
00201 L = f * Li * AbsDot(wi, n) / pdf;
00202 PBRT_FINISHED_SPECULAR_REFLECTION_RAY(const_cast<RayDifferential *>(&rd));
00203 }
00204 return L;
00205 }
00206
00207
00208 Spectrum SpecularTransmit(const RayDifferential &ray, BSDF *bsdf,
00209 RNG &rng, const Intersection &isect, const Renderer *renderer,
00210 const Scene *scene, const Sample *sample, MemoryArena &arena) {
00211 Vector wo = -ray.d, wi;
00212 float pdf;
00213 const Point &p = bsdf->dgShading.p;
00214 const Normal &n = bsdf->dgShading.nn;
00215 Spectrum f = bsdf->Sample_f(wo, &wi, BSDFSample(rng), &pdf,
00216 BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR));
00217 Spectrum L = 0.f;
00218 if (pdf > 0.f && !f.IsBlack() && AbsDot(wi, n) != 0.f) {
00219
00220 RayDifferential rd(p, wi, ray, isect.rayEpsilon);
00221 if (ray.hasDifferentials) {
00222 rd.hasDifferentials = true;
00223 rd.rxOrigin = p + isect.dg.dpdx;
00224 rd.ryOrigin = p + isect.dg.dpdy;
00225
00226 float eta = bsdf->eta;
00227 Vector w = -wo;
00228 if (Dot(wo, n) < 0) eta = 1.f / eta;
00229
00230 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx + bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00231 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy + bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00232
00233 Vector dwodx = -ray.rxDirection - wo, dwody = -ray.ryDirection - wo;
00234 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00235 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00236
00237 float mu = eta * Dot(w, n) - Dot(wi, n);
00238 float dmudx = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdx;
00239 float dmudy = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdy;
00240
00241 rd.rxDirection = wi + eta * dwodx - Vector(mu * dndx + dmudx * n);
00242 rd.ryDirection = wi + eta * dwody - Vector(mu * dndy + dmudy * n);
00243 }
00244 PBRT_STARTED_SPECULAR_REFRACTION_RAY(const_cast<RayDifferential *>(&rd));
00245 Spectrum Li = renderer->Li(scene, rd, sample, rng, arena);
00246 L = f * Li * AbsDot(wi, n) / pdf;
00247 PBRT_FINISHED_SPECULAR_REFRACTION_RAY(const_cast<RayDifferential *>(&rd));
00248 }
00249 return L;
00250 }
00251
00252
00253 Distribution1D *ComputeLightSamplingCDF(const Scene *scene) {
00254 uint32_t nLights = int(scene->lights.size());
00255 Assert(nLights > 0);
00256 vector<float>lightPower(nLights, 0.f);
00257 for (uint32_t i = 0; i < nLights; ++i)
00258 lightPower[i] = scene->lights[i]->Power(scene).y();
00259 return new Distribution1D(&lightPower[0], nLights);
00260 }
00261
00262