Skip to content

Commit

Permalink
From Adrian Egli, "update the PSSM, i did some bug fixes and added ne…
Browse files Browse the repository at this point in the history
…w features to move the camera virtual against the view direction by applaying a simple distance factor (a), which is calculated camera eye - camera center distance. and we can move the "light camera" against the light direction (b).

(a) some objects behind the camera can cast shadow
(b) object aboive the camera can cast shadow

then i fixed the shadow map orientation, now screen x coordinate alinged which improve the quality"
  • Loading branch information
robertosfield committed Sep 27, 2007
1 parent 63789c8 commit 6df0110
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 68 deletions.
63 changes: 37 additions & 26 deletions examples/osgshadow/osgshadow.cpp
Expand Up @@ -501,6 +501,7 @@ int main(int argc, char** argv)
arguments.getApplicationUsage()->addCommandLineOption("--debug-color", "ParallelSplitShadowMap display debugging color (only the first 3 maps are color r=0,g=1,b=2.");//ADEGLI
arguments.getApplicationUsage()->addCommandLineOption("--minNearSplit", "ParallelSplitShadowMap shadow map near offset.");//ADEGLI
arguments.getApplicationUsage()->addCommandLineOption("--maxFarDist", "ParallelSplitShadowMap max far distance to shadow.");//ADEGLI
arguments.getApplicationUsage()->addCommandLineOption("--moveVCamFactor", "ParallelSplitShadowMap move the virtual frustum behind the real camera, (also back ground object can cast shadow).");//ADEGLI
arguments.getApplicationUsage()->addCommandLineOption("--NVidea", "ParallelSplitShadowMap set default PolygonOffset for NVidea.");//ADEGLI
arguments.getApplicationUsage()->addCommandLineOption("--PolyOffset-Factor", "ParallelSplitShadowMap set PolygonOffset factor.");//ADEGLI
arguments.getApplicationUsage()->addCommandLineOption("--PolyOffset-Unit", "ParallelSplitShadowMap set PolygonOffset unit.");//ADEGLI
Expand Down Expand Up @@ -576,31 +577,6 @@ int main(int argc, char** argv)
// add stats
viewer.addEventHandler( new osgViewer::StatsHandler() );

osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
if (model.valid())
{
model->setNodeMask(CastsShadowTraversalMask | ReceivesShadowTraversalMask);
}
else
{
model = createTestModel(arguments);
}

// get the bounds of the model.
osg::ComputeBoundsVisitor cbbv;
model->accept(cbbv);
osg::BoundingBox bb = cbbv.getBoundingBox();

osg::Vec4 lightpos;

if (postionalLight)
{
lightpos.set(bb.center().x(), bb.center().y(), bb.zMax() + bb.radius() ,1.0f);
}
else
{
lightpos.set(0.5f,0.25f,0.8f,0.0f);
}


osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;
Expand Down Expand Up @@ -653,6 +629,14 @@ int main(int argc, char** argv)
std::cout << "ParallelSplitShadowMap : setMaxFarDistance(" << maxfardist<<")" << std::endl;
}

int moveVCamFactor = 0;
while (arguments.read("--moveVCamFactor", moveVCamFactor))
if ( maxfardist > 0 ) {
pssm->setMoveVCamBehindRCamFactor(moveVCamFactor);
std::cout << "ParallelSplitShadowMap : setMoveVCamBehindRCamFactor(" << moveVCamFactor<<")" << std::endl;
}


double polyoffsetfactor = -0.02;
double polyoffsetunit = 1.0;
while (arguments.read("--PolyOffset-Factor", polyoffsetfactor));
Expand Down Expand Up @@ -680,6 +664,33 @@ int main(int argc, char** argv)
osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap;
shadowedScene->setShadowTechnique(sm.get());
}

osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
if (model.valid())
{
model->setNodeMask(CastsShadowTraversalMask | ReceivesShadowTraversalMask);
}
else
{
model = createTestModel(arguments);
}

// get the bounds of the model.
osg::ComputeBoundsVisitor cbbv;
model->accept(cbbv);
osg::BoundingBox bb = cbbv.getBoundingBox();

osg::Vec4 lightpos;

if (postionalLight)
{
lightpos.set(bb.center().x(), bb.center().y(), bb.zMax() + bb.radius() ,1.0f);
}
else
{
lightpos.set(0.5f,0.25f,0.8f,0.0f);
}


if ( arguments.read("--base"))
{
Expand Down Expand Up @@ -712,7 +723,7 @@ int main(int argc, char** argv)
ls->getLight()->setAmbient(osg::Vec4(0.2,0.2,0.2,1.0));
ls->getLight()->setDiffuse(osg::Vec4(0.8,0.8,0.8,1.0));
}

shadowedScene->addChild(model.get());
shadowedScene->addChild(ls.get());

Expand Down
9 changes: 7 additions & 2 deletions include/osgShadow/ParallelSplitShadowMap
Expand Up @@ -60,7 +60,10 @@ class OSGSHADOW_EXPORT ParallelSplitShadowMap : public ShadowTechnique
/** Set the max far distance */
inline void setMaxFarDistance(double farDist) { _setMaxFarDistance = farDist; _isSetMaxFarDistance = true; }

/** Force to add a osg::CullFace::FRONT state */
/** Set the factor for moving the virtual camera behind the real camera*/
inline void setMoveVCamBehindRCamFactor(double distFactor ) { _move_vcam_behind_rcam_factor = distFactor; }

/** Force to add a cull face front */
inline void forceFrontCullFace() { _useFrontCullFace = true; }

/** Set min near distance for splits */
Expand Down Expand Up @@ -158,7 +161,9 @@ class OSGSHADOW_EXPORT ParallelSplitShadowMap : public ShadowTechnique
bool _useFrontCullFace;

double _split_min_near_dist;


double _move_vcam_behind_rcam_factor;

bool _linearSplit;

};
Expand Down
94 changes: 54 additions & 40 deletions src/osgShadow/ParallelSplitShadowMap.cpp
Expand Up @@ -48,6 +48,7 @@ using namespace osgShadow;


#define ZNEAR_MIN_FROM_LIGHT_SOURCE 2.0
#define MOVE_VIRTUAL_CAMERA_BEHIND_REAL_CAMERA_FACTOR 0.0

//#define SHOW_SHADOW_TEXTURE_DEBUG // DEPTH instead of color for debug information texture display in a rectangle

Expand Down Expand Up @@ -167,7 +168,8 @@ ParallelSplitShadowMap::ParallelSplitShadowMap(osg::Geode** gr, int icountplanes
_isSetMaxFarDistance(false),
_useFrontCullFace(false),
_split_min_near_dist(ZNEAR_MIN_FROM_LIGHT_SOURCE),
_linearSplit(LINEAR_SPLIT)
_linearSplit(LINEAR_SPLIT),
_move_vcam_behind_rcam_factor(MOVE_VIRTUAL_CAMERA_BEHIND_REAL_CAMERA_FACTOR)
{
_displayTexturesGroupingNode = gr;
_number_of_splits = icountplanes;
Expand All @@ -188,8 +190,8 @@ ParallelSplitShadowMap::ParallelSplitShadowMap(const ParallelSplitShadowMap& cop
_linearSplit(copy._linearSplit),
_number_of_splits(copy._number_of_splits),
_polgyonOffset(copy._polgyonOffset),
_setMaxFarDistance(copy._setMaxFarDistance)

_setMaxFarDistance(copy._setMaxFarDistance),
_move_vcam_behind_rcam_factor(copy._move_vcam_behind_rcam_factor)
{
}

Expand Down Expand Up @@ -668,8 +670,18 @@ void ParallelSplitShadowMap::calculateFrustumCorners(



osg::Matrixf viewMat;
osg::Vec3d camEye,camCenter,camUp;
pssmShadowSplitTexture._cameraView.getLookAt(camEye,camCenter,camUp);
osg::Vec3d viewDir = camCenter - camEye;
//viewDir.normalize();
camEye = camEye - viewDir * _move_vcam_behind_rcam_factor;
camFar += _move_vcam_behind_rcam_factor * viewDir.length();
viewMat.makeLookAt(camEye,camCenter,camUp);


if ( _isSetMaxFarDistance ) {
if ( camNear + _setMaxFarDistance < camFar) camFar = camNear + _setMaxFarDistance;
if (_setMaxFarDistance < camFar) camFar = _setMaxFarDistance;
}

//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -716,16 +728,14 @@ void ParallelSplitShadowMap::calculateFrustumCorners(

//////////////////////////////////////////////////////////////////////////
/// TRANSFORM frustum corners (Optimized for Orthogonal)

osg::Matrixf invProjViewMat;


osg::Matrixf projMat;
projMat.makePerspective(fovy,aspectRatio,camNear,camFar);
osg::Matrixf projViewMat(pssmShadowSplitTexture._cameraView*projMat);
invProjViewMat.invert(projViewMat);



osg::Matrixf projViewMat(viewMat*projMat);
invProjViewMat.invert(projViewMat);

//transform frustum vertices to world space
frustumCorners[0] = const_pointFarBR * invProjViewMat;
Expand Down Expand Up @@ -764,45 +774,56 @@ void ParallelSplitShadowMap::calculateLightNearFarFormFrustum(


// force zNear > 0.0
// set 2.0m distance to the nearest point
// set _split_min_near_dist(2.0m) distance to the nearest point
int count = 0;
while (zNear <= _split_min_near_dist && count++ < 10) {

// init zNear, zFar
zNear= DBL_MAX;
zFar =-DBL_MAX;

// calculate zNear, zFar
for(int i=0;i<8;i++) {
double dist_z_from_light = pssmShadowSplitTexture._lightDirection*(frustumCorners[i] - pssmShadowSplitTexture._lightCameraSource);
if ( zNear > dist_z_from_light ) zNear = dist_z_from_light;
if ( zFar < dist_z_from_light ) zFar = dist_z_from_light;
}
}

// update if zNear too small
if ( zNear <= _split_min_near_dist ){
osg::Vec3 dUpdate = - pssmShadowSplitTexture._lightDirection*(fabs(zNear)+_split_min_near_dist);
pssmShadowSplitTexture._lightCameraSource = pssmShadowSplitTexture._lightCameraSource + dUpdate;
}

}


pssmShadowSplitTexture._lightCameraTarget = pssmShadowSplitTexture._lightCameraSource + pssmShadowSplitTexture._lightDirection*zFar;
pssmShadowSplitTexture._lightNear = zNear;
pssmShadowSplitTexture._lightCameraTarget = pssmShadowSplitTexture._frustumSplitCenter;//pssmShadowSplitTexture._lightCameraSource + pssmShadowSplitTexture._lightDirection;//*zFar;
pssmShadowSplitTexture._lightNear = 0.1;//zNear;
pssmShadowSplitTexture._lightFar = zFar;
}

void ParallelSplitShadowMap::calculateLightViewProjectionFormFrustum(PSSMShadowSplitTexture &pssmShadowSplitTexture,osg::Vec3d *frustumCorners) {
//////////////////////////////////////////////////////////////////////////

// light dir
osg::Vec3d lightDir = pssmShadowSplitTexture._lightDirection;

osg::Vec3d up(0,1,0);
// calculate top, left
osg::Vec3d top(0,0,1);
osg::Vec3d left;
osg::Vec3d top;

left = up ^ lightDir;
top = lightDir ^ left;


double maxLeft,maxTop;
osg::Vec3d lightDir = pssmShadowSplitTexture._lightDirection;
lightDir.normalize();

osg::Vec3d camEye,camCenter,camUp;
pssmShadowSplitTexture._cameraView.getLookAt(camEye,camCenter,camUp);

osg::Vec3d viewDir(camCenter-camEye);
viewDir.normalize();

osg::Vec3d camLeft = camUp ^ viewDir;
camLeft.normalize();

top = lightDir ^ camLeft;
left = top ^ lightDir;

double maxLeft,maxTop;
double minLeft,minTop;

osg::Vec3d fCenter = pssmShadowSplitTexture._frustumSplitCenter;
Expand All @@ -811,32 +832,25 @@ void ParallelSplitShadowMap::calculateLightViewProjectionFormFrustum(PSSMShadowS
minLeft = minTop = DBL_MAX;
for(int i = 0; i < 8; i++)
{
osg::Vec3d diffCorner = fCenter - frustumCorners[i];
double lLeft = (diffCorner*left) * 1.5; // scale, removes edges problem, faster for calculation
double lTop = (diffCorner*top) * 1.5; // scale, removes edges problem, faster for calculation
osg::Vec3d diffCorner = pssmShadowSplitTexture._frustumSplitCenter - frustumCorners[i];
double lLeft = (diffCorner*left) * 1.41425;
double lTop = (diffCorner*top) * 1.41425;

if ( lLeft > maxLeft ) maxLeft = lLeft;
if ( lTop > maxTop ) maxTop = lTop ;
if ( lTop > maxTop ) maxTop = lTop;

if ( lLeft < minLeft ) minLeft = lLeft;
if ( lTop < minTop ) minTop = lTop ;
}
if ( lTop < minTop ) minTop = lTop;
}

osg::Matrixd lightView;
lightView.makeLookAt(pssmShadowSplitTexture._lightCameraSource,pssmShadowSplitTexture._lightCameraTarget,up);
lightView.makeLookAt(pssmShadowSplitTexture._lightCameraSource,pssmShadowSplitTexture._lightCameraTarget,top);
osg::Matrixd lightProj;

double zNear = pssmShadowSplitTexture._lightNear;
double zFar = pssmShadowSplitTexture._lightFar;

lightProj.makeOrtho(minLeft,maxLeft,minTop,maxTop,zNear,zFar);

lightProj.makeOrtho(minLeft,maxLeft,minTop,maxTop,pssmShadowSplitTexture._lightNear,pssmShadowSplitTexture._lightFar);

pssmShadowSplitTexture._camera->setViewMatrix(lightView);
pssmShadowSplitTexture._camera->setProjectionMatrix(lightProj);



}


Expand Down

0 comments on commit 6df0110

Please sign in to comment.