예제 #1
0
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));
}
예제 #2
0
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");
}