root/OpenSceneGraph/trunk/src/osgShadow/MinimalDrawBoundsShadowMap.cpp @ 13041

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

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
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 * ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
14 * Thanks to to my company http://www.ai.com.pl for allowing me free this work.
15*/
16
17#include <osgShadow/MinimalDrawBoundsShadowMap>
18#include <osgShadow/ConvexPolyhedron>
19#include <osg/PolygonOffset>
20#include <osgUtil/RenderLeaf>
21#include <osgShadow/ShadowedScene>
22#include <osg/FrameBufferObject>
23#include <osg/BlendEquation>
24#include <osg/Depth>
25#include <osg/AlphaFunc>
26#include <osg/Image>
27#include <iostream>
28#include <string.h>
29
30#define ANALYSIS_DEPTH                   1
31#define USE_FLOAT_IMAGE                  1
32
33using namespace osgShadow;
34
35MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap(): BaseClass()
36{
37}
38
39MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap
40(const MinimalDrawBoundsShadowMap& copy, const osg::CopyOp& copyop) :
41    BaseClass(copy,copyop)
42{
43}
44
45MinimalDrawBoundsShadowMap::~MinimalDrawBoundsShadowMap()
46{
47}
48
49void MinimalDrawBoundsShadowMap::ViewData::cullShadowReceivingScene( )
50{
51    BaseClass::ViewData::cullShadowReceivingScene( );
52    ThisClass::ViewData::cullBoundAnalysisScene( );
53}
54
55void MinimalDrawBoundsShadowMap::ViewData::cullBoundAnalysisScene( )
56{
57    _boundAnalysisCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
58    _boundAnalysisCamera->setViewMatrix( *_cv->getModelViewMatrix() );
59    _boundAnalysisCamera->setProjectionMatrix( _clampedProjection );
60
61    osg::Matrixd::value_type l,r,b,t,n,f;
62    _boundAnalysisCamera->getProjectionMatrixAsFrustum( l,r,b,t,n,f );
63
64    _mainCamera = _cv->getRenderStage()->getCamera();
65
66    extendProjection( _boundAnalysisCamera->getProjectionMatrix(),
67                      _boundAnalysisCamera->getViewport(), osg::Vec2( 2,2 ) );
68
69    // record the traversal mask on entry so we can reapply it later.
70    unsigned int traversalMask = _cv->getTraversalMask();
71
72    _cv->setTraversalMask( traversalMask &
73         _st->getShadowedScene()->getReceivesShadowTraversalMask() );
74
75    // do RTT camera traversal
76    _boundAnalysisCamera->accept(*_cv);
77
78    // reapply the original traversal mask
79    _cv->setTraversalMask( traversalMask );
80}
81
82
83void MinimalDrawBoundsShadowMap::ViewData::createDebugHUD( )
84{
85//    _hudSize[0] *= 2;
86    _viewportSize[0] *= 2;
87    _orthoSize[0] *= 2;
88
89    MinimalShadowMap::ViewData::createDebugHUD( );
90
91    osg::Camera * camera = _cameraDebugHUD.get();
92
93    osg::Geode* geode = new osg::Geode;
94    camera->addChild( geode );
95
96    osg::Geometry* geometry = osg::createTexturedQuadGeometry
97        ( osg::Vec3(_hudOrigin[0]+_hudSize[0],_hudOrigin[1],0),
98          osg::Vec3(_hudSize[0],0,0),
99          osg::Vec3(0,_hudSize[1],0) );
100
101    geode->addDrawable(geometry);
102
103    osg::StateSet* stateset = geometry->getOrCreateStateSet();
104    stateset->setTextureAttributeAndModes
105        (0, _boundAnalysisTexture.get(),osg::StateAttribute::ON );
106
107#if ANALYSIS_DEPTH
108    osg::Program* program = new osg::Program;
109    program->addShader( _depthColorFragmentShader.get() );
110    stateset->setAttribute( program );
111    stateset->addUniform( new osg::Uniform( "texture" , 0 ) );
112#else
113
114#endif
115}
116
117osg::BoundingBox MinimalDrawBoundsShadowMap::ViewData::scanImage
118    ( const osg::Image * image, osg::Matrix m )
119{
120    osg::BoundingBox bb, bbProj;
121
122    int components = osg::Image::computeNumComponents( image->getPixelFormat() );
123
124    if( image->getDataType() == GL_FLOAT ) {
125        float scale = 255.f / 254.f;
126        float * pf = (float *)image->data();
127        for( int y = 0; y < image->t(); y++ ) {
128            float fY = ( 0.5f + y ) / image->t();
129            for( int x = 0; x < image->s(); x++ ) {
130                float fX = ( 0.5f + x ) / image->s();
131
132                if( pf[0] < 1.0 ) {
133                    float fMinZ = pf[0] * scale;
134                    bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
135                    bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
136
137                    if( components > 1 ) {
138                        float fMaxZ = scale * ( 1.f - pf[1] );
139                        bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
140                        bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
141                    }
142                }
143
144                pf += components;
145            }
146        }
147    } else if( image->getDataType() == GL_UNSIGNED_BYTE ) {
148
149        unsigned char * pb = (unsigned char *)image->data();
150
151        float scale = 1.f / 254;
152        for( int y = 0; y < image->t(); y++ ) {
153            float fY = ( 0.5f + y ) / image->t();
154            for( int x = 0; x < image->s(); x++ ) {
155                float fX = ( 0.5f + x ) / image->s();
156
157                if( pb[0] < 255 ) {
158                    float fMinZ = scale * (pb[0] - 0.5f);
159                    fMinZ = osg::clampTo( fMinZ, 0.f, 1.f );
160
161                    bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
162                    bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
163
164                    if( components > 1 ) {
165                        float fMaxZ = scale * (255 - pb[1] + 0.5f);
166                        fMaxZ = osg::clampTo( fMaxZ, 0.f, 1.f );
167
168                        bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
169                        bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
170                    }
171                }
172
173                pb += components;
174            }
175        }
176    }
177
178    return bb;
179}
180
181void MinimalDrawBoundsShadowMap::ViewData::performBoundAnalysis( const osg::Camera& camera )
182{
183    if( !_projection.valid() )
184        return;
185
186    osg::Camera::BufferAttachmentMap & bam
187        = const_cast<osg::Camera&>( camera ).getBufferAttachmentMap();
188#if ANALYSIS_DEPTH
189    osg::Camera::Attachment & attachment = bam[ osg::Camera::DEPTH_BUFFER ];
190#else
191    osg::Camera::Attachment & attachment = bam[ osg::Camera::COLOR_BUFFER ];
192#endif
193
194    const osg::ref_ptr< osg::Image > image = attachment._image.get();
195    if( !image.valid() )
196        return;
197
198    osg::Matrix m;
199    m.invert( *_modellingSpaceToWorldPtr *
200              camera.getViewMatrix() *
201              camera.getProjectionMatrix() );
202
203    m.preMult( osg::Matrix::scale( osg::Vec3( 2.f, 2.f, 2.f ) ) *
204               osg::Matrix::translate( osg::Vec3( -1.f, -1.f, -1.f ) ) );
205
206    osg::BoundingBox bb = scanImage( image.get(), m );
207
208    if( getDebugDraw() ) {
209        ConvexPolyhedron p;
210        p.setToBoundingBox( bb );
211        p.transform( *_modellingSpaceToWorldPtr,
212                 osg::Matrix::inverse( *_modellingSpaceToWorldPtr ) );
213
214        setDebugPolytope( "scan", p,
215                      osg::Vec4( 0,0,0,1 ), osg::Vec4( 0,0,0,0.1 ) );
216    }
217
218    cutScenePolytope( *_modellingSpaceToWorldPtr,
219                     osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
220
221    frameShadowCastingCamera( _mainCamera.get(), _camera.get() );
222
223    _projection->set( _camera->getProjectionMatrix( ) );
224
225    BaseClass::ViewData::_texgen->setPlanesFromMatrix(
226            _camera->getProjectionMatrix() *
227            osg::Matrix::translate(1.0,1.0,1.0) *
228            osg::Matrix::scale(0.5,0.5,0.5) );
229
230    updateDebugGeometry( _mainCamera.get(),  _camera.get() );
231}
232
233void MinimalDrawBoundsShadowMap::ViewData::recordShadowMapParams( )
234{
235    const osgUtil::RenderStage * rs = _cv->getCurrentRenderBin()->getStage();
236
237    setShadowCameraProjectionMatrixPtr( _cv->getProjectionMatrix() );
238
239    if( !rs->getRenderBinList().empty() || rs->getBinNum() != 0 )
240    {
241
242    }
243#if 0
244    MinimalShadowMap::RenderLeafList rll;
245
246    static unsigned pass = 0, c = 0;
247
248    pass++;
249
250    std::set< osg::ref_ptr< osg::RefMatrix > > projections;
251
252    MinimalShadowMap::GetRenderLeaves( , rll );
253    for( unsigned i =0; i < rll.size(); i++ ) {
254        if( rll[i]->_projection.get() != _projection.get() ) {
255            osg::RefMatrix * projection = rll[i]->_projection.get();
256            projections.insert( rll[i]->_projection );
257            c++;
258        }
259    }
260
261    if( projections.size() > 0 )
262        _projection = (*projections.begin()).get();
263
264
265    c = 0;
266#endif
267}
268
269void MinimalDrawBoundsShadowMap::ViewData::init
270        ( ThisClass *st, osgUtil::CullVisitor *cv )
271{
272    BaseClass::ViewData::init( st, cv );
273
274    _frameShadowCastingCameraPasses = 2;
275    _camera->setCullCallback
276        ( new CameraCullCallback( this, _camera->getCullCallback() ) );
277
278    _boundAnalysisTexture = new osg::Texture2D;
279    _boundAnalysisTexture->setTextureSize
280        ( _boundAnalysisSize[0], _boundAnalysisSize[1] );
281
282    _boundAnalysisImage = new osg::Image;
283
284
285#if ANALYSIS_DEPTH
286    _boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
287                                        _boundAnalysisSize[1], 1,
288                                        GL_DEPTH_COMPONENT, GL_FLOAT );
289
290    _boundAnalysisTexture->setInternalFormat(GL_DEPTH_COMPONENT);
291//    _boundAnalysisTexture->setShadowComparison(true);
292    _boundAnalysisTexture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
293
294
295    _boundAnalysisImage->setInternalTextureFormat( GL_DEPTH_COMPONENT );
296    _boundAnalysisTexture->setInternalFormat( GL_DEPTH_COMPONENT );
297#else
298
299#if USE_FLOAT_IMAGE
300    _boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
301                                        _boundAnalysisSize[1], 1,
302                                        GL_RGBA, GL_FLOAT );
303
304    _boundAnalysisImage->setInternalTextureFormat( GL_RGBA16F_ARB );
305    _boundAnalysisTexture->setInternalFormat(GL_RGBA16F_ARB);
306#else
307    _boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
308                                        _boundAnalysisSize[1], 1,
309                                        GL_RGBA, GL_UNSIGNED_BYTE );
310
311    _boundAnalysisImage->setInternalTextureFormat( GL_RGBA );
312    _boundAnalysisTexture->setInternalFormat( GL_RGBA );
313#endif
314
315#endif
316    memset( _boundAnalysisImage->data(), 0, _boundAnalysisImage->getImageSizeInBytes() );
317
318    if( getDebugDraw() )
319        _boundAnalysisTexture->setImage(0, _boundAnalysisImage.get() );
320
321    _boundAnalysisTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
322    _boundAnalysisTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
323
324    // the shadow comparison should fail if object is outside the texture
325    _boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT);
326    _boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT);
327
328    // set up the render to texture camera.
329    // create the camera
330    _boundAnalysisCamera = new osg::Camera;
331    _boundAnalysisCamera->setName( "AnalysisCamera" );
332
333    _boundAnalysisCamera->setCullCallback( new BaseClass::CameraCullCallback(st) );
334//    _boundAnalysisCamera->setPreDrawCallback( _camera->getPreDrawCallback() );
335    _boundAnalysisCamera->setPostDrawCallback( new CameraPostDrawCallback(this) );
336
337    _boundAnalysisCamera->setClearColor( osg::Vec4(1,1,1,1) );
338    _boundAnalysisCamera->setClearMask(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
339    _boundAnalysisCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
340
341    // set viewport
342    _boundAnalysisCamera->setViewport
343            ( 0, 0, _boundAnalysisSize[0], _boundAnalysisSize[1] );
344
345        // set the camera to render before the main camera.
346    _boundAnalysisCamera->setRenderOrder(osg::Camera::PRE_RENDER);
347
348    // tell the camera to use OpenGL frame buffer object where supported.
349    _boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
350    //_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
351
352    const int OVERRIDE_ON = osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON;
353    const int OVERRIDE_OFF = osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF;
354
355    osg::StateSet* stateset = _boundAnalysisCamera->getOrCreateStateSet();
356    stateset->setAttributeAndModes
357        ( new osg::Depth( osg::Depth::LESS, 0.0, 254.f/255.f ), OVERRIDE_ON );
358
359//    stateset->setAttributeAndModes
360//        ( new osg::AlphaFunc( osg::AlphaFunc::EQUAL, 1.f ), OVERRIDE_ON );
361
362    stateset->setRenderBinDetails( 0, "RenderBin",
363                            osg::StateSet::OVERRIDE_RENDERBIN_DETAILS );
364
365    osg::Program* program = new osg::Program;
366
367    program->addShader( new osg::Shader( osg::Shader::FRAGMENT,
368        "uniform sampler2D texture;                                          \n"
369        "void main(void)                                                     \n"
370        "{                                                                   \n"
371#if ANALYSIS_DEPTH
372        " gl_FragColor = texture2D( texture, gl_TexCoord[0].xy );            \n"
373#else
374        " gl_FragColor = vec4( gl_FragCoord.z,                               \n"
375        "                      1.-gl_FragCoord.z,                            \n"
376        "                      1.,                                           \n"
377        "                       texture2D( texture, gl_TexCoord[0].xy ).a );  \n"
378#endif
379        "}                                                                   \n"
380    ) ); // program->addShader Fragment
381
382    program->addShader( new osg::Shader( osg::Shader::VERTEX,
383        "void main(void)                                                  \n"
384        "{                                                                \n"
385        "   gl_Position = ftransform();                                   \n"
386        "   gl_TexCoord[0] = gl_MultiTexCoord0;                           \n"
387        "}                                                                \n"
388    ) ); // program->addShader Vertex
389
390    stateset->setAttribute( program, OVERRIDE_ON );
391
392    // attach the texture and use it as the color buffer.
393#if ANALYSIS_DEPTH
394//    _boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisTexture.get());
395    _boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisImage.get());
396
397    stateset->setMode( GL_BLEND, OVERRIDE_OFF );
398#else
399//    _boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisTexture.get());
400    _boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisImage.get());
401
402    stateset->setAttributeAndModes
403        ( new osg::BlendEquation( osg::BlendEquation::RGBA_MIN ), OVERRIDE_ON );
404
405    stateset->setMode( GL_DEPTH_TEST, OVERRIDE_OFF );
406#endif
407}
Note: See TracBrowser for help on using the browser.