merge
commit
4d9d668a58
|
@ -285,7 +285,7 @@ if needsBuildDependencies:
|
|||
print '\nThe dependency directory and your Mitsuba codebase have different version'
|
||||
print 'numbers! Your copy of Mitsuba has version %s, whereas the dependencies ' % MTS_VERSION
|
||||
print 'have version %s. Please bring them into sync, either by running\n' % depVersion
|
||||
print '$ hg update -r v%s\n' % depVersion
|
||||
print '$ hg update -r v%s\n' % depVersion
|
||||
print 'in the Mitsuba directory, or by running\n'
|
||||
print '$ cd dependencies'
|
||||
print '$ hg pull'
|
||||
|
@ -353,7 +353,7 @@ def configure_for_objective_cpp(env):
|
|||
env.RemoveFlags(['-fstrict-aliasing', '-ftree-vectorize',
|
||||
'-std=c\+\+0x'])
|
||||
# Remove Intel compiler-specific optimization flags
|
||||
env.RemoveFlags(['-x.*', '-ax.*', '-ipo', '-no-prec-div',
|
||||
env.RemoveFlags(['-x.*', '-ax.*', '-ipo', '-no-prec-div',
|
||||
'-fp-model', 'fast=.*', '-wd.*', '-openmp'])
|
||||
env['CCFLAGS'] += ['-fno-strict-aliasing']
|
||||
# Enforce GCC usage (Intel compiler doesn't handle Objective C/C++)
|
||||
|
@ -374,7 +374,7 @@ env.__class__.ConfigureForObjectiveCPP = configure_for_objective_cpp
|
|||
env.__class__.RelaxCompilerSettings = relax_compiler_settings
|
||||
|
||||
if hasCollada:
|
||||
env.Append(CPPDEFINES = [['MTS_HAS_COLLADA', 1]] )
|
||||
env.Append(CPPDEFINES = [['MTS_HAS_COLLADA', 1]])
|
||||
|
||||
env.SConsignFile()
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ Priority: optional
|
|||
Maintainer: Wenzel Jakob <wenzel@cs.cornell.edu>
|
||||
Build-Depends: debhelper (>= 7), build-essential, scons, qt4-dev-tools,
|
||||
libpng12-dev, libjpeg-dev, libilmbase-dev, libopenexr-dev,
|
||||
libxerces-c-dev, libboost-dev, libglewmx1.5-dev, libxxf86vm-dev,
|
||||
libxerces-c-dev, libboost-dev, libglewmx-dev, libxxf86vm-dev,
|
||||
collada-dom-dev, libboost-system-dev, libboost-filesystem-dev,
|
||||
libboost-python-dev, libboost-thread-dev, libgl1-mesa-dev,
|
||||
libglu1-mesa-dev, pkg-config, libeigen3-dev
|
||||
|
@ -24,7 +24,7 @@ Description: Mitsuba renderer
|
|||
Package: mitsuba-dev
|
||||
Architecture: any
|
||||
Depends: qt4-dev-tools, libpng12-dev, libjpeg-dev, libilmbase-dev,
|
||||
libopenexr-dev, libxerces-c-dev, libboost-dev, libglewmx1.5-dev,
|
||||
libopenexr-dev, libxerces-c-dev, libboost-dev, libglewmx-dev,
|
||||
libxxf86vm-dev, collada-dom-dev, libboost-system-dev,
|
||||
libboost-filesystem-dev, libboost-python-dev, libboost-thread-dev,
|
||||
libeigen3-dev, mitsuba
|
||||
|
|
|
@ -2,11 +2,18 @@
|
|||
\subsection{Subsurface scattering models}
|
||||
\label{sec:subsurface}
|
||||
There are two ways of simulating subsurface scattering within Mitsuba:
|
||||
participating media and subsurface scattering models. The latter are described
|
||||
in this section and can be thought of as a first-order approximation of the
|
||||
former. For this reason, subsurface scattering models should be preferred when
|
||||
visually appealing output should be generated quickly and the demands on
|
||||
physical realism are secondary.
|
||||
participating media and subsurface scattering models.
|
||||
|
||||
\begin{description}
|
||||
\item[Subsurface scattering models:] Described in this section. These can be thought
|
||||
of as a first-order approximation of what happens inside a participating medium.
|
||||
They are preferable when visually appealing output should be generated
|
||||
\emph{quickly} and the demands on accuracy are secondary.
|
||||
At the moment, there is only one subsurface scattering model (the
|
||||
\pluginref{dipole}), which is described on the next page.
|
||||
\item[Participating media:] Described in Section~\ref{sec:media}. When modeling
|
||||
subsurface scattering using a participating medium, Mitsuba performs a \emph{full}
|
||||
radiative transport simulation, which correctly accounts for all scattering events.
|
||||
This is more accurate but generally significantly slower.
|
||||
\end{description}
|
||||
|
||||
At the moment, there is only one subsurface scattering model (the
|
||||
\pluginref{dipole}), which is described on the next page.
|
||||
|
|
|
@ -403,7 +403,7 @@ public:
|
|||
void colorBalance(Float r, Float g, Float b);
|
||||
|
||||
/// Draw a filled rectangle with the specified position and size
|
||||
void fill(const Point2i &offset, const Vector2i &size, const Spectrum &value);
|
||||
void fillRect(Point2i offset, Vector2i size, const Spectrum &value);
|
||||
|
||||
/// Bitmap equality operator (useful for unit-tests etc.)
|
||||
bool operator==(const Bitmap &bitmap) const;
|
||||
|
@ -699,7 +699,25 @@ public:
|
|||
* use different component formats or channels, or when the
|
||||
* component format is \ref EBitmask.
|
||||
*/
|
||||
void accumulate(const Bitmap *bitmap, const Point2i &offset);
|
||||
void accumulate(const Bitmap *bitmap, Point2i sourceOffset,
|
||||
Point2i targetOffset, Vector2i size);
|
||||
|
||||
/**
|
||||
* \brief Accumulate the contents of another bitmap into the
|
||||
* region of the specified offset
|
||||
*
|
||||
* This convenience function calls the main <tt>accumulate()</tt>
|
||||
* implementation with <tt>size</tt> set to <tt>bitmap->getSize()</tt>
|
||||
* and <tt>sourceOffset</tt> set to zero. Out-of-bounds regions are
|
||||
* ignored. It is assumed that <tt>bitmap != this</tt>.
|
||||
*
|
||||
* \remark This function throws an exception when the bitmaps
|
||||
* use different component formats or channels, or when the
|
||||
* component format is \ref EBitmask.
|
||||
*/
|
||||
inline void accumulate(const Bitmap *bitmap, Point2i targetOffset) {
|
||||
accumulate(bitmap, Point2i(0), targetOffset, bitmap->getSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Up- or down-sample this image to a different resolution
|
||||
|
|
|
@ -76,12 +76,22 @@ public:
|
|||
/// Allocate memory for a certain font
|
||||
Font(EFont font);
|
||||
|
||||
/// Draw text to the specified bitmap
|
||||
void drawText(Bitmap *dest, Point2i pos, const std::string &text) const;
|
||||
|
||||
/// Compute the size covered by the given string when rendered using this font
|
||||
Vector2i getSize(const std::string &text) const;
|
||||
|
||||
/// Upload the font to the GPU
|
||||
void init(Renderer *renderer);
|
||||
|
||||
/// Free the GPU memory
|
||||
void cleanup();
|
||||
|
||||
/// Convert the underlying bitmap to a different pixel format
|
||||
void convert(Bitmap::EPixelFormat pixelFormat,
|
||||
Bitmap::EComponentFormat componentFormat, Float gamma);
|
||||
|
||||
/// Return the name of this font
|
||||
inline const std::string &getName() const { return m_name; }
|
||||
|
||||
|
|
|
@ -74,6 +74,9 @@ public:
|
|||
/// Serialize to a binary data stream
|
||||
virtual void serialize(Stream *stream, InstanceManager *manager) const;
|
||||
|
||||
/// Return the underlying bitmap representation (if any)
|
||||
virtual ref<Bitmap> getBitmap() const;
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
Texture(const Properties &props);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <mitsuba/core/fstream.h>
|
||||
#include <mitsuba/core/bitmap.h>
|
||||
#include <mitsuba/core/statistics.h>
|
||||
#include <mitsuba/hw/font.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "banner.h"
|
||||
|
||||
|
@ -114,7 +115,33 @@ MTS_NAMESPACE_BEGIN
|
|||
* <boolean name="banner" value="false"/>
|
||||
* </film>
|
||||
* \end{xml}
|
||||
|
||||
*
|
||||
* \subsubsection*{Annotations:}
|
||||
* \label{sec:film-annotations}
|
||||
* The \pluginref{ldrfilm} and \pluginref{hdrfilm} plugins support an additional
|
||||
* feature referred to as \emph{annotations}, which can be quite useful under
|
||||
* certain circumstances.
|
||||
*
|
||||
* Annotations are used to embed useful information inside a rendered image so
|
||||
* that this information is later available to anyone viewing the image.
|
||||
* Exemplary uses of this feature might be to store the frame or take number,
|
||||
* camera parameters, or other relevant scene information.
|
||||
*
|
||||
* Annotations can either be created by means of a \emph{tag}, which is an entry
|
||||
* in the metadata table of the image file (does not modify the actual image data),
|
||||
* or a \emph{text} label which is ``burned'' into the image.
|
||||
*
|
||||
* The syntax of this looks as follows:
|
||||
*
|
||||
* \begin{xml}
|
||||
* <film type="ldrfilm">
|
||||
* <!-- Create a new metadata entry 'my_tag_name' and set it to the value 'my_tag_value' -->
|
||||
* <string name="tag('my_tag_name')" value="my_tag_value"/>
|
||||
*
|
||||
* <!-- Add the label 'Hello' at the image position X=50, Y=80 -->
|
||||
* <string name="text(50,80)" value="Hello!"/>
|
||||
* </film>
|
||||
* \end{xml}
|
||||
*/
|
||||
class HDRFilm : public Film {
|
||||
public:
|
||||
|
@ -204,6 +231,25 @@ public:
|
|||
|
||||
}
|
||||
|
||||
std::vector<std::string> keys = props.getPropertyNames();
|
||||
for (size_t i=0; i<keys.size(); ++i) {
|
||||
std::string key = boost::to_lower_copy(keys[i]);
|
||||
|
||||
if (boost::starts_with(key, "tag('") && boost::ends_with(key, "')")) {
|
||||
m_tags[keys[i].substr(5, key.length()-7)] = props.getString(keys[i]);
|
||||
} else if (boost::starts_with(key, "text(") && boost::ends_with(key, ")")) {
|
||||
std::vector<std::string> args = tokenize(key.substr(5, key.length()-6), " ,");
|
||||
|
||||
if (args.size() != 2)
|
||||
Log(EError, "Text command '%s' has an invalid number of arguments!", key.c_str());
|
||||
|
||||
Annotation annotation;
|
||||
annotation.offset = Point2i(atoi(args[0].c_str()), atoi(args[1].c_str()));
|
||||
annotation.text = props.getString(keys[i]);
|
||||
m_annotations.push_back(annotation);
|
||||
}
|
||||
}
|
||||
|
||||
m_storage = new ImageBlock(Bitmap::ESpectrumAlphaWeight, m_cropSize);
|
||||
}
|
||||
|
||||
|
@ -321,6 +367,23 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_annotations.empty()) {
|
||||
ref<Font> font = new Font(Font::EBitstreamVeraMono14);
|
||||
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), 1.0f);
|
||||
|
||||
for (size_t i=0; i<m_annotations.size(); ++i) {
|
||||
const Point2i &offset = m_annotations[i].offset;
|
||||
const std::string &text = m_annotations[i].text;
|
||||
Vector2i size = font->getSize(text);
|
||||
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
|
||||
font->drawText(bitmap, offset, text);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it = m_tags.begin();
|
||||
it != m_tags.end(); ++it)
|
||||
bitmap->getMetadata()[it->first] = it->second;
|
||||
|
||||
fs::path filename = m_destFile;
|
||||
std::string extension = boost::to_lower_copy(filename.extension().string());
|
||||
std::string properExtension = (m_fileFormat == Bitmap::EOpenEXR) ? ".exr" : ".rgbe";
|
||||
|
@ -367,6 +430,11 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
struct Annotation {
|
||||
Point2i offset;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
Bitmap::EFileFormat m_fileFormat;
|
||||
Bitmap::EPixelFormat m_pixelFormat;
|
||||
Bitmap::EComponentFormat m_componentFormat;
|
||||
|
@ -374,6 +442,9 @@ protected:
|
|||
bool m_attachLog;
|
||||
fs::path m_destFile;
|
||||
ref<ImageBlock> m_storage;
|
||||
|
||||
std::vector<Annotation> m_annotations;
|
||||
std::map<std::string, std::string> m_tags;
|
||||
};
|
||||
|
||||
MTS_IMPLEMENT_CLASS_S(HDRFilm, false, Film)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <mitsuba/core/fstream.h>
|
||||
#include <mitsuba/core/bitmap.h>
|
||||
#include <mitsuba/core/statistics.h>
|
||||
#include <mitsuba/hw/font.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "banner.h"
|
||||
|
||||
|
@ -113,6 +114,9 @@ MTS_NAMESPACE_BEGIN
|
|||
* The RGB values exported by this plugin correspond to the ITU-R Rec. BT. 709-3
|
||||
* primaries with a D65 white point. When $\texttt{gamma}$ is set to $\code{-1}$ (the default),
|
||||
* the output is in the sRGB color space and will display as intended on compatible devices.
|
||||
*
|
||||
* Note that this plugin supports render-time \emph{annotations}, which
|
||||
* are described on page~\pageref{sec:film-annotations}.
|
||||
*/
|
||||
class LDRFilm : public Film {
|
||||
public:
|
||||
|
@ -176,6 +180,25 @@ public:
|
|||
m_reinhardKey = props.getFloat("key", 0.18f);
|
||||
m_reinhardBurn = props.getFloat("burn", 0.0);
|
||||
|
||||
std::vector<std::string> keys = props.getPropertyNames();
|
||||
for (size_t i=0; i<keys.size(); ++i) {
|
||||
std::string key = boost::to_lower_copy(keys[i]);
|
||||
|
||||
if (boost::starts_with(key, "tag('") && boost::ends_with(key, "')")) {
|
||||
m_tags[keys[i].substr(5, key.length()-7)] = props.getString(keys[i]);
|
||||
} else if (boost::starts_with(key, "text(") && boost::ends_with(key, ")")) {
|
||||
std::vector<std::string> args = tokenize(key.substr(5, key.length()-6), " ,");
|
||||
|
||||
if (args.size() != 2)
|
||||
Log(EError, "Text command '%s' has an invalid number of arguments!", key.c_str());
|
||||
|
||||
Annotation annotation;
|
||||
annotation.offset = Point2i(atoi(args[0].c_str()), atoi(args[1].c_str()));
|
||||
annotation.text = props.getString(keys[i]);
|
||||
m_annotations.push_back(annotation);
|
||||
}
|
||||
}
|
||||
|
||||
m_storage = new ImageBlock(Bitmap::ESpectrumAlphaWeight, m_cropSize);
|
||||
}
|
||||
|
||||
|
@ -313,6 +336,23 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_annotations.empty()) {
|
||||
ref<Font> font = new Font(Font::EBitstreamVeraMono14);
|
||||
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), m_gamma);
|
||||
|
||||
for (size_t i=0; i<m_annotations.size(); ++i) {
|
||||
const Point2i &offset = m_annotations[i].offset;
|
||||
const std::string &text = m_annotations[i].text;
|
||||
Vector2i size = font->getSize(text);
|
||||
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
|
||||
font->drawText(bitmap, offset, text);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it = m_tags.begin();
|
||||
it != m_tags.end(); ++it)
|
||||
bitmap->getMetadata()[it->first] = it->second;
|
||||
|
||||
fs::path filename = m_destFile;
|
||||
std::string extension = boost::to_lower_copy(filename.extension().string());
|
||||
std::string expectedExtension;
|
||||
|
@ -367,6 +407,11 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
protected:
|
||||
struct Annotation {
|
||||
Point2i offset;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
Bitmap::EFileFormat m_fileFormat;
|
||||
Bitmap::EPixelFormat m_pixelFormat;
|
||||
bool m_hasBanner;
|
||||
|
@ -375,6 +420,9 @@ protected:
|
|||
ref<ImageBlock> m_storage;
|
||||
ETonemapMethod m_tonemapMethod;
|
||||
Float m_exposure, m_reinhardKey, m_reinhardBurn;
|
||||
|
||||
std::vector<Annotation> m_annotations;
|
||||
std::map<std::string, std::string> m_tags;
|
||||
};
|
||||
|
||||
MTS_IMPLEMENT_CLASS_S(LDRFilm, false, Film)
|
||||
|
|
|
@ -432,7 +432,7 @@ public:
|
|||
|
||||
bool develop(const Point2i &sourceOffset, const Vector2i &size,
|
||||
const Point2i &targetOffset, Bitmap *target) const {
|
||||
target->fill(targetOffset, size, Spectrum(0.0f));
|
||||
target->fillRect(targetOffset, size, Spectrum(0.0f));
|
||||
return false; /* Not supported by the tiled EXR film! */
|
||||
}
|
||||
|
||||
|
|
|
@ -430,47 +430,59 @@ void Bitmap::flipVertically() {
|
|||
}
|
||||
}
|
||||
|
||||
void Bitmap::accumulate(const Bitmap *bitmap, const Point2i &offset) {
|
||||
|
||||
void Bitmap::accumulate(const Bitmap *bitmap, Point2i sourceOffset,
|
||||
Point2i targetOffset, Vector2i size) {
|
||||
Assert(getPixelFormat() == bitmap->getPixelFormat() &&
|
||||
getComponentFormat() == bitmap->getComponentFormat() &&
|
||||
getChannelCount() == bitmap->getChannelCount());
|
||||
|
||||
const int
|
||||
offsetX = std::max(offset.x, 0),
|
||||
offsetY = std::max(offset.y, 0),
|
||||
endX = std::min(offset.x + bitmap->getSize().x, m_size.x),
|
||||
endY = std::min(offset.y + bitmap->getSize().y, m_size.y);
|
||||
Vector2i offsetIncrease(
|
||||
std::max(0, std::max(-sourceOffset.x, -targetOffset.x)),
|
||||
std::max(0, std::max(-sourceOffset.y, -targetOffset.y))
|
||||
);
|
||||
|
||||
if (offsetX >= endX || offsetY >= endY)
|
||||
sourceOffset += offsetIncrease;
|
||||
targetOffset += offsetIncrease;
|
||||
size -= offsetIncrease;
|
||||
|
||||
Vector2i sizeDecrease(
|
||||
std::max(0, std::max(sourceOffset.x + size.x - bitmap->getWidth(), targetOffset.x + size.x - getWidth())),
|
||||
std::max(0, std::max(sourceOffset.y + size.y - bitmap->getHeight(), targetOffset.y + size.y - getHeight())));
|
||||
|
||||
size -= sizeDecrease;
|
||||
|
||||
if (size.x <= 0 || size.y <= 0)
|
||||
return;
|
||||
|
||||
const size_t
|
||||
columns = (endX - offsetX) * m_channelCount,
|
||||
columns = size.x * m_channelCount,
|
||||
pixelStride = getBytesPerPixel(),
|
||||
sourceStride = bitmap->getSize().x * pixelStride,
|
||||
targetStride = m_size.x * pixelStride;
|
||||
sourceStride = bitmap->getWidth() * pixelStride,
|
||||
targetStride = getWidth() * pixelStride;
|
||||
|
||||
const uint8_t *source = bitmap->getUInt8Data() +
|
||||
(offsetX - offset.x + (offsetY - offset.y) * bitmap->getSize().x) * pixelStride;
|
||||
(sourceOffset.x + sourceOffset.y * (size_t) bitmap->getWidth()) * pixelStride;
|
||||
|
||||
uint8_t *target = m_data +
|
||||
(offsetX + offsetY * m_size.x) * pixelStride;
|
||||
(targetOffset.x + targetOffset.y * (size_t) m_size.x) * pixelStride;
|
||||
|
||||
for (int y = offsetY; y < endY; ++y) {
|
||||
for (int y = 0; y < size.y; ++y) {
|
||||
switch (m_componentFormat) {
|
||||
case EUInt8:
|
||||
for (size_t i = 0; i < columns; ++i)
|
||||
((uint8_t *) target)[i] += ((uint8_t *) source)[i];
|
||||
((uint8_t *) target)[i] = (uint8_t) std::min(0xFF, ((uint8_t *) source)[i] + ((uint8_t *) target)[i]);
|
||||
|
||||
break;
|
||||
|
||||
case EUInt16:
|
||||
for (size_t i = 0; i < columns; ++i)
|
||||
((uint16_t *) target)[i] += ((uint16_t *) source)[i];
|
||||
((uint16_t *) target)[i] = (uint16_t) std::min(0xFFFF, ((uint16_t *) source)[i] + ((uint16_t *) target)[i]);
|
||||
break;
|
||||
|
||||
case EUInt32:
|
||||
for (size_t i = 0; i < columns; ++i)
|
||||
((uint32_t *) target)[i] += ((uint32_t *) source)[i];
|
||||
((uint32_t *) target)[i] = std::min((uint32_t) 0xFFFFFFFFUL, ((uint32_t *) source)[i] + ((uint32_t *) target)[i]);
|
||||
break;
|
||||
|
||||
case EFloat16:
|
||||
|
@ -554,8 +566,9 @@ void Bitmap::setPixel(const Point2i &pos, const Spectrum &value) {
|
|||
}
|
||||
|
||||
void Bitmap::drawHLine(int y, int x1, int x2, const Spectrum &value) {
|
||||
AssertEx( y >= 0 && y < m_size.y &&
|
||||
x1 >= 0 && x2 < m_size.x, "Bitmap::drawVLine(): out of bounds!");
|
||||
if (y < 0 || y >= m_size.y)
|
||||
return;
|
||||
x1 = std::max(x1, 0); x2 = std::min(x2, m_size.x-1);
|
||||
|
||||
const FormatConverter *cvt = FormatConverter::getInstance(
|
||||
std::make_pair(EFloat, m_componentFormat)
|
||||
|
@ -574,8 +587,9 @@ void Bitmap::drawHLine(int y, int x1, int x2, const Spectrum &value) {
|
|||
}
|
||||
|
||||
void Bitmap::drawVLine(int x, int y1, int y2, const Spectrum &value) {
|
||||
AssertEx( x >= 0 && x < m_size.x &&
|
||||
y1 >= 0 && y2 < m_size.y, "Bitmap::drawVLine(): out of bounds!");
|
||||
if (x < 0 || x >= m_size.x)
|
||||
return;
|
||||
y1 = std::max(y1, 0); y2 = std::min(y2, m_size.y-1);
|
||||
|
||||
const FormatConverter *cvt = FormatConverter::getInstance(
|
||||
std::make_pair(EFloat, m_componentFormat)
|
||||
|
@ -601,9 +615,12 @@ void Bitmap::drawRect(const Point2i &offset, const Vector2i &size, const Spectru
|
|||
drawVLine(offset.x + size.x - 1, offset.y, offset.y + size.y - 1, value);
|
||||
}
|
||||
|
||||
void Bitmap::fill(const Point2i &offset, const Vector2i &size, const Spectrum &value) {
|
||||
AssertEx(offset.x >= 0 && offset.x + size.x <= m_size.x &&
|
||||
offset.y >= 0 && offset.y + size.y <= m_size.y, "Bitmap::fill(): out of bounds!");
|
||||
void Bitmap::fillRect(Point2i offset, Vector2i size, const Spectrum &value) {
|
||||
int sx = std::max(0, -offset.x), sy = std::max(0, -offset.y);
|
||||
size.x -= sx; size.y -= sy; offset.x += sx; offset.y += sy;
|
||||
|
||||
size.x -= std::max(0, offset.x + size.x - m_size.x);
|
||||
size.y -= std::max(0, offset.y + size.y - m_size.y);
|
||||
|
||||
const FormatConverter *cvt = FormatConverter::getInstance(
|
||||
std::make_pair(EFloat, m_componentFormat)
|
||||
|
|
|
@ -74,6 +74,70 @@ Font::Font(EFont font) {
|
|||
dscStream->read(m_kerningMatrix, 256*256);
|
||||
}
|
||||
|
||||
void Font::convert(Bitmap::EPixelFormat pixelFormat, Bitmap::EComponentFormat componentFormat, Float gamma) {
|
||||
m_bitmap = m_bitmap->convert(pixelFormat, componentFormat, gamma);
|
||||
}
|
||||
|
||||
void Font::drawText(Bitmap *dest, Point2i pos, const std::string &text) const {
|
||||
int initial = pos.x;
|
||||
|
||||
for (size_t i=0; i<text.length(); i++) {
|
||||
char character = text[i];
|
||||
if (character == '\r')
|
||||
continue;
|
||||
if (character == '\n') {
|
||||
pos.x = initial;
|
||||
pos.y += (int) (getMaxVerticalBearing()*4.0/3.0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const Font::Glyph &glyph = getGlyph(character);
|
||||
|
||||
Point2i targetOffset = pos + Vector2i(
|
||||
glyph.horizontalBearing,
|
||||
getMaxVerticalBearing() - glyph.verticalBearing - 1
|
||||
);
|
||||
|
||||
Point2i sourceOffset(
|
||||
glyph.tx.x * m_bitmap->getWidth(),
|
||||
glyph.tx.y * m_bitmap->getHeight());
|
||||
|
||||
dest->accumulate(m_bitmap.get(), sourceOffset, targetOffset, glyph.size);
|
||||
|
||||
pos.x += glyph.horizontalAdvance;
|
||||
|
||||
if (i+1 < text.length())
|
||||
pos.x += getKerning(character, text[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
Vector2i Font::getSize(const std::string &text) const {
|
||||
Vector2i size(0, getMaxVerticalBearing());
|
||||
int pos = 0;
|
||||
|
||||
for (size_t i=0; i<text.length(); i++) {
|
||||
char character = text[i];
|
||||
if (character == '\r')
|
||||
continue;
|
||||
if (character == '\n') {
|
||||
size.y += getMaxVerticalBearing()*(4.0 / 3.0);
|
||||
size.x = std::max(size.x, pos);
|
||||
pos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const Font::Glyph &glyph = getGlyph(character);
|
||||
|
||||
pos += glyph.horizontalAdvance;
|
||||
|
||||
if (i+1 < text.length())
|
||||
pos += getKerning(character, text[i+1]);
|
||||
}
|
||||
size.x = std::max(size.x, pos);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void Font::init(Renderer *renderer) {
|
||||
m_texture = renderer->createGPUTexture(m_name, m_bitmap);
|
||||
m_texture->setFilterType(GPUTexture::ENearest);
|
||||
|
|
|
@ -711,6 +711,9 @@ void export_core() {
|
|||
.def("clear", &InterpolatedSpectrum::clear)
|
||||
.def("zeroExtend", &InterpolatedSpectrum::zeroExtend);
|
||||
|
||||
void (Bitmap::*accumulate_1)(const Bitmap *bitmap, Point2i sourceOffset, Point2i targetOffset, Vector2i size) = &Bitmap::accumulate;
|
||||
void (Bitmap::*accumulate_2)(const Bitmap *bitmap, Point2i targetOffset) = &Bitmap::accumulate;
|
||||
|
||||
BP_CLASS(Bitmap, Object, (bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &>()))
|
||||
.def(bp::init<Bitmap::EPixelFormat, Bitmap::EComponentFormat, const Vector2i &, int>())
|
||||
.def(bp::init<Bitmap::EFileFormat, Stream *>())
|
||||
|
@ -719,7 +722,8 @@ void export_core() {
|
|||
.def("expand", &Bitmap::expand, BP_RETURN_VALUE)
|
||||
.def("flipVertically", &Bitmap::flipVertically)
|
||||
.def("crop", &Bitmap::crop)
|
||||
.def("accumulate", &Bitmap::accumulate)
|
||||
.def("accumulate", accumulate_1)
|
||||
.def("accumulate", accumulate_2)
|
||||
.def("clear", &Bitmap::clear)
|
||||
.def("write", &bitmap_write)
|
||||
.def("setString", &Bitmap::setString)
|
||||
|
|
|
@ -47,6 +47,7 @@ Spectrum Texture::getMinimum() const { NotImplementedError("getMinimum"); }
|
|||
Spectrum Texture::getMaximum() const { NotImplementedError("getMaximum"); }
|
||||
bool Texture::isConstant() const { NotImplementedError("isConstant"); }
|
||||
bool Texture::usesRayDifferentials() const { NotImplementedError("usesRayDifferentials"); }
|
||||
ref<Bitmap> Texture::getBitmap() const { return NULL; }
|
||||
|
||||
ref<Texture> Texture::expand() {
|
||||
return this;
|
||||
|
|
|
@ -208,9 +208,9 @@ static int irrOctreeIndex = 0;
|
|||
* rendered using diffusion theory and radiative transport, respectively.
|
||||
* The former produces an incorrect result, since the assumption of
|
||||
* many scattering events breaks down.
|
||||
* \textbf{(c)}: When the number of irradiance samples is too low, the
|
||||
* resulting noise becomes visible as ``blotchy'' artifacts in the
|
||||
* rendering.}
|
||||
* \textbf{(c)}: When the number of irradiance samples is too low when rendering
|
||||
* with the dipole model, the resulting noise becomes visible as ``blotchy'' artifacts
|
||||
* in the rendering.}
|
||||
* }
|
||||
*
|
||||
* \subsubsection*{Typical material setup}
|
||||
|
|
|
@ -400,6 +400,10 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
ref<Bitmap> getBitmap() const {
|
||||
return m_mipmap1.get() ? m_mipmap1->toBitmap() : m_mipmap3->toBitmap();
|
||||
}
|
||||
|
||||
Spectrum eval(const Point2 &uv, const Vector2 &d0, const Vector2 &d1) const {
|
||||
stats::filteredLookups.incrementBase();
|
||||
++stats::filteredLookups;
|
||||
|
|
|
@ -93,7 +93,7 @@ MTS_NAMESPACE_BEGIN
|
|||
*
|
||||
* When using this data source to represent floating point density volumes,
|
||||
* please ensure that the values are all normalized to lie in the
|
||||
* range $[0, 1]$---otherwise, the Woocock-Tracking integration method in
|
||||
* range $[0, 1]$---otherwise, the Woodcock-Tracking integration method in
|
||||
* \pluginref{heterogeneous} will produce incorrect results.
|
||||
*/
|
||||
class GridDataSource : public VolumeDataSource {
|
||||
|
|
Loading…
Reference in New Issue