root/OpenSceneGraph/trunk/src/osgShadow/ShadowMap.cpp @ 13314

Revision 13041, 23.3 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgShadow/ShadowMap>
15#include <osgShadow/ShadowedScene>
16#include <osg/Notify>
17#include <osg/ComputeBoundsVisitor>
18#include <osg/PolygonOffset>
19#include <osg/CullFace>
20#include <osg/io_utils>
21
22using namespace osgShadow;
23
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#define IMPROVE_TEXGEN_PRECISION 1
33
34//////////////////////////////////////////////////////////////////
35// fragment shader
36//
37static const char fragmentShaderSource_noBaseTexture[] =
38    "uniform sampler2DShadow osgShadow_shadowTexture; \n"
39    "uniform vec2 osgShadow_ambientBias; \n"
40    "\n"
41    "void main(void) \n"
42    "{ \n"
43    "    gl_FragColor = gl_Color * (osgShadow_ambientBias.x + shadow2DProj( osgShadow_shadowTexture, gl_TexCoord[0] ) * osgShadow_ambientBias.y); \n"
44    "}\n";
45
46//////////////////////////////////////////////////////////////////
47// fragment shader
48//
49static const char fragmentShaderSource_withBaseTexture[] =
50    "uniform sampler2D osgShadow_baseTexture; \n"
51    "uniform sampler2DShadow osgShadow_shadowTexture; \n"
52    "uniform vec2 osgShadow_ambientBias; \n"
53    "\n"
54    "void main(void) \n"
55    "{ \n"
56    "    vec4 color = gl_Color * texture2D( osgShadow_baseTexture, gl_TexCoord[0].xy ); \n"
57    "    gl_FragColor = color * (osgShadow_ambientBias.x + shadow2DProj( osgShadow_shadowTexture, gl_TexCoord[1] ) * osgShadow_ambientBias.y); \n"
58    "}\n";
59
60//////////////////////////////////////////////////////////////////
61// fragment shader
62//
63static const char fragmentShaderSource_debugHUD_texcoord[] =
64    "uniform sampler2D osgShadow_shadowTexture; \n"
65    " \n"
66    "void main(void) \n"
67    "{ \n"
68    "   vec4 texCoord = gl_TexCoord[1].xyzw; \n"
69    "   float value = texCoord.z / texCoord.w; \n"
70    "   gl_FragColor = vec4( value, value, value, 1.0 ); \n"
71    "} \n";
72
73static const char fragmentShaderSource_debugHUD[] =
74    "uniform sampler2D osgShadow_shadowTexture; \n"
75    " \n"
76    "void main(void) \n"
77    "{ \n"
78    "   vec4 texResult = texture2D(osgShadow_shadowTexture, gl_TexCoord[0].st ); \n"
79    "   float value = texResult.r; \n"
80    "   gl_FragColor = vec4( value, value, value, 0.8 ); \n"
81    "} \n";
82
83ShadowMap::ShadowMap():
84    _baseTextureUnit(0),
85    _shadowTextureUnit(1),
86    _polyOffset(1.0,1.0),
87    _ambientBias(0.5f,0.5f),
88    _textureSize(1024,1024)
89{
90}
91
92ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop):
93ShadowTechnique(copy,copyop),
94    _baseTextureUnit(copy._baseTextureUnit),
95    _shadowTextureUnit(copy._shadowTextureUnit),
96    _polyOffset(copy._polyOffset),
97    _ambientBias(copy._ambientBias),
98    _textureSize(copy._textureSize)
99{
100}
101
102void ShadowMap::setTextureUnit(unsigned int unit)
103{
104    _shadowTextureUnit = unit;
105}
106
107void ShadowMap::setPolygonOffset(const osg::Vec2& polyOffset)
108{
109    _polyOffset = polyOffset;
110}
111
112void ShadowMap::setAmbientBias(const osg::Vec2& ambientBias)
113{
114    _ambientBias = ambientBias;
115    if (_ambientBiasUniform.valid()) _ambientBiasUniform->set(_ambientBias);
116}
117
118void ShadowMap::setTextureSize(const osg::Vec2s& textureSize)
119{
120    _textureSize = textureSize;
121    dirty();
122}
123
124void ShadowMap::setLight(osg::Light* light)
125{
126    _light = light;
127}
128
129
130void ShadowMap::setLight(osg::LightSource* ls)
131{
132    _ls = ls;
133    _light = _ls->getLight();
134}
135
136void ShadowMap::createUniforms()
137{
138    _uniformList.clear();
139
140    osg::Uniform* baseTextureSampler = new osg::Uniform("osgShadow_baseTexture",(int)_baseTextureUnit);
141    _uniformList.push_back(baseTextureSampler);
142
143    osg::Uniform* shadowTextureSampler = new osg::Uniform("osgShadow_shadowTexture",(int)_shadowTextureUnit);
144    _uniformList.push_back(shadowTextureSampler);
145
146    _ambientBiasUniform = new osg::Uniform("osgShadow_ambientBias",_ambientBias);
147    _uniformList.push_back(_ambientBiasUniform.get());
148
149}
150
151void ShadowMap::createShaders()
152{
153    // if we are not given shaders, use the default
154    if( _shaderList.empty() )
155    {
156        if (_shadowTextureUnit==0)
157        {
158            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture);
159            _shaderList.push_back(fragment_shader);
160        }
161        else
162        {
163            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture);
164            _shaderList.push_back(fragment_shader);
165
166        }
167    }
168}
169
170void ShadowMap::init()
171{
172    if (!_shadowedScene) return;
173
174    _texture = new osg::Texture2D;
175    _texture->setTextureSize(_textureSize.x(), _textureSize.y());
176    _texture->setInternalFormat(GL_DEPTH_COMPONENT);
177    _texture->setShadowComparison(true);
178    _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
179    _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
180    _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
181
182    // the shadow comparison should fail if object is outside the texture
183    _texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
184    _texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
185    _texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
186
187    // set up the render to texture camera.
188    {
189        // create the camera
190        _camera = new osg::Camera;
191
192        _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT);
193
194        _camera->setCullCallback(new CameraCullCallback(this));
195
196        _camera->setClearMask(GL_DEPTH_BUFFER_BIT);
197        //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
198        _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
199        _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
200
201        // set viewport
202        _camera->setViewport(0,0,_textureSize.x(),_textureSize.y());
203
204        // set the camera to render before the main camera.
205        _camera->setRenderOrder(osg::Camera::PRE_RENDER);
206
207        // tell the camera to use OpenGL frame buffer object where supported.
208        _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
209        //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
210
211        // attach the texture and use it as the color buffer.
212        _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get());
213
214        osg::StateSet* stateset = _camera->getOrCreateStateSet();
215
216
217#if 1
218        // cull front faces so that only backfaces contribute to depth map
219
220
221        osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace;
222        cull_face->setMode(osg::CullFace::FRONT);
223        stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
224        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
225
226        // negative polygonoffset - move the backface nearer to the eye point so that backfaces
227        // shadow themselves
228        float factor = -_polyOffset[0];
229        float units =  -_polyOffset[1];
230
231        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset;
232        polygon_offset->setFactor(factor);
233        polygon_offset->setUnits(units);
234        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
235        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
236#else
237        // disabling cull faces so that only front and backfaces contribute to depth map
238        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
239
240        // negative polygonoffset - move the backface nearer to the eye point
241        // so that front faces do not shadow themselves.
242        float factor = _polyOffset[0];
243        float units =  _polyOffset[1];
244
245        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset;
246        polygon_offset->setFactor(factor);
247        polygon_offset->setUnits(units);
248        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
249        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
250#endif
251    }
252
253    {
254        _stateset = new osg::StateSet;
255        _stateset->setTextureAttributeAndModes(_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
256        _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
257        _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
258        _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
259        _stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
260
261        _texgen = new osg::TexGen;
262
263        // add Program, when empty of Shaders then we are using fixed functionality
264        _program = new osg::Program;
265        _stateset->setAttribute(_program.get());
266
267        // create default shaders if needed
268        createShaders();
269
270        // add the shader list to the program
271        for(ShaderList::const_iterator itr=_shaderList.begin();
272            itr!=_shaderList.end();
273            ++itr)
274        {
275            _program->addShader(itr->get());
276        }
277
278        // create own uniforms
279        createUniforms();
280
281        // add the uniform list to the stateset
282        for(UniformList::const_iterator itr=_uniformList.begin();
283            itr!=_uniformList.end();
284            ++itr)
285        {
286            _stateset->addUniform(itr->get());
287        }
288
289        {
290            // fake texture for baseTexture, add a fake texture
291            // we support by default at least one texture layer
292            // without this fake texture we can not support
293            // textured and not textured scene
294
295            // TODO: at the moment the PSSM supports just one texture layer in the GLSL shader, multitexture are
296            //       not yet supported !
297
298            osg::Image* image = new osg::Image;
299            // allocate the image data, noPixels x 1 x 1 with 4 rgba floats - equivilant to a Vec4!
300            int noPixels = 1;
301            image->allocateImage(noPixels,1,1,GL_RGBA,GL_FLOAT);
302            image->setInternalTextureFormat(GL_RGBA);
303            // fill in the image data.
304            osg::Vec4* dataPtr = (osg::Vec4*)image->data();
305            osg::Vec4 color(1,1,1,1);
306            *dataPtr = color;
307            // make fake texture
308            osg::Texture2D* fakeTex = new osg::Texture2D;
309            fakeTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE);
310            fakeTex->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE);
311            fakeTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
312            fakeTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
313            fakeTex->setImage(image);
314            // add fake texture
315            _stateset->setTextureAttribute(_baseTextureUnit,fakeTex,osg::StateAttribute::ON);
316            _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_2D,osg::StateAttribute::ON);
317            _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_3D,osg::StateAttribute::OFF);
318            #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
319                _stateset->setTextureMode(_baseTextureUnit,GL_TEXTURE_1D,osg::StateAttribute::OFF);
320            #endif
321        }
322    }
323
324    _dirty = false;
325}
326
327
328void ShadowMap::update(osg::NodeVisitor& nv)
329{
330    _shadowedScene->osg::Group::traverse(nv);
331}
332
333void ShadowMap::cull(osgUtil::CullVisitor& cv)
334{
335    // record the traversal mask on entry so we can reapply it later.
336    unsigned int traversalMask = cv.getTraversalMask();
337
338    osgUtil::RenderStage* orig_rs = cv.getRenderStage();
339
340    // do traversal of shadow recieving scene which does need to be decorated by the shadow map
341    {
342        cv.pushStateSet(_stateset.get());
343
344        _shadowedScene->osg::Group::traverse(cv);
345
346        cv.popStateSet();
347
348    }
349
350    // need to compute view frustum for RTT camera.
351    // 1) get the light position
352    // 2) get the center and extents of the view frustum
353
354    const osg::Light* selectLight = 0;
355    osg::Vec4 lightpos;
356    osg::Vec3 lightDir;
357
358    //MR testing giving a specific light
359    osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList();
360    for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin();
361        itr != aml.end();
362        ++itr)
363    {
364        const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get());
365        if (light)
366        {
367            if( _light.valid()) {
368                if( _light.get() == light )
369                    selectLight = light;
370                else
371                    continue;
372            }
373            else
374                selectLight = light;
375
376            osg::RefMatrix* matrix = itr->second.get();
377            if (matrix)
378            {
379                lightpos = light->getPosition() * (*matrix);
380                lightDir = osg::Matrix::transform3x3( light->getDirection(), *matrix );
381            }
382            else
383            {
384                lightpos = light->getPosition();
385                lightDir = light->getDirection();
386            }
387
388        }
389    }
390
391    osg::Matrix eyeToWorld;
392    eyeToWorld.invert(*cv.getModelViewMatrix());
393
394    lightpos = lightpos * eyeToWorld;
395    lightDir = osg::Matrix::transform3x3( lightDir, eyeToWorld );
396    lightDir.normalize();
397
398    if (selectLight)
399    {
400
401        // set to ambient on light to black so that the ambient bias uniform can take it's affect
402        const_cast<osg::Light*>(selectLight)->setAmbient(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
403
404        //std::cout<<"----- VxOSG::ShadowMap selectLight spot cutoff "<<selectLight->getSpotCutoff()<<std::endl;
405
406        float fov = selectLight->getSpotCutoff() * 2;
407        if(fov < 180.0f)   // spotlight, then we don't need the bounding box
408        {
409            osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());
410            _camera->setProjectionMatrixAsPerspective(fov, 1.0, 0.1, 1000.0);
411            _camera->setViewMatrixAsLookAt(position,position+lightDir,computeOrthogonalVector(lightDir));
412        }
413        else
414        {
415            // get the bounds of the model.
416            osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
417            cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask());
418
419            _shadowedScene->osg::Group::traverse(cbbv);
420
421            osg::BoundingBox bb = cbbv.getBoundingBox();
422
423            if (lightpos[3]!=0.0)   // point light
424            {
425                osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());
426
427                float centerDistance = (position-bb.center()).length();
428
429                float znear = centerDistance-bb.radius();
430                float zfar  = centerDistance+bb.radius();
431                float zNearRatio = 0.001f;
432                if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
433
434                float top   = (bb.radius()/centerDistance)*znear;
435                float right = top;
436
437                _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
438                _camera->setViewMatrixAsLookAt(position,bb.center(),computeOrthogonalVector(bb.center()-position));
439            }
440            else    // directional light
441            {
442                // make an orthographic projection
443                osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z());
444                lightDir.normalize();
445
446                // set the position far away along the light direction
447                osg::Vec3 position = bb.center() + lightDir * bb.radius() * 2;
448
449                float centerDistance = (position-bb.center()).length();
450
451                float znear = centerDistance-bb.radius();
452                float zfar  = centerDistance+bb.radius();
453                float zNearRatio = 0.001f;
454                if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
455
456                float top   = bb.radius();
457                float right = top;
458
459                _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar);
460                _camera->setViewMatrixAsLookAt(position,bb.center(),computeOrthogonalVector(lightDir));
461            }
462
463
464        }
465
466        cv.setTraversalMask( traversalMask &
467            getShadowedScene()->getCastsShadowTraversalMask() );
468
469        // do RTT camera traversal
470        _camera->accept(cv);
471
472        _texgen->setMode(osg::TexGen::EYE_LINEAR);
473
474#if IMPROVE_TEXGEN_PRECISION
475        // compute the matrix which takes a vertex from local coords into tex coords
476        // We actually use two matrices one used to define texgen
477        // and second that will be used as modelview when appling to OpenGL
478        _texgen->setPlanesFromMatrix( _camera->getProjectionMatrix() *
479                                      osg::Matrix::translate(1.0,1.0,1.0) *
480                                      osg::Matrix::scale(0.5f,0.5f,0.5f) );
481
482        // Place texgen with modelview which removes big offsets (making it float friendly)
483        osg::RefMatrix * refMatrix = new osg::RefMatrix
484            ( _camera->getInverseViewMatrix() * *cv.getModelViewMatrix() );
485
486        cv.getRenderStage()->getPositionalStateContainer()->
487             addPositionedTextureAttribute( _shadowTextureUnit, refMatrix, _texgen.get() );
488#else
489        // compute the matrix which takes a vertex from local coords into tex coords
490        // will use this later to specify osg::TexGen..
491        osg::Matrix MVPT = _camera->getViewMatrix() *
492               _camera->getProjectionMatrix() *
493               osg::Matrix::translate(1.0,1.0,1.0) *
494               osg::Matrix::scale(0.5f,0.5f,0.5f);
495
496        _texgen->setPlanesFromMatrix(MVPT);
497
498        orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_shadowTextureUnit, cv.getModelViewMatrix(), _texgen.get());
499#endif
500    } // if(selectLight)
501
502
503    // reapply the original traversal mask
504    cv.setTraversalMask( traversalMask );
505}
506
507void ShadowMap::cleanSceneGraph()
508{
509}
510
511///////////////////// Debug Methods
512
513////////////////////////////////////////////////////////////////////////////////
514// Callback used by debugging hud to display Shadow Map in color buffer
515// OSG does not allow to use the same GL Texture Id with different glTexParams.
516// Callback simply turns shadow compare mode off via GL while rendering hud and
517// restores it afterwards.
518////////////////////////////////////////////////////////////////////////////////
519class ShadowMap::DrawableDrawWithDepthShadowComparisonOffCallback:
520    public osg::Drawable::DrawCallback
521{
522public:
523    //
524    DrawableDrawWithDepthShadowComparisonOffCallback
525        ( osg::Texture2D * texture, unsigned stage = 0 )
526            : _texture( texture ), _stage( stage )
527    {
528    }
529
530    virtual void drawImplementation
531        ( osg::RenderInfo & ri,const osg::Drawable* drawable ) const
532    {
533        if( _texture.valid() ) {
534            // make sure proper texture is currently applied
535            ri.getState()->applyTextureAttribute( _stage, _texture.get() );
536
537            // Turn off depth comparison mode
538            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
539                             GL_NONE );
540        }
541
542        drawable->drawImplementation(ri);
543
544        if( _texture.valid() ) {
545            // Turn it back on
546            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
547                             GL_COMPARE_R_TO_TEXTURE_ARB );
548        }
549    }
550
551    osg::ref_ptr< osg::Texture2D > _texture;
552    unsigned                       _stage;
553};
554
555////////////////////////////////////////////////////////////////////////////////
556osg::ref_ptr<osg::Camera> ShadowMap::makeDebugHUD()
557{
558    // Make sure we attach initialized texture to HUD
559    if( !_texture.valid() )    init();
560
561    osg::ref_ptr<osg::Camera> camera = new osg::Camera;
562
563    osg::Vec2 size(1280, 1024);
564    // set the projection matrix
565    camera->setProjectionMatrix(osg::Matrix::ortho2D(0,size.x(),0,size.y()));
566
567    // set the view matrix
568    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
569    camera->setViewMatrix(osg::Matrix::identity());
570
571    // only clear the depth buffer
572    camera->setClearMask(GL_DEPTH_BUFFER_BIT);
573    camera->setClearColor(osg::Vec4(0.2f, 0.3f, 0.5f, 0.2f));
574    //camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
575
576    // draw subgraph after main camera view.
577    camera->setRenderOrder(osg::Camera::POST_RENDER);
578
579    // we don't want the camera to grab event focus from the viewers main camera(s).
580    camera->setAllowEventFocus(false);
581
582    osg::Geode* geode = new osg::Geode;
583
584    osg::Vec3 position(10.0f,size.y()-100.0f,0.0f);
585    osg::Vec3 delta(0.0f,-120.0f,0.0f);
586    float length = 300.0f;
587
588    // turn the text off to avoid linking with osgText
589#if 0
590    std::string timesFont("fonts/arial.ttf");
591
592    {
593        osgText::Text* text = new  osgText::Text;
594        geode->addDrawable( text );
595
596        text->setFont(timesFont);
597        text->setPosition(position);
598        text->setText("Shadow Map HUD");
599
600        position += delta;
601    }
602#endif
603
604    osg::Vec3 widthVec(length, 0.0f, 0.0f);
605    osg::Vec3 depthVec(0.0f,length, 0.0f);
606    osg::Vec3 centerBase( 10.0f + length/2, size.y()-length/2, 0.0f);
607    centerBase += delta;
608
609    osg::Geometry *geometry = osg::createTexturedQuadGeometry
610        ( centerBase-widthVec*0.5f-depthVec*0.5f, widthVec, depthVec );
611
612    geode->addDrawable( geometry );
613
614    geometry->setDrawCallback
615        ( new DrawableDrawWithDepthShadowComparisonOffCallback( _texture.get() ) );
616
617    osg::StateSet* stateset = geode->getOrCreateStateSet();
618
619    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
620    stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
621    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
622
623    // test with regular texture
624    //stateset->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")));
625
626    stateset->setTextureAttributeAndModes(0,_texture.get(),osg::StateAttribute::ON);
627
628    //test to check the texture coordinates generated during shadow pass
629#if 0
630    stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
631    stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
632    stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
633    stateset->setTextureMode(_shadowTextureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
634
635    // create TexGen node
636    osg::ref_ptr<osg::TexGenNode> texGenNode = new osg::TexGenNode;
637    texGenNode->setTextureUnit(_shadowTextureUnit);
638    texGenNode->setTexGen(_texgen.get());
639    camera->addChild(texGenNode.get());
640#endif
641    //shader for correct display
642
643    osg::ref_ptr<osg::Program> program = new osg::Program;
644    stateset->setAttribute(program.get());
645
646    osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_debugHUD);
647    program->addShader(fragment_shader);
648
649    camera->addChild(geode);
650
651    return camera;
652}
653
654//////////////////////// End Debug Section
Note: See TracBrowser for help on using the browser.