Refactor code to draw objects as points

* provide common routine to calculate point size
 * precalculate saturation magnitude
 * remove unused variables
pull/1337/head
Hleb Valoshka 2022-01-09 23:23:05 +02:00
parent 29a2e1ec1c
commit 20a4d13328
5 changed files with 95 additions and 138 deletions

View File

@ -25,30 +25,14 @@ template <class OBJ, class PREC> class ObjectRenderer : public OctreeProcessor<O
const Observer* observer { nullptr };
Renderer* renderer { nullptr };
Eigen::Vector3f viewNormal;
float fov { 0.0f };
float size { 0.0f };
float pixelSize { 0.0f };
float faintestMag { 0.0f };
float faintestMagNight { 0.0f };
float saturationMag { 0.0f };
float brightnessScale { 0.0f };
float brightnessBias { 0.0f };
float distanceLimit { 0.0f };
// Objects brighter than labelThresholdMag will be labeled
float labelThresholdMag { 0.0f };
// These are not fully used by this template's descendants
// but we place them here just in case a more sophisticated
// rendering scheme is implemented:
int nRendered { 0 };
int nClose { 0 };
int nBright { 0 };
int nProcessed { 0 };
int nLabelled { 0 };
uint64_t renderFlags { 0 };
int labelMode { 0 };
};

View File

@ -34,7 +34,8 @@ PointStarRenderer::PointStarRenderer() :
void PointStarRenderer::process(const Star& star, float distance, float appMag)
{
nProcessed++;
if (distance > distanceLimit)
return;
Vector3f starPos = star.getPosition();
@ -44,9 +45,6 @@ void PointStarRenderer::process(const Star& star, float distance, float appMag)
float orbitalRadius = star.getOrbitalRadius();
bool hasOrbit = orbitalRadius > 0.0f;
if (distance > distanceLimit)
return;
// A very rough check to see if the star may be visible: is the star in
// front of the viewer? If the star might be close (relPos.x^2 < 0.1) or
// is moving in an orbit, we'll always regard it as potentially visible.
@ -69,10 +67,10 @@ void PointStarRenderer::process(const Star& star, float distance, float appMag)
// * It may be large enough that we should render it as a mesh
// instead of a particle
// It's possible that the second condition might apply for stars
// further than one light year away if the star is huge, the fov is
// further than a solar system size if the star is huge, the fov is
// very small and the resolution is high. We'll ignore this for now
// and use the most inexpensive test possible . . .
if (distance < 1.0f || orbitSizeInPixels > 1.0f)
if (distance < SolarSystemMaxDistance || orbitSizeInPixels > 1.0f)
{
// Compute the position of the observer relative to the star.
// This is a much more accurate (and expensive) distance
@ -85,10 +83,9 @@ void PointStarRenderer::process(const Star& star, float distance, float appMag)
distance = relPos.norm();
// Recompute apparent magnitude using new distance computation
appMag = star.getApparentMagnitude((float)distance);
appMag = star.getApparentMagnitude(distance);
discSizeInPixels = star.getRadius() / astro::lightYearsToKilometers(distance) / pixelSize;
++nClose;
}
// Stars closer than the maximum solar system size are actually
@ -96,44 +93,19 @@ void PointStarRenderer::process(const Star& star, float distance, float appMag)
// planets.
if (distance > SolarSystemMaxDistance)
{
float satPoint = faintestMag - (1.0f - brightnessBias) / brightnessScale; // TODO: precompute this value
float alpha = (faintestMag - appMag) * brightnessScale + brightnessBias;
float pointSize, alpha, glareSize, glareAlpha;
float size = BaseStarDiscSize * static_cast<float>(renderer->getScreenDpi()) / 96.0f;
renderer->calculatePointSize(appMag,
size,
pointSize,
alpha,
glareSize,
glareAlpha);
if (useScaledDiscs)
{
float discSize = size;
if (alpha < 0.0f)
{
alpha = 0.0f;
}
else if (alpha > 1.0f)
{
float discScale = min(MaxScaledDiscStarSize, (float) pow(2.0f, 0.3f * (satPoint - appMag)));
discSize *= discScale;
float glareAlpha = min(0.5f, discScale / 4.0f);
glareVertexBuffer->addStar(relPos, Color(starColor, glareAlpha), discSize * 3.0f);
alpha = 1.0f;
}
starVertexBuffer->addStar(relPos, Color(starColor, alpha), discSize);
}
else
{
if (alpha < 0.0f)
{
alpha = 0.0f;
}
else if (alpha > 1.0f)
{
float discScale = min(100.0f, satPoint - appMag + 2.0f);
float glareAlpha = min(GlareOpacity, (discScale - 2.0f) / 4.0f);
glareVertexBuffer->addStar(relPos, Color(starColor, glareAlpha), 2.0f * discScale * size);
}
starVertexBuffer->addStar(relPos, Color(starColor, alpha), size);
}
++nRendered;
if (glareSize != 0.0f)
glareVertexBuffer->addStar(relPos, Color(starColor, glareAlpha), glareSize);
if (pointSize != 0.0f)
starVertexBuffer->addStar(relPos, Color(starColor, alpha), pointSize);
// Place labels for stars brighter than the specified label threshold brightness
if (((labelMode & Renderer::StarLabels) != 0) && appMag < labelThresholdMag)
@ -147,7 +119,6 @@ void PointStarRenderer::process(const Star& star, float distance, float appMag)
starDB->getStarName(star, true),
color,
relPos);
nLabelled++;
}
}
}

View File

@ -43,13 +43,12 @@ class PointStarRenderer : public ObjectRenderer<Star, float>
void process(const Star &star, float distance, float appMag);
Eigen::Vector3d obsPos;
Eigen::Vector3f viewNormal;
std::vector<RenderListEntry>* renderList { nullptr };
PointStarVertexBuffer* starVertexBuffer { nullptr };
PointStarVertexBuffer* glareVertexBuffer { nullptr };
const StarDatabase* starDB { nullptr };
const ColorTemperatureTable* colorTemp { nullptr };
float SolarSystemMaxDistance { 1.0f };
float maxDiscSize { 1.0f };
float cosFOV { 1.0f };
bool useScaledDiscs { false };
};

View File

@ -1560,6 +1560,13 @@ void Renderer::draw(const Observer& observer,
else
brightnessScale = 0.1667f;
brightnessScale *= corrFac;
if (starStyle == ScaledDiscStars)
brightnessScale *= 2.0f;
// Calculate saturation magnitude
satPoint = faintestMag - (1.0f - brightnessBias) / brightnessScale;
ambientColor = Color(ambientLightLevel, ambientLightLevel, ambientLightLevel);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
@ -1742,6 +1749,50 @@ void renderLargePoint(Renderer &renderer,
}
void
Renderer::calculatePointSize(float appMag,
float size,
float &discSize,
float &alpha,
float &glareSize,
float &glareAlpha) const
{
alpha = std::max(0.0f, (faintestMag - appMag) * brightnessScale + brightnessBias);
discSize = size;
if (starStyle == ScaledDiscStars)
{
if (alpha > 1.0f)
{
float discScale = std::min(MaxScaledDiscStarSize, pow(2.0f, 0.3f * (satPoint - appMag)));
discSize *= std::max(1.0f, discScale);
glareAlpha = std::min(0.5f, discScale / 4.0f);
glareSize = discSize * 3.0f;
alpha = 1.0f;
}
else
{
glareSize = glareAlpha = 0.0f;
}
}
else
{
if (alpha > 1.0f)
{
float discScale = std::min(100.0f, satPoint - appMag + 2.0f);
glareAlpha = std::min(GlareOpacity, (discScale - 2.0f) / 4.0f);
glareSize = 2.0f * discScale * size;
alpha = 1.0f;
}
else
{
glareSize = glareAlpha = 0.0f;
}
}
}
// If the an object occupies a pixel or less of screen space, we don't
// render its mesh at all and just display a starlike point instead.
// Switching between the particle and mesh renderings of an object is
@ -1751,74 +1802,38 @@ void renderLargePoint(Renderer &renderer,
void Renderer::renderObjectAsPoint(const Vector3f& position,
float radius,
float appMag,
float _faintestMag,
float discSizeInPixels,
const Color &color,
bool useHalos,
bool emissive,
const Matrices &mvp)
{
const float maxSize = MaxScaledDiscStarSize;
float maxDiscSize = (starStyle == ScaledDiscStars) ? maxSize : 1.0f;
const bool useScaledDiscs = starStyle == ScaledDiscStars;
float maxDiscSize = useScaledDiscs ? MaxScaledDiscStarSize : 1.0f;
float maxBlendDiscSize = maxDiscSize + 3.0f;
bool useScaledDiscs = starStyle == ScaledDiscStars;
if (discSizeInPixels < maxBlendDiscSize || useHalos)
{
float alpha = 1.0f;
float fade = 1.0f;
float size = BaseStarDiscSize * screenDpi / 96.0f;
float satPoint = _faintestMag - (1.0f - brightnessBias) / brightnessScale;
if (discSizeInPixels > maxDiscSize)
{
fade = (maxBlendDiscSize - discSizeInPixels) /
(maxBlendDiscSize - maxDiscSize);
if (fade > 1)
fade = 1;
fade = std::min(1.0f, (maxBlendDiscSize - discSizeInPixels) /
(maxBlendDiscSize - maxDiscSize));
}
alpha = (_faintestMag - appMag) * brightnessScale * 2.0f + brightnessBias;
if (alpha < 0.0f)
alpha = 0.0f;
float scale = static_cast<float>(screenDpi) / 96.0f;
float pointSize, alpha, glareSize, glareAlpha;
calculatePointSize(appMag, BaseStarDiscSize * scale, pointSize, alpha, glareSize, glareAlpha);
float pointSize = size;
float glareSize = 0.0f;
float glareAlpha = 0.0f;
if (useScaledDiscs)
{
if (alpha > 1.0f)
{
float discScale = min(maxSize, (float) pow(2.0f, 0.3f * (satPoint - appMag)));
pointSize *= max(1.0f, discScale);
glareAlpha = min(0.5f, discScale / 4.0f);
if (discSizeInPixels > maxSize)
glareAlpha = min(glareAlpha, (maxSize - discSizeInPixels) / maxSize + 1.0f);
glareSize = pointSize * 3.0f;
alpha = 1.0f;
}
}
else
{
if (alpha > 1.0f)
{
float discScale = min(100.0f, satPoint - appMag + 2.0f);
glareAlpha = min(GlareOpacity, (discScale - 2.0f) / 4.0f);
glareSize = pointSize * discScale * 2.0f ;
if (emissive)
glareSize = max(glareSize, pointSize * discSizeInPixels / (screenDpi / 96.0f) * 3.0f);
}
}
if (useScaledDiscs && discSizeInPixels > MaxScaledDiscStarSize)
glareAlpha = std::min(glareAlpha, (MaxScaledDiscStarSize - discSizeInPixels) / MaxScaledDiscStarSize + 1.0f);
alpha *= fade;
if (!emissive)
{
glareSize = max(glareSize, pointSize * discSizeInPixels / (screenDpi / 96.0f) * 3.0f);
glareAlpha *= fade;
}
if (glareSize != 0.0f)
glareSize = std::max(glareSize, pointSize * discSizeInPixels / scale * 3.0f);
Matrix3f m = m_cameraOrientation.conjugate().toRotationMatrix();
Vector3f center = position;
@ -1833,7 +1848,8 @@ void Renderer::renderObjectAsPoint(const Vector3f& position,
enableDepthTest();
disableDepthMask();
bool useSprites = starStyle != PointStars;
const bool useSprites = starStyle != PointStars;
if (useSprites)
gaussianDiscTex->bind();
if (pointSize > gl::maxPointSize)
@ -3317,7 +3333,6 @@ void Renderer::renderPlanet(Body& body,
renderObjectAsPoint(pos,
body.getRadius(),
appMag,
faintestMag,
discSizeInPixels,
body.getSurface().color,
false, false, m);
@ -3396,7 +3411,6 @@ void Renderer::renderStar(const Star& star,
renderObjectAsPoint(pos,
star.getRadius(),
appMag,
faintestMag,
discSizeInPixels,
color,
star.hasCorona(), true,
@ -4371,11 +4385,7 @@ void Renderer::renderPointStars(const StarDatabase& starDB,
starRenderer.cosFOV = (float) cos(degToRad(calcMaxFOV(fov, getAspectRatio())) / 2.0f);
starRenderer.pixelSize = pixelSize;
starRenderer.brightnessScale = brightnessScale * corrFac;
starRenderer.brightnessBias = brightnessBias;
starRenderer.faintestMag = faintestMag;
starRenderer.faintestMagNight = faintestMagNight;
starRenderer.saturationMag = saturationMag;
starRenderer.distanceLimit = distanceLimit;
starRenderer.labelMode = labelMode;
starRenderer.SolarSystemMaxDistance = SolarSystemMaxDistance;
@ -4384,18 +4394,6 @@ void Renderer::renderPointStars(const StarDatabase& starDB,
float effDistanceToScreen = mmToInches((float) REF_DISTANCE_TO_SCREEN) * pixelSize * getScreenDpi();
starRenderer.labelThresholdMag = 1.2f * max(1.0f, (faintestMag - 4.0f) * (1.0f - 0.5f * (float) log10(effDistanceToScreen)));
starRenderer.size = BaseStarDiscSize * screenDpi / 96.0f;
if (starStyle == ScaledDiscStars)
{
starRenderer.useScaledDiscs = true;
starRenderer.brightnessScale *= 2.0f;
starRenderer.maxDiscSize = starRenderer.size * MaxScaledDiscStarSize;
}
else if (starStyle == FuzzyPointStars)
{
starRenderer.brightnessScale *= 1.0f;
}
starRenderer.colorTemp = colorTemp;
gaussianDiscTex->bind();
@ -4455,17 +4453,11 @@ void Renderer::renderDeepSkyObjects(const Universe& universe,
dsoRenderer.orientationMatrix= observer.getOrientationf().conjugate().toRotationMatrix();
dsoRenderer.observer = &observer;
dsoRenderer.obsPos = obsPos;
dsoRenderer.viewNormal = observer.getOrientationf().conjugate() * -Vector3f::UnitZ();
dsoRenderer.fov = fov;
// size/pixelSize =0.86 at 120deg, 1.43 at 45deg and 1.6 at 0deg.
dsoRenderer.size = pixelSize * 1.6f / corrFac;
dsoRenderer.pixelSize = pixelSize;
dsoRenderer.brightnessScale = brightnessScale * corrFac;
dsoRenderer.brightnessBias = brightnessBias;
dsoRenderer.avgAbsMag = dsoDB->getAverageAbsoluteMagnitude();
dsoRenderer.faintestMag = faintestMag;
dsoRenderer.faintestMagNight = faintestMagNight;
dsoRenderer.saturationMag = saturationMag;
dsoRenderer.renderFlags = renderFlags;
dsoRenderer.labelMode = labelMode;
dsoRenderer.wWidth = windowWidth;

View File

@ -618,10 +618,16 @@ class Renderer
float discSizeInPixels,
const Matrices&);
void calculatePointSize(float appMag,
float size,
float &discSize,
float &alpha,
float &glareSize,
float &glareAlpha) const;
void renderObjectAsPoint(const Eigen::Vector3f& center,
float radius,
float appMag,
float _faintestMag,
float discSizeInPixels,
const Color& color,
bool useHalos,
@ -840,6 +846,9 @@ class Renderer
std::array<celgl::VertexObject*, static_cast<size_t>(VOType::Count)> m_VertexObjects;
// Saturation magnitude used to calculate a point star size
float satPoint;
// Location markers
public:
celestia::MarkerRepresentation mountainRep;
@ -897,6 +906,8 @@ class Renderer
static Color EclipticColor;
static Color SelectionCursorColor;
friend class PointStarRenderer;
};