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 "environment.h"
00025 #include "sampling.h"
00026 #include "mc.h"
00027 #include "scene.h"
00028 #include "film.h"
00029 #include "reflection/bxdf.h"
00030 #include "light.h"
00031 #include "paramset.h"
00032 #include "dynload.h"
00033
00034 using namespace lux;
00035
00036 class EnvironmentBxDF : public BxDF {
00037 public:
00038 EnvironmentBxDF() :
00039 BxDF(BxDFType(BSDF_REFLECTION | BSDF_DIFFUSE)) {}
00040 virtual ~EnvironmentBxDF() { }
00041 virtual void f(const TsPack *tspack, const Vector &wo, const Vector &wi, SWCSpectrum *const F) const {
00042 *F += SWCSpectrum(SameHemisphere(wo, wi) ? fabsf(wi.z) * INV_PI : 0.f);
00043 }
00044 };
00045
00046
00047 EnvironmentCamera::
00048 EnvironmentCamera(const Transform &world2camStart, const Transform &world2camEnd,
00049 float hither, float yon, float sopen, float sclose, int sdist,
00050 Film *film)
00051 : Camera(world2camStart, world2camEnd, hither, yon, sopen, sclose, sdist, film) {
00052 pos = CameraToWorld(Point(0, 0, 0));
00053 }
00054 float EnvironmentCamera::GenerateRay(const Sample &sample,
00055 Ray *ray) const {
00056 ray->o = CameraToWorld(Point(0,0,0));
00057
00058 float theta = M_PI * sample.imageY / film->yResolution;
00059 float phi = 2 * M_PI * sample.imageX / film->xResolution;
00060 Vector dir(sinf(theta) * cosf(phi), cosf(theta),
00061 sinf(theta) * sinf(phi));
00062 CameraToWorld(dir, &ray->d);
00063
00064 ray->time = GetTime(sample.time);
00065 ray->mint = ClipHither;
00066 ray->maxt = ClipYon;
00067 return 1.f;
00068 }
00069
00070 bool EnvironmentCamera::Sample_W(const TsPack *tspack, const Scene *scene, float u1, float u2, float u3, BSDF **bsdf, float *pdf, SWCSpectrum *We) const
00071 {
00072 const float theta = M_PI * u2 / film->yResolution;
00073 const float phi = 2 * M_PI * u1 / film->xResolution;
00074 Normal ns(sinf(theta) * cosf(phi), cosf(theta),
00075 sinf(theta) * sinf(phi));
00076 CameraToWorld(ns, &ns);
00077 Vector dpdu, dpdv;
00078 CoordinateSystem(Vector(ns), &dpdu, &dpdv);
00079 DifferentialGeometry dg(pos, ns, dpdu, dpdv, Normal(0, 0, 0), Normal(0, 0, 0), 0, 0, NULL);
00080 *bsdf = BSDF_ALLOC(tspack, SingleBSDF)(dg, ns,
00081 BSDF_ALLOC(tspack, EnvironmentBxDF)());
00082 *pdf = UniformSpherePdf();
00083 *We = SWCSpectrum(*pdf);
00084 return true;
00085 }
00086 bool EnvironmentCamera::Sample_W(const TsPack *tspack, const Scene *scene, const Point &p, const Normal &n, float u1, float u2, float u3, BSDF **bsdf, float *pdf, float *pdfDirect, VisibilityTester *visibility, SWCSpectrum *We) const
00087 {
00088 const Vector w(p - pos);
00089 Normal ns(Normalize(w));
00090 Vector dpdu, dpdv;
00091 CoordinateSystem(Vector(ns), &dpdu, &dpdv);
00092 DifferentialGeometry dg(pos, ns, dpdu, dpdv, Normal(0, 0, 0), Normal(0, 0, 0), 0, 0, NULL);
00093 *bsdf = BSDF_ALLOC(tspack, SingleBSDF)(dg, ns,
00094 BSDF_ALLOC(tspack, EnvironmentBxDF)());
00095 *pdf = UniformSpherePdf();
00096 *pdfDirect = 1.f;
00097 visibility->SetSegment(p, pos, tspack->time);
00098 *We = SWCSpectrum(*pdf);
00099 return true;
00100 }
00101
00102 BBox EnvironmentCamera::Bounds() const
00103 {
00104 BBox bound(pos);
00105 bound.Expand(MachineEpsilon::E(bound));
00106 return bound;
00107 }
00108
00109 bool EnvironmentCamera::GetSamplePosition(const Point &p, const Vector &wi, float distance, float *x, float *y) const
00110 {
00111 if (distance < ClipHither || distance > ClipYon)
00112 return false;
00113 const Vector w = WorldToCamera(wi);
00114 const float cosTheta = w.y;
00115 const float theta = acos(min(1.f, cosTheta));
00116 *y = theta * film->yResolution * INV_PI;
00117 const float sinTheta = sqrtf(Clamp(1.f - cosTheta * cosTheta, 1e-5f, 1.f));
00118 const float cosPhi = w.x / sinTheta;
00119 const float phi = acos(Clamp(cosPhi, -1.f, 1.f));
00120 if (w.z >= 0.f)
00121 *x = phi * film->xResolution * INV_TWOPI;
00122 else
00123 *x = (2.f * M_PI - phi) * film->xResolution * INV_TWOPI;
00124
00125 return true;
00126 }
00127
00128 void EnvironmentCamera::ClampRay(Ray &ray) const
00129 {
00130 ray.mint = ClipHither;
00131 ray.maxt = ClipYon;
00132 }
00133
00134 Camera* EnvironmentCamera::CreateCamera(const Transform &world2camStart, const Transform &world2camEnd,
00135 const ParamSet ¶ms, Film *film)
00136 {
00137
00138 float hither = max(1e-4f, params.FindOneFloat("hither", 1e-3f));
00139 float yon = min(params.FindOneFloat("yon", 1e30f), 1e30f);
00140
00141 float shutteropen = params.FindOneFloat("shutteropen", 0.f);
00142 float shutterclose = params.FindOneFloat("shutterclose", 1.f);
00143 int shutterdist = 0;
00144 string shutterdistribution = params.FindOneString("shutterdistribution", "uniform");
00145 if (shutterdistribution == "uniform") shutterdist = 0;
00146 else if (shutterdistribution == "gaussian") shutterdist = 1;
00147 else {
00148 std::stringstream ss;
00149 ss<<"Distribution '"<<shutterdistribution<<"' for perspective camera shutter sampling unknown. Using \"uniform\".";
00150 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
00151 shutterdist = 0;
00152 }
00153
00154 float lensradius = params.FindOneFloat("lensradius", 0.f);
00155 float focaldistance = params.FindOneFloat("focaldistance", 1e30f);
00156 float frame = params.FindOneFloat("frameaspectratio",
00157 float(film->xResolution)/float(film->yResolution));
00158 float screen[4];
00159 if (frame > 1.f) {
00160 screen[0] = -frame;
00161 screen[1] = frame;
00162 screen[2] = -1.f;
00163 screen[3] = 1.f;
00164 }
00165 else {
00166 screen[0] = -1.f;
00167 screen[1] = 1.f;
00168 screen[2] = -1.f / frame;
00169 screen[3] = 1.f / frame;
00170 }
00171 int swi;
00172 const float *sw = params.FindFloat("screenwindow", &swi);
00173 if (sw && swi == 4)
00174 memcpy(screen, sw, 4*sizeof(float));
00175 (void) lensradius;
00176 (void) focaldistance;
00177 return new EnvironmentCamera(world2camStart, world2camEnd, hither, yon,
00178 shutteropen, shutterclose, shutterdist, film);
00179 }
00180
00181 static DynamicLoader::RegisterCamera<EnvironmentCamera> r("environment");