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 "api.h"
00028 #include "parallel.h"
00029 #include "paramset.h"
00030 #include "spectrum.h"
00031 #include "scene.h"
00032 #include "renderer.h"
00033 #include "film.h"
00034 #include "volume.h"
00035 #include "probes.h"
00036
00037
00038 #include "accelerators/bvh.h"
00039 #include "accelerators/grid.h"
00040 #include "accelerators/kdtreeaccel.h"
00041 #include "cameras/environment.h"
00042 #include "cameras/orthographic.h"
00043 #include "cameras/perspective.h"
00044 #include "film/image.h"
00045 #include "filters/box.h"
00046 #include "filters/gaussian.h"
00047 #include "filters/mitchell.h"
00048 #include "filters/sinc.h"
00049 #include "filters/triangle.h"
00050 #include "integrators/ambientocclusion.h"
00051 #include "integrators/diffuseprt.h"
00052 #include "integrators/dipolesubsurface.h"
00053 #include "integrators/directlighting.h"
00054 #include "integrators/emission.h"
00055 #include "integrators/glossyprt.h"
00056 #include "integrators/igi.h"
00057 #include "integrators/irradiancecache.h"
00058 #include "integrators/path.h"
00059 #include "integrators/photonmap.h"
00060 #include "integrators/single.h"
00061 #include "integrators/useprobes.h"
00062 #include "integrators/whitted.h"
00063 #include "lights/diffuse.h"
00064 #include "lights/distant.h"
00065 #include "lights/goniometric.h"
00066 #include "lights/infinite.h"
00067 #include "lights/point.h"
00068 #include "lights/projection.h"
00069 #include "lights/spot.h"
00070 #include "materials/glass.h"
00071 #include "materials/kdsubsurface.h"
00072 #include "materials/matte.h"
00073 #include "materials/measured.h"
00074 #include "materials/metal.h"
00075 #include "materials/mirror.h"
00076 #include "materials/mixmat.h"
00077 #include "materials/plastic.h"
00078 #include "materials/substrate.h"
00079 #include "materials/subsurface.h"
00080 #include "materials/translucent.h"
00081 #include "materials/uber.h"
00082 #include "renderers/aggregatetest.h"
00083 #include "renderers/createprobes.h"
00084 #include "renderers/metropolis.h"
00085 #include "renderers/samplerrenderer.h"
00086 #include "renderers/surfacepoints.h"
00087 #include "samplers/adaptive.h"
00088 #include "samplers/bestcandidate.h"
00089 #include "samplers/halton.h"
00090 #include "samplers/lowdiscrepancy.h"
00091 #include "samplers/random.h"
00092 #include "samplers/stratified.h"
00093 #include "shapes/cone.h"
00094 #include "shapes/cylinder.h"
00095 #include "shapes/disk.h"
00096 #include "shapes/heightfield.h"
00097 #include "shapes/hyperboloid.h"
00098 #include "shapes/loopsubdiv.h"
00099 #include "shapes/nurbs.h"
00100 #include "shapes/paraboloid.h"
00101 #include "shapes/sphere.h"
00102 #include "shapes/trianglemesh.h"
00103 #include "textures/bilerp.h"
00104 #include "textures/checkerboard.h"
00105 #include "textures/constant.h"
00106 #include "textures/dots.h"
00107 #include "textures/fbm.h"
00108 #include "textures/imagemap.h"
00109 #include "textures/marble.h"
00110 #include "textures/mix.h"
00111 #include "textures/scale.h"
00112 #include "textures/uv.h"
00113 #include "textures/windy.h"
00114 #include "textures/wrinkled.h"
00115 #include "volumes/exponential.h"
00116 #include "volumes/homogeneous.h"
00117 #include "volumes/volumegrid.h"
00118 #include <map>
00119 #if (_MSC_VER >= 1400)
00120 #include <stdio.h>
00121 #define snprintf _snprintf
00122 #endif
00123 using std::map;
00124
00125
00126 Options PbrtOptions;
00127
00128
00129 #define MAX_TRANSFORMS 2
00130 #define START_TRANSFORM_BITS (1 << 0)
00131 #define END_TRANSFORM_BITS (1 << 1)
00132 #define ALL_TRANSFORMS_BITS ((1 << MAX_TRANSFORMS) - 1)
00133 struct TransformSet {
00134
00135 Transform &operator[](int i) {
00136 Assert(i >= 0 && i < MAX_TRANSFORMS);
00137 return t[i];
00138 }
00139 const Transform &operator[](int i) const { Assert(i >= 0 && i < MAX_TRANSFORMS); return t[i]; }
00140 friend TransformSet Inverse(const TransformSet &ts) {
00141 TransformSet t2;
00142 for (int i = 0; i < MAX_TRANSFORMS; ++i)
00143 t2.t[i] = Inverse(ts.t[i]);
00144 return t2;
00145 }
00146 bool IsAnimated() const {
00147 for (int i = 0; i < MAX_TRANSFORMS-1; ++i)
00148 if (t[i] != t[i+1]) return true;
00149 return false;
00150 }
00151 private:
00152 Transform t[MAX_TRANSFORMS];
00153 };
00154
00155
00156 struct RenderOptions {
00157
00158 RenderOptions();
00159 Scene *MakeScene();
00160 Camera *MakeCamera() const;
00161 Renderer *MakeRenderer() const;
00162
00163
00164 float transformStartTime, transformEndTime;
00165 string FilterName;
00166 ParamSet FilterParams;
00167 string FilmName;
00168 ParamSet FilmParams;
00169 string SamplerName;
00170 ParamSet SamplerParams;
00171 string AcceleratorName;
00172 ParamSet AcceleratorParams;
00173 string RendererName;
00174 string SurfIntegratorName, VolIntegratorName;
00175 ParamSet RendererParams;
00176 ParamSet SurfIntegratorParams, VolIntegratorParams;
00177 string CameraName;
00178 ParamSet CameraParams;
00179 TransformSet CameraToWorld;
00180 vector<Light *> lights;
00181 vector<Reference<Primitive> > primitives;
00182 mutable vector<VolumeRegion *> volumeRegions;
00183 map<string, vector<Reference<Primitive> > > instances;
00184 vector<Reference<Primitive> > *currentInstance;
00185 };
00186
00187
00188 RenderOptions::RenderOptions() {
00189
00190 transformStartTime = 0.f;
00191 transformEndTime = 1.f;
00192 FilterName = "box";
00193 FilmName = "image";
00194 SamplerName = "lowdiscrepancy";
00195 AcceleratorName = "bvh";
00196 RendererName = "sampler";
00197 SurfIntegratorName = "directlighting";
00198 VolIntegratorName = "emission";
00199 CameraName = "perspective";
00200 currentInstance = NULL;
00201 }
00202
00203
00204 struct GraphicsState {
00205
00206 GraphicsState();
00207 Reference<Material> CreateMaterial(const ParamSet ¶ms);
00208
00209
00210 map<string, Reference<Texture<float> > > floatTextures;
00211 map<string, Reference<Texture<Spectrum> > > spectrumTextures;
00212 ParamSet materialParams;
00213 string material;
00214 map<string, Reference<Material> > namedMaterials;
00215 string currentNamedMaterial;
00216 ParamSet areaLightParams;
00217 string areaLight;
00218 bool reverseOrientation;
00219 };
00220
00221
00222 GraphicsState::GraphicsState() {
00223
00224 material = "matte";
00225 reverseOrientation = false;
00226 }
00227
00228
00229 class TransformCache {
00230 public:
00231
00232 void Lookup(const Transform &t, Transform **tCached,
00233 Transform **tCachedInverse) {
00234 map<Transform, std::pair<Transform *, Transform *> >::iterator iter;
00235 iter = cache.find(t);
00236 if (iter == cache.end()) {
00237 Transform *tr = arena.Alloc<Transform>();
00238 *tr = t;
00239 Transform *tinv = arena.Alloc<Transform>();
00240 *tinv = Transform(Inverse(t));
00241 cache[t] = std::make_pair(tr, tinv);
00242 iter = cache.find(t);
00243 PBRT_ALLOCATED_CACHED_TRANSFORM();
00244 }
00245 else
00246 PBRT_FOUND_CACHED_TRANSFORM();
00247 if (tCached) *tCached = iter->second.first;
00248 if (tCachedInverse) *tCachedInverse = iter->second.second;
00249 }
00250 void Clear() {
00251 arena.FreeAll();
00252 cache.erase(cache.begin(), cache.end());
00253 }
00254 private:
00255
00256 map<Transform, std::pair<Transform *, Transform *> > cache;
00257 MemoryArena arena;
00258 };
00259
00260
00261
00262
00263 #define STATE_UNINITIALIZED 0
00264 #define STATE_OPTIONS_BLOCK 1
00265 #define STATE_WORLD_BLOCK 2
00266 static int currentApiState = STATE_UNINITIALIZED;
00267 static TransformSet curTransform;
00268 static int activeTransformBits = ALL_TRANSFORMS_BITS;
00269 static map<string, TransformSet> namedCoordinateSystems;
00270 static RenderOptions *renderOptions = NULL;
00271 static GraphicsState graphicsState;
00272 static vector<GraphicsState> pushedGraphicsStates;
00273 static vector<TransformSet> pushedTransforms;
00274 static vector<uint32_t> pushedActiveTransformBits;
00275 static TransformCache transformCache;
00276
00277
00278 #define VERIFY_INITIALIZED(func) \
00279 if (currentApiState == STATE_UNINITIALIZED) { \
00280 Error("pbrtInit() must be before calling \"%s()\". " \
00281 "Ignoring.", func); \
00282 return; \
00283 } else
00284 #define VERIFY_OPTIONS(func) \
00285 VERIFY_INITIALIZED(func); \
00286 if (currentApiState == STATE_WORLD_BLOCK) { \
00287 Error("Options cannot be set inside world block; " \
00288 "\"%s\" not allowed. Ignoring.", func); \
00289 return; \
00290 } else
00291 #define VERIFY_WORLD(func) \
00292 VERIFY_INITIALIZED(func); \
00293 if (currentApiState == STATE_OPTIONS_BLOCK) { \
00294 Error("Scene description must be inside world block; " \
00295 "\"%s\" not allowed. Ignoring.", func); \
00296 return; \
00297 } else
00298 #define FOR_ACTIVE_TRANSFORMS(expr) \
00299 for (int i = 0; i < MAX_TRANSFORMS; ++i) \
00300 if (activeTransformBits & (1 << i)) { expr }
00301 #define WARN_IF_ANIMATED_TRANSFORM(func) \
00302 do { if (curTransform.IsAnimated()) \
00303 Warning("Animated transformations set; ignoring for \"%s\"" \
00304 "and using the start transform only", func); \
00305 } while (false)
00306
00307
00308 Reference<Shape> MakeShape(const string &name,
00309 const Transform *object2world, const Transform *world2object,
00310 bool reverseOrientation, const ParamSet ¶mSet) {
00311 Shape *s = NULL;
00312
00313 if (name == "sphere")
00314 s = CreateSphereShape(object2world, world2object,
00315 reverseOrientation, paramSet);
00316
00317 else if (name == "cylinder")
00318 s = CreateCylinderShape(object2world, world2object, reverseOrientation,
00319 paramSet);
00320 else if (name == "disk")
00321 s = CreateDiskShape(object2world, world2object, reverseOrientation,
00322 paramSet);
00323 else if (name == "cone")
00324 s = CreateConeShape(object2world, world2object, reverseOrientation,
00325 paramSet);
00326 else if (name == "paraboloid")
00327 s = CreateParaboloidShape(object2world, world2object, reverseOrientation,
00328 paramSet);
00329 else if (name == "hyperboloid")
00330 s = CreateHyperboloidShape(object2world, world2object, reverseOrientation,
00331 paramSet);
00332 else if (name == "trianglemesh")
00333 s = CreateTriangleMeshShape(object2world, world2object, reverseOrientation,
00334 paramSet, &graphicsState.floatTextures);
00335 else if (name == "heightfield")
00336 s = CreateHeightfieldShape(object2world, world2object, reverseOrientation,
00337 paramSet);
00338 else if (name == "loopsubdiv")
00339 s = CreateLoopSubdivShape(object2world, world2object, reverseOrientation,
00340 paramSet);
00341 else if (name == "nurbs")
00342 s = CreateNURBSShape(object2world, world2object, reverseOrientation,
00343 paramSet);
00344 else
00345 Warning("Shape \"%s\" unknown.", name.c_str());
00346 paramSet.ReportUnused();
00347 return s;
00348 }
00349
00350
00351 Reference<Material> MakeMaterial(const string &name,
00352 const Transform &mtl2world,
00353 const TextureParams &mp) {
00354 Material *material = NULL;
00355 if (name == "matte")
00356 material = CreateMatteMaterial(mtl2world, mp);
00357 else if (name == "plastic")
00358 material = CreatePlasticMaterial(mtl2world, mp);
00359 else if (name == "translucent")
00360 material = CreateTranslucentMaterial(mtl2world, mp);
00361 else if (name == "glass")
00362 material = CreateGlassMaterial(mtl2world, mp);
00363 else if (name == "mirror")
00364 material = CreateMirrorMaterial(mtl2world, mp);
00365 else if (name == "mix") {
00366 string m1 = mp.FindString("namedmaterial1", "");
00367 string m2 = mp.FindString("namedmaterial2", "");
00368 Reference<Material> mat1 = graphicsState.namedMaterials[m1];
00369 Reference<Material> mat2 = graphicsState.namedMaterials[m2];
00370 if (!mat1) {
00371 Error("Named material \"%s\" undefined. Using \"matte\"",
00372 m1.c_str());
00373 mat1 = MakeMaterial("matte", curTransform[0], mp);
00374 }
00375 if (!mat2) {
00376 Error("Named material \"%s\" undefined. Using \"matte\"",
00377 m2.c_str());
00378 mat2 = MakeMaterial("matte", curTransform[0], mp);
00379 }
00380
00381 material = CreateMixMaterial(mtl2world, mp, mat1, mat2);
00382 }
00383 else if (name == "metal")
00384 material = CreateMetalMaterial(mtl2world, mp);
00385 else if (name == "substrate")
00386 material = CreateSubstrateMaterial(mtl2world, mp);
00387 else if (name == "uber")
00388 material = CreateUberMaterial(mtl2world, mp);
00389 else if (name == "subsurface")
00390 material = CreateSubsurfaceMaterial(mtl2world, mp);
00391 else if (name == "kdsubsurface")
00392 material = CreateKdSubsurfaceMaterial(mtl2world, mp);
00393 else if (name == "measured")
00394 material = CreateMeasuredMaterial(mtl2world, mp);
00395 else
00396 Warning("Material \"%s\" unknown.", name.c_str());
00397 mp.ReportUnused();
00398 if (!material) Error("Unable to create material \"%s\"", name.c_str());
00399 return material;
00400 }
00401
00402
00403 Reference<Texture<float> > MakeFloatTexture(const string &name,
00404 const Transform &tex2world, const TextureParams &tp) {
00405 Texture<float> *tex = NULL;
00406 if (name == "constant")
00407 tex = CreateConstantFloatTexture(tex2world, tp);
00408 else if (name == "scale")
00409 tex = CreateScaleFloatTexture(tex2world, tp);
00410 else if (name == "mix")
00411 tex = CreateMixFloatTexture(tex2world, tp);
00412 else if (name == "bilerp")
00413 tex = CreateBilerpFloatTexture(tex2world, tp);
00414 else if (name == "imagemap")
00415 tex = CreateImageFloatTexture(tex2world, tp);
00416 else if (name == "uv")
00417 tex = CreateUVFloatTexture(tex2world, tp);
00418 else if (name == "checkerboard")
00419 tex = CreateCheckerboardFloatTexture(tex2world, tp);
00420 else if (name == "dots")
00421 tex = CreateDotsFloatTexture(tex2world, tp);
00422 else if (name == "fbm")
00423 tex = CreateFBmFloatTexture(tex2world, tp);
00424 else if (name == "wrinkled")
00425 tex = CreateWrinkledFloatTexture(tex2world, tp);
00426 else if (name == "marble")
00427 tex = CreateMarbleFloatTexture(tex2world, tp);
00428 else if (name == "windy")
00429 tex = CreateWindyFloatTexture(tex2world, tp);
00430 else
00431 Warning("Float texture \"%s\" unknown.", name.c_str());
00432 tp.ReportUnused();
00433 return tex;
00434 }
00435
00436
00437 Reference<Texture<Spectrum> > MakeSpectrumTexture(const string &name,
00438 const Transform &tex2world, const TextureParams &tp) {
00439 Texture<Spectrum> *tex = NULL;
00440 if (name == "constant")
00441 tex = CreateConstantSpectrumTexture(tex2world, tp);
00442 else if (name == "scale")
00443 tex = CreateScaleSpectrumTexture(tex2world, tp);
00444 else if (name == "mix")
00445 tex = CreateMixSpectrumTexture(tex2world, tp);
00446 else if (name == "bilerp")
00447 tex = CreateBilerpSpectrumTexture(tex2world, tp);
00448 else if (name == "imagemap")
00449 tex = CreateImageSpectrumTexture(tex2world, tp);
00450 else if (name == "uv")
00451 tex = CreateUVSpectrumTexture(tex2world, tp);
00452 else if (name == "checkerboard")
00453 tex = CreateCheckerboardSpectrumTexture(tex2world, tp);
00454 else if (name == "dots")
00455 tex = CreateDotsSpectrumTexture(tex2world, tp);
00456 else if (name == "fbm")
00457 tex = CreateFBmSpectrumTexture(tex2world, tp);
00458 else if (name == "wrinkled")
00459 tex = CreateWrinkledSpectrumTexture(tex2world, tp);
00460 else if (name == "marble")
00461 tex = CreateMarbleSpectrumTexture(tex2world, tp);
00462 else if (name == "windy")
00463 tex = CreateWindySpectrumTexture(tex2world, tp);
00464 else
00465 Warning("Spectrum texture \"%s\" unknown.", name.c_str());
00466 tp.ReportUnused();
00467 return tex;
00468 }
00469
00470
00471 Light *MakeLight(const string &name,
00472 const Transform &light2world, const ParamSet ¶mSet) {
00473 Light *light = NULL;
00474 if (name == "point")
00475 light = CreatePointLight(light2world, paramSet);
00476 else if (name == "spot")
00477 light = CreateSpotLight(light2world, paramSet);
00478 else if (name == "goniometric")
00479 light = CreateGoniometricLight(light2world, paramSet);
00480 else if (name == "projection")
00481 light = CreateProjectionLight(light2world, paramSet);
00482 else if (name == "distant")
00483 light = CreateDistantLight(light2world, paramSet);
00484 else if (name == "infinite" || name == "exinfinite")
00485 light = CreateInfiniteLight(light2world, paramSet);
00486 else
00487 Warning("Light \"%s\" unknown.", name.c_str());
00488 paramSet.ReportUnused();
00489 return light;
00490 }
00491
00492
00493 AreaLight *MakeAreaLight(const string &name,
00494 const Transform &light2world, const ParamSet ¶mSet,
00495 const Reference<Shape> &shape) {
00496 AreaLight *area = NULL;
00497 if (name == "area" || name == "diffuse")
00498 area = CreateDiffuseAreaLight(light2world, paramSet, shape);
00499 else
00500 Warning("Area light \"%s\" unknown.", name.c_str());
00501 paramSet.ReportUnused();
00502 return area;
00503 }
00504
00505
00506 VolumeRegion *MakeVolumeRegion(const string &name,
00507 const Transform &volume2world, const ParamSet ¶mSet) {
00508 VolumeRegion *vr = NULL;
00509 if (name == "homogeneous")
00510 vr = CreateHomogeneousVolumeDensityRegion(volume2world, paramSet);
00511 else if (name == "volumegrid")
00512 vr = CreateGridVolumeRegion(volume2world, paramSet);
00513 else if (name == "exponential")
00514 vr = CreateExponentialVolumeRegion(volume2world, paramSet);
00515 else
00516 Warning("Volume region \"%s\" unknown.", name.c_str());
00517 paramSet.ReportUnused();
00518 return vr;
00519 }
00520
00521
00522 SurfaceIntegrator *MakeSurfaceIntegrator(const string &name,
00523 const ParamSet ¶mSet) {
00524 SurfaceIntegrator *si = NULL;
00525 if (name == "whitted")
00526 si = CreateWhittedSurfaceIntegrator(paramSet);
00527 else if (name == "directlighting")
00528 si = CreateDirectLightingIntegrator(paramSet);
00529 else if (name == "path")
00530 si = CreatePathSurfaceIntegrator(paramSet);
00531 else if (name == "photonmap" || name == "exphotonmap")
00532 si = CreatePhotonMapSurfaceIntegrator(paramSet);
00533 else if (name == "irradiancecache")
00534 si = CreateIrradianceCacheIntegrator(paramSet);
00535 else if (name == "igi")
00536 si = CreateIGISurfaceIntegrator(paramSet);
00537 else if (name == "dipolesubsurface")
00538 si = CreateDipoleSubsurfaceIntegrator(paramSet);
00539 else if (name == "ambientocclusion")
00540 si = CreateAmbientOcclusionIntegrator(paramSet);
00541 else if (name == "useprobes")
00542 si = CreateRadianceProbesSurfaceIntegrator(paramSet);
00543 else if (name == "diffuseprt")
00544 si = CreateDiffusePRTIntegratorSurfaceIntegrator(paramSet);
00545 else if (name == "glossyprt")
00546 si = CreateGlossyPRTIntegratorSurfaceIntegrator(paramSet);
00547 else
00548 Warning("Surface integrator \"%s\" unknown.", name.c_str());
00549
00550 paramSet.ReportUnused();
00551 return si;
00552 }
00553
00554
00555 VolumeIntegrator *MakeVolumeIntegrator(const string &name,
00556 const ParamSet ¶mSet) {
00557 VolumeIntegrator *vi = NULL;
00558 if (name == "null")
00559 vi = NULL;
00560 else if (name == "single")
00561 vi = CreateSingleScatteringIntegrator(paramSet);
00562 else if (name == "emission")
00563 vi = CreateEmissionVolumeIntegrator(paramSet);
00564 else
00565 Warning("Volume integrator \"%s\" unknown.", name.c_str());
00566 paramSet.ReportUnused();
00567 return vi;
00568 }
00569
00570
00571 Primitive *MakeAccelerator(const string &name,
00572 const vector<Reference<Primitive> > &prims,
00573 const ParamSet ¶mSet) {
00574 Primitive *accel = NULL;
00575 if (name == "bvh")
00576 accel = CreateBVHAccelerator(prims, paramSet);
00577 else if (name == "grid")
00578 accel = CreateGridAccelerator(prims, paramSet);
00579 else if (name == "kdtree")
00580 accel = CreateKdTreeAccelerator(prims, paramSet);
00581 else
00582 Warning("Accelerator \"%s\" unknown.", name.c_str());
00583 paramSet.ReportUnused();
00584 return accel;
00585 }
00586
00587
00588 Camera *MakeCamera(const string &name,
00589 const ParamSet ¶mSet,
00590 const TransformSet &cam2worldSet, float transformStart,
00591 float transformEnd, Film *film) {
00592 Camera *camera = NULL;
00593 Assert(MAX_TRANSFORMS == 2);
00594 Transform *cam2world[2];
00595 transformCache.Lookup(cam2worldSet[0], &cam2world[0], NULL);
00596 transformCache.Lookup(cam2worldSet[1], &cam2world[1], NULL);
00597 AnimatedTransform animatedCam2World(cam2world[0], transformStart,
00598 cam2world[1], transformEnd);
00599 if (name == "perspective")
00600 camera = CreatePerspectiveCamera(paramSet, animatedCam2World, film);
00601 else if (name == "orthographic")
00602 camera = CreateOrthographicCamera(paramSet, animatedCam2World, film);
00603 else if (name == "environment")
00604 camera = CreateEnvironmentCamera(paramSet, animatedCam2World, film);
00605 else
00606 Warning("Camera \"%s\" unknown.", name.c_str());
00607 paramSet.ReportUnused();
00608 return camera;
00609 }
00610
00611
00612 Sampler *MakeSampler(const string &name,
00613 const ParamSet ¶mSet, const Film *film, const Camera *camera) {
00614 Sampler *sampler = NULL;
00615 if (name == "adaptive")
00616 sampler = CreateAdaptiveSampler(paramSet, film, camera);
00617 else if (name == "bestcandidate")
00618 sampler = CreateBestCandidateSampler(paramSet, film, camera);
00619 else if (name == "halton")
00620 sampler = CreateHaltonSampler(paramSet, film, camera);
00621 else if (name == "lowdiscrepancy")
00622 sampler = CreateLowDiscrepancySampler(paramSet, film, camera);
00623 else if (name == "random")
00624 sampler = CreateRandomSampler(paramSet, film, camera);
00625 else if (name == "stratified")
00626 sampler = CreateStratifiedSampler(paramSet, film, camera);
00627 else
00628 Warning("Sampler \"%s\" unknown.", name.c_str());
00629 paramSet.ReportUnused();
00630 return sampler;
00631 }
00632
00633
00634 Filter *MakeFilter(const string &name,
00635 const ParamSet ¶mSet) {
00636 Filter *filter = NULL;
00637 if (name == "box")
00638 filter = CreateBoxFilter(paramSet);
00639 else if (name == "gaussian")
00640 filter = CreateGaussianFilter(paramSet);
00641 else if (name == "mitchell")
00642 filter = CreateMitchellFilter(paramSet);
00643 else if (name == "sinc")
00644 filter = CreateSincFilter(paramSet);
00645 else if (name == "triangle")
00646 filter = CreateTriangleFilter(paramSet);
00647 else
00648 Warning("Filter \"%s\" unknown.", name.c_str());
00649 paramSet.ReportUnused();
00650 return filter;
00651 }
00652
00653
00654 Film *MakeFilm(const string &name,
00655 const ParamSet ¶mSet, Filter *filter) {
00656 Film *film = NULL;
00657 if (name == "image")
00658 film = CreateImageFilm(paramSet, filter);
00659 else
00660 Warning("Film \"%s\" unknown.", name.c_str());
00661 paramSet.ReportUnused();
00662 return film;
00663 }
00664
00665
00666
00667
00668 void pbrtInit(const Options &opt) {
00669 PbrtOptions = opt;
00670
00671 if (currentApiState != STATE_UNINITIALIZED)
00672 Error("pbrtInit() has already been called.");
00673 currentApiState = STATE_OPTIONS_BLOCK;
00674 renderOptions = new RenderOptions;
00675 graphicsState = GraphicsState();
00676 SampledSpectrum::Init();
00677 }
00678
00679
00680 void pbrtCleanup() {
00681 ProbesCleanup();
00682
00683 if (currentApiState == STATE_UNINITIALIZED)
00684 Error("pbrtCleanup() called without pbrtInit().");
00685 else if (currentApiState == STATE_WORLD_BLOCK)
00686 Error("pbrtCleanup() called while inside world block.");
00687 currentApiState = STATE_UNINITIALIZED;
00688 delete renderOptions;
00689 renderOptions = NULL;
00690 }
00691
00692
00693 void pbrtIdentity() {
00694 VERIFY_INITIALIZED("Identity");
00695 FOR_ACTIVE_TRANSFORMS(curTransform[i] = Transform();)
00696 }
00697
00698
00699 void pbrtTranslate(float dx, float dy, float dz) {
00700 VERIFY_INITIALIZED("Translate");
00701 FOR_ACTIVE_TRANSFORMS(curTransform[i] =
00702 curTransform[i] * Translate(Vector(dx, dy, dz));)
00703 }
00704
00705
00706 void pbrtTransform(float tr[16]) {
00707 VERIFY_INITIALIZED("Transform");
00708 FOR_ACTIVE_TRANSFORMS(curTransform[i] = Transform(Matrix4x4(
00709 tr[0], tr[4], tr[8], tr[12],
00710 tr[1], tr[5], tr[9], tr[13],
00711 tr[2], tr[6], tr[10], tr[14],
00712 tr[3], tr[7], tr[11], tr[15]));)
00713 }
00714
00715
00716 void pbrtConcatTransform(float tr[16]) {
00717 VERIFY_INITIALIZED("ConcatTransform");
00718 FOR_ACTIVE_TRANSFORMS(curTransform[i] = curTransform[i] * Transform(
00719 Matrix4x4(tr[0], tr[4], tr[8], tr[12],
00720 tr[1], tr[5], tr[9], tr[13],
00721 tr[2], tr[6], tr[10], tr[14],
00722 tr[3], tr[7], tr[11], tr[15]));)
00723 }
00724
00725
00726 void pbrtRotate(float angle, float dx, float dy, float dz) {
00727 VERIFY_INITIALIZED("Rotate");
00728 FOR_ACTIVE_TRANSFORMS(curTransform[i] = curTransform[i] * Rotate(angle, Vector(dx, dy, dz));)
00729 }
00730
00731
00732 void pbrtScale(float sx, float sy, float sz) {
00733 VERIFY_INITIALIZED("Scale");
00734 FOR_ACTIVE_TRANSFORMS(curTransform[i] = curTransform[i] * Scale(sx, sy, sz);)
00735 }
00736
00737
00738 void pbrtLookAt(float ex, float ey, float ez, float lx, float ly,
00739 float lz, float ux, float uy, float uz) {
00740 VERIFY_INITIALIZED("LookAt");
00741 FOR_ACTIVE_TRANSFORMS({ Warning("This version of pbrt fixes a bug in the LookAt transformation.\n"
00742 "If your rendered images unexpectedly change, add a \"Scale -1 1 1\"\n"
00743 "to the start of your scene file."); break; })
00744 FOR_ACTIVE_TRANSFORMS(curTransform[i] =
00745 curTransform[i] * LookAt(Point(ex, ey, ez), Point(lx, ly, lz), Vector(ux, uy, uz));)
00746 }
00747
00748
00749 void pbrtCoordinateSystem(const string &name) {
00750 VERIFY_INITIALIZED("CoordinateSystem");
00751 namedCoordinateSystems[name] = curTransform;
00752 }
00753
00754
00755 void pbrtCoordSysTransform(const string &name) {
00756 VERIFY_INITIALIZED("CoordSysTransform");
00757 if (namedCoordinateSystems.find(name) !=
00758 namedCoordinateSystems.end())
00759 curTransform = namedCoordinateSystems[name];
00760 else
00761 Warning("Couldn't find named coordinate system \"%s\"",
00762 name.c_str());
00763 }
00764
00765
00766 void pbrtActiveTransformAll() {
00767 activeTransformBits = ALL_TRANSFORMS_BITS;
00768 }
00769
00770
00771 void pbrtActiveTransformEndTime() {
00772 activeTransformBits = END_TRANSFORM_BITS;
00773 }
00774
00775
00776 void pbrtActiveTransformStartTime() {
00777 activeTransformBits = START_TRANSFORM_BITS;
00778 }
00779
00780
00781 void pbrtTransformTimes(float start, float end) {
00782 VERIFY_OPTIONS("TransformTimes");
00783 renderOptions->transformStartTime = start;
00784 renderOptions->transformEndTime = end;
00785 }
00786
00787
00788 void pbrtPixelFilter(const string &name, const ParamSet ¶ms) {
00789 VERIFY_OPTIONS("PixelFilter");
00790 renderOptions->FilterName = name;
00791 renderOptions->FilterParams = params;
00792 }
00793
00794
00795 void pbrtFilm(const string &type, const ParamSet ¶ms) {
00796 VERIFY_OPTIONS("Film");
00797 renderOptions->FilmParams = params;
00798 renderOptions->FilmName = type;
00799 }
00800
00801
00802 void pbrtSampler(const string &name, const ParamSet ¶ms) {
00803 VERIFY_OPTIONS("Sampler");
00804 renderOptions->SamplerName = name;
00805 renderOptions->SamplerParams = params;
00806 }
00807
00808
00809 void pbrtAccelerator(const string &name, const ParamSet ¶ms) {
00810 VERIFY_OPTIONS("Accelerator");
00811 renderOptions->AcceleratorName = name;
00812 renderOptions->AcceleratorParams = params;
00813 }
00814
00815
00816 void pbrtSurfaceIntegrator(const string &name, const ParamSet ¶ms) {
00817 VERIFY_OPTIONS("SurfaceIntegrator");
00818 renderOptions->SurfIntegratorName = name;
00819 renderOptions->SurfIntegratorParams = params;
00820 }
00821
00822
00823 void pbrtVolumeIntegrator(const string &name, const ParamSet ¶ms) {
00824 VERIFY_OPTIONS("VolumeIntegrator");
00825 renderOptions->VolIntegratorName = name;
00826 renderOptions->VolIntegratorParams = params;
00827 }
00828
00829
00830 void pbrtRenderer(const string &name, const ParamSet ¶ms) {
00831 VERIFY_OPTIONS("Renderer");
00832 renderOptions->RendererName = name;
00833 renderOptions->RendererParams = params;
00834 }
00835
00836
00837 void pbrtCamera(const string &name, const ParamSet ¶ms) {
00838 VERIFY_OPTIONS("Camera");
00839 renderOptions->CameraName = name;
00840 renderOptions->CameraParams = params;
00841 renderOptions->CameraToWorld = Inverse(curTransform);
00842 namedCoordinateSystems["camera"] = renderOptions->CameraToWorld;
00843 }
00844
00845
00846 void pbrtWorldBegin() {
00847 VERIFY_OPTIONS("WorldBegin");
00848 currentApiState = STATE_WORLD_BLOCK;
00849 for (int i = 0; i < MAX_TRANSFORMS; ++i)
00850 curTransform[i] = Transform();
00851 activeTransformBits = ALL_TRANSFORMS_BITS;
00852 namedCoordinateSystems["world"] = curTransform;
00853 }
00854
00855
00856 void pbrtAttributeBegin() {
00857 VERIFY_WORLD("AttributeBegin");
00858 pushedGraphicsStates.push_back(graphicsState);
00859 pushedTransforms.push_back(curTransform);
00860 pushedActiveTransformBits.push_back(activeTransformBits);
00861 }
00862
00863
00864 void pbrtAttributeEnd() {
00865 VERIFY_WORLD("AttributeEnd");
00866 if (!pushedGraphicsStates.size()) {
00867 Error("Unmatched pbrtAttributeEnd() encountered. "
00868 "Ignoring it.");
00869 return;
00870 }
00871 graphicsState = pushedGraphicsStates.back();
00872 pushedGraphicsStates.pop_back();
00873 curTransform = pushedTransforms.back();
00874 pushedTransforms.pop_back();
00875 activeTransformBits = pushedActiveTransformBits.back();
00876 pushedActiveTransformBits.pop_back();
00877 }
00878
00879
00880 void pbrtTransformBegin() {
00881 VERIFY_WORLD("TransformBegin");
00882 pushedTransforms.push_back(curTransform);
00883 pushedActiveTransformBits.push_back(activeTransformBits);
00884 }
00885
00886
00887 void pbrtTransformEnd() {
00888 VERIFY_WORLD("TransformEnd");
00889 if (!pushedTransforms.size()) {
00890 Error("Unmatched pbrtTransformEnd() encountered. "
00891 "Ignoring it.");
00892 return;
00893 }
00894 curTransform = pushedTransforms.back();
00895 pushedTransforms.pop_back();
00896 activeTransformBits = pushedActiveTransformBits.back();
00897 pushedActiveTransformBits.pop_back();
00898 }
00899
00900
00901 void pbrtTexture(const string &name, const string &type,
00902 const string &texname, const ParamSet ¶ms) {
00903 VERIFY_WORLD("Texture");
00904 TextureParams tp(params, params, graphicsState.floatTextures,
00905 graphicsState.spectrumTextures);
00906 if (type == "float") {
00907
00908 if (graphicsState.floatTextures.find(name) !=
00909 graphicsState.floatTextures.end())
00910 Info("Texture \"%s\" being redefined", name.c_str());
00911 WARN_IF_ANIMATED_TRANSFORM("Texture");
00912 Reference<Texture<float> > ft = MakeFloatTexture(texname,
00913 curTransform[0], tp);
00914 if (ft) graphicsState.floatTextures[name] = ft;
00915 }
00916 else if (type == "color") {
00917
00918 if (graphicsState.spectrumTextures.find(name) != graphicsState.spectrumTextures.end())
00919 Info("Texture \"%s\" being redefined", name.c_str());
00920 WARN_IF_ANIMATED_TRANSFORM("Texture");
00921 Reference<Texture<Spectrum> > st = MakeSpectrumTexture(texname,
00922 curTransform[0], tp);
00923 if (st) graphicsState.spectrumTextures[name] = st;
00924 }
00925 else
00926 Error("Texture type \"%s\" unknown.", type.c_str());
00927 }
00928
00929
00930 void pbrtMaterial(const string &name, const ParamSet ¶ms) {
00931 VERIFY_WORLD("Material");
00932 graphicsState.material = name;
00933 graphicsState.materialParams = params;
00934 graphicsState.currentNamedMaterial = "";
00935 }
00936
00937
00938 void pbrtMakeNamedMaterial(const string &name,
00939 const ParamSet ¶ms) {
00940 VERIFY_WORLD("MakeNamedMaterial");
00941
00942 TextureParams mp(params, graphicsState.materialParams,
00943 graphicsState.floatTextures,
00944 graphicsState.spectrumTextures);
00945 string matName = mp.FindString("type");
00946 WARN_IF_ANIMATED_TRANSFORM("MakeNamedMaterial");
00947 if (matName == "") Error("No parameter string \"type\" found in MakeNamedMaterial");
00948 else {
00949 Reference<Material> mtl = MakeMaterial(matName, curTransform[0], mp);
00950 if (mtl) graphicsState.namedMaterials[name] = mtl;
00951 }
00952 }
00953
00954
00955
00956 void pbrtNamedMaterial(const string &name) {
00957 VERIFY_WORLD("NamedMaterial");
00958 graphicsState.currentNamedMaterial = name;
00959 }
00960
00961
00962 void pbrtLightSource(const string &name, const ParamSet ¶ms) {
00963 VERIFY_WORLD("LightSource");
00964 WARN_IF_ANIMATED_TRANSFORM("LightSource");
00965 Light *lt = MakeLight(name, curTransform[0], params);
00966 if (lt == NULL)
00967 Error("pbrtLightSource: light type \"%s\" unknown.", name.c_str());
00968 else
00969 renderOptions->lights.push_back(lt);
00970 }
00971
00972
00973 void pbrtAreaLightSource(const string &name,
00974 const ParamSet ¶ms) {
00975 VERIFY_WORLD("AreaLightSource");
00976 graphicsState.areaLight = name;
00977 graphicsState.areaLightParams = params;
00978 }
00979
00980
00981 void pbrtShape(const string &name, const ParamSet ¶ms) {
00982 VERIFY_WORLD("Shape");
00983 Reference<Primitive> prim;
00984 AreaLight *area = NULL;
00985 if (!curTransform.IsAnimated()) {
00986
00987 Transform *obj2world, *world2obj;
00988 transformCache.Lookup(curTransform[0], &obj2world, &world2obj);
00989 Reference<Shape> shape = MakeShape(name, obj2world, world2obj,
00990 graphicsState.reverseOrientation, params);
00991 if (!shape) return;
00992 Reference<Material> mtl = graphicsState.CreateMaterial(params);
00993 params.ReportUnused();
00994
00995
00996 if (graphicsState.areaLight != "") {
00997 area = MakeAreaLight(graphicsState.areaLight, curTransform[0],
00998 graphicsState.areaLightParams, shape);
00999 }
01000 prim = new GeometricPrimitive(shape, mtl, area);
01001 } else {
01002
01003
01004
01005 if (graphicsState.areaLight != "")
01006 Warning("Ignoring currently set area light when creating "
01007 "animated shape");
01008 Transform *identity;
01009 transformCache.Lookup(Transform(), &identity, NULL);
01010 Reference<Shape> shape = MakeShape(name, identity, identity,
01011 graphicsState.reverseOrientation, params);
01012 if (!shape) return;
01013 Reference<Material> mtl = graphicsState.CreateMaterial(params);
01014 params.ReportUnused();
01015
01016
01017 Assert(MAX_TRANSFORMS == 2);
01018 Transform *world2obj[2];
01019 transformCache.Lookup(curTransform[0], NULL, &world2obj[0]);
01020 transformCache.Lookup(curTransform[1], NULL, &world2obj[1]);
01021 AnimatedTransform
01022 animatedWorldToObject(world2obj[0], renderOptions->transformStartTime,
01023 world2obj[1], renderOptions->transformEndTime);
01024 Reference<Primitive> baseprim = new GeometricPrimitive(shape, mtl, NULL);
01025 if (!baseprim->CanIntersect()) {
01026
01027 vector<Reference<Primitive> > refinedPrimitives;
01028 baseprim->FullyRefine(refinedPrimitives);
01029 if (refinedPrimitives.size() == 0) return;
01030 if (refinedPrimitives.size() > 1)
01031 baseprim = new BVHAccel(refinedPrimitives);
01032 else
01033 baseprim = refinedPrimitives[0];
01034 }
01035 prim = new TransformedPrimitive(baseprim, animatedWorldToObject);
01036 }
01037
01038 if (renderOptions->currentInstance) {
01039 if (area)
01040 Warning("Area lights not supported with object instancing");
01041 renderOptions->currentInstance->push_back(prim);
01042 }
01043
01044 else {
01045 renderOptions->primitives.push_back(prim);
01046 if (area != NULL) {
01047 renderOptions->lights.push_back(area);
01048 }
01049 }
01050 }
01051
01052
01053 Reference<Material> GraphicsState::CreateMaterial(const ParamSet ¶ms) {
01054 TextureParams mp(params, materialParams,
01055 floatTextures,
01056 spectrumTextures);
01057 Reference<Material> mtl;
01058 if (currentNamedMaterial != "" &&
01059 namedMaterials.find(currentNamedMaterial) != namedMaterials.end())
01060 mtl = namedMaterials[graphicsState.currentNamedMaterial];
01061 if (!mtl)
01062 mtl = MakeMaterial(material, curTransform[0], mp);
01063 if (!mtl)
01064 mtl = MakeMaterial("matte", curTransform[0], mp);
01065 if (!mtl)
01066 Severe("Unable to create \"matte\" material?!");
01067 return mtl;
01068 }
01069
01070
01071 void pbrtReverseOrientation() {
01072 VERIFY_WORLD("ReverseOrientation");
01073 graphicsState.reverseOrientation =
01074 !graphicsState.reverseOrientation;
01075 }
01076
01077
01078 void pbrtVolume(const string &name, const ParamSet ¶ms) {
01079 VERIFY_WORLD("Volume");
01080 WARN_IF_ANIMATED_TRANSFORM("Volume");
01081 VolumeRegion *vr = MakeVolumeRegion(name, curTransform[0], params);
01082 if (vr) renderOptions->volumeRegions.push_back(vr);
01083 }
01084
01085
01086 void pbrtObjectBegin(const string &name) {
01087 VERIFY_WORLD("ObjectBegin");
01088 pbrtAttributeBegin();
01089 if (renderOptions->currentInstance)
01090 Error("ObjectBegin called inside of instance definition");
01091 renderOptions->instances[name] = vector<Reference<Primitive> >();
01092 renderOptions->currentInstance = &renderOptions->instances[name];
01093 }
01094
01095
01096 void pbrtObjectEnd() {
01097 VERIFY_WORLD("ObjectEnd");
01098 if (!renderOptions->currentInstance)
01099 Error("ObjectEnd called outside of instance definition");
01100 renderOptions->currentInstance = NULL;
01101 pbrtAttributeEnd();
01102 }
01103
01104
01105 void pbrtObjectInstance(const string &name) {
01106 VERIFY_WORLD("ObjectInstance");
01107
01108 if (renderOptions->currentInstance) {
01109 Error("ObjectInstance can't be called inside instance definition");
01110 return;
01111 }
01112 if (renderOptions->instances.find(name) == renderOptions->instances.end()) {
01113 Error("Unable to find instance named \"%s\"", name.c_str());
01114 return;
01115 }
01116 vector<Reference<Primitive> > &in = renderOptions->instances[name];
01117 if (in.size() == 0) return;
01118 if (in.size() > 1 || !in[0]->CanIntersect()) {
01119
01120 Reference<Primitive> accel =
01121 MakeAccelerator(renderOptions->AcceleratorName,
01122 in, renderOptions->AcceleratorParams);
01123 if (!accel) accel = MakeAccelerator("bvh", in, ParamSet());
01124 if (!accel) Severe("Unable to create \"bvh\" accelerator");
01125 in.erase(in.begin(), in.end());
01126 in.push_back(accel);
01127 }
01128 Assert(MAX_TRANSFORMS == 2);
01129 Transform *world2instance[2];
01130 transformCache.Lookup(curTransform[0], NULL, &world2instance[0]);
01131 transformCache.Lookup(curTransform[1], NULL, &world2instance[1]);
01132 AnimatedTransform animatedWorldToInstance(world2instance[0],
01133 renderOptions->transformStartTime,
01134 world2instance[1], renderOptions->transformEndTime);
01135 Reference<Primitive> prim =
01136 new TransformedPrimitive(in[0], animatedWorldToInstance);
01137 renderOptions->primitives.push_back(prim);
01138 }
01139
01140
01141 void pbrtWorldEnd() {
01142 VERIFY_WORLD("WorldEnd");
01143
01144 while (pushedGraphicsStates.size()) {
01145 Warning("Missing end to pbrtAttributeBegin()");
01146 pushedGraphicsStates.pop_back();
01147 pushedTransforms.pop_back();
01148 }
01149 while (pushedTransforms.size()) {
01150 Warning("Missing end to pbrtTransformBegin()");
01151 pushedTransforms.pop_back();
01152 }
01153
01154
01155 Renderer *renderer = renderOptions->MakeRenderer();
01156 Scene *scene = renderOptions->MakeScene();
01157 if (scene && renderer) renderer->Render(scene);
01158 TasksCleanup();
01159 delete renderer;
01160 delete scene;
01161
01162
01163 graphicsState = GraphicsState();
01164 transformCache.Clear();
01165 currentApiState = STATE_OPTIONS_BLOCK;
01166 ProbesPrint(stdout);
01167 for (int i = 0; i < MAX_TRANSFORMS; ++i)
01168 curTransform[i] = Transform();
01169 activeTransformBits = ALL_TRANSFORMS_BITS;
01170 namedCoordinateSystems.erase(namedCoordinateSystems.begin(),
01171 namedCoordinateSystems.end());
01172 ImageTexture<float, float>::ClearCache();
01173 ImageTexture<RGBSpectrum, Spectrum>::ClearCache();
01174 }
01175
01176
01177 Scene *RenderOptions::MakeScene() {
01178
01179 VolumeRegion *volumeRegion;
01180 if (volumeRegions.size() == 0)
01181 volumeRegion = NULL;
01182 else if (volumeRegions.size() == 1)
01183 volumeRegion = volumeRegions[0];
01184 else
01185 volumeRegion = new AggregateVolume(volumeRegions);
01186 Primitive *accelerator = MakeAccelerator(AcceleratorName,
01187 primitives, AcceleratorParams);
01188 if (!accelerator)
01189 accelerator = MakeAccelerator("bvh", primitives, ParamSet());
01190 if (!accelerator)
01191 Severe("Unable to create \"bvh\" accelerator.");
01192 Scene *scene = new Scene(accelerator, lights, volumeRegion);
01193
01194 primitives.erase(primitives.begin(), primitives.end());
01195 lights.erase(lights.begin(), lights.end());
01196 volumeRegions.erase(volumeRegions.begin(), volumeRegions.end());
01197 return scene;
01198 }
01199
01200
01201 Renderer *RenderOptions::MakeRenderer() const {
01202 Renderer *renderer = NULL;
01203 Camera *camera = MakeCamera();
01204 if (RendererName == "metropolis") {
01205 renderer = CreateMetropolisRenderer(RendererParams, camera);
01206 RendererParams.ReportUnused();
01207
01208 if (lights.size() == 0)
01209 Warning("No light sources defined in scene; "
01210 "possibly rendering a black image.");
01211 }
01212
01213 else if (RendererName == "createprobes") {
01214
01215 SurfaceIntegrator *surfaceIntegrator = MakeSurfaceIntegrator(SurfIntegratorName,
01216 SurfIntegratorParams);
01217 if (!surfaceIntegrator) Severe("Unable to create surface integrator.");
01218 VolumeIntegrator *volumeIntegrator = MakeVolumeIntegrator(VolIntegratorName,
01219 VolIntegratorParams);
01220 if (!volumeIntegrator) Severe("Unable to create volume integrator.");
01221 renderer = CreateRadianceProbesRenderer(camera, surfaceIntegrator, volumeIntegrator, RendererParams);
01222 RendererParams.ReportUnused();
01223
01224 if (lights.size() == 0)
01225 Warning("No light sources defined in scene; "
01226 "possibly rendering a black image.");
01227 }
01228 else if (RendererName == "aggregatetest") {
01229 renderer = CreateAggregateTestRenderer(RendererParams, primitives);
01230 RendererParams.ReportUnused();
01231 }
01232 else if (RendererName == "surfacepoints") {
01233 Point pCamera = camera->CameraToWorld(camera->shutterOpen, Point(0, 0, 0));
01234 renderer = CreateSurfacePointsRenderer(RendererParams, pCamera, camera->shutterOpen);
01235 RendererParams.ReportUnused();
01236 }
01237 else {
01238 if (RendererName != "sampler")
01239 Warning("Renderer type \"%s\" unknown. Using \"sampler\".",
01240 RendererName.c_str());
01241 RendererParams.ReportUnused();
01242 Sampler *sampler = MakeSampler(SamplerName, SamplerParams, camera->film, camera);
01243 if (!sampler) Severe("Unable to create sampler.");
01244
01245 SurfaceIntegrator *surfaceIntegrator = MakeSurfaceIntegrator(SurfIntegratorName,
01246 SurfIntegratorParams);
01247 if (!surfaceIntegrator) Severe("Unable to create surface integrator.");
01248 VolumeIntegrator *volumeIntegrator = MakeVolumeIntegrator(VolIntegratorName,
01249 VolIntegratorParams);
01250 if (!volumeIntegrator) Severe("Unable to create volume integrator.");
01251 renderer = new SamplerRenderer(sampler, camera, surfaceIntegrator,
01252 volumeIntegrator);
01253
01254 if (lights.size() == 0)
01255 Warning("No light sources defined in scene; "
01256 "possibly rendering a black image.");
01257 }
01258 return renderer;
01259 }
01260
01261
01262 Camera *RenderOptions::MakeCamera() const {
01263 Filter *filter = MakeFilter(FilterName, FilterParams);
01264 Film *film = MakeFilm(FilmName, FilmParams, filter);
01265 if (!film) Severe("Unable to create film.");
01266 Camera *camera = ::MakeCamera(CameraName, CameraParams,
01267 CameraToWorld, renderOptions->transformStartTime,
01268 renderOptions->transformEndTime, film);
01269 if (!camera) Severe("Unable to create camera.");
01270 return camera;
01271 }
01272
01273