preliminary sun/sky model implementation
parent
b605c5e937
commit
93217958fb
Binary file not shown.
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 184 KiB |
|
@ -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')
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue