preliminary sun/sky model implementation

metadata
Wenzel Jakob 2011-07-29 02:39:40 +02:00
parent b605c5e937
commit 93217958fb
6 changed files with 178 additions and 25 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 184 KiB

View File

@ -8,6 +8,7 @@ plugins += env.SharedLibrary('point', ['point.cpp'])
plugins += env.SharedLibrary('collimated', ['collimated.cpp'])
plugins += env.SharedLibrary('directional', ['directional.cpp'])
plugins += env.SharedLibrary('sky', ['sky.cpp'])
plugins += env.SharedLibrary('sun', ['sun.cpp'])
plugins += env.SharedLibrary('sunsky', ['sunsky.cpp'])
Export('plugins')

View File

@ -128,6 +128,8 @@ public:
}
m_pdfPixelSize = Vector2(2 * M_PI / m_pdfResolution.x, M_PI / m_pdfResolution.y);
m_pdf.build();
if (m_pdf.getOriginalSum() == 0)
Log(EError, "Error -- environment map does not contain any nonzero pixels!");
}
void preprocess(const Scene *scene) {

View File

@ -164,8 +164,8 @@ class SkyLuminaire : public Luminaire {
public:
SkyLuminaire(const Properties &props)
: Luminaire(props) {
m_intensityScale = props.getFloat("intensityScale", Float(1.0));
m_turbidity = props.getFloat("turbidity", Float(3.0));
m_intensityScale = props.getFloat("intensityScale", 1.0f);
m_turbidity = props.getFloat("turbidity", 3.0f);
if (m_turbidity < 1 || m_turbidity > 30)
Log(EError, "The turbidity parameter must be in the range [1,30]!");
@ -288,6 +288,11 @@ public:
return luminaire;
}
Spectrum Le(const Ray &ray) const {
Point2 coords = fromSphere(ray.d);
return getSkySpectralRadiance(coords.x, coords.y) * m_intensityScale;
}
std::string toString() const {
std::ostringstream oss;
oss << "SkyLuminaire[" << endl

View File

@ -75,8 +75,8 @@ Point2 configureSunPosition(Float lat, Float lon, int stdMrd,
-solarAzimuth);
}
Point2 configureSunPosition(const Vector& sunDir, const Transform &luminaireToWorld) {
return fromSphere(normalize(luminaireToWorld(sunDir)));
Point2 configureSunPosition(const Vector& sunDir, const Transform &worldToLuminaire) {
return fromSphere(normalize(worldToLuminaire(sunDir)));
}
Point2 configureSunPosition(const Properties &props) {
@ -90,7 +90,7 @@ Point2 configureSunPosition(const Properties &props) {
return configureSunPosition(
props.getVector("sunDirection"),
props.getTransform("toWorld", Transform()));
props.getTransform("toWorld", Transform()).inverse());
} else {
Float lat = props.getFloat("latitude", 35.6894f);
Float lon = props.getFloat("longitude", 139.6917f);
@ -108,6 +108,126 @@ Point2 configureSunPosition(const Properties &props) {
}
}
/* All data lifted from MI */
/* Units are either [] or cm^-1. refer when in doubt MI */
// k_o Spectrum table from pg 127, MI.
Float k_oWavelengths[64] = {
300, 305, 310, 315, 320, 325, 330, 335, 340, 345,
350, 355, 445, 450, 455, 460, 465, 470, 475, 480,
485, 490, 495, 500, 505, 510, 515, 520, 525, 530,
535, 540, 545, 550, 555, 560, 565, 570, 575, 580,
585, 590, 595, 600, 605, 610, 620, 630, 640, 650,
660, 670, 680, 690, 700, 710, 720, 730, 740, 750,
760, 770, 780, 790,
};
Float k_oAmplitudes[65] = {
10.0, 4.8, 2.7, 1.35, .8, .380, .160, .075, .04, .019, .007,
.0, .003, .003, .004, .006, .008, .009, .012, .014, .017,
.021, .025, .03, .035, .04, .045, .048, .057, .063, .07,
.075, .08, .085, .095, .103, .110, .12, .122, .12, .118,
.115, .12, .125, .130, .12, .105, .09, .079, .067, .057,
.048, .036, .028, .023, .018, .014, .011, .010, .009,
.007, .004, .0, .0
};
// k_g Spectrum table from pg 130, MI.
Float k_gWavelengths[4] = {
759, 760, 770, 771
};
Float k_gAmplitudes[4] = {
0, 3.0, 0.210, 0
};
// k_wa Spectrum table from pg 130, MI.
Float k_waWavelengths[13] = {
689, 690, 700, 710, 720,
730, 740, 750, 760, 770,
780, 790, 800
};
Float k_waAmplitudes[13] = {
0, 0.160e-1, 0.240e-1, 0.125e-1,
0.100e+1, 0.870, 0.610e-1, 0.100e-2,
0.100e-4, 0.100e-4, 0.600e-3,
0.175e-1, 0.360e-1
};
Float solWavelengths[38] = {
380, 390, 400, 410, 420, 430, 440, 450,
460, 470, 480, 490, 500, 510, 520, 530,
540, 550, 560, 570, 580, 590, 600, 610,
620, 630, 640, 650, 660, 670, 680, 690,
700, 710, 720, 730, 740, 750
};
Float solAmplitudes[38] = {
165.5, 162.3, 211.2, 258.8, 258.2,
242.3, 267.6, 296.6, 305.4, 300.6,
306.6, 288.3, 287.1, 278.2, 271.0,
272.3, 263.6, 255.0, 250.6, 253.1,
253.5, 251.3, 246.3, 241.7, 236.8,
232.1, 228.2, 223.4, 219.7, 215.3,
211.0, 207.3, 202.4, 198.7, 194.3,
190.7, 186.3, 182.6
};
Spectrum computeSunRadiance(Float theta, Float turbidity) {
InterpolatedSpectrum k_oCurve(k_oWavelengths, k_oAmplitudes, 64);
InterpolatedSpectrum k_gCurve(k_gWavelengths, k_gAmplitudes, 4);
InterpolatedSpectrum k_waCurve(k_waWavelengths, k_waAmplitudes, 13);
InterpolatedSpectrum solCurve(solWavelengths, solAmplitudes, 38);
Float data[91], wavelengths[91]; // (800 - 350) / 5 + 1
Float beta = 0.04608365822050f * turbidity - 0.04586025928522f;
Float m = 1.0f/(std::cos(theta) + 0.15f*std::pow(93.885f-theta/M_PI*180.0f, (Float) -1.253f)); // Relative Optical Mass
Float lambda;
int i;
for(i = 0, lambda = 350; i < 91; i++, lambda+=5) {
// Rayleigh Scattering
// Results agree with the graph (pg 115, MI) */
Float tauR = std::exp(-m * 0.008735f * std::pow(lambda/1000.0f, (Float) -4.08));
// Aerosal (water + dust) attenuation
// beta - amount of aerosols present
// alpha - ratio of small to large particle sizes. (0:4,usually 1.3)
// Results agree with the graph (pg 121, MI)
const Float alpha = 1.3f;
Float tauA = exp(-m * beta * std::pow(lambda/1000.0f, -alpha)); // lambda should be in um
// Attenuation due to ozone absorption
// lOzone - amount of ozone in cm(NTP)
// Results agree with the graph (pg 128, MI)
const Float lOzone = .35f;
Float tauO = std::exp(-m * k_oCurve.eval(lambda) * lOzone);
// Attenuation due to mixed gases absorption
// Results agree with the graph (pg 131, MI)
Float tauG = std::exp(-1.41f * k_gCurve.eval(lambda) * m / std::pow(1 + 118.93f
* k_gCurve.eval(lambda) * m, (Float) 0.45f));
// Attenuation due to water vapor absorbtion
// w - precipitable water vapor in centimeters (standard = 2)
// Results agree with the graph (pg 132, MI)
const Float w = 2.0;
Float tauWA = std::exp(-0.2385f * k_waCurve.eval(lambda) * w * m /
std::pow(1 + 20.07f * k_waCurve.eval(lambda) * w * m, 0.45f));
data[i] = 100.0f * solCurve.eval(lambda) * tauR * tauA * tauO * tauG * tauWA;
wavelengths[i] = lambda;
}
InterpolatedSpectrum interpolated(wavelengths, data, 91);
Spectrum discretized;
discretized.fromContinuousSpectrum(interpolated);
discretized *= 300;
return discretized;
}
MTS_NAMESPACE_END
#endif /* __SUN_H */

View File

@ -18,6 +18,9 @@
#include <mitsuba/render/scene.h>
#include <mitsuba/core/plugin.h>
#include <mitsuba/core/bitmap.h>
#include <mitsuba/core/fstream.h>
#include "sun.h"
MTS_NAMESPACE_BEGIN
@ -80,38 +83,64 @@ public:
: Luminaire(_props) {
Properties props(_props);
props.setPluginName("sun");
m_sun = static_cast<Luminaire *>(
ref<Luminaire> sun = static_cast<Luminaire *>(
PluginManager::getInstance()->createObject(
MTS_CLASS(Luminaire), props));
sun->configure();
props.setPluginName("sky");
m_sky = static_cast<Luminaire *>(
ref<Luminaire> sky = static_cast<Luminaire *>(
PluginManager::getInstance()->createObject(
MTS_CLASS(Luminaire), props));
sky->configure();
int resolution = props.getInteger("resolution", 512);
int thetaBins = resolution, phiBins = resolution*2;
/* Avoid unused parameter warnings */
std::vector<std::string> propNames;
props.putPropertyNames(propNames);
for (size_t i=0; i<propNames.size(); ++i)
if (props.wasQueried(propNames[i]))
_props.markQueried(propNames[i]);
ref<Bitmap> bitmap = new Bitmap(phiBins, thetaBins, 128);
Point2 factor(M_PI / thetaBins, (2*M_PI) / phiBins);
float *target = bitmap->getFloatData();
for (int i=0; i<thetaBins; ++i) {
Float theta = (i+.5f)*factor.x;
for (int j=0; j<phiBins; ++j) {
Float phi = (j+.5f)*factor.y;
Vector d = toSphere(theta, phi);
Ray ray(Point(0.0f), d, 0.0f);
Spectrum s = sun->Le(ray) + sky->Le(ray);
Float r, g, b;
s.toLinearRGB(r, g, b);
*target++ = r; *target++ = g;
*target++ = b; *target++ = 1;
}
}
/* Instantiate a nested envmap plugin */
Properties envProps("envmap");
Properties::Data bitmapData;
bitmapData.ptr = (uint8_t *) bitmap.get();
bitmapData.size = sizeof(Bitmap);
envProps.setData("bitmap", bitmapData);
envProps.setTransform("toWorld", m_luminaireToWorld);
envProps.setFloat("samplingWeight", m_samplingWeight);
m_luminaire = static_cast<Luminaire *>(
PluginManager::getInstance()->createObject(
MTS_CLASS(Luminaire), envProps));
ref<FileStream> fs = new FileStream("test.exr", FileStream::ETruncReadWrite);
bitmap->save(Bitmap::EEXR, fs);
}
SunSkyLuminaire(Stream *stream, InstanceManager *manager)
: Luminaire(stream, manager) {
m_sun = static_cast<Luminaire *>(manager->getInstance(stream));
m_sky = static_cast<Luminaire *>(manager->getInstance(stream));
m_luminaire = static_cast<Luminaire *>(manager->getInstance(stream));
}
void serialize(Stream *stream, InstanceManager *manager) {
Luminaire::serialize(stream, manager);
manager->serialize(stream, m_sun.get());
manager->serialize(stream, m_sky.get());
manager->serialize(stream, m_luminaire.get());
}
void configure() {
Luminaire::configure();
m_sun->configure();
m_sky->configure();
m_luminaire->configure();
}
bool isCompound() const {
@ -120,18 +149,14 @@ public:
Luminaire *getElement(int i) {
if (i == 0)
return m_sun;
else if (i == 1)
return m_sky;
return m_luminaire;
else
return NULL;
}
MTS_DECLARE_CLASS()
private:
Properties m_props;
ref<Luminaire> m_sun;
ref<Luminaire> m_sky;
ref<Luminaire> m_luminaire;
};
MTS_IMPLEMENT_CLASS_S(SunSkyLuminaire, false, Luminaire)