diff --git a/include/osgShadow/DebugShadowMap b/include/osgShadow/DebugShadowMap index 6ad7949f9..937798b5a 100644 --- a/include/osgShadow/DebugShadowMap +++ b/include/osgShadow/DebugShadowMap @@ -95,7 +95,7 @@ class OSGSHADOW_EXPORT DebugShadowMap : public ViewDependentShadowTechnique Texture used as ShadowMap - initialized by derived classes. But it has to be defined now since DebugShadowMap::ViewData methods use it */ - osg::ref_ptr< osg::Texture2D > _texture; + osg::ref_ptr< osg::Texture > _texture; /** Camera used to render ShadowMap - initialized by derived classes. But it has to be defined now since DebugShadowMap::ViewData methods use it @@ -171,6 +171,8 @@ class OSGSHADOW_EXPORT DebugShadowMap : public ViewDependentShadowTechnique ( const osg::Camera * viewCam, const osg::Camera * shadowCam, const ConvexPolyhedron * hull ); + + void dump( const char * filename = "DebugShadowDump.osg" ); }; META_ViewDependentShadowTechniqueData( ThisClass, ViewData ) diff --git a/src/osgShadow/ConvexPolyhedron.cpp b/src/osgShadow/ConvexPolyhedron.cpp index bc5d49402..a6cf2e966 100644 --- a/src/osgShadow/ConvexPolyhedron.cpp +++ b/src/osgShadow/ConvexPolyhedron.cpp @@ -1753,7 +1753,7 @@ osg::Geometry* ConvexPolyhedron::buildGeometry( const osg::Vec4d& colorOutline, osg::Vec4Array* colors = new osg::Vec4Array; geometry->setColorArray(colors); - geometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE); + geometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET); for(Faces::const_iterator itr = _faces.begin(); itr != _faces.end(); diff --git a/src/osgShadow/DebugShadowMap.cpp b/src/osgShadow/DebugShadowMap.cpp index 89529a33b..a6e0785f3 100644 --- a/src/osgShadow/DebugShadowMap.cpp +++ b/src/osgShadow/DebugShadowMap.cpp @@ -13,10 +13,11 @@ * ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski * Thanks to to my company http://www.ai.com.pl for allowing me free this work. */ - +#include #include #include #include +#include #include #include #include @@ -415,7 +416,7 @@ class DebugShadowMap::DrawableDrawWithDepthShadowComparisonOffCallback: public osg::Drawable::DrawCallback { public: - DrawableDrawWithDepthShadowComparisonOffCallback( osg::Texture2D *pTex ) + DrawableDrawWithDepthShadowComparisonOffCallback( osg::Texture *pTex ) : _pTexture( pTex ) { } @@ -426,18 +427,64 @@ public: ri.getState()->applyTextureAttribute( 0, _pTexture.get() ); // Turn off depth comparison mode - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE ); + glTexParameteri( _pTexture->getTextureTarget(), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE ); drawable->drawImplementation(ri); // Turn it back on - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, + glTexParameteri( _pTexture->getTextureTarget(), GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB ); } - osg::ref_ptr< osg::Texture2D > _pTexture; + osg::ref_ptr< osg::Texture > _pTexture; }; +void DebugShadowMap::ViewData::dump( const char * filename ) +{ + osg::ref_ptr< osg::Group > root = new osg::Group; + osgUtil::CullVisitor * cv = _cv.get(); + +#if 1 + osg::Group * cam = cv->getRenderStage()->getCamera(); + + for( unsigned int i = 0; i < cam->getNumChildren(); i++ ) + { + root->addChild( cam->getChild( i ) ); + } +#endif + + root->addChild( _st->getShadowedScene() ); + + osg::ref_ptr< osg::MatrixTransform > transform = new osg::MatrixTransform; + root->addChild( transform.get() ); + +// updateDebugGeometry( _viewCamera.get(), _camera.get() ); + + for( PolytopeGeometryMap::iterator itr = _polytopeGeometryMap.begin(); + itr != _polytopeGeometryMap.end(); + ++itr ) + { + PolytopeGeometry & pg = itr->second; + int i = 0; + { + + ConvexPolyhedron cp( pg._polytope ); + + pg._geometry[i] = cp.buildGeometry + ( pg._colorOutline, pg._colorInside, pg._geometry[i].get() ); + } + } + + for( unsigned int i = 0; i < _transform[0]->getNumChildren(); i++ ) + { + root->addChild( _transform[0]->getChild( i ) ); + } + + osgDB::writeNodeFile( *root, std::string( filename ) ); + + root->removeChildren( 0, root->getNumChildren() ); +} + void DebugShadowMap::ViewData::createDebugHUD( ) { _cameraDebugHUD = new osg::Camera; @@ -482,7 +529,7 @@ void DebugShadowMap::ViewData::createDebugHUD( ) osg::Vec3(0,_hudSize[1],0) ); osg::StateSet* stateset = _cameraDebugHUD->getOrCreateStateSet(); - stateset->setTextureAttributeAndModes(0,_texture.get(),osg::StateAttribute::ON ); + stateset->setTextureAttribute(0,_texture.get(),osg::StateAttribute::ON ); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); // stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); stateset->setAttributeAndModes diff --git a/src/osgShadow/MinimalShadowMap.cpp b/src/osgShadow/MinimalShadowMap.cpp index cf5874ed8..b0716c559 100644 --- a/src/osgShadow/MinimalShadowMap.cpp +++ b/src/osgShadow/MinimalShadowMap.cpp @@ -180,7 +180,13 @@ void MinimalShadowMap::ViewData::frameShadowCastingCamera osg::Matrix transform = osg::Matrix::inverse( mvp ); - osg::Vec3d normal = osg::Matrix::transform3x3( osg::Vec3d(0,0,-1), transform ); + // Code below was working only for directional lights ie when projection was ortho + // osg::Vec3d normal = osg::Matrix::transform3x3( osg::Vec3d( 0,0,-1)., transfrom ); + + // So I replaced it with safer code working with spot lights as well + osg::Vec3d normal = + osg::Vec3d(0,0,-1) * transform - osg::Vec3d(0,0,1) * transform; + normal.normalize(); _sceneReceivingShadowPolytope.extrude( normal * *_minLightMarginPtr ); @@ -255,7 +261,7 @@ void MinimalShadowMap::ViewData::cullShadowReceivingScene( ) _cv->clampProjectionMatrix( _clampedProjection, n, f ); } - // Aditionally clamp far plane if shadows are don't need to be cast as + // Aditionally clamp far plane if shadows don't need to be cast as // far as main projection far plane if( 0 < *_maxFarPlanePtr ) clampProjection( _clampedProjection, 0.f, *_maxFarPlanePtr ); diff --git a/src/osgShadow/StandardShadowMap.cpp b/src/osgShadow/StandardShadowMap.cpp index fe1f34307..3634215a3 100644 --- a/src/osgShadow/StandardShadowMap.cpp +++ b/src/osgShadow/StandardShadowMap.cpp @@ -104,190 +104,190 @@ StandardShadowMap::StandardShadowMap(): " // gl_TexCoord[0] 0 - can be subsituted with other index \n" " // gl_TextureMatrix[0] 0 - can be subsituted with other index \n" " // gl_MultiTexCoord0 0 - can be subsituted with other index \n" - " \n" + " \n" "const int NumEnabledLights = 1; \n" " \n" "void DynamicShadow( in vec4 ecPosition ); \n" - " \n" + " \n" "varying vec4 colorAmbientEmissive; \n" " \n" - "void SpotLight(in int i, \n" + "void SpotLight(in int i, \n" " in vec3 eye, \n" " in vec3 ecPosition3, \n" - " in vec3 normal, \n" + " in vec3 normal, \n" " inout vec4 ambient, \n" - " inout vec4 diffuse, \n" + " inout vec4 diffuse, \n" " inout vec4 specular) \n" - "{ \n" + "{ \n" " float nDotVP; // normal . light direction \n" - " float nDotHV; // normal . light half vector \n" - " float pf; // power factor \n" + " float nDotHV; // normal . light half vector \n" + " float pf; // power factor \n" " float spotDot; // cosine of angle between spotlight \n" " float spotAttenuation; // spotlight attenuation factor \n" - " float attenuation; // computed attenuation factor \n" + " float attenuation; // computed attenuation factor \n" " float d; // distance from surface to light source \n" " vec3 VP; // direction from surface to light position \n" " vec3 halfVector; // direction of maximum highlights \n" - " \n" - " // Compute vector from surface to light position \n" - " VP = vec3(gl_LightSource[i].position) - ecPosition3; \n" " \n" - " // Compute distance between surface and light position \n" + " // Compute vector from surface to light position \n" + " VP = vec3(gl_LightSource[i].position) - ecPosition3; \n" + " \n" + " // Compute distance between surface and light position \n" " d = length(VP); \n" - " \n" + " \n" " // Normalize the vector from surface to light position \n" " VP = normalize(VP); \n" - " \n" - " // Compute attenuation \n" - " attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + \n" - " gl_LightSource[i].linearAttenuation * d + \n" + " \n" + " // Compute attenuation \n" + " attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + \n" + " gl_LightSource[i].linearAttenuation * d + \n" " gl_LightSource[i].quadraticAttenuation *d*d); \n" - " \n" + " \n" " // See if point on surface is inside cone of illumination \n" " spotDot = dot(-VP, normalize(gl_LightSource[i].spotDirection)); \n" - " \n" - " if (spotDot < gl_LightSource[i].spotCosCutoff) \n" - " spotAttenuation = 0.0; // light adds no contribution \n" - " else \n" + " \n" + " if (spotDot < gl_LightSource[i].spotCosCutoff) \n" + " spotAttenuation = 0.0; // light adds no contribution \n" + " else \n" " spotAttenuation = pow(spotDot, gl_LightSource[i].spotExponent);\n" - " \n" - " // Combine the spotlight and distance attenuation. \n" + " \n" + " // Combine the spotlight and distance attenuation. \n" " attenuation *= spotAttenuation; \n" - " \n" - " halfVector = normalize(VP + eye); \n" - " \n" + " \n" + " halfVector = normalize(VP + eye); \n" + " \n" " nDotVP = max(0.0, dot(normal, VP)); \n" " nDotHV = max(0.0, dot(normal, halfVector)); \n" - " \n" + " \n" " if (nDotVP == 0.0) \n" - " pf = 0.0; \n" - " else \n" - " pf = pow(nDotHV, gl_FrontMaterial.shininess); \n" - " \n" - " ambient += gl_LightSource[i].ambient * attenuation; \n" - " diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; \n" - " specular += gl_LightSource[i].specular * pf * attenuation; \n" - "} \n" - " \n" - "void PointLight(in int i, \n" - " in vec3 eye, \n" - " in vec3 ecPosition3, \n" + " pf = 0.0; \n" + " else \n" + " pf = pow(nDotHV, gl_FrontMaterial.shininess); \n" + " \n" + " ambient += gl_LightSource[i].ambient * attenuation; \n" + " diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; \n" + " specular += gl_LightSource[i].specular * pf * attenuation; \n" + "} \n" + " \n" + "void PointLight(in int i, \n" + " in vec3 eye, \n" + " in vec3 ecPosition3, \n" " in vec3 normal, \n" " inout vec4 ambient, \n" " inout vec4 diffuse, \n" - " inout vec4 specular) \n" - "{ \n" - " float nDotVP; // normal . light direction \n" - " float nDotHV; // normal . light half vector \n" - " float pf; // power factor \n" - " float attenuation; // computed attenuation factor \n" + " inout vec4 specular) \n" + "{ \n" + " float nDotVP; // normal . light direction \n" + " float nDotHV; // normal . light half vector \n" + " float pf; // power factor \n" + " float attenuation; // computed attenuation factor \n" " float d; // distance from surface to light source \n" - " vec3 VP; // direction from surface to light position \n" - " vec3 halfVector; // direction of maximum highlights \n" - " \n" - " // Compute vector from surface to light position \n" - " VP = vec3(gl_LightSource[i].position) - ecPosition3; \n" - " \n" - " // Compute distance between surface and light position \n" + " vec3 VP; // direction from surface to light position \n" + " vec3 halfVector; // direction of maximum highlights \n" + " \n" + " // Compute vector from surface to light position \n" + " VP = vec3(gl_LightSource[i].position) - ecPosition3; \n" + " \n" + " // Compute distance between surface and light position \n" " d = length(VP); \n" - " \n" + " \n" " // Normalize the vector from surface to light position \n" " VP = normalize(VP); \n" - " \n" - " // Compute attenuation \n" - " attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + \n" - " gl_LightSource[i].linearAttenuation * d + \n" + " \n" + " // Compute attenuation \n" + " attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + \n" + " gl_LightSource[i].linearAttenuation * d + \n" " gl_LightSource[i].quadraticAttenuation * d*d);\n" - " \n" - " halfVector = normalize(VP + eye); \n" - " \n" + " \n" + " halfVector = normalize(VP + eye); \n" + " \n" " nDotVP = max(0.0, dot(normal, VP)); \n" " nDotHV = max(0.0, dot(normal, halfVector)); \n" - " \n" - " if (nDotVP == 0.0) \n" - " pf = 0.0; \n" - " else \n" + " \n" + " if (nDotVP == 0.0) \n" + " pf = 0.0; \n" + " else \n" " pf = pow(nDotHV, gl_FrontMaterial.shininess); \n" - " \n" + " \n" " ambient += gl_LightSource[i].ambient * attenuation; \n" - " diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; \n" - " specular += gl_LightSource[i].specular * pf * attenuation; \n" - "} \n" - " \n" + " diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; \n" + " specular += gl_LightSource[i].specular * pf * attenuation; \n" + "} \n" + " \n" "void DirectionalLight(in int i, \n" - " in vec3 normal, \n" - " inout vec4 ambient, \n" - " inout vec4 diffuse, \n" - " inout vec4 specular) \n" - "{ \n" - " float nDotVP; // normal . light direction \n" - " float nDotHV; // normal . light half vector \n" - " float pf; // power factor \n" - " \n" - " nDotVP = max(0.0, dot(normal, \n" - " normalize(vec3(gl_LightSource[i].position)))); \n" - " nDotHV = max(0.0, dot(normal, \n" + " in vec3 normal, \n" + " inout vec4 ambient, \n" + " inout vec4 diffuse, \n" + " inout vec4 specular) \n" + "{ \n" + " float nDotVP; // normal . light direction \n" + " float nDotHV; // normal . light half vector \n" + " float pf; // power factor \n" + " \n" + " nDotVP = max(0.0, dot(normal, \n" + " normalize(vec3(gl_LightSource[i].position)))); \n" + " nDotHV = max(0.0, dot(normal, \n" " vec3(gl_LightSource[i].halfVector))); \n" - " \n" + " \n" " if (nDotVP == 0.0) \n" - " pf = 0.0; \n" - " else \n" - " pf = pow(nDotHV, gl_FrontMaterial.shininess); \n" - " \n" + " pf = 0.0; \n" + " else \n" + " pf = pow(nDotHV, gl_FrontMaterial.shininess); \n" + " \n" " ambient += gl_LightSource[i].ambient; \n" - " diffuse += gl_LightSource[i].diffuse * nDotVP; \n" - " specular += gl_LightSource[i].specular * pf; \n" - "} \n" - " \n" - "void main( ) \n" - "{ \n" - " // Transform vertex to clip space \n" + " diffuse += gl_LightSource[i].diffuse * nDotVP; \n" + " specular += gl_LightSource[i].specular * pf; \n" + "} \n" + " \n" + "void main( ) \n" + "{ \n" + " // Transform vertex to clip space \n" " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n" " vec3 normal = normalize( gl_NormalMatrix * gl_Normal ); \n" - " \n" - " vec4 ecPos = gl_ModelViewMatrix * gl_Vertex; \n" + " \n" + " vec4 ecPos = gl_ModelViewMatrix * gl_Vertex; \n" " float ecLen = length( ecPos ); \n" " vec3 ecPosition3 = ecPos.xyz / ecPos.w; \n" - " \n" + " \n" " vec3 eye = vec3( 0.0, 0.0, 1.0 ); \n" " //vec3 eye = -normalize(ecPosition3); \n" " \n" " DynamicShadow( ecPos ); \n" - " \n" - " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; \n" - " \n" - " // Front Face lighting \n" - " \n" - " // Clear the light intensity accumulators \n" - " vec4 amb = vec4(0.0); \n" - " vec4 diff = vec4(0.0); \n" - " vec4 spec = vec4(0.0); \n" - " \n" - " // Loop through enabled lights, compute contribution from each \n" - " for (int i = 0; i < NumEnabledLights; i++) \n" - " { \n" + " \n" + " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; \n" + " \n" + " // Front Face lighting \n" + " \n" + " // Clear the light intensity accumulators \n" + " vec4 amb = vec4(0.0); \n" + " vec4 diff = vec4(0.0); \n" + " vec4 spec = vec4(0.0); \n" + " \n" + " // Loop through enabled lights, compute contribution from each \n" + " for (int i = 0; i < NumEnabledLights; i++) \n" + " { \n" " if (gl_LightSource[i].position.w == 0.0) \n" - " DirectionalLight(i, normal, amb, diff, spec); \n" + " DirectionalLight(i, normal, amb, diff, spec); \n" " else if (gl_LightSource[i].spotCutoff == 180.0) \n" - " PointLight(i, eye, ecPosition3, normal, amb, diff, spec); \n" - " else \n" - " SpotLight(i, eye, ecPosition3, normal, amb, diff, spec); \n" + " PointLight(i, eye, ecPosition3, normal, amb, diff, spec); \n" + " else \n" + " SpotLight(i, eye, ecPosition3, normal, amb, diff, spec); \n" " } \n" - " \n" - " colorAmbientEmissive = gl_FrontLightModelProduct.sceneColor + \n" - " amb * gl_FrontMaterial.ambient; \n" + " \n" + " colorAmbientEmissive = gl_FrontLightModelProduct.sceneColor + \n" + " amb * gl_FrontMaterial.ambient; \n" " \n" " gl_FrontColor = colorAmbientEmissive + \n" " diff * gl_FrontMaterial.diffuse; \n" - " \n" - " gl_FrontSecondaryColor = vec4(spec*gl_FrontMaterial.specular); \n" - " \n" - " gl_BackColor = gl_FrontColor; \n" + " \n" + " gl_FrontSecondaryColor = vec4(spec*gl_FrontMaterial.specular); \n" + " \n" + " gl_BackColor = gl_FrontColor; \n" " gl_BackSecondaryColor = gl_FrontSecondaryColor; \n" - " \n" - " gl_FogFragCoord = ecLen; \n" - "} \n" ); -} + " \n" + " gl_FogFragCoord = ecLen; \n" + "} \n" ); +} StandardShadowMap::StandardShadowMap(const StandardShadowMap& copy, const osg::CopyOp& copyop) : BaseClass(copy,copyop), @@ -426,19 +426,20 @@ void StandardShadowMap::ViewData::init( ThisClass *st, osgUtil::CullVisitor *cv _shadowTextureUnitPtr = &st->_shadowTextureUnit; _baseTextureUnitPtr = &st->_baseTextureUnit; - _texture = new osg::Texture2D; { // Setup shadow texture - _texture->setTextureSize( st->_textureSize.x(), st->_textureSize.y()); - _texture->setInternalFormat(GL_DEPTH_COMPONENT); - _texture->setShadowComparison(true); - _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE); - _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); - _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + osg::Texture2D * texture = new osg::Texture2D; + texture->setTextureSize( st->_textureSize.x(), st->_textureSize.y()); + texture->setInternalFormat(GL_DEPTH_COMPONENT); + texture->setShadowComparison(true); + texture->setShadowTextureMode(osg::Texture2D::LUMINANCE); + texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); // the shadow comparison should fail if object is outside the texture - _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER); - _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER); - _texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); + texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER); + texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER); + texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); + _texture = texture; } _camera = new osg::Camera; @@ -675,56 +676,41 @@ void StandardShadowMap::ViewData::aimShadowCastingCamera( osg::Vec3 up = lightUpVector; if( up.length2() <= 0 ) up.set( 0,1,0 ); - if( light->getSpotCutoff() < 180.0f) // spotlight, no need for bounding box + osg::Vec3d position(lightPos.x(), lightPos.y(), lightPos.z()); + if (lightPos[3]==0.0) // infinite directional light { - osg::Vec3d position(lightPos.x(), lightPos.y(), lightPos.z()); - float spotAngle = light->getSpotCutoff(); - - projection.makePerspective( spotAngle, 1.0, 0.1, 1000.0); - view.makeLookAt(position,position+lightDir,up); + // make an orthographic projection + // set the position far away along the light direction + position = bs.center() - lightDir * bs.radius() * 2; } - else - { - if (lightPos[3]!=0.0) // point light + + float centerDistance = (position-bs.center()).length(); + float znear = centerDistance-bs.radius(); + float zfar = centerDistance+bs.radius(); + float zNearRatio = 0.001f; + if (zneargetSpotCutoff() < 180.0f) // also needs znear zfar estimates { - osg::Vec3d position(lightPos.x(), lightPos.y(), lightPos.z()); - - float centerDistance = (position-bs.center()).length(); - - float znear = centerDistance-bs.radius(); - float zfar = centerDistance+bs.radius(); - float zNearRatio = 0.001f; - if (zneargetSpotCutoff(); + projection.makePerspective( spotAngle * 2, 1.0, znear, zfar); + view.makeLookAt(position,position+lightDir,up); + } else { // standard omnidirectional positional light float top = (bs.radius()/centerDistance)*znear; float right = top; projection.makeFrustum(-right,right,-top,top,znear,zfar); view.makeLookAt(position,bs.center(),up ); } - else // directional light - { - // make an orthographic projection - - // set the position far away along the light direction - float radius = bs.radius(); - osg::Vec3d position = bs.center() - lightDir * radius * 2; - - float centerDistance = (position-bs.center()).length(); - - float znear = centerDistance-radius; - float zfar = centerDistance+radius; - float zNearRatio = 0.001f; - if (znear