From Adrian Egli, further work on PSSM implementation.
This commit is contained in:
@@ -499,7 +499,14 @@ int main(int argc, char** argv)
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--mapcount", "ParallelSplitShadowMap texture count.");//ADEGLI
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--mapres", "ParallelSplitShadowMap texture resolution.");//ADEGLI
|
||||
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("--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
|
||||
arguments.getApplicationUsage()->addCommandLineOption("--CullFaceFront", "ParallelSplitShadowMap add a cull face: front.");//ADEGLI
|
||||
|
||||
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-1", "Use test model one.");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-2", "Use test model two.");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-3", "Use test model three.");
|
||||
@@ -625,13 +632,42 @@ int main(int argc, char** argv)
|
||||
while (arguments.read("--mapcount", mapcount));
|
||||
osg::ref_ptr<osgShadow::ParallelSplitShadowMap> pssm = new osgShadow::ParallelSplitShadowMap(NULL,mapcount);
|
||||
|
||||
unsigned int mapres = 1024;
|
||||
while (arguments.read("--mapres", mapres));
|
||||
pssm->setTextureResolution(mapres);
|
||||
int mapres = 1024;
|
||||
while (arguments.read("--mapres", mapres))
|
||||
pssm->setTextureResolution(mapres);
|
||||
|
||||
while (arguments.read("--debug-color")) { pssm->setDebugColorOn(); }
|
||||
|
||||
|
||||
int minNearSplit=0;
|
||||
while (arguments.read("--minNearSplit", minNearSplit))
|
||||
if ( minNearSplit > 0 ) {
|
||||
pssm->setMinNearDistanceForSplits(minNearSplit);
|
||||
std::cout << "ParallelSplitShadowMap : setMinNearDistanceForSplits(" << minNearSplit <<")" << std::endl;
|
||||
}
|
||||
|
||||
int maxfardist = 0;
|
||||
while (arguments.read("--maxFarDist", maxfardist))
|
||||
if ( maxfardist > 0 ) {
|
||||
pssm->setMaxFarDistance(maxfardist);
|
||||
std::cout << "ParallelSplitShadowMap : setMaxFarDistance(" << maxfardist<<")" << std::endl;
|
||||
}
|
||||
|
||||
double polyoffsetfactor = -0.02;
|
||||
double polyoffsetunit = 1.0;
|
||||
while (arguments.read("--PolyOffset-Factor", polyoffsetfactor));
|
||||
while (arguments.read("--PolyOffset-Unit", polyoffsetunit));
|
||||
pssm->setPolygonOffset(osg::Vec2(polyoffsetfactor,polyoffsetunit)); //ATI Radeon
|
||||
|
||||
if (arguments.read("--NVidea")){
|
||||
//pssm->setPolygonOffset(osg::Vec2(-0.02,1.0)); //ATI Radeon
|
||||
pssm->setPolygonOffset(osg::Vec2(10.0f,20.0f)); //NVidea
|
||||
}
|
||||
|
||||
if ( arguments.read("--CullFaceFront") ) {
|
||||
pssm->forceFrontCullFace();
|
||||
}
|
||||
|
||||
shadowedScene->setShadowTechnique(pssm.get());
|
||||
}
|
||||
else if (arguments.read("--ssm"))
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
#include <osg/Material>
|
||||
|
||||
#include <osgShadow/ShadowTechnique>
|
||||
|
||||
|
||||
namespace osgShadow {
|
||||
|
||||
class OSGSHADOW_EXPORT ParallelSplitShadowMap : public ShadowTechnique
|
||||
{
|
||||
public:
|
||||
@@ -56,6 +57,38 @@ class OSGSHADOW_EXPORT ParallelSplitShadowMap : public ShadowTechnique
|
||||
/** Set the texture resolution */
|
||||
inline void setTextureResolution(unsigned int resolution) { _resolution = resolution; }
|
||||
|
||||
/** Set the max far distance */
|
||||
inline void setMaxFarDistance(double farDist) { _setMaxFarDistance = farDist; _isSetMaxFarDistance = true; }
|
||||
|
||||
/** Force to add a osg::CullFace::FRONT state */
|
||||
inline void forceFrontCullFace() { _useFrontCullFace = true; }
|
||||
|
||||
/** Set min near distance for splits */
|
||||
inline void setMinNearDistanceForSplits(double nd){ _split_min_near_dist=nd; }
|
||||
|
||||
/** use linear split (default: linear) */
|
||||
inline void useLinearSplit(bool flag) { _linearSplit = flag;}
|
||||
|
||||
|
||||
/**
|
||||
light / |
|
||||
\ / |
|
||||
min near dist / |
|
||||
for splits / |
|
||||
\ / <20> |
|
||||
./ \ <20> |
|
||||
| \ <20> |
|
||||
| x <20> |
|
||||
| <20> |
|
||||
. | |
|
||||
\ <20> |
|
||||
\ <20> |
|
||||
\ |
|
||||
\ |
|
||||
\ |
|
||||
|
||||
.<- max far dist. ->.
|
||||
*/
|
||||
protected :
|
||||
|
||||
virtual ~ParallelSplitShadowMap() {}
|
||||
@@ -119,6 +152,15 @@ class OSGSHADOW_EXPORT ParallelSplitShadowMap : public ShadowTechnique
|
||||
|
||||
unsigned int _resolution;
|
||||
|
||||
double _setMaxFarDistance;
|
||||
bool _isSetMaxFarDistance;
|
||||
|
||||
bool _useFrontCullFace;
|
||||
|
||||
double _split_min_near_dist;
|
||||
|
||||
bool _linearSplit;
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
/* ParallelSplitShadowMap written by Adrian Egli */
|
||||
|
||||
#include <osgShadow/ParallelSplitShadowMap>
|
||||
|
||||
#include <osgShadow/ShadowedScene>
|
||||
#include <osg/Notify>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
@@ -32,9 +33,12 @@
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osg/Texture1D>
|
||||
|
||||
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
|
||||
|
||||
// split scheme
|
||||
#define TEXTURE_RESOLUTION 1024
|
||||
//#define ADAPTIVE_TEXTURE_RESOLUTION
|
||||
@@ -109,32 +113,32 @@ std::string ParallelSplitShadowMap::generateGLSL_FragmentShader_BaseTex(bool deb
|
||||
if ( _debug_color_in_GLSL ) {
|
||||
|
||||
|
||||
sstr << " float c0=0.5;" << std::endl;
|
||||
sstr << " float c1=0.5;" << std::endl;
|
||||
sstr << " float c2=0.5;" << std::endl;
|
||||
sstr << " float c0=0.0;" << std::endl;
|
||||
sstr << " float c1=0.0;" << std::endl;
|
||||
sstr << " float c2=0.0;" << std::endl;
|
||||
|
||||
sstr << " float sumTerm=0.0;" << std::endl;
|
||||
|
||||
for (unsigned int i=0;i<_number_of_splits;i++) {
|
||||
if ( i < 3 ) sstr << " c" << i << "=0.5+0.5*term" << i << ";" << std::endl;
|
||||
if ( i < 3 ) sstr << " c" << i << "=term" << i << ";" << std::endl;
|
||||
sstr << " sumTerm=sumTerm+term" << i << ";" << std::endl;
|
||||
}
|
||||
|
||||
sstr << " vec4 color = gl_Color*vec4(c0,c1,c2,1.0); " << std::endl;
|
||||
sstr << " vec4 color = gl_Color * ( 1.0 - sumTerm ) + (sumTerm)* gl_Color*vec4(c0,(1.0-c0)*c1,(1.0-c0)*(1.0-c1)*c2,1.0); " << std::endl;
|
||||
|
||||
sstr << " vec4 texcolor = vec4(1,1,1,1); " << std::endl;
|
||||
} else {
|
||||
sstr << " vec4 color = gl_Color; "<< std::endl;
|
||||
sstr << " vec4 texcolor = texture2D(baseTexture,gl_TexCoord[0].st); " << std::endl;
|
||||
}
|
||||
|
||||
|
||||
sstr << " vec4 texcolor = texture2D(baseTexture,gl_TexCoord[0].st); " << std::endl;
|
||||
|
||||
|
||||
sstr << " float enableBaseTextureFilter = enableBaseTexture*(1.0 - step(texcolor.x+texcolor.y+texcolor.z+texcolor.a,0.0)); " << std::endl; //18
|
||||
sstr << " vec4 colorTex = color*texcolor;" << std::endl;
|
||||
sstr << " vec4 colorTex = color*texcolor;" << std::endl;
|
||||
sstr << " gl_FragColor = (color*(1.0-enableBaseTextureFilter) + colorTex*enableBaseTextureFilter)*(1.0-0.30*v); "<< std::endl;
|
||||
|
||||
|
||||
|
||||
|
||||
sstr << "}"<< std::endl;
|
||||
|
||||
|
||||
@@ -159,7 +163,11 @@ ParallelSplitShadowMap::ParallelSplitShadowMap(osg::Geode** gr, int icountplanes
|
||||
_textureUnitOffset(1),
|
||||
_debug_color_in_GLSL(false),
|
||||
_user_polgyonOffset_set(false),
|
||||
_resolution(TEXTURE_RESOLUTION)
|
||||
_resolution(TEXTURE_RESOLUTION),
|
||||
_isSetMaxFarDistance(false),
|
||||
_useFrontCullFace(false),
|
||||
_split_min_near_dist(ZNEAR_MIN_FROM_LIGHT_SOURCE),
|
||||
_linearSplit(LINEAR_SPLIT)
|
||||
{
|
||||
_displayTexturesGroupingNode = gr;
|
||||
_number_of_splits = icountplanes;
|
||||
@@ -171,7 +179,17 @@ ParallelSplitShadowMap::ParallelSplitShadowMap(osg::Geode** gr, int icountplanes
|
||||
ParallelSplitShadowMap::ParallelSplitShadowMap(const ParallelSplitShadowMap& copy, const osg::CopyOp& copyop):
|
||||
ShadowTechnique(copy,copyop),
|
||||
_textureUnitOffset(copy._textureUnitOffset),
|
||||
_number_of_splits(copy._number_of_splits)
|
||||
_debug_color_in_GLSL(copy._debug_color_in_GLSL),
|
||||
_user_polgyonOffset_set(copy._user_polgyonOffset_set),
|
||||
_resolution(copy._resolution),
|
||||
_isSetMaxFarDistance(copy._isSetMaxFarDistance),
|
||||
_useFrontCullFace(copy._useFrontCullFace),
|
||||
_split_min_near_dist(copy._split_min_near_dist),
|
||||
_linearSplit(copy._linearSplit),
|
||||
_number_of_splits(copy._number_of_splits),
|
||||
_polgyonOffset(copy._polgyonOffset),
|
||||
_setMaxFarDistance(copy._setMaxFarDistance)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
@@ -243,7 +261,7 @@ void ParallelSplitShadowMap::init(){
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
pssmShadowSplitTexture._camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
pssmShadowSplitTexture._camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
|
||||
// set viewport
|
||||
pssmShadowSplitTexture._camera->setViewport(0,0,pssmShadowSplitTexture._resolution,pssmShadowSplitTexture._resolution);
|
||||
@@ -273,6 +291,13 @@ void ParallelSplitShadowMap::init(){
|
||||
stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
}
|
||||
|
||||
if ( _useFrontCullFace ) {
|
||||
osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace;
|
||||
cull_face->setMode(osg::CullFace::FRONT);
|
||||
stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
}
|
||||
}
|
||||
// set up stateset and append texture, texGen ,...
|
||||
{
|
||||
@@ -304,7 +329,7 @@ void ParallelSplitShadowMap::init(){
|
||||
osg::Uniform* shadowTextureSampler = new osg::Uniform(strST.str().c_str(),(int)(pssmShadowSplitTexture._textureUnit));
|
||||
pssmShadowSplitTexture._stateset->addUniform(shadowTextureSampler);
|
||||
|
||||
//TODO: NOT YET SUPPORTED in the current version of the shader
|
||||
//TODO: NOT YET SUPPORTED in the current version of the shader
|
||||
//std::stringstream strAB; strAB << "ambientBias" << (pssmShadowSplitTexture._textureUnit-1);
|
||||
//osg::Uniform* ambientBias = new osg::Uniform(strAB.str().c_str(),pssmShadowSplitTexture._ambientBias);
|
||||
//pssmShadowSplitTexture._stateset->addUniform(ambientBias);
|
||||
@@ -330,11 +355,11 @@ void ParallelSplitShadowMap::init(){
|
||||
|
||||
{
|
||||
// fake texture for baseTexture, add a fake texture
|
||||
// we support by default at least one texture layer
|
||||
// without this fake texture we can not support
|
||||
// textured and not textured scene
|
||||
// we support by default at least one texture layer
|
||||
// without this fake texture we can not support
|
||||
// textured and not textured scene
|
||||
|
||||
// TODO: at the moment the PSSM supports just one texture layer in the GLSL shader, multitexture are
|
||||
// TODO: at the moment the PSSM supports just one texture layer in the GLSL shader, multitexture are
|
||||
// not yet supported !
|
||||
|
||||
osg::Image* image = new osg::Image;
|
||||
@@ -641,13 +666,18 @@ void ParallelSplitShadowMap::calculateFrustumCorners(
|
||||
double fovy,aspectRatio,camNear,camFar;
|
||||
pssmShadowSplitTexture._cameraProj.getPerspective(fovy,aspectRatio,camNear,camFar);
|
||||
|
||||
|
||||
|
||||
if ( _isSetMaxFarDistance ) {
|
||||
if ( camNear + _setMaxFarDistance < camFar) camFar = camNear + _setMaxFarDistance;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/// CALCULATE SPLIT
|
||||
double maxFar = camFar;
|
||||
double minNear = camNear;
|
||||
double camNearFar_Dist = maxFar - camNear;
|
||||
bool linear = LINEAR_SPLIT;
|
||||
if ( linear ) {
|
||||
if ( _linearSplit ) {
|
||||
camFar = camNear + (camNearFar_Dist) * ((double)(pssmShadowSplitTexture._splitID+1))/((double)(_number_of_splits));
|
||||
camNear = camNear + (camNearFar_Dist) * ((double)(pssmShadowSplitTexture._splitID))/((double)(_number_of_splits));
|
||||
} else {
|
||||
@@ -686,13 +716,17 @@ void ParallelSplitShadowMap::calculateFrustumCorners(
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/// TRANSFORM frustum corners (Optimized for Orthogonal)
|
||||
osg::Matrixf projMat;
|
||||
projMat.makePerspective(fovy,aspectRatio,camNear,camFar);
|
||||
|
||||
osg::Matrixf projViewMat = pssmShadowSplitTexture._cameraView*projMat;
|
||||
osg::Matrixf invProjViewMat;
|
||||
|
||||
osg::Matrixf projMat;
|
||||
projMat.makePerspective(fovy,aspectRatio,camNear,camFar);
|
||||
osg::Matrixf projViewMat(pssmShadowSplitTexture._cameraView*projMat);
|
||||
invProjViewMat.invert(projViewMat);
|
||||
|
||||
|
||||
|
||||
|
||||
//transform frustum vertices to world space
|
||||
frustumCorners[0] = const_pointFarBR * invProjViewMat;
|
||||
frustumCorners[1] = const_pointNearBR* invProjViewMat;
|
||||
@@ -709,7 +743,7 @@ void ParallelSplitShadowMap::calculateFrustumCorners(
|
||||
//
|
||||
// compute directional light inital postion;
|
||||
void ParallelSplitShadowMap::calculateLightInitalPosition(PSSMShadowSplitTexture &pssmShadowSplitTexture,osg::Vec3d *frustumCorners){
|
||||
pssmShadowSplitTexture._frustumSplitCenter = frustumCorners[0];
|
||||
pssmShadowSplitTexture._frustumSplitCenter = frustumCorners[0];
|
||||
for(int i=1;i<8;i++) {
|
||||
pssmShadowSplitTexture._frustumSplitCenter +=frustumCorners[i];
|
||||
}
|
||||
@@ -732,7 +766,7 @@ void ParallelSplitShadowMap::calculateLightNearFarFormFrustum(
|
||||
// force zNear > 0.0
|
||||
// set 2.0m distance to the nearest point
|
||||
int count = 0;
|
||||
while (zNear <= ZNEAR_MIN_FROM_LIGHT_SOURCE && count++ < 10) {
|
||||
while (zNear <= _split_min_near_dist && count++ < 10) {
|
||||
zNear= DBL_MAX;
|
||||
zFar =-DBL_MAX;
|
||||
for(int i=0;i<8;i++) {
|
||||
@@ -741,8 +775,8 @@ void ParallelSplitShadowMap::calculateLightNearFarFormFrustum(
|
||||
if ( zFar < dist_z_from_light ) zFar = dist_z_from_light;
|
||||
}
|
||||
|
||||
if ( zNear <= ZNEAR_MIN_FROM_LIGHT_SOURCE ){
|
||||
osg::Vec3 dUpdate = - pssmShadowSplitTexture._lightDirection*(fabs(zNear)+ZNEAR_MIN_FROM_LIGHT_SOURCE);
|
||||
if ( zNear <= _split_min_near_dist ){
|
||||
osg::Vec3 dUpdate = - pssmShadowSplitTexture._lightDirection*(fabs(zNear)+_split_min_near_dist);
|
||||
pssmShadowSplitTexture._lightCameraSource = pssmShadowSplitTexture._lightCameraSource + dUpdate;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user