void Atmosphere::computeColor (double JD, Vec3d sunPos, Vec3d moonPos, float moonPhase, StelCore* core, float eclipseFac, float latitude, float altitude, float temperature, float relativeHumidity) { // We lazily initialize vertex buffer at the first draw, // so we can only call this after that. // We also need a renderer reference (again lazily from draw()) to // construct index buffers as they might change at every call to computeColor(). if(NULL == renderer) {return;} const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff); if (viewport != prj->getViewport()) { // The viewport changed: update the number of points in the grid updateGrid(prj); } eclipseFactor = eclipseFac; if(eclipseFac < 0.0001f) eclipseFactor = 0.0001f; // No need to calculate if not visible if (!fader.getInterstate()) { averageLuminance = 0.001f + lightPollutionLuminance; return; } // Calculate the atmosphere RGB for each point of the grid if (myisnan(sunPos.length())) sunPos.set(0.,0.,-1.*AU); if (myisnan(moonPos.length())) moonPos.set(0.,0.,-1.*AU); sunPos.normalize(); moonPos.normalize(); float sun_pos[3]; sun_pos[0] = sunPos[0]; sun_pos[1] = sunPos[1]; sun_pos[2] = sunPos[2]; float moon_pos[3]; moon_pos[0] = moonPos[0]; moon_pos[1] = moonPos[1]; moon_pos[2] = moonPos[2]; sky.setParamsv(sun_pos, 5.f); skyb.setLocation(latitude * M_PI/180., altitude, temperature, relativeHumidity); skyb.setSunMoon(moon_pos[2], sun_pos[2]); // Calculate the date from the julian day. int year, month, day; StelUtils::getDateFromJulianDay(JD, &year, &month, &day); skyb.setDate(year, month, moonPhase); // Variables used to compute the average sky luminance double sum_lum = 0.; Vec3d point(1., 0., 0.); skylightStruct2 b2; float lumi; vertexGrid->unlock(); // Compute the sky color for every point above the ground for (int i=0; i<(1+skyResolutionX)*(1+skyResolutionY); ++i) { const Vec2f position = vertexGrid->getVertex(i).position; prj->unProject(position[0], position[1], point); Q_ASSERT(fabs(point.lengthSquared()-1.0) < 1e-10); if (point[2]<=0) { point[2] = -point[2]; // The sky below the ground is the symmetric of the one above : // it looks nice and gives proper values for brightness estimation } // Use the Skybright.cpp 's models for brightness which gives better results. lumi = skyb.getLuminance(moon_pos[0]*point[0]+moon_pos[1]*point[1]+moon_pos[2]*point[2], sun_pos[0]*point[0]+sun_pos[1]*point[1]+sun_pos[2]*point[2], point[2]); lumi *= eclipseFactor; // Add star background luminance lumi += 0.0001; // Multiply by the input scale of the ToneConverter (is not done automatically by the xyYtoRGB method called later) //lumi*=eye->getInputScale(); // Add the light pollution luminance AFTER the scaling to avoid scaling it because it is the cause // of the scaling itself lumi += lightPollutionLuminance; // Store for later statistics sum_lum+=lumi; Q_ASSERT_X(NULL != vertexGrid, Q_FUNC_INFO, "Vertex buffer not initialized when setting colors"); // Now need to compute the xy part of the color component // This is done in a GLSL shader if possible if(NULL != shader) { // Store the back projected position + luminance in the input color to the shader const Vec4f color = Vec4f(point[0], point[1], point[2], lumi); vertexGrid->setVertex(i, Vertex(position, color)); continue; } // Shaderless fallback if (lumi > 0.01) { // Use the Skylight model for the color b2.pos[0] = point[0]; b2.pos[1] = point[1]; b2.pos[2] = point[2]; sky.getxyYValuev(b2); } else { // Too dark to see atmosphere color, don't bother computing it b2.color[0] = 0.25; b2.color[1] = 0.25; } const Vec4f color = Vec4f(b2.color[0], b2.color[1], lumi, 1.0f); vertexGrid->setVertex(i, Vertex(position, color)); } vertexGrid->lock(); // Update average luminance averageLuminance = sum_lum/((1+skyResolutionX)*(1+skyResolutionY)); }
void Atmosphere::updateGrid(const StelProjectorP projector) { viewport = projector->getViewport(); const float viewportWidth = projector->getViewportWidth(); const float viewportHeight = projector->getViewportHeight(); const float aspectRatio = viewportWidth / viewportHeight; skyResolutionY = StelApp::getInstance() .getSettings() ->value("landscape/atmosphereybin", 44) .toInt(); const float resolutionX = skyResolutionY * 0.5 * sqrt(3.0) * aspectRatio; skyResolutionX = static_cast<int>(floor(0.5 + resolutionX)); const float stepX = viewportWidth / (skyResolutionX - 0.5); const float stepY = viewportHeight / skyResolutionY; const float viewportLeft = projector->getViewportPosX(); const float viewportBottom = projector->getViewportPosY(); vertexGrid->unlock(); vertexGrid->clear(); // Construct the vertex grid. for(int y = 0; y <= skyResolutionY; ++y) { const float yPos = viewportBottom + y * stepY; for (int x = 0; x <= skyResolutionX; ++x) { const float offset = (x == 0) ? 0.0f : (x == skyResolutionX) ? viewportWidth : (x - 0.5 * (y & 1)) * stepX; const float xPos = viewportLeft + offset; vertexGrid->addVertex(Vertex(Vec2f(xPos, yPos), Vec4f())); } } vertexGrid->lock(); // The grid is (resolutionX + 1) * (resolutionY + 1), // so the rows are for 0 to resolutionY-1 // The last row includes vertices in row resolutionY // Construct an index buffer for each row in the grid. for(int row = 0; row < skyResolutionY; ++row) { StelIndexBuffer* buffer; // Reuse previously used row index buffer. if(rowIndices.size() > row) { buffer = rowIndices[row]; buffer->unlock(); buffer->clear(); } // Add new row index buffer. else { buffer = renderer->createIndexBuffer(IndexType_U16); rowIndices.append(buffer); } uint g0 = row * (1 + skyResolutionX); uint g1 = (row + 1) * (1 + skyResolutionX); for (int col = 0; col <= skyResolutionX; ++col) { buffer->addIndex(g0++); buffer->addIndex(g1++); } buffer->lock(); Q_ASSERT_X(buffer->length() == (skyResolutionX + 1) * 2, Q_FUNC_INFO, "Unexpected grid row index buffer size"); } Q_ASSERT_X(rowIndices.size() >= skyResolutionY, Q_FUNC_INFO, "Not enough row index buffers"); }