Skip to content

Commit

Permalink
Add atmospheric mixing and extinction handling to Toast Survey (Stell…
Browse files Browse the repository at this point in the history
…arium#158)

This is a bit more optimistic than MilkyWay, given that DSS itself is more than the eye can see. But we have a bit of extinction, and brightness dimming in twilight/daylight sky now.
  • Loading branch information
gzotti authored May 20, 2018
1 parent a715fba commit 646880f
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 23 deletions.
95 changes: 80 additions & 15 deletions src/core/StelToast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@
#include "StelApp.hpp"
#include "StelCore.hpp"
#include "StelPainter.hpp"
#include "StelSkyDrawer.hpp"
#include "StelModuleMgr.hpp"
#include "RefractionExtinction.hpp"
#include "StelTexture.hpp"
#include "StelTextureMgr.hpp"
#include "StelToast.hpp"
#include "LandscapeMgr.hpp"

#include <QTimeLine>

Expand Down Expand Up @@ -101,10 +105,13 @@ bool ToastTile::isCovered(const SphericalCap& viewportShape) const
}


void ToastTile::prepareDraw()
void ToastTile::prepareDraw(Vec3f color)
{
Q_ASSERT(!empty);

StelSkyDrawer *drawer=StelApp::getInstance().getCore()->getSkyDrawer();
const bool withExtinction=(drawer->getFlagHasAtmosphere() && drawer->getExtinction().getExtinctionCoefficient()>=0.01f);

if (texture.isNull())
{
//qDebug() << "load texture" << imagePath;
Expand All @@ -127,7 +134,38 @@ void ToastTile::prepareDraw()
vertexArray = getGrid()->getVertexArray(level, x, y, ml);
textureArray = getGrid()->getTextureArray(level, x, y, ml);
indexArray = getGrid()->getTrianglesIndex(level, x, y, ml);
colorArray.clear();
for (int i=0; i<vertexArray.size(); ++i)
colorArray.append(color);
}
// Recreate the color array in any case. Assume we must compute extinction on every frame.
if (withExtinction)
{
StelCore *core=StelApp::getInstance().getCore();
// We must process the vertices to find geometric altitudes in order to compute vertex colors.
const Extinction& extinction=drawer->getExtinction();
colorArray.clear();

for (int i=0; i<vertexArray.size(); ++i)
{
Vec3d vertAltAz=core->j2000ToAltAz(vertexArray.at(i), StelCore::RefractionOn);
Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001);

float oneMag=0.0f;
extinction.forward(vertAltAz, &oneMag);
// drop of one magnitude: should be factor 2.5 or 40%. We take 70% to keep it more visible.
// Also, for Toast, we do not observe Bortle as for the default MilkyWay.
float extinctionFactor=std::pow(0.7f , oneMag);
Vec3f thisColor=Vec3f(color[0]*extinctionFactor, color[1]*extinctionFactor, color[2]*extinctionFactor);
colorArray.append(thisColor);
}

}
else
{
colorArray.fill(Vec3f(1.0f));
}


if (subTiles.isEmpty() && level < getSurvey()->getMaxLevel())
{
Expand All @@ -151,10 +189,9 @@ void ToastTile::prepareDraw()
}


void ToastTile::drawTile(StelPainter* sPainter)
void ToastTile::drawTile(StelPainter* sPainter, Vec3f color)
{
if (!prepared)
prepareDraw();
prepareDraw(color);

// Still not ready
if (texture.isNull() || !texture->bind())
Expand All @@ -170,19 +207,16 @@ void ToastTile::drawTile(StelPainter* sPainter)
if (texFader.state()==QTimeLine::Running)
{
sPainter->setBlending(true);
sPainter->setColor(1,1,1, texFader.currentValue());
}
else
{
sPainter->setBlending(false);
sPainter->setColor(1, 1, 1, 1);
}

Q_ASSERT(vertexArray.size() == textureArray.size());

sPainter->setCullFace(true);
// sPainter.drawArrays(GL_TRIANGLES, vertexArray.size(), vertexArray.data(), textureArray.data(), Q_NULLPTR, Q_NULLPTR, indexArray.size(), indexArray.constData());
sPainter->setArrays(vertexArray.constData(), textureArray.constData());
sPainter->setArrays(vertexArray.constData(), textureArray.constData(), colorArray.constData());
sPainter->drawFromArray(StelPainter::Triangles, indexArray.size(), 0, true, indexArray.constData());

// SphericalConvexPolygon poly(getGrid()->getPolygon(level, x, y));
Expand All @@ -191,7 +225,7 @@ void ToastTile::drawTile(StelPainter* sPainter)
}


void ToastTile::draw(StelPainter* sPainter, const SphericalCap& viewportShape, int maxVisibleLevel)
void ToastTile::draw(StelPainter* sPainter, const SphericalCap& viewportShape, int maxVisibleLevel, Vec3f color)
{
if (!isVisible(viewportShape, maxVisibleLevel))
{
Expand All @@ -209,26 +243,27 @@ void ToastTile::draw(StelPainter* sPainter, const SphericalCap& viewportShape, i
return;
}
if (level==maxVisibleLevel || !isCovered(viewportShape))
drawTile(sPainter);
drawTile(sPainter, color);

// Draw all the children
foreach (ToastTile* child, subTiles)
{
child->draw(sPainter, viewportShape, maxVisibleLevel);
child->draw(sPainter, viewportShape, maxVisibleLevel, color);
}
}

/////// ToastSurvey methods ////////////
ToastSurvey::ToastSurvey(const QString& path, int amaxLevel)
: path(path), maxLevel(amaxLevel), toastCache(200)
: grid(Q_NULLPTR), path(path), rootTile(Q_NULLPTR), maxLevel(amaxLevel), toastCache(200)
{
}

ToastSurvey::~ToastSurvey()
{
delete rootTile;
delete grid;
rootTile = Q_NULLPTR;
delete grid;
grid = Q_NULLPTR;
}


Expand All @@ -255,9 +290,39 @@ void ToastSurvey::draw(StelPainter* sPainter)
if (!grid) grid = new ToastGrid(maxLevel);
if (!rootTile) rootTile = new ToastTile(this, 0, 0, 0);

// We also get the viewport shape to discard invisibly tiles.
// Compute global brightness depending on sky/atmosphere. (taken from MilkyWay, but without extra Bortle stuff)
StelCore *core=StelApp::getInstance().getCore();
StelSkyDrawer *drawer=core->getSkyDrawer();
const bool withExtinction=(drawer->getFlagHasAtmosphere() && drawer->getExtinction().getExtinctionCoefficient()>=0.01f);
Vec3f color(1.0f);

if (withExtinction)
{
const float lum = drawer->surfaceBrightnessToLuminance(12.f); // How to calibrate the DSS texture?

// Get the luminance scaled between 0 and 1
StelToneReproducer* eye = core->getToneReproducer();
float aLum =eye->adaptLuminanceScaled(lum);

// Bound a maximum luminance. GZ: Is there any reference/reason, or just trial and error?
aLum = qMin(1.0f, aLum*2.f); // Was 0.38 for MilkyWay. TOAST is allowed to look a bit artificial though...
color.set(aLum, aLum, aLum);

// adapt brightness by atmospheric brightness. This block developed for ZodiacalLight, hopefully similarly applicable...
const float atmLum = GETSTELMODULE(LandscapeMgr)->getAtmosphereAverageLuminance();
// 10cd/m^2 at sunset, 3.3 at civil twilight (sun at -6deg). 0.0145 sun at -12, 0.0004 sun at -18, 0.01 at Full Moon!?
//qDebug() << "AtmLum: " << atmLum;
float atmFactor=qMax(0.35f, 50.0f*(0.02f-atmLum)); // keep visible in twilight, but this is enough for some effect with the moon.
color*=atmFactor*atmFactor;

if (color[0]<0) color[0]=0;
if (color[1]<0) color[1]=0;
if (color[2]<0) color[2]=0;
}

// We also get the viewport shape to discard invisible tiles.
const SphericalCap& viewportRegion = sPainter->getProjector()->getBoundingCap();
rootTile->draw(sPainter, viewportRegion, maxVisibleLevel);
rootTile->draw(sPainter, viewportRegion, maxVisibleLevel, color);
}


Expand Down
16 changes: 10 additions & 6 deletions src/core/StelToast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "StelTextureTypes.hpp"
#include "VecMath.hpp"
#include "StelToastGrid.hpp"
#include "StelVertexArray.hpp"
#include "StelFader.hpp"

class StelPainter;
class ToastSurvey;
Expand Down Expand Up @@ -61,11 +63,12 @@ class ToastTile
ToastTile(ToastSurvey *survey, int level, int x, int y);
virtual ~ToastTile();
Coord getCoord() const { Coord c = { level, x, y }; return c; }
void draw(StelPainter* painter, const SphericalCap& viewportShape, int maxVisibleLevel);
// color is a global sky color (set to 1/1/1 for full brightness) which may be modulated by atmospheric brightness.
void draw(StelPainter* painter, const SphericalCap& viewportShape, int maxVisibleLevel, Vec3f color);
bool isTransparent();

protected:
void drawTile(StelPainter* painter);
void drawTile(StelPainter* painter, Vec3f color);
//! Return the survey the tile belongs to.
const ToastSurvey* getSurvey() const;
//! Return the toast grid used by the tile.
Expand All @@ -75,7 +78,8 @@ class ToastTile
//! return whether the tile is covered by its children tiles
//! This is used to avoid drawing tiles that will be covered anyway
bool isCovered(const SphericalCap& viewportShape) const;
void prepareDraw();
//! prepare arrays. color is set for a global brightness scaling. With atmosphere on, this will also set extinction effects.
void prepareDraw(Vec3f color);

private:
//! The ToastSurvey object this tile belongs to
Expand Down Expand Up @@ -108,7 +112,7 @@ class ToastTile
QVector<Vec3d> vertexArray;
QVector<Vec2f> textureArray;
QVector<unsigned short> indexArray;

QVector<Vec3f> colorArray; // for extinction
// Used for smooth fade in
QTimeLine texFader;
};
Expand Down Expand Up @@ -146,9 +150,9 @@ class ToastSurvey : public QObject
void putIntoCache(ToastTile* tile);

private:
ToastGrid* grid = Q_NULLPTR;
ToastGrid* grid;
QString path;
ToastTile* rootTile = Q_NULLPTR;
ToastTile* rootTile;
int maxLevel;

typedef QCache<ToastTile::Coord, ToastTile> ToastCache;
Expand Down
4 changes: 2 additions & 2 deletions src/core/StelVertexArray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct StelVertexArray
QVector<Vec3d> vertex;
//! OpenGL compatible array of edge flags to be displayed using vertex arrays.
QVector<Vec2f> texCoords;
//! OpenGL compatible array of vertex colors to be displayed using arrays. (GZ/NEW)
//! OpenGL compatible array of vertex colors to be displayed using arrays.
//! The color (if exists) shall be multiplied with texture to modulate e.g. for extinction of Milky Way or other large items.
QVector<Vec3f> colors;
//! OpenGL compatible array of indices for the vertex and the textures
Expand All @@ -65,7 +65,7 @@ struct StelVertexArray


//! call a function for each triangle of the array.
//! func should define the following method : // GZ NEW: colors
//! func should define the following method :
//! void operator() (const Vec3d* vertex[3], const Vec2f* tex[3], const Vec3f* colors[3], unsigned int indices[3])
//! The method takes arrays of *pointers* as arguments because we can't assume the values are contiguous
template<class Func>
Expand Down

0 comments on commit 646880f

Please sign in to comment.