Fixed eclipse shadows on non-spherical planets (especially noticeable on

Saturn.) Fix affects the GLSL/OpenGL 2.0 render path only.
sensor-dev
Chris Laurel 2010-04-23 22:14:44 +00:00
parent f357f2608b
commit 52b1dccdff
7 changed files with 76 additions and 44 deletions

View File

@ -549,6 +549,20 @@ GLSL_RenderContext::GLSL_RenderContext(const LightingState& ls, float _objRadius
atmosphere(NULL),
blendMode(Material::InvalidBlend),
objRadius(_objRadius),
objScale(Vector3f::Constant(_objRadius)),
objOrientation(orientation),
lunarLambert(0.0f)
{
initLightingEnvironment();
}
GLSL_RenderContext::GLSL_RenderContext(const LightingState& ls, const Eigen::Vector3f& _objScale, const Quaternionf& orientation) :
lightingState(ls),
atmosphere(NULL),
blendMode(Material::InvalidBlend),
objRadius(_objScale.maxCoeff()),
objScale(_objScale),
objOrientation(orientation),
lunarLambert(0.0f)
{
@ -749,7 +763,7 @@ GLSL_RenderContext::makeCurrent(const Material& m)
prog->setLightParameters(lightingState, diffuse, specular, emissive);
if (shaderProps.hasEclipseShadows() != 0)
prog->setEclipseShadowParameters(lightingState, objRadius, objOrientation);
prog->setEclipseShadowParameters(lightingState, objScale, objOrientation);
// TODO: handle emissive color
prog->shininess = m.specularPower;

View File

@ -115,6 +115,7 @@ class GLSL_RenderContext : public RenderContext
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
GLSL_RenderContext(const LightingState& ls, float _objRadius, const Eigen::Quaternionf& orientation);
GLSL_RenderContext(const LightingState& ls, const Eigen::Vector3f& _objScale, const Eigen::Quaternionf& orientation);
virtual ~GLSL_RenderContext();
virtual void makeCurrent(const cmod::Material&);
@ -134,6 +135,7 @@ class GLSL_RenderContext : public RenderContext
const Atmosphere* atmosphere;
cmod::Material::BlendMode blendMode;
float objRadius;
Eigen::Vector3f objScale;
Eigen::Quaternionf objOrientation;
// extended material properties

View File

@ -7064,12 +7064,12 @@ void Renderer::renderObject(const Vector3f& pos,
switch (context->getRenderPath())
{
case GLContext::GLPath_GLSL:
renderSphere_GLSL(ri, ls,
const_cast<Atmosphere*>(obj.atmosphere), cloudTexOffset,
obj.radius,
textureResolution,
renderFlags,
obj.orientation, viewFrustum, *context);
renderEllipsoid_GLSL(ri, ls,
const_cast<Atmosphere*>(obj.atmosphere), cloudTexOffset,
scaleFactors,
textureResolution,
renderFlags,
obj.orientation, viewFrustum, *context);
break;
case GLContext::GLPath_NV30:
@ -7282,7 +7282,7 @@ void Renderer::renderObject(const Vector3f& pos,
cloudTex,
cloudNormalMap,
cloudTexOffset,
radius,
scaleFactors,
textureResolution,
renderFlags,
obj.orientation,

View File

@ -52,17 +52,19 @@ const double AtmosphereExtinctionThreshold = 0.05;
// Render a planet sphere with GLSL shaders
void renderSphere_GLSL(const RenderInfo& ri,
void renderEllipsoid_GLSL(const RenderInfo& ri,
const LightingState& ls,
Atmosphere* atmosphere,
float cloudTexOffset,
float radius,
const Vector3f& semiAxes,
unsigned int textureRes,
int renderFlags,
const Quaternionf& planetOrientation,
const Frustum& frustum,
const GLContext& context)
{
float radius = semiAxes.maxCoeff();
Texture* textures[MAX_SPHERE_MESH_TEXTURES] =
{ NULL, NULL, NULL, NULL, NULL, NULL };
unsigned int nTextures = 0;
@ -271,7 +273,7 @@ void renderSphere_GLSL(const RenderInfo& ri,
}
if (shadprop.hasEclipseShadows() != 0)
prog->setEclipseShadowParameters(ls, radius, planetOrientation);
prog->setEclipseShadowParameters(ls, semiAxes, planetOrientation);
glColor(ri.color);
@ -391,13 +393,15 @@ void renderClouds_GLSL(const RenderInfo& ri,
Texture* cloudTex,
Texture* cloudNormalMap,
float texOffset,
float radius,
const Vector3f& semiAxes,
unsigned int textureRes,
int renderFlags,
const Quaternionf& planetOrientation,
const Frustum& frustum,
const GLContext& context)
{
float radius = semiAxes.maxCoeff();
Texture* textures[MAX_SPHERE_MESH_TEXTURES] =
{ NULL, NULL, NULL, NULL, NULL, NULL };
unsigned int nTextures = 0;
@ -500,7 +504,7 @@ void renderClouds_GLSL(const RenderInfo& ri,
#endif
if (shadprop.shadowCounts != 0)
prog->setEclipseShadowParameters(ls, cloudRadius, planetOrientation);
prog->setEclipseShadowParameters(ls, semiAxes, planetOrientation);
unsigned int attributes = LODSphereMesh::Normals;
if (cloudNormalMap != NULL)

View File

@ -17,11 +17,11 @@
#include <Eigen/Geometry>
void renderSphere_GLSL(const RenderInfo& ri,
void renderEllipsoid_GLSL(const RenderInfo& ri,
const LightingState& ls,
Atmosphere* atmosphere,
float cloudTexOffset,
float radius,
const Eigen::Vector3f& semiAxes,
unsigned int textureRes,
int renderFlags,
const Eigen::Quaternionf& planetOrientation,
@ -44,7 +44,7 @@ void renderClouds_GLSL(const RenderInfo& ri,
Texture* cloudTex,
Texture* cloudNormalMap,
float texOffset,
float radius,
const Eigen::Vector3f& semiAxes,
unsigned int textureRes,
int renderFlags,
const Eigen::Quaternionf& planetOrientation,

View File

@ -3363,14 +3363,19 @@ CelestiaGLProgram::setLightParameters(const LightingState& ls,
}
// Set GLSL shader constants for shadows from ellipsoid occluders; shadows from
// irregular objects are not handled yet.
/** Set GLSL shader constants for shadows from ellipsoid occluders; shadows from
* irregular objects are not handled yet.
* \param scaleFactors the scale factors of the object being shadowed
* \param orientation orientation of the object being shadowed
*/
void
CelestiaGLProgram::setEclipseShadowParameters(const LightingState& ls,
float planetRadius,
const Eigen::Quaternionf& planetOrientation)
const Vector3f& scaleFactors,
const Eigen::Quaternionf& orientation)
{
Matrix3f planetTransform = planetOrientation.toRotationMatrix();
// Compute the transformation from model to world coordinates
Transform3f rotation(orientation.conjugate());
Matrix4f modelToWorld = (rotation * Scaling3f(scaleFactors)).matrix();
for (unsigned int li = 0;
li < min(ls.nLights, MaxShaderLights);
@ -3380,6 +3385,13 @@ CelestiaGLProgram::setEclipseShadowParameters(const LightingState& ls,
{
unsigned int nShadows = min((size_t) MaxShaderEclipseShadows, ls.shadows[li]->size());
// The shadow bias matrix maps from
Matrix4f shadowBias;
shadowBias << 0.5f, 0.0f, 0.0f, 0.5f,
0.0f, 0.5f, 0.0f, 0.5f,
0.0f, 0.0f, 0.5f, 0.5f,
0.0f, 0.0f, 0.0f, 1.0f;
for (unsigned int i = 0; i < nShadows; i++)
{
EclipseShadow& shadow = ls.shadows[li]->at(i);
@ -3388,30 +3400,30 @@ CelestiaGLProgram::setEclipseShadowParameters(const LightingState& ls,
// Compute shadow parameters: max depth of at the center of the shadow
// (always 1 if an eclipse is total) and the linear falloff
// rate from the center to the outer endge of the penumbra.
float u = shadow.umbraRadius / shadow.penumbraRadius;
shadowParams.falloff = -shadow.maxDepth / std::max(0.001f, 1.0f - std::fabs(u));
float umbra = shadow.umbraRadius / shadow.penumbraRadius;
shadowParams.falloff = -shadow.maxDepth / std::max(0.001f, 1.0f - std::fabs(umbra));
shadowParams.maxDepth = shadow.maxDepth;
// Compute the transformation to use for generating texture
// coordinates from the object vertices.
Vector3f origin = planetTransform * shadow.origin;
Vector3f dir = planetTransform * shadow.direction;
float scale = planetRadius / shadow.penumbraRadius;
Quaternionf shadowRotation;
shadowRotation.setFromTwoVectors(Vector3f::UnitY(), dir);
Matrix3f m = shadowRotation.toRotationMatrix();
Vector3f sAxis = m * Vector3f::UnitX() * (0.5f * scale);
Vector3f tAxis = m * Vector3f::UnitZ() * (0.5f * scale);
// Compute a transformation that will rotate points in world space to shadow space
Vector3f u = shadow.direction.unitOrthogonal();
Vector3f v = u.cross(shadow.direction);
Matrix4f shadowRotation;
shadowRotation << u.transpose(), 0.0f,
v.transpose(), 0.0f,
shadow.direction.transpose(), 0.0f,
0.0f, 0.0f, 0.0f, 1.0f;
Vector4f texGenS;
Vector4f texGenT;
texGenS.start<3>() = sAxis;
texGenT.start<3>() = tAxis;
texGenS[3] = -origin.dot(sAxis) / planetRadius + 0.5f;
texGenT[3] = -origin.dot(tAxis) / planetRadius + 0.5f;
shadowParams.texGenS = texGenS;
shadowParams.texGenT = texGenT;
// Compose the world-to-shadow matrix
Matrix4f worldToShadow = shadowRotation *
Transform3f(Scaling3f(1.0f / shadow.penumbraRadius)).matrix() *
Transform3f(Translation3f(-shadow.origin)).matrix();
// Finally, multiply all the matrices together to get the mapping from
// object space to shadow map space.
Matrix4f m = shadowBias * worldToShadow * modelToWorld;
shadowParams.texGenS = m.row(0);
shadowParams.texGenT = m.row(1);
}
}
}

View File

@ -159,8 +159,8 @@ class CelestiaGLProgram
#endif
);
void setEclipseShadowParameters(const LightingState& ls,
float planetRadius,
const Eigen::Quaternionf& planetOrientation);
const Eigen::Vector3f& scale,
const Eigen::Quaternionf& orientation);
void setAtmosphereParameters(const Atmosphere& atmosphere,
float atmPlanetRadius,
float objRadius);