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

Revision 8886, 23.2 kB (checked in by robert, 6 years ago)

From Chris Denham, "
I think I may have discovered a bug in osgShadow/ShadowMap.cpp that results in incomplete shadows being generated.
The problem seems to caused by an incorrect interpretation of the spot light cutoff angle. The valid ranges for spot cutoff are 0-90 and 180, i.e half the 'field of view' for the spotlight. Whereas the shadow map code seems to assume the the spot cutoff is equal to the field of view. This results in the shadows generated by the spotlight getting clipped at half the spot cutoff angle.

I have fixed this in my copy of ShadowMap?.cpp:
===============================
//Original code from OSG 2.6:

if(selectLight->getSpotCutoff() < 180.0f) // spotlight, then we don't need the bounding box
{

osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());
float spotAngle = selectLight->getSpotCutoff();
_camera->setProjectionMatrixAsPerspective(spotAngle, 1.0, 0.1, 1000.0);

_camera->setViewMatrixAsLookAt(position,position+lightDir,osg::Vec3(0.0f,1.0f,0.0f));

}

===============================
// My modifications:

float fov = selectLight->getSpotCutoff() * 2;
if(fov < 180.0f) // spotlight, then we don't need the bounding box
{

osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());
_camera->setProjectionMatrixAsPerspective(fov, 1.0, 0.1, 1000.0);

_camera->setViewMatrixAsLookAt(position,position+lightDir,osg::Vec3(0.0f,1.0f,0.0f));

}

This change seems correct for spot cutoff in the range 0, 90, but since OpenGL doesn't claim to support cutoffs >90 && <180, I'm not sure how shadow map should deal with those cases, but ignoring spot cut off greater than 90 here seems reasonable to me.
"

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