further spectrum-related cleanups
parent
c552a79902
commit
5c8201d764
279
doc/basics.tex
279
doc/basics.tex
|
@ -11,142 +11,19 @@ A quick video tutorial on using the GUI can be found here: \url{http://vimeo.com
|
|||
\subsection{Command line interface}
|
||||
\label{sec:mitsuba}
|
||||
The \texttt{mitsuba} binary is an alternative non-interactive rendering
|
||||
frontend for command-line use and batch job operation.
|
||||
frontend for command-line usage and batch job operation.
|
||||
To get a listing of the parameters it supports, run
|
||||
the executable without parameters:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba
|
||||
\end{shell}
|
||||
\lstref{mitsuba-cli} shows the output resulting from this command. The most common
|
||||
mode of operation is to render a single scene, which is provided as a parameter, e.g.
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba path-to/my-scene.xml
|
||||
\end{shell}
|
||||
It is also possible to connect to network render nodes, which essentially lets Mitsuba parallelize
|
||||
over additional cores. To do this, pass a semicolon-separated list of machines to
|
||||
the \code{-c} parameter.
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -c machine1;machine2;... path-to/my-scene.xml
|
||||
\end{shell}
|
||||
There are two different ways in which you can access render nodes:
|
||||
\begin{itemize}
|
||||
\item\textbf{Direct}: Here, you create a direct connection to a running \code{mtssrv} instance on
|
||||
another machine (\code{mtssrv} is the Mitsuba server process). From the the performance
|
||||
standpoint, this approach should always be preferred over the SSH method described below when there is
|
||||
a choice between them. There are some disadvantages though: first, you need to manually start
|
||||
\code{mtssrv} on every machine you want to use.
|
||||
|
||||
And perhaps more importantly: the direct communication
|
||||
protocol makes no provisions for a malicious user on the remote side. It is too costly
|
||||
to constantly check the communication stream for illegal data sequences, so Mitsuba simply doesn't do it.
|
||||
The consequence of this is that you should only use the direct communication approach within
|
||||
trusted networks.
|
||||
|
||||
For direct connections, you can specify the remote port as follows:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -c machine:1234 path-to/my-scene.xml
|
||||
\end{shell}
|
||||
When none is given, Mitsuba assumes that the server uses default port 7554.
|
||||
\item \textbf{SSH}:
|
||||
This approach works as follows: The renderer creates a SSH connection
|
||||
to the remote side, where it launches a Mitsuba worker instance.
|
||||
All subsequent communication then passes through the encrypted link.
|
||||
This is completely secure but slower due to the encryption overhead.
|
||||
If you are rendering a complex scene, there is a good chance that it
|
||||
won't matter much since most time is spent doing computations rather than
|
||||
communicating
|
||||
|
||||
Such an SSH link can be created simply by using a slightly different syntax:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -c username@machine path-to/my-scene.xml
|
||||
\end{shell}
|
||||
The above line assumes that the remote home directory contains
|
||||
a Mitsuba source directory (with compiled binaries) named \code{mitsuba}.
|
||||
If that is not the case, you need to provide the path to such a directory manually, e.g:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -c username@machine:/opt/mitsuba path-to/my-scene.xml
|
||||
\end{shell}
|
||||
For the SSH connection approach to work, you \emph{must} enable passwordless
|
||||
authentication.
|
||||
Try opening a terminal window and running the command \code{ssh username@machine}
|
||||
(replace with the details of your remote connection).
|
||||
If you are asked for a password, something is not set up correctly --- please see
|
||||
\url{http://www.debian-administration.org/articles/152} for instructions.
|
||||
|
||||
On Windows, the situation is a bit more difficult since there is no suitable SSH client by
|
||||
default. To get SSH connections to work, Mitsuba requires \code{plink.exe} (from PuTTY) to
|
||||
be on the path. For passwordless authentication with a Linux/OSX-based
|
||||
server, convert your private key to PuTTY's format using \code{puttygen.exe}.
|
||||
Afterwards, start \code{pageant.exe} to load and authenticate the key. All
|
||||
of these binaries are available from the PuTTY website, and there is also
|
||||
a copy in the \code{tools/windows/bin}
|
||||
directory in the Mitsuba repository.
|
||||
|
||||
It is possible to mix the two approaches to access some machines directly and others
|
||||
over SSH.
|
||||
\end{itemize}
|
||||
When doing many network-based renders over the command line, it can become tedious to
|
||||
specify the connections every time. They can alternatively be loaded from a text file
|
||||
where each line contains a separate connection description as discussed previously:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -s servers.txt path-to/my-scene.xml
|
||||
\end{shell}
|
||||
where \code{servers.txt} e.g. contains
|
||||
\begin{shell}
|
||||
user1@machine1.domain.org:/opt/mitsuba
|
||||
machine2.domain.org
|
||||
machine3.domain.org:7346
|
||||
\end{shell}
|
||||
\subsubsection{Passing parameters}
|
||||
Any attribute in the scene XML file can be parameterized from the
|
||||
command line.
|
||||
For instance, you can render a scene several times with different reflectance values
|
||||
on a certain material by changing its description to something like
|
||||
\begin{xml}
|
||||
<bsdf type="lambertian">
|
||||
<spectrum name="reflectance" value="$\texttt{\$}$reflectance"/>
|
||||
</bsdf>
|
||||
\end{xml}
|
||||
and running Mitsuba as follows:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -Dreflectance=0.1 -o ref_0.1.exr scene.xml
|
||||
$\texttt{\$}$ mitsuba -Dreflectance=0.2 -o ref_0.2.exr scene.xml
|
||||
$\texttt{\$}$ mitsuba -Dreflectance=0.5 -o ref_0.5.exr scene.xml
|
||||
\end{shell}
|
||||
|
||||
\subsubsection{Writing partial images to disk}
|
||||
When doing lengthy command line renders on Linux or OSX, it is possible
|
||||
to send a signal to the process using
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ killall -HUP mitsuba
|
||||
\end{shell}
|
||||
This causes the renderer to write out the partially finished
|
||||
image, after which it continues rendering. This can sometimes be useful to
|
||||
check if everything is working correctly.
|
||||
|
||||
\subsubsection{Rendering an animation}
|
||||
The command line interface is ideally suited for rendering large amounts of files in batch
|
||||
operation. You can simply pass in the files using a wildcard in the filename. If you've
|
||||
already rendered a subset of the frames and you only want to complete the remainder, add the
|
||||
\texttt{-x} flag, and all files with existing output will be skipped. You can also
|
||||
let the scheduler work on several scenes at once using the \texttt{-j} parameter --- this is
|
||||
especially useful when you are
|
||||
parallelizing over multiple machines: as some of the participating cores
|
||||
finish rendering the current frame, they can immediately start working on the next one
|
||||
instead of having to wait for all other cores to finish. Altogether, you
|
||||
might start the renderer something like this
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -xj 2 -c machine1;machine2;... animation/frame_*.xml
|
||||
\end{shell}
|
||||
|
||||
|
||||
\begin{console}[label=lst:mitsuba-cli,caption=Command line options of the \texttt{mitsuba} binary]
|
||||
Mitsuba version 0.1.1, Copyright (c) 2010 Wenzel Jakob
|
||||
Mitsuba version 0.2.1, Copyright (c) 2011 Wenzel Jakob
|
||||
Usage: mitsuba [options] <One or more scene XML files>
|
||||
Options/Arguments:
|
||||
-h Display this help text
|
||||
|
||||
-D key=val Define a constant, which can referenced as "$\texttt{\$}$key" in the scene
|
||||
-D key=val Define a constant, which can referenced as "$\$$key" in the scene
|
||||
|
||||
-o fname Write the output image to the file denoted by "fname"
|
||||
|
||||
|
@ -179,15 +56,139 @@ Options/Arguments:
|
|||
|
||||
-x Skip rendering of files where output already exists
|
||||
|
||||
-r sec Write (partial) output images every 'sec' seconds
|
||||
|
||||
-b res Specify the block resolution used to split images into parallel
|
||||
workloads (default: 32). Only applies to some integrators.
|
||||
|
||||
-v Be more verbose
|
||||
|
||||
-b Disable progress bars
|
||||
-w Treat warnings as errors
|
||||
|
||||
The README file included with the distribution contains further information.
|
||||
-z Disable progress bars
|
||||
|
||||
For documentation, please refer to http://www.mitsuba-renderer.org/docs.html
|
||||
\end{console}
|
||||
\lstref{mitsuba-cli} shows the output resulting from this command. The most common
|
||||
mode of operation is to render a single scene, which is provided as a parameter, e.g.
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba path-to/my-scene.xml
|
||||
\end{shell}
|
||||
It is also possible to connect to network render nodes, which essentially lets Mitsuba parallelize
|
||||
over additional cores. To do this, pass a semicolon-separated list of machines to
|
||||
the \code{-c} parameter.
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -c machine1;machine2;... path-to/my-scene.xml
|
||||
\end{shell}
|
||||
There are two different ways in which you can access render nodes:
|
||||
\begin{itemize}
|
||||
\item\textbf{Direct}: Here, you create a direct connection to a running \code{mtssrv} instance on
|
||||
another machine (\code{mtssrv} is the Mitsuba server process). From the the performance
|
||||
standpoint, this approach should always be preferred over the SSH method described below when there is
|
||||
a choice between them. There are some disadvantages though: first, you need to manually start
|
||||
\code{mtssrv} on every machine you want to use.
|
||||
|
||||
And perhaps more importantly: the direct communication
|
||||
protocol makes no provisions for a malicious user on the remote side. It is too costly
|
||||
to constantly check the communication stream for illegal data sequences, so Mitsuba simply doesn't do it.
|
||||
The consequence of this is that you should only use the direct communication approach within
|
||||
trusted networks.
|
||||
|
||||
For direct connections, you can specify the remote port as follows:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -c machine:1234 path-to/my-scene.xml
|
||||
\end{shell}
|
||||
When no port is explicitly specified, Mitsuba uses default value of 7554.
|
||||
\item \textbf{SSH}:
|
||||
This approach works as follows: The renderer creates a SSH connection
|
||||
to the remote side, where it launches a Mitsuba worker instance.
|
||||
All subsequent communication then passes through the encrypted link.
|
||||
This is completely secure but slower due to the encryption overhead.
|
||||
If you are rendering a complex scene, there is a good chance that it
|
||||
won't matter much since most time is spent doing computations rather than
|
||||
communicating
|
||||
|
||||
Such an SSH link can be created simply by using a slightly different syntax:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -c username@machine path-to/my-scene.xml
|
||||
\end{shell}
|
||||
The above line assumes that the remote home directory contains
|
||||
a Mitsuba source directory named \code{mitsuba},
|
||||
which contains the compiled Mitsuba binaries.
|
||||
If that is not the case, you need to provide the path to such a directory manually, e.g:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -c username@machine:/opt/mitsuba path-to/my-scene.xml
|
||||
\end{shell}
|
||||
For the SSH connection approach to work, you \emph{must} enable passwordless
|
||||
authentication.
|
||||
Try opening a terminal window and running the command \code{ssh username@machine}
|
||||
(replace with the details of your remote connection).
|
||||
If you are asked for a password, something is not set up correctly --- please see
|
||||
\url{http://www.debian-administration.org/articles/152} for instructions.
|
||||
|
||||
On Windows, the situation is a bit more difficult since there is no suitable SSH client by
|
||||
default. To get SSH connections to work, Mitsuba requires \code{plink.exe} (from PuTTY) to
|
||||
be on the path. For passwordless authentication with a Linux/OSX-based
|
||||
server, convert your private key to PuTTY's format using \code{puttygen.exe}.
|
||||
Afterwards, start \code{pageant.exe} to load and authenticate the key. All
|
||||
of these binaries are available from the PuTTY website.
|
||||
|
||||
It is possible to mix the two approaches to access some machines directly and others
|
||||
over SSH.
|
||||
\end{itemize}
|
||||
When doing many network-based renders over the command line, it can become tedious to
|
||||
specify the connections every time. They can alternatively be loaded from a text file
|
||||
where each line contains a separate connection description as discussed previously:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -s servers.txt path-to/my-scene.xml
|
||||
\end{shell}
|
||||
where \code{servers.txt} e.g. contains
|
||||
\begin{shell}
|
||||
user1@machine1.domain.org:/opt/mitsuba
|
||||
machine2.domain.org
|
||||
machine3.domain.org:7346
|
||||
\end{shell}
|
||||
\subsubsection{Passing parameters}
|
||||
Any attribute in the XML-based scene description language can be parameterized from the
|
||||
command line.
|
||||
For instance, you can render a scene several times with different reflectance values
|
||||
on a certain material by changing its description to something like
|
||||
\begin{xml}
|
||||
<bsdf type="diffuse">
|
||||
<spectrum name="reflectance" value="$\texttt{\$}$reflectance"/>
|
||||
</bsdf>
|
||||
\end{xml}
|
||||
and running Mitsuba as follows:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -Dreflectance=0.1 -o ref_0.1.exr scene.xml
|
||||
$\texttt{\$}$ mitsuba -Dreflectance=0.2 -o ref_0.2.exr scene.xml
|
||||
$\texttt{\$}$ mitsuba -Dreflectance=0.5 -o ref_0.5.exr scene.xml
|
||||
\end{shell}
|
||||
|
||||
\subsubsection{Writing partial images to disk}
|
||||
When doing lengthy command line renders on Linux or OSX, it is possible
|
||||
to send a signal to the process using
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ killall -HUP mitsuba
|
||||
\end{shell}
|
||||
This causes the renderer to write out the partially finished
|
||||
image, after which it continues rendering. This can sometimes be useful to
|
||||
check if everything is working correctly.
|
||||
|
||||
\subsubsection{Rendering an animation}
|
||||
The command line interface is ideally suited for rendering large amounts of files in batch
|
||||
operation. You can simply pass in the files using a wildcard in the filename.
|
||||
|
||||
If you've already rendered a subset of the frames and you only want to complete the remainder,
|
||||
add the \texttt{-x} flag, and all files with existing output will be skipped. You can also
|
||||
let the scheduler work on several scenes at once using the \texttt{-j} parameter --- this is
|
||||
especially useful when parallelizing over multiple machines: as some of the participating machines
|
||||
finish rendering the current frame, they can immediately start working on the next one
|
||||
instead of having to wait for all other cores to finish. Altogether, you
|
||||
might start the with parameters such as the following
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ mitsuba -xj 2 -c machine1;machine2;... animation/frame_*.xml
|
||||
\end{shell}
|
||||
\subsection{Direct connection server}
|
||||
A Mitsuba compute node can be created using the \code{mtssrv} executable. By default,
|
||||
it will listen on port 7554:
|
||||
|
@ -204,13 +205,19 @@ $\texttt{\$}$ mtssrv -i maxwell.cs.cornell.edu
|
|||
\end{shell}
|
||||
As advised in Section~\ref{sec:mitsuba}, it is advised to run \code{mtssrv} \emph{only} in trusted networks.
|
||||
|
||||
One nice feature of \code{mtssrv} is that it (like \code{mitsuba}) also supports the \code{-c} and \code{-s}
|
||||
parameters, which can be used to connect to additional compute servers.
|
||||
This allows building large hierarchies of nodes,
|
||||
where communication occurs only amongst neighbors and the root node presents itself as
|
||||
a computer with hundreds of cores.
|
||||
Connecting clients will not be able to distinguish additional cores obtained in this manner
|
||||
from the actual server cores.
|
||||
One nice feature of \code{mtssrv} is that it (like the \code{mitsuba} executable)
|
||||
also supports the \code{-c} and \code{-s} parameters, which create connections
|
||||
to additional compute servers.
|
||||
Using this feature, one can create hierarchies of compute nodes. For instance,
|
||||
the root \code{mttsrv} instance of such a hierarchy could share its work with a
|
||||
number of other machines running \code{mtssrv}, and each of these might also
|
||||
share their work with further machines, and so on...
|
||||
|
||||
The parallelization over such hierarchies happens transparently---when
|
||||
connecting a renderering process to the root node, it sees a machine
|
||||
with hundreds or thousands of cores, to which it can submit work without
|
||||
needing to worry about how exactly it is going to be spread out in
|
||||
the hierarchy.
|
||||
|
||||
Such hierarchies are mainly useful to reduce communication bottlenecks when distributing
|
||||
large resources (such as scenes) to remote machines. Imagine the following hypothetical scenario:
|
||||
|
@ -222,7 +229,7 @@ connection and the need to transmit your scene to every single compute node invo
|
|||
Using \code{mtssrv}, you can
|
||||
instead designate a central scheduling node at your workplace, which accepts connections and delegates
|
||||
rendering tasks to the other machines. In this case, you will only have to transmit the scene once,
|
||||
and the remaining distribution happens over the comparatively fast ethernet at your workplace.
|
||||
and the remaining distribution happens over the fast local network at your workplace.
|
||||
\subsection{Utility launcher}
|
||||
\label{sec:mtsutil}
|
||||
When working on a larger project, one often needs to implement various utility programs that
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
\section{Compiling the renderer}
|
||||
\label{sec:compiling}
|
||||
To compile Mitsuba, you will need a recent C++ compiler (e.g. GCC 4.1+ or
|
||||
Visual Studio 2008+) and some additional libraries, which Mitsuba uses internally.
|
||||
Builds on all supported platforms are done using a unified system
|
||||
|
@ -33,6 +34,8 @@ build/config-icl12-msvc2010-win32.py
|
|||
build/config-icl12-msvc2010-win64.py
|
||||
\end{shell}
|
||||
|
||||
\subsection{Compilation flags}
|
||||
\label{sec:compiling-flags}
|
||||
Usually, you will not have to make any modification to this file, but sometimes a few minor
|
||||
edits may be necessary. In particular, you might want to add or remove certain
|
||||
compilation flags from the \code{CXXFLAGS} parameter. The following settings
|
||||
|
@ -50,9 +53,7 @@ Off by default.
|
|||
\item[\texttt{MTS\_SSE}]Activate optimized SSE routines. On by default.
|
||||
\item[\texttt{MTS\_HAS\_COHERENT\_RT}]Include coherent ray tracing support (depends on \texttt{MTS\_SSE}). This flag is activated by default.
|
||||
\item[\texttt{MTS\_DEBUG\_FP}]Generated NaNs and overflows will cause floating point exceptions, which can be caught in a debugger. This is slow and mainly meant as a debugging tool for developers. Off by default.
|
||||
\item[\texttt{MTS\_SPECTRUM\_SAMPLES=}$\langle ..\rangle$]This setting defines the number of spectral samples (in the 400-700 $nm$ range) used to render scenes.
|
||||
The default is 3 samples, in which case the renderer automatically turns into an RGB-based system. For high-quality spectral rendering, this should
|
||||
be set to 30 or higher.
|
||||
\item[\texttt{SPECTRUM\_SAMPLES=}$\langle ..\rangle$]This setting defines the number of spectral samples (in the 368-830 $nm$ range) that are used to render scenes. The default is 3 samples, in which case the renderer automatically turns into an RGB-based system. For high-quality spectral rendering, this should be set to 30 or higher.
|
||||
\item[\texttt{SINGLE\_PRECISION}] Do all computation in single precision. This is normally sufficient and therefore used as the default setting.
|
||||
\item[\texttt{DOUBLE\_PRECISION}] Do all computation in double precision. This flag is incompatible with
|
||||
\texttt{MTS\_SSE}, \texttt{MTS\_HAS\_COHERENT\_RT}, and \texttt{MTS\_DEBUG\_FP}.
|
||||
|
|
|
@ -122,40 +122,77 @@ Integer and floating point values can be passed as follows:
|
|||
Note that you must adhere to the format expected by the object, i.e. you can't pass an integer property
|
||||
to an object, which expects a floating-point value associated with that name.
|
||||
\subsubsection{Strings}
|
||||
Passing strings is very straightforward:
|
||||
Passing strings is straightforward:
|
||||
\begin{xml}
|
||||
<string name="stringProperty" value="This is a string"/>
|
||||
\end{xml}
|
||||
\subsubsection{Color spectra}
|
||||
There are several different ways of passing color spectra to objects, which can be used interchangeably.
|
||||
The most basic one is to supply linear RGB or sRGB values as floating-point triplets or hex values
|
||||
Depending on the compilation flags of Mitsuba (see \secref{compiling-flags} for
|
||||
details), the renderer internally either represents colors using discretized color spectra
|
||||
(when \texttt{SPECTRUM\_SAMPLES} is set to a value other than 3), or it
|
||||
uses a basic linear RGB representation\footnote{The official
|
||||
releases all use linear RGB---to do spectral renderings, you will have
|
||||
to compile Mitsuba yourself.}.
|
||||
Irrespective of which internal representation is used, Mitsuba supports
|
||||
several different ways of specifying color information, which is then
|
||||
converted appropriately.
|
||||
|
||||
The preferred way of passing color spectra to the renderer is to explicitly
|
||||
denote the associated wavelengths of each value:
|
||||
\begin{xml}
|
||||
<spectrum name="spectrumProperty" value="400:0.56, 500:0.18, 600:0.58, 700:0.24"/>
|
||||
\end{xml}
|
||||
This is a mapping from wavelength in nanometers (before the colon)
|
||||
to a reflectance or intensity value (after the colon).
|
||||
Values in between are linearly interpolated from the two closest neighbors.
|
||||
A useful shortcut to get a completely uniform spectrum, it is to provide
|
||||
only a single value:
|
||||
\begin{xml}
|
||||
<spectrum name="spectrumProperty" value="0.56"/>
|
||||
\end{xml}
|
||||
|
||||
Another (discouraged) option is to directly provide the spectrum in Mitsuba's
|
||||
internal representation, avoiding the need for any kind of conversion.
|
||||
However, this is problematic, since the associated scene will likely not work
|
||||
anymore when Mitsuba is compiled with a different value of
|
||||
\texttt{SPECTRUM\_SAMPLES}.
|
||||
For completeness, the possibility is explained nonetheless. Assuming that
|
||||
the 360-830$nm$ range is discretized into ten 47$nm$-sized blocks
|
||||
(i.e. \texttt{SPECTRUM\_SAMPLES} is set to 10), their values can be specified
|
||||
as follows:
|
||||
\begin{xml}
|
||||
<spectrum name="spectrumProperty" value=".2, .2, .8, .4, .6, .5, .1, .9, .4, .2"/>
|
||||
\end{xml}
|
||||
|
||||
Another convenient way of providing color spectra is by specifying linear RGB
|
||||
or sRGB values using floating-point triplets or hex values:
|
||||
\begin{xml}
|
||||
<rgb name="spectrumProperty" value="0.2, 0.8, 0.4"/>
|
||||
<srgb name="spectrumProperty" value="0.4, 0.3, 0.2"/>
|
||||
<srgb name="spectrumProperty" value="#f9aa34"/>
|
||||
\end{xml}
|
||||
When Mitsuba is compiled with the default settings, it internally uses linear RGB to represent colors, so
|
||||
these values are directly used. The renderer can also be configured to sample the color spectrum using a specified
|
||||
number of samples, in which case the RGB values are first converted into spectra using a simple heuristic.
|
||||
When Mitsuba is compiled with the default settings, it internally uses
|
||||
linear RGB to represent colors, so these values can directly be used.
|
||||
However, when configured for doing spectral rendering, a suitable color
|
||||
spectrum with the requested RGB reflectance must be found. This is a tricky
|
||||
problem, since there is an infinite number of spectra with this property.
|
||||
|
||||
You can also directly supply the spectral color samples that Mitsuba internally uses if spectral rendering is
|
||||
active. This unfortunately closely couples the interpretation of a scene to how Mitsuba is compiled, which
|
||||
can be a disadvantage.
|
||||
For instance, the below example assumes that 6 spectral samples in the 400-700nm range are being used:
|
||||
Mitsuba uses a method by Smits et al. \cite{Smits2005RGB} to find a
|
||||
``plausible'' spectrum that is as smooth as possible. To do so, it uses
|
||||
one of two methods depending on whether the spectrum contains a
|
||||
unitless reflectance value, or a radiance-valued intensity.
|
||||
\begin{xml}
|
||||
<spectrum name="spectrumProperty" value="0.2, 0.8, 0.4, 0.6, 0.1, 0.9"/>
|
||||
<rgb name="spectrumProperty" intent="reflectance" value="0.2, 0.8, 0.4"/>
|
||||
<rgb name="spectrumProperty" intent="illuminant" value="0.2, 0.8, 0.4"/>
|
||||
\end{xml}
|
||||
A safer way is to specify a linearly interpolated spectral power distribution, which is converted into
|
||||
the internal spectral representation when the scene is loaded.
|
||||
\begin{xml}
|
||||
<spectrum name="spectrumProperty" value="400:0.56, 500:0.18, 600:0.58, 700:0.24"/>
|
||||
\end{xml}
|
||||
This is essentially a mapping from wavelength in nanometers (before the colon) to a reflectance or
|
||||
intensity value (after the colon). Missing values are linearly interpolated from the two closest neighbors.
|
||||
The \texttt{reflectance} intent is used by default, so remember to
|
||||
set it to \texttt{illuminant} when defining the brightness of a
|
||||
light source with the \texttt{<rgb>} tag.
|
||||
|
||||
When spectral power distributions are obtained from measurements (e.g. at 10nm intervals), they are
|
||||
usually quite unwiedy and can clutter the scene description. For this reason,
|
||||
there is yet another way to pass a spectrum by loading it from an external
|
||||
When spectral power distributions are obtained from measurements
|
||||
(e.g. at 10$nm$ intervals), they are usually quite unwiedy and can clutter
|
||||
the scene description. For this reason, there is yet another way to pass
|
||||
a spectrum by loading it from an external
|
||||
file:
|
||||
\begin{xml}
|
||||
<spectrum name="spectrumProperty" filename="measuredSpectrum.spd"/>
|
||||
|
@ -173,11 +210,6 @@ are allowed. Here is an example:
|
|||
...
|
||||
\end{xml}
|
||||
|
||||
Passing a single value to \texttt{spectrum} will result in a a completely flat spectral power distribution:
|
||||
\begin{xml}
|
||||
<spectrum name="spectrumProperty" value="0.56"/>
|
||||
\end{xml}
|
||||
|
||||
Finally, it is also possible to specify the spectral distribution of a black body emitter, where the temperature is given in Kelvin.
|
||||
\begin{xml}
|
||||
<blackbody name="spectrumProperty" temperature="5000"/>
|
||||
|
@ -233,8 +265,8 @@ choices are available:
|
|||
\end{xml}
|
||||
\item Scaling operations. The coefficients may also be negative to obtain a flip, e.g.
|
||||
\begin{xml}
|
||||
<scale x="2" y="1" z="-1"/>
|
||||
<scale value="5"/> <!-- (uniform scale) -->
|
||||
<scale value="5"/> <!-- uniform scale -->
|
||||
<scale x="2" y="1" z="-1"/> <!-- non-unform scale -->
|
||||
\end{xml}
|
||||
\item Explicit 4$\times$4 matrices, e.g
|
||||
\begin{xml}
|
||||
|
|
|
@ -1,23 +1,33 @@
|
|||
\section{Introduction}
|
||||
\textbf{Disclaimer:} This is manual is currently a work in progress---please
|
||||
bear with me while things are coming together.
|
||||
\textbf{Disclaimer:} This is manual documents the usage, file format, and
|
||||
internal design of the Mitsuba rendering system. It is currently a work
|
||||
in progress, hence some parts may still be incomplete or missing.
|
||||
|
||||
\subsection{About Mitsuba}
|
||||
Mitsuba is an extensible rendering framework written in portable C++. It implements unbiased
|
||||
as well as biased techniques and contains heavy optimizations targeted towards current CPU
|
||||
architectures.
|
||||
In comparison to other open source renderers, Mitsuba places a strong emphasis on recent research-oriented
|
||||
rendering techniques, such as path-based formulations of Metropolis Light Transport and volumetric
|
||||
modeling approaches.
|
||||
Mitsuba is a research-oriented rendering system in the style of PBRT
|
||||
(\url{www.pbrt.org}), from which it derives much inspiration.
|
||||
It is written in portable C++, implements unbiased as well
|
||||
as biased techniques, and contains heavy optimizations targeted
|
||||
towards current CPU architectures.
|
||||
|
||||
\paragraph{Performance:}
|
||||
In comparison to other open source renderers, Mitsuba places a strong
|
||||
emphasis on experimental rendering techniques, such as path-based
|
||||
formulations of Metropolis Light Transport and volumetric
|
||||
modeling approaches. Thus, it may be of genuine interest to those who
|
||||
would like to experiment with such techniques that haven't yet found
|
||||
their way into mainstream renderers, and it also provides a solid
|
||||
foundation for research in this domain.
|
||||
|
||||
Other design considerations are are:
|
||||
|
||||
\parheader{Performance:}
|
||||
One important goal of Mitsuba is to provide optimized implementations of the most commonly
|
||||
used rendering algorithms. By virtue of running on a shared foundation, comparisons between them can
|
||||
better highlight the merits and limitations of different approaches. This is in contrast to, say,
|
||||
comparing two completely different rendering products, where technical information on the underlying
|
||||
implementation is often intentionally not provided.
|
||||
|
||||
\paragraph{Robustness:}
|
||||
\parheader{Robustness:}
|
||||
In many cases, physically-based rendering packages force the user to model scenes with the underlying
|
||||
algorithm (specifically: its convergence behavior) in mind. For instance, glass windows are routinely
|
||||
replaced with light portals, photons must be manually guided to the relevant parts of a scene, and
|
||||
|
@ -25,18 +35,18 @@ interactions with complex materials are taboo, since they cannot be importance s
|
|||
One focus of Mitsuba will be to develop path-space light transport algorithms, which handle such
|
||||
cases more gracefully.
|
||||
|
||||
\paragraph{Scalability:} Mitsuba instances can be merged into large clusters, which transparently distribute and
|
||||
\parheader{Scalability:} Mitsuba instances can be merged into large clusters, which transparently distribute and
|
||||
jointly execute tasks assigned to them using only node-to-node communcation. It has successfully
|
||||
scaled to large-scale renderings that involved 1024 cores working on a single image.
|
||||
scaled to large-scale renderings that involved more than 1000 cores working on a single image.
|
||||
Most algorithms in Mitsuba are written using a generic parallelization layer, which can tap
|
||||
into this cluster-wide parallelism. The principle is that if any component of the renderer produces
|
||||
work that takes longer than a second or so, it at least ought to use all of the processing power
|
||||
it can get.
|
||||
|
||||
The renderer also tries to be very conservative in its use of memory, which lets it handle
|
||||
The renderer also tries to be very conservative in its use of memory, which allows it to handle
|
||||
large scenes (>30 million triangles) and multi-gigabyte heterogeneous volumes on consumer hardware.
|
||||
|
||||
\paragraph{Usability:}
|
||||
\parheader{Usability:}
|
||||
Mitsuba comes with a graphical user interface to interactively explore scenes. Once a suitable
|
||||
viewpoint has been found, it is straightforward to perform renderings using any of the
|
||||
implemented rendering techniques, while tweaking their parameters to find the most suitable
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
\newcommand{\MtsVer}{\color{lstattrib}\texttt{"\MitsubaVersion"}}
|
||||
|
||||
\newcommand{\showbreak}{$\rhookswarrow$ }
|
||||
\newcommand{\parheader}[1]{\vspace{2mm}\textbf{\color{myblue}#1}}
|
||||
|
||||
\newcommand{\otoprule}{\midrule[.8pt]}
|
||||
\newlength\fboxrulebackup
|
||||
|
|
|
@ -12,3 +12,12 @@
|
|||
year = {2011},
|
||||
month = {July}
|
||||
}
|
||||
|
||||
@article{Smits2005RGB,
|
||||
title = {{An RGB-to-spectrum conversion for reflectances}},
|
||||
author = {Smits, Brian},
|
||||
journal = {Graphics tools: The jgt editors' choice},
|
||||
pages = {291},
|
||||
year = {2005},
|
||||
publisher = {AK Peters, Ltd.}
|
||||
}
|
||||
|
|
|
@ -68,11 +68,15 @@ public:
|
|||
* \param useConvergenceEstimate Estimate the convergence behavior
|
||||
* of the GL-quadrature by comparing the 4, 7 and 13-point
|
||||
* variants and increase the absolute tolerance accordingly.
|
||||
*
|
||||
* \param warn Should the integrator warn when the number of
|
||||
* function evaluations is exceeded?
|
||||
*/
|
||||
GaussLobattoIntegrator(size_t maxEvals,
|
||||
Float absError = 0,
|
||||
Float relError = 0,
|
||||
bool useConvergenceEstimate = true);
|
||||
bool useConvergenceEstimate = true,
|
||||
bool warn = true);
|
||||
|
||||
/**
|
||||
* \brief Integrate the function \c f from \c a to \c b.
|
||||
|
@ -106,8 +110,8 @@ protected:
|
|||
protected:
|
||||
Float m_absError, m_relError;
|
||||
size_t m_maxEvals;
|
||||
bool m_exceededEvals;
|
||||
const bool m_useConvergenceEstimate;
|
||||
bool m_useConvergenceEstimate;
|
||||
bool m_warn;
|
||||
static const Float m_alpha;
|
||||
static const Float m_beta;
|
||||
static const Float m_x1;
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace fs = boost::filesystem;
|
|||
specified in the configuration file!
|
||||
#endif
|
||||
|
||||
#define SPECTRUM_MIN_WAVELENGTH 400
|
||||
#define SPECTRUM_MAX_WAVELENGTH 700
|
||||
#define SPECTRUM_MIN_WAVELENGTH 360
|
||||
#define SPECTRUM_MAX_WAVELENGTH 830
|
||||
#define SPECTRUM_RANGE \
|
||||
(SPECTRUM_MAX_WAVELENGTH-SPECTRUM_MIN_WAVELENGTH)
|
||||
|
||||
|
@ -154,8 +154,8 @@ public:
|
|||
* for the specified number of samples
|
||||
*/
|
||||
inline InterpolatedSpectrum(size_t size = 0) {
|
||||
m_wavelength.reserve(size);
|
||||
m_value.reserve(size);
|
||||
m_wavelengths.reserve(size);
|
||||
m_values.reserve(size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,6 +195,9 @@ public:
|
|||
*/
|
||||
void zeroExtend();
|
||||
|
||||
/// Clear all stored entries
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* \brief Return the value of the spectral power distribution
|
||||
* at the given wavelength.
|
||||
|
@ -226,11 +229,11 @@ public:
|
|||
/// Virtual destructor
|
||||
virtual ~InterpolatedSpectrum() { }
|
||||
private:
|
||||
std::vector<Float> m_wavelength, m_value;
|
||||
std::vector<Float> m_wavelengths, m_values;
|
||||
};
|
||||
|
||||
/** \brief Discrete spectral power distribution based on a number
|
||||
* of wavelength bins over the 400-700 nm range.
|
||||
* of wavelength bins over the 360-830 nm range.
|
||||
*
|
||||
* This class defines a vector-like data type that can be used for
|
||||
* computations involving radiance.
|
||||
|
@ -524,7 +527,7 @@ public:
|
|||
Float eval(Float lambda) const;
|
||||
|
||||
/// \brief Return the wavelength range covered by a spectral bin
|
||||
std::pair<Float, Float> getBinCoverage(size_t index) const;
|
||||
static std::pair<Float, Float> getBinCoverage(size_t index);
|
||||
|
||||
/// Return the luminance in candelas.
|
||||
#if SPECTRUM_SAMPLES == 3
|
||||
|
@ -558,7 +561,7 @@ public:
|
|||
|
||||
/// Convert from linear RGB
|
||||
inline void fromLinearRGB(Float r, Float g, Float b,
|
||||
EConversionIntent /* unused */) {
|
||||
EConversionIntent intent = EReflectance /* unused */) {
|
||||
/* Nothing to do -- the renderer is in RGB mode */
|
||||
s[0] = r; s[1] = g; s[2] = b;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ protected:
|
|||
|
||||
/// Asserts that the two floating point values are equal
|
||||
void assertEqualsImpl(Float expected, Float actual, Float epsilon, const char *file, int line);
|
||||
|
||||
/// Asserts that the two spectral power distributions are equal
|
||||
void assertEqualsImpl(const Spectrum &expected, const Spectrum &actual, Float epsilon, const char *file, int line);
|
||||
|
||||
/// Asserts that the two 2D vectors are equal
|
||||
void assertEqualsImpl(const Vector2 &expected, const Vector2 &actual, Float epsilon, const char *file, int line);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<xsd:element name="transform" type="transform"/>
|
||||
<xsd:element name="string" type="string"/>
|
||||
<xsd:element name="spectrum" type="spectrum"/>
|
||||
<xsd:element name="rgb" type="string"/>
|
||||
<xsd:element name="rgb" type="rgb"/>
|
||||
<xsd:element name="srgb" type="string"/>
|
||||
<xsd:element name="blackbody" type="blackbody"/>
|
||||
</xsd:choice>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<xsd:element name="transform" type="transform"/>
|
||||
<xsd:element name="string" type="string"/>
|
||||
<xsd:element name="spectrum" type="spectrum"/>
|
||||
<xsd:element name="rgb" type="string"/>
|
||||
<xsd:element name="rgb" type="rgb"/>
|
||||
<xsd:element name="srgb" type="string"/>
|
||||
<xsd:element name="blackbody" type="blackbody"/>
|
||||
</xsd:choice>
|
||||
|
@ -276,6 +276,12 @@
|
|||
<xsd:attribute name="value" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="rgb">
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="value" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="intent" type="xsd:string" use="optional"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="spectrum">
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="filename" type="xsd:string" use="optional"/>
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
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/render/bsdf.h>
|
||||
#include <mitsuba/render/consttexture.h>
|
||||
#include "ior.h"
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/*! \plugin{conductor}{Smooth conductor}
|
||||
*/
|
||||
class SmoothConductor : public BSDF {
|
||||
public:
|
||||
SmoothConductor(const Properties &props) : BSDF(props) {
|
||||
m_specularReflectance = new ConstantSpectrumTexture(
|
||||
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
|
||||
|
||||
m_eta = props.getSpectrum("eta");
|
||||
m_k = props.getSpectrum("k");
|
||||
|
||||
m_components.push_back(EDeltaReflection | EFrontSide);
|
||||
m_usesRayDifferentials = false;
|
||||
}
|
||||
|
||||
SmoothConductor(Stream *stream, InstanceManager *manager)
|
||||
: BSDF(stream, manager) {
|
||||
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_eta = Spectrum(stream);
|
||||
m_k = Spectrum(stream);
|
||||
m_components.push_back(EDeltaReflection | EFrontSide);
|
||||
m_usesRayDifferentials =
|
||||
m_specularReflectance->usesRayDifferentials();
|
||||
}
|
||||
|
||||
virtual ~SmoothConductor() { }
|
||||
|
||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||
BSDF::serialize(stream, manager);
|
||||
manager->serialize(stream, m_specularReflectance.get());
|
||||
m_eta.serialize(stream);
|
||||
m_k.serialize(stream);
|
||||
}
|
||||
|
||||
void addChild(const std::string &name, ConfigurableObject *child) {
|
||||
if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && name == "specularReflectance") {
|
||||
m_specularReflectance = static_cast<Texture *>(child);
|
||||
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
|
||||
} else {
|
||||
BSDF::addChild(name, child);
|
||||
}
|
||||
}
|
||||
|
||||
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
|
||||
return Spectrum(0.0f);
|
||||
}
|
||||
|
||||
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||
return Spectrum(0.0f);
|
||||
}
|
||||
|
||||
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &sample) const {
|
||||
return Spectrum(0.0f);
|
||||
}
|
||||
|
||||
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "SmoothConductor[" << endl
|
||||
<< " eta = " << m_eta.toString() << "," << endl
|
||||
<< " k = " << m_k.toString() << "," << endl
|
||||
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << endl
|
||||
<< "]";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
private:
|
||||
ref<Texture> m_specularReflectance;
|
||||
Spectrum m_eta;
|
||||
Spectrum m_k;
|
||||
};
|
||||
|
||||
MTS_IMPLEMENT_CLASS_S(SmoothConductor, false, BSDF)
|
||||
MTS_EXPORT_PLUGIN(SmoothConductor, "Smooth conductor");
|
||||
MTS_NAMESPACE_END
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#if !defined(__MICROFACET_H)
|
||||
#define __MICROFACET_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Implements the microfacet distributions discussed in
|
||||
* "Microfacet Models for Refraction through Rough Surfaces"
|
||||
* by Bruce Walter, Stephen R. Marschner, Hongsong Li, and Kenneth E. Torrance
|
||||
*/
|
||||
class MicrofacetDistribution {
|
||||
public:
|
||||
/// Supported distribution types
|
||||
enum EType {
|
||||
/// Beckmann distribution derived from Gaussian random surfaces
|
||||
EBeckmann = 0,
|
||||
/// Classical Phong distribution
|
||||
EPhong = 1,
|
||||
/// Long-tailed distribution proposed by Walter et al.
|
||||
EGGX = 2
|
||||
};
|
||||
|
||||
/// Create a microfacet distribution of the specified type
|
||||
MicrofacetDistribution(EType type = EBeckmann)
|
||||
: m_type(type) { }
|
||||
|
||||
/**
|
||||
* \brief Create a microfacet distribution of the specified name
|
||||
* (ggx/phong/beckmann)
|
||||
*/
|
||||
MicrofacetDistribution(const std::string &name) {
|
||||
std::string distr =
|
||||
boost::to_lower_copy(props.getString("distribution", "beckmann"));
|
||||
|
||||
if (distr == "beckmann")
|
||||
m_type = EBeckmann;
|
||||
else if (distr == "phong")
|
||||
m_type = EPhong;
|
||||
else if (distr == "ggx")
|
||||
m_type = EGGX;
|
||||
else
|
||||
SLog(EError, "Specified an invalid distribution \"%s\", must be "
|
||||
"\"beckmann\", \"phong\", or \"ggx\"!", distr.c_str());
|
||||
}
|
||||
|
||||
/// Return the distribution type
|
||||
inline EType getType() const { return m_type; }
|
||||
|
||||
/**
|
||||
* \brief Convert the roughness values so that they behave similarly to the
|
||||
* Beckmann distribution.
|
||||
*
|
||||
* Also clamps to the minimal roughness 1e-4 to avoid numerical issues
|
||||
* (For lower roughness values, please switch to the smooth BSDF variants)
|
||||
*/
|
||||
Float transformRoughness(Float value) const {
|
||||
if (m_type == EPhong)
|
||||
value = 2 / (value * value) - 2;
|
||||
return std::max(value, (Float) 1e-4f);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Implements the microfacet distribution function D
|
||||
*
|
||||
* \param m The microsurface normal
|
||||
* \param v An arbitrary direction
|
||||
*/
|
||||
Float eval(const Vector &m, Float alpha) const {
|
||||
if (Frame::cosTheta(m) <= 0)
|
||||
return 0.0f;
|
||||
|
||||
Float result;
|
||||
switch (m_type) {
|
||||
case EBeckmann: {
|
||||
/* Beckmann distribution function for Gaussian random surfaces */
|
||||
const Float ex = Frame::tanTheta(m) / alpha;
|
||||
result = std::exp(-(ex*ex)) / (M_PI * alpha*alpha *
|
||||
std::pow(Frame::cosTheta(m), (Float) 4.0f));
|
||||
}
|
||||
break;
|
||||
|
||||
case EPhong: {
|
||||
/* Phong distribution function */
|
||||
result = (alpha + 2) * INV_TWOPI
|
||||
* std::pow(Frame::cosTheta(m), alpha);
|
||||
}
|
||||
break;
|
||||
|
||||
case EGGX: {
|
||||
/* Empirical GGX distribution function for rough surfaces */
|
||||
const Float tanTheta = Frame::tanTheta(m),
|
||||
cosTheta = Frame::cosTheta(m);
|
||||
|
||||
const Float root = alpha / (cosTheta*cosTheta *
|
||||
(alpha*alpha + tanTheta*tanTheta));
|
||||
|
||||
result = INV_PI * (root * root);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SLog(EError, "Invalid distribution function!");
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/* Prevent potential numerical issues in other stages of the model */
|
||||
if (result < 1e-20f)
|
||||
result = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sample microsurface normals according to
|
||||
* the selected distribution
|
||||
*
|
||||
* \param sample A uniformly distributed 2D sample
|
||||
* \param alpha Surface roughness
|
||||
*/
|
||||
Normal sample(const Point2 &sample, Float alpha) const {
|
||||
/* The azimuthal component is always selected
|
||||
uniformly regardless of the distribution */
|
||||
Float phiM = (2.0f * M_PI) * sample.y,
|
||||
thetaM = 0.0f;
|
||||
|
||||
switch (m_type) {
|
||||
case EBeckmann:
|
||||
thetaM = std::atan(std::sqrt(-alpha*alpha *
|
||||
std::log(1.0f - sample.x)));
|
||||
break;
|
||||
|
||||
case EPhong:
|
||||
thetaM = std::acos(std::pow(sample.x, (Float) 1 /
|
||||
(alpha + 2)));
|
||||
break;
|
||||
|
||||
case EGGX:
|
||||
thetaM = std::atan(alpha * std::sqrt(sample.x) /
|
||||
std::sqrt(1.0f - sample.x));
|
||||
break;
|
||||
|
||||
default:
|
||||
SLog(EError, "Invalid distribution function!");
|
||||
}
|
||||
|
||||
return Normal(sphericalDirection(thetaM, phiM));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Smith's shadow-masking function G1 for each
|
||||
* of the supported microfacet distributions
|
||||
*
|
||||
* \param m The microsurface normal
|
||||
* \param v An arbitrary direction
|
||||
* \param alpha The surface roughness
|
||||
*/
|
||||
Float smithG1(const Vector &v, const Vector &m, Float alpha) const {
|
||||
const Float tanTheta = std::abs(Frame::tanTheta(v));
|
||||
|
||||
/* perpendicular incidence -- no shadowing/masking */
|
||||
if (tanTheta == 0.0f)
|
||||
return 1.0f;
|
||||
|
||||
/* Can't see the back side from the front and vice versa */
|
||||
if (dot(v, m) * Frame::cosTheta(v) <= 0)
|
||||
return 0.0f;
|
||||
|
||||
switch (m_type) {
|
||||
case EPhong:
|
||||
/* Approximation recommended by Bruce Walter: Use
|
||||
the Beckmann shadowing-masking function with
|
||||
specially chosen roughness value */
|
||||
alpha = std::sqrt(0.5f * alpha + 1) / tanTheta;
|
||||
|
||||
case EBeckmann: {
|
||||
/* Use a fast and accurate (<0.35% rel. error) rational
|
||||
approximation to the shadowing-masking function */
|
||||
const Float a = 1.0f / (alpha * tanTheta);
|
||||
const Float aSqr = a * a;
|
||||
|
||||
if (a >= 1.6f)
|
||||
return 1.0f;
|
||||
|
||||
return (3.535f * a + 2.181f * aSqr)
|
||||
/ (1.0f + 2.276f * a + 2.577f * aSqr);
|
||||
}
|
||||
break;
|
||||
|
||||
case EGGX: {
|
||||
const Float root = alpha * tanTheta;
|
||||
return 2.0f / (1.0f + std::sqrt(1.0f + root*root));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SLog(EError, "Invalid distribution function!");
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string toString() const {
|
||||
switch (m_distribution) {
|
||||
case EBeckmann: return "beckmann"; break;
|
||||
case EPhong: return "phong"; break;
|
||||
case EGGX: return "ggx"; break;
|
||||
default:
|
||||
SLog(EError, "Invalid distribution function");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
private:
|
||||
EType type;
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
#endif /* __MICROFACET_H */
|
|
@ -23,7 +23,6 @@ MTS_NAMESPACE_BEGIN
|
|||
FOR A PARTICULAR PURPOSE. See the license for more details.
|
||||
*/
|
||||
|
||||
|
||||
const Float GaussLobattoIntegrator::m_alpha = (Float) std::sqrt(2.0/3.0);
|
||||
const Float GaussLobattoIntegrator::m_beta = (Float) (1.0/std::sqrt(5.0));
|
||||
const Float GaussLobattoIntegrator::m_x1 = (Float) 0.94288241569547971906;
|
||||
|
@ -31,11 +30,12 @@ const Float GaussLobattoIntegrator::m_x2 = (Float) 0.64185334234578130578;
|
|||
const Float GaussLobattoIntegrator::m_x3 = (Float) 0.23638319966214988028;
|
||||
|
||||
GaussLobattoIntegrator::GaussLobattoIntegrator(size_t maxEvals,
|
||||
Float absError, Float relError, bool useConvergenceEstimate)
|
||||
Float absError, Float relError, bool useConvergenceEstimate, bool warn)
|
||||
: m_absError(absError),
|
||||
m_relError(relError),
|
||||
m_maxEvals(maxEvals),
|
||||
m_useConvergenceEstimate(useConvergenceEstimate) {
|
||||
m_useConvergenceEstimate(useConvergenceEstimate),
|
||||
m_warn(warn) {
|
||||
if (m_absError == 0 && m_relError == 0)
|
||||
SLog(EError, "GaussLobattoIntegrator:: Absolute and relative "
|
||||
"error requirements can't both be zero!");
|
||||
|
@ -53,9 +53,9 @@ Float GaussLobattoIntegrator::integrate(
|
|||
}
|
||||
const Float absTolerance = calculateAbsTolerance(f, a, b, evals);
|
||||
evals += 2;
|
||||
if (evals >= m_maxEvals)
|
||||
SLog(EWarn, "GaussLobattoIntegrator: Maximum number of evaluations reached!");
|
||||
Float result = factor * adaptiveGaussLobattoStep(f, a, b, f(a), f(b), absTolerance, evals);
|
||||
if (evals >= m_maxEvals && m_warn)
|
||||
SLog(EWarn, "GaussLobattoIntegrator: Maximum number of evaluations reached!");
|
||||
if (_evals)
|
||||
*_evals = evals;
|
||||
return result;
|
||||
|
@ -73,18 +73,15 @@ Float GaussLobattoIntegrator::calculateAbsTolerance(
|
|||
const Float y11= f(m+m_alpha*h);
|
||||
const Float y13= f(b);
|
||||
|
||||
Float acc=h*((Float) 0.0158271919734801831*(y1+y13)
|
||||
+(Float) 0.0942738402188500455*(f(m-m_x1*h)+f(m+m_x1*h))
|
||||
+(Float) 0.1550719873365853963*(y3+y11)
|
||||
+(Float) 0.1888215739601824544*(f(m-m_x2*h)+ f(m+m_x2*h))
|
||||
+(Float) 0.1997734052268585268*(y5+y9)
|
||||
+(Float) 0.2249264653333395270*(f(m-m_x3*h)+f(m+m_x3*h))
|
||||
+(Float) 0.2426110719014077338*y7);
|
||||
Float acc = h*((Float) 0.0158271919734801831*(y1+y13)
|
||||
+ (Float) 0.0942738402188500455*(f(m-m_x1*h)+f(m+m_x1*h))
|
||||
+ (Float) 0.1550719873365853963*(y3+y11)
|
||||
+ (Float) 0.1888215739601824544*(f(m-m_x2*h)+ f(m+m_x2*h))
|
||||
+ (Float) 0.1997734052268585268*(y5+y9)
|
||||
+ (Float) 0.2249264653333395270*(f(m-m_x3*h)+f(m+m_x3*h))
|
||||
+ (Float) 0.2426110719014077338*y7);
|
||||
evals += 13;
|
||||
|
||||
if (acc == 0)
|
||||
SLog(EError, "GaussLobattoIntegrator: Cannot calculate absolute error from relative error");
|
||||
|
||||
Float r = 1.0;
|
||||
if (m_useConvergenceEstimate) {
|
||||
const Float integral2 = (h/6)*(y1+y13+5*(y5+y9));
|
||||
|
@ -98,7 +95,7 @@ Float GaussLobattoIntegrator::calculateAbsTolerance(
|
|||
}
|
||||
Float result = std::numeric_limits<Float>::infinity();
|
||||
|
||||
if (m_relError != 0)
|
||||
if (m_relError != 0 && acc != 0)
|
||||
result = acc * std::max(m_relError,
|
||||
std::numeric_limits<Float>::epsilon())
|
||||
/ (r*std::numeric_limits<Float>::epsilon());
|
||||
|
@ -134,16 +131,11 @@ Float GaussLobattoIntegrator::adaptiveGaussLobattoStep(
|
|||
|
||||
evals += 5;
|
||||
|
||||
if (evals >= m_maxEvals) {
|
||||
if (evals-5 < m_maxEvals) // Warn once
|
||||
SLog(EWarn, "GaussLobattoIntegrator: Maximum number of evaluations reached!");
|
||||
if (evals >= m_maxEvals)
|
||||
return integral1;
|
||||
}
|
||||
|
||||
Float dist = acc + (integral1-integral2);
|
||||
if(dist==acc || mll<=a || b<=mrr) {
|
||||
if (m<=a || b<=m)
|
||||
SLog(EWarn, "GaussLobattoIntegrator: Interval contains no more machine numbers!");
|
||||
if (dist==acc || mll<=a || b<=mrr) {
|
||||
return integral1;
|
||||
} else {
|
||||
return adaptiveGaussLobattoStep(f,a,mll,fa,fmll,acc,evals)
|
||||
|
|
|
@ -160,15 +160,12 @@ void Spectrum::staticShutdown() {
|
|||
void Spectrum::fromContinuousSpectrum(const ContinuousSpectrum &smooth) {
|
||||
#if SPECTRUM_SAMPLES == 3
|
||||
/* Convolve with the XYZ matching functions and convert to RGB */
|
||||
Float start = CIE_wavelengths[0], end = CIE_wavelengths[CIE_samples-1];
|
||||
|
||||
Float X = smooth->average(ProductSpectrum(smooth, CIE_X_interp),
|
||||
(Float) CIE_start, (Float) CIE_end);
|
||||
Float Y = smooth->average(ProductSpectrum(smooth, CIE_Y_interp),
|
||||
(Float) CIE_start, (Float) CIE_end);
|
||||
Float Z = smooth->average(ProductSpectrum(smooth, CIE_Z_interp),
|
||||
(Float) CIE_start, (Float) CIE_end);
|
||||
Float normalization = 1.0f /
|
||||
CIE_Y_interp.average((Float) CIE_start, (Float) CIE_end);
|
||||
Float X = ProductSpectrum(smooth, CIE_X_interp).average(start, end);
|
||||
Float Y = ProductSpectrum(smooth, CIE_Y_interp).average(start, end);
|
||||
Float Z = ProductSpectrum(smooth, CIE_Z_interp).average(start, end);
|
||||
Float normalization = 1.0f / CIE_Y_interp.average(start, end);
|
||||
|
||||
X *= normalization; Y *= normalization; Z *= normalization;
|
||||
|
||||
|
@ -197,7 +194,7 @@ Float Spectrum::eval(Float lambda) const {
|
|||
#endif
|
||||
}
|
||||
|
||||
std::pair<Float, Float> Spectrum::getBinCoverage(size_t index) const {
|
||||
std::pair<Float, Float> Spectrum::getBinCoverage(size_t index) {
|
||||
#if SPECTRUM_SAMPLES == 3
|
||||
SLog(EError, "Spectrum::getBinCoverage() is not supported when Mitsuba "
|
||||
"is configured for RGB-based rendering");
|
||||
|
@ -413,7 +410,8 @@ std::string Spectrum::toString() const {
|
|||
#if SPECTRUM_SAMPLES == 3
|
||||
oss << s[i];
|
||||
#else
|
||||
oss << m_wavelengths[i] << " => " << s[i];
|
||||
oss << m_wavelengths[i] << "-"
|
||||
<< m_wavelengths[i+1] << "nm => " << s[i];
|
||||
#endif
|
||||
if (i < SPECTRUM_SAMPLES - 1)
|
||||
oss << ", ";
|
||||
|
@ -441,14 +439,27 @@ Float ProductSpectrum::eval(Float lambda) const {
|
|||
}
|
||||
|
||||
Float ContinuousSpectrum::average(Float lambdaMin, Float lambdaMax) const {
|
||||
GaussLobattoIntegrator integrator(10000, Epsilon, Epsilon);
|
||||
GaussLobattoIntegrator integrator(10000, Epsilon, Epsilon, false, false);
|
||||
|
||||
if (lambdaMax <= lambdaMin)
|
||||
return 0.0f;
|
||||
|
||||
return integrator.integrate(
|
||||
boost::bind(&ContinuousSpectrum::eval, this, _1), lambdaMin, lambdaMax)
|
||||
/ (lambdaMax - lambdaMin);
|
||||
Float integral = 0;
|
||||
|
||||
/// Integrate over 50nm-sized regions
|
||||
size_t nSteps = std::max((size_t) 1,
|
||||
(size_t) std::ceil((lambdaMax - lambdaMin) / 50));
|
||||
Float stepSize = (lambdaMax - lambdaMin) / nSteps,
|
||||
pos = lambdaMin;
|
||||
|
||||
for (size_t i=0; i<nSteps; ++i) {
|
||||
integral += integrator.integrate(
|
||||
boost::bind(&ContinuousSpectrum::eval, this, _1),
|
||||
pos, pos + stepSize);
|
||||
pos+= stepSize;
|
||||
}
|
||||
|
||||
return integral / (lambdaMax - lambdaMin);
|
||||
}
|
||||
|
||||
InterpolatedSpectrum::InterpolatedSpectrum(const fs::path &path) {
|
||||
|
@ -471,72 +482,81 @@ InterpolatedSpectrum::InterpolatedSpectrum(const fs::path &path) {
|
|||
append(lambda, value);
|
||||
}
|
||||
SLog(EInfo, "\"%s\": loaded a spectral power distribution with " SIZE_T_FMT
|
||||
" entries", path.leaf().c_str(), m_wavelength.size());
|
||||
" entries", path.leaf().c_str(), m_wavelengths.size());
|
||||
}
|
||||
|
||||
InterpolatedSpectrum::InterpolatedSpectrum(const Float *wavelengths, const Float *values, size_t nEntries) {
|
||||
m_wavelength.resize(nEntries);
|
||||
m_value.resize(nEntries);
|
||||
m_wavelengths.resize(nEntries);
|
||||
m_values.resize(nEntries);
|
||||
|
||||
for (size_t i=0; i<nEntries; ++i) {
|
||||
m_wavelength[i] = *wavelengths++;
|
||||
if (i > 0 && m_wavelength[i-1] >= m_wavelength[i])
|
||||
m_wavelengths[i] = *wavelengths++;
|
||||
if (i > 0 && m_wavelengths[i-1] >= m_wavelengths[i])
|
||||
SLog(EError, "InterpolatedSpectrum: spectral power distribution values must "
|
||||
"be provided in order of increasing wavelength!");
|
||||
m_value[i] = *values++;
|
||||
m_values[i] = *values++;
|
||||
}
|
||||
}
|
||||
|
||||
void InterpolatedSpectrum::append(Float lambda, Float value) {
|
||||
if (m_wavelength.size() != 0 && m_wavelength[m_wavelength.size()-1] >= lambda)
|
||||
if (m_wavelengths.size() != 0 && m_wavelengths[m_wavelengths.size()-1] >= lambda)
|
||||
SLog(EError, "InterpolatedSpectrum: spectral power distribution values must "
|
||||
"be provided in order of increasing wavelength!");
|
||||
m_wavelength.push_back(lambda);
|
||||
m_value.push_back(value);
|
||||
m_wavelengths.push_back(lambda);
|
||||
m_values.push_back(value);
|
||||
}
|
||||
|
||||
void InterpolatedSpectrum::clear() {
|
||||
m_wavelengths.clear();
|
||||
m_values.clear();
|
||||
}
|
||||
|
||||
void InterpolatedSpectrum::zeroExtend() {
|
||||
if (m_wavelength.size() < 2)
|
||||
if (m_wavelengths.size() < 2)
|
||||
SLog(EError, "InterpolatedSpectrum::zeroExtend() -- at least 2 "
|
||||
"entries are needed!");
|
||||
|
||||
Float avgSpacing = 0;
|
||||
for (size_t i=0; i<m_wavelength.size()-1; ++i)
|
||||
avgSpacing += m_wavelength[i+1] - m_wavelength[i];
|
||||
for (size_t i=0; i<m_wavelengths.size()-1; ++i)
|
||||
avgSpacing += m_wavelengths[i+1] - m_wavelengths[i];
|
||||
|
||||
avgSpacing /= m_wavelength.size()-1;
|
||||
m_wavelength.insert(m_wavelength.begin(), m_wavelength[0] - avgSpacing);
|
||||
m_wavelength.push_back(m_wavelength[m_wavelength.size()-1] + avgSpacing);
|
||||
m_value.insert(m_value.begin(), 0.0f);
|
||||
m_value.push_back(0);
|
||||
avgSpacing /= m_wavelengths.size()-1;
|
||||
if (m_values[0] != 0) {
|
||||
m_wavelengths.insert(m_wavelengths.begin(), m_wavelengths[0] - avgSpacing);
|
||||
m_values.insert(m_values.begin(), 0.0f);
|
||||
}
|
||||
if (m_values[m_values.size()-1] != 0) {
|
||||
m_wavelengths.push_back(m_wavelengths[m_wavelengths.size()-1] + avgSpacing);
|
||||
m_values.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
Float InterpolatedSpectrum::average(Float lambdaMin, Float lambdaMax) const {
|
||||
typedef std::vector<Float>::const_iterator iterator;
|
||||
|
||||
if (m_wavelength.size() < 2)
|
||||
if (m_wavelengths.size() < 2)
|
||||
return 0.0f;
|
||||
|
||||
Float rangeStart = std::max(lambdaMin, m_wavelength[0]);
|
||||
Float rangeEnd = std::min(lambdaMax, m_wavelength[m_wavelength.size()-1]);
|
||||
Float rangeStart = std::max(lambdaMin, m_wavelengths[0]);
|
||||
Float rangeEnd = std::min(lambdaMax, m_wavelengths[m_wavelengths.size()-1]);
|
||||
|
||||
if (rangeEnd <= rangeStart)
|
||||
return 0.0f;
|
||||
|
||||
/* Find the starting index using binary search */
|
||||
size_t entry = std::max((size_t) (std::lower_bound(m_wavelength.begin(),
|
||||
m_wavelength.end(), rangeStart) - m_wavelength.begin()), (size_t) 1) - 1;
|
||||
size_t entry = std::max((size_t) (std::lower_bound(m_wavelengths.begin(),
|
||||
m_wavelengths.end(), rangeStart) - m_wavelengths.begin()), (size_t) 1) - 1;
|
||||
|
||||
Float result = 0.0f;
|
||||
for (; entry+1 < m_wavelength.size() && rangeEnd >= m_wavelength[entry]; ++entry) {
|
||||
for (; entry+1 < m_wavelengths.size() && rangeEnd >= m_wavelengths[entry]; ++entry) {
|
||||
/* Step through the samples and integrate trapezoids */
|
||||
|
||||
Float a = m_wavelength[entry],
|
||||
b = m_wavelength[entry+1],
|
||||
Float a = m_wavelengths[entry],
|
||||
b = m_wavelengths[entry+1],
|
||||
ca = std::max(a, rangeStart),
|
||||
cb = std::min(b, rangeEnd),
|
||||
fa = m_value[entry],
|
||||
fb = m_value[entry+1],
|
||||
fa = m_values[entry],
|
||||
fb = m_values[entry+1],
|
||||
invAB = 1.0f / (b - a);
|
||||
|
||||
if (cb <= ca)
|
||||
|
@ -553,26 +573,26 @@ Float InterpolatedSpectrum::average(Float lambdaMin, Float lambdaMax) const {
|
|||
|
||||
Float InterpolatedSpectrum::eval(Float lambda) const {
|
||||
typedef std::vector<Float>::const_iterator iterator;
|
||||
if (m_wavelength.size() < 2 ||
|
||||
lambda < m_wavelength[0] ||
|
||||
lambda > m_wavelength[m_wavelength.size()-1])
|
||||
if (m_wavelengths.size() < 2 ||
|
||||
lambda < m_wavelengths[0] ||
|
||||
lambda > m_wavelengths[m_wavelengths.size()-1])
|
||||
return 0;
|
||||
|
||||
/* Find the associated table entries using binary search */
|
||||
std::pair<iterator, iterator> result =
|
||||
std::equal_range(m_wavelength.begin(), m_wavelength.end(), lambda);
|
||||
std::equal_range(m_wavelengths.begin(), m_wavelengths.end(), lambda);
|
||||
|
||||
size_t idx1 = result.first - m_wavelength.begin();
|
||||
size_t idx2 = result.second - m_wavelength.begin();
|
||||
size_t idx1 = result.first - m_wavelengths.begin();
|
||||
size_t idx2 = result.second - m_wavelengths.begin();
|
||||
if (idx1 == idx2) {
|
||||
Float a = m_wavelength[idx1-1],
|
||||
b = m_wavelength[idx1],
|
||||
fa = m_value[idx1-1],
|
||||
fb = m_value[idx1];
|
||||
Float a = m_wavelengths[idx1-1],
|
||||
b = m_wavelengths[idx1],
|
||||
fa = m_values[idx1-1],
|
||||
fb = m_values[idx1];
|
||||
return lerp((lambda - a) / (b-a), fb, fa);
|
||||
} else if (idx2 == idx1+1) {
|
||||
/* Hit a value exactly */
|
||||
return m_value[idx1];
|
||||
return m_values[idx1];
|
||||
} else {
|
||||
SLog(EError, "Internal error while interpolating spectrum values");
|
||||
return 0;
|
||||
|
@ -582,9 +602,9 @@ Float InterpolatedSpectrum::eval(Float lambda) const {
|
|||
std::string InterpolatedSpectrum::toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "InterpolatedSpectrum[" << endl;
|
||||
for (size_t i=0; i<m_wavelength.size(); ++i) {
|
||||
oss << " " << m_wavelength[i] << " nm => " << m_value[i];
|
||||
if (i+1 < m_wavelength.size())
|
||||
for (size_t i=0; i<m_wavelengths.size(); ++i) {
|
||||
oss << " " << m_wavelengths[i] << " nm => " << m_values[i];
|
||||
if (i+1 < m_wavelengths.size())
|
||||
oss << ",";
|
||||
oss << endl;
|
||||
}
|
||||
|
@ -633,369 +653,367 @@ const Float CIE_wavelengths[CIE_samples] = {
|
|||
808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821,
|
||||
822, 823, 824, 825, 826, 827, 828, 829, 830 };
|
||||
|
||||
|
||||
|
||||
const Float CIE_X_entries[CIE_samples] = {
|
||||
0.0001299000f, 0.0001458470f, 0.0001638021f, 0.0001840037f,
|
||||
0.0002066902f, 0.0002321000f, 0.0002607280f, 0.0002930750f,
|
||||
0.0003293880f, 0.0003699140f, 0.0004149000f, 0.0004641587f,
|
||||
0.0005189860f, 0.0005818540f, 0.0006552347f, 0.0007416000f,
|
||||
0.0008450296f, 0.0009645268f, 0.001094949f, 0.001231154f,
|
||||
0.001368000f, 0.001502050f, 0.001642328f, 0.001802382f,
|
||||
0.001995757f, 0.002236000f, 0.002535385f, 0.002892603f,
|
||||
0.003300829f, 0.003753236f, 0.004243000f, 0.004762389f,
|
||||
0.005330048f, 0.005978712f, 0.006741117f, 0.007650000f,
|
||||
0.008751373f, 0.01002888f, 0.01142170f, 0.01286901f,
|
||||
0.01431000f, 0.01570443f, 0.01714744f, 0.01878122f,
|
||||
0.02074801f, 0.02319000f, 0.02620736f, 0.02978248f,
|
||||
0.03388092f, 0.03846824f, 0.04351000f, 0.04899560f,
|
||||
0.05502260f, 0.06171880f, 0.06921200f, 0.07763000f,
|
||||
0.08695811f, 0.09717672f, 0.1084063f, 0.1207672f,
|
||||
0.1343800f, 0.1493582f, 0.1653957f, 0.1819831f,
|
||||
0.1986110f, 0.2147700f, 0.2301868f, 0.2448797f,
|
||||
0.2587773f, 0.2718079f, 0.2839000f, 0.2949438f,
|
||||
0.3048965f, 0.3137873f, 0.3216454f, 0.3285000f,
|
||||
0.3343513f, 0.3392101f, 0.3431213f, 0.3461296f,
|
||||
0.3482800f, 0.3495999f, 0.3501474f, 0.3500130f,
|
||||
0.3492870f, 0.3480600f, 0.3463733f, 0.3442624f,
|
||||
0.3418088f, 0.3390941f, 0.3362000f, 0.3331977f,
|
||||
0.3300411f, 0.3266357f, 0.3228868f, 0.3187000f,
|
||||
0.3140251f, 0.3088840f, 0.3032904f, 0.2972579f,
|
||||
0.2908000f, 0.2839701f, 0.2767214f, 0.2689178f,
|
||||
0.2604227f, 0.2511000f, 0.2408475f, 0.2298512f,
|
||||
0.2184072f, 0.2068115f, 0.1953600f, 0.1842136f,
|
||||
0.1733273f, 0.1626881f, 0.1522833f, 0.1421000f,
|
||||
0.1321786f, 0.1225696f, 0.1132752f, 0.1042979f,
|
||||
0.09564000f, 0.08729955f, 0.07930804f, 0.07171776f,
|
||||
0.06458099f, 0.05795001f, 0.05186211f, 0.04628152f,
|
||||
0.04115088f, 0.03641283f, 0.03201000f, 0.02791720f,
|
||||
0.02414440f, 0.02068700f, 0.01754040f, 0.01470000f,
|
||||
0.01216179f, 0.009919960f, 0.007967240f, 0.006296346f,
|
||||
0.004900000f, 0.003777173f, 0.002945320f, 0.002424880f,
|
||||
0.002236293f, 0.002400000f, 0.002925520f, 0.003836560f,
|
||||
0.005174840f, 0.006982080f, 0.009300000f, 0.01214949f,
|
||||
0.01553588f, 0.01947752f, 0.02399277f, 0.02910000f,
|
||||
0.03481485f, 0.04112016f, 0.04798504f, 0.05537861f,
|
||||
0.06327000f, 0.07163501f, 0.08046224f, 0.08973996f,
|
||||
0.09945645f, 0.1096000f, 0.1201674f, 0.1311145f,
|
||||
0.1423679f, 0.1538542f, 0.1655000f, 0.1772571f,
|
||||
0.1891400f, 0.2011694f, 0.2133658f, 0.2257499f,
|
||||
0.2383209f, 0.2510668f, 0.2639922f, 0.2771017f,
|
||||
0.2904000f, 0.3038912f, 0.3175726f, 0.3314384f,
|
||||
0.3454828f, 0.3597000f, 0.3740839f, 0.3886396f,
|
||||
0.4033784f, 0.4183115f, 0.4334499f, 0.4487953f,
|
||||
0.4643360f, 0.4800640f, 0.4959713f, 0.5120501f,
|
||||
0.5282959f, 0.5446916f, 0.5612094f, 0.5778215f,
|
||||
0.5945000f, 0.6112209f, 0.6279758f, 0.6447602f,
|
||||
0.6615697f, 0.6784000f, 0.6952392f, 0.7120586f,
|
||||
0.7288284f, 0.7455188f, 0.7621000f, 0.7785432f,
|
||||
0.7948256f, 0.8109264f, 0.8268248f, 0.8425000f,
|
||||
0.8579325f, 0.8730816f, 0.8878944f, 0.9023181f,
|
||||
0.9163000f, 0.9297995f, 0.9427984f, 0.9552776f,
|
||||
0.9672179f, 0.9786000f, 0.9893856f, 0.9995488f,
|
||||
1.0090892f, 1.0180064f, 1.0263000f, 1.0339827f,
|
||||
1.0409860f, 1.0471880f, 1.0524667f, 1.0567000f,
|
||||
1.0597944f, 1.0617992f, 1.0628068f, 1.0629096f,
|
||||
1.0622000f, 1.0607352f, 1.0584436f, 1.0552244f,
|
||||
1.0509768f, 1.0456000f, 1.0390369f, 1.0313608f,
|
||||
1.0226662f, 1.0130477f, 1.0026000f, 0.9913675f,
|
||||
0.9793314f, 0.9664916f, 0.9528479f, 0.9384000f,
|
||||
0.9231940f, 0.9072440f, 0.8905020f, 0.8729200f,
|
||||
0.8544499f, 0.8350840f, 0.8149460f, 0.7941860f,
|
||||
0.7729540f, 0.7514000f, 0.7295836f, 0.7075888f,
|
||||
0.6856022f, 0.6638104f, 0.6424000f, 0.6215149f,
|
||||
0.6011138f, 0.5811052f, 0.5613977f, 0.5419000f,
|
||||
0.5225995f, 0.5035464f, 0.4847436f, 0.4661939f,
|
||||
0.4479000f, 0.4298613f, 0.4120980f, 0.3946440f,
|
||||
0.3775333f, 0.3608000f, 0.3444563f, 0.3285168f,
|
||||
0.3130192f, 0.2980011f, 0.2835000f, 0.2695448f,
|
||||
0.2561184f, 0.2431896f, 0.2307272f, 0.2187000f,
|
||||
0.2070971f, 0.1959232f, 0.1851708f, 0.1748323f,
|
||||
0.1649000f, 0.1553667f, 0.1462300f, 0.1374900f,
|
||||
0.1291467f, 0.1212000f, 0.1136397f, 0.1064650f,
|
||||
0.09969044f, 0.09333061f, 0.08740000f, 0.08190096f,
|
||||
0.07680428f, 0.07207712f, 0.06768664f, 0.06360000f,
|
||||
0.05980685f, 0.05628216f, 0.05297104f, 0.04981861f,
|
||||
0.04677000f, 0.04378405f, 0.04087536f, 0.03807264f,
|
||||
0.03540461f, 0.03290000f, 0.03056419f, 0.02838056f,
|
||||
0.02634484f, 0.02445275f, 0.02270000f, 0.02108429f,
|
||||
0.01959988f, 0.01823732f, 0.01698717f, 0.01584000f,
|
||||
0.01479064f, 0.01383132f, 0.01294868f, 0.01212920f,
|
||||
0.01135916f, 0.01062935f, 0.009938846f, 0.009288422f,
|
||||
0.008678854f, 0.008110916f, 0.007582388f, 0.007088746f,
|
||||
0.006627313f, 0.006195408f, 0.005790346f, 0.005409826f,
|
||||
0.005052583f, 0.004717512f, 0.004403507f, 0.004109457f,
|
||||
0.003833913f, 0.003575748f, 0.003334342f, 0.003109075f,
|
||||
0.002899327f, 0.002704348f, 0.002523020f, 0.002354168f,
|
||||
0.002196616f, 0.002049190f, 0.001910960f, 0.001781438f,
|
||||
0.001660110f, 0.001546459f, 0.001439971f, 0.001340042f,
|
||||
0.001246275f, 0.001158471f, 0.001076430f, 0.0009999493f,
|
||||
0.0009287358f, 0.0008624332f, 0.0008007503f, 0.0007433960f,
|
||||
0.0006900786f, 0.0006405156f, 0.0005945021f, 0.0005518646f,
|
||||
0.0005124290f, 0.0004760213f, 0.0004424536f, 0.0004115117f,
|
||||
0.0003829814f, 0.0003566491f, 0.0003323011f, 0.0003097586f,
|
||||
0.0002888871f, 0.0002695394f, 0.0002515682f, 0.0002348261f,
|
||||
0.0002191710f, 0.0002045258f, 0.0001908405f, 0.0001780654f,
|
||||
0.0001661505f, 0.0001550236f, 0.0001446219f, 0.0001349098f,
|
||||
0.0001258520f, 0.0001174130f, 0.0001095515f, 0.0001022245f,
|
||||
0.00009539445f, 0.00008902390f, 0.00008307527f, 0.00007751269f,
|
||||
0.00007231304f, 0.00006745778f, 0.00006292844f, 0.00005870652f,
|
||||
0.00005477028f, 0.00005109918f, 0.00004767654f, 0.00004448567f,
|
||||
0.00004150994f, 0.00003873324f, 0.00003614203f, 0.00003372352f,
|
||||
0.00003146487f, 0.00002935326f, 0.00002737573f, 0.00002552433f,
|
||||
0.00002379376f, 0.00002217870f, 0.00002067383f, 0.00001927226f,
|
||||
0.00001796640f, 0.00001674991f, 0.00001561648f, 0.00001455977f,
|
||||
0.00001357387f, 0.00001265436f, 0.00001179723f, 0.00001099844f,
|
||||
0.00001025398f, 0.000009559646f, 0.000008912044f, 0.000008308358f,
|
||||
0.000007745769f, 0.000007221456f, 0.000006732475f, 0.000006276423f,
|
||||
0.000005851304f, 0.000005455118f, 0.000005085868f, 0.000004741466f,
|
||||
0.000004420236f, 0.000004120783f, 0.000003841716f, 0.000003581652f,
|
||||
0.000003339127f, 0.000003112949f, 0.000002902121f, 0.000002705645f,
|
||||
0.000002522525f, 0.000002351726f, 0.000002192415f, 0.000002043902f,
|
||||
0.000001905497f, 0.000001776509f, 0.000001656215f, 0.000001544022f,
|
||||
0.000001439440f, 0.000001341977f, 0.000001251141f
|
||||
0.0001299000, 0.0001458470, 0.0001638021, 0.0001840037,
|
||||
0.0002066902, 0.0002321000, 0.0002607280, 0.0002930750,
|
||||
0.0003293880, 0.0003699140, 0.0004149000, 0.0004641587,
|
||||
0.0005189860, 0.0005818540, 0.0006552347, 0.0007416000,
|
||||
0.0008450296, 0.0009645268, 0.001094949, 0.001231154,
|
||||
0.001368000, 0.001502050, 0.001642328, 0.001802382,
|
||||
0.001995757, 0.002236000, 0.002535385, 0.002892603,
|
||||
0.003300829, 0.003753236, 0.004243000, 0.004762389,
|
||||
0.005330048, 0.005978712, 0.006741117, 0.007650000,
|
||||
0.008751373, 0.01002888, 0.01142170, 0.01286901,
|
||||
0.01431000, 0.01570443, 0.01714744, 0.01878122,
|
||||
0.02074801, 0.02319000, 0.02620736, 0.02978248,
|
||||
0.03388092, 0.03846824, 0.04351000, 0.04899560,
|
||||
0.05502260, 0.06171880, 0.06921200, 0.07763000,
|
||||
0.08695811, 0.09717672, 0.1084063, 0.1207672,
|
||||
0.1343800, 0.1493582, 0.1653957, 0.1819831,
|
||||
0.1986110, 0.2147700, 0.2301868, 0.2448797,
|
||||
0.2587773, 0.2718079, 0.2839000, 0.2949438,
|
||||
0.3048965, 0.3137873, 0.3216454, 0.3285000,
|
||||
0.3343513, 0.3392101, 0.3431213, 0.3461296,
|
||||
0.3482800, 0.3495999, 0.3501474, 0.3500130,
|
||||
0.3492870, 0.3480600, 0.3463733, 0.3442624,
|
||||
0.3418088, 0.3390941, 0.3362000, 0.3331977,
|
||||
0.3300411, 0.3266357, 0.3228868, 0.3187000,
|
||||
0.3140251, 0.3088840, 0.3032904, 0.2972579,
|
||||
0.2908000, 0.2839701, 0.2767214, 0.2689178,
|
||||
0.2604227, 0.2511000, 0.2408475, 0.2298512,
|
||||
0.2184072, 0.2068115, 0.1953600, 0.1842136,
|
||||
0.1733273, 0.1626881, 0.1522833, 0.1421000,
|
||||
0.1321786, 0.1225696, 0.1132752, 0.1042979,
|
||||
0.09564000, 0.08729955, 0.07930804, 0.07171776,
|
||||
0.06458099, 0.05795001, 0.05186211, 0.04628152,
|
||||
0.04115088, 0.03641283, 0.03201000, 0.02791720,
|
||||
0.02414440, 0.02068700, 0.01754040, 0.01470000,
|
||||
0.01216179, 0.009919960, 0.007967240, 0.006296346,
|
||||
0.004900000, 0.003777173, 0.002945320, 0.002424880,
|
||||
0.002236293, 0.002400000, 0.002925520, 0.003836560,
|
||||
0.005174840, 0.006982080, 0.009300000, 0.01214949,
|
||||
0.01553588, 0.01947752, 0.02399277, 0.02910000,
|
||||
0.03481485, 0.04112016, 0.04798504, 0.05537861,
|
||||
0.06327000, 0.07163501, 0.08046224, 0.08973996,
|
||||
0.09945645, 0.1096000, 0.1201674, 0.1311145,
|
||||
0.1423679, 0.1538542, 0.1655000, 0.1772571,
|
||||
0.1891400, 0.2011694, 0.2133658, 0.2257499,
|
||||
0.2383209, 0.2510668, 0.2639922, 0.2771017,
|
||||
0.2904000, 0.3038912, 0.3175726, 0.3314384,
|
||||
0.3454828, 0.3597000, 0.3740839, 0.3886396,
|
||||
0.4033784, 0.4183115, 0.4334499, 0.4487953,
|
||||
0.4643360, 0.4800640, 0.4959713, 0.5120501,
|
||||
0.5282959, 0.5446916, 0.5612094, 0.5778215,
|
||||
0.5945000, 0.6112209, 0.6279758, 0.6447602,
|
||||
0.6615697, 0.6784000, 0.6952392, 0.7120586,
|
||||
0.7288284, 0.7455188, 0.7621000, 0.7785432,
|
||||
0.7948256, 0.8109264, 0.8268248, 0.8425000,
|
||||
0.8579325, 0.8730816, 0.8878944, 0.9023181,
|
||||
0.9163000, 0.9297995, 0.9427984, 0.9552776,
|
||||
0.9672179, 0.9786000, 0.9893856, 0.9995488,
|
||||
1.0090892, 1.0180064, 1.0263000, 1.0339827,
|
||||
1.0409860, 1.0471880, 1.0524667, 1.0567000,
|
||||
1.0597944, 1.0617992, 1.0628068, 1.0629096,
|
||||
1.0622000, 1.0607352, 1.0584436, 1.0552244,
|
||||
1.0509768, 1.0456000, 1.0390369, 1.0313608,
|
||||
1.0226662, 1.0130477, 1.0026000, 0.9913675,
|
||||
0.9793314, 0.9664916, 0.9528479, 0.9384000,
|
||||
0.9231940, 0.9072440, 0.8905020, 0.8729200,
|
||||
0.8544499, 0.8350840, 0.8149460, 0.7941860,
|
||||
0.7729540, 0.7514000, 0.7295836, 0.7075888,
|
||||
0.6856022, 0.6638104, 0.6424000, 0.6215149,
|
||||
0.6011138, 0.5811052, 0.5613977, 0.5419000,
|
||||
0.5225995, 0.5035464, 0.4847436, 0.4661939,
|
||||
0.4479000, 0.4298613, 0.4120980, 0.3946440,
|
||||
0.3775333, 0.3608000, 0.3444563, 0.3285168,
|
||||
0.3130192, 0.2980011, 0.2835000, 0.2695448,
|
||||
0.2561184, 0.2431896, 0.2307272, 0.2187000,
|
||||
0.2070971, 0.1959232, 0.1851708, 0.1748323,
|
||||
0.1649000, 0.1553667, 0.1462300, 0.1374900,
|
||||
0.1291467, 0.1212000, 0.1136397, 0.1064650,
|
||||
0.09969044, 0.09333061, 0.08740000, 0.08190096,
|
||||
0.07680428, 0.07207712, 0.06768664, 0.06360000,
|
||||
0.05980685, 0.05628216, 0.05297104, 0.04981861,
|
||||
0.04677000, 0.04378405, 0.04087536, 0.03807264,
|
||||
0.03540461, 0.03290000, 0.03056419, 0.02838056,
|
||||
0.02634484, 0.02445275, 0.02270000, 0.02108429,
|
||||
0.01959988, 0.01823732, 0.01698717, 0.01584000,
|
||||
0.01479064, 0.01383132, 0.01294868, 0.01212920,
|
||||
0.01135916, 0.01062935, 0.009938846, 0.009288422,
|
||||
0.008678854, 0.008110916, 0.007582388, 0.007088746,
|
||||
0.006627313, 0.006195408, 0.005790346, 0.005409826,
|
||||
0.005052583, 0.004717512, 0.004403507, 0.004109457,
|
||||
0.003833913, 0.003575748, 0.003334342, 0.003109075,
|
||||
0.002899327, 0.002704348, 0.002523020, 0.002354168,
|
||||
0.002196616, 0.002049190, 0.001910960, 0.001781438,
|
||||
0.001660110, 0.001546459, 0.001439971, 0.001340042,
|
||||
0.001246275, 0.001158471, 0.001076430, 0.0009999493,
|
||||
0.0009287358, 0.0008624332, 0.0008007503, 0.0007433960,
|
||||
0.0006900786, 0.0006405156, 0.0005945021, 0.0005518646,
|
||||
0.0005124290, 0.0004760213, 0.0004424536, 0.0004115117,
|
||||
0.0003829814, 0.0003566491, 0.0003323011, 0.0003097586,
|
||||
0.0002888871, 0.0002695394, 0.0002515682, 0.0002348261,
|
||||
0.0002191710, 0.0002045258, 0.0001908405, 0.0001780654,
|
||||
0.0001661505, 0.0001550236, 0.0001446219, 0.0001349098,
|
||||
0.0001258520, 0.0001174130, 0.0001095515, 0.0001022245,
|
||||
0.00009539445, 0.00008902390, 0.00008307527, 0.00007751269,
|
||||
0.00007231304, 0.00006745778, 0.00006292844, 0.00005870652,
|
||||
0.00005477028, 0.00005109918, 0.00004767654, 0.00004448567,
|
||||
0.00004150994, 0.00003873324, 0.00003614203, 0.00003372352,
|
||||
0.00003146487, 0.00002935326, 0.00002737573, 0.00002552433,
|
||||
0.00002379376, 0.00002217870, 0.00002067383, 0.00001927226,
|
||||
0.00001796640, 0.00001674991, 0.00001561648, 0.00001455977,
|
||||
0.00001357387, 0.00001265436, 0.00001179723, 0.00001099844,
|
||||
0.00001025398, 0.000009559646, 0.000008912044, 0.000008308358,
|
||||
0.000007745769, 0.000007221456, 0.000006732475, 0.000006276423,
|
||||
0.000005851304, 0.000005455118, 0.000005085868, 0.000004741466,
|
||||
0.000004420236, 0.000004120783, 0.000003841716, 0.000003581652,
|
||||
0.000003339127, 0.000003112949, 0.000002902121, 0.000002705645,
|
||||
0.000002522525, 0.000002351726, 0.000002192415, 0.000002043902,
|
||||
0.000001905497, 0.000001776509, 0.000001656215, 0.000001544022,
|
||||
0.000001439440, 0.000001341977, 0.000001251141
|
||||
};
|
||||
|
||||
const Float CIE_Y_entries[CIE_samples] = {
|
||||
0.000003917000f, 0.000004393581f, 0.000004929604f, 0.000005532136f,
|
||||
0.000006208245f, 0.000006965000f, 0.000007813219f, 0.000008767336f,
|
||||
0.000009839844f, 0.00001104323f, 0.00001239000f, 0.00001388641f,
|
||||
0.00001555728f, 0.00001744296f, 0.00001958375f, 0.00002202000f,
|
||||
0.00002483965f, 0.00002804126f, 0.00003153104f, 0.00003521521f,
|
||||
0.00003900000f, 0.00004282640f, 0.00004691460f, 0.00005158960f,
|
||||
0.00005717640f, 0.00006400000f, 0.00007234421f, 0.00008221224f,
|
||||
0.00009350816f, 0.0001061361f, 0.0001200000f, 0.0001349840f,
|
||||
0.0001514920f, 0.0001702080f, 0.0001918160f, 0.0002170000f,
|
||||
0.0002469067f, 0.0002812400f, 0.0003185200f, 0.0003572667f,
|
||||
0.0003960000f, 0.0004337147f, 0.0004730240f, 0.0005178760f,
|
||||
0.0005722187f, 0.0006400000f, 0.0007245600f, 0.0008255000f,
|
||||
0.0009411600f, 0.001069880f, 0.001210000f, 0.001362091f,
|
||||
0.001530752f, 0.001720368f, 0.001935323f, 0.002180000f,
|
||||
0.002454800f, 0.002764000f, 0.003117800f, 0.003526400f,
|
||||
0.004000000f, 0.004546240f, 0.005159320f, 0.005829280f,
|
||||
0.006546160f, 0.007300000f, 0.008086507f, 0.008908720f,
|
||||
0.009767680f, 0.01066443f, 0.01160000f, 0.01257317f,
|
||||
0.01358272f, 0.01462968f, 0.01571509f, 0.01684000f,
|
||||
0.01800736f, 0.01921448f, 0.02045392f, 0.02171824f,
|
||||
0.02300000f, 0.02429461f, 0.02561024f, 0.02695857f,
|
||||
0.02835125f, 0.02980000f, 0.03131083f, 0.03288368f,
|
||||
0.03452112f, 0.03622571f, 0.03800000f, 0.03984667f,
|
||||
0.04176800f, 0.04376600f, 0.04584267f, 0.04800000f,
|
||||
0.05024368f, 0.05257304f, 0.05498056f, 0.05745872f,
|
||||
0.06000000f, 0.06260197f, 0.06527752f, 0.06804208f,
|
||||
0.07091109f, 0.07390000f, 0.07701600f, 0.08026640f,
|
||||
0.08366680f, 0.08723280f, 0.09098000f, 0.09491755f,
|
||||
0.09904584f, 0.1033674f, 0.1078846f, 0.1126000f,
|
||||
0.1175320f, 0.1226744f, 0.1279928f, 0.1334528f,
|
||||
0.1390200f, 0.1446764f, 0.1504693f, 0.1564619f,
|
||||
0.1627177f, 0.1693000f, 0.1762431f, 0.1835581f,
|
||||
0.1912735f, 0.1994180f, 0.2080200f, 0.2171199f,
|
||||
0.2267345f, 0.2368571f, 0.2474812f, 0.2586000f,
|
||||
0.2701849f, 0.2822939f, 0.2950505f, 0.3085780f,
|
||||
0.3230000f, 0.3384021f, 0.3546858f, 0.3716986f,
|
||||
0.3892875f, 0.4073000f, 0.4256299f, 0.4443096f,
|
||||
0.4633944f, 0.4829395f, 0.5030000f, 0.5235693f,
|
||||
0.5445120f, 0.5656900f, 0.5869653f, 0.6082000f,
|
||||
0.6293456f, 0.6503068f, 0.6708752f, 0.6908424f,
|
||||
0.7100000f, 0.7281852f, 0.7454636f, 0.7619694f,
|
||||
0.7778368f, 0.7932000f, 0.8081104f, 0.8224962f,
|
||||
0.8363068f, 0.8494916f, 0.8620000f, 0.8738108f,
|
||||
0.8849624f, 0.8954936f, 0.9054432f, 0.9148501f,
|
||||
0.9237348f, 0.9320924f, 0.9399226f, 0.9472252f,
|
||||
0.9540000f, 0.9602561f, 0.9660074f, 0.9712606f,
|
||||
0.9760225f, 0.9803000f, 0.9840924f, 0.9874812f,
|
||||
0.9903128f, 0.9928116f, 0.9949501f, 0.9967108f,
|
||||
0.9980983f, 0.9991120f, 0.9997482f, 1.0000000f,
|
||||
0.9998567f, 0.9993046f, 0.9983255f, 0.9968987f,
|
||||
0.9950000f, 0.9926005f, 0.9897426f, 0.9864444f,
|
||||
0.9827241f, 0.9786000f, 0.9740837f, 0.9691712f,
|
||||
0.9638568f, 0.9581349f, 0.9520000f, 0.9454504f,
|
||||
0.9384992f, 0.9311628f, 0.9234576f, 0.9154000f,
|
||||
0.9070064f, 0.8982772f, 0.8892048f, 0.8797816f,
|
||||
0.8700000f, 0.8598613f, 0.8493920f, 0.8386220f,
|
||||
0.8275813f, 0.8163000f, 0.8047947f, 0.7930820f,
|
||||
0.7811920f, 0.7691547f, 0.7570000f, 0.7447541f,
|
||||
0.7324224f, 0.7200036f, 0.7074965f, 0.6949000f,
|
||||
0.6822192f, 0.6694716f, 0.6566744f, 0.6438448f,
|
||||
0.6310000f, 0.6181555f, 0.6053144f, 0.5924756f,
|
||||
0.5796379f, 0.5668000f, 0.5539611f, 0.5411372f,
|
||||
0.5283528f, 0.5156323f, 0.5030000f, 0.4904688f,
|
||||
0.4780304f, 0.4656776f, 0.4534032f, 0.4412000f,
|
||||
0.4290800f, 0.4170360f, 0.4050320f, 0.3930320f,
|
||||
0.3810000f, 0.3689184f, 0.3568272f, 0.3447768f,
|
||||
0.3328176f, 0.3210000f, 0.3093381f, 0.2978504f,
|
||||
0.2865936f, 0.2756245f, 0.2650000f, 0.2547632f,
|
||||
0.2448896f, 0.2353344f, 0.2260528f, 0.2170000f,
|
||||
0.2081616f, 0.1995488f, 0.1911552f, 0.1829744f,
|
||||
0.1750000f, 0.1672235f, 0.1596464f, 0.1522776f,
|
||||
0.1451259f, 0.1382000f, 0.1315003f, 0.1250248f,
|
||||
0.1187792f, 0.1127691f, 0.1070000f, 0.1014762f,
|
||||
0.09618864f, 0.09112296f, 0.08626485f, 0.08160000f,
|
||||
0.07712064f, 0.07282552f, 0.06871008f, 0.06476976f,
|
||||
0.06100000f, 0.05739621f, 0.05395504f, 0.05067376f,
|
||||
0.04754965f, 0.04458000f, 0.04175872f, 0.03908496f,
|
||||
0.03656384f, 0.03420048f, 0.03200000f, 0.02996261f,
|
||||
0.02807664f, 0.02632936f, 0.02470805f, 0.02320000f,
|
||||
0.02180077f, 0.02050112f, 0.01928108f, 0.01812069f,
|
||||
0.01700000f, 0.01590379f, 0.01483718f, 0.01381068f,
|
||||
0.01283478f, 0.01192000f, 0.01106831f, 0.01027339f,
|
||||
0.009533311f, 0.008846157f, 0.008210000f, 0.007623781f,
|
||||
0.007085424f, 0.006591476f, 0.006138485f, 0.005723000f,
|
||||
0.005343059f, 0.004995796f, 0.004676404f, 0.004380075f,
|
||||
0.004102000f, 0.003838453f, 0.003589099f, 0.003354219f,
|
||||
0.003134093f, 0.002929000f, 0.002738139f, 0.002559876f,
|
||||
0.002393244f, 0.002237275f, 0.002091000f, 0.001953587f,
|
||||
0.001824580f, 0.001703580f, 0.001590187f, 0.001484000f,
|
||||
0.001384496f, 0.001291268f, 0.001204092f, 0.001122744f,
|
||||
0.001047000f, 0.0009765896f, 0.0009111088f, 0.0008501332f,
|
||||
0.0007932384f, 0.0007400000f, 0.0006900827f, 0.0006433100f,
|
||||
0.0005994960f, 0.0005584547f, 0.0005200000f, 0.0004839136f,
|
||||
0.0004500528f, 0.0004183452f, 0.0003887184f, 0.0003611000f,
|
||||
0.0003353835f, 0.0003114404f, 0.0002891656f, 0.0002684539f,
|
||||
0.0002492000f, 0.0002313019f, 0.0002146856f, 0.0001992884f,
|
||||
0.0001850475f, 0.0001719000f, 0.0001597781f, 0.0001486044f,
|
||||
0.0001383016f, 0.0001287925f, 0.0001200000f, 0.0001118595f,
|
||||
0.0001043224f, 0.00009733560f, 0.00009084587f, 0.00008480000f,
|
||||
0.00007914667f, 0.00007385800f, 0.00006891600f, 0.00006430267f,
|
||||
0.00006000000f, 0.00005598187f, 0.00005222560f, 0.00004871840f,
|
||||
0.00004544747f, 0.00004240000f, 0.00003956104f, 0.00003691512f,
|
||||
0.00003444868f, 0.00003214816f, 0.00003000000f, 0.00002799125f,
|
||||
0.00002611356f, 0.00002436024f, 0.00002272461f, 0.00002120000f,
|
||||
0.00001977855f, 0.00001845285f, 0.00001721687f, 0.00001606459f,
|
||||
0.00001499000f, 0.00001398728f, 0.00001305155f, 0.00001217818f,
|
||||
0.00001136254f, 0.00001060000f, 0.000009885877f, 0.000009217304f,
|
||||
0.000008592362f, 0.000008009133f, 0.000007465700f, 0.000006959567f,
|
||||
0.000006487995f, 0.000006048699f, 0.000005639396f, 0.000005257800f,
|
||||
0.000004901771f, 0.000004569720f, 0.000004260194f, 0.000003971739f,
|
||||
0.000003702900f, 0.000003452163f, 0.000003218302f, 0.000003000300f,
|
||||
0.000002797139f, 0.000002607800f, 0.000002431220f, 0.000002266531f,
|
||||
0.000002113013f, 0.000001969943f, 0.000001836600f, 0.000001712230f,
|
||||
0.000001596228f, 0.000001488090f, 0.000001387314f, 0.000001293400f,
|
||||
0.000001205820f, 0.000001124143f, 0.000001048009f, 0.0000009770578f,
|
||||
0.0000009109300f, 0.0000008492513f, 0.0000007917212f, 0.0000007380904f,
|
||||
0.0000006881098f, 0.0000006415300f, 0.0000005980895f, 0.0000005575746f,
|
||||
0.0000005198080f, 0.0000004846123f, 0.0000004518100f
|
||||
0.000003917000, 0.000004393581, 0.000004929604, 0.000005532136,
|
||||
0.000006208245, 0.000006965000, 0.000007813219, 0.000008767336,
|
||||
0.000009839844, 0.00001104323, 0.00001239000, 0.00001388641,
|
||||
0.00001555728, 0.00001744296, 0.00001958375, 0.00002202000,
|
||||
0.00002483965, 0.00002804126, 0.00003153104, 0.00003521521,
|
||||
0.00003900000, 0.00004282640, 0.00004691460, 0.00005158960,
|
||||
0.00005717640, 0.00006400000, 0.00007234421, 0.00008221224,
|
||||
0.00009350816, 0.0001061361, 0.0001200000, 0.0001349840,
|
||||
0.0001514920, 0.0001702080, 0.0001918160, 0.0002170000,
|
||||
0.0002469067, 0.0002812400, 0.0003185200, 0.0003572667,
|
||||
0.0003960000, 0.0004337147, 0.0004730240, 0.0005178760,
|
||||
0.0005722187, 0.0006400000, 0.0007245600, 0.0008255000,
|
||||
0.0009411600, 0.001069880, 0.001210000, 0.001362091,
|
||||
0.001530752, 0.001720368, 0.001935323, 0.002180000,
|
||||
0.002454800, 0.002764000, 0.003117800, 0.003526400,
|
||||
0.004000000, 0.004546240, 0.005159320, 0.005829280,
|
||||
0.006546160, 0.007300000, 0.008086507, 0.008908720,
|
||||
0.009767680, 0.01066443, 0.01160000, 0.01257317,
|
||||
0.01358272, 0.01462968, 0.01571509, 0.01684000,
|
||||
0.01800736, 0.01921448, 0.02045392, 0.02171824,
|
||||
0.02300000, 0.02429461, 0.02561024, 0.02695857,
|
||||
0.02835125, 0.02980000, 0.03131083, 0.03288368,
|
||||
0.03452112, 0.03622571, 0.03800000, 0.03984667,
|
||||
0.04176800, 0.04376600, 0.04584267, 0.04800000,
|
||||
0.05024368, 0.05257304, 0.05498056, 0.05745872,
|
||||
0.06000000, 0.06260197, 0.06527752, 0.06804208,
|
||||
0.07091109, 0.07390000, 0.07701600, 0.08026640,
|
||||
0.08366680, 0.08723280, 0.09098000, 0.09491755,
|
||||
0.09904584, 0.1033674, 0.1078846, 0.1126000,
|
||||
0.1175320, 0.1226744, 0.1279928, 0.1334528,
|
||||
0.1390200, 0.1446764, 0.1504693, 0.1564619,
|
||||
0.1627177, 0.1693000, 0.1762431, 0.1835581,
|
||||
0.1912735, 0.1994180, 0.2080200, 0.2171199,
|
||||
0.2267345, 0.2368571, 0.2474812, 0.2586000,
|
||||
0.2701849, 0.2822939, 0.2950505, 0.3085780,
|
||||
0.3230000, 0.3384021, 0.3546858, 0.3716986,
|
||||
0.3892875, 0.4073000, 0.4256299, 0.4443096,
|
||||
0.4633944, 0.4829395, 0.5030000, 0.5235693,
|
||||
0.5445120, 0.5656900, 0.5869653, 0.6082000,
|
||||
0.6293456, 0.6503068, 0.6708752, 0.6908424,
|
||||
0.7100000, 0.7281852, 0.7454636, 0.7619694,
|
||||
0.7778368, 0.7932000, 0.8081104, 0.8224962,
|
||||
0.8363068, 0.8494916, 0.8620000, 0.8738108,
|
||||
0.8849624, 0.8954936, 0.9054432, 0.9148501,
|
||||
0.9237348, 0.9320924, 0.9399226, 0.9472252,
|
||||
0.9540000, 0.9602561, 0.9660074, 0.9712606,
|
||||
0.9760225, 0.9803000, 0.9840924, 0.9874812,
|
||||
0.9903128, 0.9928116, 0.9949501, 0.9967108,
|
||||
0.9980983, 0.9991120, 0.9997482, 1.0000000,
|
||||
0.9998567, 0.9993046, 0.9983255, 0.9968987,
|
||||
0.9950000, 0.9926005, 0.9897426, 0.9864444,
|
||||
0.9827241, 0.9786000, 0.9740837, 0.9691712,
|
||||
0.9638568, 0.9581349, 0.9520000, 0.9454504,
|
||||
0.9384992, 0.9311628, 0.9234576, 0.9154000,
|
||||
0.9070064, 0.8982772, 0.8892048, 0.8797816,
|
||||
0.8700000, 0.8598613, 0.8493920, 0.8386220,
|
||||
0.8275813, 0.8163000, 0.8047947, 0.7930820,
|
||||
0.7811920, 0.7691547, 0.7570000, 0.7447541,
|
||||
0.7324224, 0.7200036, 0.7074965, 0.6949000,
|
||||
0.6822192, 0.6694716, 0.6566744, 0.6438448,
|
||||
0.6310000, 0.6181555, 0.6053144, 0.5924756,
|
||||
0.5796379, 0.5668000, 0.5539611, 0.5411372,
|
||||
0.5283528, 0.5156323, 0.5030000, 0.4904688,
|
||||
0.4780304, 0.4656776, 0.4534032, 0.4412000,
|
||||
0.4290800, 0.4170360, 0.4050320, 0.3930320,
|
||||
0.3810000, 0.3689184, 0.3568272, 0.3447768,
|
||||
0.3328176, 0.3210000, 0.3093381, 0.2978504,
|
||||
0.2865936, 0.2756245, 0.2650000, 0.2547632,
|
||||
0.2448896, 0.2353344, 0.2260528, 0.2170000,
|
||||
0.2081616, 0.1995488, 0.1911552, 0.1829744,
|
||||
0.1750000, 0.1672235, 0.1596464, 0.1522776,
|
||||
0.1451259, 0.1382000, 0.1315003, 0.1250248,
|
||||
0.1187792, 0.1127691, 0.1070000, 0.1014762,
|
||||
0.09618864, 0.09112296, 0.08626485, 0.08160000,
|
||||
0.07712064, 0.07282552, 0.06871008, 0.06476976,
|
||||
0.06100000, 0.05739621, 0.05395504, 0.05067376,
|
||||
0.04754965, 0.04458000, 0.04175872, 0.03908496,
|
||||
0.03656384, 0.03420048, 0.03200000, 0.02996261,
|
||||
0.02807664, 0.02632936, 0.02470805, 0.02320000,
|
||||
0.02180077, 0.02050112, 0.01928108, 0.01812069,
|
||||
0.01700000, 0.01590379, 0.01483718, 0.01381068,
|
||||
0.01283478, 0.01192000, 0.01106831, 0.01027339,
|
||||
0.009533311, 0.008846157, 0.008210000, 0.007623781,
|
||||
0.007085424, 0.006591476, 0.006138485, 0.005723000,
|
||||
0.005343059, 0.004995796, 0.004676404, 0.004380075,
|
||||
0.004102000, 0.003838453, 0.003589099, 0.003354219,
|
||||
0.003134093, 0.002929000, 0.002738139, 0.002559876,
|
||||
0.002393244, 0.002237275, 0.002091000, 0.001953587,
|
||||
0.001824580, 0.001703580, 0.001590187, 0.001484000,
|
||||
0.001384496, 0.001291268, 0.001204092, 0.001122744,
|
||||
0.001047000, 0.0009765896, 0.0009111088, 0.0008501332,
|
||||
0.0007932384, 0.0007400000, 0.0006900827, 0.0006433100,
|
||||
0.0005994960, 0.0005584547, 0.0005200000, 0.0004839136,
|
||||
0.0004500528, 0.0004183452, 0.0003887184, 0.0003611000,
|
||||
0.0003353835, 0.0003114404, 0.0002891656, 0.0002684539,
|
||||
0.0002492000, 0.0002313019, 0.0002146856, 0.0001992884,
|
||||
0.0001850475, 0.0001719000, 0.0001597781, 0.0001486044,
|
||||
0.0001383016, 0.0001287925, 0.0001200000, 0.0001118595,
|
||||
0.0001043224, 0.00009733560, 0.00009084587, 0.00008480000,
|
||||
0.00007914667, 0.00007385800, 0.00006891600, 0.00006430267,
|
||||
0.00006000000, 0.00005598187, 0.00005222560, 0.00004871840,
|
||||
0.00004544747, 0.00004240000, 0.00003956104, 0.00003691512,
|
||||
0.00003444868, 0.00003214816, 0.00003000000, 0.00002799125,
|
||||
0.00002611356, 0.00002436024, 0.00002272461, 0.00002120000,
|
||||
0.00001977855, 0.00001845285, 0.00001721687, 0.00001606459,
|
||||
0.00001499000, 0.00001398728, 0.00001305155, 0.00001217818,
|
||||
0.00001136254, 0.00001060000, 0.000009885877, 0.000009217304,
|
||||
0.000008592362, 0.000008009133, 0.000007465700, 0.000006959567,
|
||||
0.000006487995, 0.000006048699, 0.000005639396, 0.000005257800,
|
||||
0.000004901771, 0.000004569720, 0.000004260194, 0.000003971739,
|
||||
0.000003702900, 0.000003452163, 0.000003218302, 0.000003000300,
|
||||
0.000002797139, 0.000002607800, 0.000002431220, 0.000002266531,
|
||||
0.000002113013, 0.000001969943, 0.000001836600, 0.000001712230,
|
||||
0.000001596228, 0.000001488090, 0.000001387314, 0.000001293400,
|
||||
0.000001205820, 0.000001124143, 0.000001048009, 0.0000009770578,
|
||||
0.0000009109300, 0.0000008492513, 0.0000007917212, 0.0000007380904,
|
||||
0.0000006881098, 0.0000006415300, 0.0000005980895, 0.0000005575746,
|
||||
0.0000005198080, 0.0000004846123, 0.0000004518100
|
||||
};
|
||||
|
||||
const Float CIE_Z_entries[CIE_samples] = {
|
||||
0.0006061000f, 0.0006808792f, 0.0007651456f, 0.0008600124f,
|
||||
0.0009665928f, 0.001086000f, 0.001220586f, 0.001372729f,
|
||||
0.001543579f, 0.001734286f, 0.001946000f, 0.002177777f,
|
||||
0.002435809f, 0.002731953f, 0.003078064f, 0.003486000f,
|
||||
0.003975227f, 0.004540880f, 0.005158320f, 0.005802907f,
|
||||
0.006450001f, 0.007083216f, 0.007745488f, 0.008501152f,
|
||||
0.009414544f, 0.01054999f, 0.01196580f, 0.01365587f,
|
||||
0.01558805f, 0.01773015f, 0.02005001f, 0.02251136f,
|
||||
0.02520288f, 0.02827972f, 0.03189704f, 0.03621000f,
|
||||
0.04143771f, 0.04750372f, 0.05411988f, 0.06099803f,
|
||||
0.06785001f, 0.07448632f, 0.08136156f, 0.08915364f,
|
||||
0.09854048f, 0.1102000f, 0.1246133f, 0.1417017f,
|
||||
0.1613035f, 0.1832568f, 0.2074000f, 0.2336921f,
|
||||
0.2626114f, 0.2947746f, 0.3307985f, 0.3713000f,
|
||||
0.4162091f, 0.4654642f, 0.5196948f, 0.5795303f,
|
||||
0.6456000f, 0.7184838f, 0.7967133f, 0.8778459f,
|
||||
0.9594390f, 1.0390501f, 1.1153673f, 1.1884971f,
|
||||
1.2581233f, 1.3239296f, 1.3856000f, 1.4426352f,
|
||||
1.4948035f, 1.5421903f, 1.5848807f, 1.6229600f,
|
||||
1.6564048f, 1.6852959f, 1.7098745f, 1.7303821f,
|
||||
1.7470600f, 1.7600446f, 1.7696233f, 1.7762637f,
|
||||
1.7804334f, 1.7826000f, 1.7829682f, 1.7816998f,
|
||||
1.7791982f, 1.7758671f, 1.7721100f, 1.7682589f,
|
||||
1.7640390f, 1.7589438f, 1.7524663f, 1.7441000f,
|
||||
1.7335595f, 1.7208581f, 1.7059369f, 1.6887372f,
|
||||
1.6692000f, 1.6475287f, 1.6234127f, 1.5960223f,
|
||||
1.5645280f, 1.5281000f, 1.4861114f, 1.4395215f,
|
||||
1.3898799f, 1.3387362f, 1.2876400f, 1.2374223f,
|
||||
1.1878243f, 1.1387611f, 1.0901480f, 1.0419000f,
|
||||
0.9941976f, 0.9473473f, 0.9014531f, 0.8566193f,
|
||||
0.8129501f, 0.7705173f, 0.7294448f, 0.6899136f,
|
||||
0.6521049f, 0.6162000f, 0.5823286f, 0.5504162f,
|
||||
0.5203376f, 0.4919673f, 0.4651800f, 0.4399246f,
|
||||
0.4161836f, 0.3938822f, 0.3729459f, 0.3533000f,
|
||||
0.3348578f, 0.3175521f, 0.3013375f, 0.2861686f,
|
||||
0.2720000f, 0.2588171f, 0.2464838f, 0.2347718f,
|
||||
0.2234533f, 0.2123000f, 0.2011692f, 0.1901196f,
|
||||
0.1792254f, 0.1685608f, 0.1582000f, 0.1481383f,
|
||||
0.1383758f, 0.1289942f, 0.1200751f, 0.1117000f,
|
||||
0.1039048f, 0.09666748f, 0.08998272f, 0.08384531f,
|
||||
0.07824999f, 0.07320899f, 0.06867816f, 0.06456784f,
|
||||
0.06078835f, 0.05725001f, 0.05390435f, 0.05074664f,
|
||||
0.04775276f, 0.04489859f, 0.04216000f, 0.03950728f,
|
||||
0.03693564f, 0.03445836f, 0.03208872f, 0.02984000f,
|
||||
0.02771181f, 0.02569444f, 0.02378716f, 0.02198925f,
|
||||
0.02030000f, 0.01871805f, 0.01724036f, 0.01586364f,
|
||||
0.01458461f, 0.01340000f, 0.01230723f, 0.01130188f,
|
||||
0.01037792f, 0.009529306f, 0.008749999f, 0.008035200f,
|
||||
0.007381600f, 0.006785400f, 0.006242800f, 0.005749999f,
|
||||
0.005303600f, 0.004899800f, 0.004534200f, 0.004202400f,
|
||||
0.003900000f, 0.003623200f, 0.003370600f, 0.003141400f,
|
||||
0.002934800f, 0.002749999f, 0.002585200f, 0.002438600f,
|
||||
0.002309400f, 0.002196800f, 0.002100000f, 0.002017733f,
|
||||
0.001948200f, 0.001889800f, 0.001840933f, 0.001800000f,
|
||||
0.001766267f, 0.001737800f, 0.001711200f, 0.001683067f,
|
||||
0.001650001f, 0.001610133f, 0.001564400f, 0.001513600f,
|
||||
0.001458533f, 0.001400000f, 0.001336667f, 0.001270000f,
|
||||
0.001205000f, 0.001146667f, 0.001100000f, 0.001068800f,
|
||||
0.001049400f, 0.001035600f, 0.001021200f, 0.001000000f,
|
||||
0.0009686400f, 0.0009299200f, 0.0008868800f, 0.0008425600f,
|
||||
0.0008000000f, 0.0007609600f, 0.0007236800f, 0.0006859200f,
|
||||
0.0006454400f, 0.0006000000f, 0.0005478667f, 0.0004916000f,
|
||||
0.0004354000f, 0.0003834667f, 0.0003400000f, 0.0003072533f,
|
||||
0.0002831600f, 0.0002654400f, 0.0002518133f, 0.0002400000f,
|
||||
0.0002295467f, 0.0002206400f, 0.0002119600f, 0.0002021867f,
|
||||
0.0001900000f, 0.0001742133f, 0.0001556400f, 0.0001359600f,
|
||||
0.0001168533f, 0.0001000000f, 0.00008613333f, 0.00007460000f,
|
||||
0.00006500000f, 0.00005693333f, 0.00004999999f, 0.00004416000f,
|
||||
0.00003948000f, 0.00003572000f, 0.00003264000f, 0.00003000000f,
|
||||
0.00002765333f, 0.00002556000f, 0.00002364000f, 0.00002181333f,
|
||||
0.00002000000f, 0.00001813333f, 0.00001620000f, 0.00001420000f,
|
||||
0.00001213333f, 0.00001000000f, 0.000007733333f, 0.000005400000f,
|
||||
0.000003200000f, 0.000001333333f, 0.000000000000f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f
|
||||
0.0006061000, 0.0006808792, 0.0007651456, 0.0008600124,
|
||||
0.0009665928, 0.001086000, 0.001220586, 0.001372729,
|
||||
0.001543579, 0.001734286, 0.001946000, 0.002177777,
|
||||
0.002435809, 0.002731953, 0.003078064, 0.003486000,
|
||||
0.003975227, 0.004540880, 0.005158320, 0.005802907,
|
||||
0.006450001, 0.007083216, 0.007745488, 0.008501152,
|
||||
0.009414544, 0.01054999, 0.01196580, 0.01365587,
|
||||
0.01558805, 0.01773015, 0.02005001, 0.02251136,
|
||||
0.02520288, 0.02827972, 0.03189704, 0.03621000,
|
||||
0.04143771, 0.04750372, 0.05411988, 0.06099803,
|
||||
0.06785001, 0.07448632, 0.08136156, 0.08915364,
|
||||
0.09854048, 0.1102000, 0.1246133, 0.1417017,
|
||||
0.1613035, 0.1832568, 0.2074000, 0.2336921,
|
||||
0.2626114, 0.2947746, 0.3307985, 0.3713000,
|
||||
0.4162091, 0.4654642, 0.5196948, 0.5795303,
|
||||
0.6456000, 0.7184838, 0.7967133, 0.8778459,
|
||||
0.9594390, 1.0390501, 1.1153673, 1.1884971,
|
||||
1.2581233, 1.3239296, 1.3856000, 1.4426352,
|
||||
1.4948035, 1.5421903, 1.5848807, 1.6229600,
|
||||
1.6564048, 1.6852959, 1.7098745, 1.7303821,
|
||||
1.7470600, 1.7600446, 1.7696233, 1.7762637,
|
||||
1.7804334, 1.7826000, 1.7829682, 1.7816998,
|
||||
1.7791982, 1.7758671, 1.7721100, 1.7682589,
|
||||
1.7640390, 1.7589438, 1.7524663, 1.7441000,
|
||||
1.7335595, 1.7208581, 1.7059369, 1.6887372,
|
||||
1.6692000, 1.6475287, 1.6234127, 1.5960223,
|
||||
1.5645280, 1.5281000, 1.4861114, 1.4395215,
|
||||
1.3898799, 1.3387362, 1.2876400, 1.2374223,
|
||||
1.1878243, 1.1387611, 1.0901480, 1.0419000,
|
||||
0.9941976, 0.9473473, 0.9014531, 0.8566193,
|
||||
0.8129501, 0.7705173, 0.7294448, 0.6899136,
|
||||
0.6521049, 0.6162000, 0.5823286, 0.5504162,
|
||||
0.5203376, 0.4919673, 0.4651800, 0.4399246,
|
||||
0.4161836, 0.3938822, 0.3729459, 0.3533000,
|
||||
0.3348578, 0.3175521, 0.3013375, 0.2861686,
|
||||
0.2720000, 0.2588171, 0.2464838, 0.2347718,
|
||||
0.2234533, 0.2123000, 0.2011692, 0.1901196,
|
||||
0.1792254, 0.1685608, 0.1582000, 0.1481383,
|
||||
0.1383758, 0.1289942, 0.1200751, 0.1117000,
|
||||
0.1039048, 0.09666748, 0.08998272, 0.08384531,
|
||||
0.07824999, 0.07320899, 0.06867816, 0.06456784,
|
||||
0.06078835, 0.05725001, 0.05390435, 0.05074664,
|
||||
0.04775276, 0.04489859, 0.04216000, 0.03950728,
|
||||
0.03693564, 0.03445836, 0.03208872, 0.02984000,
|
||||
0.02771181, 0.02569444, 0.02378716, 0.02198925,
|
||||
0.02030000, 0.01871805, 0.01724036, 0.01586364,
|
||||
0.01458461, 0.01340000, 0.01230723, 0.01130188,
|
||||
0.01037792, 0.009529306, 0.008749999, 0.008035200,
|
||||
0.007381600, 0.006785400, 0.006242800, 0.005749999,
|
||||
0.005303600, 0.004899800, 0.004534200, 0.004202400,
|
||||
0.003900000, 0.003623200, 0.003370600, 0.003141400,
|
||||
0.002934800, 0.002749999, 0.002585200, 0.002438600,
|
||||
0.002309400, 0.002196800, 0.002100000, 0.002017733,
|
||||
0.001948200, 0.001889800, 0.001840933, 0.001800000,
|
||||
0.001766267, 0.001737800, 0.001711200, 0.001683067,
|
||||
0.001650001, 0.001610133, 0.001564400, 0.001513600,
|
||||
0.001458533, 0.001400000, 0.001336667, 0.001270000,
|
||||
0.001205000, 0.001146667, 0.001100000, 0.001068800,
|
||||
0.001049400, 0.001035600, 0.001021200, 0.001000000,
|
||||
0.0009686400, 0.0009299200, 0.0008868800, 0.0008425600,
|
||||
0.0008000000, 0.0007609600, 0.0007236800, 0.0006859200,
|
||||
0.0006454400, 0.0006000000, 0.0005478667, 0.0004916000,
|
||||
0.0004354000, 0.0003834667, 0.0003400000, 0.0003072533,
|
||||
0.0002831600, 0.0002654400, 0.0002518133, 0.0002400000,
|
||||
0.0002295467, 0.0002206400, 0.0002119600, 0.0002021867,
|
||||
0.0001900000, 0.0001742133, 0.0001556400, 0.0001359600,
|
||||
0.0001168533, 0.0001000000, 0.00008613333, 0.00007460000,
|
||||
0.00006500000, 0.00005693333, 0.00004999999, 0.00004416000,
|
||||
0.00003948000, 0.00003572000, 0.00003264000, 0.00003000000,
|
||||
0.00002765333, 0.00002556000, 0.00002364000, 0.00002181333,
|
||||
0.00002000000, 0.00001813333, 0.00001620000, 0.00001420000,
|
||||
0.00001213333, 0.00001000000, 0.000007733333, 0.000005400000,
|
||||
0.000003200000, 0.000001333333, 0.000000000000, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0
|
||||
};
|
||||
|
||||
const Float RGB2Spec_wavelengths[RGB2Spec_samples] = {
|
||||
|
|
|
@ -286,6 +286,18 @@ void SceneHandler::endElement(const XMLCh* const xmlName) {
|
|||
|
||||
context.parent->properties.setPoint(context.attributes["name"], Point(x, y, z));
|
||||
} else if (name == "rgb") {
|
||||
Spectrum::EConversionIntent intent = Spectrum::EReflectance;
|
||||
if (context.attributes.find("intent") != context.attributes.end()) {
|
||||
std::string intentString = boost::to_lower_copy(context.attributes["intent"]);
|
||||
if (intentString == "reflectance")
|
||||
intent = Spectrum::EReflectance;
|
||||
else if (intentString == "illuminant")
|
||||
intent = Spectrum::EIlluminant;
|
||||
else
|
||||
SLog(EError, "Invalid intent \"%s\", must be "
|
||||
"\"reflectance\" or \"illuminant\"", intentString.c_str());
|
||||
}
|
||||
|
||||
std::string valueStr = context.attributes["value"];
|
||||
std::vector<std::string> tokens = tokenize(valueStr, ", ");
|
||||
Float value[3];
|
||||
|
@ -308,7 +320,7 @@ void SceneHandler::endElement(const XMLCh* const xmlName) {
|
|||
XMLLog(EError, "Invalid RGB value specified");
|
||||
}
|
||||
Spectrum specValue;
|
||||
specValue.fromLinearRGB(value[0], value[1], value[2]);
|
||||
specValue.fromLinearRGB(value[0], value[1], value[2], intent);
|
||||
context.parent->properties.setSpectrum(context.attributes["name"],
|
||||
specValue);
|
||||
} else if (name == "srgb") {
|
||||
|
|
|
@ -48,6 +48,16 @@ void TestCase::assertEqualsImpl(Float expected, Float actual, Float epsilon, con
|
|||
"expected floating point value %f, got %f.", expected, actual);
|
||||
}
|
||||
|
||||
void TestCase::assertEqualsImpl(const Spectrum &expected, const Spectrum &actual, Float epsilon, const char *file, int line) {
|
||||
bool match = true;
|
||||
for (int i=0; i<SPECTRUM_SAMPLES; ++i)
|
||||
if (std::abs(expected[i]-actual[i]) > epsilon)
|
||||
match = false;
|
||||
if (!match)
|
||||
Thread::getThread()->getLogger()->log(EError, NULL, file, line, "Assertion failure: "
|
||||
"expected vector %s, got %s.", expected.toString().c_str(), actual.toString().c_str());
|
||||
}
|
||||
|
||||
void TestCase::assertEqualsImpl(const Vector2 &expected, const Vector2 &actual, Float epsilon, const char *file, int line) {
|
||||
bool match = true;
|
||||
for (int i=0; i<2; ++i)
|
||||
|
@ -58,6 +68,7 @@ void TestCase::assertEqualsImpl(const Vector2 &expected, const Vector2 &actual,
|
|||
"expected vector %s, got %s.", expected.toString().c_str(), actual.toString().c_str());
|
||||
}
|
||||
|
||||
|
||||
void TestCase::assertEqualsImpl(const Point2 &expected, const Point2 &actual, Float epsilon, const char *file, int line) {
|
||||
bool match = true;
|
||||
for (int i=0; i<2; ++i)
|
||||
|
|
|
@ -71,7 +71,7 @@ void help() {
|
|||
cout << " -v Be more verbose" << endl << endl;
|
||||
cout << " -w Treat warnings as errors" << endl << endl;
|
||||
cout << " -z Disable progress bars" << endl << endl;
|
||||
cout << " The README file included with the distribution contains further information." << endl;
|
||||
cout << " For documentation, please refer to http://www.mitsuba-renderer.org/docs.html" << endl;
|
||||
}
|
||||
|
||||
ref<RenderQueue> renderQueue = NULL;
|
||||
|
|
|
@ -180,7 +180,7 @@ int ubi_main(int argc, char **argv) {
|
|||
cout << " To listen on stdin, specify \"-ls\" (implies -q)" << endl << endl;
|
||||
cout << " -n name Assign a node name to this instance (Default: host name)" << endl << endl;
|
||||
cout << " -v Be more verbose" << endl << endl;
|
||||
cout << " The README file included with the distribution contains further information." << endl;
|
||||
cout << " For documentation, please refer to http://www.mitsuba-renderer.org/docs.html" << endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,8 @@ void help() {
|
|||
}
|
||||
}
|
||||
|
||||
cout << testcases.str() << utilities.str();
|
||||
cout << testcases.str() << utilities.str() << endl;
|
||||
cout << " For documentation, please refer to http://www.mitsuba-renderer.org/docs.html" << endl << endl;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
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/render/testcase.h>
|
||||
#include <mitsuba/core/bitmap.h>
|
||||
#include <mitsuba/core/fstream.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
class TestSpectrum : public TestCase {
|
||||
public:
|
||||
MTS_BEGIN_TESTCASE()
|
||||
MTS_DECLARE_TEST(test01_spectrum)
|
||||
MTS_DECLARE_TEST(test02_interpolatedSpectrum)
|
||||
MTS_DECLARE_TEST(test03_blackBody)
|
||||
MTS_END_TESTCASE()
|
||||
|
||||
void test01_spectrum() {
|
||||
#if SPECTRUM_SAMPLES > 3
|
||||
Spectrum spec(0.0f);
|
||||
Float binStart = Spectrum::getBinCoverage(2).first;
|
||||
Float binEnd = Spectrum::getBinCoverage(2).second;
|
||||
|
||||
spec[2] = 1.0f;
|
||||
assertEquals(spec.eval(binStart+Epsilon), 1.0f);
|
||||
assertEquals(spec.eval(binEnd-Epsilon), 1.0f);
|
||||
assertEquals(spec.eval(binStart-Epsilon), 0.0f);
|
||||
assertEquals(spec.eval(binEnd+Epsilon), 0.0f);
|
||||
#endif
|
||||
|
||||
assertEqualsEpsilon(Spectrum(1.0f).getLuminance(), 1.0f, 1e-5f);
|
||||
|
||||
#if SPECTRUM_SAMPLES == 30
|
||||
/* Verify against the implementation in PBRT */
|
||||
Spectrum test;
|
||||
Float r, g, b;
|
||||
test.fromLinearRGB(0.1f, 0.2f, 0.3f, Spectrum::EReflectance);
|
||||
test.toLinearRGB(r, g, b);
|
||||
assertEqualsEpsilon(r, 0.124274f, 1e-5f);
|
||||
assertEqualsEpsilon(g, 0.190133f, 1e-5f);
|
||||
assertEqualsEpsilon(b, 0.270029f, 1e-5f);
|
||||
test.fromLinearRGB(0.1f, 0.2f, 0.3f, Spectrum::EIlluminant);
|
||||
test.toLinearRGB(r, g, b);
|
||||
assertEqualsEpsilon(r, 0.0961602f, 1e-5f);
|
||||
assertEqualsEpsilon(g, 0.184446f, 1e-5f);
|
||||
assertEqualsEpsilon(b, 0.273519f, 1e-5f);
|
||||
#elif SPECTRUM_SAMPLES == 3
|
||||
Spectrum test;
|
||||
Float x, y, z;
|
||||
test.fromXYZ(0.1f, 0.2f, 0.3f);
|
||||
test.toXYZ(x, y, z);
|
||||
assertEqualsEpsilon(x, 0.1, 1e-5f);
|
||||
assertEqualsEpsilon(y, 0.2, 1e-5f);
|
||||
assertEqualsEpsilon(z, 0.3, 1e-5f);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test02_interpolatedSpectrum() {
|
||||
/* Test the interpolated spectrum
|
||||
evaluation and integration routines */
|
||||
InterpolatedSpectrum spec;
|
||||
|
||||
spec.append(500, 1);
|
||||
spec.append(700, 2);
|
||||
spec.append(800, 3);
|
||||
|
||||
InterpolatedSpectrum spec2 = spec;
|
||||
|
||||
assertEquals(spec.eval(499), 0.0f);
|
||||
assertEquals(spec.eval(500), 1.0f);
|
||||
assertEquals(spec.eval(600), 1.5f);
|
||||
assertEquals(spec.eval(700), 2.0f);
|
||||
assertEquals(spec.eval(750), 2.5f);
|
||||
assertEquals(spec.eval(800), 3.0f);
|
||||
assertEquals(spec.eval(801), 0.0f);
|
||||
assertEqualsEpsilon(spec.average(0, 1000), 550.0f/1000.0f, 1e-6f);
|
||||
assertEqualsEpsilon(spec.average(550, 551), 1.2525f, 1e-6f);
|
||||
|
||||
spec2.zeroExtend();
|
||||
assertEquals(spec2.eval(500.0f-150.0f), 0.0f);
|
||||
assertEquals(spec2.eval(500.0f-150.0f/2.0f), 0.5f);
|
||||
|
||||
spec2.clear();
|
||||
spec2.append(0, 1);
|
||||
spec2.append(1000, 1);
|
||||
Spectrum spec3;
|
||||
spec3.fromContinuousSpectrum(spec2);
|
||||
#if SPECTRUM_SAMPLES > 3
|
||||
assertEqualsEpsilon(spec3, Spectrum(1.0f), 1e-5f);
|
||||
#endif
|
||||
Float x, y, z;
|
||||
spec3.toXYZ(x, y, z);
|
||||
assertEqualsEpsilon(x, 1.0f, 1e-3f);
|
||||
assertEqualsEpsilon(y, 1.0f, 1e-3f);
|
||||
assertEqualsEpsilon(z, 1.0f, 1e-3f);
|
||||
|
||||
#if SPECTRUM_SAMPLES > 3
|
||||
spec2.clear();
|
||||
spec2.append(Spectrum::getBinCoverage(0).first, 0);
|
||||
spec2.append(Spectrum::getBinCoverage(1).first, 1);
|
||||
spec2.append(Spectrum::getBinCoverage(2).first, 1);
|
||||
spec2.append(Spectrum::getBinCoverage(2).second, 0);
|
||||
spec3.fromContinuousSpectrum(spec2);
|
||||
Spectrum spec4(0.0f);
|
||||
|
||||
spec4[0] = 0.5f;
|
||||
spec4[1] = 1.0f;
|
||||
spec4[2] = 0.5f;
|
||||
assertEqualsEpsilon(spec3, spec4, 1e-5f);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test03_blackBody() {
|
||||
/* Spot-check a 5000 Kelvin spectrum against values obtained at
|
||||
https://www.sensiac.org/external/resources/calculators/infrared_radiance_calculator.jsf
|
||||
|
||||
Mitsuba uses units of W * m^-2 * sr^-1 * nm^-1, whereas that
|
||||
page uses W * cm^-2 * sr^-1 * um^-1 --- this is the reason for
|
||||
the factor of 10-difference.
|
||||
*/
|
||||
BlackBodySpectrum spec(5000);
|
||||
assertEqualsEpsilon(spec.eval(400)/10, 874, .5f);
|
||||
assertEqualsEpsilon(spec.eval(500)/10, 1211, .5f);
|
||||
assertEqualsEpsilon(spec.eval(600)/10, 1276, .5f);
|
||||
assertEqualsEpsilon(spec.eval(2000)/10, 115.8f, .5f);
|
||||
assertEqualsEpsilon(spec.average(100, 1000) * .09f, 715, 1);
|
||||
}
|
||||
};
|
||||
|
||||
MTS_EXPORT_TESTCASE(TestSpectrum, "Testcase for manipulating spectral data")
|
||||
MTS_NAMESPACE_END
|
Loading…
Reference in New Issue