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 "directlighting.h"
00025 #include "bxdf.h"
00026 #include "camera.h"
00027 #include "paramset.h"
00028 #include "dynload.h"
00029
00030 using namespace lux;
00031
00032
00033 DirectLightingIntegrator::DirectLightingIntegrator(LightStrategy st, int md) {
00034 maxDepth = md;
00035 lightStrategy = st;
00036 }
00037
00038 void DirectLightingIntegrator::RequestSamples(Sample *sample, const Scene *scene) {
00039 if (lightStrategy == SAMPLE_AUTOMATIC) {
00040 if (scene->lights.size() > 5)
00041 lightStrategy = SAMPLE_ONE_UNIFORM;
00042 else
00043 lightStrategy = SAMPLE_ALL_UNIFORM;
00044 }
00045
00046 vector<u_int> structure;
00047
00048 structure.push_back(2);
00049 structure.push_back(1);
00050 structure.push_back(2);
00051 structure.push_back(1);
00052
00053 sampleOffset = sample->AddxD(structure, maxDepth + 1);
00054 }
00055
00056 void DirectLightingIntegrator::Preprocess(const TsPack *tspack, const Scene *scene)
00057 {
00058
00059 BufferType type = BUF_TYPE_PER_PIXEL;
00060 scene->sampler->GetBufferType(&type);
00061 bufferId = scene->camera->film->RequestBuffer(type, BUF_FRAMEBUFFER, "eye");
00062 }
00063
00064 int DirectLightingIntegrator::LiInternal(const TsPack *tspack, const Scene *scene,
00065 const RayDifferential &ray, const Sample *sample,
00066 vector<SWCSpectrum> &L, float *alpha, int rayDepth) const {
00067 int nContribs = 0;
00068 Intersection isect;
00069 const float time = ray.time;
00070
00071 if (scene->Intersect(ray, &isect)) {
00072
00073 float *sampleData = sample->sampler->GetLazyValues(const_cast<Sample *>(sample), sampleOffset, rayDepth);
00074 float *lightSample = &sampleData[0];
00075 float *lightNum = &sampleData[2];
00076 float *bsdfSample = &sampleData[3];
00077 float *bsdfComponent = &sampleData[5];
00078
00079
00080 BSDF *bsdf = isect.GetBSDF(tspack, ray);
00081 Vector wo = -ray.d;
00082 const Point &p = bsdf->dgShading.p;
00083 const Normal &n = bsdf->dgShading.nn;
00084
00085
00086 if (isect.arealight) {
00087 L[isect.arealight->group] += isect.Le(tspack, wo);
00088 ++nContribs;
00089 }
00090
00091
00092 if (scene->lights.size() > 0) {
00093
00094 SWCSpectrum Ll;
00095 switch (lightStrategy) {
00096 case SAMPLE_ALL_UNIFORM:
00097 {
00098 const u_int nLights = scene->lights.size();
00099 const float lIncrement = 1.f / nLights;
00100 float l = *lightNum * lIncrement;
00101 for (u_int i = 0; i < nLights; ++i, l += lIncrement) {
00102 int g = UniformSampleOneLight(tspack, scene, p, n,
00103 wo, bsdf, sample,
00104 lightSample, &l, bsdfSample, bsdfComponent, &Ll);
00105 if (!Ll.Black()) {
00106 Ll *= lIncrement;
00107 L[g] += Ll;
00108 ++nContribs;
00109 }
00110 }
00111 break;
00112 }
00113 case SAMPLE_ONE_UNIFORM:
00114 {
00115 int g = UniformSampleOneLight(tspack, scene, p, n,
00116 wo, bsdf, sample,
00117 lightSample, lightNum, bsdfSample, bsdfComponent, &Ll);
00118 if (!Ll.Black()) {
00119 L[g] += Ll;
00120 ++nContribs;
00121 }
00122 break;
00123 }
00124 default:
00125 break;
00126 }
00127 }
00128
00129 if (rayDepth < maxDepth) {
00130 Vector wi;
00131
00132 float pdf;
00133 SWCSpectrum f;
00134 if (bsdf->Sample_f(tspack, wo, &wi, .5f, .5f, .5f, &f, &pdf, BxDFType(BSDF_REFLECTION | BSDF_SPECULAR), NULL, NULL, true)) {
00135
00136 RayDifferential rd(p, wi);
00137 rd.time = time;
00138 rd.hasDifferentials = true;
00139 rd.rx.o = p + isect.dg.dpdx;
00140 rd.ry.o = p + isect.dg.dpdy;
00141
00142 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx +
00143 bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00144 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy +
00145 bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00146 Vector dwodx = -ray.rx.d - wo, dwody = -ray.ry.d - wo;
00147 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00148 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00149 rd.rx.d = wi - dwodx +
00150 2 * Vector(Dot(wo, n) * dndx + dDNdx * n);
00151 rd.ry.d = wi - dwody +
00152 2 * Vector(Dot(wo, n) * dndy + dDNdy * n);
00153 vector<SWCSpectrum> Lr(scene->lightGroups.size(), SWCSpectrum(0.f));
00154 int nc = LiInternal(tspack, scene, rd, sample, Lr, alpha, rayDepth + 1);
00155 if (nc > 0) {
00156 SWCSpectrum filter(f * AbsDot(wi, n));
00157 for (u_int i = 0; i < L.size(); ++i)
00158 L[i] += Lr[i] * filter;
00159 nContribs += nc;
00160 }
00161 }
00162
00163 if (bsdf->Sample_f(tspack, wo, &wi, .5f, .5f, .5f, &f, &pdf, BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR), NULL, NULL, true)) {
00164
00165 RayDifferential rd(p, wi);
00166 rd.time = time;
00167 rd.hasDifferentials = true;
00168 rd.rx.o = p + isect.dg.dpdx;
00169 rd.ry.o = p + isect.dg.dpdy;
00170
00171 float eta = bsdf->eta;
00172 Vector w = -wo;
00173 if (Dot(wo, n) < 0) eta = 1.f / eta;
00174
00175 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx + bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00176 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy + bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00177
00178 Vector dwodx = -ray.rx.d - wo, dwody = -ray.ry.d - wo;
00179 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00180 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00181
00182 float mu = eta * Dot(w, n) - Dot(wi, n);
00183 float dmudx = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdx;
00184 float dmudy = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdy;
00185
00186 rd.rx.d = wi + eta * dwodx - Vector(mu * dndx + dmudx * n);
00187 rd.ry.d = wi + eta * dwody - Vector(mu * dndy + dmudy * n);
00188 vector<SWCSpectrum> Lt(scene->lightGroups.size(), SWCSpectrum(0.f));
00189 int nc = LiInternal(tspack, scene, rd, sample, Lt, alpha, rayDepth + 1);
00190 if (nc > 0) {
00191 SWCSpectrum filter(f * AbsDot(wi, n));
00192 for (u_int i = 0; i < L.size(); ++i)
00193 L[i] += Lt[i] * filter;
00194 nContribs += nc;
00195 }
00196 }
00197 }
00198 } else {
00199
00200 for (u_int i = 0; i < scene->lights.size(); ++i) {
00201 SWCSpectrum Le(scene->lights[i]->Le(tspack, ray));
00202 if (!Le.Black()) {
00203 L[scene->lights[i]->group] += Le;
00204 ++nContribs;
00205 }
00206 }
00207 if (rayDepth == 0)
00208 *alpha = 0.f;
00209 }
00210
00211 if (nContribs > 0) {
00212 SWCSpectrum Lt(1.f);
00213 scene->volumeIntegrator->Transmittance(tspack, scene, ray, sample, alpha, &Lt);
00214 for (u_int i = 0; i < L.size(); ++i)
00215 L[i] *= Lt;
00216 }
00217 SWCSpectrum VLi(0.f);
00218 int g = scene->volumeIntegrator->Li(tspack, scene, ray, sample, &VLi, alpha);
00219 if (!VLi.Black()) {
00220 L[g] += VLi;
00221 ++nContribs;
00222 }
00223
00224 return nContribs;
00225 }
00226
00227 int DirectLightingIntegrator::Li(const TsPack *tspack, const Scene *scene,
00228 const Sample *sample) const {
00229 RayDifferential ray;
00230 float rayWeight = tspack->camera->GenerateRay(*sample, &ray);
00231 if (rayWeight > 0.f) {
00232
00233 ++(sample->imageX);
00234 float wt1 = tspack->camera->GenerateRay(*sample, &ray.rx);
00235 --(sample->imageX);
00236 ++(sample->imageY);
00237 float wt2 = tspack->camera->GenerateRay(*sample, &ray.ry);
00238 ray.hasDifferentials = (wt1 > 0.f) && (wt2 > 0.f);
00239 --(sample->imageY);
00240 }
00241
00242 vector<SWCSpectrum> L(scene->lightGroups.size(), SWCSpectrum(0.f));
00243 float alpha = 1.f;
00244 int nContribs = LiInternal(tspack, scene, ray, sample, L, &alpha, 0);
00245 for (u_int i = 0; i < L.size(); ++i)
00246 sample->AddContribution(sample->imageX, sample->imageY,
00247 L[i].ToXYZ(tspack) * rayWeight, alpha, 0.f, bufferId, i);
00248
00249 return nContribs;
00250 }
00251
00252 SurfaceIntegrator* DirectLightingIntegrator::CreateSurfaceIntegrator(const ParamSet ¶ms) {
00253 int maxDepth = params.FindOneInt("maxdepth", 5);
00254
00255 LightStrategy estrategy;
00256 string st = params.FindOneString("strategy", "auto");
00257 if (st == "one") estrategy = SAMPLE_ONE_UNIFORM;
00258 else if (st == "all") estrategy = SAMPLE_ALL_UNIFORM;
00259 else if (st == "auto") estrategy = SAMPLE_AUTOMATIC;
00260 else {
00261 std::stringstream ss;
00262 ss<<"Strategy '"<<st<<"' for direct lighting unknown. Using \"auto\".";
00263 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
00264 estrategy = SAMPLE_AUTOMATIC;
00265 }
00266
00267 return new DirectLightingIntegrator(estrategy, maxDepth);
00268 }
00269
00270 static DynamicLoader::RegisterSurfaceIntegrator<DirectLightingIntegrator> r("directlighting");