got rid of exrtexture, renamed ldrtexture to bitmap and extended it to handle EXRs.
parent
38a908306e
commit
c4eaf13ec8
|
@ -10,12 +10,16 @@ An simple scene with a single mesh and the default lighting and camera setup mig
|
||||||
something like this:
|
something like this:
|
||||||
\begin{xml}
|
\begin{xml}
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<scene>
|
<scene version=$\MtsVer$>
|
||||||
<shape type="obj">
|
<shape type="obj">
|
||||||
<string name="filename" value="dragon.obj"/>
|
<string name="filename" value="dragon.obj"/>
|
||||||
</shape>
|
</shape>
|
||||||
</scene>
|
</scene>
|
||||||
\end{xml}
|
\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
|
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
|
\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),
|
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
|
Similarly, you could write
|
||||||
\begin{xml}
|
\begin{xml}
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<scene>
|
<scene version=$\MtsVer$>
|
||||||
<shape type="sphere">
|
<shape type="sphere">
|
||||||
<float name="radius" value="10"/>
|
<float name="radius" value="10"/>
|
||||||
</shape>
|
</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:
|
and one or more luminaires. Here is a more complex example:
|
||||||
\begin{xml}
|
\begin{xml}
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<scene>
|
<scene version=$\MtsVer$>
|
||||||
<integrator type="path"> <!-- Path trace an 8-bounce GI solution -->
|
<integrator type="path"> <!-- Path trace an 8-bounce GI solution -->
|
||||||
<integer name="maxDepth" value="8"/>
|
<integer name="maxDepth" value="8"/>
|
||||||
</integrator>
|
</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
|
to declare it over and over again, which wastes memory, you can make use of references. Here is an example
|
||||||
of how this works:
|
of how this works:
|
||||||
\begin{xml}
|
\begin{xml}
|
||||||
<scene>
|
<scene version=$\MtsVer$>
|
||||||
<texture type="ldrtexture" id="myImage">
|
<texture type="bitmap" id="myImage">
|
||||||
<string name="filename" value="textures/myImage.jpg"/>
|
<string name="filename" value="textures/myImage.jpg"/>
|
||||||
</texture>
|
</texture>
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 146 KiB |
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
|
@ -44,13 +44,14 @@
|
||||||
|
|
||||||
\newcommand{\renderings}[1]{
|
\newcommand{\renderings}[1]{
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
\centering
|
\centering
|
||||||
\hfill
|
\hfill
|
||||||
#1
|
#1
|
||||||
\end{figure}
|
\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{\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}
|
\newcommand{\smallrendering}[2]{ \subfigure[#1]{\fbox{\includegraphics[width=0.2\textwidth]{images/#2}}}\hfill}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ either be performed by nesting BSDFs within shapes, or they can
|
||||||
be named and then later referenced by their name.
|
be named and then later referenced by their name.
|
||||||
The following fragment shows an example of both kinds of usages:
|
The following fragment shows an example of both kinds of usages:
|
||||||
\begin{xml}
|
\begin{xml}
|
||||||
<scene>
|
<scene version=$\MtsVer$>
|
||||||
<!-- Creating a named BSDF for later use -->
|
<!-- Creating a named BSDF for later use -->
|
||||||
<bsdf type=".. BSDF type .." id="myNamedMaterial">
|
<bsdf type=".. BSDF type .." id="myNamedMaterial">
|
||||||
<!-- BSDF parameters go here -->
|
<!-- BSDF parameters go here -->
|
||||||
|
|
|
@ -53,8 +53,8 @@ MTS_NAMESPACE_BEGIN
|
||||||
* \end{xml}
|
* \end{xml}
|
||||||
* \begin{xml}[caption=Lambertian material with a texture map, label=lst:lambertian-textured]
|
* \begin{xml}[caption=Lambertian material with a texture map, label=lst:lambertian-textured]
|
||||||
* <bsdf type="lambertian">
|
* <bsdf type="lambertian">
|
||||||
* <texture type="ldrtexture" name="reflectance">
|
* <texture type="bitmap" name="reflectance">
|
||||||
* <string name="filename" value="wood.jpg"/>
|
* <string name="filename" value="wood.jpg"/>
|
||||||
* </texture>
|
* </texture>
|
||||||
* </bsdf>
|
* </bsdf>
|
||||||
* \end{xml}
|
* \end{xml}
|
||||||
|
|
|
@ -57,8 +57,8 @@ MTS_NAMESPACE_BEGIN
|
||||||
*
|
*
|
||||||
* \begin{xml}[caption=Lambertian material with a texture map, label=lst:lambertian-textured]
|
* \begin{xml}[caption=Lambertian material with a texture map, label=lst:lambertian-textured]
|
||||||
* <bsdf type="lambertian">
|
* <bsdf type="lambertian">
|
||||||
* <texture type="ldrtexture" name="reflectance">
|
* <texture type="bitmap" name="reflectance">
|
||||||
* <string name="filename" value="wood.jpg"/>
|
* <string name="filename" value="wood.jpg"/>
|
||||||
* </texture>
|
* </texture>
|
||||||
* </bsdf>
|
* </bsdf>
|
||||||
* \end{xml}
|
* \end{xml}
|
||||||
|
|
|
@ -30,7 +30,7 @@ MTS_NAMESPACE_BEGIN
|
||||||
* used to model the surface roughness.
|
* used to model the surface roughness.
|
||||||
* \begin{enumerate}[(i)]
|
* \begin{enumerate}[(i)]
|
||||||
* \item \code{beckmann}: Physically-based distribution derived from
|
* \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.
|
* \item \code{phong}: Classical $\cos^p\theta$ distribution.
|
||||||
* The Phong exponent $p$ is obtained using a transformation that
|
* The Phong exponent $p$ is obtained using a transformation that
|
||||||
* produces roughness similar to a Beckmann distribution of the same
|
* 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{extIOR}{\Float}{Exterior index of refraction \default{1.0}}
|
||||||
* \parameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
|
* \parameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
|
||||||
* factor used to modulate the reflectance component\default{1.0}}
|
* 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}}
|
* 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
|
* This plugin implements a realistic microfacet scattering model for rendering
|
||||||
* rough interfaces between dielectric materials, such as a transition from air to ground glass.
|
* rough interfaces between dielectric materials, such as a transition from air to
|
||||||
* Microfacet theory describes surfaces as an arrangement of unresolved and ideally specular
|
* ground glass. Microfacet theory describes rough surfaces as an arrangement of
|
||||||
* facets, whose normals are given by a specially chosen \emph{microfacet
|
* unresolved and ideally specular facets, whose normal directions are given by
|
||||||
* distribution}. By accounting for shadowing and masking effects between
|
* a specially chosen \emph{microfacet distribution}. By accounting for shadowing
|
||||||
* these facets, it is possible to reproduce the off-specular reflections
|
* and masking effects between these facets, it is possible to reproduce the
|
||||||
* peaks observed in real-world measurements of such materials.
|
* 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
|
* This plugin is essentially the ``roughened'' equivalent of the plugin
|
||||||
* \pluginref{dielectric}. Its implementation is based on the paper
|
* \pluginref{dielectric}. As the roughness value is decreased, it increasingly
|
||||||
* ``Microfacet Models for Refraction through Rough Surfaces''
|
* approximates that model. Its implementation is based on the paper
|
||||||
* \cite{Walter07Microfacet}. The model supports several types of microfacet
|
* ``Microfacet Models for Refraction through Rough Surfaces'' by Walter et
|
||||||
* distributions and a texturable roughness. The default settings are set
|
* 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
|
* to a borosilicate glass BK7/air interface with a light amount of rougness
|
||||||
* modeled using a Beckmann distribution.
|
* modeled using a Beckmann distribution.
|
||||||
*
|
*
|
||||||
* When using this plugin, it is crucial that the scene contains
|
* When using this plugin, it is crucial that the scene contains
|
||||||
* meaningful and mutally compatible index of refraction change -- see
|
* meaningful and mutally compatible index of refraction change---see
|
||||||
* \figref{glass-explanation} for an example.
|
* \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 {
|
class RoughDielectric : public BSDF {
|
||||||
public:
|
public:
|
||||||
|
@ -384,7 +411,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the roughness */
|
/* 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 */
|
/* Microsurface normal distribution */
|
||||||
const Float D = evalD(H, alpha);
|
const Float D = evalD(H, alpha);
|
||||||
|
@ -467,7 +495,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the roughness */
|
/* 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
|
/* Suggestion by Bruce Walter: sample using a slightly different
|
||||||
value of alpha. This in practice limits the weights to
|
value of alpha. This in practice limits the weights to
|
||||||
|
@ -549,7 +578,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the roughness */
|
/* 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
|
/* Suggestion by Bruce Walter: sample using a slightly different
|
||||||
value of alpha. This in practice limits the weights to
|
value of alpha. This in practice limits the weights to
|
||||||
|
@ -671,7 +701,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the roughness */
|
/* 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
|
/* Suggestion by Bruce Walter: sample using a slightly different
|
||||||
value of alpha. This in practice limits the weights to
|
value of alpha. This in practice limits the weights to
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
Import('env', 'plugins')
|
Import('env', 'plugins')
|
||||||
|
|
||||||
plugins += env.SharedLibrary('exrtexture', ['exrtexture.cpp'])
|
plugins += env.SharedLibrary('bitmap', ['bitmap.cpp'])
|
||||||
plugins += env.SharedLibrary('ldrtexture', ['ldrtexture.cpp'])
|
|
||||||
plugins += env.SharedLibrary('gridtexture', ['gridtexture.cpp'])
|
plugins += env.SharedLibrary('gridtexture', ['gridtexture.cpp'])
|
||||||
plugins += env.SharedLibrary('checkerboard', ['checkerboard.cpp'])
|
plugins += env.SharedLibrary('checkerboard', ['checkerboard.cpp'])
|
||||||
plugins += env.SharedLibrary('vertexcolors', ['vertexcolors.cpp'])
|
plugins += env.SharedLibrary('vertexcolors', ['vertexcolors.cpp'])
|
||||||
|
|
|
@ -31,14 +31,17 @@
|
||||||
MTS_NAMESPACE_BEGIN
|
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:
|
public:
|
||||||
LDRTexture(const Properties &props) : Texture2D(props) {
|
BitmapTexture(const Properties &props) : Texture2D(props) {
|
||||||
m_filename = Thread::getThread()->getFileResolver()->resolve(
|
m_filename = Thread::getThread()->getFileResolver()->resolve(
|
||||||
props.getString("filename"));
|
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());
|
Log(EInfo, "Loading texture \"%s\"", m_filename.leaf().c_str());
|
||||||
|
|
||||||
ref<FileStream> fs = new FileStream(m_filename, FileStream::EReadOnly);
|
ref<FileStream> fs = new FileStream(m_filename, FileStream::EReadOnly);
|
||||||
|
@ -71,7 +74,9 @@ public:
|
||||||
|
|
||||||
m_maxAnisotropy = props.getFloat("maxAnisotropy", 8);
|
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;
|
m_format = Bitmap::EJPEG;
|
||||||
else if (extension == ".png")
|
else if (extension == ".png")
|
||||||
m_format = Bitmap::EPNG;
|
m_format = Bitmap::EPNG;
|
||||||
|
@ -86,7 +91,7 @@ public:
|
||||||
initializeFrom(bitmap);
|
initializeFrom(bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
LDRTexture(Stream *stream, InstanceManager *manager)
|
BitmapTexture(Stream *stream, InstanceManager *manager)
|
||||||
: Texture2D(stream, manager) {
|
: Texture2D(stream, manager) {
|
||||||
m_filename = stream->readString();
|
m_filename = stream->readString();
|
||||||
Log(EInfo, "Unserializing texture \"%s\"", m_filename.leaf().c_str());
|
Log(EInfo, "Unserializing texture \"%s\"", m_filename.leaf().c_str());
|
||||||
|
@ -121,84 +126,91 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeFrom(Bitmap *bitmap) {
|
void initializeFrom(Bitmap *bitmap) {
|
||||||
ref<Bitmap> corrected = new Bitmap(bitmap->getWidth(), bitmap->getHeight(), 128);
|
ref<Bitmap> corrected;
|
||||||
|
m_bpp = bitmap->getBitsPerPixel();
|
||||||
float tbl[256];
|
if (bitmap->getBitsPerPixel() == 128) {
|
||||||
if (m_gamma == -1) {
|
/* Nothing needs to be done */
|
||||||
for (int i=0; i<256; ++i)
|
corrected = bitmap;
|
||||||
tbl[i] = fromSRGBComponent((Float) i / (Float) 255);
|
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<256; ++i)
|
corrected = new Bitmap(bitmap->getWidth(), bitmap->getHeight(), 128);
|
||||||
tbl[i] = std::pow((Float) i / (Float) 255, m_gamma);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *data = bitmap->getData();
|
float tbl[256];
|
||||||
float *flData = corrected->getFloatData();
|
if (m_gamma == -1) {
|
||||||
if (bitmap->getBitsPerPixel() == 32) {
|
for (int i=0; i<256; ++i)
|
||||||
for (int y=0; y<bitmap->getHeight(); ++y) {
|
tbl[i] = fromSRGBComponent((Float) i / (Float) 255);
|
||||||
for (int x=0; x<bitmap->getWidth(); ++x) {
|
} else {
|
||||||
float
|
for (int i=0; i<256; ++i)
|
||||||
r = tbl[*data++],
|
tbl[i] = std::pow((Float) i / (Float) 255, m_gamma);
|
||||||
g = tbl[*data++],
|
|
||||||
b = tbl[*data++],
|
|
||||||
a = *data++ / 255.0f;
|
|
||||||
*flData++ = r;
|
|
||||||
*flData++ = g;
|
|
||||||
*flData++ = b;
|
|
||||||
*flData++ = a;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (bitmap->getBitsPerPixel() == 24) {
|
|
||||||
for (int y=0; y<bitmap->getHeight(); ++y) {
|
uint8_t *data = bitmap->getData();
|
||||||
for (int x=0; x<bitmap->getWidth(); ++x) {
|
float *flData = corrected->getFloatData();
|
||||||
float
|
if (bitmap->getBitsPerPixel() == 32) {
|
||||||
r = tbl[*data++],
|
for (int y=0; y<bitmap->getHeight(); ++y) {
|
||||||
g = tbl[*data++],
|
for (int x=0; x<bitmap->getWidth(); ++x) {
|
||||||
b = tbl[*data++];
|
float
|
||||||
*flData++ = r;
|
r = tbl[*data++],
|
||||||
*flData++ = g;
|
g = tbl[*data++],
|
||||||
*flData++ = b;
|
b = tbl[*data++],
|
||||||
*flData++ = 1.0f;
|
a = *data++ / 255.0f;
|
||||||
|
*flData++ = r;
|
||||||
|
*flData++ = g;
|
||||||
|
*flData++ = b;
|
||||||
|
*flData++ = a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (bitmap->getBitsPerPixel() == 24) {
|
||||||
} else if (bitmap->getBitsPerPixel() == 16) {
|
for (int y=0; y<bitmap->getHeight(); ++y) {
|
||||||
for (int y=0; y<bitmap->getHeight(); ++y) {
|
for (int x=0; x<bitmap->getWidth(); ++x) {
|
||||||
for (int x=0; x<bitmap->getWidth(); ++x) {
|
float
|
||||||
float col = tbl[*data++],
|
r = tbl[*data++],
|
||||||
a = *data++ / 255.0f;
|
g = tbl[*data++],
|
||||||
*flData++ = col;
|
b = tbl[*data++];
|
||||||
*flData++ = col;
|
*flData++ = r;
|
||||||
*flData++ = col;
|
*flData++ = g;
|
||||||
*flData++ = a;
|
*flData++ = b;
|
||||||
|
*flData++ = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (bitmap->getBitsPerPixel() == 16) {
|
||||||
} else if (bitmap->getBitsPerPixel() == 8) {
|
for (int y=0; y<bitmap->getHeight(); ++y) {
|
||||||
for (int y=0; y<bitmap->getHeight(); ++y) {
|
for (int x=0; x<bitmap->getWidth(); ++x) {
|
||||||
for (int x=0; x<bitmap->getWidth(); ++x) {
|
float col = tbl[*data++],
|
||||||
float col = tbl[*data++];
|
a = *data++ / 255.0f;
|
||||||
*flData++ = col;
|
*flData++ = col;
|
||||||
*flData++ = col;
|
*flData++ = col;
|
||||||
*flData++ = col;
|
*flData++ = col;
|
||||||
*flData++ = 1.0f;
|
*flData++ = a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (bitmap->getBitsPerPixel() == 8) {
|
||||||
} else if (bitmap->getBitsPerPixel() == 1) {
|
for (int y=0; y<bitmap->getHeight(); ++y) {
|
||||||
int pos = 0;
|
for (int x=0; x<bitmap->getWidth(); ++x) {
|
||||||
for (int y=0; y<bitmap->getHeight(); ++y) {
|
float col = tbl[*data++];
|
||||||
for (int x=0; x<bitmap->getWidth(); ++x) {
|
*flData++ = col;
|
||||||
int entry = pos / 8;
|
*flData++ = col;
|
||||||
int bit = pos % 8;
|
*flData++ = col;
|
||||||
int value = (data[entry] & (1 << bit)) ? 255 : 0;
|
*flData++ = 1.0f;
|
||||||
float col = tbl[value];
|
}
|
||||||
*flData++ = col;
|
|
||||||
*flData++ = col;
|
|
||||||
*flData++ = col;
|
|
||||||
*flData++ = 1.0f;
|
|
||||||
pos++;
|
|
||||||
}
|
}
|
||||||
|
} else if (bitmap->getBitsPerPixel() == 1) {
|
||||||
|
int pos = 0;
|
||||||
|
for (int y=0; y<bitmap->getHeight(); ++y) {
|
||||||
|
for (int x=0; x<bitmap->getWidth(); ++x) {
|
||||||
|
int entry = pos / 8;
|
||||||
|
int bit = pos % 8;
|
||||||
|
int value = (data[entry] & (1 << bit)) ? 255 : 0;
|
||||||
|
float col = tbl[value];
|
||||||
|
*flData++ = col;
|
||||||
|
*flData++ = col;
|
||||||
|
*flData++ = col;
|
||||||
|
*flData++ = 1.0f;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log(EError, "%i bpp images are currently not supported!", bitmap->getBitsPerPixel());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Log(EError, "%i bpp images are currently not supported!", bitmap->getBitsPerPixel());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mipmap = MIPMap::fromBitmap(corrected, m_filterType,
|
m_mipmap = MIPMap::fromBitmap(corrected, m_filterType,
|
||||||
|
@ -258,10 +270,16 @@ public:
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "LDRTexture[" << endl
|
oss << "BitmapTexture[" << endl
|
||||||
<< " filename = \"" << m_filename << "\"," << 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();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,13 +296,14 @@ protected:
|
||||||
Float m_gamma;
|
Float m_gamma;
|
||||||
MIPMap::EWrapMode m_wrapMode;
|
MIPMap::EWrapMode m_wrapMode;
|
||||||
Float m_maxAnisotropy;
|
Float m_maxAnisotropy;
|
||||||
|
int m_bpp;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ================ Hardware shader implementation ================
|
// ================ Hardware shader implementation ================
|
||||||
|
|
||||||
class LDRTextureShader : public Shader {
|
class BitmapTextureShader : public Shader {
|
||||||
public:
|
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,
|
const Point2 &uvOffset, const Vector2 &uvScale, MIPMap::EWrapMode wrapMode,
|
||||||
Float maxAnisotropy)
|
Float maxAnisotropy)
|
||||||
: Shader(renderer, ETextureShader), m_uvOffset(uvOffset), m_uvScale(uvScale) {
|
: Shader(renderer, ETextureShader), m_uvOffset(uvOffset), m_uvScale(uvScale) {
|
||||||
|
@ -342,14 +361,14 @@ private:
|
||||||
Vector2 m_uvScale;
|
Vector2 m_uvScale;
|
||||||
};
|
};
|
||||||
|
|
||||||
Shader *LDRTexture::createShader(Renderer *renderer) const {
|
Shader *BitmapTexture::createShader(Renderer *renderer) const {
|
||||||
return new LDRTextureShader(renderer, m_filename.leaf(),
|
return new BitmapTextureShader(renderer, m_filename.leaf(),
|
||||||
m_mipmap->getLDRBitmap(), m_uvOffset, m_uvScale,
|
m_mipmap->getLDRBitmap(), m_uvOffset, m_uvScale,
|
||||||
m_wrapMode, (m_filterType == MIPMap::EEWA)
|
m_wrapMode, (m_filterType == MIPMap::EEWA)
|
||||||
? m_maxAnisotropy : 1.0f);
|
? m_maxAnisotropy : 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS_S(LDRTexture, false, Texture2D)
|
MTS_IMPLEMENT_CLASS_S(BitmapTexture, false, Texture2D)
|
||||||
MTS_IMPLEMENT_CLASS(LDRTextureShader, false, Shader)
|
MTS_IMPLEMENT_CLASS(BitmapTextureShader, false, Shader)
|
||||||
MTS_EXPORT_PLUGIN(LDRTexture, "LDR texture (JPG/PNG/TGA/BMP)");
|
MTS_EXPORT_PLUGIN(BitmapTexture, "Bitmap texture (EXR/JPG/PNG/TGA/BMP)");
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
|
@ -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
|
|
Loading…
Reference in New Issue