From 42a050e87c2b4b22f393f879d0320d5a01d98f31 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 1 Mar 2010 11:52:44 +0000 Subject: [PATCH] From Wojciech Lewandowski, "Here comes a list of small fixes in StandardShadowMap and derived classes affecting LispSM techniques. Changes made against SVN trunk. Fixes in StandardShadowMap.cpp & MinimalShadowMap.cpp were made for spotlight issues. There were cases when further located spotlights were not shadowing properly. Small tweak in DebugShadowMap & StandardShadowMap.cpp to not limit shadow maps to texture2D (which should also allow texture2D arrays and cube maps). I simply replaced ptr to osg::Texture2D with pointer to osg::Texture. Interpretation of this member could be now changed with change of shaders in derived classes. This may be useful for guys who override LispSM or MinimalBoundsShadowMaps techniques. Could be useful for implementation of PerspectiveCascadedShadowMaps technique for example. ConvexPolyhedron.cpp & DebugShadowMap.cpp contain debug HUD tweaks. Change in ConvexPolyhedron.cpp overcomes the regression problem with color per primitive binding which caused that shadow volume outlines stopped to draw. I simply changed PER_PRIMITIVE to PER_PRIMITIVE_SET and it works again. Other adition is dump method I added to DebugShadowMap which can be used in shadow debugging mode to dump current frame shadow volumes & scene to osg file. It could be then loaded into viewer and freely examined from different angles (which is difficult inside the application if shadow adopts to view and projection). " --- include/osgShadow/DebugShadowMap | 4 +- src/osgShadow/ConvexPolyhedron.cpp | 2 +- src/osgShadow/DebugShadowMap.cpp | 59 ++++- src/osgShadow/MinimalShadowMap.cpp | 10 +- src/osgShadow/StandardShadowMap.cpp | 334 +++++++++++++--------------- 5 files changed, 225 insertions(+), 184 deletions(-) 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