Refactor render.cpp and extract some classes to own files

pull/3/head
Hleb Valoshka 2019-12-01 15:32:10 +03:00
parent 7f052a65e4
commit 8778c07ccb
12 changed files with 1116 additions and 988 deletions

View File

@ -47,6 +47,7 @@ set(CELENGINE_SOURCES
globular.h globular.h
glshader.cpp glshader.cpp
glshader.h glshader.h
#hdrfuncrender.cpp
image.cpp image.cpp
image.h image.h
lightenv.h lightenv.h
@ -66,11 +67,13 @@ set(CELENGINE_SOURCES
name.h name.h
nebula.cpp nebula.cpp
nebula.h nebula.h
objectrenderer.h
observer.cpp observer.cpp
observer.h observer.h
octree.h octree.h
opencluster.cpp opencluster.cpp
opencluster.h opencluster.h
orbitsampler.h
overlay.cpp overlay.cpp
overlay.h overlay.h
overlayimage.cpp overlayimage.cpp
@ -85,15 +88,20 @@ set(CELENGINE_SOURCES
# particlesystem.h # particlesystem.h
planetgrid.cpp planetgrid.cpp
planetgrid.h planetgrid.h
pointstarrenderer.cpp
pointstarrenderer.h
pointstarvertexbuffer.cpp
pointstarvertexbuffer.h
rectangle.h rectangle.h
referencemark.h referencemark.h
rendcontext.cpp rendcontext.cpp
rendcontext.h rendcontext.h
render.cpp render.cpp
render.h
renderglsl.cpp renderglsl.cpp
renderglsl.h renderglsl.h
render.h
renderinfo.h renderinfo.h
renderlistentry.h
rotationmanager.cpp rotationmanager.cpp
rotationmanager.h rotationmanager.h
selection.cpp selection.cpp

View File

@ -27,6 +27,8 @@
// License and a copy of the GNU General Public License along with // License and a copy of the GNU General Public License along with
// orbitpath. If not, see <http://www.gnu.org/licenses/>. // orbitpath. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <deque> #include <deque>
#include <Eigen/Geometry> #include <Eigen/Geometry>

View File

@ -0,0 +1,443 @@
// render.cpp
//
// Copyright (C) 2001-2009, the Celestia Development Team
// Original version by Chris Laurel <claurel@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifdef USE_HDR
void Renderer::genBlurTextures()
{
for (size_t i = 0; i < BLUR_PASS_COUNT; ++i)
{
if (blurTextures[i] != nullptr)
{
delete blurTextures[i];
blurTextures[i] = nullptr;
}
}
if (blurTempTexture != nullptr)
{
delete blurTempTexture;
blurTempTexture = nullptr;
}
blurBaseWidth = sceneTexWidth, blurBaseHeight = sceneTexHeight;
if (blurBaseWidth > blurBaseHeight)
{
while (blurBaseWidth > BLUR_SIZE)
{
blurBaseWidth >>= 1;
blurBaseHeight >>= 1;
}
}
else
{
while (blurBaseHeight > BLUR_SIZE)
{
blurBaseWidth >>= 1;
blurBaseHeight >>= 1;
}
}
genBlurTexture(0);
genBlurTexture(1);
Image *tempImg;
ImageTexture *tempTexture;
tempImg = new Image(GL_LUMINANCE, blurBaseWidth, blurBaseHeight);
tempTexture = new ImageTexture(*tempImg, Texture::EdgeClamp, Texture::DefaultMipMaps);
delete tempImg;
if (tempTexture && tempTexture->getName() != 0)
blurTempTexture = tempTexture;
}
void Renderer::genBlurTexture(int blurLevel)
{
Image *img;
ImageTexture *texture;
#ifdef DEBUG_HDR
HDR_LOG <<
"Window width = " << windowWidth << ", " <<
"Window height = " << windowHeight << ", " <<
"Blur tex width = " << (blurBaseWidth>>blurLevel) << ", " <<
"Blur tex height = " << (blurBaseHeight>>blurLevel) << endl;
#endif
img = new Image(blurFormat,
blurBaseWidth>>blurLevel,
blurBaseHeight>>blurLevel);
texture = new ImageTexture(*img,
Texture::EdgeClamp,
Texture::NoMipMaps);
delete img;
if (texture && texture->getName() != 0)
blurTextures[blurLevel] = texture;
}
void Renderer::genSceneTexture()
{
unsigned int *data;
if (sceneTexture != 0)
glDeleteTextures(1, &sceneTexture);
sceneTexWidth = 1;
sceneTexHeight = 1;
while (sceneTexWidth < windowWidth)
sceneTexWidth <<= 1;
while (sceneTexHeight < windowHeight)
sceneTexHeight <<= 1;
sceneTexWScale = (windowWidth > 0) ? (GLfloat)sceneTexWidth / (GLfloat)windowWidth :
1.0f;
sceneTexHScale = (windowHeight > 0) ? (GLfloat)sceneTexHeight / (GLfloat)windowHeight :
1.0f;
data = (unsigned int* )malloc(sceneTexWidth*sceneTexHeight*4*sizeof(unsigned int));
memset(data, 0, sceneTexWidth*sceneTexHeight*4*sizeof(unsigned int));
glGenTextures(1, &sceneTexture);
glBindTexture(GL_TEXTURE_2D, sceneTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, sceneTexWidth, sceneTexHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, data);
free(data);
#ifdef DEBUG_HDR
static int genSceneTexCounter = 1;
HDR_LOG <<
"[" << genSceneTexCounter++ << "] " <<
"Window width = " << windowWidth << ", " <<
"Window height = " << windowHeight << ", " <<
"Tex width = " << sceneTexWidth << ", " <<
"Tex height = " << sceneTexHeight << endl;
#endif
}
void Renderer::renderToBlurTexture(int blurLevel)
{
if (blurTextures[blurLevel] == nullptr)
return;
GLsizei blurTexWidth = blurBaseWidth>>blurLevel;
GLsizei blurTexHeight = blurBaseHeight>>blurLevel;
GLsizei blurDrawWidth = (GLfloat)windowWidth/(GLfloat)sceneTexWidth * blurTexWidth;
GLsizei blurDrawHeight = (GLfloat)windowHeight/(GLfloat)sceneTexHeight * blurTexHeight;
GLfloat blurWScale = 1.f;
GLfloat blurHScale = 1.f;
GLfloat savedWScale = 1.f;
GLfloat savedHScale = 1.f;
glPushAttrib(GL_COLOR_BUFFER_BIT | GL_VIEWPORT_BIT);
glClearColor(0, 0, 0, 1.f);
glViewport(0, 0, blurDrawWidth, blurDrawHeight);
glBindTexture(GL_TEXTURE_2D, sceneTexture);
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, 0.0f, 1.0f);
glEnd();
// Do not need to scale alpha so mask it off
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glEnable(GL_BLEND);
savedWScale = sceneTexWScale;
savedHScale = sceneTexHScale;
// Remove ldr part of image
{
const GLfloat bias = -0.5f;
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
glColor4f(-bias, -bias, -bias, 0.0f);
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glVertex2f(0.0f, 0.0f);
glVertex2f(1.f, 0.0f);
glVertex2f(1.f, 1.f);
glVertex2f(0.0f, 1.f);
glEnd();
glEnable(GL_TEXTURE_2D);
blurTextures[blurLevel]->bind();
glCopyTexImage2D(GL_TEXTURE_2D, 0, blurFormat, 0, 0,
blurTexWidth, blurTexHeight, 0);
}
// Scale back up hdr part
{
glBlendEquationEXT(GL_FUNC_ADD_EXT);
glBlendFunc(GL_DST_COLOR, GL_ONE);
glBegin(GL_QUADS);
drawBlendedVertices(0.f, 0.f, 1.f); //x2
drawBlendedVertices(0.f, 0.f, 1.f); //x2
glEnd();
}
glDisable(GL_BLEND);
if (!useLuminanceAlpha)
{
blurTempTexture->bind();
glCopyTexImage2D(GL_TEXTURE_2D, blurLevel, GL_LUMINANCE, 0, 0,
blurTexWidth, blurTexHeight, 0);
// Erase color, replace with luminance image
glBegin(GL_QUADS);
glColor4f(0.f, 0.f, 0.f, 1.f);
glVertex2f(0.0f, 0.0f);
glVertex2f(1.0f, 0.0f);
glVertex2f(1.0f, 1.0f);
glVertex2f(0.0f, 1.0f);
glEnd();
glBegin(GL_QUADS);
drawBlendedVertices(0.f, 0.f, 1.f);
glEnd();
}
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
blurTextures[blurLevel]->bind();
glCopyTexImage2D(GL_TEXTURE_2D, 0, blurFormat, 0, 0,
blurTexWidth, blurTexHeight, 0);
// blending end
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLfloat xdelta = 1.0f / (GLfloat)blurTexWidth;
GLfloat ydelta = 1.0f / (GLfloat)blurTexHeight;
blurWScale = ((GLfloat)blurTexWidth / (GLfloat)blurDrawWidth);
blurHScale = ((GLfloat)blurTexHeight / (GLfloat)blurDrawHeight);
sceneTexWScale = blurWScale;
sceneTexHScale = blurHScale;
// Butterworth low pass filter to reduce flickering dots
{
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, 0.0f, .5f*1.f);
drawBlendedVertices(-xdelta, 0.0f, .5f*0.333f);
drawBlendedVertices( xdelta, 0.0f, .5f*0.25f);
glEnd();
glCopyTexImage2D(GL_TEXTURE_2D, 0, blurFormat, 0, 0,
blurTexWidth, blurTexHeight, 0);
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, -ydelta, .5f*0.667f);
drawBlendedVertices(0.0f, ydelta, .5f*0.333f);
glEnd();
glCopyTexImage2D(GL_TEXTURE_2D, 0, blurFormat, 0, 0,
blurTexWidth, blurTexHeight, 0);
glClear(GL_COLOR_BUFFER_BIT);
}
// Gaussian blur
switch (blurLevel)
{
/*
case 0:
drawGaussian3x3(xdelta, ydelta, blurTexWidth, blurTexHeight, 1.f);
break;
*/
#ifdef __APPLE__
case 0:
drawGaussian5x5(xdelta, ydelta, blurTexWidth, blurTexHeight, 1.f);
break;
case 1:
drawGaussian9x9(xdelta, ydelta, blurTexWidth, blurTexHeight, .3f);
break;
#else
// Gamma correct: windows=(mac^1.8)^(1/2.2)
case 0:
drawGaussian5x5(xdelta, ydelta, blurTexWidth, blurTexHeight, 1.f);
break;
case 1:
drawGaussian9x9(xdelta, ydelta, blurTexWidth, blurTexHeight, .373f);
break;
#endif
default:
break;
}
blurTextures[blurLevel]->bind();
glCopyTexImage2D(GL_TEXTURE_2D, 0, blurFormat, 0, 0,
blurTexWidth, blurTexHeight, 0);
glDisable(GL_BLEND);
glClear(GL_COLOR_BUFFER_BIT);
glPopAttrib();
sceneTexWScale = savedWScale;
sceneTexHScale = savedHScale;
}
void Renderer::renderToTexture(const Observer& observer,
const Universe& universe,
float faintestMagNight,
const Selection& sel)
{
if (sceneTexture == 0)
return;
glPushAttrib(GL_COLOR_BUFFER_BIT);
draw(observer, universe, faintestMagNight, sel);
glBindTexture(GL_TEXTURE_2D, sceneTexture);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0,
sceneTexWidth, sceneTexHeight, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPopAttrib();
}
void Renderer::drawSceneTexture()
{
if (sceneTexture == 0)
return;
glBindTexture(GL_TEXTURE_2D, sceneTexture);
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, 0.0f, 1.0f);
glEnd();
}
void Renderer::drawBlendedVertices(float xdelta, float ydelta, float blend)
{
glColor4f(1.0f, 1.0f, 1.0f, blend);
glTexCoord2i(0, 0); glVertex2f(xdelta, ydelta);
glTexCoord2i(1, 0); glVertex2f(sceneTexWScale+xdelta, ydelta);
glTexCoord2i(1, 1); glVertex2f(sceneTexWScale+xdelta, sceneTexHScale+ydelta);
glTexCoord2i(0, 1); glVertex2f(xdelta, sceneTexHScale+ydelta);
}
void Renderer::drawGaussian3x3(float xdelta, float ydelta, GLsizei width, GLsizei height, float blend)
{
#ifdef USE_BLOOM_LISTS
if (gaussianLists[0] == 0)
{
gaussianLists[0] = glGenLists(1);
glNewList(gaussianLists[0], GL_COMPILE);
#endif
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, 0.0f, blend);
drawBlendedVertices(-xdelta, 0.0f, 0.25f*blend);
drawBlendedVertices( xdelta, 0.0f, 0.20f*blend);
glEnd();
// Take result of horiz pass and apply vertical pass
glCopyTexImage2D(GL_TEXTURE_2D, 0, blurFormat, 0, 0,
width, height, 0);
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, -ydelta, 0.429f);
drawBlendedVertices(0.0f, ydelta, 0.300f);
glEnd();
#ifdef USE_BLOOM_LISTS
glEndList();
}
glCallList(gaussianLists[0]);
#endif
}
void Renderer::drawGaussian5x5(float xdelta, float ydelta, GLsizei width, GLsizei height, float blend)
{
#ifdef USE_BLOOM_LISTS
if (gaussianLists[1] == 0)
{
gaussianLists[1] = glGenLists(1);
glNewList(gaussianLists[1], GL_COMPILE);
#endif
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, 0.0f, blend);
drawBlendedVertices(-xdelta, 0.0f, 0.475f*blend);
drawBlendedVertices( xdelta, 0.0f, 0.475f*blend);
drawBlendedVertices(-2.0f*xdelta, 0.0f, 0.075f*blend);
drawBlendedVertices( 2.0f*xdelta, 0.0f, 0.075f*blend);
glEnd();
glCopyTexImage2D(GL_TEXTURE_2D, 0, blurFormat, 0, 0,
width, height, 0);
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, -ydelta, 0.475f);
drawBlendedVertices(0.0f, ydelta, 0.475f);
drawBlendedVertices(0.0f, -2.0f*ydelta, 0.075f);
drawBlendedVertices(0.0f, 2.0f*ydelta, 0.075f);
glEnd();
#ifdef USE_BLOOM_LISTS
glEndList();
}
glCallList(gaussianLists[1]);
#endif
}
void Renderer::drawGaussian9x9(float xdelta, float ydelta, GLsizei width, GLsizei height, float blend)
{
#ifdef USE_BLOOM_LISTS
if (gaussianLists[2] == 0)
{
gaussianLists[2] = glGenLists(1);
glNewList(gaussianLists[2], GL_COMPILE);
#endif
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, 0.0f, blend);
drawBlendedVertices(-xdelta, 0.0f, 0.632f*blend);
drawBlendedVertices( xdelta, 0.0f, 0.632f*blend);
drawBlendedVertices(-2.0f*xdelta, 0.0f, 0.159f*blend);
drawBlendedVertices( 2.0f*xdelta, 0.0f, 0.159f*blend);
drawBlendedVertices(-3.0f*xdelta, 0.0f, 0.016f*blend);
drawBlendedVertices( 3.0f*xdelta, 0.0f, 0.016f*blend);
glEnd();
glCopyTexImage2D(GL_TEXTURE_2D, 0, blurFormat, 0, 0,
width, height, 0);
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, -ydelta, 0.632f);
drawBlendedVertices(0.0f, ydelta, 0.632f);
drawBlendedVertices(0.0f, -2.0f*ydelta, 0.159f);
drawBlendedVertices(0.0f, 2.0f*ydelta, 0.159f);
drawBlendedVertices(0.0f, -3.0f*ydelta, 0.016f);
drawBlendedVertices(0.0f, 3.0f*ydelta, 0.016f);
glEnd();
#ifdef USE_BLOOM_LISTS
glEndList();
}
glCallList(gaussianLists[2]);
#endif
}
void Renderer::drawBlur()
{
blurTextures[0]->bind();
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, 0.0f, 1.0f);
glEnd();
blurTextures[1]->bind();
glBegin(GL_QUADS);
drawBlendedVertices(0.0f, 0.0f, 1.0f);
glEnd();
}
bool Renderer::getBloomEnabled()
{
return bloomEnabled;
}
void Renderer::setBloomEnabled(bool aBloomEnabled)
{
bloomEnabled = aBloomEnabled;
}
void Renderer::increaseBrightness()
{
brightPlus += 1.0f;
}
void Renderer::decreaseBrightness()
{
brightPlus -= 1.0f;
}
float Renderer::getBrightness()
{
return brightPlus;
}
#endif // USE_HDR

View File

@ -0,0 +1,63 @@
// objectrenderer.h
//
// Copyright (C) 2001-2019, the Celestia Development Team
// Original version by Chris Laurel <claurel@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#pragma once
#include <Eigen/Core>
#include "octree.h"
#ifdef USE_GLCONTEXT
class GLContext;
#endif
class Observer;
class Renderer;
template <class OBJ, class PREC> class ObjectRenderer : public OctreeProcessor<OBJ, PREC>
{
public:
ObjectRenderer(PREC _distanceLimit) : distanceLimit((float) _distanceLimit) {};
void process(const OBJ& /*unused*/, PREC /*unused*/, float /*unused*/) {};
const Observer* observer { nullptr };
#ifdef USE_GLCONTEXT
GLContext* context { nullptr };
#endif
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 };
#ifdef USE_HDR
float exposure { 0.0f };
#endif
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

@ -0,0 +1,48 @@
// orbitsampler.h
//
// Copyright (C) 2001-2019, the Celestia Development Team
// Original version by Chris Laurel <claurel@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#pragma once
#include <Eigen/Core>
#include <celephem/orbit.h>
#include "curveplot.h"
class OrbitSampler : public OrbitSampleProc
{
public:
std::vector<CurvePlotSample> samples;
OrbitSampler() = default;
void sample(double t, const Eigen::Vector3d& position, const Eigen::Vector3d& velocity)
{
CurvePlotSample samp;
samp.t = t;
samp.position = position;
samp.velocity = velocity;
samples.push_back(samp);
}
void insertForward(CurvePlot* plot)
{
for (const auto& sample : samples)
{
plot->addSample(sample);
}
}
void insertBackward(CurvePlot* plot)
{
for (auto iter = samples.rbegin(); iter != samples.rend(); ++iter)
{
plot->addSample(*iter);
}
}
};

View File

@ -0,0 +1,203 @@
// pointstarrenderer.cpp
//
// Copyright (C) 2001-2019, the Celestia Development Team
// Original version by Chris Laurel <claurel@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <celengine/starcolors.h>
#include <celengine/star.h>
#include <celengine/univcoord.h>
#include "pointstarvertexbuffer.h"
#include "render.h"
#include "pointstarrenderer.h"
using namespace std;
using namespace Eigen;
// Convert a position in the universal coordinate system to astrocentric
// coordinates, taking into account possible orbital motion of the star.
static Vector3d astrocentricPosition(const UniversalCoord& pos,
const Star& star,
double t)
{
return pos.offsetFromKm(star.getPosition(t));
}
PointStarRenderer::PointStarRenderer() :
ObjectRenderer<Star, float>(StarDistanceLimit)
{
}
void PointStarRenderer::process(const Star& star, float distance, float appMag)
{
nProcessed++;
Vector3f starPos = star.getPosition();
// Calculate the difference at double precision *before* converting to float.
// This is very important for stars that are far from the origin.
Vector3f relPos = (starPos.cast<double>() - obsPos).cast<float>();
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.
// TODO: consider normalizing relPos and comparing relPos*viewNormal against
// cosFOV--this will cull many more stars than relPos*viewNormal, at the
// cost of a normalize per star.
if (relPos.dot(viewNormal) > 0.0f || relPos.x() * relPos.x() < 0.1f || hasOrbit)
{
#ifdef HDR_COMPRESS
Color starColorFull = colorTemp->lookupColor(star.getTemperature());
Color starColor(starColorFull.red() * 0.5f,
starColorFull.green() * 0.5f,
starColorFull.blue() * 0.5f);
#else
Color starColor = colorTemp->lookupColor(star.getTemperature());
#endif
float discSizeInPixels = 0.0f;
float orbitSizeInPixels = 0.0f;
if (hasOrbit)
orbitSizeInPixels = orbitalRadius / (distance * pixelSize);
// Special handling for stars less than one light year away . . .
// We can't just go ahead and render a nearby star in the usual way
// for two reasons:
// * It may be clipped by the near plane
// * 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
// 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)
{
// Compute the position of the observer relative to the star.
// This is a much more accurate (and expensive) distance
// calculation than the previous one which used the observer's
// position rounded off to floats.
Vector3d hPos = astrocentricPosition(observer->getPosition(),
star,
observer->getTime());
relPos = hPos.cast<float>() * -astro::kilometersToLightYears(1.0f);
distance = relPos.norm();
// Recompute apparent magnitude using new distance computation
appMag = astro::absToAppMag(star.getAbsoluteMagnitude(), distance);
discSizeInPixels = star.getRadius() / astro::lightYearsToKilometers(distance) / pixelSize;
++nClose;
}
// Place labels for stars brighter than the specified label threshold brightness
if (((labelMode & Renderer::StarLabels) != 0) && appMag < labelThresholdMag)
{
Vector3f starDir = relPos;
starDir.normalize();
if (starDir.dot(viewNormal) > cosFOV)
{
float distr = 3.5f * (labelThresholdMag - appMag)/labelThresholdMag;
if (distr > 1.0f)
distr = 1.0f;
renderer->addBackgroundAnnotation(nullptr, starDB->getStarName(star, true),
Color(Renderer::StarLabelColor, distr * Renderer::StarLabelColor.alpha()),
relPos);
nLabelled++;
}
}
// Stars closer than the maximum solar system size are actually
// added to the render list and depth sorted, since they may occlude
// planets.
if (distance > SolarSystemMaxDistance)
{
#ifdef USE_HDR
float satPoint = saturationMag;
float alpha = exposure*(faintestMag - appMag)/(faintestMag - saturationMag + 0.001f);
#else
float satPoint = faintestMag - (1.0f - brightnessBias) / brightnessScale; // TODO: precompute this value
float alpha = (faintestMag - appMag) * brightnessScale + brightnessBias;
#endif
#ifdef DEBUG_HDR_ADAPT
minMag = max(minMag, appMag);
maxMag = min(maxMag, appMag);
minAlpha = min(minAlpha, alpha);
maxAlpha = max(maxAlpha, alpha);
++total;
if (alpha > above)
{
++countAboveN;
}
#endif
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);
#ifdef DEBUG_HDR_ADAPT
maxSize = max(maxSize, 2.0f * discScale * size);
#endif
}
starVertexBuffer->addStar(relPos, Color(starColor, alpha), size);
}
++nRendered;
}
else
{
Matrix3f viewMat = observer->getOrientationf().toRotationMatrix();
Vector3f viewMatZ = viewMat.row(2);
RenderListEntry rle;
rle.renderableType = RenderListEntry::RenderableStar;
rle.star = &star;
// Objects in the render list are always rendered relative to
// a viewer at the origin--this is different than for distant
// stars.
float scale = astro::lightYearsToKilometers(1.0f);
rle.position = relPos * scale;
rle.centerZ = rle.position.dot(viewMatZ);
rle.distance = rle.position.norm();
rle.radius = star.getRadius();
rle.discSizeInPixels = discSizeInPixels;
rle.appMag = appMag;
rle.isOpaque = true;
renderList->push_back(rle);
}
}
}

View File

@ -0,0 +1,65 @@
// pointstarrenderer.h
//
// Copyright (C) 2001-2019, the Celestia Development Team
// Original version by Chris Laurel <claurel@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#pragma once
#include <Eigen/Core>
#include <vector>
#include "objectrenderer.h"
#include "renderlistentry.h"
class ColorTemperatureTable;
class PointStarVertexBuffer;
class Star;
class StarDatabase;
// TODO: move these variables to PointStarRenderer class
// without adding a variable. Requires C++17
constexpr const float StarDistanceLimit = 1.0e6f;
// Star disc size in pixels
constexpr const float BaseStarDiscSize = 5.0f;
constexpr const float MaxScaledDiscStarSize = 8.0f;
constexpr const float GlareOpacity = 0.65f;
class PointStarRenderer : public ObjectRenderer<Star, float>
{
public:
#if 0
static constexpr const float StarDistanceLimit = 1.0e6f;
// Star disc size in pixels
static constexpr const float BaseStarDiscSize = 5.0f;
static constexpr const float MaxScaledDiscStarSize = 8.0f;
static constexpr const float GlareOpacity = 0.65f;
#endif
PointStarRenderer();
void process(const Star &star, float distance, float appMag);
Eigen::Vector3d obsPos;
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 };
#ifdef DEBUG_HDR_ADAPT
float minMag { 0.0f };
float maxMag { 0.0f };
float minAlpha { 0.0f };
float maxAlpha { 0.0f };
float maxSize { 0.0f };
float above { 0.0f };
unsigned long countAboveN { 0 };
unsigned long total { 0 };
#endif
bool useScaledDiscs { false };
};

View File

@ -0,0 +1,133 @@
// starfield.cpp
//
// Copyright (C) 2001-2019, the Celestia Development Team
// Original version by Chris Laurel <claurel@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <GL/glew.h>
#include <celutil/color.h>
#include "objectrenderer.h"
#include "shadermanager.h"
#include "render.h"
#include "texture.h"
#include "pointstarvertexbuffer.h"
PointStarVertexBuffer::PointStarVertexBuffer(const Renderer& _renderer,
unsigned int _capacity) :
renderer(_renderer),
capacity(_capacity)
{
vertices = new StarVertex[capacity];
}
PointStarVertexBuffer::~PointStarVertexBuffer()
{
delete[] vertices;
}
void PointStarVertexBuffer::startSprites()
{
auto *prog = renderer.getShaderManager().getShader("star");
if (prog == nullptr)
return;
prog->use();
prog->samplerParam("starTex") = 0;
unsigned int stride = sizeof(StarVertex);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, stride, &vertices[0].position);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, stride, &vertices[0].color);
glEnableVertexAttribArray(CelestiaGLProgram::PointSizeAttributeIndex);
glVertexAttribPointer(CelestiaGLProgram::PointSizeAttributeIndex,
1, GL_FLOAT, GL_FALSE,
stride, &vertices[0].size);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glEnable(GL_POINT_SPRITE);
useSprites = true;
}
void PointStarVertexBuffer::startPoints()
{
auto *prog = renderer.getShaderManager().getShader(ShaderProperties::PerVertexColor);
if (prog == nullptr)
return;
prog->use();
unsigned int stride = sizeof(StarVertex);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, stride, &vertices[0].position);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, stride, &vertices[0].color);
// An option to control the size of the stars would be helpful.
// Which size looks best depends a lot on the resolution and the
// type of display device.
// glPointSize(2.0f);
// glEnable(GL_POINT_SMOOTH);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
useSprites = false;
}
void PointStarVertexBuffer::render()
{
if (nStars != 0)
{
unsigned int stride = sizeof(StarVertex);
if (useSprites)
{
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
}
else
{
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
glPointSize(1.0f);
}
glVertexPointer(3, GL_FLOAT, stride, &vertices[0].position);
glColorPointer(4, GL_UNSIGNED_BYTE, stride, &vertices[0].color);
if (useSprites)
{
glVertexAttribPointer(CelestiaGLProgram::PointSizeAttributeIndex,
1, GL_FLOAT, GL_FALSE,
stride, &vertices[0].size);
}
if (texture != nullptr)
texture->bind();
glDrawArrays(GL_POINTS, 0, nStars);
nStars = 0;
}
}
void PointStarVertexBuffer::finish()
{
render();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (useSprites)
{
glDisableVertexAttribArray(CelestiaGLProgram::PointSizeAttributeIndex);
glDisable(GL_POINT_SPRITE);
}
glUseProgram(0);
}
void PointStarVertexBuffer::setTexture(Texture* _texture)
{
texture = _texture;
}

View File

@ -0,0 +1,75 @@
// pointstarvertexbuffer.h
//
// Copyright (C) 2001-2019, the Celestia Development Team
// Original version by Chris Laurel <claurel@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#pragma once
#include <Eigen/Core>
class Color;
class Renderer;
class Texture;
// PointStarVertexBuffer is used when hardware supports point sprites.
class PointStarVertexBuffer
{
public:
using capacity_t = unsigned int;
PointStarVertexBuffer(const Renderer& _renderer, unsigned int _capacity);
~PointStarVertexBuffer();
PointStarVertexBuffer() = delete;
PointStarVertexBuffer(const PointStarVertexBuffer&) = delete;
PointStarVertexBuffer(PointStarVertexBuffer&&) = delete;
PointStarVertexBuffer& operator=(const PointStarVertexBuffer&) = delete;
PointStarVertexBuffer& operator=(PointStarVertexBuffer&&) = delete;
void startPoints();
void startSprites();
void render();
void finish();
inline void addStar(const Eigen::Vector3f& pos, const Color&, float);
void setTexture(Texture* /*_texture*/);
private:
struct StarVertex
{
Eigen::Vector3f position;
float size;
unsigned char color[4];
float pad;
};
const Renderer& renderer;
capacity_t capacity;
capacity_t nStars { 0 };
StarVertex* vertices { nullptr };
Texture* texture { nullptr };
bool useSprites { false };
};
inline void PointStarVertexBuffer::addStar(const Eigen::Vector3f& pos,
const Color& color,
float size)
{
if (nStars < capacity)
{
vertices[nStars].position = pos;
vertices[nStars].size = size;
color.get(vertices[nStars].color);
nStars++;
}
if (nStars == capacity)
{
render();
nStars = 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,9 @@
#ifndef _CELENGINE_RENDER_H_ #ifndef _CELENGINE_RENDER_H_
#define _CELENGINE_RENDER_H_ #define _CELENGINE_RENDER_H_
#include <vector>
#include <list>
#include <string>
#include <Eigen/Core> #include <Eigen/Core>
#include <celmath/frustum.h> #include <celmath/frustum.h>
#include <celengine/universe.h> #include <celengine/universe.h>
@ -21,15 +24,13 @@
#endif #endif
#include <celengine/starcolors.h> #include <celengine/starcolors.h>
#include <celengine/rendcontext.h> #include <celengine/rendcontext.h>
#include "celengine/vertexobject.h" #include <celengine/renderlistentry.h>
#include <celengine/vertexobject.h>
#if NO_TTF #if NO_TTF
#include <celtxf/texturefont.h> #include <celtxf/texturefont.h>
#else #else
#include <celttf/truetypefont.h> #include <celttf/truetypefont.h>
#endif #endif
#include <vector>
#include <list>
#include <string>
class RendererWatcher; class RendererWatcher;
@ -38,6 +39,7 @@ class ReferenceMark;
class CurvePlot; class CurvePlot;
class AsterismList; class AsterismList;
class Rect; class Rect;
class PointStarVertexBuffer;
struct LightSource struct LightSource
{ {
@ -48,39 +50,6 @@ struct LightSource
}; };
struct RenderListEntry
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
enum RenderableType
{
RenderableStar,
RenderableBody,
RenderableCometTail,
RenderableReferenceMark,
};
union
{
const Star* star;
Body* body;
const ReferenceMark* refMark;
};
Eigen::Vector3f position;
Eigen::Vector3f sun;
float distance;
float radius;
float centerZ;
float nearZ;
float farZ;
float discSizeInPixels;
float appMag;
RenderableType renderableType;
bool isOpaque;
};
struct SecondaryIlluminator struct SecondaryIlluminator
{ {
const Body* body; const Body* body;
@ -90,8 +59,6 @@ struct SecondaryIlluminator
}; };
class PointStarVertexBuffer;
class Renderer class Renderer
{ {
public: public:

View File

@ -0,0 +1,49 @@
// renderlistentry.h
//
// Copyright (C) 2001-2019, Celestia Development Team
// Contact: Chris Laurel <claurel@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#pragma once
#include <Eigen/Core>
class Star;
class Body;
class ReferenceMark;
struct RenderListEntry
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
enum RenderableType
{
RenderableStar,
RenderableBody,
RenderableCometTail,
RenderableReferenceMark,
};
union
{
const Star* star;
Body* body;
const ReferenceMark* refMark;
};
Eigen::Vector3f position;
Eigen::Vector3f sun;
float distance;
float radius;
float centerZ;
float nearZ;
float farZ;
float discSizeInPixels;
float appMag;
RenderableType renderableType;
bool isOpaque;
};