From c511567250d98026b7c6608da9b90ba271518ed5 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Thu, 21 Apr 2011 01:12:08 +0200 Subject: [PATCH] partial merge with the -ctrewrite branch --- include/mitsuba/core/random.h | 5 +++ include/mitsuba/core/ray.h | 4 +-- include/mitsuba/render/mipmap.h | 15 +++++++-- include/mitsuba/render/shape.h | 8 +++-- include/mitsuba/render/texture.h | 13 +++++--- src/bsdfs/SConscript | 1 + src/bsdfs/lambertian.cpp | 2 +- src/libcore/random.cpp | 5 +++ src/librender/mipmap.cpp | 56 ++++++++++++++++++++------------ src/librender/shape.cpp | 6 ++++ src/librender/texture.cpp | 4 +++ src/medium/heterogeneous.cpp | 53 +++++++++++++++--------------- src/phase/microflake.cpp | 24 +++++++++++--- src/phase/microflake_fiber.h | 12 +++++++ src/shapes/hair.cpp | 4 +-- src/shapes/obj.cpp | 5 +-- src/textures/exrtexture.cpp | 8 +++++ src/textures/ldrtexture.cpp | 34 +++++++++++-------- 18 files changed, 173 insertions(+), 86 deletions(-) diff --git a/include/mitsuba/core/random.h b/include/mitsuba/core/random.h index af4650ad..80434c6a 100644 --- a/include/mitsuba/core/random.h +++ b/include/mitsuba/core/random.h @@ -101,6 +101,11 @@ public: */ Random(); + /** + * \brief Construct a random generator with a custom seed + */ + Random(uint64_t seed); + /// Construct a new random generator seeded from a pre-existing one Random(Random *random); diff --git a/include/mitsuba/core/ray.h b/include/mitsuba/core/ray.h index 1e8efa4f..fad8dcd9 100644 --- a/include/mitsuba/core/ray.h +++ b/include/mitsuba/core/ray.h @@ -113,7 +113,7 @@ struct Ray { /// Return a string representation of this ray inline std::string toString() const { std::ostringstream oss; - oss << "Ray[orig=" << o.toString() << ", dest=" + oss << "Ray[orig=" << o.toString() << ", dir=" << d.toString() << ", mint=" << mint << ", maxt=" << maxt << ", time=" << time << "]"; return oss.str(); @@ -188,7 +188,7 @@ struct RayDifferential : public Ray { std::ostringstream oss; oss << "RayDifferential[" << endl << " orig = " << o.toString() << "," << endl - << " dest = " << d.toString() << "," << endl + << " dir = " << d.toString() << "," << endl << " mint = " << mint << "," << endl << " maxt = " << maxt << "," << endl << " time = " << time << "," << endl diff --git a/include/mitsuba/render/mipmap.h b/include/mitsuba/render/mipmap.h index 8dd92f9c..8a974f8e 100644 --- a/include/mitsuba/render/mipmap.h +++ b/include/mitsuba/render/mipmap.h @@ -36,17 +36,26 @@ public: EClamp }; + enum EFilterType { + /// Elliptically weighted average + EEWA, + /// Trilinear filtering + ETrilinear, + /// No filtering + ENone + }; + /** * Construct a new mip-map from the given texture. Does not * need to have a power-of-two size. */ MIPMap(int width, int height, Spectrum *pixels, - bool isotropic = false, EWrapMode wrapMode = ERepeat, + EFilterType filterType = EEWA, EWrapMode wrapMode = ERepeat, Float maxAnisotropy = 8.0f); /// Construct a mip map from a HDR bitmap static ref fromBitmap(Bitmap *bitmap, - bool isotropic = false, EWrapMode wrapMode = ERepeat, + EFilterType filterType = EEWA, EWrapMode wrapMode = ERepeat, Float maxAnisotropy = 8.0f); /// Do a mip-map lookup at the appropriate level @@ -115,7 +124,7 @@ private: int *m_levelWidth; int *m_levelHeight; Spectrum **m_pyramid; - bool m_isotropic; + EFilterType m_filterType; EWrapMode m_wrapMode; Float *m_weightLut; Float m_maxAnisotropy; diff --git a/include/mitsuba/render/shape.h b/include/mitsuba/render/shape.h index 36540058..df89fb27 100644 --- a/include/mitsuba/render/shape.h +++ b/include/mitsuba/render/shape.h @@ -195,8 +195,12 @@ public: virtual Shape *getElement(int i); - /// Return the shape's surface area - virtual Float getSurfaceArea() const = 0; + /** + * \brief Return the shape's surface area + * + * The default implementation throws an exception + */ + virtual Float getSurfaceArea() const; /// Return a bounding box containing the shape virtual AABB getAABB() const = 0; diff --git a/include/mitsuba/render/texture.h b/include/mitsuba/render/texture.h index 155e1c62..7fd8f008 100644 --- a/include/mitsuba/render/texture.h +++ b/include/mitsuba/render/texture.h @@ -39,6 +39,9 @@ public: /// Return the component-wise maximum of the texture over its domain virtual Spectrum getMaximum() const = 0; + /// Return the resolution in pixels, if applicable + virtual Vector3i getResolution() const; + /** * \brief Does this texture do pre-filtering when ray * differentials are available? @@ -64,11 +67,6 @@ public: /// Serialize to a binary data stream virtual void serialize(Stream *stream, InstanceManager *manager) const; - MTS_DECLARE_CLASS() -protected: - Texture2D(const Properties &props); - Texture2D(Stream *stream, InstanceManager *manager); - /// Texture2D subclass must provide this function virtual Spectrum getValue(const Point2 &uv) const = 0; @@ -76,6 +74,11 @@ protected: virtual Spectrum getValue(const Point2 &uv, Float dudx, Float dudy, Float dvdx, Float dvdy) const = 0; + MTS_DECLARE_CLASS() +protected: + Texture2D(const Properties &props); + Texture2D(Stream *stream, InstanceManager *manager); + virtual ~Texture2D(); protected: Point2 m_uvOffset; diff --git a/src/bsdfs/SConscript b/src/bsdfs/SConscript index 80979651..4ad7dfb0 100644 --- a/src/bsdfs/SConscript +++ b/src/bsdfs/SConscript @@ -13,5 +13,6 @@ plugins += env.SharedLibrary('#plugins/roughglass', ['roughglass.cpp']) plugins += env.SharedLibrary('#plugins/roughmetal', ['roughmetal.cpp']) plugins += env.SharedLibrary('#plugins/composite', ['composite.cpp']) plugins += env.SharedLibrary('#plugins/twosided', ['twosided.cpp']) +plugins += env.SharedLibrary('#plugins/irawan', ['irawan.cpp']) Export('plugins') diff --git a/src/bsdfs/lambertian.cpp b/src/bsdfs/lambertian.cpp index 473cd7c4..7502ed15 100644 --- a/src/bsdfs/lambertian.cpp +++ b/src/bsdfs/lambertian.cpp @@ -116,7 +116,7 @@ public: std::string toString() const { std::ostringstream oss; - oss << "Microfacet[" << endl + oss << "Lambertian[" << endl << " reflectance = " << indent(m_reflectance->toString()) << endl << "]"; return oss.str(); diff --git a/src/libcore/random.cpp b/src/libcore/random.cpp index 27ba1bcc..3246b87a 100644 --- a/src/libcore/random.cpp +++ b/src/libcore/random.cpp @@ -80,6 +80,11 @@ Random::Random(Random *random) { seed(random); } +Random::Random(uint64_t seedval) { + mti=MT_N+1; /* mti==N+1 means mt[N] is not initialized */ + seed(seedval); +} + Random::Random(Stream *stream, InstanceManager *manager) : SerializableObject(stream, manager) { mti = stream->readInt(); diff --git a/src/librender/mipmap.cpp b/src/librender/mipmap.cpp index ca62a8ed..78103416 100644 --- a/src/librender/mipmap.cpp +++ b/src/librender/mipmap.cpp @@ -26,12 +26,12 @@ static StatsCounter ewaLookups("Texture", "EWA texture lookups"); /* Isotropic/anisotropic EWA mip-map texture map class based on PBRT */ MIPMap::MIPMap(int width, int height, Spectrum *pixels, - bool isotropic, EWrapMode wrapMode, Float maxAnisotropy) - : m_width(width), m_height(height), m_isotropic(isotropic), + EFilterType filterType, EWrapMode wrapMode, Float maxAnisotropy) + : m_width(width), m_height(height), m_filterType(filterType), m_wrapMode(wrapMode), m_maxAnisotropy(maxAnisotropy) { Spectrum *texture = pixels; - if (!isPow2(width) || !isPow2(height)) { + if (filterType != ENone && (!isPow2(width) || !isPow2(height))) { m_width = (int) roundToPow2((uint32_t) width); m_height = (int) roundToPow2((uint32_t) height); @@ -87,7 +87,11 @@ MIPMap::MIPMap(int width, int height, Spectrum *pixels, delete[] texture1; } - m_levels = 1 + log2i((uint32_t) std::max(width, height)); + if (m_filterType != ENone) + m_levels = 1 + log2i((uint32_t) std::max(width, height)); + else + m_levels = 1; + m_pyramid = new Spectrum*[m_levels]; m_pyramid[0] = texture; m_levelWidth = new int[m_levels]; @@ -111,7 +115,7 @@ MIPMap::MIPMap(int width, int height, Spectrum *pixels, } } - if (!isotropic) { + if (m_filterType == EEWA) { m_weightLut = static_cast(allocAligned(sizeof(Float)*MIPMAP_LUTSIZE)); for (int i=0; i MIPMap::fromBitmap(Bitmap *bitmap, bool isotropic, +ref MIPMap::fromBitmap(Bitmap *bitmap, EFilterType filterType, EWrapMode wrapMode, Float maxAnisotropy) { int width = bitmap->getWidth(); int height = bitmap->getHeight(); @@ -169,7 +173,7 @@ ref MIPMap::fromBitmap(Bitmap *bitmap, bool isotropic, } return new MIPMap(width, height, pixels, - isotropic, wrapMode, maxAnisotropy); + filterType, wrapMode, maxAnisotropy); } MIPMap::ResampleWeight *MIPMap::resampleWeights(int oldRes, int newRes) const { @@ -179,7 +183,7 @@ MIPMap::ResampleWeight *MIPMap::resampleWeights(int oldRes, int newRes) const { ResampleWeight *weights = new ResampleWeight[newRes]; for (int i=0; iserialize(stream, m_exteriorMedium.get()); stream->writeBool(m_occluder); } + +Float Shape::getSurfaceArea() const { + Log(EError, "%s::getSurfaceArea(): Not implemented!", + getClass()->getName().c_str()); + return 0.0f; +} bool Shape::rayIntersect(const Ray &ray, Float mint, Float maxt, Float &t, void *temp) const { diff --git a/src/librender/texture.cpp b/src/librender/texture.cpp index 19d94d92..713e8300 100644 --- a/src/librender/texture.cpp +++ b/src/librender/texture.cpp @@ -28,6 +28,10 @@ Texture::Texture(const Properties &props) Texture::Texture(Stream *stream, InstanceManager *manager) : ConfigurableObject(stream, manager) { } + +Vector3i Texture::getResolution() const { + return Vector3i(0); +} Texture::~Texture() { } diff --git a/src/medium/heterogeneous.cpp b/src/medium/heterogeneous.cpp index 29d73cb4..987dd15d 100644 --- a/src/medium/heterogeneous.cpp +++ b/src/medium/heterogeneous.cpp @@ -35,7 +35,7 @@ MTS_NAMESPACE_BEGIN #if defined(HETVOL_STATISTICS) static StatsCounter avgNewtonIterations("Heterogeneous volume", "Avg. # of Newton-Bisection iterations", EAverage); -static StatsCounter avgRayMarchingStepsTransmission("Heterogeneous volume", +static StatsCounter avgRayMarchingStepsTransmittance("Heterogeneous volume", "Avg. # of ray marching steps (transmittance)", EAverage); static StatsCounter avgRayMarchingStepsSampling("Heterogeneous volume", "Avg. # of ray marching steps (sampling)", EAverage); @@ -45,7 +45,7 @@ static StatsCounter earlyExits("Heterogeneous volume", /** * Flexible heterogeneous medium implementation, which acquires its data from - * nested Volume instances. These can be constant, use a procedural + * nested \ref Volume instances. These can be constant, use a procedural * function, or fetch data from disk, e.g. using a memory-mapped density grid. * * Instead of allowing separate volumes to be provided for the scattering @@ -53,14 +53,16 @@ static StatsCounter earlyExits("Heterogeneous volume", * enforcing a spectrally uniform sigma_t, which must be provided using a * nested scalar-valued volume named 'density'. * - * A nested spectrum-valued 'albedo' volume must also be provided, which is + * Another nested spectrum-valued 'albedo' volume must also be provided, which is * used to compute the parameter sigma_s using the expression * "sigma_s = density * albedo" (i.e. 'albedo' contains the single-scattering * albedo of the medium). * * Optionally, one can also provide an vector-valued 'orientation' volume, * which contains local particle orientation that will be passed to - * scattering models such as Kajiya-Kay phase function. + * scattering models such as a the Micro-flake or Kajiya-Kay phase functions. + * + * \author Wenzel Jakob */ class HeterogeneousMedium : public Medium { public: @@ -98,7 +100,7 @@ public: Log(EError, "No density specified!"); if (m_albedo.get() == NULL) Log(EError, "No albedo specified!"); - m_aabb = m_density->getAABB(); + m_densityAABB = m_density->getAABB(); m_directionallyVaryingCoefficients = m_phaseFunction->needsDirectionallyVaryingCoefficients(); @@ -162,7 +164,7 @@ public: /* Determine the ray segment, along which the density integration should take place */ Float mint, maxt; - if (!m_aabb.rayIntersect(ray, mint, maxt)) + if (!m_densityAABB.rayIntersect(ray, mint, maxt)) return 0.0f; mint = std::max(mint, ray.mint); @@ -171,23 +173,20 @@ public: Point p = ray(mint), pLast = ray(maxt); - for (int i=0; i<3; ++i) { - maxComp = std::max(maxComp, std::abs(p[i])); - maxComp = std::max(maxComp, std::abs(pLast[i])); - } - /* Ignore degenerate path segments */ + for (int i=0; i<3; ++i) + maxComp = std::max(std::max(maxComp, + std::abs(p[i])), std::abs(pLast[i])); if (length < 1e-6f * maxComp) return 0.0f; /* Compute a suitable step size */ - uint32_t nSteps = (uint32_t) std::ceil(length / m_stepSize); - nSteps += nSteps % 2; + uint32_t nSteps = (uint32_t) std::ceil(length / m_stepSize)*2; const Float stepSize = length/nSteps; const Vector increment = ray.d * stepSize; #if defined(HETVOL_STATISTICS) - avgRayMarchingStepsTransmission.incrementBase(); + avgRayMarchingStepsTransmittance.incrementBase(); earlyExits.incrementBase(); #endif @@ -209,7 +208,7 @@ public: m = 6 - m; #if defined(HETVOL_STATISTICS) - ++avgRayMarchingStepsTransmission; + ++avgRayMarchingStepsTransmittance; #endif #if defined(HETVOL_EARLY_EXIT) @@ -287,19 +286,17 @@ public: /* Determine the ray segment, along which the density integration should take place */ Float mint, maxt; - if (!m_aabb.rayIntersect(ray, mint, maxt)) + if (!m_densityAABB.rayIntersect(ray, mint, maxt)) return false; mint = std::max(mint, ray.mint); maxt = std::min(maxt, ray.maxt); Float length = maxt - mint, maxComp = 0; Point p = ray(mint), pLast = ray(maxt); - for (int i=0; i<3; ++i) { - maxComp = std::max(maxComp, std::abs(p[i])); - maxComp = std::max(maxComp, std::abs(pLast[i])); - } - /* Ignore degenerate path segments */ + for (int i=0; i<3; ++i) + maxComp = std::max(std::max(maxComp, + std::abs(p[i])), std::abs(pLast[i])); if (length < 1e-6f * maxComp) return 0.0f; @@ -434,10 +431,7 @@ public: mRec.pdfSuccessRev = expVal * densityAtMinT; mRec.transmittance = Spectrum(expVal); - if (mRec.pdfSuccess == 0) - return false; - - return success; + return success && mRec.pdfSuccess > 0; } void pdfDistance(const Ray &ray, MediumSamplingRecord &mRec) const { @@ -458,9 +452,9 @@ public: std::string toString() const { std::ostringstream oss; oss << "HeterogeneousMedium[" << endl + << " density = " << indent(m_density.toString()) << "," << endl << " albedo = " << indent(m_albedo.toString()) << "," << endl << " orientation = " << indent(m_orientation.toString()) << "," << endl - << " density = " << indent(m_density.toString()) << "," << endl << " stepSize = " << m_stepSize << "," << endl << " densityMultiplier = " << m_densityMultiplier << endl << "]"; @@ -475,6 +469,11 @@ protected: Vector orientation = m_orientation->lookupVector(p); if (!orientation.isZero()) density *= m_phaseFunction->sigmaDir(dot(d, orientation)); + ///////// HACKY WORKAROUND FOR ZERO DENSITIES ///////// + else + return 0; + ///////// HACKY WORKAROUND FOR ZERO DENSITIES ///////// + } return density; } @@ -483,7 +482,7 @@ protected: ref m_albedo; ref m_orientation; Float m_stepSize; - AABB m_aabb; + AABB m_densityAABB; bool m_directionallyVaryingCoefficients; }; diff --git a/src/phase/microflake.cpp b/src/phase/microflake.cpp index 33412fe6..601c3f2d 100644 --- a/src/phase/microflake.cpp +++ b/src/phase/microflake.cpp @@ -16,7 +16,6 @@ along with this program. If not, see . */ -#include #include #include #include @@ -50,6 +49,8 @@ static StatsCounter avgSampleIterations("Micro-flake model", * "Building Volumetric Appearance Models of Fabric using * Micro CT Imaging" by Shuang Zhao, Wenzel Jakob, Steve Marschner, * and Kavita Bala, ACM SIGGRAPH 2011 + * + * \author Wenzel Jakob */ class MicroflakePhaseFunction : public PhaseFunction { public: @@ -71,8 +72,14 @@ public: } Float f(const PhaseFunctionQueryRecord &pRec) const { - if (pRec.mRec.orientation.isZero()) - return 0.0f; + if (pRec.mRec.orientation.isZero()) { + /* What to do when the local orientation is undefined */ + #if 0 + return 1.0f / (4 * M_PI); + #else + return 0.0f; + #endif + } Frame frame(pRec.mRec.orientation); Vector wi = frame.toLocal(pRec.wi); @@ -88,8 +95,15 @@ public: } inline Float sample(PhaseFunctionQueryRecord &pRec, Sampler *sampler) const { - if (pRec.mRec.orientation.isZero()) - return 0.0f; + if (pRec.mRec.orientation.isZero()) { + /* What to do when the local orientation is undefined */ + #if 0 + pRec.wo = squareToSphere(sampler->next2D()); + return 1.0f; + #else + return 0.0f; + #endif + } Frame frame(pRec.mRec.orientation); Vector wi = frame.toLocal(pRec.wi); diff --git a/src/phase/microflake_fiber.h b/src/phase/microflake_fiber.h index 0f83c229..44f5f248 100644 --- a/src/phase/microflake_fiber.h +++ b/src/phase/microflake_fiber.h @@ -186,6 +186,18 @@ static StatsCounter avgBrentFunEvals("Micro-flake model", "Average Brent solver function evaluations", EAverage); #endif + +/** + * \brief Flake distribution for simulating rough fibers + * + * This class implements the Gaussian flake distribution proposed in + * + * "Building Volumetric Appearance Models of Fabric using + * Micro CT Imaging" by Shuang Zhao, Wenzel Jakob, Steve Marschner, + * and Kavita Bala, ACM SIGGRAPH 2011 + * + * \author Wenzel Jakob + */ class GaussianFiberDistribution { public: inline GaussianFiberDistribution() {} diff --git a/src/shapes/hair.cpp b/src/shapes/hair.cpp index 08054284..b8184be5 100644 --- a/src/shapes/hair.cpp +++ b/src/shapes/hair.cpp @@ -372,7 +372,7 @@ public: } #else /// Compute the AABB of a segment (only used during tree construction) - AABB getAABB(int index) const { + AABB getAABB(index_type index) const { index_type iv = m_segIndex.at(index); // cosine of steepest miter angle @@ -393,7 +393,7 @@ public: } /// Compute the clipped AABB of a segment (only used during tree construction) - AABB getClippedAABB(int index, const AABB &box) const { + AABB getClippedAABB(index_type index, const AABB &box) const { AABB aabb(getAABB(index)); aabb.clip(box); return aabb; diff --git a/src/shapes/obj.cpp b/src/shapes/obj.cpp index 65f3be43..ddf2fab7 100644 --- a/src/shapes/obj.cpp +++ b/src/shapes/obj.cpp @@ -464,11 +464,8 @@ public: m_meshes[i]->addChild(name, child); } } else if (cClass->derivesFrom(MTS_CLASS(Medium))) { - Assert(m_subsurface == NULL); - for (size_t i=0; isetParent(m_meshes[i]); + for (size_t i=0; iaddChild(name, child); - } } else { Shape::addChild(name, child); } diff --git a/src/textures/exrtexture.cpp b/src/textures/exrtexture.cpp index 86d684c4..baa1f12b 100644 --- a/src/textures/exrtexture.cpp +++ b/src/textures/exrtexture.cpp @@ -87,6 +87,14 @@ public: return true; } + Vector3i getResolution() const { + return Vector3i( + m_mipmap->getWidth(), + m_mipmap->getHeight(), + 1 + ); + } + std::string toString() const { std::ostringstream oss; oss << "EXRTexture[filename=\"" << m_filename.file_string() << "\"]"; diff --git a/src/textures/ldrtexture.cpp b/src/textures/ldrtexture.cpp index e8bf988b..fceb9f37 100644 --- a/src/textures/ldrtexture.cpp +++ b/src/textures/ldrtexture.cpp @@ -35,11 +35,6 @@ MTS_NAMESPACE_BEGIN */ class LDRTexture : public Texture2D { public: - enum EFilterType { - EEWAFilter = 0, - EIsotropicFilter - }; - LDRTexture(const Properties &props) : Texture2D(props) { m_filename = Thread::getThread()->getFileResolver()->resolve( props.getString("filename")); @@ -53,12 +48,14 @@ public: std::string wrapMode = props.getString("wrapMode", "repeat"); if (filterType == "ewa") - m_anisotropic = true; - else if (filterType == "isotropic") - m_anisotropic = false; + m_filterType = MIPMap::EEWA; + else if (filterType == "trilinear") + m_filterType = MIPMap::ETrilinear; + else if (filterType == "none") + m_filterType = MIPMap::ENone; else Log(EError, "Unknown filter type '%s' -- must be " - "'ewa' or 'isotropic'!", filterType.c_str()); + "'ewa', 'isotropic', or 'none'!", filterType.c_str()); if (wrapMode == "repeat") m_wrapMode = MIPMap::ERepeat; @@ -95,7 +92,7 @@ public: Log(EInfo, "Unserializing texture \"%s\"", m_filename.leaf().c_str()); m_gamma = stream->readFloat(); m_format = static_cast(stream->readInt()); - m_anisotropic = stream->readBool(); + m_filterType = (MIPMap::EFilterType) stream->readInt(); m_wrapMode = (MIPMap::EWrapMode) stream->readUInt(); m_maxAnisotropy = stream->readFloat(); uint32_t size = stream->readUInt(); @@ -204,7 +201,7 @@ public: Log(EError, "%i bpp images are currently not supported!", bitmap->getBitsPerPixel()); } - m_mipmap = MIPMap::fromBitmap(corrected, !m_anisotropic, + m_mipmap = MIPMap::fromBitmap(corrected, m_filterType, m_wrapMode, m_maxAnisotropy); m_average = m_mipmap->triangle(m_mipmap->getLevels()-1, 0, 0); m_maximum = m_mipmap->getMaximum(); @@ -215,7 +212,7 @@ public: stream->writeString(m_filename.file_string()); stream->writeFloat(m_gamma); stream->writeInt(m_format); - stream->writeBool(m_anisotropic); + stream->writeInt(m_filterType); stream->writeUInt(m_wrapMode); stream->writeFloat(m_maxAnisotropy); @@ -251,6 +248,14 @@ public: return true; } + Vector3i getResolution() const { + return Vector3i( + m_mipmap->getWidth(), + m_mipmap->getHeight(), + 1 + ); + } + std::string toString() const { std::ostringstream oss; oss << "LDRTexture[" << endl @@ -268,9 +273,9 @@ protected: ref m_stream; fs::path m_filename; Bitmap::EFileFormat m_format; + MIPMap::EFilterType m_filterType; Spectrum m_average, m_maximum; Float m_gamma; - bool m_anisotropic; MIPMap::EWrapMode m_wrapMode; Float m_maxAnisotropy; }; @@ -340,7 +345,8 @@ private: Shader *LDRTexture::createShader(Renderer *renderer) const { return new LDRTextureShader(renderer, m_filename.leaf(), m_mipmap->getLDRBitmap(), m_uvOffset, m_uvScale, - m_wrapMode, m_anisotropic ? m_maxAnisotropy : 1.0f); + m_wrapMode, (m_filterType == MIPMap::EEWA) + ? m_maxAnisotropy : 1.0f); } MTS_IMPLEMENT_CLASS_S(LDRTexture, false, Texture2D)