got rid of exrtexture, renamed ldrtexture to bitmap and extended it to handle EXRs.

metadata
Wenzel Jakob 2011-07-03 17:10:12 +02:00
parent 38a908306e
commit c4eaf13ec8
11 changed files with 176 additions and 235 deletions

View File

@ -10,12 +10,16 @@ An simple scene with a single mesh and the default lighting and camera setup mig
something like this:
\begin{xml}
<?xml version="1.0" encoding="utf-8"?>
<scene>
<scene version=$\MtsVer$>
<shape type="obj">
<string name="filename" value="dragon.obj"/>
</shape>
</scene>
\end{xml}
The scene version attribute denotes the release of Mitsuba that was used to
create the scene. This information allows Mitsuba to always correctly process the
file irregardless of any potential future changes in the scene description language.
This example already contains the most important things to know about format: you can have
\emph{objects} (such as the objects instantiated by the \code{scene} or \code{shape} tags), which are allowed to be nested within
each other. Each object optionally accepts \emph{properties} (such as the \code{string} tag),
@ -29,7 +33,7 @@ the certainly case for the plugin named \code{obj} (it contains a WaveFront OBJ
Similarly, you could write
\begin{xml}
<?xml version="1.0" encoding="utf-8"?>
<scene>
<scene version=$\MtsVer$>
<shape type="sphere">
<float name="radius" value="10"/>
</shape>
@ -43,7 +47,7 @@ The most common scene setup is to declare an integrator, some geometry, a camera
and one or more luminaires. Here is a more complex example:
\begin{xml}
<?xml version="1.0" encoding="utf-8"?>
<scene>
<scene version=$\MtsVer$>
<integrator type="path"> <!-- Path trace an 8-bounce GI solution -->
<integer name="maxDepth" value="8"/>
</integrator>
@ -202,8 +206,8 @@ Quite often, you will find yourself using an object (such as a material) in many
to declare it over and over again, which wastes memory, you can make use of references. Here is an example
of how this works:
\begin{xml}
<scene>
<texture type="ldrtexture" id="myImage">
<scene version=$\MtsVer$>
<texture type="bitmap" id="myImage">
<string name="filename" value="textures/myImage.jpg"/>
</texture>

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

View File

@ -44,13 +44,14 @@
\newcommand{\renderings}[1]{
\begin{figure}[h!]
\setcounter{subfigure}{0}
\centering
\hfill
#1
\end{figure}
}
\newcommand{\rendering}[2]{\subfigure[#1]{\fbox{\includegraphics[width=0.4\textwidth]{images/#2}}}\hfill}
\newcommand{\rendering}[2]{\subfigure[#1]{\fbox{\includegraphics[width=0.47\textwidth]{images/#2}}}\hfill}
\newcommand{\medrendering}[2]{ \subfigure[#1]{\fbox{\includegraphics[width=0.3\textwidth]{images/#2}}}\hfill}
\newcommand{\smallrendering}[2]{ \subfigure[#1]{\fbox{\includegraphics[width=0.2\textwidth]{images/#2}}}\hfill}

View File

@ -73,7 +73,7 @@ either be performed by nesting BSDFs within shapes, or they can
be named and then later referenced by their name.
The following fragment shows an example of both kinds of usages:
\begin{xml}
<scene>
<scene version=$\MtsVer$>
<!-- Creating a named BSDF for later use -->
<bsdf type=".. BSDF type .." id="myNamedMaterial">
<!-- BSDF parameters go here -->

View File

@ -53,7 +53,7 @@ MTS_NAMESPACE_BEGIN
* \end{xml}
* \begin{xml}[caption=Lambertian material with a texture map, label=lst:lambertian-textured]
* <bsdf type="lambertian">
* <texture type="ldrtexture" name="reflectance">
* <texture type="bitmap" name="reflectance">
* <string name="filename" value="wood.jpg"/>
* </texture>
* </bsdf>

View File

@ -57,7 +57,7 @@ MTS_NAMESPACE_BEGIN
*
* \begin{xml}[caption=Lambertian material with a texture map, label=lst:lambertian-textured]
* <bsdf type="lambertian">
* <texture type="ldrtexture" name="reflectance">
* <texture type="bitmap" name="reflectance">
* <string name="filename" value="wood.jpg"/>
* </texture>
* </bsdf>

View File

@ -30,7 +30,7 @@ MTS_NAMESPACE_BEGIN
* used to model the surface roughness.
* \begin{enumerate}[(i)]
* \item \code{beckmann}: Physically-based distribution derived from
* Gaussian random surfaces. This is the default choice.
* Gaussian random surfaces. This is the default.
* \item \code{phong}: Classical $\cos^p\theta$ distribution.
* The Phong exponent $p$ is obtained using a transformation that
* produces roughness similar to a Beckmann distribution of the same
@ -55,35 +55,62 @@ MTS_NAMESPACE_BEGIN
* \parameter{extIOR}{\Float}{Exterior index of refraction \default{1.0}}
* \parameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
* factor used to modulate the reflectance component\default{1.0}}
* \parameter{specular\showbreak Transmittance}{\Spectrum\Or\Texture}{Optional
* \lastparameter{specular\showbreak Transmittance}{\Spectrum\Or\Texture}{Optional
* factor used to modulate the transmittance component\default{1.0}}
* }
*
* \renderings{
* \medrendering{Beckmann, $\alpha$=0.2}{bsdf_dielectric_glass}
* \medrendering{Beckmann, $\alpha$=0.3}{bsdf_dielectric_glass}
* \medrendering{Beckmann, $\alpha$=0.4}{bsdf_dielectric_glass}
* }
*
* This plugin implements a realistic microfacet scattering model for rendering
* rough interfaces between dielectric materials, such as a transition from air to ground glass.
* Microfacet theory describes surfaces as an arrangement of unresolved and ideally specular
* facets, whose normals are given by a specially chosen \emph{microfacet
* distribution}. By accounting for shadowing and masking effects between
* these facets, it is possible to reproduce the off-specular reflections
* peaks observed in real-world measurements of such materials.
* rough interfaces between dielectric materials, such as a transition from air to
* ground glass. Microfacet theory describes rough surfaces as an arrangement of
* unresolved and ideally specular facets, whose normal directions are given by
* a specially chosen \emph{microfacet distribution}. By accounting for shadowing
* and masking effects between these facets, it is possible to reproduce the
* off-specular reflections peaks observed in real-world measurements of such
* materials.
* \renderings{
* \rendering{Rough glass (Beckmann, $\alpha$=0.1)}{bsdf_roughdielectric_beckmann_0_1.jpg}
* \rendering{Ground glass (GGX, $\alpha$=0.304, \lstref{roughdielectric-roughglass})}{bsdf_roughdielectric_ggx_0_304.jpg}
* }
*
* This plugin is essentially the ``roughened'' equivalent of the plugin
* \pluginref{dielectric}. Its implementation is based on the paper
* ``Microfacet Models for Refraction through Rough Surfaces''
* \cite{Walter07Microfacet}. The model supports several types of microfacet
* distributions and a texturable roughness. The default settings are set
* \pluginref{dielectric}. As the roughness value is decreased, it increasingly
* approximates that model. Its implementation is based on the paper
* ``Microfacet Models for Refraction through Rough Surfaces'' by Walter et
* al. \cite{Walter07Microfacet}. The model supports several types of microfacet
* distributions and has a texturable roughness parameter.
* The default settings are set
* to a borosilicate glass BK7/air interface with a light amount of rougness
* modeled using a Beckmann distribution.
*
* When using this plugin, it is crucial that the scene contains
* meaningful and mutally compatible index of refraction change -- see
* \figref{glass-explanation} for an example.
* meaningful and mutally compatible index of refraction change---see
* \figref{glass-explanation} for an example. Also, please note that
* the importance sampling implementation of this model is close, but
* not perfect a perfect match to the underlying scattering distribution,
* particularly for high roughness values and when the \texttt{GGX}
* model is used. Hence, such renderings may converge slowly.
*
* \begin{xml}[caption=Ground glass, label=lst:roughdielectric-roughglass]
* <bsdf type="roughdielectric">
* <string name="distribution" value="ggx"/>
* <float name="alpha" value="0.304"/>
* <float name="intIOR" value="1.5046"/>
* <float name="extIOR" value="1.0"/>
* </bsdf>
* \end{xml}
*
* \begin{xml}[caption=Textured rougness, label=lst:roughdielectric-textured]
* <bsdf type="roughdielectric">
* <string name="distribution" value="beckmann"/>
* <float name="intIOR" value="1.5046"/>
* <float name="extIOR" value="1.0"/>
*
* <texture type="bitmap" name="alpha">
* <string name="filename" value="roughness.exr"/>
* </texture>
* </bsdf>
* \end{xml}
*/
class RoughDielectric : public BSDF {
public:
@ -384,7 +411,8 @@ public:
}
/* Evaluate the roughness */
const Float alpha = m_alpha->getValue(bRec.its).average();
const Float alpha =
std::max(m_alpha->getValue(bRec.its).average(), (Float) 1e-4f);
/* Microsurface normal distribution */
const Float D = evalD(H, alpha);
@ -467,7 +495,8 @@ public:
}
/* Evaluate the roughness */
Float alpha = m_alpha->getValue(bRec.its).average();
Float alpha =
std::max(m_alpha->getValue(bRec.its).average(), (Float) 1e-4f);
/* Suggestion by Bruce Walter: sample using a slightly different
value of alpha. This in practice limits the weights to
@ -549,7 +578,8 @@ public:
}
/* Evaluate the roughness */
Float alpha = m_alpha->getValue(bRec.its).average();
Float alpha =
std::max(m_alpha->getValue(bRec.its).average(), (Float) 1e-4f);
/* Suggestion by Bruce Walter: sample using a slightly different
value of alpha. This in practice limits the weights to
@ -671,7 +701,8 @@ public:
}
/* Evaluate the roughness */
Float alpha = m_alpha->getValue(bRec.its).average();
Float alpha =
std::max(m_alpha->getValue(bRec.its).average(), (Float) 1e-4f);
/* Suggestion by Bruce Walter: sample using a slightly different
value of alpha. This in practice limits the weights to

View File

@ -1,7 +1,6 @@
Import('env', 'plugins')
plugins += env.SharedLibrary('exrtexture', ['exrtexture.cpp'])
plugins += env.SharedLibrary('ldrtexture', ['ldrtexture.cpp'])
plugins += env.SharedLibrary('bitmap', ['bitmap.cpp'])
plugins += env.SharedLibrary('gridtexture', ['gridtexture.cpp'])
plugins += env.SharedLibrary('checkerboard', ['checkerboard.cpp'])
plugins += env.SharedLibrary('vertexcolors', ['vertexcolors.cpp'])

View File

@ -31,14 +31,17 @@
MTS_NAMESPACE_BEGIN
/**
* Gamma-corrected bitmap texture using the JPG, PNG, TGA or BMP
* Gamma-corrected bitmap texture using the EXR, JPG, PNG, TGA or BMP
* file formats.
*/
class LDRTexture : public Texture2D {
class BitmapTexture : public Texture2D {
public:
LDRTexture(const Properties &props) : Texture2D(props) {
BitmapTexture(const Properties &props) : Texture2D(props) {
m_filename = Thread::getThread()->getFileResolver()->resolve(
props.getString("filename"));
m_gamma = props.getFloat("gamma", -1); /* -1 means sRGB */
/* -1 means sRGB. Gamma is ignored when loading EXR files */
m_gamma = props.getFloat("gamma", -1);
Log(EInfo, "Loading texture \"%s\"", m_filename.leaf().c_str());
ref<FileStream> fs = new FileStream(m_filename, FileStream::EReadOnly);
@ -71,7 +74,9 @@ public:
m_maxAnisotropy = props.getFloat("maxAnisotropy", 8);
if (extension == ".jpg" || extension == ".jpeg")
if (extension == ".exr")
m_format = Bitmap::EEXR;
else if (extension == ".jpg" || extension == ".jpeg")
m_format = Bitmap::EJPEG;
else if (extension == ".png")
m_format = Bitmap::EPNG;
@ -86,7 +91,7 @@ public:
initializeFrom(bitmap);
}
LDRTexture(Stream *stream, InstanceManager *manager)
BitmapTexture(Stream *stream, InstanceManager *manager)
: Texture2D(stream, manager) {
m_filename = stream->readString();
Log(EInfo, "Unserializing texture \"%s\"", m_filename.leaf().c_str());
@ -121,7 +126,13 @@ public:
}
void initializeFrom(Bitmap *bitmap) {
ref<Bitmap> corrected = new Bitmap(bitmap->getWidth(), bitmap->getHeight(), 128);
ref<Bitmap> corrected;
m_bpp = bitmap->getBitsPerPixel();
if (bitmap->getBitsPerPixel() == 128) {
/* Nothing needs to be done */
corrected = bitmap;
} else {
corrected = new Bitmap(bitmap->getWidth(), bitmap->getHeight(), 128);
float tbl[256];
if (m_gamma == -1) {
@ -200,6 +211,7 @@ public:
} else {
Log(EError, "%i bpp images are currently not supported!", bitmap->getBitsPerPixel());
}
}
m_mipmap = MIPMap::fromBitmap(corrected, m_filterType,
m_wrapMode, m_maxAnisotropy);
@ -258,10 +270,16 @@ public:
std::string toString() const {
std::ostringstream oss;
oss << "LDRTexture[" << endl
oss << "BitmapTexture[" << endl
<< " filename = \"" << m_filename << "\"," << endl
<< " gamma = " << m_gamma << endl
<< "]";
<< " bpp = " << m_bpp;
if (m_bpp < 128) {
oss << "," << endl
<< " gamma = " << m_gamma << endl;
} else {
oss << endl;
}
oss << "]";
return oss.str();
}
@ -278,13 +296,14 @@ protected:
Float m_gamma;
MIPMap::EWrapMode m_wrapMode;
Float m_maxAnisotropy;
int m_bpp;
};
// ================ Hardware shader implementation ================
class LDRTextureShader : public Shader {
class BitmapTextureShader : public Shader {
public:
LDRTextureShader(Renderer *renderer, std::string filename, ref<Bitmap> bitmap,
BitmapTextureShader(Renderer *renderer, std::string filename, ref<Bitmap> bitmap,
const Point2 &uvOffset, const Vector2 &uvScale, MIPMap::EWrapMode wrapMode,
Float maxAnisotropy)
: Shader(renderer, ETextureShader), m_uvOffset(uvOffset), m_uvScale(uvScale) {
@ -342,14 +361,14 @@ private:
Vector2 m_uvScale;
};
Shader *LDRTexture::createShader(Renderer *renderer) const {
return new LDRTextureShader(renderer, m_filename.leaf(),
Shader *BitmapTexture::createShader(Renderer *renderer) const {
return new BitmapTextureShader(renderer, m_filename.leaf(),
m_mipmap->getLDRBitmap(), m_uvOffset, m_uvScale,
m_wrapMode, (m_filterType == MIPMap::EEWA)
? m_maxAnisotropy : 1.0f);
}
MTS_IMPLEMENT_CLASS_S(LDRTexture, false, Texture2D)
MTS_IMPLEMENT_CLASS(LDRTextureShader, false, Shader)
MTS_EXPORT_PLUGIN(LDRTexture, "LDR texture (JPG/PNG/TGA/BMP)");
MTS_IMPLEMENT_CLASS_S(BitmapTexture, false, Texture2D)
MTS_IMPLEMENT_CLASS(BitmapTextureShader, false, Shader)
MTS_EXPORT_PLUGIN(BitmapTexture, "Bitmap texture (EXR/JPG/PNG/TGA/BMP)");
MTS_NAMESPACE_END

View File

@ -1,113 +0,0 @@
/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2011 by Wenzel Jakob and others.
Mitsuba is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Mitsuba is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/core/bitmap.h>
#include <mitsuba/core/mstream.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/properties.h>
#include <mitsuba/render/texture.h>
#include <mitsuba/render/mipmap.h>
MTS_NAMESPACE_BEGIN
/**
* Simple linear (i.e. not gamma corrected) bitmap texture
* using the EXR file format
*/
class EXRTexture : public Texture2D {
public:
EXRTexture(const Properties &props) : Texture2D(props) {
m_filename = Thread::getThread()->getFileResolver()->resolve(
props.getString("filename"));
Log(EInfo, "Loading texture \"%s\"", m_filename.leaf().c_str());
ref<FileStream> fs = new FileStream(m_filename, FileStream::EReadOnly);
ref<Bitmap> bitmap = new Bitmap(Bitmap::EEXR, fs);
m_mipmap = MIPMap::fromBitmap(bitmap);
m_average = m_mipmap->triangle(m_mipmap->getLevels()-1, 0, 0);
m_maximum = m_mipmap->getMaximum();
}
EXRTexture(Stream *stream, InstanceManager *manager)
: Texture2D(stream, manager) {
m_filename = stream->readString();
Log(EInfo, "Unserializing texture \"%s\"", m_filename.leaf().c_str());
size_t size = stream->readSize();
ref<MemoryStream> mStream = new MemoryStream(size);
stream->copyTo(mStream, size);
mStream->setPos(0);
ref<Bitmap> bitmap = new Bitmap(Bitmap::EEXR, mStream);
m_mipmap = MIPMap::fromBitmap(bitmap);
m_average = m_mipmap->triangle(m_mipmap->getLevels()-1, 0, 0);
m_maximum = m_mipmap->getMaximum();
}
void serialize(Stream *stream, InstanceManager *manager) const {
Texture2D::serialize(stream, manager);
stream->writeString(m_filename.file_string());
ref<Stream> is = new FileStream(m_filename, FileStream::EReadOnly);
stream->writeSize(is->getSize());
is->copyTo(stream);
}
Spectrum getValue(const Point2 &uv) const {
return m_mipmap->triangle(0, uv.x, uv.y);
}
Spectrum getValue(const Point2 &uv, Float dudx,
Float dudy, Float dvdx, Float dvdy) const {
return m_mipmap->getValue(uv.x, uv.y, dudx, dudy, dvdx, dvdy);
}
Spectrum getMaximum() const {
return m_maximum;
}
Spectrum getAverage() const {
return m_average;
}
bool usesRayDifferentials() const {
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() << "\"]";
return oss.str();
}
MTS_DECLARE_CLASS()
protected:
ref<MIPMap> m_mipmap;
fs::path m_filename;
Spectrum m_average, m_maximum;
};
MTS_IMPLEMENT_CLASS_S(EXRTexture, false, Texture2D)
MTS_EXPORT_PLUGIN(EXRTexture, "HDR texture (EXR)");
MTS_NAMESPACE_END