Show
Ignore:
Timestamp:
12/15/07 16:22:00 (7 years ago)
Author:
robert
Message:

Added setting of ambient bias uniform

Files:
1 modified

Legend:

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

    r7690 r7692  
    3030#include <osgText/Text> 
    3131 
    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     ////////////////////////////////////////////////////////////////// 
    59     // fragment shader 
    60     // 
    61     static const char fragmentShaderSource_debugHUD_texcoord[] = 
    62         "uniform sampler2D osgShadow_shadowTexture; \n" 
    63         " \n" 
    64         "void main(void) \n" 
    65         "{ \n" 
    66         "   vec4 texCoord = gl_TexCoord[1].xyzw; \n" 
    67         "   float value = texCoord.z / texCoord.w; \n" 
    68         "   gl_FragColor = vec4( value, value, value, 1.0 ); \n" 
    69         "} \n"; 
    70  
    71     static const char fragmentShaderSource_debugHUD[] = 
    72         "uniform sampler2D osgShadow_shadowTexture; \n" 
    73         " \n" 
    74         "void main(void) \n" 
    75         "{ \n" 
    76         "   vec4 texResult = texture2D(osgShadow_shadowTexture, gl_TexCoord[0].st ); \n" 
    77         "   float value = texResult.r + 0.5; \n" 
    78         "   gl_FragColor = vec4( value, value, value, 0.8 ); \n" 
    79         "} \n"; 
    80  
    81     ShadowMap::ShadowMap(): 
    82     _baseTextureUnit(0), 
    83         _shadowTextureUnit(1), 
    84         _ambientBias(0.5f,0.5f), 
    85         _textureSize(1024,1024) 
    86     { 
     32////////////////////////////////////////////////////////////////// 
     33// fragment shader 
     34// 
     35static 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// 
     47static 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////////////////////////////////////////////////////////////////// 
     59// fragment shader 
     60// 
     61static const char fragmentShaderSource_debugHUD_texcoord[] = 
     62    "uniform sampler2D osgShadow_shadowTexture; \n" 
     63    " \n" 
     64    "void main(void) \n" 
     65    "{ \n" 
     66    "   vec4 texCoord = gl_TexCoord[1].xyzw; \n" 
     67    "   float value = texCoord.z / texCoord.w; \n" 
     68    "   gl_FragColor = vec4( value, value, value, 1.0 ); \n" 
     69    "} \n"; 
     70 
     71static const char fragmentShaderSource_debugHUD[] = 
     72    "uniform sampler2D osgShadow_shadowTexture; \n" 
     73    " \n" 
     74    "void main(void) \n" 
     75    "{ \n" 
     76    "   vec4 texResult = texture2D(osgShadow_shadowTexture, gl_TexCoord[0].st ); \n" 
     77    "   float value = texResult.r + 0.5; \n" 
     78    "   gl_FragColor = vec4( value, value, value, 0.8 ); \n" 
     79    "} \n"; 
     80 
     81ShadowMap::ShadowMap(): 
     82_baseTextureUnit(0), 
     83    _shadowTextureUnit(1), 
     84    _ambientBias(0.5f,0.5f), 
     85    _textureSize(1024,1024) 
     86{ 
     87} 
     88 
     89ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop): 
     90ShadowTechnique(copy,copyop), 
     91    _baseTextureUnit(copy._baseTextureUnit), 
     92    _shadowTextureUnit(copy._shadowTextureUnit), 
     93    _ambientBias(copy._ambientBias), 
     94    _textureSize(copy._textureSize) 
     95{ 
     96} 
     97 
     98void ShadowMap::setTextureUnit(unsigned int unit) 
     99{ 
     100    _shadowTextureUnit = unit; 
     101} 
     102 
     103void ShadowMap::setAmbientBias(const osg::Vec2& ambientBias) 
     104{ 
     105    _ambientBias = ambientBias; 
     106    if (_ambientBiasUniform.valid()) _ambientBiasUniform->set(_ambientBias); 
     107} 
     108 
     109void ShadowMap::setTextureSize(const osg::Vec2s& textureSize) 
     110{ 
     111    _textureSize = textureSize; 
     112    dirty(); 
     113} 
     114 
     115void ShadowMap::setLight(osg::Light* light) 
     116{ 
     117    _light = light; 
     118} 
     119 
     120 
     121void ShadowMap::setLight(osg::LightSource* ls) 
     122{ 
     123    _ls = ls; 
     124    _light = _ls->getLight(); 
     125} 
     126 
     127void ShadowMap::createUniforms() 
     128{ 
     129    _uniformList.clear(); 
     130 
     131    osg::Uniform* baseTextureSampler = new osg::Uniform("osgShadow_baseTexture",(int)_baseTextureUnit); 
     132    _uniformList.push_back(baseTextureSampler); 
     133 
     134    osg::Uniform* shadowTextureSampler = new osg::Uniform("osgShadow_shadowTexture",(int)_shadowTextureUnit); 
     135    _uniformList.push_back(shadowTextureSampler); 
     136 
     137    _ambientBiasUniform = new osg::Uniform("osgShadow_ambientBias",_ambientBias); 
     138    _uniformList.push_back(_ambientBiasUniform.get()); 
     139 
     140} 
     141 
     142void ShadowMap::createShaders() 
     143{ 
     144    // if we are not given shaders, use the default 
     145    if( _shaderList.empty() ) 
     146    { 
     147        if (_shadowTextureUnit==0) 
     148        { 
     149            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture); 
     150            _shaderList.push_back(fragment_shader); 
     151        } 
     152        else 
     153        { 
     154            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture); 
     155            _shaderList.push_back(fragment_shader); 
     156 
     157        } 
    87158    } 
    88  
    89     ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop): 
    90     ShadowTechnique(copy,copyop), 
    91         _baseTextureUnit(copy._baseTextureUnit), 
    92         _shadowTextureUnit(copy._shadowTextureUnit), 
    93         _ambientBias(copy._ambientBias), 
    94         _textureSize(copy._textureSize) 
    95     { 
     159} 
     160 
     161void ShadowMap::init() 
     162{ 
     163    if (!_shadowedScene) return; 
     164 
     165    _texture = new osg::Texture2D; 
     166    _texture->setTextureSize(_textureSize.x(), _textureSize.y()); 
     167    _texture->setInternalFormat(GL_DEPTH_COMPONENT); 
     168    _texture->setShadowComparison(true); 
     169    _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE); 
     170    _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
     171    _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); 
     172 
     173    // the shadow comparison should fail if object is outside the texture 
     174    _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER); 
     175    _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER); 
     176    _texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     177 
     178    // set up the render to texture camera. 
     179    { 
     180        // create the camera 
     181        _camera = new osg::Camera; 
     182 
     183        _camera->setCullCallback(new CameraCullCallback(this)); 
     184 
     185        _camera->setClearMask(GL_DEPTH_BUFFER_BIT); 
     186        //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
     187        _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     188        _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); 
     189 
     190        // set viewport 
     191        _camera->setViewport(0,0,_textureSize.x(),_textureSize.y()); 
     192 
     193        // set the camera to render before the main camera. 
     194        _camera->setRenderOrder(osg::Camera::PRE_RENDER); 
     195 
     196        // tell the camera to use OpenGL frame buffer object where supported. 
     197        _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 
     198        //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW); 
     199 
     200        // attach the texture and use it as the color buffer. 
     201        _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get()); 
     202 
     203        osg::StateSet* stateset = _camera->getOrCreateStateSet(); 
     204 
     205 
     206#if 1 
     207        // cull front faces so that only backfaces contribute to depth map 
     208 
     209        osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace; 
     210        cull_face->setMode(osg::CullFace::FRONT); 
     211        stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     212        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     213 
     214        // negative polygonoffset - move the backface nearer to the eye point so that backfaces 
     215        // shadow themselves 
     216        float factor = -1.0f; 
     217        float units = -1.0f; 
     218 
     219        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset; 
     220        polygon_offset->setFactor(factor); 
     221        polygon_offset->setUnits(units); 
     222        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     223        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     224#else 
     225        // disabling cull faces so that only front and backfaces contribute to depth map 
     226        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); 
     227 
     228        // negative polygonoffset - move the backface nearer to the eye point 
     229        // so that front faces do not shadow themselves. 
     230        float factor = 1.0f; 
     231        float units = 1.0f; 
     232 
     233        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset; 
     234        polygon_offset->setFactor(factor); 
     235        polygon_offset->setUnits(units); 
     236        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     237        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     238#endif 
    96239    } 
    97240 
    98     void ShadowMap::setTextureUnit(unsigned int unit) 
    99     { 
    100         _shadowTextureUnit = unit; 
     241    { 
     242        _stateset = new osg::StateSet;         
     243        _stateset->setTextureAttributeAndModes(_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
     244        _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); 
     245        _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); 
     246        _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); 
     247        _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); 
     248 
     249        _texgen = new osg::TexGen; 
     250 
     251        // add Program, when empty of Shaders then we are using fixed functionality 
     252        _program = new osg::Program; 
     253        _stateset->setAttribute(_program.get()); 
     254 
     255        // create default shaders if needed 
     256        createShaders(); 
     257 
     258        // add the shader list to the program 
     259        for(ShaderList::const_iterator itr=_shaderList.begin(); 
     260            itr!=_shaderList.end(); 
     261            ++itr) 
     262        { 
     263            _program->addShader(itr->get()); 
     264        } 
     265 
     266        // create own uniforms 
     267        createUniforms(); 
     268 
     269        // add the uniform list to the stateset 
     270        for(UniformList::const_iterator itr=_uniformList.begin(); 
     271            itr!=_uniformList.end(); 
     272            ++itr) 
     273        { 
     274            _stateset->addUniform(itr->get()); 
     275        } 
     276 
     277        { 
     278            // fake texture for baseTexture, add a fake texture 
     279            // we support by default at least one texture layer 
     280            // without this fake texture we can not support 
     281            // textured and not textured scene 
     282 
     283            // TODO: at the moment the PSSM supports just one texture layer in the GLSL shader, multitexture are 
     284            //       not yet supported ! 
     285 
     286            osg::Image* image = new osg::Image; 
     287            // allocate the image data, noPixels x 1 x 1 with 4 rgba floats - equivilant to a Vec4! 
     288            int noPixels = 1; 
     289            image->allocateImage(noPixels,1,1,GL_RGBA,GL_FLOAT); 
     290            image->setInternalTextureFormat(GL_RGBA); 
     291            // fill in the image data. 
     292            osg::Vec4* dataPtr = (osg::Vec4*)image->data(); 
     293            osg::Vec4 color(1,1,1,1); 
     294            *dataPtr = color; 
     295            // make fake texture 
     296            osg::Texture2D* fakeTex = new osg::Texture2D; 
     297            fakeTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER); 
     298            fakeTex->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER); 
     299            fakeTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
     300            fakeTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); 
     301            fakeTex->setImage(image); 
     302            // add fake texture 
     303            _stateset->setTextureAttribute(_baseTextureUnit,fakeTex,osg::StateAttribute::ON); 
     304            _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_1D,osg::StateAttribute::OFF); 
     305            _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_2D,osg::StateAttribute::ON); 
     306            _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_3D,osg::StateAttribute::OFF); 
     307        } 
    101308    } 
    102309 
    103     void ShadowMap::setAmbientBias(const osg::Vec2& ambientBias) 
    104     { 
    105         _ambientBias = ambientBias; 
     310    _dirty = false; 
     311} 
     312 
     313 
     314void ShadowMap::update(osg::NodeVisitor& nv) 
     315{ 
     316    _shadowedScene->osg::Group::traverse(nv); 
     317} 
     318 
     319void ShadowMap::cull(osgUtil::CullVisitor& cv) 
     320{ 
     321    // record the traversal mask on entry so we can reapply it later. 
     322    unsigned int traversalMask = cv.getTraversalMask(); 
     323 
     324    osgUtil::RenderStage* orig_rs = cv.getRenderStage(); 
     325 
     326    // do traversal of shadow receiving scene which does need to be decorated by the shadow map 
     327    { 
     328        cv.pushStateSet(_stateset.get()); 
     329 
     330        _shadowedScene->osg::Group::traverse(cv); 
     331 
     332        cv.popStateSet(); 
     333 
    106334    } 
    107335 
    108     void ShadowMap::setTextureSize(const osg::Vec2s& textureSize) 
    109     { 
    110         _textureSize = textureSize; 
    111         dirty(); 
    112     } 
    113  
    114     void ShadowMap::setLight(osg::Light* light) 
    115     { 
    116         _light = light; 
    117     } 
    118  
    119  
    120     void ShadowMap::setLight(osg::LightSource* ls) 
    121     { 
    122         _ls = ls; 
    123         _light = _ls->getLight(); 
    124     } 
    125  
    126     void ShadowMap::createUniforms() 
    127     { 
    128         _uniformList.clear(); 
    129  
    130         osg::Uniform* baseTextureSampler = new osg::Uniform("osgShadow_baseTexture",(int)_baseTextureUnit); 
    131         _uniformList.push_back(baseTextureSampler); 
    132  
    133         osg::Uniform* shadowTextureSampler = new osg::Uniform("osgShadow_shadowTexture",(int)_shadowTextureUnit); 
    134         _uniformList.push_back(shadowTextureSampler); 
    135  
    136         _ambientBiasUniform = new osg::Uniform("osgShadow_ambientBias",_ambientBias); 
    137         _uniformList.push_back(_ambientBiasUniform.get()); 
    138  
    139     } 
    140  
    141     void ShadowMap::createShaders() 
    142     { 
    143         // if we are not given shaders, use the default 
    144         if( _shaderList.empty() ) 
    145         { 
    146             if (_shadowTextureUnit==0) 
    147             { 
    148                 osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture); 
    149                 _shaderList.push_back(fragment_shader); 
     336    // need to compute view frustum for RTT camera. 
     337    // 1) get the light position 
     338    // 2) get the center and extents of the view frustum 
     339 
     340    const osg::Light* selectLight = 0; 
     341    osg::Vec4 lightpos; 
     342    osg::Vec3 lightDir; 
     343 
     344    //MR testing giving a specific light 
     345    osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); 
     346    for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); 
     347        itr != aml.end(); 
     348        ++itr) 
     349    { 
     350        const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get()); 
     351        if (light) 
     352        { 
     353            if( _light.valid()) { 
     354                if( _light.get() == light ) 
     355                    selectLight = light; 
     356                else 
     357                    continue; 
    150358            } 
    151359            else 
     360                selectLight = light; 
     361 
     362            osg::RefMatrix* matrix = itr->second.get(); 
     363            if (matrix)  
    152364            { 
    153                 osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture); 
    154                 _shaderList.push_back(fragment_shader); 
    155  
     365                lightpos = light->getPosition() * (*matrix); 
     366                lightDir = light->getDirection() * (*matrix); 
    156367            } 
     368            else  
     369            { 
     370                lightpos = light->getPosition(); 
     371                lightDir = light->getDirection(); 
     372            } 
     373 
    157374        } 
    158375    } 
    159376 
    160     void ShadowMap::init() 
    161     { 
    162         if (!_shadowedScene) return; 
    163  
    164         _texture = new osg::Texture2D; 
    165         _texture->setTextureSize(_textureSize.x(), _textureSize.y()); 
    166         _texture->setInternalFormat(GL_DEPTH_COMPONENT); 
    167         _texture->setShadowComparison(true); 
    168         _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE); 
    169         _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
    170         _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); 
    171  
    172         // the shadow comparison should fail if object is outside the texture 
    173         _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER); 
    174         _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER); 
    175         _texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
    176  
    177         // set up the render to texture camera. 
    178         { 
    179             // create the camera 
    180             _camera = new osg::Camera; 
    181  
    182             _camera->setCullCallback(new CameraCullCallback(this)); 
    183  
    184             _camera->setClearMask(GL_DEPTH_BUFFER_BIT); 
    185             //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
    186             _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
    187             _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); 
    188  
    189             // set viewport 
    190             _camera->setViewport(0,0,_textureSize.x(),_textureSize.y()); 
    191  
    192             // set the camera to render before the main camera. 
    193             _camera->setRenderOrder(osg::Camera::PRE_RENDER); 
    194  
    195             // tell the camera to use OpenGL frame buffer object where supported. 
    196             _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 
    197             //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW); 
    198  
    199             // attach the texture and use it as the color buffer. 
    200             _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get()); 
    201  
    202             osg::StateSet* stateset = _camera->getOrCreateStateSet(); 
    203  
    204  
    205 #if 1 
    206             // cull front faces so that only backfaces contribute to depth map 
    207  
    208             osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace; 
    209             cull_face->setMode(osg::CullFace::FRONT); 
    210             stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    211             stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    212  
    213             // negative polygonoffset - move the backface nearer to the eye point so that backfaces 
    214             // shadow themselves 
    215             float factor = -1.0f; 
    216             float units = -1.0f; 
    217  
    218             osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset; 
    219             polygon_offset->setFactor(factor); 
    220             polygon_offset->setUnits(units); 
    221             stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    222             stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    223 #else 
    224             // disabling cull faces so that only front and backfaces contribute to depth map 
    225             stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); 
    226  
    227             // negative polygonoffset - move the backface nearer to the eye point 
    228             // so that front faces do not shadow themselves. 
    229             float factor = 1.0f; 
    230             float units = 1.0f; 
    231  
    232             osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset; 
    233             polygon_offset->setFactor(factor); 
    234             polygon_offset->setUnits(units); 
    235             stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    236             stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    237 #endif 
    238         } 
    239  
    240         { 
    241             _stateset = new osg::StateSet;         
    242             _stateset->setTextureAttributeAndModes(_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 
    243             _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); 
    244             _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); 
    245             _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); 
    246             _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); 
    247  
    248             _texgen = new osg::TexGen; 
    249  
    250             // add Program, when empty of Shaders then we are using fixed functionality 
    251             _program = new osg::Program; 
    252             _stateset->setAttribute(_program.get()); 
    253  
    254             // create default shaders if needed 
    255             createShaders(); 
    256  
    257             // add the shader list to the program 
    258             for(ShaderList::const_iterator itr=_shaderList.begin(); 
    259                 itr!=_shaderList.end(); 
    260                 ++itr) 
    261             { 
    262                 _program->addShader(itr->get()); 
    263             } 
    264  
    265             // create own uniforms 
    266             createUniforms(); 
    267  
    268             // add the uniform list to the stateset 
    269             for(UniformList::const_iterator itr=_uniformList.begin(); 
    270                 itr!=_uniformList.end(); 
    271                 ++itr) 
    272             { 
    273                 _stateset->addUniform(itr->get()); 
    274             } 
    275  
    276             { 
    277                 // fake texture for baseTexture, add a fake texture 
    278                 // we support by default at least one texture layer 
    279                 // without this fake texture we can not support 
    280                 // textured and not textured scene 
    281  
    282                 // TODO: at the moment the PSSM supports just one texture layer in the GLSL shader, multitexture are 
    283                 //       not yet supported ! 
    284  
    285                 osg::Image* image = new osg::Image; 
    286                 // allocate the image data, noPixels x 1 x 1 with 4 rgba floats - equivilant to a Vec4! 
    287                 int noPixels = 1; 
    288                 image->allocateImage(noPixels,1,1,GL_RGBA,GL_FLOAT); 
    289                 image->setInternalTextureFormat(GL_RGBA); 
    290                 // fill in the image data. 
    291                 osg::Vec4* dataPtr = (osg::Vec4*)image->data(); 
    292                 osg::Vec4 color(1,1,1,1); 
    293                 *dataPtr = color; 
    294                 // make fake texture 
    295                 osg::Texture2D* fakeTex = new osg::Texture2D; 
    296                 fakeTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER); 
    297                 fakeTex->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER); 
    298                 fakeTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
    299                 fakeTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); 
    300                 fakeTex->setImage(image); 
    301                 // add fake texture 
    302                 _stateset->setTextureAttribute(_baseTextureUnit,fakeTex,osg::StateAttribute::ON); 
    303                 _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_1D,osg::StateAttribute::OFF); 
    304                 _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_2D,osg::StateAttribute::ON); 
    305                 _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_3D,osg::StateAttribute::OFF); 
    306             } 
    307         } 
    308  
    309         _dirty = false; 
    310     } 
    311  
    312  
    313     void ShadowMap::update(osg::NodeVisitor& nv) 
    314     { 
    315         _shadowedScene->osg::Group::traverse(nv); 
    316     } 
    317  
    318     void ShadowMap::cull(osgUtil::CullVisitor& cv) 
    319     { 
    320         // record the traversal mask on entry so we can reapply it later. 
    321         unsigned int traversalMask = cv.getTraversalMask(); 
    322  
    323         osgUtil::RenderStage* orig_rs = cv.getRenderStage(); 
    324  
    325         // do traversal of shadow receiving scene which does need to be decorated by the shadow map 
    326         { 
    327             cv.pushStateSet(_stateset.get()); 
    328  
    329             _shadowedScene->osg::Group::traverse(cv); 
    330  
    331             cv.popStateSet(); 
    332  
    333         } 
    334  
    335         // need to compute view frustum for RTT camera. 
    336         // 1) get the light position 
    337         // 2) get the center and extents of the view frustum 
    338  
    339         const osg::Light* selectLight = 0; 
    340         osg::Vec4 lightpos; 
    341         osg::Vec3 lightDir; 
    342  
    343         //MR testing giving a specific light 
    344         osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); 
    345         for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); 
    346             itr != aml.end(); 
    347             ++itr) 
    348         { 
    349             const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get()); 
    350             if (light) 
    351             { 
    352                 if( _light.valid()) { 
    353                     if( _light.get() == light ) 
    354                         selectLight = light; 
    355                     else 
    356                         continue; 
    357                 } 
    358                 else 
    359                     selectLight = light; 
    360  
    361                 osg::RefMatrix* matrix = itr->second.get(); 
    362                 if (matrix)  
    363                 { 
    364                     lightpos = light->getPosition() * (*matrix); 
    365                     lightDir = light->getDirection() * (*matrix); 
    366                 } 
    367                 else  
    368                 { 
    369                     lightpos = light->getPosition(); 
    370                     lightDir = light->getDirection(); 
    371                 } 
    372  
    373             } 
    374         } 
    375          
    376         osg::Matrix eyeToWorld; 
    377         eyeToWorld.invert(*cv.getModelViewMatrix()); 
    378  
    379         lightpos = lightpos * eyeToWorld; 
    380         //MR do we do this for the direction also ? preliminary Yes, but still no good result 
    381         lightDir = lightDir * eyeToWorld; 
    382         lightDir.normalize(); 
    383  
    384         if (selectLight) 
    385         { 
    386  
    387             // set to ambient on light to black so that the ambient bias uniform can take it's affect 
    388             const_cast<osg::Light*>(selectLight)->setAmbient(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); 
    389  
    390             //std::cout<<"----- VxOSG::ShadowMap selectLight spot cutoff "<<selectLight->getSpotCutoff()<<std::endl; 
    391  
    392             if(selectLight->getSpotCutoff() < 180.0f)   // spotlight, then we don't need the bounding box 
     377    osg::Matrix eyeToWorld; 
     378    eyeToWorld.invert(*cv.getModelViewMatrix()); 
     379 
     380    lightpos = lightpos * eyeToWorld; 
     381    //MR do we do this for the direction also ? preliminary Yes, but still no good result 
     382    lightDir = lightDir * eyeToWorld; 
     383    lightDir.normalize(); 
     384 
     385    if (selectLight) 
     386    { 
     387 
     388        // set to ambient on light to black so that the ambient bias uniform can take it's affect 
     389        const_cast<osg::Light*>(selectLight)->setAmbient(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); 
     390 
     391        //std::cout<<"----- VxOSG::ShadowMap selectLight spot cutoff "<<selectLight->getSpotCutoff()<<std::endl; 
     392 
     393        if(selectLight->getSpotCutoff() < 180.0f)   // spotlight, then we don't need the bounding box 
     394        { 
     395            osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); 
     396            float spotAngle = selectLight->getSpotCutoff(); 
     397            _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
     398            _camera->setProjectionMatrixAsPerspective(spotAngle, 1.0, 0.1, 1000.0); 
     399            _camera->setViewMatrixAsLookAt(position,position+lightDir,osg::Vec3(0.0f,1.0f,0.0f)); 
     400        } 
     401        else 
     402        { 
     403            // get the bounds of the model.     
     404            osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); 
     405            cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask()); 
     406 
     407            _shadowedScene->osg::Group::traverse(cbbv); 
     408 
     409            osg::BoundingBox bb = cbbv.getBoundingBox(); 
     410 
     411            if (lightpos[3]!=0.0)   // point light 
    393412            { 
    394413                osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); 
    395                 float spotAngle = selectLight->getSpotCutoff(); 
     414 
     415                float centerDistance = (position-bb.center()).length(); 
     416 
     417                float znear = centerDistance-bb.radius(); 
     418                float zfar  = centerDistance+bb.radius(); 
     419                float zNearRatio = 0.001f; 
     420                if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; 
     421 
     422                float top   = (bb.radius()/centerDistance)*znear; 
     423                float right = top; 
     424 
    396425                _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
    397                 _camera->setProjectionMatrixAsPerspective(spotAngle, 1.0, 0.1, 1000.0); 
    398                 _camera->setViewMatrixAsLookAt(position,position+lightDir,osg::Vec3(0.0f,1.0f,0.0f)); 
     426                _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar); 
     427                _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); 
    399428            } 
    400             else 
     429            else    // directional light 
    401430            { 
    402                 // get the bounds of the model.     
    403                 osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); 
    404                 cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask()); 
    405  
    406                 _shadowedScene->osg::Group::traverse(cbbv); 
    407  
    408                 osg::BoundingBox bb = cbbv.getBoundingBox(); 
    409  
    410                 if (lightpos[3]!=0.0)   // point light 
    411                 { 
    412                     osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); 
    413  
    414                     float centerDistance = (position-bb.center()).length(); 
    415  
    416                     float znear = centerDistance-bb.radius(); 
    417                     float zfar  = centerDistance+bb.radius(); 
    418                     float zNearRatio = 0.001f; 
    419                     if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; 
    420  
    421                     float top   = (bb.radius()/centerDistance)*znear; 
    422                     float right = top; 
    423  
    424                     _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
    425                     _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar); 
    426                     _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); 
    427                 } 
    428                 else    // directional light 
    429                 { 
    430                     // make an orthographic projection 
    431                     osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z()); 
    432                     lightDir.normalize(); 
    433  
    434                     // set the position far away along the light direction 
    435                     osg::Vec3 position = lightDir * bb.radius()  * 20; 
    436  
    437                     float centerDistance = (position-bb.center()).length(); 
    438  
    439                     float znear = centerDistance-bb.radius(); 
    440                     float zfar  = centerDistance+bb.radius(); 
    441                     float zNearRatio = 0.001f; 
    442                     if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; 
    443  
    444                     float top   = bb.radius(); 
    445                     float right = top; 
    446  
    447                     _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
    448                     _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar); 
    449                     _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); 
    450                 } 
    451  
    452  
     431                // make an orthographic projection 
     432                osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z()); 
     433                lightDir.normalize(); 
     434 
     435                // set the position far away along the light direction 
     436                osg::Vec3 position = lightDir * bb.radius()  * 20; 
     437 
     438                float centerDistance = (position-bb.center()).length(); 
     439 
     440                float znear = centerDistance-bb.radius(); 
     441                float zfar  = centerDistance+bb.radius(); 
     442                float zNearRatio = 0.001f; 
     443                if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; 
     444 
     445                float top   = bb.radius(); 
     446                float right = top; 
     447 
     448                _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
     449                _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar); 
     450                _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f)); 
    453451            } 
    454                 // compute the matrix which takes a vertex from local coords into tex coords 
    455                 // will use this later to specify osg::TexGen.. 
    456                 osg::Matrix MVPT = _camera->getViewMatrix() *  
    457                     _camera->getProjectionMatrix() * 
    458                     osg::Matrix::translate(1.0,1.0,1.0) * 
    459                     osg::Matrix::scale(0.5f,0.5f,0.5f); 
    460  
    461                 _texgen->setMode(osg::TexGen::EYE_LINEAR); 
    462                 _texgen->setPlanesFromMatrix(MVPT); 
    463  
    464             cv.setTraversalMask( traversalMask &  
    465                 getShadowedScene()->getCastsShadowTraversalMask() ); 
    466  
    467             // do RTT camera traversal 
    468             _camera->accept(cv); 
    469  
    470             orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_shadowTextureUnit, cv.getModelViewMatrix(), _texgen.get()); 
    471         } // if(selectLight) 
    472  
    473  
    474         // reapply the original traversal mask 
    475         cv.setTraversalMask( traversalMask ); 
     452 
     453 
     454        } 
     455            // compute the matrix which takes a vertex from local coords into tex coords 
     456            // will use this later to specify osg::TexGen.. 
     457            osg::Matrix MVPT = _camera->getViewMatrix() *  
     458                _camera->getProjectionMatrix() * 
     459                osg::Matrix::translate(1.0,1.0,1.0) * 
     460                osg::Matrix::scale(0.5f,0.5f,0.5f); 
     461 
     462            _texgen->setMode(osg::TexGen::EYE_LINEAR); 
     463            _texgen->setPlanesFromMatrix(MVPT); 
     464 
     465        cv.setTraversalMask( traversalMask &  
     466            getShadowedScene()->getCastsShadowTraversalMask() ); 
     467 
     468        // do RTT camera traversal 
     469        _camera->accept(cv); 
     470 
     471        orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_shadowTextureUnit, cv.getModelViewMatrix(), _texgen.get()); 
     472    } // if(selectLight) 
     473 
     474 
     475    // reapply the original traversal mask 
     476    cv.setTraversalMask( traversalMask ); 
     477} 
     478 
     479void ShadowMap::cleanSceneGraph() 
     480{ 
     481} 
     482 
     483///////////////////// Debug Methods 
     484 
     485osg::ref_ptr<osg::Camera> ShadowMap::makeDebugHUD() 
     486{ 
     487    osg::ref_ptr<osg::Camera> camera = new osg::Camera; 
     488 
     489    osg::Vec2 size(1280, 1024); 
     490    // set the projection matrix 
     491    camera->setProjectionMatrix(osg::Matrix::ortho2D(0,size.x(),0,size.y())); 
     492 
     493    // set the view matrix     
     494    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); 
     495    camera->setViewMatrix(osg::Matrix::identity()); 
     496 
     497    // only clear the depth buffer 
     498    camera->setClearMask(GL_DEPTH_BUFFER_BIT); 
     499    camera->setClearColor(osg::Vec4(0.2f, 0.3f, 0.5f, 0.2f)); 
     500    //camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
     501 
     502    // draw subgraph after main camera view. 
     503    camera->setRenderOrder(osg::Camera::POST_RENDER); 
     504 
     505    // we don't want the camera to grab event focus from the viewers main camera(s). 
     506    camera->setAllowEventFocus(false); 
     507 
     508    osg::Geode* geode = new osg::Geode; 
     509 
     510    osg::Vec3 position(10.0f,size.y()-100.0f,0.0f); 
     511    osg::Vec3 delta(0.0f,-120.0f,0.0f);  
     512    float lenght = 300.0f; 
     513 
     514    // turn the text off to avoid linking with osgText 
     515#if 0 
     516    std::string timesFont("fonts/arial.ttf"); 
     517 
     518    { 
     519        osgText::Text* text = new  osgText::Text; 
     520        geode->addDrawable( text ); 
     521 
     522        text->setFont(timesFont); 
     523        text->setPosition(position); 
     524        text->setText("Shadow Map HUD"); 
     525 
     526        position += delta; 
    476527    } 
    477  
    478     void ShadowMap::cleanSceneGraph() 
    479     { 
    480     } 
    481  
    482     ///////////////////// Debug Methods 
    483  
    484     osg::ref_ptr<osg::Camera> ShadowMap::makeDebugHUD() 
    485     { 
    486         osg::ref_ptr<osg::Camera> camera = new osg::Camera; 
    487  
    488         osg::Vec2 size(1280, 1024); 
    489         // set the projection matrix 
    490         camera->setProjectionMatrix(osg::Matrix::ortho2D(0,size.x(),0,size.y())); 
    491  
    492         // set the view matrix     
    493         camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); 
    494         camera->setViewMatrix(osg::Matrix::identity()); 
    495  
    496         // only clear the depth buffer 
    497         camera->setClearMask(GL_DEPTH_BUFFER_BIT); 
    498         camera->setClearColor(osg::Vec4(0.2f, 0.3f, 0.5f, 0.2f)); 
    499         //camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
    500  
    501         // draw subgraph after main camera view. 
    502         camera->setRenderOrder(osg::Camera::POST_RENDER); 
    503  
    504         // we don't want the camera to grab event focus from the viewers main camera(s). 
    505         camera->setAllowEventFocus(false); 
    506  
    507         osg::Geode* geode = new osg::Geode; 
    508  
    509         osg::Vec3 position(10.0f,size.y()-100.0f,0.0f); 
    510         osg::Vec3 delta(0.0f,-120.0f,0.0f);  
    511         float lenght = 300.0f; 
    512  
    513         // turn the text off to avoid linking with osgText 
     528#endif 
     529 
     530    osg::Vec3 widthVec(lenght, 0.0f, 0.0f); 
     531    osg::Vec3 depthVec(0.0f,lenght, 0.0f); 
     532    osg::Vec3 centerBase( 10.0f + lenght/2, size.y()-lenght/2, 0.0f); 
     533    centerBase += delta; 
     534 
     535    geode->addDrawable( osg::createTexturedQuadGeometry( centerBase-widthVec*0.5f-depthVec*0.5f,  
     536                                                         widthVec, depthVec) ); 
     537 
     538    osg::StateSet* stateset = geode->getOrCreateStateSet(); 
     539 
     540    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); 
     541    stateset->setMode(GL_BLEND,osg::StateAttribute::ON); 
     542    //stateset->setAttribute(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON); 
     543    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 
     544 
     545    // test with regular texture 
     546    //stateset->setTextureAttributeAndModes(_baseTextureUnit, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb"))); 
     547 
     548    stateset->setTextureAttributeAndModes(_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON); 
     549 
     550    //test to check the texture coordinates generated during shadow pass 
    514551#if 0 
    515         std::string timesFont("fonts/arial.ttf"); 
    516  
    517         { 
    518             osgText::Text* text = new  osgText::Text; 
    519             geode->addDrawable( text ); 
    520  
    521             text->setFont(timesFont); 
    522             text->setPosition(position); 
    523             text->setText("Shadow Map HUD"); 
    524  
    525             position += delta; 
    526         } 
     552    stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); 
     553    stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); 
     554    stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); 
     555    stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); 
     556 
     557    // create TexGen node 
     558    osg::ref_ptr<osg::TexGenNode> texGenNode = new osg::TexGenNode; 
     559    texGenNode->setTextureUnit(_shadowTextureUnit); 
     560    texGenNode->setTexGen(_texgen.get()); 
     561    camera->addChild(texGenNode.get()); 
    527562#endif 
    528          
    529         osg::Vec3 widthVec(lenght, 0.0f, 0.0f); 
    530         osg::Vec3 depthVec(0.0f,lenght, 0.0f); 
    531         osg::Vec3 centerBase( 10.0f + lenght/2, size.y()-lenght/2, 0.0f); 
    532         centerBase += delta; 
    533          
    534         geode->addDrawable( osg::createTexturedQuadGeometry( centerBase-widthVec*0.5f-depthVec*0.5f,  
    535                                                              widthVec, depthVec) ); 
    536  
    537         osg::StateSet* stateset = geode->getOrCreateStateSet(); 
    538  
    539         stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); 
    540         stateset->setMode(GL_BLEND,osg::StateAttribute::ON); 
    541         //stateset->setAttribute(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON); 
    542         stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 
    543  
    544         // test with regular texture 
    545         //stateset->setTextureAttributeAndModes(_baseTextureUnit, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb"))); 
    546  
    547         stateset->setTextureAttributeAndModes(_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON); 
    548          
    549         //test to check the texture coordinates generated during shadow pass 
    550 #if 0 
    551         stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); 
    552         stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); 
    553         stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); 
    554         stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); 
    555  
    556         // create TexGen node 
    557         osg::ref_ptr<osg::TexGenNode> texGenNode = new osg::TexGenNode; 
    558         texGenNode->setTextureUnit(_shadowTextureUnit); 
    559         texGenNode->setTexGen(_texgen.get()); 
    560         camera->addChild(texGenNode.get()); 
    561 #endif 
    562         //shader for correct display 
    563  
    564         osg::ref_ptr<osg::Program> program = new osg::Program; 
    565         stateset->setAttribute(program.get()); 
    566          
    567         osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_debugHUD); 
    568         program->addShader(fragment_shader); 
    569  
    570         camera->addChild(geode); 
    571  
    572         return camera; 
    573     } 
    574  
    575     //////////////////////// End Debug Section 
    576  
     563    //shader for correct display 
     564 
     565    osg::ref_ptr<osg::Program> program = new osg::Program; 
     566    stateset->setAttribute(program.get()); 
     567 
     568    osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_debugHUD); 
     569    program->addShader(fragment_shader); 
     570 
     571    camera->addChild(geode); 
     572 
     573    return camera; 
     574} 
     575 
     576//////////////////////// End Debug Section 
     577