Skip to content

Commit

Permalink
Cast a reddish tint over the landscape when sun is low. (#3858)
Browse files Browse the repository at this point in the history
* Cast a reddish tint over the landscape when sun is low.
- reddening is drawn down to -1° solar altitude with a smooth curve
- Scenery3D: ambient also receives a slight reddening
- Scenery3D: cleanup outdated code (night mode)
  • Loading branch information
gzotti authored Sep 8, 2024
1 parent bc5958c commit 660f90a
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 49 deletions.
48 changes: 19 additions & 29 deletions plugins/Scenery3d/src/S3DRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -969,29 +969,17 @@ void S3DRenderer::calculateLighting()
//specular factor is calculated from other values for now
float specular = std::min(ambientBrightness*directionalBrightness*5.0f,1.0f);

//if the night vision mode is on, use red-tinted lighting
bool red=StelApp::getInstance().getVisionModeNight();

float torchDiff = shaderParameters.torchLight ? torchBrightness : 0.0f;
lightInfo.torchAttenuation = 1.0f / (torchRange * torchRange);

if(red)
{
lightInfo.ambient = QVector3D(ambientBrightness,0, 0);
lightInfo.directional = QVector3D(directionalBrightness,0,0);
lightInfo.emissive = QVector3D(emissiveFactor,0,0);
lightInfo.specular = QVector3D(specular,0,0);
lightInfo.torchDiffuse = QVector3D(torchDiff,0,0);
}
else
{
//for now, lighting is only white
lightInfo.ambient = QVector3D(ambientBrightness,ambientBrightness, ambientBrightness);
lightInfo.directional = QVector3D(directionalBrightness,directionalBrightness,directionalBrightness);
lightInfo.emissive = QVector3D(emissiveFactor,emissiveFactor,emissiveFactor);
lightInfo.specular = QVector3D(specular,specular,specular);
lightInfo.torchDiffuse = QVector3D(torchDiff,torchDiff,torchDiff);
}
static LandscapeMgr *lmgr=GETSTELMODULE(LandscapeMgr);
QVector3D solarTint=lmgr->getLandscapeTint().toQVector();
//ambient tries to neutralize sunrise reddening a bit to model collecting light more of the blue sky. Directional and specular are tinted with possibly reddened sun.
lightInfo.ambient = ambientBrightness*(QVector3D(0.4,0.4,0.4)+0.6*solarTint);
lightInfo.directional = directionalBrightness*QVector3D(powf(solarTint[0],2.5f), powf(solarTint[1], 2.5f), powf(solarTint[2], 2.5f));
lightInfo.emissive = QVector3D(emissiveFactor,emissiveFactor,emissiveFactor);
lightInfo.specular = specular*solarTint;
lightInfo.torchDiffuse = QVector3D(torchDiff,torchDiff,torchDiff);
}

void S3DRenderer::calcCubeMVP(const Vec3d translation)
Expand Down Expand Up @@ -1497,10 +1485,12 @@ void S3DRenderer::drawDebug()
Q_ASSERT(lightInfo.directionalSource<=LightParameters::DS_Venus_Ambient);
directionalSourceString = directionalSourceStrings.at(lightInfo.directionalSource);

const QString lightMessage=QString("Ambient: %1 Directional: %2. Shadows cast by: %3 from %4/%5/%6")
.arg(lightInfo.ambient[0], 6, 'f', 4).arg(lightInfo.directional[0], 6, 'f', 4)
.arg(shadowCasterName).arg(lightInfo.lightDirectionV3f.v[0], 6, 'f', 4)
.arg(lightInfo.lightDirectionV3f.v[1], 6, 'f', 4).arg(lightInfo.lightDirectionV3f.v[2], 6, 'f', 4);
QString lightMessage=QString("Ambient: %1/%2/%3 Directional: %4/%5/%6. Shadows cast by: %7")
.arg(QString::number(lightInfo.ambient[0], 'f', 1), QString::number(lightInfo.ambient[1], 'f', 1), QString::number(lightInfo.ambient[2], 'f', 1),
QString::number(lightInfo.directional[0], 'f', 4), QString::number(lightInfo.directional[1], 'f', 4), QString::number(lightInfo.directional[2], 'f', 4))
.arg(shadowCasterName);
if (lightInfo.shadowCaster>LightParameters::SC_None)
lightMessage.append(QString(" from %1/%2/%3").arg(QString::number(lightInfo.lightDirectionV3f.v[0],'f', 4), QString::number(lightInfo.lightDirectionV3f.v[1], 'f', 4), QString::number(lightInfo.lightDirectionV3f.v[2],'f', 4)));
const QString lightMessage2=QString("Contributions: Ambient Sun: %1, Moon: %2, Background+^L: %3")
.arg(lightInfo.sunAmbient, 6, 'f', 4).arg(lightInfo.moonAmbient, 6, 'f', 4).arg(lightInfo.backgroundAmbient, 6, 'f', 4);
const QString lightMessage3=QString(" Directional %1 by: %2, emissive factor: %3, landscape opacity: %4")
Expand All @@ -1510,15 +1500,15 @@ void S3DRenderer::drawDebug()
painter.setFont(debugTextFont);
painter.setColor(1.f,0.f,1.f,1.f);
// For now, these messages print light mixture values.
painter.drawText(20, 160, lightMessage);
painter.drawText(20, 145, lightMessage2);
painter.drawText(20, 130, lightMessage3);
painter.drawText(20, 115, QString("Torch range %1, brightness %2/%3/%4").arg(torchRange).arg(lightInfo.torchDiffuse[0]).arg(lightInfo.torchDiffuse[1]).arg(lightInfo.torchDiffuse[2]));
painter.drawText(70, 160, lightMessage);
painter.drawText(70, 145, lightMessage2);
painter.drawText(70, 130, lightMessage3);
painter.drawText(70, 115, QString("Torch range %1, brightness %2/%3/%4").arg(torchRange).arg(lightInfo.torchDiffuse[0]).arg(lightInfo.torchDiffuse[1]).arg(lightInfo.torchDiffuse[2]));

const AABBox& bbox = currentScene->getSceneAABB();
QString str = QString("BB: %1/%2/%3 %4/%5/%6").arg(bbox.min.v[0], 7, 'f', 2).arg(bbox.min.v[1], 7, 'f', 2).arg(bbox.min.v[2], 7, 'f', 2)
.arg(bbox.max.v[0], 7, 'f', 2).arg(bbox.max.v[1], 7, 'f', 2).arg(bbox.max.v[2], 7, 'f', 2);
painter.drawText(10, 100, str);
painter.drawText(70, 100, str);
// PRINT OTHER MESSAGES HERE:

float screen_x = altAzProjector->getViewportWidth() - 500.0f;
Expand Down
8 changes: 4 additions & 4 deletions plugins/Scenery3d/src/S3DRenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,10 @@ class S3DRenderer : public QObject, protected QOpenGLFunctions
Vec3f lightDirectionV3f;
//same as lightDirectionV3f, but as QVector3D
QVector3D lightDirectionWorld;
QVector3D ambient;
QVector3D directional;
QVector3D specular;
QVector3D emissive;
QVector3D ambient; // color [0...1]
QVector3D directional; // color [0...1]
QVector3D specular; // color [0...1]
QVector3D emissive; // color [0...1]

QVector3D torchDiffuse;
float torchAttenuation;
Expand Down
40 changes: 26 additions & 14 deletions src/core/modules/Landscape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,11 +1110,13 @@ void LandscapeOldStyle::drawDecor(StelCore*const core, const int firstFreeTexSam
(1.f-landscapeTransparency)*landFader.getInterstate());
}
else
{
renderProgram->setUniformValue(shaderVars.brightness,
landscapeBrightness, landscapeBrightness, landscapeBrightness,
(1.f-landscapeTransparency)*landFader.getInterstate());
}
{
renderProgram->setUniformValue(shaderVars.brightness,
landscapeBrightness*landscapeTint[0],
landscapeBrightness*landscapeTint[1],
landscapeBrightness*landscapeTint[2],
(1.f-landscapeTransparency)*landFader.getInterstate());
}

renderProgram->setUniformValue(shaderVars.tanMode, tanMode);
renderProgram->setUniformValue(shaderVars.calibrated, calibrated);
Expand Down Expand Up @@ -1209,7 +1211,9 @@ void LandscapeOldStyle::drawGround(StelCore*const core, const int firstFreeTexSa
renderProgram->setUniformValue(shaderVars.vshift, vshift);
renderProgram->setUniformValue(shaderVars.projectionMatrixInverse, prj->getProjectionMatrix().toQMatrix().inverted());
renderProgram->setUniformValue(shaderVars.brightness,
landscapeBrightness, landscapeBrightness, landscapeBrightness,
landscapeBrightness*landscapeTint[0],
landscapeBrightness*landscapeTint[1],
landscapeBrightness*landscapeTint[2],
(1.f-landscapeTransparency)*landFader.getInterstate());
prj->setUnProjectUniforms(*renderProgram);
gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Expand Down Expand Up @@ -1479,8 +1483,12 @@ void LandscapePolygonal::draw(StelCore* core, bool onlyPolygon)
sPainter.setCullFace(true);

if (!onlyPolygon) // The only useful application of the onlyPolygon is a demo which does not fill the polygon
{
sPainter.setColor(landscapeBrightness*groundColor, (1.f-landscapeTransparency)*landFader.getInterstate());
{
sPainter.setColor(
landscapeBrightness*groundColor[0]*landscapeTint[0],
landscapeBrightness*groundColor[1]*landscapeTint[1],
landscapeBrightness*groundColor[2]*landscapeTint[2],
(1.f-landscapeTransparency)*landFader.getInterstate());
#ifdef GL_MULTISAMPLE
const auto gl = sPainter.glFuncs();
if (multisamplingEnabled_)
Expand Down Expand Up @@ -1686,9 +1694,11 @@ void main(void)
if (!onlyPolygon || !horizonPolygon) // Make sure to draw the regular pano when there is no polygon
{
renderProgram->bind();
renderProgram->setUniformValue(shaderVars.brightness,
landscapeBrightness, landscapeBrightness,
landscapeBrightness, landFader.getInterstate());
renderProgram->setUniformValue(shaderVars.brightness,
landscapeBrightness*landscapeTint[0],
landscapeBrightness*landscapeTint[1],
landscapeBrightness*landscapeTint[2],
landFader.getInterstate());
const int mainTexSampler = 0;
mapTex->bind(mainTexSampler);
renderProgram->setUniformValue(shaderVars.mapTex, mainTexSampler);
Expand Down Expand Up @@ -2045,9 +2055,11 @@ void main(void)
landscapeBrightness*bottomCapColor[2],
bottomCapColor[0] < 0 ? 0 : landFader.getInterstate());

renderProgram->setUniformValue(shaderVars.brightness,
landscapeBrightness, landscapeBrightness,
landscapeBrightness, (1.f-landscapeTransparency)*landFader.getInterstate());
renderProgram->setUniformValue(shaderVars.brightness,
landscapeBrightness*landscapeTint[0],
landscapeBrightness*landscapeTint[1],
landscapeBrightness*landscapeTint[2],
(1.f-landscapeTransparency)*landFader.getInterstate());
const int mainTexSampler = 0;
mapTex->bind(mainTexSampler);
renderProgram->setUniformValue(shaderVars.mapTex, mainTexSampler);
Expand Down
4 changes: 4 additions & 0 deletions src/core/modules/Landscape.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ class Landscape
//! This is called in each draw().
void setBrightness(const double b, const double pollutionBrightness=0.0) {landscapeBrightness = static_cast<float>(b); lightScapeBrightness=static_cast<float>(pollutionBrightness); }

//! Set a tint to render the landscape. Useful for low-sun scenes
void setTint(Vec3f color){landscapeTint=color;}

//! Returns the current brightness level
double getBrightness() const { return static_cast<double>(landscapeBrightness); }
//! Returns the lightscape brightness
Expand Down Expand Up @@ -241,6 +244,7 @@ class Landscape

float minBrightness; //! Read from landscape.ini:[landscape]minimal_brightness. Allows minimum visibility that cannot be underpowered.
float landscapeBrightness; //! brightness [0..1] to draw the landscape. Computed by the LandscapeMgr.
Vec3f landscapeTint; //! color tint to draw the landscape (daylight texture only). Nice for sunrise/sunset.
float lightScapeBrightness; //! can be used to draw nightscape texture (e.g. city light pollution), if available. Computed by the LandscapeMgr.
bool validLandscape; //! was a landscape loaded properly?
LinearFader landFader; //! Used to slowly fade in/out landscape painting.
Expand Down
5 changes: 5 additions & 0 deletions src/core/modules/LandscapeMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ LandscapeMgr::LandscapeMgr()
, flagEnvironmentAutoEnabling(false)
, flagLandscapeUseTransparency(false)
, landscapeTransparency(0.)
, landscapeTint(1.f, 1.f, 1.f)
{
setObjectName("LandscapeMgr"); // should be done by StelModule's constructor.

Expand Down Expand Up @@ -542,6 +543,7 @@ void LandscapeMgr::update(double deltaTime)
if (currentPlanet->getID() == sun->getID())
{
landscape->setBrightness(1.0, 1.0);
landscape->setTint(Vec3f(1.f));
return;
}

Expand Down Expand Up @@ -653,6 +655,9 @@ void LandscapeMgr::update(double deltaTime)
}
landscape->setBrightness(landscapeBrightness, lightscapeBrightness);

// extra colorful sunrise/sunset management.
landscape->setTint(landscapeTint);

messageFader.update(static_cast<int>(deltaTime*1000));
}

Expand Down
8 changes: 7 additions & 1 deletion src/core/modules/LandscapeMgr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,10 @@ public slots:
}
}

//! Set a discoloration to simulate sunrise/sunset colors.
void setLandscapeTint(const Vec3f &c){landscapeTint=c;}
Vec3f getLandscapeTint() const {return landscapeTint;}

/*
//This method has been removed, use StelSkyDrawer::getBortleScaleIndex instead, or StelMainScriptAPI::getBortleScaleIndex in scripts
//Also, if required, please use StelSkyDrawer::setBortleScaleIndex or StelMainScriptAPI::setBortleScaleIndex instead of LandscapeMgr::setAtmosphereBortleLightPollution
Expand Down Expand Up @@ -836,8 +840,10 @@ private slots:

//! Indicate use of the default transparency value specified in config.ini.
bool flagLandscapeUseTransparency;
//! A transparency value
//! A user-configurable transparency value to make landscape partially see-through and let objects below the horizon be visible
double landscapeTransparency;
//! Color tint to draw the landscape in. Can be useful for sunrise/sunset scenes.
Vec3f landscapeTint;

//! The ID of the currently loaded landscape
QString currentLandscapeID;
Expand Down
33 changes: 32 additions & 1 deletion src/core/modules/Planet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2846,6 +2846,37 @@ void Planet::draw(StelCore* core, float maxMagLabels, const QFont& planetNameFon
return;
}

static SolarSystem* ssm = GETSTELMODULE(SolarSystem);
const bool isSun = this==ssm->getSun();
const bool currentLocationIsEarth = core->getCurrentLocation().planetName == "Earth";
if (isSun && currentLocationIsEarth)
{
static LandscapeMgr* lmgr = GETSTELMODULE(LandscapeMgr);
Vec3f posAltAz = getAltAzPosAuto(core).toVec3f();
posAltAz.normalize();

// If sun is higher than -1 degrees, tint the landscape.
// Down to 0 degree, this tint is derived from the halo color.
// Below that, we must find a smooth transition (adapted cosine). Below -1 degrees,
// it is assumed the reddish tint should have dissipated, and the blue sky is illuminating the landscape in a neutral tone.
if (posAltAz[2]<sinf(-1.f*M_PI_180f))
lmgr->setLandscapeTint(Vec3f(1.f));
else
{
const float sunAlt=asinf(posAltAz[2]);
const float angleFactor=sunAlt>0 ? 1.f : 0.5f*(cosf(180.f*sunAlt)+1.f);

// Find extinction settings to change colors. The method is rather ad-hoc.
const float extinctedMag=getVMagnitudeWithExtinction(core)-getVMagnitude(core); // this is net value of extinction, in mag.
//Vec3f color(haloColor[0], powf(0.75f, extinctedMag) * haloColor[1], powf(0.42f, 0.9f*extinctedMag) * haloColor[2]);
Vec3f color(haloColor[0], powf(0.80f, extinctedMag) * haloColor[1], powf(0.25f, extinctedMag) * haloColor[2]);

Vec3f fullTint(0.25f*Vec3f(3.f+sqrtf(color[0]), 3.f+sqrtf(color[1]), 3.f+sqrtf(color[2])));

lmgr->setLandscapeTint(angleFactor*fullTint + (1.f-angleFactor)*Vec3f(1.f)); // final tint
}
}

// Try to improve speed for minor planets: test if visible at all.
// For a full catalog of NEAs (11000 objects), with this and resetting deltaJD according to distance, rendering time went 4.5fps->12fps.
// TBD: Note that taking away the asteroids at this stage breaks dim-asteroid occultation of stars!
Expand Down Expand Up @@ -3447,7 +3478,7 @@ void Planet::draw3dModel(StelCore* core, StelProjector::ModelViewTranformP trans
rotationAngle -= q0*static_cast<float>(180.0/M_PI);

StelPainter sPainter(core->getProjection(StelCore::FrameJ2000));
const auto pos = getJ2000EquatorialPos(core).toVec3f();
const Vec3f pos = getJ2000EquatorialPos(core).toVec3f();

// Find new extincted color for halo. The method is again rather ad-hoc, but does not look too bad.
// For the sun, we have again to use the stronger extinction to avoid color mismatch.
Expand Down

0 comments on commit 660f90a

Please sign in to comment.