From 071b7379c1baf8c379e23654e24c93a0190ea26d Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sat, 25 Jun 2011 00:24:41 +0200 Subject: [PATCH] fixed the composite material --- data/linux/build-sourcedist.sh | 9 -- data/tests/test_bsdf.xml | 43 +++++++-- src/bsdfs/composite.cpp | 170 ++++++++++++++++----------------- src/bsdfs/mask.cpp | 2 +- src/bsdfs/roughglass.cpp | 56 ++++++----- src/mitsuba/mtsutil.cpp | 2 + src/tests/test_chisquare.cpp | 6 +- 7 files changed, 154 insertions(+), 134 deletions(-) delete mode 100755 data/linux/build-sourcedist.sh diff --git a/data/linux/build-sourcedist.sh b/data/linux/build-sourcedist.sh deleted file mode 100755 index 47969bd6..00000000 --- a/data/linux/build-sourcedist.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -tar --exclude-vcs -czvf mitsuba-$1.tar.gz ChangeLog README SConstruct \ - config include/ schema/ src/bsdfs/ src/cameras/ src/collada/ src/films/ src/libcore/ src/libhw/ \ - src/librender/ src/luminaires/ src/medium/ src/mitsuba/ src/phase/ src/qtgui/ src/rfilters/ src/samplers/ \ - src/shapes/ src/subsurface/ src/textures/ src/utils/ src/volume/ src/integrators/direct src/integrators/misc \ - src/integrators/path src/integrators/photonmapper src/integrators/vpl tools/boost tools/darwin \ - tools/build.sh tools/scons-1.2.0 tools/windows tools/linux/*.sh tools/linux/mitsuba.desktop tools/qt4.py \ - tools/build.bat doc/license.txt setpath.sh diff --git a/data/tests/test_bsdf.xml b/data/tests/test_bsdf.xml index c93b06f2..2450e5c7 100644 --- a/data/tests/test_bsdf.xml +++ b/data/tests/test_bsdf.xml @@ -41,6 +41,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -55,15 +80,6 @@ - - - - - - - - @@ -82,5 +98,14 @@ + + + + + + + + diff --git a/src/bsdfs/composite.cpp b/src/bsdfs/composite.cpp index 0d6c14af..792fb4ae 100644 --- a/src/bsdfs/composite.cpp +++ b/src/bsdfs/composite.cpp @@ -29,13 +29,12 @@ MTS_NAMESPACE_BEGIN class Composite : public BSDF { public: Composite(const Properties &props) - : BSDF(props), m_bsdfWeight(NULL) { + : BSDF(props), m_bsdfWeights(NULL), m_componentIndex(NULL), m_bsdfOffset(NULL) { /* Parse the weight parameter */ std::vector weights = tokenize(props.getString("weights", ""), " ,;"); m_bsdfCount = weights.size(); - m_bsdfWeight = new Float[m_bsdfCount]; - m_bsdfOffset = new int[m_bsdfCount]; + m_bsdfWeights = new Float[m_bsdfCount]; Float totalWeight = 0; char *end_ptr = NULL; @@ -45,7 +44,7 @@ public: SLog(EError, "Could not parse the BRDF weights!"); if (weight < 0) SLog(EError, "Invalid BRDF weight!"); - m_bsdfWeight[i] = weight; + m_bsdfWeights[i] = weight; totalWeight += weight; } @@ -54,12 +53,11 @@ public: } Composite(Stream *stream, InstanceManager *manager) - : BSDF(stream, manager), m_bsdfWeight(NULL) { + : BSDF(stream, manager), m_bsdfWeights(NULL), m_componentIndex(NULL), m_bsdfOffset(NULL) { m_bsdfCount = stream->readSize(); - m_bsdfWeight = new Float[m_bsdfCount]; - m_bsdfOffset = new int[m_bsdfCount]; + m_bsdfWeights = new Float[m_bsdfCount]; for (size_t i=0; ireadFloat(); + m_bsdfWeights[i] = stream->readFloat(); BSDF *bsdf = static_cast(manager->getInstance(stream)); bsdf->incRef(); m_bsdfs.push_back(bsdf); @@ -72,10 +70,12 @@ public: m_bsdfs[i]->decRef(); if (m_type) delete[] m_type; - if (m_bsdfWeight) { - delete[] m_bsdfWeight; + if (m_bsdfWeights) + delete[] m_bsdfWeights; + if (m_componentIndex) + delete[] m_componentIndex; + if (m_bsdfOffset) delete[] m_bsdfOffset; - } } void serialize(Stream *stream, InstanceManager *manager) const { @@ -83,7 +83,7 @@ public: stream->writeSize(m_bsdfCount); for (size_t i=0; iwriteFloat(m_bsdfWeight[i]); + stream->writeFloat(m_bsdfWeights[i]); manager->serialize(stream, m_bsdfs[i]); } } @@ -99,24 +99,37 @@ public: Log(EError, "BSDF count mismatch: " SIZE_T_FMT " bsdfs, but specified " SIZE_T_FMT " weights", m_bsdfs.size(), m_bsdfCount); - int offset = 0; for (size_t i=0; igetComponentCount(); + m_componentCount += m_bsdfs[i]->getComponentCount(); m_pdf = DiscretePDF(m_bsdfs.size()); + if (m_type) + delete[] m_type; + if (m_componentIndex) + delete[] m_componentIndex; + if (m_bsdfOffset) + delete[] m_bsdfOffset; + m_type = new unsigned int[m_componentCount]; + m_componentIndex = new std::pair[m_componentCount]; + m_bsdfOffset = new int[m_bsdfCount]; + int ctr = 0, offset = 0; + for (size_t i=0; igetComponentCount(); ++j) { int componentType = bsdf->getType(j); m_type[offset+j] = componentType; + m_componentIndex[ctr++] = std::make_pair((int) i, j); } + m_combinedType |= bsdf->getType(); offset += bsdf->getComponentCount(); m_usesRayDifferentials |= bsdf->usesRayDifferentials(); - m_pdf[i] = m_bsdfWeight[i]; + m_pdf[i] = m_bsdfWeights[i]; } m_pdf.build(); } @@ -124,7 +137,7 @@ public: Spectrum getDiffuseReflectance(const Intersection &its) const { Spectrum result(0.0f); for (size_t i=0; igetDiffuseReflectance(its) * m_bsdfWeight[i]; + result+= m_bsdfs[i]->getDiffuseReflectance(its) * m_bsdfWeights[i]; return result; } @@ -133,18 +146,13 @@ public: if (bRec.component == -1) { for (size_t i=0; if(bRec) * m_bsdfWeight[i]; + result += m_bsdfs[i]->f(bRec) * m_bsdfWeights[i]; } else { /* Pick out an individual component */ - for (size_t i=0; i= m_bsdfs[i]->getComponentCount()) - continue; - - BSDFQueryRecord bRec2(bRec); - bRec2.component = component; - return m_bsdfs[i]->f(bRec2) * m_bsdfWeight[i]; - } + int idx = m_componentIndex[bRec.component].first; + BSDFQueryRecord bRec2(bRec); + bRec2.component = m_componentIndex[bRec.component].second; + return m_bsdfs[idx]->f(bRec2) * m_bsdfWeights[idx]; } return result; @@ -155,18 +163,13 @@ public: if (bRec.component == -1) { for (size_t i=0; ifDelta(bRec) * m_bsdfWeight[i]; + result += m_bsdfs[i]->fDelta(bRec) * m_bsdfWeights[i]; } else { /* Pick out an individual component */ - for (size_t i=0; i= m_bsdfs[i]->getComponentCount()) - continue; - - BSDFQueryRecord bRec2(bRec); - bRec2.component = component; - return m_bsdfs[i]->fDelta(bRec2) * m_bsdfWeight[i]; - } + int idx = m_componentIndex[bRec.component].first; + BSDFQueryRecord bRec2(bRec); + bRec2.component = m_componentIndex[bRec.component].second; + return m_bsdfs[idx]->fDelta(bRec2) * m_bsdfWeights[idx]; } return result; @@ -180,15 +183,10 @@ public: result += m_bsdfs[i]->pdf(bRec) * m_pdf[i]; } else { /* Pick out an individual component */ - for (size_t i=0; i= m_bsdfs[i]->getComponentCount()) - continue; - - BSDFQueryRecord bRec2(bRec); - bRec2.component = component; - return m_bsdfs[i]->pdf(bRec2); - } + int idx = m_componentIndex[bRec.component].first; + BSDFQueryRecord bRec2(bRec); + bRec2.component = m_componentIndex[bRec.component].second; + return m_bsdfs[idx]->pdf(bRec2); } return result; @@ -202,15 +200,10 @@ public: result += m_bsdfs[i]->pdfDelta(bRec) * m_pdf[i]; } else { /* Pick out an individual component */ - for (size_t i=0; i= m_bsdfs[i]->getComponentCount()) - continue; - - BSDFQueryRecord bRec2(bRec); - bRec2.component = component; - return m_bsdfs[i]->pdfDelta(bRec2); - } + int idx = m_componentIndex[bRec.component].first; + BSDFQueryRecord bRec2(bRec); + bRec2.component = m_componentIndex[bRec.component].second; + return m_bsdfs[idx]->pdfDelta(bRec2); } return result; @@ -220,7 +213,11 @@ public: Point2 sample(_sample); if (bRec.component == -1) { int entry = m_pdf.sampleReuse(sample.x); - m_bsdfs[entry]->sample(bRec, sample); + Spectrum result = m_bsdfs[entry]->sample(bRec, sample); + + if (result.isZero()) // sampling failed + return result; + bRec.sampledComponent += m_bsdfOffset[entry]; if (bRec.sampledType & BSDF::EDelta) { @@ -232,28 +229,24 @@ public: } } else { /* Pick out an individual component */ - for (size_t i=0; i= m_bsdfs[i]->getComponentCount()) - continue; - - int tempComponent = bRec.component; - bRec.component = component; - Spectrum result = m_bsdfs[i]->sample(bRec, pdf, sample); - bRec.component = bRec.sampledComponent = tempComponent; - - return result * m_bsdfWeight[i]; - } + int idx = m_componentIndex[bRec.component].first; + int tempComponent = bRec.component; + bRec.component = m_componentIndex[bRec.component].second; + Spectrum result = m_bsdfs[idx]->sample(bRec, pdf, sample) * m_bsdfWeights[idx]; + bRec.component = bRec.sampledComponent = tempComponent; + return result; } - Log(EError, "Internal error!"); - return Spectrum(0.0f); } Spectrum sample(BSDFQueryRecord &bRec, const Point2 &_sample) const { Point2 sample(_sample); if (bRec.component == -1) { int entry = m_pdf.sampleReuse(sample.x); - m_bsdfs[entry]->sample(bRec, sample); + Spectrum result = m_bsdfs[entry]->sample(bRec, sample); + + if (result.isZero()) // sampling failed + return result; + bRec.sampledComponent += m_bsdfOffset[entry]; if (bRec.sampledType & BSDF::EDelta) @@ -262,21 +255,13 @@ public: return f(bRec)/pdf(bRec); } else { /* Pick out an individual component */ - for (size_t i=0; i= m_bsdfs[i]->getComponentCount()) - continue; - - int tempComponent = bRec.component; - bRec.component = component; - Spectrum result = m_bsdfs[i]->sample(bRec, sample); - bRec.component = bRec.sampledComponent = tempComponent; - - return result * m_bsdfWeight[i]; - } + int idx = m_componentIndex[bRec.component].first; + int tempComponent = bRec.component; + bRec.component = m_componentIndex[bRec.component].second; + Spectrum result = m_bsdfs[idx]->sample(bRec, sample) * m_bsdfWeights[idx]; + bRec.component = bRec.sampledComponent = tempComponent; + return result; } - Log(EError, "Internal error!"); - return Spectrum(0.0f); } void addChild(const std::string &name, ConfigurableObject *child) { @@ -292,11 +277,17 @@ public: std::string toString() const { std::ostringstream oss; oss << "Composite[" << endl + << " weights = {"; + for (size_t i=0; itoString()) << "," << endl; + oss << " " << indent(m_bsdfs[i]->toString(), 2) << "," << endl; oss << " }" << endl - << " pdf = " << m_pdf.toString() << endl << "]"; return oss.str(); } @@ -306,7 +297,8 @@ public: MTS_DECLARE_CLASS() private: size_t m_bsdfCount; - Float *m_bsdfWeight; + Float *m_bsdfWeights; + std::pair *m_componentIndex; int *m_bsdfOffset; std::vector m_bsdfs; DiscretePDF m_pdf; @@ -424,7 +416,7 @@ private: }; Shader *Composite::createShader(Renderer *renderer) const { - return new CompositeShader(renderer, m_bsdfs, m_bsdfWeight); + return new CompositeShader(renderer, m_bsdfs, m_bsdfWeights); } MTS_IMPLEMENT_CLASS(CompositeShader, false, Shader) diff --git a/src/bsdfs/mask.cpp b/src/bsdfs/mask.cpp index cf7414d9..86962351 100644 --- a/src/bsdfs/mask.cpp +++ b/src/bsdfs/mask.cpp @@ -41,7 +41,7 @@ public: virtual ~Mask() { if (m_type) - delete m_type; + delete[] m_type; } void serialize(Stream *stream, InstanceManager *manager) const { diff --git a/src/bsdfs/roughglass.cpp b/src/bsdfs/roughglass.cpp index 51265743..3bf70684 100644 --- a/src/bsdfs/roughglass.cpp +++ b/src/bsdfs/roughglass.cpp @@ -111,6 +111,37 @@ public: return Spectrum(0.0f); } + inline Vector reflect(const Vector &wi, const Normal &m) const { + return 2 * dot(wi, m) * Vector(m) - wi; + } + + inline bool refract(const Vector &wi, Vector &wo, const Normal &m) const { + /* Determine the appropriate indices of refraction */ + Float etaI = m_extIOR, etaT = m_intIOR; + if (Frame::cosTheta(wi) < 0) + std::swap(etaI, etaT); + + Float eta = etaI / etaT, c = dot(wi, m); + + /* Using Snell's law, calculate the squared cosine of the + angle between the normal and the transmitted ray */ + Float cosThetaTSqr = 1 + eta * eta * (c*c-1); + + if (cosThetaTSqr < 0) + return false; // Total internal reflection + + /* Compute the transmitted direction */ + wo = m * (eta*c - signum(wi.z) + * std::sqrt(cosThetaTSqr)) - wi * eta; + + return true; + } + + inline Float signum(Float value) const { + return (value < 0) ? -1.0f : 1.0f; + } + + /** * \brief Implements the microfacet distribution function D * @@ -248,29 +279,6 @@ public: return Normal(sphericalDirection(thetaM, phiM)); } - inline Vector reflect(const Vector &wi, const Normal &m) const { - return 2 * dot(wi, m) * Vector(m) - wi; - } - - inline bool refract(const Vector &wi, Vector &wo, const Normal &m) const { - Float etaI = m_extIOR, etaT = m_intIOR; - if (Frame::cosTheta(wi) < 0) - std::swap(etaI, etaT); - - Float eta = etaI / etaT, c = dot(wi, m); - Float cosThetaTSqr = 1 + eta * eta * (c*c-1); - if (cosThetaTSqr < 0) // Total internal reflection - return false; - - wo = m * (eta*c - signum(wi.z) - * std::sqrt(cosThetaTSqr)) - wi * eta; - return true; - } - - inline Float signum(Float value) const { - return (value < 0) ? -1.0f : 1.0f; - } - inline Spectrum fReflection(const BSDFQueryRecord &bRec) const { Float intIOR = m_intIOR, extIOR = m_extIOR; @@ -448,7 +456,7 @@ public: /* Sample the microfacet normal */ Vector m = sampleD(sample, alpha); - /* Refract */ + /* Refract based on 'm' */ if (!refract(bRec.wi, bRec.wo, m)) return Spectrum(0.0f); diff --git a/src/mitsuba/mtsutil.cpp b/src/mitsuba/mtsutil.cpp index 19602220..a3a619bf 100644 --- a/src/mitsuba/mtsutil.cpp +++ b/src/mitsuba/mtsutil.cpp @@ -66,6 +66,8 @@ void help() { FileResolver *fileResolver = Thread::getThread()->getFileResolver(); std::ostringstream utilities, testcases; + cout << "[ Loading plugin list .. ]" << endl << endl; + testcases << "The following testcases are available:" << endl << endl; utilities << endl << "The following utilities are available:" << endl << endl; diff --git a/src/tests/test_chisquare.cpp b/src/tests/test_chisquare.cpp index e666be1c..ed2b6dbf 100644 --- a/src/tests/test_chisquare.cpp +++ b/src/tests/test_chisquare.cpp @@ -73,7 +73,7 @@ public: SAssert(a >= 0 && b >= 0); Float min = std::min(a, b); Float err = std::abs(a - b); - m_largestWeight = std::max(m_largestWeight, a * Frame::cosTheta(bRec.wo)); + m_largestWeight = std::max(m_largestWeight, a * std::abs(Frame::cosTheta(bRec.wo))); if (min < Epsilon && err > Epsilon) // absolute error threshold mismatch = true; @@ -205,8 +205,10 @@ public: progress->update(j+1); } } + Log(EInfo, "Done with this BSDF. The largest encountered " + "importance weight was = %.2f", largestWeight); + largestWeight = 0; } - Log(EInfo, "Done with this model. The largest encountered importance weight was = %.2f", largestWeight); } Log(EInfo, "%i/%i BSDF checks succeeded", testCount-failureCount, testCount); delete progress;