Enable new atmospheres to work for irregular objects.
Moved parameter setup for atmospheres, lighting, and shadows into the CelestiaGLProgram class.ver1_5_1
parent
ffcb3299cf
commit
1cc0b38fde
|
@ -13,6 +13,7 @@
|
|||
#include <celutil/reshandle.h>
|
||||
#include <celutil/color.h>
|
||||
#include <celmath/vecmath.h>
|
||||
#include <celengine/multitexture.h>
|
||||
|
||||
|
||||
class Atmosphere
|
||||
|
@ -54,5 +55,13 @@ class Atmosphere
|
|||
Vec3f absorptionCoeff;
|
||||
};
|
||||
|
||||
// Atmosphere density is modeled with a exp(-y/H) falloff, where
|
||||
// H is the scale height of the atmosphere. Thus atmospheres have
|
||||
// infinite extent, but we still need to choose some finite sphere
|
||||
// to render. The radius of the sphere is the height at which the
|
||||
// density of the atmosphere falls to the extinction threshold, i.e.
|
||||
// -H * ln(extinctionThreshold)
|
||||
extern const double AtmosphereExtinctionThreshold;
|
||||
|
||||
#endif // _ATMOSPHERE_H_
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
// lightenv.h
|
||||
//
|
||||
// Structures that describe the lighting environment for rendering objects
|
||||
// in Celestia.
|
||||
//
|
||||
// Copyright (C) 2006, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef _CELENGINE_LIGHTENV_H_
|
||||
#define _CELENGINE_LIGHTENV_H_
|
||||
|
||||
#include <celutil/color.h>
|
||||
#include <celmath/vecmath.h>
|
||||
#include <vector>
|
||||
|
||||
static const unsigned int MaxLights = 8;
|
||||
|
||||
class DirectionalLight
|
||||
{
|
||||
public:
|
||||
Color color;
|
||||
float irradiance;
|
||||
Vec3f direction_eye;
|
||||
Vec3f direction_obj;
|
||||
|
||||
// Required for eclipse shadows only--may be able to use
|
||||
// distance instead of position.
|
||||
Point3d position;
|
||||
float apparentSize;
|
||||
};
|
||||
|
||||
class EclipseShadow
|
||||
{
|
||||
public:
|
||||
Point3f origin;
|
||||
Vec3f direction;
|
||||
float penumbraRadius;
|
||||
float umbraRadius;
|
||||
};
|
||||
|
||||
class LightingState
|
||||
{
|
||||
public:
|
||||
LightingState() : nLights(0),
|
||||
eyeDir_obj(0.0f, 0.0f, -1.0f),
|
||||
eyePos_obj(0.0f, 0.0f, -1.0f)
|
||||
{ shadows[0] = NULL; };
|
||||
|
||||
unsigned int nLights;
|
||||
DirectionalLight lights[MaxLights];
|
||||
std::vector<EclipseShadow>* shadows[MaxLights];
|
||||
|
||||
Vec3f eyeDir_obj;
|
||||
Point3f eyePos_obj;
|
||||
|
||||
Vec3f ambientColor;
|
||||
};
|
||||
|
||||
#endif // _CELENGINE_LIGHTENV_H_
|
|
@ -360,6 +360,7 @@ setExtendedVertexArrays(const Mesh::VertexDescription& desc,
|
|||
|
||||
GLSL_RenderContext::GLSL_RenderContext(const LightingState& ls, float _objRadius, const Mat4f& _xform) :
|
||||
lightingState(ls),
|
||||
atmosphere(NULL),
|
||||
blendOn(false),
|
||||
objRadius(_objRadius),
|
||||
xform(_xform),
|
||||
|
@ -402,6 +403,7 @@ GLSL_RenderContext::initLightingEnvironment()
|
|||
}
|
||||
|
||||
|
||||
// TODO: eliminate this and use CelestiaGLProgram::setLightingParameters instead
|
||||
void
|
||||
GLSL_RenderContext::setLightingParameters(CelestiaGLProgram& prog, Color materialDiffuse, Color materialSpecular)
|
||||
{
|
||||
|
@ -462,6 +464,7 @@ GLSL_RenderContext::setLightingParameters(CelestiaGLProgram& prog, Color materia
|
|||
}
|
||||
|
||||
|
||||
// TODO: eliminate this and use CelestiaGLProgram::setShadowParameters instead
|
||||
void
|
||||
GLSL_RenderContext::setShadowParameters(CelestiaGLProgram& prog)
|
||||
{
|
||||
|
@ -584,6 +587,13 @@ GLSL_RenderContext::makeCurrent(const Mesh::Material& m)
|
|||
}
|
||||
}
|
||||
|
||||
if (atmosphere != NULL)
|
||||
{
|
||||
// Only use new atmosphere code in OpenGL 2.0 path when new style parameters are defined.
|
||||
if (atmosphere->mieScaleHeight > 0.0f)
|
||||
shaderProps.texUsage |= ShaderProperties::Scattering;
|
||||
}
|
||||
|
||||
// Get a shader for the current rendering configuration
|
||||
CelestiaGLProgram* prog = GetShaderManager().getShader(shaderProps);
|
||||
if (prog == NULL)
|
||||
|
@ -613,6 +623,11 @@ GLSL_RenderContext::makeCurrent(const Mesh::Material& m)
|
|||
{
|
||||
prog->nightTexMin = 1.0f;
|
||||
}
|
||||
|
||||
if (shaderProps.hasScattering())
|
||||
{
|
||||
prog->setAtmosphereParameters(*atmosphere, objRadius, objRadius);
|
||||
}
|
||||
|
||||
bool blendOnNow = false;
|
||||
if (m.opacity != 1.0f || (baseTex != NULL && baseTex->hasAlpha()))
|
||||
|
@ -645,6 +660,12 @@ GLSL_RenderContext::setVertexArrays(const Mesh::VertexDescription& desc,
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
GLSL_RenderContext::setAtmosphere(const Atmosphere* _atmosphere)
|
||||
{
|
||||
atmosphere = _atmosphere;
|
||||
}
|
||||
|
||||
// Extended material properties -- currently just lunarLambert term
|
||||
void
|
||||
GLSL_RenderContext::setLunarLambert(float l)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// rendcontext.h
|
||||
//
|
||||
// Copyright (C) 2004, Chris Laurel <claurel@shatters.net>
|
||||
// Copyright (C) 2004-2006, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
|
@ -14,47 +14,6 @@
|
|||
#include "shadermanager.h"
|
||||
|
||||
|
||||
static const unsigned int MaxLights = 8;
|
||||
|
||||
struct DirectionalLight
|
||||
{
|
||||
Color color;
|
||||
float irradiance;
|
||||
Vec3f direction_eye;
|
||||
Vec3f direction_obj;
|
||||
|
||||
// Required for eclipse shadows only--may be able to use
|
||||
// distance instead of position.
|
||||
Point3d position;
|
||||
float apparentSize;
|
||||
};
|
||||
|
||||
struct EclipseShadow
|
||||
{
|
||||
Point3f origin;
|
||||
Vec3f direction;
|
||||
float penumbraRadius;
|
||||
float umbraRadius;
|
||||
};
|
||||
|
||||
struct LightingState
|
||||
{
|
||||
LightingState() : nLights(0),
|
||||
eyeDir_obj(0.0f, 0.0f, -1.0f),
|
||||
eyePos_obj(0.0f, 0.0f, -1.0f)
|
||||
{ shadows[0] = NULL; };
|
||||
|
||||
unsigned int nLights;
|
||||
DirectionalLight lights[MaxLights];
|
||||
std::vector<EclipseShadow>* shadows[MaxLights];
|
||||
|
||||
Vec3f eyeDir_obj;
|
||||
Point3f eyePos_obj;
|
||||
|
||||
Vec3f ambientColor;
|
||||
};
|
||||
|
||||
|
||||
class RenderContext
|
||||
{
|
||||
public:
|
||||
|
@ -138,7 +97,8 @@ class GLSL_RenderContext : public RenderContext
|
|||
virtual void setVertexArrays(const Mesh::VertexDescription& desc,
|
||||
void* vertexData);
|
||||
|
||||
virtual void setLunarLambert(float);
|
||||
virtual void setLunarLambert(float);
|
||||
virtual void setAtmosphere(const Atmosphere*);
|
||||
|
||||
private:
|
||||
void initLightingEnvironment();
|
||||
|
@ -147,6 +107,7 @@ class GLSL_RenderContext : public RenderContext
|
|||
|
||||
private:
|
||||
const LightingState& lightingState;
|
||||
const Atmosphere* atmosphere;
|
||||
bool blendOn;
|
||||
float objRadius;
|
||||
Mat4f xform;
|
||||
|
|
|
@ -4971,7 +4971,7 @@ void Renderer::renderObject(Point3f pos,
|
|||
if (context->getRenderPath() == GLContext::GLPath_GLSL && lit)
|
||||
{
|
||||
ResourceHandle texOverride = obj.surface->baseTexture.tex[textureResolution];
|
||||
renderModel_GLSL(model, ri, texOverride, ls, obj.radius, planetMat);
|
||||
renderModel_GLSL(model, ri, texOverride, ls, obj.atmosphere, obj.radius, renderFlags, planetMat);
|
||||
for (unsigned int i = 1; i < 8;/*context->getMaxTextures();*/ i++)
|
||||
{
|
||||
glx::glActiveTextureARB(GL_TEXTURE0_ARB + i);
|
||||
|
|
|
@ -50,172 +50,7 @@ using namespace std;
|
|||
const double AtmosphereExtinctionThreshold = 0.05;
|
||||
|
||||
|
||||
static void setLightParameters_GLSL(CelestiaGLProgram& prog,
|
||||
const ShaderProperties& shadprop,
|
||||
const LightingState& ls,
|
||||
Color materialDiffuse,
|
||||
Color materialSpecular)
|
||||
{
|
||||
unsigned int nLights = min(MaxShaderLights, ls.nLights);
|
||||
|
||||
Vec3f diffuseColor(materialDiffuse.red(),
|
||||
materialDiffuse.green(),
|
||||
materialDiffuse.blue());
|
||||
Vec3f specularColor(materialSpecular.red(),
|
||||
materialSpecular.green(),
|
||||
materialSpecular.blue());
|
||||
|
||||
for (unsigned int i = 0; i < nLights; i++)
|
||||
{
|
||||
const DirectionalLight& light = ls.lights[i];
|
||||
|
||||
Vec3f lightColor = Vec3f(light.color.red(),
|
||||
light.color.green(),
|
||||
light.color.blue()) * light.irradiance;
|
||||
prog.lights[i].direction = light.direction_obj;
|
||||
|
||||
if (shadprop.usesShadows() ||
|
||||
shadprop.usesFragmentLighting() ||
|
||||
shadprop.lightModel == ShaderProperties::RingIllumModel)
|
||||
{
|
||||
prog.fragLightColor[i] = Vec3f(lightColor.x * diffuseColor.x,
|
||||
lightColor.y * diffuseColor.y,
|
||||
lightColor.z * diffuseColor.z);
|
||||
if (shadprop.hasSpecular())
|
||||
{
|
||||
prog.fragLightSpecColor[i] = Vec3f(lightColor.x * specularColor.x,
|
||||
lightColor.y * specularColor.y,
|
||||
lightColor.z * specularColor.z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prog.lights[i].diffuse = Vec3f(lightColor.x * diffuseColor.x,
|
||||
lightColor.y * diffuseColor.y,
|
||||
lightColor.z * diffuseColor.z);
|
||||
}
|
||||
prog.lights[i].specular = Vec3f(lightColor.x * specularColor.x,
|
||||
lightColor.y * specularColor.y,
|
||||
lightColor.z * specularColor.z);
|
||||
|
||||
Vec3f halfAngle_obj = ls.eyeDir_obj + light.direction_obj;
|
||||
if (halfAngle_obj.length() != 0.0f)
|
||||
halfAngle_obj.normalize();
|
||||
prog.lights[i].halfVector = halfAngle_obj;
|
||||
}
|
||||
|
||||
prog.ambientColor = ls.ambientColor;
|
||||
prog.opacity = materialDiffuse.alpha();
|
||||
}
|
||||
|
||||
|
||||
// Set GLSL shader constants for shadows from ellipsoid occluders; shadows from
|
||||
// irregular objects are not handled yet.
|
||||
static void
|
||||
setEclipseShadowShaderConstants(const LightingState& ls,
|
||||
float planetRadius,
|
||||
const Mat4f& planetMat,
|
||||
CelestiaGLProgram& prog)
|
||||
{
|
||||
for (unsigned int li = 0;
|
||||
li < min(ls.nLights, MaxShaderLights);
|
||||
li++)
|
||||
{
|
||||
vector<EclipseShadow>* shadows = ls.shadows[li];
|
||||
|
||||
if (shadows != NULL)
|
||||
{
|
||||
unsigned int nShadows = min((size_t) MaxShaderShadows,
|
||||
shadows->size());
|
||||
|
||||
for (unsigned int i = 0; i < nShadows; i++)
|
||||
{
|
||||
EclipseShadow& shadow = shadows->at(i);
|
||||
CelestiaGLProgramShadow& shadowParams = prog.shadows[li][i];
|
||||
|
||||
float R2 = 0.25f;
|
||||
float umbra = shadow.umbraRadius / shadow.penumbraRadius;
|
||||
umbra = umbra * umbra;
|
||||
if (umbra < 0.0001f)
|
||||
umbra = 0.0001f;
|
||||
else if (umbra > 0.99f)
|
||||
umbra = 0.99f;
|
||||
|
||||
float umbraRadius = R2 * umbra;
|
||||
float penumbraRadius = R2;
|
||||
float shadowBias = 1.0f / (1.0f - penumbraRadius / umbraRadius);
|
||||
shadowParams.bias = shadowBias;
|
||||
shadowParams.scale = -shadowBias / umbraRadius;
|
||||
|
||||
// Compute the transformation to use for generating texture
|
||||
// coordinates from the object vertices.
|
||||
Point3f origin = shadow.origin * planetMat;
|
||||
Vec3f dir = shadow.direction * planetMat;
|
||||
float scale = planetRadius / shadow.penumbraRadius;
|
||||
Vec3f axis = Vec3f(0, 1, 0) ^ dir;
|
||||
float angle = (float) acos(Vec3f(0, 1, 0) * dir);
|
||||
axis.normalize();
|
||||
Mat4f mat = Mat4f::rotation(axis, -angle);
|
||||
Vec3f sAxis = Vec3f(0.5f * scale, 0, 0) * mat;
|
||||
Vec3f tAxis = Vec3f(0, 0, 0.5f * scale) * mat;
|
||||
|
||||
float sw = (Point3f(0, 0, 0) - origin) * sAxis / planetRadius + 0.5f;
|
||||
float tw = (Point3f(0, 0, 0) - origin) * tAxis / planetRadius + 0.5f;
|
||||
shadowParams.texGenS = Vec4f(sAxis.x, sAxis.y, sAxis.z, sw);
|
||||
shadowParams.texGenT = Vec4f(tAxis.x, tAxis.y, tAxis.z, tw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set the scattering and absoroption shader parameters for atmosphere simulation.
|
||||
// They are from standard units to the normalized system used by the shaders.
|
||||
// atmObjRadius - the radius in km of the planet with the atmosphere
|
||||
// objRadius - the radius in km of the object we're rendering
|
||||
static void setAtmosphereParameters_GLSL(CelestiaGLProgram& prog,
|
||||
const Atmosphere& atmosphere,
|
||||
float atmPlanetRadius,
|
||||
float objRadius)
|
||||
{
|
||||
// Compute the radius of the atmosphere to render; the density falls off
|
||||
// exponentially with height above the planet's surface, so the actual
|
||||
// radius is infinite. That's a bit impractical, so well just render the
|
||||
// portion out to the point where the density is 1/1000 of the surface
|
||||
// density.
|
||||
float atmosphereRadius = atmPlanetRadius + -atmosphere.mieScaleHeight * (float) log(AtmosphereExtinctionThreshold);
|
||||
|
||||
float mieCoeff = atmosphere.mieCoeff * objRadius;
|
||||
Vec3f rayleighCoeff = atmosphere.rayleighCoeff * objRadius;
|
||||
Vec3f absorptionCoeff = atmosphere.absorptionCoeff * objRadius;
|
||||
|
||||
float r = atmosphereRadius / objRadius;
|
||||
prog.atmosphereRadius = Vec3f(r, r * r, atmPlanetRadius / objRadius);
|
||||
|
||||
prog.mieCoeff = mieCoeff;
|
||||
prog.mieScaleHeight = objRadius / atmosphere.mieScaleHeight;
|
||||
|
||||
// The scattering shaders use the Schlick approximation to the
|
||||
// Henyey-Greenstein phase function because it's slightly faster
|
||||
// to compute. Convert the HG asymmetry parameter to the Schlick
|
||||
// parameter.
|
||||
float g = atmosphere.miePhaseAsymmetry;
|
||||
prog.miePhaseAsymmetry = 1.55f * g - 0.55f * g * g * g;
|
||||
|
||||
prog.rayleighCoeff = rayleighCoeff;
|
||||
prog.rayleighScaleHeight = 0.0f; // TODO
|
||||
|
||||
// Precompute sum and inverse sum of scattering coefficients to save work
|
||||
// in the vertex shader.
|
||||
Vec3f scatterCoeffSum = Vec3f(rayleighCoeff.x + mieCoeff,
|
||||
rayleighCoeff.y + mieCoeff,
|
||||
rayleighCoeff.z + mieCoeff);
|
||||
prog.scatterCoeffSum = scatterCoeffSum;
|
||||
prog.invScatterCoeffSum = Vec3f(1.0f / scatterCoeffSum.x, 1.0f / scatterCoeffSum.y, 1.0f / scatterCoeffSum.z);
|
||||
prog.extinctionCoeff = scatterCoeffSum + absorptionCoeff;
|
||||
}
|
||||
|
||||
|
||||
// Render a planet sphere with GLSL shaders
|
||||
void renderSphere_GLSL(const RenderInfo& ri,
|
||||
const LightingState& ls,
|
||||
RingSystem* rings,
|
||||
|
@ -348,8 +183,7 @@ void renderSphere_GLSL(const RenderInfo& ri,
|
|||
|
||||
prog->use();
|
||||
|
||||
setLightParameters_GLSL(*prog, shadprop, ls,
|
||||
ri.color, ri.specularColor);
|
||||
prog->setLightParameters(ls, ri.color, ri.specularColor);
|
||||
|
||||
prog->eyePosition = ls.eyePos_obj;
|
||||
prog->shininess = ri.specularPower;
|
||||
|
@ -376,11 +210,11 @@ void renderSphere_GLSL(const RenderInfo& ri,
|
|||
|
||||
if (shadprop.hasScattering())
|
||||
{
|
||||
setAtmosphereParameters_GLSL(*prog, *atmosphere, radius, radius);
|
||||
prog->setAtmosphereParameters(*atmosphere, radius, radius);
|
||||
}
|
||||
|
||||
if (shadprop.shadowCounts != 0)
|
||||
setEclipseShadowShaderConstants(ls, radius, planetMat, *prog);
|
||||
prog->setEclipseShadowParameters(ls, radius, planetMat);
|
||||
|
||||
glColor(ri.color);
|
||||
|
||||
|
@ -396,17 +230,25 @@ void renderSphere_GLSL(const RenderInfo& ri,
|
|||
}
|
||||
|
||||
|
||||
// Render a mesh object
|
||||
void renderModel_GLSL(Model* model,
|
||||
const RenderInfo& ri,
|
||||
ResourceHandle texOverride,
|
||||
const LightingState& ls,
|
||||
const Atmosphere* atmosphere,
|
||||
float radius,
|
||||
int renderFlags,
|
||||
const Mat4f& planetMat)
|
||||
{
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
GLSL_RenderContext rc(ls, radius, planetMat);
|
||||
|
||||
if (renderFlags & Renderer::ShowAtmospheres)
|
||||
{
|
||||
rc.setAtmosphere(atmosphere);
|
||||
}
|
||||
|
||||
// Handle extended material attributes (per model only, not per submesh)
|
||||
rc.setLunarLambert(ri.lunarLambert);
|
||||
|
||||
|
@ -427,6 +269,7 @@ void renderModel_GLSL(Model* model,
|
|||
}
|
||||
|
||||
|
||||
// Render the cloud sphere for a world a cloud layer defined
|
||||
void renderClouds_GLSL(const RenderInfo& ri,
|
||||
const LightingState& ls,
|
||||
Atmosphere* atmosphere,
|
||||
|
@ -507,8 +350,7 @@ void renderClouds_GLSL(const RenderInfo& ri,
|
|||
|
||||
prog->use();
|
||||
|
||||
setLightParameters_GLSL(*prog, shadprop, ls,
|
||||
ri.color, ri.specularColor);
|
||||
prog->setLightParameters(ls, ri.color, ri.specularColor);
|
||||
prog->eyePosition = ls.eyePos_obj;
|
||||
prog->ambientColor = Vec3f(ri.ambientColor.red(), ri.ambientColor.green(),
|
||||
ri.ambientColor.blue());
|
||||
|
@ -518,7 +360,7 @@ void renderClouds_GLSL(const RenderInfo& ri,
|
|||
|
||||
if (shadprop.hasScattering())
|
||||
{
|
||||
setAtmosphereParameters_GLSL(*prog, *atmosphere, radius, cloudRadius);
|
||||
prog->setAtmosphereParameters(*atmosphere, radius, cloudRadius);
|
||||
}
|
||||
|
||||
if (shadprop.texUsage & ShaderProperties::RingShadowTexture)
|
||||
|
@ -529,7 +371,7 @@ void renderClouds_GLSL(const RenderInfo& ri,
|
|||
}
|
||||
|
||||
if (shadprop.shadowCounts != 0)
|
||||
setEclipseShadowShaderConstants(ls, cloudRadius, planetMat, *prog);
|
||||
prog->setEclipseShadowParameters(ls, cloudRadius, planetMat);
|
||||
|
||||
unsigned int attributes = LODSphereMesh::Normals;
|
||||
g_lodSphere->render(context,
|
||||
|
@ -543,6 +385,7 @@ void renderClouds_GLSL(const RenderInfo& ri,
|
|||
}
|
||||
|
||||
|
||||
// Render the sky sphere for a world with an atmosphere
|
||||
void
|
||||
renderAtmosphere_GLSL(const RenderInfo& ri,
|
||||
const LightingState& ls,
|
||||
|
@ -569,19 +412,19 @@ renderAtmosphere_GLSL(const RenderInfo& ri,
|
|||
|
||||
prog->use();
|
||||
|
||||
setLightParameters_GLSL(*prog, shadprop, ls,
|
||||
ri.color, ri.specularColor);
|
||||
prog->setLightParameters(ls, ri.color, ri.specularColor);
|
||||
prog->ambientColor = Vec3f(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float atmosphereRadius = radius + -atmosphere->mieScaleHeight * (float) log(AtmosphereExtinctionThreshold);
|
||||
float atmScale = atmosphereRadius / radius;
|
||||
|
||||
prog->eyePosition = Point3f(ls.eyePos_obj.x / atmScale, ls.eyePos_obj.y / atmScale, ls.eyePos_obj.z / atmScale);
|
||||
setAtmosphereParameters_GLSL(*prog, *atmosphere, radius, atmosphereRadius);
|
||||
prog->setAtmosphereParameters(*atmosphere, radius, atmosphereRadius);
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
// Currently eclipse shadows are ignored when rendering atmospheres
|
||||
if (shadprop.shadowCounts != 0)
|
||||
setEclipseShadowShaderConstants(ls, radius, planetMat, *prog);
|
||||
prog->setEclipseShadowParameters(ls, radius, planetMat);
|
||||
#endif
|
||||
|
||||
glPushMatrix();
|
||||
|
@ -634,6 +477,7 @@ static void renderRingSystem(float innerRadius,
|
|||
}
|
||||
|
||||
|
||||
// Render a planetary ring system
|
||||
void renderRings_GLSL(RingSystem& rings,
|
||||
RenderInfo& ri,
|
||||
const LightingState& ls,
|
||||
|
@ -675,8 +519,7 @@ void renderRings_GLSL(RingSystem& rings,
|
|||
prog->eyePosition = ls.eyePos_obj;
|
||||
prog->ambientColor = Vec3f(ri.ambientColor.red(), ri.ambientColor.green(),
|
||||
ri.ambientColor.blue());
|
||||
setLightParameters_GLSL(*prog, shadprop, ls,
|
||||
ri.color, ri.specularColor);
|
||||
prog->setLightParameters(ls, ri.color, ri.specularColor);
|
||||
|
||||
for (unsigned int li = 0; li < ls.nLights; li++)
|
||||
{
|
||||
|
|
|
@ -9,13 +9,10 @@
|
|||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
// Atmosphere density is modeled with a exp(-y/H) falloff, where
|
||||
// H is the scale height of the atmosphere. Thus atmospheres have
|
||||
// infinite extent, but we still need to choose some finite sphere
|
||||
// to render. The radius of the sphere is the height at which the
|
||||
// density of the atmosphere falls to the extinction threshold, i.e.
|
||||
// -H * ln(extinctionThreshold)
|
||||
extern const double AtmosphereExtinctionThreshold;
|
||||
#ifndef _CELENGINE_RENDERGLSL_H_
|
||||
#define _CELENGINE_RENDERGLSL_H_
|
||||
|
||||
#include <celengine/lightenv.h>
|
||||
|
||||
void renderSphere_GLSL(const RenderInfo& ri,
|
||||
const LightingState& ls,
|
||||
|
@ -33,7 +30,9 @@ void renderModel_GLSL(Model* model,
|
|||
const RenderInfo& ri,
|
||||
ResourceHandle texOverride,
|
||||
const LightingState& ls,
|
||||
const Atmosphere* atmosphere,
|
||||
float radius,
|
||||
int renderFlags,
|
||||
const Mat4f& planetMat);
|
||||
|
||||
void renderClouds_GLSL(const RenderInfo& ri,
|
||||
|
@ -66,6 +65,7 @@ void renderRings_GLSL(RingSystem& rings,
|
|||
bool renderShadow,
|
||||
unsigned int nSections);
|
||||
|
||||
#endif // _CELENGINE_RENDERGLSL_H_
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ static const char* errorFragmentShaderSource =
|
|||
"}\n";
|
||||
|
||||
|
||||
|
||||
ShaderManager&
|
||||
GetShaderManager()
|
||||
{
|
||||
|
@ -205,42 +206,6 @@ ShaderManager::getShader(const ShaderProperties& props)
|
|||
}
|
||||
|
||||
|
||||
CelestiaGLProgram::CelestiaGLProgram(GLProgram& _program,
|
||||
const ShaderProperties& props) :
|
||||
program(&_program)
|
||||
{
|
||||
initParameters(props);
|
||||
initSamplers(props);
|
||||
};
|
||||
|
||||
|
||||
CelestiaGLProgram::~CelestiaGLProgram()
|
||||
{
|
||||
delete program;
|
||||
}
|
||||
|
||||
|
||||
FloatShaderParameter
|
||||
CelestiaGLProgram::floatParam(const string& paramName)
|
||||
{
|
||||
return FloatShaderParameter(program->getID(), paramName.c_str());
|
||||
}
|
||||
|
||||
|
||||
Vec3ShaderParameter
|
||||
CelestiaGLProgram::vec3Param(const string& paramName)
|
||||
{
|
||||
return Vec3ShaderParameter(program->getID(), paramName.c_str());
|
||||
}
|
||||
|
||||
|
||||
Vec4ShaderParameter
|
||||
CelestiaGLProgram::vec4Param(const string& paramName)
|
||||
{
|
||||
return Vec4ShaderParameter(program->getID(), paramName.c_str());
|
||||
}
|
||||
|
||||
|
||||
static string
|
||||
LightProperty(unsigned int i, char* property)
|
||||
{
|
||||
|
@ -313,142 +278,6 @@ VarScatterInFS()
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
CelestiaGLProgram::initParameters(const ShaderProperties& props)
|
||||
{
|
||||
for (unsigned int i = 0; i < props.nLights; i++)
|
||||
{
|
||||
lights[i].direction = vec3Param(LightProperty(i, "direction"));
|
||||
lights[i].diffuse = vec3Param(LightProperty(i, "diffuse"));
|
||||
lights[i].specular = vec3Param(LightProperty(i, "specular"));
|
||||
lights[i].halfVector = vec3Param(LightProperty(i, "halfVector"));
|
||||
|
||||
fragLightColor[i] = vec3Param(FragLightProperty(i, "color"));
|
||||
fragLightSpecColor[i] = vec3Param(FragLightProperty(i, "specColor"));
|
||||
|
||||
for (unsigned int j = 0; j < props.getShadowCountForLight(i); j++)
|
||||
{
|
||||
shadows[i][j].texGenS =
|
||||
vec4Param(IndexedParameter("shadowTexGenS", i, j));
|
||||
shadows[i][j].texGenT =
|
||||
vec4Param(IndexedParameter("shadowTexGenT", i, j));
|
||||
shadows[i][j].scale =
|
||||
floatParam(IndexedParameter("shadowScale", i, j));
|
||||
shadows[i][j].bias =
|
||||
floatParam(IndexedParameter("shadowBias", i, j));
|
||||
}
|
||||
}
|
||||
|
||||
if (props.hasSpecular())
|
||||
{
|
||||
shininess = floatParam("shininess");
|
||||
}
|
||||
|
||||
if (props.isViewDependent() || props.hasScattering())
|
||||
{
|
||||
eyePosition = vec3Param("eyePosition");
|
||||
}
|
||||
|
||||
opacity = floatParam("opacity");
|
||||
ambientColor = vec3Param("ambientColor");
|
||||
|
||||
if (props.texUsage & ShaderProperties::RingShadowTexture)
|
||||
{
|
||||
ringWidth = floatParam("ringWidth");
|
||||
ringRadius = floatParam("ringRadius");
|
||||
}
|
||||
|
||||
textureOffset = floatParam("textureOffset");
|
||||
|
||||
if (props.texUsage & ShaderProperties::CloudShadowTexture)
|
||||
{
|
||||
cloudHeight = floatParam("cloudHeight");
|
||||
shadowTextureOffset = floatParam("cloudShadowTexOffset");
|
||||
}
|
||||
|
||||
if ((props.texUsage & ShaderProperties::NightTexture) != 0)
|
||||
{
|
||||
nightTexMin = floatParam("nightTexMin");
|
||||
}
|
||||
|
||||
if (props.hasScattering())
|
||||
{
|
||||
mieCoeff = floatParam("mieCoeff");
|
||||
mieScaleHeight = floatParam("mieH");
|
||||
miePhaseAsymmetry = floatParam("mieK");
|
||||
rayleighCoeff = vec3Param("rayleighCoeff");
|
||||
rayleighScaleHeight = floatParam("rayleighH");
|
||||
atmosphereRadius = vec3Param("atmosphereRadius");
|
||||
scatterCoeffSum = vec3Param("scatterCoeffSum");
|
||||
invScatterCoeffSum = vec3Param("invScatterCoeffSum");
|
||||
extinctionCoeff = vec3Param("extinctionCoeff");
|
||||
}
|
||||
|
||||
if (props.lightModel == ShaderProperties::LunarLambertModel)
|
||||
{
|
||||
lunarLambert = floatParam("lunarLambert");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CelestiaGLProgram::initSamplers(const ShaderProperties& props)
|
||||
{
|
||||
program->use();
|
||||
|
||||
unsigned int nSamplers = 0;
|
||||
|
||||
if (props.texUsage & ShaderProperties::DiffuseTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "diffTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::NormalTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "normTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::SpecularTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "specTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::NightTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "nightTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::RingShadowTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "ringTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::OverlayTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "overlayTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::CloudShadowTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "cloudShadowTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DumpShaderSource(ostream& out, const std::string& source)
|
||||
{
|
||||
|
@ -615,7 +444,7 @@ AssignDiffuse(unsigned int lightIndex, const ShaderProperties& props)
|
|||
// NH - dot product of light and half vectors
|
||||
|
||||
static string
|
||||
DirectionalLight(unsigned int i, const ShaderProperties& props)
|
||||
AddDirectionalLightContrib(unsigned int i, const ShaderProperties& props)
|
||||
{
|
||||
string source;
|
||||
|
||||
|
@ -1185,7 +1014,7 @@ ShaderManager::buildVertexShader(const ShaderProperties& props)
|
|||
|
||||
for (unsigned int i = 0; i < props.nLights; i++)
|
||||
{
|
||||
source += DirectionalLight(i, props);
|
||||
source += AddDirectionalLightContrib(i, props);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::NightTexture)
|
||||
|
@ -1991,3 +1820,340 @@ ShaderManager::buildProgram(const ShaderProperties& props)
|
|||
else
|
||||
return new CelestiaGLProgram(*prog, props);
|
||||
}
|
||||
|
||||
|
||||
CelestiaGLProgram::CelestiaGLProgram(GLProgram& _program,
|
||||
const ShaderProperties& _props) :
|
||||
program(&_program),
|
||||
props(_props)
|
||||
{
|
||||
initParameters();
|
||||
initSamplers();
|
||||
};
|
||||
|
||||
|
||||
CelestiaGLProgram::~CelestiaGLProgram()
|
||||
{
|
||||
delete program;
|
||||
}
|
||||
|
||||
|
||||
FloatShaderParameter
|
||||
CelestiaGLProgram::floatParam(const string& paramName)
|
||||
{
|
||||
return FloatShaderParameter(program->getID(), paramName.c_str());
|
||||
}
|
||||
|
||||
|
||||
Vec3ShaderParameter
|
||||
CelestiaGLProgram::vec3Param(const string& paramName)
|
||||
{
|
||||
return Vec3ShaderParameter(program->getID(), paramName.c_str());
|
||||
}
|
||||
|
||||
|
||||
Vec4ShaderParameter
|
||||
CelestiaGLProgram::vec4Param(const string& paramName)
|
||||
{
|
||||
return Vec4ShaderParameter(program->getID(), paramName.c_str());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CelestiaGLProgram::initParameters()
|
||||
{
|
||||
for (unsigned int i = 0; i < props.nLights; i++)
|
||||
{
|
||||
lights[i].direction = vec3Param(LightProperty(i, "direction"));
|
||||
lights[i].diffuse = vec3Param(LightProperty(i, "diffuse"));
|
||||
lights[i].specular = vec3Param(LightProperty(i, "specular"));
|
||||
lights[i].halfVector = vec3Param(LightProperty(i, "halfVector"));
|
||||
|
||||
fragLightColor[i] = vec3Param(FragLightProperty(i, "color"));
|
||||
fragLightSpecColor[i] = vec3Param(FragLightProperty(i, "specColor"));
|
||||
|
||||
for (unsigned int j = 0; j < props.getShadowCountForLight(i); j++)
|
||||
{
|
||||
shadows[i][j].texGenS =
|
||||
vec4Param(IndexedParameter("shadowTexGenS", i, j));
|
||||
shadows[i][j].texGenT =
|
||||
vec4Param(IndexedParameter("shadowTexGenT", i, j));
|
||||
shadows[i][j].scale =
|
||||
floatParam(IndexedParameter("shadowScale", i, j));
|
||||
shadows[i][j].bias =
|
||||
floatParam(IndexedParameter("shadowBias", i, j));
|
||||
}
|
||||
}
|
||||
|
||||
if (props.hasSpecular())
|
||||
{
|
||||
shininess = floatParam("shininess");
|
||||
}
|
||||
|
||||
if (props.isViewDependent() || props.hasScattering())
|
||||
{
|
||||
eyePosition = vec3Param("eyePosition");
|
||||
}
|
||||
|
||||
opacity = floatParam("opacity");
|
||||
ambientColor = vec3Param("ambientColor");
|
||||
|
||||
if (props.texUsage & ShaderProperties::RingShadowTexture)
|
||||
{
|
||||
ringWidth = floatParam("ringWidth");
|
||||
ringRadius = floatParam("ringRadius");
|
||||
}
|
||||
|
||||
textureOffset = floatParam("textureOffset");
|
||||
|
||||
if (props.texUsage & ShaderProperties::CloudShadowTexture)
|
||||
{
|
||||
cloudHeight = floatParam("cloudHeight");
|
||||
shadowTextureOffset = floatParam("cloudShadowTexOffset");
|
||||
}
|
||||
|
||||
if ((props.texUsage & ShaderProperties::NightTexture) != 0)
|
||||
{
|
||||
nightTexMin = floatParam("nightTexMin");
|
||||
}
|
||||
|
||||
if (props.hasScattering())
|
||||
{
|
||||
mieCoeff = floatParam("mieCoeff");
|
||||
mieScaleHeight = floatParam("mieH");
|
||||
miePhaseAsymmetry = floatParam("mieK");
|
||||
rayleighCoeff = vec3Param("rayleighCoeff");
|
||||
rayleighScaleHeight = floatParam("rayleighH");
|
||||
atmosphereRadius = vec3Param("atmosphereRadius");
|
||||
scatterCoeffSum = vec3Param("scatterCoeffSum");
|
||||
invScatterCoeffSum = vec3Param("invScatterCoeffSum");
|
||||
extinctionCoeff = vec3Param("extinctionCoeff");
|
||||
}
|
||||
|
||||
if (props.lightModel == ShaderProperties::LunarLambertModel)
|
||||
{
|
||||
lunarLambert = floatParam("lunarLambert");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CelestiaGLProgram::initSamplers()
|
||||
{
|
||||
program->use();
|
||||
|
||||
unsigned int nSamplers = 0;
|
||||
|
||||
if (props.texUsage & ShaderProperties::DiffuseTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "diffTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::NormalTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "normTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::SpecularTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "specTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::NightTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "nightTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::RingShadowTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "ringTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::OverlayTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "overlayTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
|
||||
if (props.texUsage & ShaderProperties::CloudShadowTexture)
|
||||
{
|
||||
int slot = glx::glGetUniformLocationARB(program->getID(), "cloudShadowTex");
|
||||
if (slot != -1)
|
||||
glx::glUniform1iARB(slot, nSamplers++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CelestiaGLProgram::setLightParameters(const LightingState& ls,
|
||||
Color materialDiffuse,
|
||||
Color materialSpecular)
|
||||
{
|
||||
unsigned int nLights = min(MaxShaderLights, ls.nLights);
|
||||
|
||||
Vec3f diffuseColor(materialDiffuse.red(),
|
||||
materialDiffuse.green(),
|
||||
materialDiffuse.blue());
|
||||
Vec3f specularColor(materialSpecular.red(),
|
||||
materialSpecular.green(),
|
||||
materialSpecular.blue());
|
||||
|
||||
for (unsigned int i = 0; i < nLights; i++)
|
||||
{
|
||||
const DirectionalLight& light = ls.lights[i];
|
||||
|
||||
Vec3f lightColor = Vec3f(light.color.red(),
|
||||
light.color.green(),
|
||||
light.color.blue()) * light.irradiance;
|
||||
lights[i].direction = light.direction_obj;
|
||||
|
||||
if (props.usesShadows() ||
|
||||
props.usesFragmentLighting() ||
|
||||
props.lightModel == ShaderProperties::RingIllumModel)
|
||||
{
|
||||
fragLightColor[i] = Vec3f(lightColor.x * diffuseColor.x,
|
||||
lightColor.y * diffuseColor.y,
|
||||
lightColor.z * diffuseColor.z);
|
||||
if (props.hasSpecular())
|
||||
{
|
||||
fragLightSpecColor[i] = Vec3f(lightColor.x * specularColor.x,
|
||||
lightColor.y * specularColor.y,
|
||||
lightColor.z * specularColor.z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lights[i].diffuse = Vec3f(lightColor.x * diffuseColor.x,
|
||||
lightColor.y * diffuseColor.y,
|
||||
lightColor.z * diffuseColor.z);
|
||||
}
|
||||
|
||||
lights[i].specular = Vec3f(lightColor.x * specularColor.x,
|
||||
lightColor.y * specularColor.y,
|
||||
lightColor.z * specularColor.z);
|
||||
|
||||
Vec3f halfAngle_obj = ls.eyeDir_obj + light.direction_obj;
|
||||
if (halfAngle_obj.length() != 0.0f)
|
||||
halfAngle_obj.normalize();
|
||||
lights[i].halfVector = halfAngle_obj;
|
||||
}
|
||||
|
||||
eyePosition = ls.eyePos_obj;
|
||||
ambientColor = Vec3f(ls.ambientColor.x * diffuseColor.x,
|
||||
ls.ambientColor.y * diffuseColor.y,
|
||||
ls.ambientColor.z * diffuseColor.z);
|
||||
opacity = materialDiffuse.alpha();
|
||||
}
|
||||
|
||||
|
||||
// Set GLSL shader constants for shadows from ellipsoid occluders; shadows from
|
||||
// irregular objects are not handled yet.
|
||||
void
|
||||
CelestiaGLProgram::setEclipseShadowParameters(const LightingState& ls,
|
||||
float planetRadius,
|
||||
const Mat4f& planetMat)
|
||||
{
|
||||
for (unsigned int li = 0;
|
||||
li < min(ls.nLights, MaxShaderLights);
|
||||
li++)
|
||||
{
|
||||
if (shadows != NULL)
|
||||
{
|
||||
unsigned int nShadows = min((size_t) MaxShaderShadows, ls.shadows[li]->size());
|
||||
|
||||
for (unsigned int i = 0; i < nShadows; i++)
|
||||
{
|
||||
EclipseShadow& shadow = ls.shadows[li]->at(i);
|
||||
CelestiaGLProgramShadow& shadowParams = shadows[li][i];
|
||||
|
||||
float R2 = 0.25f;
|
||||
float umbra = shadow.umbraRadius / shadow.penumbraRadius;
|
||||
umbra = umbra * umbra;
|
||||
if (umbra < 0.0001f)
|
||||
umbra = 0.0001f;
|
||||
else if (umbra > 0.99f)
|
||||
umbra = 0.99f;
|
||||
|
||||
float umbraRadius = R2 * umbra;
|
||||
float penumbraRadius = R2;
|
||||
float shadowBias = 1.0f / (1.0f - penumbraRadius / umbraRadius);
|
||||
shadowParams.bias = shadowBias;
|
||||
shadowParams.scale = -shadowBias / umbraRadius;
|
||||
|
||||
// Compute the transformation to use for generating texture
|
||||
// coordinates from the object vertices.
|
||||
Point3f origin = shadow.origin * planetMat;
|
||||
Vec3f dir = shadow.direction * planetMat;
|
||||
float scale = planetRadius / shadow.penumbraRadius;
|
||||
Vec3f axis = Vec3f(0, 1, 0) ^ dir;
|
||||
float angle = (float) acos(Vec3f(0, 1, 0) * dir);
|
||||
axis.normalize();
|
||||
Mat4f mat = Mat4f::rotation(axis, -angle);
|
||||
Vec3f sAxis = Vec3f(0.5f * scale, 0, 0) * mat;
|
||||
Vec3f tAxis = Vec3f(0, 0, 0.5f * scale) * mat;
|
||||
|
||||
float sw = (Point3f(0, 0, 0) - origin) * sAxis / planetRadius + 0.5f;
|
||||
float tw = (Point3f(0, 0, 0) - origin) * tAxis / planetRadius + 0.5f;
|
||||
shadowParams.texGenS = Vec4f(sAxis.x, sAxis.y, sAxis.z, sw);
|
||||
shadowParams.texGenT = Vec4f(tAxis.x, tAxis.y, tAxis.z, tw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set the scattering and absoroption shader parameters for atmosphere simulation.
|
||||
// They are from standard units to the normalized system used by the shaders.
|
||||
// atmPlanetRadius - the radius in km of the planet with the atmosphere
|
||||
// objRadius - the radius in km of the object we're rendering
|
||||
void
|
||||
CelestiaGLProgram::setAtmosphereParameters(const Atmosphere& atmosphere,
|
||||
float atmPlanetRadius,
|
||||
float objRadius)
|
||||
{
|
||||
// Compute the radius of the sky sphere to render; the density of the atmosphere
|
||||
// fallse off exponentially with height above the planet's surface, so the actual
|
||||
// radius is infinite. That's a bit impractical, so well just render the portion
|
||||
// out to the point where the density is some fraction of the surface density.
|
||||
float skySphereRadius = atmPlanetRadius + -atmosphere.mieScaleHeight * (float) log(AtmosphereExtinctionThreshold);
|
||||
|
||||
float tMieCoeff = atmosphere.mieCoeff * objRadius;
|
||||
Vec3f tRayleighCoeff = atmosphere.rayleighCoeff * objRadius;
|
||||
Vec3f tAbsorptionCoeff = atmosphere.absorptionCoeff * objRadius;
|
||||
|
||||
float r = skySphereRadius / objRadius;
|
||||
atmosphereRadius = Vec3f(r, r * r, atmPlanetRadius / objRadius);
|
||||
|
||||
mieCoeff = tMieCoeff;
|
||||
mieScaleHeight = objRadius / atmosphere.mieScaleHeight;
|
||||
|
||||
// The scattering shaders use the Schlick approximation to the
|
||||
// Henyey-Greenstein phase function because it's slightly faster
|
||||
// to compute. Convert the HG asymmetry parameter to the Schlick
|
||||
// parameter.
|
||||
float g = atmosphere.miePhaseAsymmetry;
|
||||
miePhaseAsymmetry = 1.55f * g - 0.55f * g * g * g;
|
||||
|
||||
rayleighCoeff = tRayleighCoeff;
|
||||
rayleighScaleHeight = 0.0f; // TODO
|
||||
|
||||
// Precompute sum and inverse sum of scattering coefficients to save work
|
||||
// in the vertex shader.
|
||||
Vec3f tScatterCoeffSum = Vec3f(tRayleighCoeff.x + tMieCoeff,
|
||||
tRayleighCoeff.y + tMieCoeff,
|
||||
tRayleighCoeff.z + tMieCoeff);
|
||||
scatterCoeffSum = tScatterCoeffSum;
|
||||
invScatterCoeffSum = Vec3f(1.0f / tScatterCoeffSum.x, 1.0f / tScatterCoeffSum.y, 1.0f / tScatterCoeffSum.z);
|
||||
extinctionCoeff = tScatterCoeffSum + tAbsorptionCoeff;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <map>
|
||||
#include <iostream>
|
||||
#include <celengine/glshader.h>
|
||||
#include <celengine/lightenv.h>
|
||||
#include <celengine/atmosphere.h>
|
||||
|
||||
class ShaderProperties
|
||||
{
|
||||
|
@ -91,6 +93,16 @@ class CelestiaGLProgram
|
|||
|
||||
void use() const { program->use(); }
|
||||
|
||||
void setLightParameters(const LightingState& ls,
|
||||
Color materialDiffuse,
|
||||
Color materialSpecular);
|
||||
void setEclipseShadowParameters(const LightingState& ls,
|
||||
float planetRadius,
|
||||
const Mat4f& planetMat);
|
||||
void setAtmosphereParameters(const Atmosphere& atmosphere,
|
||||
float atmPlanetRadius,
|
||||
float objRadius);
|
||||
|
||||
public:
|
||||
CelestiaGLProgramLight lights[MaxShaderLights];
|
||||
Vec3ShaderParameter fragLightColor[MaxShaderLights];
|
||||
|
@ -152,14 +164,15 @@ class CelestiaGLProgram
|
|||
CelestiaGLProgramShadow shadows[MaxShaderLights][MaxShaderShadows];
|
||||
|
||||
private:
|
||||
void initParameters(const ShaderProperties&);
|
||||
void initSamplers(const ShaderProperties&);
|
||||
void initParameters();
|
||||
void initSamplers();
|
||||
|
||||
FloatShaderParameter floatParam(const std::string&);
|
||||
Vec3ShaderParameter vec3Param(const std::string&);
|
||||
Vec4ShaderParameter vec4Param(const std::string&);
|
||||
|
||||
GLProgram* program;
|
||||
const ShaderProperties props;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue