- Made orbit path rendering work for multistar systems
- Added foundations of multiple light source renderingver1_5_1
parent
4e69c6998b
commit
0cae2cc3e2
|
@ -68,5 +68,24 @@ class GLContext
|
|||
std::vector<std::string> extensions;
|
||||
};
|
||||
|
||||
|
||||
static const unsigned int MaxLights = 8;
|
||||
|
||||
struct DirectionalLight
|
||||
{
|
||||
Color color;
|
||||
float intensity;
|
||||
Vec3f direction;
|
||||
};
|
||||
|
||||
|
||||
struct LightingState
|
||||
{
|
||||
LightingState() : nLights(0) {};
|
||||
unsigned int nLights;
|
||||
DirectionalLight lights[MaxLights];
|
||||
};
|
||||
|
||||
|
||||
#endif // _CELENGINE_GLCONTEXT_H_
|
||||
|
||||
|
|
|
@ -1108,6 +1108,35 @@ void Renderer::autoMag(float& faintestMag)
|
|||
}
|
||||
|
||||
|
||||
// Set up the light sources for rendering a solar system. The positions of
|
||||
// all nearby stars are converted from universal to solar system coordinates.
|
||||
static void
|
||||
setupLightSources(const vector<const Star*>& nearStars,
|
||||
const Star& sun,
|
||||
double t,
|
||||
vector<Renderer::LightSource>& lightSources)
|
||||
{
|
||||
UniversalCoord center = sun.getPosition(t);
|
||||
|
||||
lightSources.clear();
|
||||
|
||||
for (vector<const Star*>::const_iterator iter = nearStars.begin();
|
||||
iter != nearStars.end(); iter++)
|
||||
{
|
||||
if ((*iter)->getVisibility())
|
||||
{
|
||||
Vec3d v = ((*iter)->getPosition(t) - center) *
|
||||
astro::microLightYearsToKilometers(1.0);
|
||||
Renderer::LightSource ls;
|
||||
ls.position = Point3d(v.x, v.y, v.z);
|
||||
ls.luminosity = (*iter)->getLuminosity();
|
||||
ls.color = Color::White;
|
||||
lightSources.push_back(ls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::render(const Observer& observer,
|
||||
const Universe& universe,
|
||||
float faintestMagNight,
|
||||
|
@ -1172,24 +1201,6 @@ void Renderer::render(const Observer& observer,
|
|||
// faintestPlanetMag = faintestMag + (2.5f * (float) log10((double) square(45.0f / fov)));
|
||||
faintestPlanetMag = faintestMag;
|
||||
|
||||
|
||||
#if 0
|
||||
// See if there's a solar system nearby that we need to render.
|
||||
SolarSystem* solarSystem = universe.getNearestSolarSystem(observer.getPosition());
|
||||
const Star* sun = NULL;
|
||||
if (solarSystem != NULL)
|
||||
sun = solarSystem->getStar();
|
||||
|
||||
if ((sun != NULL) && ((renderFlags & ShowPlanets) != 0))
|
||||
{
|
||||
renderPlanetarySystem(*sun,
|
||||
*solarSystem->getPlanets(),
|
||||
observer,
|
||||
now,
|
||||
(labelMode & (BodyLabelMask)) != 0);
|
||||
starTex->bind();
|
||||
}
|
||||
#else
|
||||
if (renderFlags & ShowPlanets)
|
||||
{
|
||||
nearStars.clear();
|
||||
|
@ -1201,6 +1212,7 @@ void Renderer::render(const Observer& observer,
|
|||
SolarSystem* solarSystem = universe.getSolarSystem(sun);
|
||||
if (solarSystem != NULL)
|
||||
{
|
||||
setupLightSources(nearStars, *sun, now, lightSources);
|
||||
renderPlanetarySystem(*sun,
|
||||
*solarSystem->getPlanets(),
|
||||
observer,
|
||||
|
@ -1208,9 +1220,8 @@ void Renderer::render(const Observer& observer,
|
|||
(labelMode & (BodyLabelMask)) != 0);
|
||||
}
|
||||
}
|
||||
starTex->bind();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Color skyColor(0.0f, 0.0f, 0.0f);
|
||||
|
||||
|
@ -1373,13 +1384,13 @@ void Renderer::render(const Observer& observer,
|
|||
|
||||
glPopMatrix();
|
||||
|
||||
#if 0
|
||||
if ((renderFlags & ShowOrbits) != 0 && orbitMask != 0 && solarSystem != NULL)
|
||||
// Render orbit paths
|
||||
if ((renderFlags & ShowOrbits) != 0 && orbitMask != 0)
|
||||
{
|
||||
vector<CachedOrbit*>::const_iterator iter;
|
||||
|
||||
// Clear the keep flag for all orbits in the cache; if they're not
|
||||
// used when rendering this frame, they'll get marked for recycling.
|
||||
// used when rendering this frame, they'll get marked for
|
||||
// recycling.
|
||||
vector<CachedOrbit*>::const_iterator iter;
|
||||
for (iter = orbitCache.begin(); iter != orbitCache.end(); iter++)
|
||||
(*iter)->keep = false;
|
||||
|
||||
|
@ -1388,16 +1399,25 @@ void Renderer::render(const Observer& observer,
|
|||
if ((renderFlags & ShowSmoothLines) != 0)
|
||||
enableSmoothLines();
|
||||
|
||||
const Star* sun = solarSystem->getStar();
|
||||
Point3d obsPos = astrocentricPosition(observer.getPosition(),
|
||||
*sun, observer.getTime());
|
||||
glPushMatrix();
|
||||
glTranslatef((float) astro::kilometersToAU(-obsPos.x),
|
||||
(float) astro::kilometersToAU(-obsPos.y),
|
||||
(float) astro::kilometersToAU(-obsPos.z));
|
||||
renderOrbits(solarSystem->getPlanets(), sel, now,
|
||||
obsPos, Point3d(0.0, 0.0, 0.0));
|
||||
glPopMatrix();
|
||||
for (vector<const Star*>::const_iterator starIter = nearStars.begin();
|
||||
starIter != nearStars.end(); starIter++)
|
||||
{
|
||||
const Star* sun = *starIter;
|
||||
SolarSystem* solarSystem = universe.getSolarSystem(sun);
|
||||
|
||||
if (solarSystem != NULL)
|
||||
{
|
||||
Point3d obsPos = astrocentricPosition(observer.getPosition(),
|
||||
*sun, observer.getTime());
|
||||
glPushMatrix();
|
||||
glTranslatef((float) astro::kilometersToAU(-obsPos.x),
|
||||
(float) astro::kilometersToAU(-obsPos.y),
|
||||
(float) astro::kilometersToAU(-obsPos.z));
|
||||
renderOrbits(solarSystem->getPlanets(), sel, now,
|
||||
obsPos, Point3d(0.0, 0.0, 0.0));
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
if ((renderFlags & ShowSmoothLines) != 0)
|
||||
disableSmoothLines();
|
||||
|
@ -1408,9 +1428,7 @@ void Renderer::render(const Observer& observer,
|
|||
if (!(*iter)->keep)
|
||||
(*iter)->body = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
renderLabels();
|
||||
|
||||
|
@ -2112,6 +2130,21 @@ struct RenderInfo
|
|||
};
|
||||
|
||||
|
||||
// Used to sort light sources in order of decreasing intensity
|
||||
struct LightIntensityPredicate
|
||||
{
|
||||
int unused;
|
||||
|
||||
LightIntensityPredicate() {};
|
||||
|
||||
bool operator()(const DirectionalLight& l0,
|
||||
const DirectionalLight& l1) const
|
||||
{
|
||||
return (l0.intensity > l1.intensity);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void renderAtmosphere(const Atmosphere& atmosphere,
|
||||
Point3f center,
|
||||
float radius,
|
||||
|
@ -4280,15 +4313,69 @@ void Renderer::renderLocations(const vector<Location*>& locations,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
setupObjectLighting(const vector<Renderer::LightSource>& suns,
|
||||
const Point3d& objPosition,
|
||||
LightingState& ls)
|
||||
{
|
||||
unsigned int nLights = min(MaxLights, suns.size());
|
||||
if (nLights == 0)
|
||||
return;
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < nLights; i++)
|
||||
{
|
||||
Vec3d dir = suns[i].position - objPosition;
|
||||
ls.lights[i].direction =
|
||||
Vec3f((float) dir.x, (float) dir.y, (float) dir.z);
|
||||
float distance = astro::kilometersToAU(ls.lights[i].direction.length());
|
||||
ls.lights[i].intensity = suns[i].luminosity / (distance * distance);
|
||||
ls.lights[i].color = suns[i].color;
|
||||
}
|
||||
|
||||
// Sort light sources by brightness. Light zero should always be the
|
||||
// brightest. Optimize common cases of one and two lights.
|
||||
if (nLights == 2)
|
||||
{
|
||||
if (ls.lights[0].intensity < ls.lights[1].intensity)
|
||||
swap(ls.lights[0], ls.lights[1]);
|
||||
}
|
||||
else if (nLights > 2)
|
||||
{
|
||||
sort(ls.lights, ls.lights + nLights, LightIntensityPredicate());
|
||||
}
|
||||
|
||||
// After sorting, the first light is always the brightest
|
||||
float maxIntensity = ls.lights[0].intensity;
|
||||
|
||||
// Normalize the brightnesses of the light sources.
|
||||
// TODO: Skip this step when high dynamic range rendering to floating point
|
||||
// buffers is enabled.
|
||||
// TODO: Investigate logarithmic functions for scaling light brightness, to
|
||||
// better simulate what the human eye would see.
|
||||
ls.nLights = 0;
|
||||
for (i = 0; i < nLights; i++)
|
||||
{
|
||||
ls.lights[i].intensity /= maxIntensity;
|
||||
|
||||
// Cull light sources that don't contribute significantly (less than
|
||||
// the resolution of an 8-bit color channel.)
|
||||
if (ls.lights[i].intensity < 1.0f / 255.0f)
|
||||
break;
|
||||
|
||||
ls.nLights++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::renderObject(Point3f pos,
|
||||
float distance,
|
||||
double now,
|
||||
Quatf cameraOrientation,
|
||||
float nearPlaneDistance,
|
||||
float farPlaneDistance,
|
||||
Vec3f sunDirection,
|
||||
Color sunColor,
|
||||
RenderProperties& obj)
|
||||
RenderProperties& obj,
|
||||
const LightingState& ls)
|
||||
{
|
||||
RenderInfo ri;
|
||||
|
||||
|
@ -4296,6 +4383,15 @@ void Renderer::renderObject(Point3f pos,
|
|||
float discSizeInPixels = obj.radius /
|
||||
(max(nearPlaneDistance, altitude) * pixelSize);
|
||||
|
||||
// HACK
|
||||
Vec3f sunDirection(0.0f, 1.0f, 0.0f);
|
||||
Color sunColor(0.0f, 0.0f, 0.0f);
|
||||
if (ls.nLights > 0)
|
||||
{
|
||||
sunDirection = ls.lights[0].direction;
|
||||
sunColor = ls.lights[0].color;// * ls.lights[0].intensity;
|
||||
}
|
||||
|
||||
// Enable depth buffering
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
@ -4327,7 +4423,7 @@ void Renderer::renderObject(Point3f pos,
|
|||
// small, the potentially nonuniform scale factor shouldn't mess up
|
||||
// the lighting calculations enough to be noticeable.
|
||||
// TODO: Figure out a better way to render ellipsoids than applying
|
||||
// a nonunifom scale factor to a sphere . . . it makes me nervous.
|
||||
// a nonunifom scale factor to a sphere.
|
||||
float radius = obj.radius;
|
||||
Vec3f semiMajorAxes(radius, radius * (1.0f - obj.oblateness), radius);
|
||||
glScale(semiMajorAxes);
|
||||
|
@ -4934,9 +5030,13 @@ void Renderer::renderPlanet(Body& body,
|
|||
}
|
||||
}
|
||||
|
||||
LightingState lights;
|
||||
setupObjectLighting(lightSources,
|
||||
body.getHeliocentricPosition(now),
|
||||
lights);
|
||||
renderObject(pos, distance, now,
|
||||
orientation, nearPlaneDistance, farPlaneDistance,
|
||||
sunDirection, sunColor, rp);
|
||||
rp, lights);
|
||||
|
||||
// Render the horizon compass for spherical and ellipsoidal bodies
|
||||
if ((renderFlags & ShowCelestialSphere) != 0 &&
|
||||
|
@ -5080,7 +5180,7 @@ void Renderer::renderStar(const Star& star,
|
|||
|
||||
renderObject(pos, distance, now,
|
||||
orientation, nearPlaneDistance, farPlaneDistance,
|
||||
Vec3f(1.0f, 0.0f, 0.0f), Color(1.0f, 1.0f, 1.0f), rp);
|
||||
rp, LightingState());
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
|
|
@ -228,6 +228,13 @@ class Renderer
|
|||
bool usePoints;
|
||||
};
|
||||
|
||||
struct LightSource
|
||||
{
|
||||
Point3d position;
|
||||
Color color;
|
||||
float luminosity;
|
||||
};
|
||||
|
||||
private:
|
||||
struct SkyVertex
|
||||
{
|
||||
|
@ -281,9 +288,8 @@ class Renderer
|
|||
Quatf cameraOrientation,
|
||||
float nearPlaneDistance,
|
||||
float farPlaneDistance,
|
||||
Vec3f sunDirection,
|
||||
Color sunColor,
|
||||
RenderProperties& obj);
|
||||
RenderProperties& obj,
|
||||
const LightingState&);
|
||||
|
||||
void renderPlanet(Body& body,
|
||||
Point3f pos,
|
||||
|
@ -397,6 +403,8 @@ class Renderer
|
|||
std::vector<EclipseShadow> eclipseShadows;
|
||||
std::vector<const Star*> nearStars;
|
||||
|
||||
std::vector<LightSource> lightSources;
|
||||
|
||||
std::vector<StarLabel> labelledStars;
|
||||
|
||||
double modelMatrix[16];
|
||||
|
|
Loading…
Reference in New Issue