void Shape::configure() { if (m_bsdf == NULL) { ref<BSDF> bsdf = NULL; if (isEmitter() || isSensor() || hasSubsurface()) { /* Light source / sensor and no BSDF! -> set an all-absorbing BSDF */ Properties props("diffuse"); props.setSpectrum("reflectance", Spectrum(0.0f)); bsdf = static_cast<BSDF *> (PluginManager::getInstance()-> createObject(MTS_CLASS(BSDF), props)); } else if (!isMediumTransition()) { /* A surface without BSDF, which is not a medium transition/sensor/emitter/subsurface emitter doesn't make much sense. Assign it a 0.5 Lambertian BRDF for convenience */ Properties props("diffuse"); props.setSpectrum("reflectance", Spectrum(0.5f)); bsdf = static_cast<BSDF *> (PluginManager::getInstance()-> createObject(MTS_CLASS(BSDF), props)); } else { /* Assign a "null" BSDF */ bsdf = static_cast<BSDF *> (PluginManager::getInstance()-> createObject(MTS_CLASS(BSDF), Properties("null"))); } bsdf->configure(); addChild(bsdf); } if ((m_bsdf->getType() & BSDF::ENull) && (isEmitter() || isSensor() || hasSubsurface())) Log(EError, "Shape \"%s\" has an index-matched BSDF and an " "emitter/sensor/subsurface attachment. This is not allowed!", getName().c_str()); }
void Sensor::configure() { if (m_film == NULL) { /* Instantiate an EXR film by default */ m_film = static_cast<Film*> (PluginManager::getInstance()-> createObject(MTS_CLASS(Film), Properties("hdrfilm"))); m_film->configure(); } if (m_sampler == NULL) { /* No sampler has been selected - load an independent filter with 4 samples/pixel by default */ Properties props("independent"); props.setInteger("sampleCount", 4); m_sampler = static_cast<Sampler *> (PluginManager::getInstance()-> createObject(MTS_CLASS(Sampler), props)); m_sampler->configure(); } m_aspect = m_film->getSize().x / (Float) m_film->getSize().y; m_resolution = Vector2(m_film->getCropSize()); m_invResolution = Vector2( (Float) 1 / m_resolution.x, (Float) 1 / m_resolution.y); }
std::pair<Texture *, Texture *> BSDF::ensureEnergyConservation( Texture *tex1, Texture *tex2, const std::string ¶mName1, const std::string ¶mName2, Float max) const { if (!m_ensureEnergyConservation) return std::make_pair(tex1, tex2); Float actualMax = (tex1->getMaximum() + tex2->getMaximum()).max(); if (actualMax > max) { std::ostringstream oss; Float scale = 0.99f * (max / actualMax); oss << "The BSDF" << endl << toString() << endl << "violates energy conservation! The parameters \"" << paramName1 << "\" " << "and \"" << paramName2 << "\" sum to a component-wise maximum of " << actualMax << " (which is > " << max << "!) and will therefore be " << "scaled by " << scale << " to prevent issues. Specify the parameter " << "ensureEnergyConservation=false to the BSDF to prevent this from " << "happening."; Log(EWarn, "%s", oss.str().c_str()); Properties props("scale"); props.setFloat("scale", scale); Texture *scaleTexture1 = static_cast<Texture *> (PluginManager::getInstance()-> createObject(MTS_CLASS(Texture), props)); Texture *scaleTexture2 = static_cast<Texture *> (PluginManager::getInstance()-> createObject(MTS_CLASS(Texture), props)); scaleTexture1->addChild(tex1); scaleTexture1->configure(); scaleTexture2->addChild(tex2); scaleTexture2->configure(); return std::make_pair(scaleTexture1, scaleTexture2); } return std::make_pair(tex1, tex2); }
void Sensor::addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(Sampler))) { m_sampler = static_cast<Sampler *>(child); } else if (child->getClass()->derivesFrom(MTS_CLASS(Film))) { m_film = static_cast<Film *>(child); } else { AbstractEmitter::addChild(name, child); } }
void addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) { BSDF *bsdf = static_cast<BSDF *>(child); m_bsdfs.push_back(bsdf); bsdf->incRef(); } else if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && name == "weight") { m_weight = static_cast<Texture *>(child); } else { BSDF::addChild(name, child); } }
void Shape::addChild(const std::string &name, ConfigurableObject *child) { const Class *cClass = child->getClass(); if (cClass->derivesFrom(MTS_CLASS(BSDF))) { m_bsdf = static_cast<BSDF *>(child); } else if (cClass->derivesFrom(MTS_CLASS(Emitter))) { Emitter *emitter = static_cast<Emitter *>(child); if (m_emitter != NULL) Log(EError, "Tried to attach multiple emitters to a shape!"); if (emitter) { if (!emitter->isOnSurface()) Log(EError, "Tried to attach an incompatible emitter to a surface!"); if (m_exteriorMedium) emitter->setMedium(m_exteriorMedium); } m_emitter = emitter; } else if (cClass->derivesFrom(MTS_CLASS(Sensor))) { Sensor *sensor = static_cast<Sensor *>(child); if (m_sensor != NULL) Log(EError, "Tried to attach multiple sensors to a shape!"); if (sensor) { if (!sensor->isOnSurface()) Log(EError, "Tried to attach an incompatible sensor to a surface!"); if (m_exteriorMedium) sensor->setMedium(m_exteriorMedium); } m_sensor = sensor; } else if (cClass->derivesFrom(MTS_CLASS(Subsurface))) { Assert(m_subsurface == NULL); if (m_interiorMedium != NULL) Log(EError, "Shape \"%s\" has both an interior medium " "and a subsurface scattering model -- please choose one or the other!", getName().c_str()); m_subsurface = static_cast<Subsurface *>(child); } else if (cClass->derivesFrom(MTS_CLASS(Medium))) { if (name == "interior") { Assert(m_interiorMedium == NULL || m_interiorMedium == child); if (m_subsurface != NULL) Log(EError, "Shape \"%s\" has both an interior medium " "and a subsurface scattering model -- please choose one or the other!", getName().c_str()); m_interiorMedium = static_cast<Medium *>(child); } else if (name == "exterior") { Assert(m_exteriorMedium == NULL || m_exteriorMedium == child); m_exteriorMedium = static_cast<Medium *>(child); if (m_emitter) m_emitter->setMedium(m_exteriorMedium); if (m_sensor) m_sensor->setMedium(m_exteriorMedium); } else { Log(EError, "Shape: Invalid medium child (must be named " "'interior' or 'exterior')!"); } } else { ConfigurableObject::addChild(name, child); } }
void addChild(const std::string &name, ConfigurableObject *child) { const Class *cClass = child->getClass(); if (cClass->derivesFrom(MTS_CLASS(Integrator))) { if (!cClass->derivesFrom(MTS_CLASS(SamplingIntegrator))) Log(EError, "The sub-integrator must be derived from the class SamplingIntegrator"); m_subIntegrator = static_cast<SamplingIntegrator *>(child); m_subIntegrator->setParent(this); } else { Integrator::addChild(name, child); } }
void addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) { if (m_nested != NULL) Log(EError, "Only a single nested BSDF can be added!"); m_nested = static_cast<BSDF *>(child); } else if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) { if (m_displacement != NULL) Log(EError, "Only a single displacement texture can be specified!"); m_displacement = static_cast<Texture *>(child); } else { BSDF::addChild(name, child); } }
Texture *BSDF::ensureEnergyConservation(Texture *texture, const std::string ¶mName, Float max) const { if (!m_ensureEnergyConservation) return texture; Float actualMax = texture->getMaximum().max(); if (actualMax > max) { std::ostringstream oss; Float scale = 0.99f * (max / actualMax); oss << "The BSDF" << endl << toString() << endl << "violates energy conservation! The parameter \"" << paramName << "\" " << "has a component-wise maximum of "<< actualMax << " (which is > " << max << "!) " << "and will therefore be scaled by " << scale << " to prevent " << "issues. Specify the parameter ensureEnergyConservation=false " << "to the BSDF to prevent this from happening."; Log(EWarn, "%s", oss.str().c_str()); Properties props("scale"); props.setFloat("scale", scale); Texture *scaleTexture = static_cast<Texture *> (PluginManager::getInstance()-> createObject(MTS_CLASS(Texture), props)); scaleTexture->addChild(texture); scaleTexture->configure(); return scaleTexture; } return texture; }
bool preprocess(const Scene *scene, RenderQueue *queue, const RenderJob *job, int sceneResID, int cameraResID, int samplerResID) { if (m_ready) return true; if (!scene->getIntegrator()->getClass() ->derivesFrom(MTS_CLASS(SampleIntegrator))) { Log(EError, "The dipole subsurface integrator requires " "a sampling-based surface integrator!"); } m_octree = new IrradianceOctree(m_maxDepth, m_minDelta, scene->getKDTree()->getAABB()); Float sa = 0; for (std::vector<Shape *>::iterator it = m_shapes.begin(); it != m_shapes.end(); ++it) sa += (*it)->getSurfaceArea(); size_t sampleCount = (size_t) std::ceil(sa / (M_PI * m_minMFP * m_minMFP) * m_sampleMultiplier); Log(EInfo, "Generating " SIZE_T_FMT " irradiance samples..", sampleCount); ref<Scheduler> sched = Scheduler::getInstance(); /* This could be a bit more elegant.. - inform the irradiance sampler about the index of this subsurface integrator */ std::vector<Subsurface *> ssIntegrators = scene->getSubsurfaceIntegrators(); int index = -1; for (size_t i=0; i<ssIntegrators.size(); ++i) { if (ssIntegrators[i] == this) { index = (int) i; break; } } Assert(index != -1); ref<IrradianceSamplingProcess> proc = new IrradianceSamplingProcess( sampleCount, (size_t) std::ceil(sampleCount/100.0f), index, m_irrSamples, m_irrIndirect, job); proc->bindResource("scene", sceneResID); scene->bindUsedResources(proc); m_proc = proc; sched->schedule(proc); sched->wait(proc); m_proc = NULL; if (proc->getReturnStatus() != ParallelProcess::ESuccess) return false; const IrradianceRecordVector &results = *proc->getSamples(); for (size_t i=0; i<results.size(); ++i) m_octree->addSample(results[i]); m_octree->preprocess(); m_octreeResID = Scheduler::getInstance()->registerResource(m_octree); m_ready = true; return true; }
void configure() { if (m_phase == NULL) m_phase = static_cast<PhaseFunction *> (PluginManager::getInstance()-> createObject(MTS_CLASS(PhaseFunction), Properties("isotropic"))); if (m_sigmaT != NULL || m_albedo != NULL) { /* Support for the alternative scattering/absorption * coefficient parameter passing convention */ if (m_sigmaT == NULL || m_albedo == NULL) SLog(EError, "Please provide *both* sigmaT & albedo!"); m_sigmaS = new SpectrumProductTexture(m_sigmaT, m_albedo); m_sigmaA = new SpectrumSubtractionTexture(m_sigmaT, m_sigmaS); m_sigmaT = NULL; m_albedo = NULL; } int extraFlags = m_sigmaS->isConstant() && m_sigmaA->isConstant() ? 0 : ESpatiallyVarying; m_components.clear(); m_components.push_back(EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler | extraFlags); if (m_thickness != std::numeric_limits<Float>::infinity()) { m_components.push_back(EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags); m_components.push_back(EDeltaTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags); } m_usesRayDifferentials = m_sigmaS->usesRayDifferentials() || m_sigmaA->usesRayDifferentials(); BSDF::configure(); }
void addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) { if (m_nested != NULL) Log(EError, "Only a single nested BRDF can be added!"); m_nested = static_cast<BSDF *>(child); } else if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) { if (name == "sigmaA") m_sigmaA = static_cast<Texture *>(child); else if (name == "alpha") m_alpha = static_cast<Texture *>(child); else BSDF::addChild(name, child); } else { BSDF::addChild(name, child); } }
CausticPerturbation::CausticPerturbation(const Scene *scene, Sampler *sampler, MemoryPool &pool, Float minJump, Float coveredArea) : m_scene(scene), m_sampler(sampler), m_pool(pool) { if (!scene->getSensor()->getClass()->derivesFrom(MTS_CLASS(PerspectiveCamera))) Log(EError, "The caustic perturbation requires a perspective camera."); const PerspectiveCamera *camera = static_cast<const PerspectiveCamera *>(scene->getSensor()); Vector2i filmSize = camera->getFilm()->getSize(), cropSize = camera->getFilm()->getCropSize(); /* Simple heuristic for choosing a jump size: assumes that each pixel on the camera subtends the same area on the sphere */ Float degPerPixel = std::min( camera->getXFov() / filmSize.x, camera->getYFov() / filmSize.y), radPerPixel = degPerPixel * M_PI / 180.0f; Float r1 = minJump, r2 = std::sqrt(coveredArea * cropSize.x*cropSize.y / M_PI); /* [Veach, p. 354] */ /* These represent the *desired* angle change range as seen from the camera */ m_theta1 = radPerPixel * r1; m_theta2 = radPerPixel * r2; m_logRatio = -math::fastlog(m_theta2 / m_theta1); }
void Medium::configure() { if (m_phaseFunction == NULL) { m_phaseFunction = static_cast<PhaseFunction *> (PluginManager::getInstance()-> createObject(MTS_CLASS(PhaseFunction), Properties("isotropic"))); m_phaseFunction->configure(); } }
ref<Shape> createShape(const Scene *scene) { /* Create a bounding sphere that surrounds the scene */ BSphere sceneBSphere(scene->getAABB().getBSphere()); sceneBSphere.radius = std::max(Epsilon, sceneBSphere.radius * 1.5f); BSphere geoBSphere(scene->getKDTree()->getAABB().getBSphere()); if (sceneBSphere != m_sceneBSphere || geoBSphere != m_geoBSphere) { m_sceneBSphere = sceneBSphere; m_geoBSphere = geoBSphere; configure(); } Transform trafo = Transform::translate(Vector(m_sceneBSphere.center)) * Transform::scale(Vector(m_sceneBSphere.radius)); Properties props("sphere"); props.setTransform("toWorld", trafo); props.setBoolean("flipNormals", true); Shape *shape = static_cast<Shape *> (PluginManager::getInstance()-> createObject(MTS_CLASS(Shape), props)); shape->addChild(this); shape->configure(); return shape; }
BitmapTexture(Stream *stream, InstanceManager *manager) : Texture2D(stream, manager) { m_filename = stream->readString(); Log(EDebug, "Unserializing texture \"%s\"", m_filename.filename().string().c_str()); m_filterType = (EMIPFilterType) stream->readUInt(); m_wrapModeU = (ReconstructionFilter::EBoundaryCondition) stream->readUInt(); m_wrapModeV = (ReconstructionFilter::EBoundaryCondition) stream->readUInt(); m_gamma = stream->readFloat(); m_maxAnisotropy = stream->readFloat(); m_channel = stream->readString(); size_t size = stream->readSize(); ref<MemoryStream> mStream = new MemoryStream(size); stream->copyTo(mStream, size); mStream->seek(0); ref<Bitmap> bitmap = new Bitmap(Bitmap::EAuto, mStream); if (m_gamma != 0) bitmap->setGamma(m_gamma); /* Downsample using a 2-lobed Lanczos reconstruction filter */ Properties rfilterProps("lanczos"); rfilterProps.setInteger("lobes", 2); ref<ReconstructionFilter> rfilter = static_cast<ReconstructionFilter *> ( PluginManager::getInstance()->createObject( MTS_CLASS(ReconstructionFilter), rfilterProps)); rfilter->configure(); Bitmap::EPixelFormat pixelFormat; if (!m_channel.empty()) { /* Create a texture from a certain channel of an image */ pixelFormat = Bitmap::ELuminance; bitmap = bitmap->extractChannel(findChannel(bitmap, m_channel)); if (m_channel == "a") bitmap->setGamma(1.0f); } else { switch (bitmap->getPixelFormat()) { case Bitmap::ELuminance: case Bitmap::ELuminanceAlpha: pixelFormat = Bitmap::ELuminance; break; case Bitmap::ERGB: case Bitmap::ERGBA: pixelFormat = Bitmap::ERGB; break; default: Log(EError, "The input image has an unsupported pixel format!"); return; } } if (pixelFormat == Bitmap::ELuminance) m_mipmap1 = new MIPMap1(bitmap, pixelFormat, Bitmap::EFloat, rfilter, m_wrapModeU, m_wrapModeV, m_filterType, m_maxAnisotropy, fs::path(), 0); else m_mipmap3 = new MIPMap3(bitmap, pixelFormat, Bitmap::EFloat, rfilter, m_wrapModeU, m_wrapModeV, m_filterType, m_maxAnisotropy, fs::path(), 0); }
void addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && name == "specularReflectance") { m_specularReflectance = static_cast<Texture *>(child); m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials(); } else { BSDF::addChild(name, child); } }
void addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && (name == "reflectance" || name == "diffuseReflectance")) { } else { BSDF::addChild(name, child); } }
void AbstractEmitter::addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(Medium))) { Assert(m_medium == NULL); m_medium = static_cast<Medium *>(child); } else { ConfigurableObject::addChild(name, child); } }
size_t Scheduler::getLocalWorkerCount() const { size_t count = 0; LockGuard lock(m_mutex); for (size_t i=0; i<m_workers.size(); ++i) { if (m_workers[i]->getClass() == MTS_CLASS(LocalWorker)) count++; } return count; }
void addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) { if (m_nested != NULL) Log(EError, "Only a single nested BSDF can be added!"); m_nested = static_cast<BSDF *>(child); } else if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) { if (m_displacement != NULL) Log(EError, "Only a single displacement texture can be specified!"); const Properties &props = child->getProperties(); if (props.getPluginName() == "bitmap" && !props.hasProperty("gamma")) Log(EError, "When using a bitmap texture as a bump map, please explicitly specify " "the 'gamma' parameter of the bitmap plugin. In most cases the following is the correct choice: " "<float name=\"gamma\" value=\"1.0\"/>"); m_displacement = static_cast<Texture *>(child); } else { BSDF::addChild(name, child); } }
void Luminaire::addChild(const std::string &name, ConfigurableObject *child) { const Class *cClass = child->getClass(); if (cClass->derivesFrom(MTS_CLASS(Medium))) { Assert(m_medium == NULL); m_medium = static_cast<Medium *>(child); } else { ConfigurableObject::addChild(name, child); } }
void Medium::addChild(const std::string &name, ConfigurableObject *child) { const Class *cClass = child->getClass(); if (cClass->derivesFrom(MTS_CLASS(PhaseFunction))) { Assert(m_phaseFunction == NULL); m_phaseFunction = static_cast<PhaseFunction *>(child); } else { Log(EError, "Medium: Invalid child node! (\"%s\")", cClass->getName().c_str()); } }
void addChild(const std::string &name, ConfigurableObject *child) { const Class *cClass = child->getClass(); if (cClass->derivesFrom(MTS_CLASS(PhaseFunction))) { Assert(m_phase == NULL); m_phase = static_cast<PhaseFunction *>(child); } else if (cClass->derivesFrom(MTS_CLASS(Texture))) { if (name == "sigmaS") m_sigmaS = static_cast<Texture *>(child); else if (name == "sigmaA") m_sigmaA = static_cast<Texture *>(child); else if (name == "sigmaT") m_sigmaT = static_cast<Texture *>(child); else if (name == "albedo") m_albedo = static_cast<Texture *>(child); else BSDF::addChild(name, child); } else { BSDF::addChild(name, child); } }
ref<Shape> createShape(const Scene *scene) { ref<AnimatedTransform> trafo = new AnimatedTransform(m_worldTransform); trafo->prependScale(Vector(m_apertureRadius)); Properties props("disk"); props.setAnimatedTransform("toWorld", trafo); Shape *shape = static_cast<Shape *> (PluginManager::getInstance()-> createObject(MTS_CLASS(Shape), props)); shape->addChild(this); shape->configure(); return shape; }
/// Connect to globally shared resources void wakeup(ConfigurableObject *parent, std::map<std::string, SerializableObject *> ¶ms) { if (!m_globalPhotonMap.get() && params.find("globalPhotonMap") != params.end()) m_globalPhotonMap = static_cast<PhotonMap *>(params["globalPhotonMap"]); if (!m_causticPhotonMap.get() && params.find("causticPhotonMap") != params.end()) m_causticPhotonMap = static_cast<PhotonMap *>(params["causticPhotonMap"]); if (!m_bre.get() && params.find("bre") != params.end()) m_bre = static_cast<BeamRadianceEstimator *>(params["bre"]); if (parent && parent->getClass()->derivesFrom(MTS_CLASS(SamplingIntegrator))) m_parentIntegrator = static_cast<SamplingIntegrator *>(parent); else m_parentIntegrator = this; }
void addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) { if (name == "exponent") m_exponent = static_cast<Texture *>(child); else if (name == "specularReflectance") m_specularReflectance = static_cast<Texture *>(child); else if (name == "diffuseReflectance") m_diffuseReflectance = static_cast<Texture *>(child); else BSDF::addChild(name, child); } else { BSDF::addChild(name, child); } }
void configure() { PhaseFunction::configure(); m_type = EAnisotropic | ENonSymmetric; Properties props("independent"); m_sampler = static_cast<Sampler*>(PluginManager::getInstance()->createObject(MTS_CLASS(Sampler), props)); m_sampler->configure(); if (m_stddev != -1.f) { Float sigma1 = m_fiberDistr.sigmaT(0.f) * 2.f; Float sigma2 = sigma1; Float sigma3 = m_fiberDistr.sigmaT(1.f) * 2.f; D = Matrix3x3(Vector(sigma1 * sigma1, 0, 0), Vector(0, sigma2 * sigma2, 0), Vector(0, 0, sigma3 * sigma3)); } }
void setParent(ConfigurableObject *parent) { Sensor::setParent(parent); if (parent->getClass()->derivesFrom(MTS_CLASS(Shape))) { Shape *shape = static_cast<Shape *>(parent); if (m_shape == shape || shape->isCompound()) return; if (m_shape != NULL) Log(EError, "An irradiance sensor cannot be parent of multiple shapes"); m_shape = shape; } else { Log(EError, "An irradiance sensor must be child of a shape instance"); } }
void addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) { if (name == "alpha") m_alphaU = m_alphaV = static_cast<Texture *>(child); else if (name == "alphaU") m_alphaU = static_cast<Texture *>(child); else if (name == "alphaV") m_alphaV = static_cast<Texture *>(child); else if (name == "specularReflectance") m_specularReflectance = static_cast<Texture *>(child); else BSDF::addChild(name, child); } else { BSDF::addChild(name, child); } }