Atmosphere.cpp   Atmosphere.cpp 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*/ */
#include <QDebug> #include <QDebug>
#include <QFile>
#ifdef USE_OPENGL_ES2 #include <QTextStream>
#include "GLES2/gl2.h" #include <QSettings>
#endif
#include <QGLShaderProgram>
#include <QtOpenGL>
#include "Atmosphere.hpp" #include "Atmosphere.hpp"
#include "renderer/StelRenderer.hpp"
#include "StelUtils.hpp" #include "StelUtils.hpp"
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelProjector.hpp" #include "StelProjector.hpp"
#include "StelToneReproducer.hpp" #include "StelToneReproducer.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelPainter.hpp"
#include "StelFileMgr.hpp" #include "StelFileMgr.hpp"
inline bool myisnan(double value) inline bool myisnan(double value)
{ {
return value != value; return value != value;
} }
Atmosphere::Atmosphere(void) :viewport(0,0,0,0), posGrid(NULL), colorGrid(N Atmosphere::Atmosphere()
ULL), indices(NULL), : viewport(0,0,0,0)
averageLuminance(0.f), eclipseFac , averageLuminance(0.f)
tor(1.f), lightPollutionLuminance(0) , eclipseFactor(1.f)
, lightPollutionLuminance(0)
, shader(NULL)
, vertexGrid(NULL)
, renderer(NULL)
{ {
setFadeDuration(1.5f); setFadeDuration(1.5f);
useShader = StelApp::getInstance().getUseGLShaders();
if (useShader)
{
qDebug() << "Use vertex shader for atmosphere rendering.";
QGLShader* vShader = new QGLShader(QGLShader::Vertex);
if (!vShader->compileSourceFile(":/shaders/xyYToRGB.glsl"))
{
qWarning() << "Error while compiling shader: " << vS
hader->log();
useShader = false;
}
if (!vShader->log().isEmpty())
{
qWarning() << "Warnings while compiling vertex shade
r: " << vShader->log();
}
QGLShader* fShader = new QGLShader(QGLShader::Fragment);
if (!fShader->compileSourceCode(
"varying mediump vec4 result
SkyColor;\n"
"void main()\n"
"{\n"
" gl_FragColor = resultSk
yColor;\n"
"}"))
{
qWarning() << "Error while compiling fragment shader
: " << fShader->log();
useShader = false;
}
if (!fShader->log().isEmpty())
{
qWarning() << "Warnings while compiling fragment sha
der: " << vShader->log();
}
atmoShaderProgram = new QGLShaderProgram();
atmoShaderProgram->addShader(vShader);
atmoShaderProgram->addShader(fShader);
if (!atmoShaderProgram->link())
{
qWarning() << "Error while linking shader program: "
<< atmoShaderProgram->log();
useShader = false;
}
if (!atmoShaderProgram->log().isEmpty())
{
qWarning() << "Warnings while linking shader: " << a
tmoShaderProgram->log();
}
atmoShaderProgram->bind();
shaderAttribLocations.alphaWaOverAlphaDa = atmoShaderProgram
->uniformLocation("alphaWaOverAlphaDa");
shaderAttribLocations.oneOverGamma = atmoShaderProgram->unif
ormLocation("oneOverGamma");
shaderAttribLocations.term2TimesOneOverMaxdLpOneOverGamma =
atmoShaderProgram->uniformLocation("term2TimesOneOverMaxdLpOneOverGamma");
shaderAttribLocations.brightnessScale = atmoShaderProgram->u
niformLocation("brightnessScale");
shaderAttribLocations.sunPos = atmoShaderProgram->uniformLoc
ation("sunPos");
shaderAttribLocations.term_x = atmoShaderProgram->uniformLoc
ation("term_x");
shaderAttribLocations.Ax = atmoShaderProgram->uniformLocatio
n("Ax");
shaderAttribLocations.Bx = atmoShaderProgram->uniformLocatio
n("Bx");
shaderAttribLocations.Cx = atmoShaderProgram->uniformLocatio
n("Cx");
shaderAttribLocations.Dx = atmoShaderProgram->uniformLocatio
n("Dx");
shaderAttribLocations.Ex = atmoShaderProgram->uniformLocatio
n("Ex");
shaderAttribLocations.term_y = atmoShaderProgram->uniformLoc
ation("term_y");
shaderAttribLocations.Ay = atmoShaderProgram->uniformLocatio
n("Ay");
shaderAttribLocations.By = atmoShaderProgram->uniformLocatio
n("By");
shaderAttribLocations.Cy = atmoShaderProgram->uniformLocatio
n("Cy");
shaderAttribLocations.Dy = atmoShaderProgram->uniformLocatio
n("Dy");
shaderAttribLocations.Ey = atmoShaderProgram->uniformLocatio
n("Ey");
shaderAttribLocations.projectionMatrix = atmoShaderProgram->
uniformLocation("projectionMatrix");
shaderAttribLocations.skyVertex = atmoShaderProgram->attribu
teLocation("skyVertex");
shaderAttribLocations.skyColor = atmoShaderProgram->attribut
eLocation("skyColor");
atmoShaderProgram->release();
}
} }
Atmosphere::~Atmosphere(void) Atmosphere::~Atmosphere(void)
{ {
if (posGrid) if(NULL != shader) {delete shader;}
{ if(NULL != vertexGrid) {delete vertexGrid;}
delete[] posGrid; foreach(StelIndexBuffer* buffer, rowIndices)
posGrid = NULL;
}
if (colorGrid)
{ {
delete[] colorGrid; delete buffer;
colorGrid = NULL;
}
if (indices)
{
delete[] indices;
indices = NULL;
}
if (useShader)
{
delete atmoShaderProgram;
} }
} }
void Atmosphere::computeColor(double JD, Vec3d _sunPos, Vec3d moonPos, floa void Atmosphere::computeColor
t moonPhase, (double JD, Vec3d sunPos, Vec3d moonPos, float moonPhase, StelCore*
StelCore* core, f core, float eclipseFac,
loat latitude, float altitude, float temperature, float relativeHumidity) float latitude, float altitude, float temperature, float relativeHu
midity)
{ {
// 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 com
puteColor().
if(NULL == renderer) {return;}
const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff); const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
if (viewport != prj->getViewport()) if (viewport != prj->getViewport())
{ {
// The viewport changed: update the number of point of the g // The viewport changed: update the number of points in the
rid grid
viewport = prj->getViewport(); updateGrid(prj);
if (posGrid)
delete[] posGrid;
if (colorGrid)
delete[] colorGrid;
if (indices)
delete[] indices;
skyResolutionY = StelApp::getInstance().getSettings()->value
("landscape/atmosphereybin", 44).toInt();
skyResolutionX = (int)floor(0.5+skyResolutionY*(0.5*sqrt(3.0
))*prj->getViewportWidth()/prj->getViewportHeight());
posGrid = new Vec2f[(1+skyResolutionX)*(1+skyResolutionY)];
colorGrid = new Vec4f[(1+skyResolutionX)*(1+skyResolutionY)]
;
float stepX = (float)prj->getViewportWidth() / (skyResolutio
nX-0.5);
float stepY = (float)prj->getViewportHeight() / skyResolutio
nY;
float viewport_left = (float)prj->getViewportPosX();
float viewport_bottom = (float)prj->getViewportPosY();
for (int x=0; x<=skyResolutionX; ++x)
{
for(int y=0; y<=skyResolutionY; ++y)
{
Vec2f &v(posGrid[y*(1+skyResolutionX)+x]);
v[0] = viewport_left + ((x == 0) ? 0.f :
(x == skyResolutionX) ? (flo
at)prj->getViewportWidth() : (x-0.5*(y&1))*stepX);
v[1] = viewport_bottom+y*stepY;
}
}
// Generate the indices used to draw the quads
indices = new unsigned int[(skyResolutionX+1)*skyResolutionY
*2];
int i=0;
for (int y2=0; y2<skyResolutionY; ++y2)
{
unsigned int g0 = y2*(1+skyResolutionX);
unsigned int g1 = (y2+1)*(1+skyResolutionX);
for (int x2=0; x2<=skyResolutionX; ++x2)
{
indices[i++]=g0++;
indices[i++]=g1++;
}
}
} }
if (myisnan(_sunPos.length())) eclipseFactor = eclipseFac;
_sunPos.set(0.,0.,-1.*AU); if(eclipseFac < 0.0001f)
if (myisnan(moonPos.length())) eclipseFactor = 0.0001f;
moonPos.set(0.,0.,-1.*AU);
// Update the eclipse intensity factor to apply on atmosphere model
// these are for radii
const float sun_angular_size = atan(696000.f/AU/_sunPos.length());
const float moon_angular_size = atan(1738.f/AU/moonPos.length());
const float touch_angle = sun_angular_size + moon_angular_size;
// determine luminance falloff during solar eclipses
_sunPos.normalize();
moonPos.normalize();
float separation_angle = std::acos(_sunPos.dot(moonPos)); // angle
between them
// qDebug("touch at %f\tnow at %f (%f)\n", touch_angle, separation_a
ngle, separation_angle/touch_angle);
// bright stars should be visible at total eclipse
// TODO: correct for atmospheric diffusion
// TODO: use better coverage function (non-linear)
// because of above issues, this algorithm darkens more quickly than
reality
if (separation_angle < touch_angle)
{
float dark_angle = moon_angular_size - sun_angular_size;
float min = 0.0001f; // so bright stars show up at total ec
lipse
if (dark_angle < 0.f)
{
// annular eclipse
float asun = sun_angular_size*sun_angular_size;
min = (asun - moon_angular_size*moon_angular_size)/a
sun; // minimum proportion of sun uncovered
dark_angle *= -1;
}
if (separation_angle < dark_angle)
eclipseFactor = min;
else
eclipseFactor = min + (1.f-min)*(separation_angle-da
rk_angle)/(touch_angle-dark_angle);
}
else
eclipseFactor = 1.f;
// No need to calculate if not visible // No need to calculate if not visible
if (!fader.getInterstate()) if (!fader.getInterstate())
{ {
averageLuminance = 0.001f + lightPollutionLuminance; averageLuminance = 0.001f + lightPollutionLuminance;
return; return;
} }
// Calculate the atmosphere RGB for each point of the grid // Calculate the atmosphere RGB for each point of the grid
float sunPos[3]; if (myisnan(sunPos.length()))
sunPos[0] = _sunPos[0]; sunPos.set(0.,0.,-1.*AU);
sunPos[1] = _sunPos[1]; if (myisnan(moonPos.length()))
sunPos[2] = _sunPos[2]; 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]; float moon_pos[3];
moon_pos[0] = moonPos[0]; moon_pos[0] = moonPos[0];
moon_pos[1] = moonPos[1]; moon_pos[1] = moonPos[1];
moon_pos[2] = moonPos[2]; moon_pos[2] = moonPos[2];
sky.setParamsv(sunPos, 5.f); sky.setParamsv(sun_pos, 5.f);
skyb.setLocation(latitude * M_PI/180., altitude, temperature, relati veHumidity); skyb.setLocation(latitude * M_PI/180., altitude, temperature, relati veHumidity);
skyb.setSunMoon(moon_pos[2], sunPos[2]); skyb.setSunMoon(moon_pos[2], sun_pos[2]);
// Calculate the date from the julian day. // Calculate the date from the julian day.
int year, month, day; int year, month, day;
StelUtils::getDateFromJulianDay(JD, &year, &month, &day); StelUtils::getDateFromJulianDay(JD, &year, &month, &day);
skyb.setDate(year, month, moonPhase); skyb.setDate(year, month, moonPhase);
// Variables used to compute the average sky luminance // Variables used to compute the average sky luminance
double sum_lum = 0.; double sum_lum = 0.;
Vec3d point(1., 0., 0.); Vec3d point(1., 0., 0.);
skylightStruct2 b2; skylightStruct2 b2;
float lumi; float lumi;
vertexGrid->unlock();
// Compute the sky color for every point above the ground // Compute the sky color for every point above the ground
for (int i=0; i<(1+skyResolutionX)*(1+skyResolutionY); ++i) for (int i=0; i<(1+skyResolutionX)*(1+skyResolutionY); ++i)
{ {
const Vec2f &v(posGrid[i]); const Vec2f position = vertexGrid->getVertex(i).position;
prj->unProject(v[0],v[1],point); prj->unProject(position[0], position[1], point);
Q_ASSERT(fabs(point.lengthSquared()-1.0) < 1e-10); Q_ASSERT(fabs(point.lengthSquared()-1.0) < 1e-10);
if (point[2]<=0) if (point[2]<=0)
{ {
point[2] = -point[2]; point[2] = -point[2];
// The sky below the ground is the symmetric of the one above : // The sky below the ground is the symmetric of the one above :
// it looks nice and gives proper values for brightn ess estimation // it looks nice and gives proper values for brightn ess estimation
} }
// Use the Skybright.cpp 's models for brightness which give s better results. // Use the Skybright.cpp 's models for brightness which give s better results.
lumi = skyb.getLuminance(moon_pos[0]*point[0]+moon_pos[1]*po lumi = skyb.getLuminance(moon_pos[0]*point[0]+moon_pos[1]*po
int[1]+ int[1]+moon_pos[2]*point[2],
moon_pos[2]*point[2], sunPos[0]*point[0]+sun sun_pos[0]*
Pos[1]*point[1]+ point[0]+sun_pos[1]*point[1]+sun_pos[2]*point[2],
sunPos[2]*point[2], point[2]); point[2]);
lumi *= eclipseFactor; lumi *= eclipseFactor;
// Add star background luminance // Add star background luminance
lumi += 0.0001; lumi += 0.0001;
// Multiply by the input scale of the ToneConverter (is not done automatically by the xyYtoRGB method called later) // Multiply by the input scale of the ToneConverter (is not done automatically by the xyYtoRGB method called later)
//lumi*=eye->getInputScale(); //lumi*=eye->getInputScale();
// Add the light pollution luminance AFTER the scaling to av oid scaling it because it is the cause // Add the light pollution luminance AFTER the scaling to av oid scaling it because it is the cause
// of the scaling itself // of the scaling itself
lumi += lightPollutionLuminance; lumi += lightPollutionLuminance;
// Store for later statistics // Store for later statistics
sum_lum+=lumi; sum_lum+=lumi;
Q_ASSERT_X(NULL != vertexGrid, Q_FUNC_INFO,
"Vertex buffer not initialized when setting color
s");
// Now need to compute the xy part of the color component // Now need to compute the xy part of the color component
// This can be done in the openGL shader if possible // This is done in a GLSL shader if possible
if (useShader) if(NULL != shader)
{ {
// Store the back projected position + luminance in the input color to the shader // Store the back projected position + luminance in the input color to the shader
colorGrid[i].set(point[0], point[1], point[2], lumi) 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 else
{ {
if (lumi>0.01) // Too dark to see atmosphere color, don't bother co
{ mputing it
b2.pos[0] = point[0]; b2.color[0] = 0.25;
b2.pos[1] = point[1]; b2.color[1] = 0.25;
b2.pos[2] = point[2];
// Use the Skylight model for the color
sky.getxyYValuev(b2);
}
else
{
// Too dark to see atmosphere color, don't b
other computing it
b2.color[0]=0.25;
b2.color[1]=0.25;
}
colorGrid[i].set(b2.color[0], b2.color[1], lumi, 1.f
);
} }
const Vec4f color = Vec4f(b2.color[0], b2.color[1], lumi, 1.
0f);
vertexGrid->setVertex(i, Vertex(position, color));
} }
vertexGrid->lock();
// Update average luminance // Update average luminance
averageLuminance = sum_lum/((1+skyResolutionX)*(1+skyResolutionY)); averageLuminance = sum_lum/((1+skyResolutionX)*(1+skyResolutionY));
} }
// Draw the atmosphere using the precalc values stored in tab_sky void Atmosphere::draw(StelCore* core, StelRenderer* renderer)
void Atmosphere::draw(StelCore* core)
{ {
// Renderer is NULL at first draw call.
// We load the shader, initialize vertex buffer and set the renderer
.
//
// We don't actually draw anything at the first call - computeColor
// must be called to fill the vertex buffer with drawable data.
if(NULL == this->renderer)
{
Q_ASSERT_X(NULL == shader && NULL == vertexGrid && rowIndice
s.size() == 0,
Q_FUNC_INFO, "Shader and/or vertex/index buffer i
nitialized at first draw call");
if(renderer->isGLSLSupported())
{
if(!lazyLoadShader(renderer))
{
qWarning() << "Failed loading atmosphere sha
der. Falling back to CPU code path";
}
}
vertexGrid = renderer->createVertexBuffer<Vertex>(PrimitiveT
ype_TriangleStrip);
this->renderer = renderer;
return;
}
Q_ASSERT_X(NULL != vertexGrid && rowIndices.size() > 0, Q_FUNC_INFO,
"Vertex and/or index buffer not initialized at first draw
call");
Q_ASSERT_X(vertexGrid->length() == (skyResolutionY + 1) * (skyResolu
tionX + 1),
Q_FUNC_INFO, "Vertex grid size doesn't match atmosphere r
esolution");
Q_ASSERT_X(rowIndices.size() == skyResolutionY, Q_FUNC_INFO,
"Number of row index buffers doesn't match atmosphere res
olution");
if (StelApp::getInstance().getVisionModeNight()) if (StelApp::getInstance().getVisionModeNight())
{
return; return;
}
StelToneReproducer* eye = core->getToneReproducer(); StelToneReproducer* eye = core->getToneReproducer();
if (!fader.getInterstate()) if (!fader.getInterstate())
{
return; return;
}
StelPainter sPainter(core->getProjection2d()); renderer->setBlendMode(BlendMode_Add);
glBlendFunc(GL_ONE, GL_ONE);
sPainter.enableTexture2d(false);
glEnable(GL_BLEND);
const float atm_intensity = fader.getInterstate(); const float atm_intensity = fader.getInterstate();
if (useShader) if(NULL != shader)
{ {
atmoShaderProgram->bind(); shader->bind();
float a, b, c; float a, b, c;
eye->getShadersParams(a, b, c); eye->getShadersParams(a, b, c);
atmoShaderProgram->setUniformValue(shaderAttribLocations.alp
haWaOverAlphaDa, a); shader->setUniformValue("alphaWaOverAlphaDa"
atmoShaderProgram->setUniformValue(shaderAttribLocations.one , a);
OverGamma, b); shader->setUniformValue("oneOverGamma"
atmoShaderProgram->setUniformValue(shaderAttribLocations.ter , b);
m2TimesOneOverMaxdLpOneOverGamma, c); shader->setUniformValue("term2TimesOneOverMaxdLpOneOverGamma
atmoShaderProgram->setUniformValue(shaderAttribLocations.bri " , c);
ghtnessScale, atm_intensity); shader->setUniformValue("brightnessScale"
, atm_intensity);
Vec3f sunPos; Vec3f sunPos;
float term_x, Ax, Bx, Cx, Dx, Ex, term_y, Ay, By, Cy, Dy, Ey ; float term_x, Ax, Bx, Cx, Dx, Ex, term_y, Ay, By, Cy, Dy, Ey ;
sky.getShadersParams(sunPos, term_x, Ax, Bx, Cx, Dx, Ex, ter m_y, Ay, By, Cy, Dy, Ey); sky.getShadersParams(sunPos, term_x, Ax, Bx, Cx, Dx, Ex, ter m_y, Ay, By, Cy, Dy, Ey);
atmoShaderProgram->setUniformValue(shaderAttribLocations.sun
Pos, sunPos[0], sunPos[1], sunPos[2]); shader->setUniformValue("sunPos" , sunPos);
atmoShaderProgram->setUniformValue(shaderAttribLocations.ter shader->setUniformValue("term_x" , term_x);
m_x, term_x); shader->setUniformValue("Ax" , Ax);
atmoShaderProgram->setUniformValue(shaderAttribLocations.Ax, shader->setUniformValue("Bx" , Bx);
Ax); shader->setUniformValue("Cx" , Cx);
atmoShaderProgram->setUniformValue(shaderAttribLocations.Bx, shader->setUniformValue("Dx" , Dx);
Bx); shader->setUniformValue("Ex" , Ex);
atmoShaderProgram->setUniformValue(shaderAttribLocations.Cx, shader->setUniformValue("term_y" , term_y);
Cx); shader->setUniformValue("Ay" , Ay);
atmoShaderProgram->setUniformValue(shaderAttribLocations.Dx, shader->setUniformValue("By" , By);
Dx); shader->setUniformValue("Cy" , Cy);
atmoShaderProgram->setUniformValue(shaderAttribLocations.Ex, shader->setUniformValue("Dy" , Dy);
Ex); shader->setUniformValue("Ey" , Ey);
atmoShaderProgram->setUniformValue(shaderAttribLocations.ter
m_y, term_y); const Mat4f& projectionMatrix = core->getProjection2d()->get
atmoShaderProgram->setUniformValue(shaderAttribLocations.Ay, ProjectionMatrix();
Ay); shader->setUniformValue("projectionMatrix", projectionMatrix
atmoShaderProgram->setUniformValue(shaderAttribLocations.By, );
By);
atmoShaderProgram->setUniformValue(shaderAttribLocations.Cy, for(int row = 0; row < skyResolutionY; ++row)
Cy); {
atmoShaderProgram->setUniformValue(shaderAttribLocations.Dy, renderer->drawVertexBuffer(vertexGrid, rowIndices[ro
Dy); w]);
atmoShaderProgram->setUniformValue(shaderAttribLocations.Ey, }
Ey);
const Mat4f& m = sPainter.getProjector()->getProjectionMatri shader->release();
x();
atmoShaderProgram->setUniformValue(shaderAttribLocations.pro
jectionMatrix,
QMatrix4x4(m[0], m[4], m[8], m[12], m[1], m[5], m[9]
, m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]));
atmoShaderProgram->enableAttributeArray(shaderAttribLocation
s.skyVertex);
atmoShaderProgram->enableAttributeArray(shaderAttribLocation
s.skyColor);
atmoShaderProgram->setAttributeArray(shaderAttribLocations.s
kyVertex, (const GLfloat*)posGrid, 2, 0);
atmoShaderProgram->setAttributeArray(shaderAttribLocations.s
kyColor, (const GLfloat*)colorGrid, 4, 0);
// And draw everything at once
unsigned int* shift=indices;
for (int y=0;y<skyResolutionY;++y)
{
glDrawElements(GL_TRIANGLE_STRIP, (skyResolutionX+1)
*2, GL_UNSIGNED_INT, shift);
shift += (skyResolutionX+1)*2;
}
atmoShaderProgram->disableAttributeArray(shaderAttribLocatio
ns.skyVertex);
atmoShaderProgram->disableAttributeArray(shaderAttribLocatio
ns.skyColor);
atmoShaderProgram->release();
} }
else else
{ {
// No shader is available on this graphics card, compute col ors with the CPU // No shader is available on this graphics card, compute col ors on the CPU.
// Adapt luminance at this point to avoid a mismatch with th e adaptation value // Adapt luminance at this point to avoid a mismatch with th e adaptation value
for (int i=0;i<(1+skyResolutionX)*(1+skyResolutionY);++i) vertexGrid->unlock();
for (int i = 0; i < (1 + skyResolutionX) * (1 + skyResoluti
onY); ++i)
{
Vertex vertex = vertexGrid->getVertex(i);
eye->xyYToRGB(vertex.color);
vertex.color *= atm_intensity;
vertexGrid->setVertex(i, vertex);
}
vertexGrid->lock();
for(int row = 0; row < skyResolutionY; ++row)
{
renderer->drawVertexBuffer(vertexGrid, rowIndices[ro
w]);
}
}
}
bool Atmosphere::lazyLoadShader(StelRenderer* renderer)
{
qDebug() << "Using vertex shader for atmosphere rendering.";
QFile vertexShaderFile(":/shaders/xyYToRGB.glsl");
if(!vertexShaderFile.open(QIODevice::ReadOnly))
{
qWarning() << "Error opening shader file: ':/shaders/xyYToRG
B.glsl'";
return false;
}
shader = renderer->createGLSLShader();
if(!shader->addVertexShader(QTextStream(&vertexShaderFile).readAll()
))
{
qWarning() << "Error adding atmosphere vertex shader: " << s
hader->log();
delete shader;
shader = NULL;
return false;
}
if(!shader->addFragmentShader("varying mediump vec4 resultSkyColor;\
n"
"void main()\n"
"{\n"
" gl_FragColor = resultSkyColor;\n"
"}"))
{
qWarning() << "Error adding atmosphere fragment shader: " <<
shader->log();
delete shader;
shader = NULL;
return false;
}
if(!shader->build())
{
qWarning() << "Error building atmosphere shader: " << shader
->log();
delete shader;
shader = NULL;
return false;
}
if(!shader->log().isEmpty())
{
qDebug() << "Atmosphere shader build log: " << shader->log()
;
}
return true;
}
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/atmosphereybi
n", 44)
.toInt();
const float resolutionX = skyResolutionY * 0.5 * sqrt(3.0) * aspe
ctRatio;
skyResolutionX = static_cast<int>(floor(0.5 + resolution
X));
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) ? viewpor
tWidth
: (x - 0.
5 * (y & 1)) * stepX;
const float xPos = viewportLeft + offset;
vertexGrid->addVertex(Vertex(Vec2f(xPos, yPos), Vec4
f()));
}
}
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
{ {
Vec4f& c = colorGrid[i]; buffer = renderer->createIndexBuffer(IndexType_U16);
eye->xyYToRGB(c); rowIndices.append(buffer);
c*=atm_intensity;
} }
sPainter.setShadeModel(StelPainter::ShadeModelSmooth);
sPainter.enableClientStates(true, false, true, false);
sPainter.setColorPointer(4, GL_FLOAT, colorGrid);
sPainter.setVertexPointer(2, GL_FLOAT, posGrid);
// And draw everything at once uint g0 = row * (1 + skyResolutionX);
unsigned int* shift=indices; uint g1 = (row + 1) * (1 + skyResolutionX);
for (int y=0;y<skyResolutionY;++y) for (int col = 0; col <= skyResolutionX; ++col)
{ {
sPainter.drawFromArray(StelPainter::TriangleStrip, ( buffer->addIndex(g0++);
skyResolutionX+1)*2, 0, false, shift); buffer->addIndex(g1++);
shift += (skyResolutionX+1)*2;
} }
sPainter.setShadeModel(StelPainter::ShadeModelFlat); buffer->lock();
Q_ASSERT_X(buffer->length() == (skyResolutionX + 1) * 2, Q_F
UNC_INFO,
"Unexpected grid row index buffer size");
} }
Q_ASSERT_X(rowIndices.size() >= skyResolutionY, Q_FUNC_INFO,
"Not enough row index buffers");
} }
 End of changes. 42 change blocks. 
339 lines changed or deleted 316 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/