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 "integrators/glossyprt.h"
00028 #include "sh.h"
00029 #include "light.h"
00030 #include "scene.h"
00031 #include "camera.h"
00032 #include "intersection.h"
00033 #include "paramset.h"
00034
00035
00036 GlossyPRTIntegrator::~GlossyPRTIntegrator() {
00037 delete[] c_in;
00038 delete[] B;
00039 }
00040
00041
00042 void GlossyPRTIntegrator::Preprocess(const Scene *scene,
00043 const Camera *camera, const Renderer *renderer) {
00044
00045 BBox bbox = scene->WorldBound();
00046 Point p = .5f * bbox.pMin + .5f * bbox.pMax;
00047 RNG rng;
00048 MemoryArena arena;
00049 c_in = new Spectrum[SHTerms(lmax)];
00050 SHProjectIncidentDirectRadiance(p, 0.f, camera->shutterOpen, arena,
00051 scene, false, lmax, rng, c_in);
00052
00053
00054 B = new Spectrum[SHTerms(lmax)*SHTerms(lmax)];
00055 SHComputeBSDFMatrix(Kd, Ks, roughness, rng, 1024, lmax, B);
00056 }
00057
00058
00059 void GlossyPRTIntegrator::RequestSamples(Sampler *sampler, Sample *sample, const Scene *scene) {
00060 }
00061
00062
00063 Spectrum GlossyPRTIntegrator::Li(const Scene *scene, const Renderer *,
00064 const RayDifferential &ray, const Intersection &isect,
00065 const Sample *sample, RNG &rng, MemoryArena &arena) const {
00066 Spectrum L = 0.f;
00067 Vector wo = -ray.d;
00068
00069 L += isect.Le(wo);
00070
00071
00072 BSDF *bsdf = isect.GetBSDF(ray, arena);
00073 const Point &p = bsdf->dgShading.p;
00074
00075
00076
00077 Spectrum *c_t = arena.Alloc<Spectrum>(SHTerms(lmax));
00078 Spectrum *T = arena.Alloc<Spectrum>(SHTerms(lmax)*SHTerms(lmax));
00079 SHComputeTransferMatrix(p, isect.rayEpsilon, scene, rng, nSamples,
00080 lmax, T);
00081 SHMatrixVectorMultiply(T, c_in, c_t, lmax);
00082
00083
00084 Vector r1 = bsdf->LocalToWorld(Vector(1,0,0));
00085 Vector r2 = bsdf->LocalToWorld(Vector(0,1,0));
00086 Normal nl = Normal(bsdf->LocalToWorld(Vector(0,0,1)));
00087 Matrix4x4 rot(r1.x, r2.x, nl.x, 0,
00088 r1.y, r2.y, nl.y, 0,
00089 r1.z, r2.z, nl.z, 0,
00090 0, 0, 0, 1);
00091 Spectrum *c_l = arena.Alloc<Spectrum>(SHTerms(lmax));
00092 SHRotate(c_t, c_l, rot, lmax, arena);
00093 #if 0
00094
00095
00096 float *Ylm = ALLOCA(float, SHTerms(lmax));
00097 int ns = 1024;
00098 for (int i = 0; i < ns; ++i) {
00099 Vector wi;
00100 float pdf;
00101 Spectrum f = bsdf->Sample_f(wo, &wi, BSDFSample(rng), &pdf);
00102 if (pdf > 0.f && !f.IsBlack() && !scene->IntersectP(Ray(p, wi))) {
00103 f *= fabsf(Dot(wi, n)) / (pdf * ns);
00104 SHEvaluate(bsdf->WorldToLocal(wi), lmax, Ylm);
00105
00106 Spectrum Li = 0.f;
00107 for (int j = 0; j < SHTerms(lmax); ++j)
00108 Li += Ylm[j] * c_l[j] * f;
00109 L += Li.Clamp();
00110 }
00111 }
00112 #else
00113
00114
00115 Spectrum *c_o = arena.Alloc<Spectrum>(SHTerms(lmax));
00116 SHMatrixVectorMultiply(B, c_l, c_o, lmax);
00117
00118
00119 Vector woLocal = bsdf->WorldToLocal(wo);
00120 float *Ylm = ALLOCA(float, SHTerms(lmax));
00121 SHEvaluate(woLocal, lmax, Ylm);
00122 Spectrum Li = 0.f;
00123 for (int i = 0; i < SHTerms(lmax); ++i)
00124 Li += Ylm[i] * c_o[i];
00125 L += Li.Clamp();
00126 #endif
00127 return L;
00128 }
00129
00130
00131 GlossyPRTIntegrator *CreateGlossyPRTIntegratorSurfaceIntegrator(const ParamSet ¶ms) {
00132 int lmax = params.FindOneInt("lmax", 4);
00133 int ns = params.FindOneInt("nsamples", 4096);
00134 Spectrum Kd = params.FindOneSpectrum("Kd", Spectrum(0.5f));
00135 Spectrum Ks = params.FindOneSpectrum("Ks", Spectrum(0.25f));
00136 float roughness = params.FindOneFloat("roughness", 0.1f);
00137 return new GlossyPRTIntegrator(Kd, Ks, roughness, lmax, ns);
00138 }
00139
00140