partial merge with the -ctrewrite branch
parent
a3f7922f0f
commit
c511567250
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<MIPMap> 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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<Float *>(allocAligned(sizeof(Float)*MIPMAP_LUTSIZE));
|
||||
for (int i=0; i<MIPMAP_LUTSIZE; ++i) {
|
||||
Float pos = (Float) i / (Float) (MIPMAP_LUTSIZE-1);
|
||||
|
@ -121,7 +125,7 @@ MIPMap::MIPMap(int width, int height, Spectrum *pixels,
|
|||
}
|
||||
|
||||
MIPMap::~MIPMap() {
|
||||
if (!m_isotropic)
|
||||
if (m_filterType == EEWA)
|
||||
freeAligned(m_weightLut);
|
||||
for (int i=0; i<m_levels; i++)
|
||||
delete[] m_pyramid[i];
|
||||
|
@ -149,7 +153,7 @@ Spectrum MIPMap::getMaximum() const {
|
|||
return max;
|
||||
}
|
||||
|
||||
ref<MIPMap> MIPMap::fromBitmap(Bitmap *bitmap, bool isotropic,
|
||||
ref<MIPMap> MIPMap::fromBitmap(Bitmap *bitmap, EFilterType filterType,
|
||||
EWrapMode wrapMode, Float maxAnisotropy) {
|
||||
int width = bitmap->getWidth();
|
||||
int height = bitmap->getHeight();
|
||||
|
@ -169,7 +173,7 @@ ref<MIPMap> 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; i<newRes; i++) {
|
||||
Float center = (i + .5f) * oldRes / newRes;
|
||||
weights[i].firstTexel = (int) std::floor(center - filterWidth + (Float) 0.5f);
|
||||
weights[i].firstTexel = floorToInt(center - filterWidth + (Float) 0.5f);
|
||||
Float weightSum = 0;
|
||||
for (int j=0; j<4; j++) {
|
||||
Float pos = weights[i].firstTexel + j + .5f;
|
||||
|
@ -221,20 +225,26 @@ Spectrum MIPMap::getTexel(int level, int x, int y) const {
|
|||
}
|
||||
|
||||
Spectrum MIPMap::triangle(int level, Float x, Float y) const {
|
||||
level = clamp(level, 0, m_levels - 1);
|
||||
x = x * m_levelWidth[level] - 0.5f;
|
||||
y = y * m_levelHeight[level] - 0.5f;
|
||||
int xPos = (int) std::floor(x), yPos = (int) std::floor(y);
|
||||
Float dx = x - xPos, dy = y - yPos;
|
||||
return getTexel(level, xPos, yPos) * (1.0f - dx) * (1.0f - dy)
|
||||
+ getTexel(level, xPos, yPos + 1) * (1.0f - dx) * dy
|
||||
+ getTexel(level, xPos + 1, yPos) * dx * (1.0f - dy)
|
||||
+ getTexel(level, xPos + 1, yPos + 1) * dx * dy;
|
||||
if (m_filterType == ENone) {
|
||||
int xPos = floorToInt(x*m_levelWidth[0]),
|
||||
yPos = floorToInt(y*m_levelHeight[0]);
|
||||
return getTexel(0, xPos, yPos);
|
||||
} else {
|
||||
level = clamp(level, 0, m_levels - 1);
|
||||
x = x * m_levelWidth[level] - 0.5f;
|
||||
y = y * m_levelHeight[level] - 0.5f;
|
||||
int xPos = floorToInt(x), yPos = floorToInt(y);
|
||||
Float dx = x - xPos, dy = y - yPos;
|
||||
return getTexel(level, xPos, yPos) * (1.0f - dx) * (1.0f - dy)
|
||||
+ getTexel(level, xPos, yPos + 1) * (1.0f - dx) * dy
|
||||
+ getTexel(level, xPos + 1, yPos) * dx * (1.0f - dy)
|
||||
+ getTexel(level, xPos + 1, yPos + 1) * dx * dy;
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum MIPMap::getValue(Float u, Float v,
|
||||
Float dudx, Float dudy, Float dvdx, Float dvdy) const {
|
||||
if (m_isotropic) {
|
||||
if (m_filterType == ETrilinear) {
|
||||
++mipmapLookups;
|
||||
/* Conservatively estimate a square lookup region */
|
||||
Float width = 2.0f * std::max(
|
||||
|
@ -256,7 +266,7 @@ Spectrum MIPMap::getValue(Float u, Float v,
|
|||
return triangle(level, u, v) * (1.0f - delta)
|
||||
+ triangle(level, u, v) * delta;
|
||||
}
|
||||
} else {
|
||||
} else if (m_filterType == EEWA) {
|
||||
if (dudx*dudx + dudy*dudy < dvdx*dvdx + dvdy*dvdy) {
|
||||
std::swap(dudx, dvdx);
|
||||
std::swap(dudy, dvdy);
|
||||
|
@ -278,11 +288,15 @@ Spectrum MIPMap::getValue(Float u, Float v,
|
|||
Float lod =
|
||||
std::min(std::max((Float) 0, m_levels - 1 + log2(minorLength)),
|
||||
(Float) (m_levels-1));
|
||||
int ilod = (int) std::floor(lod);
|
||||
int ilod = floorToInt(lod);
|
||||
Float d = lod - ilod;
|
||||
|
||||
return EWA(u, v, dudx, dudy, dvdx, dvdy, ilod) * (1-d) +
|
||||
EWA(u, v, dudx, dudy, dvdx, dvdy, ilod+1) * d;
|
||||
} else {
|
||||
int xPos = floorToInt(u*m_levelWidth[0]),
|
||||
yPos = floorToInt(v*m_levelHeight[0]);
|
||||
return getTexel(0, xPos, yPos);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,12 @@ void Shape::serialize(Stream *stream, InstanceManager *manager) const {
|
|||
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 {
|
||||
Log(EError, "%s::rayIntersect(): Not implemented!",
|
||||
|
|
|
@ -29,6 +29,10 @@ Texture::Texture(Stream *stream, InstanceManager *manager)
|
|||
: ConfigurableObject(stream, manager) {
|
||||
}
|
||||
|
||||
Vector3i Texture::getResolution() const {
|
||||
return Vector3i(0);
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <tt>Volume</tt> 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<VolumeDataSource> m_albedo;
|
||||
ref<VolumeDataSource> m_orientation;
|
||||
Float m_stepSize;
|
||||
AABB m_aabb;
|
||||
AABB m_densityAABB;
|
||||
bool m_directionallyVaryingCoefficients;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <mitsuba/core/chisquare.h>
|
||||
#include <mitsuba/core/frame.h>
|
||||
#include <mitsuba/render/phase.h>
|
||||
#include <mitsuba/render/medium.h>
|
||||
|
@ -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);
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; i<m_meshes.size(); ++i) {
|
||||
child->setParent(m_meshes[i]);
|
||||
for (size_t i=0; i<m_meshes.size(); ++i)
|
||||
m_meshes[i]->addChild(name, child);
|
||||
}
|
||||
} else {
|
||||
Shape::addChild(name, child);
|
||||
}
|
||||
|
|
|
@ -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() << "\"]";
|
||||
|
|
|
@ -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<Bitmap::EFileFormat>(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<MemoryStream> 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)
|
||||
|
|
Loading…
Reference in New Issue