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

Stellarium / stellarium / 10609521019

29 Aug 2024 05:56AM UTC coverage: 12.113% (-0.03%) from 12.138%
10609521019

Pull #3847

github

alex-w
[SSE] Add info for total candidates for addiing...
Pull Request #3847: Threaded planet computation (and a few more speedups)

30 of 686 new or added lines in 51 files covered. (4.37%)

41 existing lines in 18 files now uncovered.

14434 of 119159 relevant lines covered (12.11%)

19024.8 hits per line

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

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

20

21
#include "StelSkyDrawer.hpp"
22
#include "StelProjector.hpp"
23
#include "StelFileMgr.hpp"
24

25
#include "StelToneReproducer.hpp"
26
#include "StelTextureMgr.hpp"
27
#include "StelApp.hpp"
28
#include "StelCore.hpp"
29
#include "StelMovementMgr.hpp"
30
#include "StelPainter.hpp"
31
#include "StelMainView.hpp"
32

33
#include "StelModuleMgr.hpp"
34
#include "LandscapeMgr.hpp"
35
#include "Landscape.hpp"
36

37
#include <QOpenGLContext>
38
#include <QOpenGLVertexArrayObject>
39
#include <QOpenGLShaderProgram>
40
#include <QOpenGLBuffer>
41
#include <QStringList>
42
#include <QSettings>
43
#include <QDebug>
44
#include <QtGlobal>
45

46
// The 0.025 corresponds to the maximum eye resolution in degree
47
#define EYE_RESOLUTION (0.25f)
48
#define MAX_LINEAR_RADIUS 8.f
49

50
StelSkyDrawer::StelSkyDrawer(StelCore* acore) :
×
51
        core(acore),
×
52
        eye(acore->getToneReproducer()),
×
53
        vao(new QOpenGLVertexArrayObject),
×
54
        vbo(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer)),
×
55
        maxAdaptFov(180.f),
×
56
        minAdaptFov(0.1f),
×
57
        lnfovFactor(0.f),
×
58
        flagStarTwinkle(false),
×
59
        flagForcedTwinkle(false),
×
60
        twinkleAmount(0.0),
×
61
        flagDrawBigStarHalo(true),
×
62
        flagStarSpiky(false),
×
63
        flagStarMagnitudeLimit(false),
×
64
        flagNebulaMagnitudeLimit(false),
×
65
        flagPlanetMagnitudeLimit(false),
×
66
        starRelativeScale(1.),
×
67
        starAbsoluteScaleF(1.),
×
68
        starLinearScale(19.569f),
×
69
        limitMagnitude(-100.f),
×
70
        limitLuminance(0.f),
×
71
        customStarMagLimit(0.0),
×
72
        customNebulaMagLimit(0.0),
×
73
        customPlanetMagLimit(0.0),
×
74
        inScale(1.f),
×
75
        starShaderProgram(Q_NULLPTR),
×
76
        starShaderVars(StarShaderVars()),
×
77
        nbPointSources(0),
×
78
        maxLum(0.f),
×
79
        oldLum(-1.f),
×
80
        flagLuminanceAdaptation(false),
×
81
        daylightLabelThreshold(250.0),
×
82
        big3dModelHaloRadius(150.f)
×
83
{
84
        setObjectName("StelSkyDrawer");
×
85
        QSettings* conf = StelApp::getInstance().getSettings();
×
86
        initColorTableFromConfigFile(conf);
×
87

88
        setFlagHasAtmosphere(conf->value("landscape/flag_atmosphere", true).toBool());
×
89
        setTwinkleAmount(conf->value("stars/star_twinkle_amount",0.3).toDouble());
×
90
        setFlagTwinkle(conf->value("stars/flag_star_twinkle",true).toBool());
×
91
        setFlagForcedTwinkle(conf->value("stars/flag_forced_twinkle",false).toBool());
×
92
        setFlagDrawBigStarHalo(conf->value("stars/flag_star_halo",true).toBool());
×
93
        flagStarSpiky=(conf->value("stars/flag_star_spiky", false).toBool()); // too early to use the set method here!
×
94
        setMaxAdaptFov(conf->value("stars/mag_converter_max_fov",70.0).toFloat());
×
95
        setMinAdaptFov(conf->value("stars/mag_converter_min_fov",0.1).toFloat());
×
96
        setFlagLuminanceAdaptation(conf->value("viewing/use_luminance_adaptation",true).toBool());
×
97
        setDaylightLabelThreshold(conf->value("viewing/sky_brightness_label_threshold", 250.0).toDouble());
×
98
        setFlagStarMagnitudeLimit(conf->value("astro/flag_star_magnitude_limit", false).toBool());
×
99
        setCustomStarMagnitudeLimit(conf->value("astro/star_magnitude_limit", 6.5).toDouble());
×
100
        setFlagPlanetMagnitudeLimit(conf->value("astro/flag_planet_magnitude_limit", false).toBool());
×
101
        setCustomPlanetMagnitudeLimit(conf->value("astro/planet_magnitude_limit", 6.5).toDouble());
×
102
        setFlagNebulaMagnitudeLimit(conf->value("astro/flag_nebula_magnitude_limit", false).toBool());
×
103
        setCustomNebulaMagnitudeLimit(conf->value("astro/nebula_magnitude_limit", 8.5).toDouble());
×
104

105
        setLightPollutionLuminance(conf->value("stars/init_light_pollution_luminance", StelCore::bortleScaleIndexToLuminance(3)).toFloat());
×
106
        setRelativeStarScale(conf->value("stars/relative_scale", 1.0).toDouble());
×
107
        setAbsoluteStarScale(conf->value("stars/absolute_scale", 1.0).toDouble());
×
108
        setExtinctionCoefficient(conf->value("landscape/atmospheric_extinction_coefficient", 0.13).toDouble());
×
109

110
        const QString extinctionMode = conf->value("astro/extinction_mode_below_horizon", "zero").toString();
×
111
        // zero by default
112
        if (extinctionMode=="mirror")
×
113
                extinction.setUndergroundExtinctionMode(Extinction::UndergroundExtinctionMirror);
×
114
        else if (extinctionMode=="max")
×
115
                extinction.setUndergroundExtinctionMode(Extinction::UndergroundExtinctionMax);
×
116

117
        setAtmosphereTemperature(conf->value("landscape/temperature_C", 15.0).toDouble());
×
118
        setAtmospherePressure(conf->value("landscape/pressure_mbar", 1013.0).toDouble());
×
119

120
        // four extras for finetuning
121
        setFlagDrawSunAfterAtmosphere(conf->value("landscape/draw_sun_after_atmosphere",false).toBool());
×
122
        setFlagEarlySunHalo(conf->value("landscape/early_solar_halo",false).toBool());
×
123
        setFlagTfromK(conf->value("landscape/use_T_from_k",false).toBool());
×
124
        setT(conf->value("landscape/turbidity",5.).toDouble());
×
125

126
        // Initialize buffers for use by gl vertex array
127
        vertexArray = new StarVertex[maxPointSources*6];
×
128
        
129
        textureCoordArray = new unsigned char[maxPointSources*6*2];
×
130
        for (unsigned int i=0;i<maxPointSources; ++i)
×
131
        {
132
                static const unsigned char texElems[] = {0, 0, 255, 0, 255, 255, 0, 0, 255, 255, 0, 255};
133
                unsigned char* elem = &textureCoordArray[i*6*2];
×
134
                std::memcpy(elem, texElems, 12);
×
135
        }
136
        texImgHalo=QImage(StelFileMgr::getInstallationDir()+"/textures/star16x16.png");
×
137
        texImgHaloSpiky=QImage(StelFileMgr::getInstallationDir()+"/textures/star16x16_rays.png");
×
138
}
×
139

140
StelSkyDrawer::~StelSkyDrawer()
×
141
{
142
        delete[] vertexArray;
×
143
        vertexArray = Q_NULLPTR;
×
144
        delete[] textureCoordArray;
×
145
        textureCoordArray = Q_NULLPTR;
×
146
        
147
        delete starShaderProgram;
×
148
        starShaderProgram = Q_NULLPTR;
×
149
}
×
150

151
// Init parameters from config file
152
void StelSkyDrawer::init()
×
153
{
154
        initializeOpenGLFunctions();
×
155

156
        // Load star texture no mipmap:
157
        texHalo = StelApp::getInstance().getTextureManager().createTexture(texImgHalo);
×
158
        texHaloRayed = StelApp::getInstance().getTextureManager().createTexture(texImgHaloSpiky);
×
159
        texBigHalo = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/haloLune.png");
×
160
        texSunHalo = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/halo.png");        
×
161
        texSunCorona = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/corona.png");
×
162

163
        // Create shader program
164
        QOpenGLShader vshader(QOpenGLShader::Vertex);
×
165
        const char *vsrc =
×
166
                "ATTRIBUTE mediump vec2 pos;\n"
167
                "ATTRIBUTE mediump vec2 texCoord;\n"
168
                "ATTRIBUTE mediump vec3 color;\n"
169
                "uniform mediump mat4 projectionMatrix;\n"
170
                "VARYING mediump vec2 texc;\n"
171
                "VARYING mediump vec3 outColor;\n"
172
                "void main(void)\n"
173
                "{\n"
174
                "    gl_Position = projectionMatrix * vec4(pos.x, pos.y, 0, 1);\n"
175
                "    texc = texCoord;\n"
176
                "    outColor = color;\n"
177
                "}\n";
178
        vshader.compileSourceCode(StelOpenGL::globalShaderPrefix(StelOpenGL::VERTEX_SHADER) + vsrc);
×
179
        if (!vshader.log().isEmpty()) { qWarning() << "StelSkyDrawer::init(): Warnings while compiling vshader: " << vshader.log(); }
×
180

181
        QOpenGLShader fshader(QOpenGLShader::Fragment);
×
182
        const char *fsrc =
×
183
                "VARYING mediump vec2 texc;\n"
184
                "VARYING mediump vec3 outColor;\n"
185
                "uniform sampler2D tex;\n"
186
                "void main(void)\n"
187
                "{\n"
188
                "    FRAG_COLOR = texture2D(tex, texc)*vec4(outColor, 1.);\n"
189
                "}\n";
190
        fshader.compileSourceCode(StelOpenGL::globalShaderPrefix(StelOpenGL::FRAGMENT_SHADER) + fsrc);
×
191
        if (!fshader.log().isEmpty()) { qWarning() << "StelSkyDrawer::init(): Warnings while compiling fshader: " << fshader.log(); }
×
192

193
        starShaderProgram = new QOpenGLShaderProgram(QOpenGLContext::currentContext());
×
194
        starShaderProgram->addShader(&vshader);
×
195
        starShaderProgram->addShader(&fshader);
×
196
        StelPainter::linkProg(starShaderProgram, "starShader");
×
197
        starShaderVars.projectionMatrix = starShaderProgram->uniformLocation("projectionMatrix");
×
198
        starShaderVars.texCoord = starShaderProgram->attributeLocation("texCoord");
×
199
        starShaderVars.pos = starShaderProgram->attributeLocation("pos");
×
200
        starShaderVars.color = starShaderProgram->attributeLocation("color");
×
201
        starShaderVars.texture = starShaderProgram->uniformLocation("tex");
×
202

203
        vbo->create();
×
204
        vbo->bind();
×
205
        vbo->setUsagePattern(QOpenGLBuffer::StreamDraw);
×
206
        vbo->allocate(maxPointSources*6*sizeof(StarVertex) + maxPointSources*6*2);
×
207

208
        if(vao->create())
×
209
        {
210
                vao->bind();
×
211
                setupCurrentVAO();
×
212
                vao->release();
×
213
        }
214

215
        vbo->release();
×
216

217
        update(0);
×
218
}
×
219

220
void StelSkyDrawer::setupCurrentVAO()
×
221
{
222
        vbo->bind();
×
223
        starShaderProgram->setAttributeBuffer(starShaderVars.pos, GL_FLOAT, 0, 2, sizeof(StarVertex));
×
224
        starShaderProgram->setAttributeBuffer(starShaderVars.color, GL_UNSIGNED_BYTE, offsetof(StarVertex,color), 3, sizeof(StarVertex));
×
225
        starShaderProgram->setAttributeBuffer(starShaderVars.texCoord, GL_UNSIGNED_BYTE, maxPointSources*6*sizeof(StarVertex), 2, 0);
×
226
        vbo->release();
×
227
        starShaderProgram->enableAttributeArray(starShaderVars.pos);
×
228
        starShaderProgram->enableAttributeArray(starShaderVars.color);
×
229
        starShaderProgram->enableAttributeArray(starShaderVars.texCoord);
×
230
}
×
231

232
void StelSkyDrawer::bindVAO()
×
233
{
234
        if(vao->isCreated())
×
235
                vao->bind();
×
236
        else
237
                setupCurrentVAO();
×
238
}
×
239

240
void StelSkyDrawer::releaseVAO()
×
241
{
242
        if(vao->isCreated())
×
243
        {
244
                vao->release();
×
245
        }
246
        else
247
        {
248
                starShaderProgram->disableAttributeArray(starShaderVars.pos);
×
249
                starShaderProgram->disableAttributeArray(starShaderVars.color);
×
250
                starShaderProgram->disableAttributeArray(starShaderVars.texCoord);
×
251
        }
252
}
×
253

254
void StelSkyDrawer::update(double)
×
255
{
256
        float fov = static_cast<float>(core->getMovementMgr()->getCurrentFov());
×
257
        if (fov > maxAdaptFov)
×
258
        {
259
                fov = maxAdaptFov;
×
260
        }
261
        else
262
        {
263
                if (fov < minAdaptFov)
×
264
                        fov = minAdaptFov;
×
265
        }
266

267
        if (getFlagHasAtmosphere() && core->getJD()>2387627.5) // JD given is J1825.0; ignore Bortle scale index before that.
×
268
        {
269
        // GZ: Light pollution must take global atmosphere setting into account!
270
        // moved parts from setBortleScale() here
271
        // This formula is a fit to a set of values calibrated by hand, looking at the faintest star in stellarium at around 40 deg FOV.
272
        // It should roughly match the scale described at http://en.wikipedia.org/wiki/Bortle_Dark-Sky_Scale
273
                const auto nelm = StelCore::luminanceToNELM(lightPollutionLuminance);
×
274
                setInputScale(3.3541f*std::exp(-0.404f*(16.5f-2*nelm)));
×
275
        }
276
        else
277
            setInputScale(2.45f);
×
278

279
        // This factor is fully arbitrary. It corresponds to the collecting area x exposure time of the instrument
280
        // It is based on a power law, so that it varies progressively with the FOV to smoothly switch from human
281
        // vision to binocculares/telescope. Use a max of 0.7 because after that the atmosphere starts to glow too much!
282
        float powFactor = std::pow(60.f/qMax(0.7f,fov), 0.8f);
×
283
        eye->setInputScale(inScale*powFactor);
×
284

285
        // Set the fov factor for point source luminance computation
286
        // the division by powFactor should in principle not be here, but it doesn't look nice if removed
287
        lnfovFactor = std::log(1.f/50.f*2025000.f* 60.f*60.f / (fov*fov) / (EYE_RESOLUTION*EYE_RESOLUTION)/powFactor/1.4f);
×
288

289
        // Precompute
290
        starLinearScale = static_cast<float>(std::pow(35.*2.0*starAbsoluteScaleF, 1.40*0.5*starRelativeScale));
×
291

292
        // update limit mag
293
        limitMagnitude = computeLimitMagnitude();
×
294

295
        // update limit luminance
296
        limitLuminance = computeLimitLuminance();
×
297
}
×
298

299
// Compute the current limit magnitude by dichotomy
300
float StelSkyDrawer::computeLimitMagnitude() const
×
301
{
302
        float a=-26.f;
×
303
        float b=30.f;
×
304
        RCMag rcmag;
305
        float lim = 0.f;
×
306
        int safety=0;
×
307
        while (std::fabs(lim-a)>0.05f)
×
308
        {
309
                computeRCMag(lim, &rcmag);
×
310
                float tmp = lim;
×
311
                if (rcmag.radius<=0.f)
×
312
                {
313
                        lim=(a+lim)*0.5f;
×
314
                        b=tmp;
×
315
                }
316
                else
317
                {
318
                        lim=(b+lim)*0.5f;
×
319
                        a=tmp;
×
320
                }
321
                ++safety;
×
322
                if (safety>20)
×
323
                {
324
                        lim=-99;
×
325
                        break;
×
326
                }
327
        }
328
        return lim;
×
329
}
330

331
// Compute the current limit luminance by dichotomy
332
float StelSkyDrawer::computeLimitLuminance() const
×
333
{
334
        float a=0.f;
×
335
        float b=500000.f;
×
336
        float lim=40.f;
×
337
        int safety=0;
×
338
        float adaptL;
339
        while (std::fabs(lim-a)>0.05f)
×
340
        {
341
                adaptL = eye->adaptLuminanceScaled(lim);
×
342
                if (adaptL<=0.05f) // Object considered not visible if its adapted scaled luminance<0.05
×
343
                {
344
                        float tmp = lim;
×
345
                        lim=(b+lim)*0.5f;
×
346
                        a=tmp;
×
347
                }
348
                else
349
                {
350
                        float tmp = lim;
×
351
                        lim=(a+lim)*0.5f;
×
352
                        b=tmp;
×
353
                }
354
                ++safety;
×
355
                if (safety>30)
×
356
                {
357
                        lim=500000;
×
358
                        break;
×
359
                }
360
        }
361
        return lim;
×
362
}
363

364
// Compute the ln of the luminance for a point source with the given mag for the current FOV
365
float StelSkyDrawer::pointSourceMagToLnLuminance(float mag) const
×
366
{
367
        return -0.92103f*(mag + 12.12331f) + lnfovFactor;
×
368
}
369

370
float StelSkyDrawer::pointSourceLuminanceToMag(float lum) const
×
371
{
372
        return (std::log(lum) - lnfovFactor)/-0.92103f - 12.12331f;
×
373
}
374

375
// Compute the luminance for an extended source with the given surface brightness in Vmag/arcmin^2
376
float StelSkyDrawer::surfaceBrightnessToLuminance(float sb)
×
377
{
378
        return 2.f*2025000.f*std::exp(-0.92103f*(sb + 12.12331f))/(1.f/60.f*1.f/60.f);
×
379
}
380

381
// Compute the surface brightness from the luminance of an extended source
382
float StelSkyDrawer::luminanceToSurfacebrightness(float lum)
×
383
{
384
        return std::log(lum*(1.f/60.f*1.f/60.f)/(2.f*2025000.f))/-0.92103f - 12.12331f;
×
385
}
386

387
// Compute RMag and CMag from magnitude for a point source.
388
bool StelSkyDrawer::computeRCMag(float mag, RCMag* rcMag) const
×
389
{
390
        rcMag->radius = eye->adaptLuminanceScaledLn(pointSourceMagToLnLuminance(mag), static_cast<float>(starRelativeScale)*1.40f*0.5f);
×
391
        rcMag->radius *=starLinearScale;
×
392
        rcMag->radius *=StelMainView::getInstance().getCustomScreenshotMagnification();
×
393
        // Use now statically min_rmag = 0.5, because higher and too small values look bad
394
        if (rcMag->radius < 0.3f)
×
395
        {
396
                rcMag->radius = 0.f;
×
397
                rcMag->luminance = 0.f;
×
398
                return false;
×
399
        }
400

401
        // if size of star is too small (blink) we put its size to 1.2 --> no more blink
402
        // And we compensate the difference of brighteness with cmag
403
        if (rcMag->radius<1.2f)
×
404
        {
405
                rcMag->luminance= rcMag->radius * rcMag->radius * rcMag->radius / 1.728f;
×
406
                if (rcMag->luminance < 0.05f)
×
407
                {
408
                        rcMag->radius = rcMag->luminance = 0.f;
×
409
                        return false;
×
410
                }
411
                rcMag->radius = 1.2f;
×
412
        }
413
        else
414
        {
415
                // cmag:
416
                rcMag->luminance = 1.0f;
×
417
                if (rcMag->radius>MAX_LINEAR_RADIUS)
×
418
                {
419
                        rcMag->radius=MAX_LINEAR_RADIUS+std::sqrt(1.f+rcMag->radius-MAX_LINEAR_RADIUS)-1.f;
×
420
                }
421
        }
422
        return true;
×
423
}
424

425
void StelSkyDrawer::preDrawPointSource(StelPainter* p)
×
426
{
427
        Q_ASSERT(p);
×
428
        Q_ASSERT(nbPointSources==0);
×
429

430
        // Blending is really important. Otherwise faint stars in the vicinity of
431
        // bright star will cause tiny black squares on the bright star, e.g. see Procyon.
432
        p->setBlending(true, GL_ONE, GL_ONE);
×
433
}
×
434

435
// Finalize the drawing of point sources
436
void StelSkyDrawer::postDrawPointSource(StelPainter* sPainter)
×
437
{
438
        Q_ASSERT(sPainter);
×
439

440
        if (nbPointSources==0)
×
441
                return;
×
442
        if (flagStarSpiky)
×
443
                texHaloRayed->bind();
×
444
        else
445
                texHalo->bind();
×
446
        sPainter->setBlending(true, GL_ONE, GL_ONE);
×
447

NEW
448
        const QMatrix4x4 qMat=sPainter->getProjector()->getProjectionMatrix().toQMatrix();
×
449

450
        vbo->bind();
×
451
        vbo->write(0, vertexArray, nbPointSources*6*sizeof(StarVertex));
×
452
        vbo->write(maxPointSources*6*sizeof(StarVertex), textureCoordArray, nbPointSources*6*2);
×
453
        vbo->release();
×
454

455
        starShaderProgram->bind();
×
456
        starShaderProgram->setUniformValue(starShaderVars.projectionMatrix, qMat);
×
457
        
458
        bindVAO();
×
459
        glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(nbPointSources)*6);
×
460
        releaseVAO();
×
461

462
        starShaderProgram->release();
×
463
        
464
        nbPointSources = 0;
×
465
}
466

467
// Draw a point source halo.
468
bool StelSkyDrawer::drawPointSource(StelPainter* sPainter, const Vec3d& v, const RCMag& rcMag, const Vec3f& color, bool checkInScreen, float twinkleFactor)
×
469
{
470
        Q_ASSERT(sPainter);
×
471

472
        if (rcMag.radius<=0.f)
×
473
                return false;
×
474

475
        Vec3d win;
×
476
        if (!(checkInScreen ? sPainter->getProjector()->projectCheck(v, win) : sPainter->getProjector()->project(v, win)))
×
477
                return false;
×
478

479
        const float radius = rcMag.radius * static_cast<float>(sPainter->getProjector()->getDevicePixelsPerPixel());
×
480
        const float frand=StelApp::getInstance().getRandF();
×
481

482
        // Random coef for star twinkling. twinkleFactor can introduce height-dependent twinkling.
483
        const float tw = ((flagStarTwinkle && (flagHasAtmosphere || flagForcedTwinkle))) ? (1.f-twinkleFactor*static_cast<float>(twinkleAmount)*frand)*rcMag.luminance : rcMag.luminance;
×
484

485
        // If the rmag is big, draw a big halo
486
        if (flagDrawBigStarHalo && radius>MAX_LINEAR_RADIUS+5.f)
×
487
        {
488
                float cmag = qMin(1.0f, qMin(rcMag.luminance, (radius-(MAX_LINEAR_RADIUS+5.f))/30.f));
×
489
                float rmag = 150.f;
×
490

491
                texBigHalo->bind();
×
492
                sPainter->setBlending(true, GL_ONE, GL_ONE);
×
493
                sPainter->setColor(color*cmag);
×
494
                sPainter->drawSprite2dModeNoDeviceScale(win[0], win[1], rmag);
×
495
        }
496

497
        unsigned char starColor[3] = {
NEW
498
                static_cast<unsigned char>(std::min(static_cast<int>(color[0]*tw*255+0.5f), 255)),
×
NEW
499
                static_cast<unsigned char>(std::min(static_cast<int>(color[1]*tw*255+0.5f), 255)),
×
NEW
500
                static_cast<unsigned char>(std::min(static_cast<int>(color[2]*tw*255+0.5f), 255))};
×
501
        
502
        // Store the drawing instructions in the vertex arrays
503
        StarVertex* vx = &(vertexArray[nbPointSources*6]);
×
504
        vx->pos.set(win[0]-radius,win[1]-radius); std::memcpy(vx->color, starColor, 3); ++vx;
×
505
        vx->pos.set(win[0]+radius,win[1]-radius); std::memcpy(vx->color, starColor, 3); ++vx;
×
506
        vx->pos.set(win[0]+radius,win[1]+radius); std::memcpy(vx->color, starColor, 3); ++vx;
×
507
        vx->pos.set(win[0]-radius,win[1]-radius); std::memcpy(vx->color, starColor, 3); ++vx;
×
508
        vx->pos.set(win[0]+radius,win[1]+radius); std::memcpy(vx->color, starColor, 3); ++vx;
×
509
        vx->pos.set(win[0]-radius,win[1]+radius); std::memcpy(vx->color, starColor, 3); ++vx;
×
510

511
        ++nbPointSources;
×
512
        if (nbPointSources>=maxPointSources)
×
513
        {
514
                // Flush the buffer (draw all buffered stars)
515
                postDrawPointSource(sPainter);
×
516
        }
517
        return true;
×
518
}
519

520
// Draw's the Sun's corona during a solar eclipse on Earth.
521
void StelSkyDrawer::drawSunCorona(StelPainter* painter, const Vec3f& v, float radius, const Vec3f& color, const float alpha, const float angle)
×
522
{
523
        texSunCorona->bind();
×
524
        painter->setBlending(true, GL_ONE, GL_ONE);
×
525

526
        Vec3f win;
×
527
        painter->getProjector()->project(v, win);
×
528
        // For some reason we must mix color with the given alpha as well, else mixing does not work.
529
        painter->setColor(color*alpha, alpha);
×
530
        // pre-compensate the automatic scaling of sprite painting on HiDPI screens
531
        radius /= static_cast<float>(painter->getProjector()->getDevicePixelsPerPixel());
×
532
        // Our corona image was made in 2008-08-01 near Khovd, Mongolia. It shows the correct parallactic angle for its location and time, we must add this, and subtract the ecliptic/equator angle from that date of 15.43 degrees.
533
        painter->drawSprite2dMode(win[0], win[1], radius, -angle+44.65f-15.43f);
×
534

535
        postDrawPointSource(painter);
×
536
}
×
537

538
// Terminate drawing of a 3D model, draw the halo
539
void StelSkyDrawer::postDrawSky3dModel(StelPainter* painter, const Vec3d& v, float illuminatedArea, float mag, const Vec3f& color, const bool isSun)
×
540
{
541
        const float pixPerRad = painter->getProjector()->getPixelPerRadAtCenter();
×
542
        // Assume a disk shape
543
        float pixRadius = std::sqrt(illuminatedArea/(60.f*60.f)*M_PI_180f*M_PI_180f*(pixPerRad*pixPerRad))/M_PIf;
×
544
        float pxRd = pixRadius*3.f+100.f;
×
545
        bool noStarHalo = false;
×
546

547
        if (isSun)
×
548
        {
549
                // Sun, halo size varies in function of the magnitude because sun as seen from pluto should look dimmer
550
                // as the sun as seen from earth
551
                texSunHalo->bind();
×
552
                painter->setBlending(true, GL_ONE, GL_ONE);
×
553

554
                float rmag = big3dModelHaloRadius*(mag+15.f)/-11.f;
×
555
                float cmag = (rmag>=pxRd) ? 1.f : qMax(0.15f, 1.f-(pxRd-rmag)/100); // was qMax(0, .), but this would remove the halo when sun is dim.
×
556
                Vec3f win;
×
557
                painter->getProjector()->project(v, win);
×
558
                painter->setColor(color*cmag);
×
559
                painter->drawSprite2dModeNoDeviceScale(win[0], win[1], rmag);
×
560
                noStarHalo = true;
×
561
        }
562

563
        // Now draw the halo according the object brightness
564
        const bool saveTwinkle = flagStarTwinkle;
×
565
        flagStarTwinkle = false;
×
566
        const bool saveForcedTwinkle = flagForcedTwinkle;
×
567
        flagForcedTwinkle = false;
×
568
        const bool saveSpiky = flagStarSpiky;
×
569
        if (mag<-5.f) // exclude very bright objects only
×
570
                flagStarSpiky = false;
×
571
        else
572
                flagStarSpiky = saveSpiky;
×
573

574
        RCMag rcm;
575
        computeRCMag(mag, &rcm);
×
576

577
        // We now have the radius and luminosity of the small halo
578
        // If the disk of the planet is big enough to be visible, we should adjust the eye adaptation luminance
579
        // so that the radius of the halo is small enough to be not visible (so that we see the disk)
580

581
        // TODO: Change drawing halo to more realistic view of stars and planets
582
        float tStart = 3.f; // Was 2.f: planet's halo is too dim. Atque 2020-11-12: No need to change these anymore. It appears that this has to do with halo size vs FOV (?).
×
583
        float tStop = 6.f;
×
584
        bool truncated=false;
×
585

586
        float maxHaloRadius = qMax(tStart*6.f, pixRadius*3.f); //Atque 2020-11-12: Careful, if tStart*6.f is too big (tStart*10.f or something), the Moon gets a ridiculously big halo.
×
587
        if (rcm.radius>maxHaloRadius)
×
588
        {
589
                truncated = true;
×
590
                rcm.radius=maxHaloRadius+std::sqrt(rcm.radius-maxHaloRadius);
×
591
        }
592

593
        // Fade the halo away when the disk is too big
594
        if (pixRadius>=tStop)
×
595
        {
596
                rcm.luminance=0.f;
×
597
        }
598
        if (pixRadius>tStart && pixRadius<tStop)
×
599
        {
600
                rcm.luminance=(tStop-pixRadius)/(tStop-tStart);
×
601
        }
602

603
        if (truncated && flagLuminanceAdaptation)
×
604
        {
605
                float wl = findWorldLumForMag(mag, rcm.radius);
×
606
                if (wl>0)
×
607
                {
608
                        const float fov = static_cast<float>(core->getMovementMgr()->getCurrentFov());
×
609
                        // Report to the SkyDrawer that a very bright object (most notably Sun, Moon, bright planet)
610
                        // is in view. LP:1138533 correctly wants no such effect if object is hidden by landscape horizon.
611
                        LandscapeMgr* lmgr=GETSTELMODULE(LandscapeMgr);
×
612
                        Q_ASSERT(lmgr);
×
613
                        Landscape *landscape=lmgr->getCurrentLandscape();
×
614
                        Q_ASSERT(landscape);
×
615
                        float opacity=(landscape->getFlagShow() ? landscape->getOpacity(core->j2000ToAltAz(v, StelCore::RefractionAuto)) : 0.0f);
×
616
                        reportLuminanceInFov(qMin(700.f, qMin(wl/50, (60.f*60.f)/(fov*fov)*6.f))*(1.0f-opacity));
×
617
                }
618
        }
619

620
        if (!noStarHalo)
×
621
        {
622
                preDrawPointSource(painter);
×
623
                drawPointSource(painter, v, rcm, color);
×
624
                postDrawPointSource(painter);
×
625
        }
626
        flagStarTwinkle=saveTwinkle;
×
627
        flagForcedTwinkle=saveForcedTwinkle;
×
628
        flagStarSpiky=saveSpiky;
×
629
}
×
630

631
float StelSkyDrawer::findWorldLumForMag(float mag, float targetRadius) const
×
632
{
633
        const float saveLum = eye->getWorldAdaptationLuminance();        // save
×
634

635
        // Compute the luminance by dichotomy
636
        float a=0.001f;
×
637
        float b=500000.f;
×
638
        RCMag rcmag;
639
        rcmag.radius=-99;
×
640
        float curLum = 500.f;
×
641
        int safety=0;
×
642
        while (std::fabs(rcmag.radius-targetRadius)>0.1f)
×
643
        {
644
                eye->setWorldAdaptationLuminance(curLum);
×
645
                computeRCMag(mag, &rcmag);
×
646
                if (rcmag.radius<=targetRadius)
×
647
                {
648
                        float tmp = curLum;
×
649
                        curLum=(a+curLum)/2;
×
650
                        b=tmp;
×
651
                }
652
                else
653
                {
654
                        float tmp = curLum;
×
655
                        curLum=(b+curLum)/2;
×
656
                        a=tmp;
×
657
                }
658
                ++safety;
×
659
                if (safety>20)
×
660
                {
661
                        if (curLum>490000.f)
×
662
                        {
663
                                curLum = 500000.f;
×
664
                        }
665
                        else
666
                        {
667
                                curLum=-1;
×
668
                        }
669
                        break;
×
670
                }
671
        }
672

673
        eye->setWorldAdaptationLuminance(saveLum);        // restore
×
674

675
        return curLum;
×
676
}
677

678
// Report that an object of luminance lum is currently displayed
679
void StelSkyDrawer::reportLuminanceInFov(float lum, bool fastAdaptation)
×
680
{
681
        if (lum > maxLum)
×
682
        {
683
                if (oldLum<0)
×
684
                        oldLum=lum;
×
685
                // Use a log law for smooth transitions
686
                if (fastAdaptation==true && lum>oldLum)
×
687
                {
688
                        maxLum = lum;
×
689
                }
690
                else
691
                {
692
                        float transitionSpeed = 0.2f;
×
693
                        maxLum = std::exp(std::log(oldLum)+(std::log(lum)-std::log(oldLum))* qMin(1.f, 1.f/StelApp::getInstance().getFps()/transitionSpeed));
×
694
                }
695
        }
696
}
×
697

698
void StelSkyDrawer::preDraw()
×
699
{
700
        eye->setWorldAdaptationLuminance(maxLum);
×
701
        // Re-initialize for next stage
702
        oldLum = maxLum;
×
703
        maxLum = 0;
×
704
}
×
705

706

707
void StelSkyDrawer::setLightPollutionLuminance(const double luminance)
×
708
{
709
        if(lightPollutionLuminance==luminance)
×
710
                return;
×
711
        lightPollutionLuminance=luminance;
×
712
        emit lightPollutionLuminanceChanged(luminance);
×
713
}
714

715
int StelSkyDrawer::getBortleScaleIndex() const
×
716
{
717
        return StelCore::luminanceToBortleScaleIndex(lightPollutionLuminance);
×
718
}
719

720
void StelSkyDrawer::setFlagStarSpiky(bool b)
×
721
{
722
        if (b!=flagStarSpiky)
×
723
        {
724
                flagStarSpiky=b;
×
725
                emit flagStarSpikyChanged(flagStarSpiky);
×
726
        }
727
}
×
728

729
// colors for B-V display
730
Vec3f StelSkyDrawer::colorTable[128] = {
731
        Vec3f(0.602745f,0.713725f,1.000000f),
732
        Vec3f(0.604902f,0.715294f,1.000000f),
733
        Vec3f(0.607059f,0.716863f,1.000000f),
734
        Vec3f(0.609215f,0.718431f,1.000000f),
735
        Vec3f(0.611372f,0.720000f,1.000000f),
736
        Vec3f(0.613529f,0.721569f,1.000000f),
737
        Vec3f(0.635490f,0.737255f,1.000000f),
738
        Vec3f(0.651059f,0.749673f,1.000000f),
739
        Vec3f(0.666627f,0.762092f,1.000000f),
740
        Vec3f(0.682196f,0.774510f,1.000000f),
741
        Vec3f(0.697764f,0.786929f,1.000000f),
742
        Vec3f(0.713333f,0.799347f,1.000000f),
743
        Vec3f(0.730306f,0.811242f,1.000000f),
744
        Vec3f(0.747278f,0.823138f,1.000000f),
745
        Vec3f(0.764251f,0.835033f,1.000000f),
746
        Vec3f(0.781223f,0.846929f,1.000000f),
747
        Vec3f(0.798196f,0.858824f,1.000000f),
748
        Vec3f(0.812282f,0.868236f,1.000000f),
749
        Vec3f(0.826368f,0.877647f,1.000000f),
750
        Vec3f(0.840455f,0.887059f,1.000000f),
751
        Vec3f(0.854541f,0.896470f,1.000000f),
752
        Vec3f(0.868627f,0.905882f,1.000000f),
753
        Vec3f(0.884627f,0.916862f,1.000000f),
754
        Vec3f(0.900627f,0.927843f,1.000000f),
755
        Vec3f(0.916627f,0.938823f,1.000000f),
756
        Vec3f(0.932627f,0.949804f,1.000000f),
757
        Vec3f(0.948627f,0.960784f,1.000000f),
758
        Vec3f(0.964444f,0.972549f,1.000000f),
759
        Vec3f(0.980261f,0.984313f,1.000000f),
760
        Vec3f(0.996078f,0.996078f,1.000000f),
761
        Vec3f(1.000000f,1.000000f,1.000000f),
762
        Vec3f(1.000000f,0.999643f,0.999287f),
763
        Vec3f(1.000000f,0.999287f,0.998574f),
764
        Vec3f(1.000000f,0.998930f,0.997861f),
765
        Vec3f(1.000000f,0.998574f,0.997148f),
766
        Vec3f(1.000000f,0.998217f,0.996435f),
767
        Vec3f(1.000000f,0.997861f,0.995722f),
768
        Vec3f(1.000000f,0.997504f,0.995009f),
769
        Vec3f(1.000000f,0.997148f,0.994296f),
770
        Vec3f(1.000000f,0.996791f,0.993583f),
771
        Vec3f(1.000000f,0.996435f,0.992870f),
772
        Vec3f(1.000000f,0.996078f,0.992157f),
773
        Vec3f(1.000000f,0.991140f,0.981554f),
774
        Vec3f(1.000000f,0.986201f,0.970951f),
775
        Vec3f(1.000000f,0.981263f,0.960349f),
776
        Vec3f(1.000000f,0.976325f,0.949746f),
777
        Vec3f(1.000000f,0.971387f,0.939143f),
778
        Vec3f(1.000000f,0.966448f,0.928540f),
779
        Vec3f(1.000000f,0.961510f,0.917938f),
780
        Vec3f(1.000000f,0.956572f,0.907335f),
781
        Vec3f(1.000000f,0.951634f,0.896732f),
782
        Vec3f(1.000000f,0.946695f,0.886129f),
783
        Vec3f(1.000000f,0.941757f,0.875526f),
784
        Vec3f(1.000000f,0.936819f,0.864924f),
785
        Vec3f(1.000000f,0.931881f,0.854321f),
786
        Vec3f(1.000000f,0.926942f,0.843718f),
787
        Vec3f(1.000000f,0.922004f,0.833115f),
788
        Vec3f(1.000000f,0.917066f,0.822513f),
789
        Vec3f(1.000000f,0.912128f,0.811910f),
790
        Vec3f(1.000000f,0.907189f,0.801307f),
791
        Vec3f(1.000000f,0.902251f,0.790704f),
792
        Vec3f(1.000000f,0.897313f,0.780101f),
793
        Vec3f(1.000000f,0.892375f,0.769499f),
794
        Vec3f(1.000000f,0.887436f,0.758896f),
795
        Vec3f(1.000000f,0.882498f,0.748293f),
796
        Vec3f(1.000000f,0.877560f,0.737690f),
797
        Vec3f(1.000000f,0.872622f,0.727088f),
798
        Vec3f(1.000000f,0.867683f,0.716485f),
799
        Vec3f(1.000000f,0.862745f,0.705882f),
800
        Vec3f(1.000000f,0.858617f,0.695975f),
801
        Vec3f(1.000000f,0.854490f,0.686068f),
802
        Vec3f(1.000000f,0.850362f,0.676161f),
803
        Vec3f(1.000000f,0.846234f,0.666254f),
804
        Vec3f(1.000000f,0.842107f,0.656346f),
805
        Vec3f(1.000000f,0.837979f,0.646439f),
806
        Vec3f(1.000000f,0.833851f,0.636532f),
807
        Vec3f(1.000000f,0.829724f,0.626625f),
808
        Vec3f(1.000000f,0.825596f,0.616718f),
809
        Vec3f(1.000000f,0.821468f,0.606811f),
810
        Vec3f(1.000000f,0.817340f,0.596904f),
811
        Vec3f(1.000000f,0.813213f,0.586997f),
812
        Vec3f(1.000000f,0.809085f,0.577090f),
813
        Vec3f(1.000000f,0.804957f,0.567183f),
814
        Vec3f(1.000000f,0.800830f,0.557275f),
815
        Vec3f(1.000000f,0.796702f,0.547368f),
816
        Vec3f(1.000000f,0.792574f,0.537461f),
817
        Vec3f(1.000000f,0.788447f,0.527554f),
818
        Vec3f(1.000000f,0.784319f,0.517647f),
819
        Vec3f(1.000000f,0.784025f,0.520882f),
820
        Vec3f(1.000000f,0.783731f,0.524118f),
821
        Vec3f(1.000000f,0.783436f,0.527353f),
822
        Vec3f(1.000000f,0.783142f,0.530588f),
823
        Vec3f(1.000000f,0.782848f,0.533824f),
824
        Vec3f(1.000000f,0.782554f,0.537059f),
825
        Vec3f(1.000000f,0.782259f,0.540294f),
826
        Vec3f(1.000000f,0.781965f,0.543529f),
827
        Vec3f(1.000000f,0.781671f,0.546765f),
828
        Vec3f(1.000000f,0.781377f,0.550000f),
829
        Vec3f(1.000000f,0.781082f,0.553235f),
830
        Vec3f(1.000000f,0.780788f,0.556471f),
831
        Vec3f(1.000000f,0.780494f,0.559706f),
832
        Vec3f(1.000000f,0.780200f,0.562941f),
833
        Vec3f(1.000000f,0.779905f,0.566177f),
834
        Vec3f(1.000000f,0.779611f,0.569412f),
835
        Vec3f(1.000000f,0.779317f,0.572647f),
836
        Vec3f(1.000000f,0.779023f,0.575882f),
837
        Vec3f(1.000000f,0.778728f,0.579118f),
838
        Vec3f(1.000000f,0.778434f,0.582353f),
839
        Vec3f(1.000000f,0.778140f,0.585588f),
840
        Vec3f(1.000000f,0.777846f,0.588824f),
841
        Vec3f(1.000000f,0.777551f,0.592059f),
842
        Vec3f(1.000000f,0.777257f,0.595294f),
843
        Vec3f(1.000000f,0.776963f,0.598530f),
844
        Vec3f(1.000000f,0.776669f,0.601765f),
845
        Vec3f(1.000000f,0.776374f,0.605000f),
846
        Vec3f(1.000000f,0.776080f,0.608235f),
847
        Vec3f(1.000000f,0.775786f,0.611471f),
848
        Vec3f(1.000000f,0.775492f,0.614706f),
849
        Vec3f(1.000000f,0.775197f,0.617941f),
850
        Vec3f(1.000000f,0.774903f,0.621177f),
851
        Vec3f(1.000000f,0.774609f,0.624412f),
852
        Vec3f(1.000000f,0.774315f,0.627647f),
853
        Vec3f(1.000000f,0.774020f,0.630883f),
854
        Vec3f(1.000000f,0.773726f,0.634118f),
855
        Vec3f(1.000000f,0.773432f,0.637353f),
856
        Vec3f(1.000000f,0.773138f,0.640588f),
857
        Vec3f(1.000000f,0.772843f,0.643824f),
858
        Vec3f(1.000000f,0.772549f,0.647059f),
859
};
860

861
static float Gamma(float gamma, float x)
×
862
{
863
        return ((x<=0.f) ? 0.f : std::exp(gamma*std::log(x)));
×
864
}
865

866
static Vec3f Gamma(float gamma,const Vec3f &x)
×
867
{
868
        return Vec3f(Gamma(gamma,x[0]),Gamma(gamma,x[1]),Gamma(gamma,x[2]));
×
869
}
870

871
// Load B-V conversion parameters from config file
872
void StelSkyDrawer::initColorTableFromConfigFile(QSettings* conf)
×
873
{
874
        std::map<float,Vec3f> color_map;
×
875
        for (int bV100=-50;bV100<=400;bV100++)
×
876
        {
877
                QString entry = QString::asprintf("bv_color_%+5.2f", static_cast<double>(bV100)*0.01);
×
878
                const QStringList s(conf->value(QString("stars/") + entry).toStringList());
×
879
                if (!s.isEmpty())
×
880
                {
881
                        Vec3f c;
×
882
                        if (s.size()==1)
×
883
                                c = Vec3f(s[0]);
×
884
                        else
885
                                c =Vec3f(s);
×
886
                        color_map[bV100*0.01f] = Gamma(eye->getDisplayGamma(),c);
×
887
                }
888
        }
×
889

890
        if (color_map.size() > 1)
×
891
        {
892
                for (unsigned char i=0;i<128;i++)
×
893
                {
894
                        const float bV = StelSkyDrawer::indexToBV(i);
×
895
                        auto greater = color_map.upper_bound(bV);
×
896
                        if (greater == color_map.begin())
×
897
                        {
898
                                colorTable[i] = greater->second;
×
899
                        }
900
                        else
901
                        {
902
                                auto less = greater;--less;
×
903
                                if (greater == color_map.end())
×
904
                                {
905
                                        colorTable[i] = less->second;
×
906
                                }
907
                                else
908
                                {
909
                                        colorTable[i] = Gamma(1.f/eye->getDisplayGamma(), ((bV-less->first)*greater->second + (greater->first-bV)*less->second) *(1.f/(greater->first-less->first)));
×
910
                                }
911
                        }
912
                }
913
        }
914

915
//         QString res;
916
//         for (int i=0;i<128;i++)
917
//         {
918
//                 res += QString("Vec3f(%1,%2,%3),\n").arg(colorTable[i][0], 0, 'g', 6).arg(colorTable[i][1], 0, 'g', 6).arg(colorTable[i][2], 0, 'g', 6);
919
//         }
920
//         qDebug() << res;
921
}
×
922

923
double StelSkyDrawer::getWorldAdaptationLuminance() const
×
924
{
925
        return static_cast<double>(eye->getWorldAdaptationLuminance());
×
926
}
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