• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Stellarium / stellarium / 15291801018

28 May 2025 04:52AM UTC coverage: 11.931% (-0.02%) from 11.951%
15291801018

push

github

alex-w
Added new set of navigational stars (XIX century)

0 of 6 new or added lines in 2 files covered. (0.0%)

14124 existing lines in 74 files now uncovered.

14635 of 122664 relevant lines covered (11.93%)

18291.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/core/modules/MilkyWay.cpp
1
/*
2
 * Stellarium
3
 * Copyright (C) 2002 Fabien Chereau
4
 * Copyright (C) 2014 Georg Zotti (extinction parts)
5
 * Copyright (C) 2022 Ruslan Kabatsayev
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * as published by the Free Software Foundation; either version 2
10
 * of the License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
20
 */
21

22
#include "MilkyWay.hpp"
23
#include "StelFader.hpp"
24
#include "StelTexture.hpp"
25
#include "StelUtils.hpp"
26
#include "StelFileMgr.hpp"
27

28
#include "StelProjector.hpp"
29
#include "StelToneReproducer.hpp"
30
#include "StelApp.hpp"
31
#include "StelOpenGLArray.hpp"
32
#include "SaturationShader.hpp"
33
#include "StelTextureMgr.hpp"
34
#include "StelSkyDrawer.hpp"
35
#include "StelPainter.hpp"
36
#include "StelTranslator.hpp"
37
#include "StelModuleMgr.hpp"
38
#include "LandscapeMgr.hpp"
39
#include "StelMovementMgr.hpp"
40
#include "Planet.hpp"
41
// For debugging draw() only:
42
// #include "StelObjectMgr.hpp"
43

44
#include <QDebug>
45
#include <QSettings>
46
#include <QOpenGLShaderProgram>
47

48
namespace
49
{
50
constexpr int FS_QUAD_COORDS_PER_VERTEX = 2;
51
constexpr int SKY_VERTEX_ATTRIB_INDEX = 0;
52
}
53

54
// Class which manages the displaying of the Milky Way
55
MilkyWay::MilkyWay()
×
56
        : color(1.f, 1.f, 1.f)
×
57
        , intensity(1.)
×
58
        , intensityFovScale(1.0)
×
59
        , intensityMinFov(0.25) // when zooming in further, MilkyWay is no longer visible.
×
60
        , intensityMaxFov(2.5) // when zooming out further, MilkyWay is fully visible (when enabled).
×
UNCOV
61
        , shaderVars()
×
62
{
63
        setObjectName("MilkyWay");
×
64
        fader = new LinearFader();
×
UNCOV
65
}
×
66

UNCOV
67
MilkyWay::~MilkyWay()
×
68
{
69
        delete fader;
×
70
        fader = Q_NULLPTR;
×
UNCOV
71
}
×
72

UNCOV
73
void MilkyWay::init()
×
74
{
75
        QSettings* conf = StelApp::getInstance().getSettings();
×
UNCOV
76
        Q_ASSERT(conf);
×
77

UNCOV
78
        auto& gl = *QOpenGLContext::currentContext()->functions();
×
79

80
        mainTex = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/milkyway.png");
×
81
        mainTex->bind(0);
×
82
        gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
×
83
        mainTex->release();
×
84
        setFlagShow(conf->value("astro/flag_milky_way").toBool());
×
85
        setIntensity(conf->value("astro/milky_way_intensity",1.).toDouble());
×
86
        setSaturation(conf->value("astro/milky_way_saturation", 1.).toDouble());
×
UNCOV
87
        setColor(Vec3f(conf->value("astro/milky_way_color", "1.0,1.0,1.0").toString()));
×
88

89
        vbo.reset(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
×
90
        vbo->create();
×
91
        vbo->bind();
×
UNCOV
92
        const GLfloat vertices[]=
×
93
        {
94
                // full screen quad
95
                -1, -1,
96
                 1, -1,
97
                -1,  1,
98
                 1,  1,
99
        };
100
        gl.glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
×
UNCOV
101
        vbo->release();
×
102

103
        vao.reset(new QOpenGLVertexArrayObject);
×
104
        vao->create();
×
105
        bindVAO();
×
106
        setupCurrentVAO();
×
UNCOV
107
        releaseVAO();
×
108

109
        QString displayGroup = N_("Display Options");
×
110
        addAction("actionShow_MilkyWay", displayGroup, N_("Milky Way"), "flagMilkyWayDisplayed", "M");
×
UNCOV
111
}
×
112

UNCOV
113
void MilkyWay::setupCurrentVAO()
×
114
{
115
        auto& gl = *QOpenGLContext::currentContext()->functions();
×
116
        vbo->bind();
×
117
        gl.glVertexAttribPointer(0, FS_QUAD_COORDS_PER_VERTEX, GL_FLOAT, false, 0, 0);
×
118
        vbo->release();
×
119
        gl.glEnableVertexAttribArray(SKY_VERTEX_ATTRIB_INDEX);
×
UNCOV
120
}
×
121

UNCOV
122
void MilkyWay::bindVAO()
×
123
{
124
        if(vao->isCreated())
×
UNCOV
125
                vao->bind();
×
126
        else
127
                setupCurrentVAO();
×
UNCOV
128
}
×
129

UNCOV
130
void MilkyWay::releaseVAO()
×
131
{
UNCOV
132
        if(vao->isCreated())
×
133
        {
UNCOV
134
                vao->release();
×
135
        }
136
        else
137
        {
138
                auto& gl = *QOpenGLContext::currentContext()->functions();
×
UNCOV
139
                gl.glDisableVertexAttribArray(SKY_VERTEX_ATTRIB_INDEX);
×
140
        }
UNCOV
141
}
×
142

UNCOV
143
void MilkyWay::update(double deltaTime)
×
144
{
UNCOV
145
        fader->update(static_cast<int>(deltaTime*1000));
×
146
        //calculate FOV fade value, linear fade between intensityMaxFov and intensityMinFov
147
        double fov = StelApp::getInstance().getCore()->getMovementMgr()->getCurrentFov();
×
148
        intensityFovScale = qBound(0.0,(fov - intensityMinFov) / (intensityMaxFov - intensityMinFov),1.0);
×
UNCOV
149
}
×
150

151
/*************************************************************************
152
 Reimplementation of the getCallOrder method
153
*************************************************************************/
UNCOV
154
double MilkyWay::getCallOrder(StelModuleActionName actionName) const
×
155
{
156
        if (actionName==StelModule::ActionDraw)
×
157
                return 1;
×
UNCOV
158
        return 0;
×
159
}
160

UNCOV
161
void MilkyWay::setFlagShow(bool b)
×
162
{
UNCOV
163
        if (*fader != b)
×
164
        {
165
                *fader = b;
×
166
                StelApp::immediateSave("astro/flag_milky_way", b);
×
UNCOV
167
                emit milkyWayDisplayedChanged(b);
×
168
        }
UNCOV
169
}
×
170

UNCOV
171
bool MilkyWay::getFlagShow() const {return *fader;}
×
172

173
// Set Milky Way intensity. Default value: 1.
UNCOV
174
void MilkyWay::setIntensity(double aintensity)
×
175
{
UNCOV
176
        if(!qFuzzyCompare(aintensity, intensity))
×
177
        {
178
                intensity = aintensity;
×
179
                StelApp::immediateSave("astro/milky_way_intensity", aintensity);
×
UNCOV
180
                emit intensityChanged(intensity);
×
181
        }
UNCOV
182
}
×
183

184
// Set Milky Way saturation (color strength).
UNCOV
185
void MilkyWay::setSaturation(double sat)
×
186
{
UNCOV
187
        if(!qFuzzyCompare(sat, saturation))
×
188
        {
189
                saturation = sat;
×
190
                StelApp::immediateSave("astro/milky_way_saturation", sat);
×
UNCOV
191
                emit saturationChanged(saturation);
×
192
        }
UNCOV
193
}
×
194

UNCOV
195
void MilkyWay::setColor(const Vec3f& c)
×
196
{
UNCOV
197
        if (c!=color)
×
198
        {
199
                color=c;
×
UNCOV
200
                emit colorChanged(c);
×
201
        }
UNCOV
202
}
×
203

204

UNCOV
205
void MilkyWay::draw(StelCore* core)
×
206
{
207
        if (!fader->getInterstate())
×
UNCOV
208
                return;
×
209

210
        const auto modelView = core->getJ2000ModelViewTransform();
×
211
        const auto projector = core->getProjection(modelView);
×
212
        const auto drawer=core->getSkyDrawer();
×
UNCOV
213
        const auto& extinction=drawer->getExtinction();
×
214

UNCOV
215
        if(!renderProgram || !prevProjector || !projector->isSameProjection(*prevProjector))
×
216
        {
217
                renderProgram.reset(new QOpenGLShaderProgram);
×
UNCOV
218
                prevProjector = projector;
×
219

220
                const auto vert =
221
                        StelOpenGL::globalShaderPrefix(StelOpenGL::VERTEX_SHADER) +
×
UNCOV
222
                        R"(
×
223
ATTRIBUTE highp vec3 vertex;
224
VARYING highp vec3 ndcPos;
225
void main()
226
{
227
        gl_Position = vec4(vertex, 1.);
228
        ndcPos = vertex;
229
}
230
)";
231
                bool ok = renderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vert);
×
232
                if(!renderProgram->log().isEmpty())
×
233
                        qWarning().noquote() << "MilkyWay: Warnings while compiling vertex shader:\n" << renderProgram->log();
×
UNCOV
234
                if(!ok) return;
×
235

236
                const auto frag =
237
                        StelOpenGL::globalShaderPrefix(StelOpenGL::FRAGMENT_SHADER) +
×
238
                        projector->getUnProjectShader() +
×
239
                        core->getAberrationShader() +
×
240
                        extinction.getForwardTransformShader() +
×
241
                        makeSaturationShader()+
×
UNCOV
242
                        R"(
×
243
VARYING highp vec3 ndcPos;
244
uniform sampler2D mainTex;
245
uniform lowp float saturation;
246
uniform vec3 brightness;
247
uniform mat4 projectionMatrixInverse;
248
uniform bool extinctionEnabled;
249
uniform float bortleIntensity;
250
void main(void)
251
{
252
        const float PI = 3.14159265;
253
        vec4 winPos = projectionMatrixInverse * vec4(ndcPos, 1);
254
        bool ok = false;
255
        vec3 modelPos = unProject(winPos.x, winPos.y, ok).xyz;
256
        if(!ok)
257
        {
258
                FRAG_COLOR = vec4(0);
259
                return;
260
        }
261
        modelPos = normalize(modelPos);
262
        modelPos = applyAberrationToViewDir(modelPos);
263
        float modelZenithAngle = acos(-modelPos.z);
264
        float modelLongitude = atan(modelPos.x, modelPos.y);
265
        vec2 texc = vec2(modelLongitude/(2.*PI), modelZenithAngle/PI);
266

267
        float extinctionFactor;
268
        if(extinctionEnabled)
269
        {
270
                vec3 worldPos = winPosToWorldPos(winPos.x, winPos.y, ok);
271
                vec3 altAzViewDir = worldPosToAltAzPos(worldPos);
272
                float mag = extinctionMagnitude(altAzViewDir);
273
                extinctionFactor=pow(0.3, mag) * (1.1-bortleIntensity*0.1); // drop of one magnitude: should be factor 2.5 or 40%. We take 30%, it looks more realistic.
274
        }
275
        else
276
        {
277
                extinctionFactor = 1.;
278
        }
279

280
    vec4 color = texture2D(mainTex, texc)*vec4(brightness,1)*extinctionFactor;
281
        if(saturation != 1.0)
282
                color.rgb = saturate(color.rgb, saturation);
283
        FRAG_COLOR = color;
284
}
285
)";
286
                ok = renderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, frag);
×
287
                if(!renderProgram->log().isEmpty())
×
UNCOV
288
                        qWarning().noquote() << "MilkyWay: Warnings while compiling fragment shader:\n" << renderProgram->log();
×
289

UNCOV
290
                if(!ok) return;
×
291

UNCOV
292
                renderProgram->bindAttributeLocation("vertex", SKY_VERTEX_ATTRIB_INDEX);
×
293

294
                if(!StelPainter::linkProg(renderProgram.get(), "Milky Way render program"))
×
UNCOV
295
                        return;
×
296

297
                renderProgram->bind();
×
298
                shaderVars.mainTex          = renderProgram->uniformLocation("mainTex");
×
299
                shaderVars.saturation       = renderProgram->uniformLocation("saturation");
×
300
                shaderVars.brightness       = renderProgram->uniformLocation("brightness");
×
301
                shaderVars.bortleIntensity  = renderProgram->uniformLocation("bortleIntensity");
×
302
                shaderVars.extinctionEnabled= renderProgram->uniformLocation("extinctionEnabled");
×
303
                shaderVars.projectionMatrixInverse = renderProgram->uniformLocation("projectionMatrixInverse");
×
304
                renderProgram->release();
×
305
        }
×
306
        if(!renderProgram || !renderProgram->isLinked())
×
UNCOV
307
                return;
×
308

UNCOV
309
        StelToneReproducer* eye = core->getToneReproducer();
×
310

UNCOV
311
        Q_ASSERT(mainTex);        // A texture must be loaded before calling this
×
312

313
        // This RGB color corresponds to the night blue scotopic color = 0.25, 0.25 in xyY mode.
314
        // since milky way is always seen white RGB value in the texture (1.0,1.0,1.0)
315
        // Vec3f c = Vec3f(0.34165f, 0.429666f, 0.63586f);
316
        // This is the same color, just brighter to have Blue=1.
317
        //Vec3f c = Vec3f(0.53730381f, .675724216f, 1.0f);
318
        // The new texture (V0.13.1) is quite blue to start with. It is better to apply white color for it.
319
        //Vec3f c = Vec3f(1.0f, 1.0f, 1.0f);
320
        // Still better: Re-activate the configurable color!
UNCOV
321
        Vec3f c = color;
×
322

323
        // We must also adjust milky way to light pollution.
324
        // Is there any way to calibrate this?
325
        static LandscapeMgr *lMgr=GETSTELMODULE(LandscapeMgr);
×
326
        const float atmFadeIntensity = lMgr->getAtmosphereFadeIntensity();
×
327
        const float nelm = StelCore::luminanceToNELM(drawer->getLightPollutionLuminance());
×
UNCOV
328
        const float bortleIntensity = 1.f+(15.5f-2*nelm)*atmFadeIntensity; // smoothed Bortle index moderated by atmosphere fader.
×
329

UNCOV
330
        const float lum = drawer->surfaceBrightnessToLuminance(12.f+0.15f*bortleIntensity); // was 11.5; Source? How to calibrate the new texture?
×
331

332
        // Get the luminance scaled between 0 and 1
UNCOV
333
        float aLum =eye->adaptLuminanceScaled(lum*fader->getInterstate());
×
334

335
        // Bound a maximum luminance. GZ: Is there any reference/reason, or just trial and error?
UNCOV
336
        aLum = qMin(0.38f, aLum*2.f);
×
337

338

339
        // intensity of 1.0 is "proper", but allow boost for dim screens
UNCOV
340
        c*=aLum*static_cast<float>(intensity*intensityFovScale);
×
341

342
        //StelObjectMgr *omgr=GETSTELMODULE(StelObjectMgr); // Activate for debugging only
343
        //Q_ASSERT(omgr);
344
        // TODO: Find an even better balance with sky brightness, MW should be hard to see during Full Moon and at least somewhat reduced in smaller phases.
345
        // adapt brightness by atmospheric brightness. This block developed for ZodiacalLight, hopefully similarly applicable...
UNCOV
346
        const float atmLum = lMgr->getAtmosphereAverageLuminance();
×
347
        // Approximate values for Preetham: 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!?
348
        //omgr->setExtraInfoString(StelObject::DebugAid, QString("AtmLum: %1<br/>").arg(QString::number(atmLum, 'f', 4)));
349
        // The atmLum of Bruneton's model is about 1/2 higher than that of Preetham/Schaefer. We must rebalance that!
350
        float atmFactor=0.35;
×
UNCOV
351
        if (lMgr->getAtmosphereModel()=="showmysky")
×
352
        {
UNCOV
353
                atmFactor=qMax(0.35f, 50.0f*(0.02f-0.2f*atmLum)); // The factor 0.2f was found empirically. Nominally it should be 0.667, but 0.2 or at least 0.4 looks better.
×
354
        }
355
        else
356
        {
UNCOV
357
                atmFactor=qMax(0.35f, 50.0f*(0.02f-atmLum)); // keep visible in twilight, but this is enough for some effect with the moon.
×
358
        }
359
        //omgr->addToExtraInfoString(StelObject::DebugAid, QString("AtmFactor: %1<br/>").arg(QString::number(atmFactor, 'f', 4)));
UNCOV
360
        c*=atmFactor*atmFactor;
×
361

362
        if (c[0]<0) c[0]=0;
×
363
        if (c[1]<0) c[1]=0;
×
UNCOV
364
        if (c[2]<0) c[2]=0;
×
365

UNCOV
366
        renderProgram->bind();
×
367

368
        renderProgram->setUniformValue(shaderVars.extinctionEnabled, drawer->getFlagHasAtmosphere() && extinction.getExtinctionCoefficient()>=0.01f);
×
UNCOV
369
        renderProgram->setUniformValue(shaderVars.bortleIntensity, bortleIntensity);
×
370

371
        const int mainTexSampler = 0;
×
372
        mainTex->bind(mainTexSampler);
×
UNCOV
373
        renderProgram->setUniformValue(shaderVars.mainTex, mainTexSampler);
×
374

375
        renderProgram->setUniformValue(shaderVars.projectionMatrixInverse, projector->getProjectionMatrix().toQMatrix().inverted());
×
376
        renderProgram->setUniformValue(shaderVars.brightness, c.toQVector());
×
UNCOV
377
        renderProgram->setUniformValue(shaderVars.saturation, GLfloat(saturation));
×
378

379
        core->setAberrationUniforms(*renderProgram);
×
380
        projector->setUnProjectUniforms(*renderProgram);
×
UNCOV
381
        extinction.setForwardTransformUniforms(*renderProgram);
×
382

UNCOV
383
        auto& gl = *QOpenGLContext::currentContext()->functions();
×
384

385
        gl.glEnable(GL_BLEND);
×
386
        gl.glBlendFunc(GL_ONE,GL_ONE); // allow colored sky background
×
387
        bindVAO();
×
388
        gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
×
389
        releaseVAO();
×
390
        gl.glDisable(GL_BLEND);
×
UNCOV
391
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc