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 "paramset.h"
00027
00028 using namespace lux;
00029
00030
00031 DirectLighting::DirectLighting(LightStrategy st, int md) {
00032 maxDepth = md;
00033 lightStrategy = st;
00034 }
00035
00036 void DirectLighting::RequestSamples(Sample *sample, const Scene *scene) {
00037 if (lightStrategy == SAMPLE_AUTOMATIC) {
00038 if (scene->lights.size() > 10)
00039 lightStrategy = SAMPLE_ONE_UNIFORM;
00040 else
00041 lightStrategy = SAMPLE_ALL_UNIFORM;
00042 }
00043
00044 vector<u_int> structure;
00045 if (lightStrategy == SAMPLE_ALL_UNIFORM) {
00046
00047 structure.push_back(2);
00048 structure.push_back(2);
00049 structure.push_back(1);
00050 } else {
00051
00052 structure.push_back(2);
00053 structure.push_back(1);
00054 structure.push_back(2);
00055 structure.push_back(1);
00056 }
00057
00058 sampleOffset = sample->AddxD(structure, maxDepth + 1);
00059 }
00060
00061 SWCSpectrum DirectLighting::LiInternal(const Scene *scene,
00062 const RayDifferential &ray, const Sample *sample,
00063 float *alpha, int rayDepth) const {
00064 Intersection isect;
00065 SWCSpectrum L(0.);
00066 if (alpha) *alpha = 1.;
00067
00068 if (scene->Intersect(ray, &isect)) {
00069
00070 float *sampleData = sample->sampler->GetLazyValues(const_cast<Sample *>(sample), sampleOffset, rayDepth);
00071 float *lightSample, *lightNum, *bsdfSample, *bsdfComponent;
00072 if (lightStrategy == SAMPLE_ALL_UNIFORM) {
00073 lightSample = &sampleData[0];
00074 lightNum = NULL;
00075 bsdfSample = &sampleData[2];
00076 bsdfComponent = &sampleData[4];
00077 } else {
00078 lightSample = &sampleData[0];
00079 lightNum = &sampleData[2];
00080 bsdfSample = &sampleData[3];
00081 bsdfComponent = &sampleData[5];
00082 }
00083
00084
00085 BSDF *bsdf = isect.GetBSDF(ray, fabsf(2.f * bsdfComponent[0] - 1.f));
00086 Vector wo = -ray.d;
00087 const Point &p = bsdf->dgShading.p;
00088 const Normal &n = bsdf->dgShading.nn;
00089
00090
00091 L += isect.Le(wo);
00092
00093
00094 if (scene->lights.size() > 0) {
00095
00096 switch (lightStrategy) {
00097 case SAMPLE_ALL_UNIFORM:
00098 L += UniformSampleAllLights(scene, p, n,
00099 wo, bsdf, sample,
00100 lightSample, bsdfSample, bsdfComponent);
00101 break;
00102 case SAMPLE_ONE_UNIFORM:
00103 L += UniformSampleOneLight(scene, p, n,
00104 wo, bsdf, sample,
00105 lightSample, lightNum, bsdfSample, bsdfComponent);
00106 break;
00107 default:
00108 break;
00109 }
00110 }
00111
00112 if (rayDepth < maxDepth) {
00113 Vector wi;
00114
00115 SWCSpectrum f = bsdf->Sample_f(wo, &wi,
00116 BxDFType(BSDF_REFLECTION | BSDF_SPECULAR));
00117 if (!f.Black()) {
00118
00119 RayDifferential rd(p, wi);
00120 rd.hasDifferentials = true;
00121 rd.rx.o = p + isect.dg.dpdx;
00122 rd.ry.o = p + isect.dg.dpdy;
00123
00124 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx +
00125 bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00126 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy +
00127 bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00128 Vector dwodx = -ray.rx.d - wo, dwody = -ray.ry.d - wo;
00129 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00130 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00131 rd.rx.d = wi -
00132 dwodx + 2 * Vector(Dot(wo, n) * dndx +
00133 dDNdx * n);
00134 rd.ry.d = wi -
00135 dwody + 2 * Vector(Dot(wo, n) * dndy +
00136 dDNdy * n);
00137
00138 L += LiInternal(scene, rd, sample, alpha, rayDepth + 1) * f * AbsDot(wi, n);
00139 }
00140
00141 f = bsdf->Sample_f(wo, &wi,
00142 BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR));
00143 if (!f.Black()) {
00144
00145 RayDifferential rd(p, wi);
00146 rd.hasDifferentials = true;
00147 rd.rx.o = p + isect.dg.dpdx;
00148 rd.ry.o = p + isect.dg.dpdy;
00149
00150 float eta = bsdf->eta;
00151 Vector w = -wo;
00152 if (Dot(wo, n) < 0) eta = 1.f / eta;
00153
00154 Normal dndx = bsdf->dgShading.dndu * bsdf->dgShading.dudx + bsdf->dgShading.dndv * bsdf->dgShading.dvdx;
00155 Normal dndy = bsdf->dgShading.dndu * bsdf->dgShading.dudy + bsdf->dgShading.dndv * bsdf->dgShading.dvdy;
00156
00157 Vector dwodx = -ray.rx.d - wo, dwody = -ray.ry.d - wo;
00158 float dDNdx = Dot(dwodx, n) + Dot(wo, dndx);
00159 float dDNdy = Dot(dwody, n) + Dot(wo, dndy);
00160
00161 float mu = eta * Dot(w, n) - Dot(wi, n);
00162 float dmudx = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdx;
00163 float dmudy = (eta - (eta*eta*Dot(w,n))/Dot(wi, n)) * dDNdy;
00164
00165 rd.rx.d = wi + eta * dwodx - Vector(mu * dndx + dmudx * n);
00166 rd.ry.d = wi + eta * dwody - Vector(mu * dndy + dmudy * n);
00167
00168 L += LiInternal(scene, rd, sample, alpha, rayDepth + 1) * f * AbsDot(wi, n);
00169 }
00170 }
00171 } else {
00172
00173 for (u_int i = 0; i < scene->lights.size(); ++i)
00174 L += scene->lights[i]->Le(ray);
00175 if (alpha && L.Black()) *alpha = 0.;
00176 }
00177
00178 return L * scene->volumeIntegrator->Transmittance(scene, ray, sample, alpha) + scene->volumeIntegrator->Li(scene, ray, sample, alpha);
00179 }
00180
00181 SWCSpectrum DirectLighting::Li(const Scene *scene,
00182 const RayDifferential &ray, const Sample *sample,
00183 float *alpha) const {
00184 SampleGuard guard(sample->sampler, sample);
00185
00186 sample->AddContribution(sample->imageX, sample->imageY,
00187 LiInternal(scene, ray, sample, alpha, 0).ToXYZ(),
00188 alpha ? *alpha : 1.f);
00189
00190 return SWCSpectrum(-1.f);
00191 }
00192
00193 SurfaceIntegrator* DirectLighting::CreateSurfaceIntegrator(const ParamSet ¶ms) {
00194 int maxDepth = params.FindOneInt("maxdepth", 5);
00195
00196 LightStrategy estrategy;
00197 string st = params.FindOneString("strategy", "auto");
00198 if (st == "one") estrategy = SAMPLE_ONE_UNIFORM;
00199 else if (st == "all") estrategy = SAMPLE_ALL_UNIFORM;
00200 else if (st == "auto") estrategy = SAMPLE_AUTOMATIC;
00201 else {
00202 std::stringstream ss;
00203 ss<<"Strategy '"<<st<<"' for direct lighting unknown. Using \"auto\".";
00204 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
00205 estrategy = SAMPLE_AUTOMATIC;
00206 }
00207
00208 return new DirectLighting(estrategy, maxDepth);
00209 }