Show
Ignore:
Timestamp:
10/02/07 23:45:09 (7 years ago)
Author:
robert
Message:

From Mihair Radu, "Most of the additions are small utility methods:
- set the resolution of the shadow map; it calls dirty() to
re-initialize at next update
- keep a list of Shader objects to use instead of the default ones, if
the list is empty, the default shaders are used
- explicitly create the Uniform variables, so that subsequent additions
that require more Uniforms can put them in a central place
- set a Light or LightSource? to use explicitly for shadow casting,
allows multiple lights in the scene, with one casting shadows

There are two additions that do not ( yet ) function correctly, but in
the present usage they do not interfere with the regular usage of the
techique:
- support for using spotlights, it's using Light.spotCutoff to determine
if it's a spot-light and not point-light,

there is an error in the setup of either the shadow camera or the

texgen, most likely due to the direction of the spotlight, since the
position is being used just like in point or directional lights.
- creation of a debugHUD

the hud is created properly, ( the example included shows it ), but

it displays only white, there has been some discussion of displaying the
shadow map, but I could not find it, the addition of a simple fragment
shader with the appropriate color transform should get this going."

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/src/osgShadow/ShadowMap.cpp

    r7412 r7539  
    2222using namespace osgShadow; 
    2323 
    24  
    25 ////////////////////////////////////////////////////////////////// 
    26 // fragment shader 
    27 // 
    28 static const char fragmentShaderSource_noBaseTexture[] =  
    29     "uniform sampler2DShadow shadowTexture; \n" 
    30     "uniform vec2 ambientBias; \n" 
    31     "\n" 
    32     "void main(void) \n" 
    33     "{ \n" 
    34     "    gl_FragColor = gl_Color * (ambientBias.x + shadow2DProj( shadowTexture, gl_TexCoord[0] ) * ambientBias.y); \n" 
    35     "}\n"; 
    36  
    37 ////////////////////////////////////////////////////////////////// 
    38 // fragment shader 
    39 // 
    40 static const char fragmentShaderSource_withBaseTexture[] =  
    41     "uniform sampler2D baseTexture; \n" 
    42     "uniform sampler2DShadow shadowTexture; \n" 
    43     "uniform vec2 ambientBias; \n" 
    44     "\n" 
    45     "void main(void) \n" 
    46     "{ \n" 
    47     "    vec4 color = gl_Color * texture2D( baseTexture, gl_TexCoord[0].xy ); \n" 
    48     "    gl_FragColor = color * (ambientBias.x + shadow2DProj( shadowTexture, gl_TexCoord[1] ) * ambientBias.y); \n" 
    49     "}\n"; 
    50  
    51 ShadowMap::ShadowMap(): 
    52     _textureUnit(1), 
    53     _ambientBias(0.3f,1.2f) 
    54 { 
    55 } 
    56  
    57 ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop): 
     24#include <iostream> 
     25//for debug 
     26#include <osg/LightSource> 
     27#include <osg/PolygonMode> 
     28#include <osg/Geometry> 
     29#include <osgDB/ReadFile> 
     30#include <osgText/Text> 
     31 
     32    ////////////////////////////////////////////////////////////////// 
     33    // fragment shader 
     34    // 
     35    static const char fragmentShaderSource_noBaseTexture[] =  
     36        "uniform sampler2DShadow osgShadow_shadowTexture; \n" 
     37        "uniform vec2 osgShadow_ambientBias; \n" 
     38        "\n" 
     39        "void main(void) \n" 
     40        "{ \n" 
     41        "    gl_FragColor = gl_Color * (osgShadow_ambientBias.x + shadow2DProj( osgShadow_shadowTexture, gl_TexCoord[0] ) * osgShadow_ambientBias.y); \n" 
     42        "}\n"; 
     43 
     44    ////////////////////////////////////////////////////////////////// 
     45    // fragment shader 
     46    // 
     47    static const char fragmentShaderSource_withBaseTexture[] =  
     48        "uniform sampler2D osgShadow_baseTexture; \n" 
     49        "uniform sampler2DShadow osgShadow_shadowTexture; \n" 
     50        "uniform vec2 osgShadow_ambientBias; \n" 
     51        "\n" 
     52        "void main(void) \n" 
     53        "{ \n" 
     54        "    vec4 color = gl_Color * texture2D( osgShadow_baseTexture, gl_TexCoord[0].xy ); \n" 
     55        "    gl_FragColor = color * (osgShadow_ambientBias.x + shadow2DProj( osgShadow_shadowTexture, gl_TexCoord[1] ) * osgShadow_ambientBias.y); \n" 
     56        "}\n"; 
     57 
     58    ShadowMap::ShadowMap(): 
     59    _baseTextureUnit(0), 
     60        _shadowTextureUnit(1), 
     61        _ambientBias(0.3f,1.2f), 
     62        _textureSize(1024,1024) 
     63    { 
     64    } 
     65 
     66    ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop): 
    5867    ShadowTechnique(copy,copyop), 
    59     _textureUnit(copy._textureUnit), 
    60     _ambientBias(copy._ambientBias) 
    61 { 
    62 } 
    63  
    64 void ShadowMap::setTextureUnit(unsigned int unit) 
    65 { 
    66     _textureUnit = unit; 
    67 } 
    68  
    69 void ShadowMap::setAmbientBias(const osg::Vec2& ambientBias) 
    70 { 
    71     _ambientBias = ambientBias; 
    72 } 
    73  
    74 void ShadowMap::init() 
    75 { 
    76     if (!_shadowedScene) return; 
    77  
    78     unsigned int tex_width = 1024; 
    79     unsigned int tex_height = 1024; 
    80      
    81     _texture = new osg::Texture2D; 
    82     _texture->setTextureSize(tex_width, tex_height); 
    83     _texture->setInternalFormat(GL_DEPTH_COMPONENT); 
    84     _texture->setShadowComparison(true); 
    85     _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE); 
    86     _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
    87     _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); 
    88     _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE); 
    89     _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE); 
    90  
    91     // set up the render to texture camera. 
    92     { 
    93         // create the camera 
    94         _camera = new osg::Camera; 
    95  
    96         _camera->setCullCallback(new CameraCullCallback(this)); 
    97  
    98         _camera->setClearMask(GL_DEPTH_BUFFER_BIT); 
    99         //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
    100         _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
    101         _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); 
    102  
    103         // set viewport 
    104         _camera->setViewport(0,0,tex_width,tex_height); 
    105  
    106         // set the camera to render before the main camera. 
    107         _camera->setRenderOrder(osg::Camera::PRE_RENDER); 
    108  
    109         // tell the camera to use OpenGL frame buffer object where supported. 
    110         _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 
    111         //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW); 
    112  
    113         // attach the texture and use it as the color buffer. 
    114         _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get()); 
    115  
    116         osg::StateSet* stateset = _camera->getOrCreateStateSet(); 
    117  
    118         float factor = 0.0f; 
    119         float units = 1.0f; 
    120  
    121         osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset; 
    122         polygon_offset->setFactor(factor); 
    123         polygon_offset->setUnits(units); 
    124         stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    125         stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    126  
    127         osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace; 
    128         cull_face->setMode(osg::CullFace::FRONT); 
    129         stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    130         stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     68        _baseTextureUnit(copy._baseTextureUnit), 
     69        _shadowTextureUnit(copy._shadowTextureUnit), 
     70        _ambientBias(copy._ambientBias), 
     71        _textureSize(copy._textureSize) 
     72    { 
     73    } 
     74 
     75    void ShadowMap::setTextureUnit(unsigned int unit) 
     76    { 
     77        _shadowTextureUnit = unit; 
     78    } 
     79 
     80    void ShadowMap::setAmbientBias(const osg::Vec2& ambientBias) 
     81    { 
     82        _ambientBias = ambientBias; 
     83    } 
     84 
     85    void ShadowMap::setTextureSize(const osg::Vec2s& textureSize) 
     86    { 
     87        _textureSize = textureSize; 
     88        dirty(); 
     89    } 
     90 
     91    void ShadowMap::setLight(osg::Light* light) 
     92    { 
     93        _light = light; 
     94    } 
     95 
     96 
     97    void ShadowMap::setLight(osg::LightSource* ls) 
     98    { 
     99        _ls = ls; 
     100        _light = _ls->getLight(); 
     101    } 
     102 
     103    void ShadowMap::createUniforms() 
     104    { 
     105        _uniformList.clear(); 
     106 
     107        osg::Uniform* baseTextureSampler = new osg::Uniform("osgShadow_baseTexture",(int)_baseTextureUnit); 
     108        _uniformList.push_back(baseTextureSampler); 
     109 
     110        osg::Uniform* shadowTextureSampler = new osg::Uniform("osgShadow_shadowTexture",(int)_shadowTextureUnit); 
     111        _uniformList.push_back(shadowTextureSampler); 
     112 
     113        osg::Uniform* ambientBias = new osg::Uniform("osgShadow_ambientBias",_ambientBias); 
     114        _uniformList.push_back(ambientBias); 
     115 
     116    } 
     117 
     118    void ShadowMap::createShaders() 
     119    { 
     120        // if we are not given shaders, use the default 
     121        if( _shaderList.empty() ) 
     122        { 
     123            if (_shadowTextureUnit==0) 
     124            { 
     125                osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture); 
     126                _shaderList.push_back(fragment_shader); 
     127            } 
     128            else 
     129            { 
     130                osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture); 
     131                _shaderList.push_back(fragment_shader); 
     132 
     133            } 
     134        } 
     135    } 
     136 
     137    void ShadowMap::init() 
     138    { 
     139        if (!_shadowedScene) return; 
     140 
     141        _texture = new osg::Texture2D; 
     142        _texture->setTextureSize(_textureSize.x(), _textureSize.y()); 
     143        _texture->setInternalFormat(GL_DEPTH_COMPONENT); 
     144        _texture->setShadowComparison(true); 
     145        _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE); 
     146        _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
     147        _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); 
     148        _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE); 
     149        _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE); 
     150 
     151        // set up the render to texture camera. 
     152        { 
     153            // create the camera 
     154            _camera = new osg::Camera; 
     155 
     156            _camera->setCullCallback(new CameraCullCallback(this)); 
     157 
     158            _camera->setClearMask(GL_DEPTH_BUFFER_BIT); 
     159            //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
     160            _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     161            _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); 
     162 
     163            // set viewport 
     164            _camera->setViewport(0,0,_textureSize.x(),_textureSize.y()); 
     165 
     166            // set the camera to render before the main camera. 
     167            _camera->setRenderOrder(osg::Camera::PRE_RENDER); 
     168 
     169            // tell the camera to use OpenGL frame buffer object where supported. 
     170            _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 
     171            //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW); 
     172 
     173            // attach the texture and use it as the color buffer. 
     174            _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get()); 
     175 
     176            osg::StateSet* stateset = _camera->getOrCreateStateSet(); 
     177 
     178            float factor = 0.0f; 
     179            float units = 1.0f; 
     180 
     181            osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset; 
     182            polygon_offset->setFactor(factor); 
     183            polygon_offset->setUnits(units); 
     184            stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     185            stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     186 
     187            osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace; 
     188            cull_face->setMode(osg::CullFace::FRONT); 
     189            stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     190            stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     191 
     192        } 
     193 
     194        { 
     195            _stateset = new osg::StateSet;         
     196            _stateset->setTextureAttributeAndModes(_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     197            _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); 
     198            _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); 
     199            _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); 
     200            _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); 
     201 
     202            _texgen = new osg::TexGen; 
     203 
     204            // add Program, when empty of Shaders then we are using fixed functionality 
     205            _program = new osg::Program; 
     206            _stateset->setAttribute(_program.get()); 
     207 
     208            // create default shaders if needed 
     209            createShaders(); 
     210 
     211            // add the shader list to the program 
     212            for(ShaderList::const_iterator itr=_shaderList.begin(); 
     213                itr!=_shaderList.end(); 
     214                ++itr) 
     215            { 
     216                _program->addShader(itr->get()); 
     217            } 
     218 
     219            // create own uniforms 
     220            createUniforms(); 
     221 
     222            // add the uniform list to the stateset 
     223            for(UniformList::const_iterator itr=_uniformList.begin(); 
     224                itr!=_uniformList.end(); 
     225                ++itr) 
     226            { 
     227                _stateset->addUniform(itr->get()); 
     228            } 
     229 
     230        } 
     231 
     232        _dirty = false; 
     233    } 
     234 
     235 
     236    void ShadowMap::update(osg::NodeVisitor& nv) 
     237    { 
     238        _shadowedScene->osg::Group::traverse(nv); 
     239    } 
     240 
     241    void ShadowMap::cull(osgUtil::CullVisitor& cv) 
     242    { 
     243        // record the traversal mask on entry so we can reapply it later. 
     244        unsigned int traversalMask = cv.getTraversalMask(); 
     245 
     246        osgUtil::RenderStage* orig_rs = cv.getRenderStage(); 
     247 
     248        // do traversal of shadow recieving scene which does need to be decorated by the shadow map 
     249        { 
     250            cv.pushStateSet(_stateset.get()); 
     251 
     252            _shadowedScene->osg::Group::traverse(cv); 
     253 
     254            cv.popStateSet(); 
     255 
     256        } 
     257 
     258        // need to compute view frustum for RTT camera. 
     259        // 1) get the light position 
     260        // 2) get the center and extents of the view frustum 
     261 
     262        const osg::Light* selectLight = 0; 
     263        osg::Vec4 lightpos; 
     264        osg::Vec3 lightDir; 
     265 
     266        //MR testing giving a specific light 
     267        osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); 
     268        for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); 
     269            itr != aml.end(); 
     270            ++itr) 
     271        { 
     272            const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get()); 
     273            if (light) 
     274            { 
     275                if( _light.valid()) { 
     276                    if( _light.get() == light ) 
     277                        selectLight = light; 
     278                    else 
     279                        continue; 
     280                } 
     281                else 
     282                    selectLight = light; 
     283 
     284                osg::RefMatrix* matrix = itr->second.get(); 
     285                if (matrix)  
     286                { 
     287                    lightpos = light->getPosition() * (*matrix); 
     288                    lightDir = light->getDirection() * (*matrix); 
     289                } 
     290                else  
     291                { 
     292                    lightpos = light->getPosition(); 
     293                    lightDir = light->getDirection(); 
     294                } 
     295 
     296            } 
     297        } 
     298 
     299        osg::Matrix eyeToWorld; 
     300        eyeToWorld.invert(*cv.getModelViewMatrix()); 
     301 
     302        lightpos = lightpos * eyeToWorld; 
     303        //MR do we do this for the direction also ? preliminary Yes, but still no good result 
     304        lightDir = lightDir * eyeToWorld; 
     305        lightDir.normalize(); 
     306 
     307        if (selectLight) 
     308        { 
     309 
     310            //std::cout<<"----- VxOSG::ShadowMap selectLight spot cutoff "<<selectLight->getSpotCutoff()<<std::endl; 
     311 
     312            if(selectLight->getSpotCutoff() < 180.0f)   // spotlight, then we don't need the bounding box 
     313            { 
     314                osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); 
     315                float spotAngle = selectLight->getSpotCutoff(); 
     316                _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
     317                _camera->setProjectionMatrixAsPerspective(spotAngle, 1.0, 0.1, 1000.0); 
     318                _camera->setViewMatrixAsLookAt(position,position+lightDir,osg::Vec3(0.0f,1.0f,0.0f)); 
     319            } 
     320            else 
     321            { 
     322                // get the bounds of the model.     
     323                osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); 
     324                cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask()); 
     325 
     326                _shadowedScene->osg::Group::traverse(cbbv); 
     327 
     328                osg::BoundingBox bb = cbbv.getBoundingBox(); 
     329 
     330                if (lightpos[3]!=0.0)   // point light 
     331                { 
     332                    osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); 
     333 
     334                    float centerDistance = (position-bb.center()).length(); 
     335 
     336                    float znear = centerDistance-bb.radius(); 
     337                    float zfar  = centerDistance+bb.radius(); 
     338                    float zNearRatio = 0.001f; 
     339                    if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; 
     340 
     341                    float top   = (bb.radius()/centerDistance)*znear; 
     342                    float right = top; 
     343 
     344                    _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
     345                    _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar); 
     346                    _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); 
     347                } 
     348                else    // directional light 
     349                { 
     350                    // make an orthographic projection 
     351                    osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z()); 
     352                    lightDir.normalize(); 
     353 
     354                    // set the position far away along the light direction 
     355                    osg::Vec3 position = lightDir * bb.radius()  * 20; 
     356 
     357                    float centerDistance = (position-bb.center()).length(); 
     358 
     359                    float znear = centerDistance-bb.radius(); 
     360                    float zfar  = centerDistance+bb.radius(); 
     361                    float zNearRatio = 0.001f; 
     362                    if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; 
     363 
     364                    float top   = bb.radius(); 
     365                    float right = top; 
     366 
     367                    _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
     368                    _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar); 
     369                    _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); 
     370                } 
     371 
     372                // compute the matrix which takes a vertex from local coords into tex coords 
     373                // will use this later to specify osg::TexGen.. 
     374                osg::Matrix MVPT = _camera->getViewMatrix() *  
     375                    _camera->getProjectionMatrix() * 
     376                    osg::Matrix::translate(1.0,1.0,1.0) * 
     377                    osg::Matrix::scale(0.5f,0.5f,0.5f); 
     378 
     379                _texgen->setMode(osg::TexGen::EYE_LINEAR); 
     380                _texgen->setPlanesFromMatrix(MVPT); 
     381            } 
     382 
     383 
     384            cv.setTraversalMask( traversalMask &  
     385                getShadowedScene()->getCastsShadowTraversalMask() ); 
     386 
     387            // do RTT camera traversal 
     388            _camera->accept(cv); 
     389 
     390            orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_shadowTextureUnit, cv.getModelViewMatrix(), _texgen.get()); 
     391        } // if(selectLight) 
     392 
     393 
     394        // reapply the original traversal mask 
     395        cv.setTraversalMask( traversalMask ); 
     396    } 
     397 
     398    void ShadowMap::cleanSceneGraph() 
     399    { 
     400    } 
     401 
     402    ///////////////////// Debug Methods 
     403 
     404    osg::ref_ptr<osg::Camera> ShadowMap::makeDebugHUD() 
     405    { 
     406        osg::ref_ptr<osg::Camera> camera = new osg::Camera; 
     407 
     408        osg::Vec2 size(1280, 1024); 
     409        // set the projection matrix 
     410        camera->setProjectionMatrix(osg::Matrix::ortho2D(0,size.x(),0,size.y())); 
     411 
     412        // set the view matrix     
     413        camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); 
     414        camera->setViewMatrix(osg::Matrix::identity()); 
     415 
     416        // only clear the depth buffer 
     417        camera->setClearMask(GL_DEPTH_BUFFER_BIT); 
     418        camera->setClearColor(osg::Vec4(0.2f, 0.3f, 0.5f, 0.2f)); 
     419        //camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
     420 
     421        // draw subgraph after main camera view. 
     422        camera->setRenderOrder(osg::Camera::POST_RENDER); 
     423 
     424        // we don't want the camera to grab event focus from the viewers main camera(s). 
     425        camera->setAllowEventFocus(false); 
     426 
     427        osg::Geode* geode = new osg::Geode; 
     428 
     429        osg::Vec3 position(10.0f,size.y()-100.0f,0.0f); 
     430        osg::Vec3 delta(0.0f,-120.0f,0.0f);  
     431        float lenght = 300.0f; 
     432 
     433        // turn the text off to avoid linking with osgText 
     434#if 0 
     435        std::string timesFont("fonts/arial.ttf"); 
     436 
     437        { 
     438            osgText::Text* text = new  osgText::Text; 
     439            geode->addDrawable( text ); 
     440 
     441            text->setFont(timesFont); 
     442            text->setPosition(position); 
     443            text->setText("Shadow Map HUD"); 
     444 
     445            position += delta; 
     446        } 
     447#endif 
    131448         
    132     } 
    133      
    134     { 
    135         _stateset = new osg::StateSet;         
    136         _stateset->setTextureAttributeAndModes(_textureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    137         _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); 
    138         _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); 
    139         _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); 
    140         _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); 
     449        osg::Vec3 widthVec(lenght, 0.0f, 0.0f); 
     450        osg::Vec3 depthVec(0.0f,lenght, 0.0f); 
     451        osg::Vec3 centerBase( 10.0f + lenght/2, size.y()-lenght/2, 0.0f); 
     452        centerBase += delta; 
    141453         
    142         _texgen = new osg::TexGen; 
    143  
    144 #if 1 
    145         osg::Program* program = new osg::Program; 
    146         _stateset->setAttribute(program); 
    147  
    148         if (_textureUnit==0) 
    149         { 
    150             osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture); 
    151             program->addShader(fragment_shader); 
    152  
    153             osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit); 
    154             _stateset->addUniform(shadowTextureSampler); 
    155         } 
    156         else 
    157         { 
    158             osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture); 
    159             program->addShader(fragment_shader); 
    160  
    161             osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0); 
    162             _stateset->addUniform(baseTextureSampler); 
    163  
    164             osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit); 
    165             _stateset->addUniform(shadowTextureSampler); 
    166         } 
    167          
    168         osg::Uniform* ambientBias = new osg::Uniform("ambientBias",_ambientBias); 
    169         _stateset->addUniform(ambientBias); 
    170  
    171 #endif 
    172     } 
    173      
    174     _dirty = false; 
    175 } 
    176  
    177  
    178 void ShadowMap::update(osg::NodeVisitor& nv) 
    179 { 
    180     _shadowedScene->osg::Group::traverse(nv); 
    181 } 
    182  
    183 void ShadowMap::cull(osgUtil::CullVisitor& cv) 
    184 { 
    185     // record the traversal mask on entry so we can reapply it later. 
    186     unsigned int traversalMask = cv.getTraversalMask(); 
    187  
    188     osgUtil::RenderStage* orig_rs = cv.getRenderStage(); 
    189  
    190     // do traversal of shadow recieving scene which does need to be decorated by the shadow map 
    191     { 
    192         cv.pushStateSet(_stateset.get()); 
    193      
    194         _shadowedScene->osg::Group::traverse(cv); 
    195          
    196         cv.popStateSet(); 
    197  
    198     } 
    199      
    200     // need to compute view frustum for RTT camera. 
    201     // 1) get the light position 
    202     // 2) get the center and extents of the view frustum 
    203  
    204     const osg::Light* selectLight = 0; 
    205     osg::Vec4 lightpos; 
    206  
    207     osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); 
    208     for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); 
    209         itr != aml.end(); 
    210         ++itr) 
    211     { 
    212         const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get()); 
    213         if (light) 
    214         { 
    215             osg::RefMatrix* matrix = itr->second.get(); 
    216             if (matrix) lightpos = light->getPosition() * (*matrix); 
    217             else lightpos = light->getPosition(); 
    218  
    219             selectLight = light; 
    220         } 
    221     } 
    222      
    223     osg::Matrix eyeToWorld; 
    224     eyeToWorld.invert(*cv.getModelViewMatrix()); 
    225      
    226     lightpos = lightpos * eyeToWorld; 
    227  
    228     if (selectLight) 
    229     { 
    230  
    231         // get the bounds of the model.     
    232         osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); 
    233         cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask()); 
    234          
    235         _shadowedScene->osg::Group::traverse(cbbv); 
    236          
    237         osg::BoundingBox bb = cbbv.getBoundingBox(); 
    238          
    239         if (lightpos[3]!=0.0) 
    240         { 
    241             osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); 
    242  
    243             float centerDistance = (position-bb.center()).length(); 
    244  
    245             float znear = centerDistance-bb.radius(); 
    246             float zfar  = centerDistance+bb.radius(); 
    247             float zNearRatio = 0.001f; 
    248             if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; 
    249  
    250             float top   = (bb.radius()/centerDistance)*znear; 
    251             float right = top; 
    252  
    253             _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
    254             _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar); 
    255             _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); 
    256              
    257  
    258             // compute the matrix which takes a vertex from local coords into tex coords 
    259             // will use this later to specify osg::TexGen.. 
    260             osg::Matrix MVPT = _camera->getViewMatrix() *  
    261                                _camera->getProjectionMatrix() * 
    262                                osg::Matrix::translate(1.0,1.0,1.0) * 
    263                                osg::Matrix::scale(0.5f,0.5f,0.5f); 
    264                                 
    265             _texgen->setMode(osg::TexGen::EYE_LINEAR); 
    266             _texgen->setPlanesFromMatrix(MVPT); 
    267         } 
    268         else 
    269         { 
    270             // make an orthographic projection 
    271             osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z()); 
    272             lightDir.normalize(); 
    273  
    274             // set the position far away along the light direction 
    275             osg::Vec3 position = lightDir * bb.radius()  * 20; 
    276  
    277             float centerDistance = (position-bb.center()).length(); 
    278  
    279             float znear = centerDistance-bb.radius(); 
    280             float zfar  = centerDistance+bb.radius(); 
    281             float zNearRatio = 0.001f; 
    282             if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; 
    283  
    284             float top   = bb.radius(); 
    285             float right = top; 
    286  
    287             _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
    288             _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar); 
    289             _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); 
    290              
    291  
    292             // compute the matrix which takes a vertex from local coords into tex coords 
    293             // will use this later to specify osg::TexGen.. 
    294             osg::Matrix MVPT = _camera->getViewMatrix() *  
    295                                _camera->getProjectionMatrix() * 
    296                                osg::Matrix::translate(1.0,1.0,1.0) * 
    297                                osg::Matrix::scale(0.5f,0.5f,0.5f); 
    298                                 
    299             _texgen->setMode(osg::TexGen::EYE_LINEAR); 
    300             _texgen->setPlanesFromMatrix(MVPT); 
    301         } 
    302  
    303  
    304         cv.setTraversalMask( traversalMask &  
    305                              getShadowedScene()->getCastsShadowTraversalMask() ); 
    306  
    307         // do RTT camera traversal 
    308         _camera->accept(cv); 
    309  
    310         orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_textureUnit, cv.getModelViewMatrix(), _texgen.get()); 
    311     } 
    312  
    313  
    314     // reapply the original traversal mask 
    315     cv.setTraversalMask( traversalMask ); 
    316 } 
    317  
    318 void ShadowMap::cleanSceneGraph() 
    319 { 
    320 } 
     454        geode->addDrawable( osg::createTexturedQuadGeometry( centerBase-widthVec*0.5f-depthVec*0.5f,  
     455                                                             widthVec, depthVec) ); 
     456 
     457        osg::StateSet* stateset = geode->getOrCreateStateSet(); 
     458 
     459        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); 
     460        stateset->setMode(GL_BLEND,osg::StateAttribute::ON); 
     461        //stateset->setAttribute(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON); 
     462        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 
     463 
     464        //stateset->setTextureAttributeAndModes(_baseTextureUnit, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb"))); 
     465        stateset->setTextureAttributeAndModes(_baseTextureUnit,_texture.get(),osg::StateAttribute::ON); 
     466 
     467        //TODO might need to have a shader for correct display 
     468 
     469        camera->addChild(geode); 
     470 
     471        return camera; 
     472    } 
     473 
     474    //////////////////////// End Debug Section 
     475