Show
Ignore:
Timestamp:
07/19/05 18:30:55 (9 years ago)
Author:
robert
Message:

Ported all the render to texture examples across to using the new osg::CameraNode?.
Added support for texture cube maps in FBO + CameraNode?.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgprerendercubemap/osgprerendercubemap.cpp

    r3214 r4395  
    1 #include <osg/GLExtensions> 
    2 #include <osg/Group> 
     1#include <osgProducer/Viewer> 
     2 
     3#include <osg/Projection> 
     4#include <osg/Geometry> 
     5#include <osg/Texture> 
     6#include <osg/TexGen> 
    37#include <osg/Geode> 
    4 #include <osg/Matrix> 
    5 #include <osg/Quat> 
    6 #include <osg/StateSet> 
     8#include <osg/ShapeDrawable> 
     9#include <osg/PolygonOffset> 
     10#include <osg/CullFace> 
    711#include <osg/TextureCubeMap> 
    8 #include <osg/TexGen> 
    912#include <osg/TexMat> 
    10 #include <osg/TexEnvCombine> 
    11 #include <osg/ShapeDrawable> 
    12 #include <osg/PositionAttitudeTransform> 
    13  
    1413#include <osg/MatrixTransform> 
    15  
    16 #include <osgUtil/RenderToTextureStage> 
    17 #include <osgUtil/Optimizer> 
     14#include <osg/Light> 
     15#include <osg/LightSource> 
     16#include <osg/PolygonOffset> 
     17#include <osg/CullFace> 
     18#include <osg/Material> 
     19#include <osg/RefNodePath> 
     20 
    1821#include <osgUtil/TransformCallback> 
    1922 
    20 #include <osgDB/ReadFile> 
    21 #include <osgDB/Registry> 
    22  
    23 #include <osgGA/TrackballManipulator> 
    24 #include <osgGA/FlightManipulator> 
    25 #include <osgGA/DriveManipulator> 
    26  
    27 #include <osgProducer/Viewer> 
    28  
    29 #include <iostream> 
    30 #include <string> 
    31 #include <vector> 
    32  
    33 #define UPDATE_ONE_IMAGE_PER_FRAME 1 
    34  
    35  
    36 class PrerenderAppCallback : public osg::NodeCallback 
     23#include <osg/CameraNode> 
     24#include <osg/TexGenNode> 
     25 
     26using namespace osg; 
     27 
     28 
     29ref_ptr<Group> _create_scene() 
     30{ 
     31  ref_ptr<Group> scene = new Group; 
     32  ref_ptr<Geode> geode_1 = new Geode; 
     33  scene->addChild(geode_1.get()); 
     34 
     35  ref_ptr<Geode> geode_2 = new Geode; 
     36  ref_ptr<MatrixTransform> transform_2 = new MatrixTransform; 
     37  transform_2->addChild(geode_2.get()); 
     38  transform_2->setUpdateCallback(new osgUtil::TransformCallback(Vec3(0, 0, 0), Y_AXIS, inDegrees(45.0f))); 
     39  scene->addChild(transform_2.get()); 
     40 
     41  ref_ptr<Geode> geode_3 = new Geode; 
     42  ref_ptr<MatrixTransform> transform_3 = new MatrixTransform; 
     43  transform_3->addChild(geode_3.get()); 
     44  transform_3->setUpdateCallback(new osgUtil::TransformCallback(Vec3(0, 0, 0), Y_AXIS, inDegrees(-22.5f))); 
     45  scene->addChild(transform_3.get()); 
     46 
     47  const float radius = 0.8f; 
     48  const float height = 1.0f; 
     49  ref_ptr<TessellationHints> hints = new TessellationHints; 
     50  hints->setDetailRatio(2.0f); 
     51  ref_ptr<ShapeDrawable> shape; 
     52 
     53  shape = new ShapeDrawable(new Box(Vec3(0.0f, -2.0f, 0.0f), 10, 0.1f, 10), hints.get()); 
     54  shape->setColor(Vec4(0.5f, 0.5f, 0.7f, 1.0f)); 
     55  geode_1->addDrawable(shape.get()); 
     56 
     57 
     58  shape = new ShapeDrawable(new Sphere(Vec3(-3.0f, 0.0f, 0.0f), radius), hints.get()); 
     59  shape->setColor(Vec4(0.6f, 0.8f, 0.8f, 1.0f)); 
     60  geode_2->addDrawable(shape.get()); 
     61 
     62  shape = new ShapeDrawable(new Box(Vec3(3.0f, 0.0f, 0.0f), 2 * radius), hints.get()); 
     63  shape->setColor(Vec4(0.4f, 0.9f, 0.3f, 1.0f)); 
     64  geode_2->addDrawable(shape.get()); 
     65 
     66  shape = new ShapeDrawable(new Cone(Vec3(0.0f, 0.0f, -3.0f), radius, height), hints.get()); 
     67  shape->setColor(Vec4(0.2f, 0.5f, 0.7f, 1.0f)); 
     68  geode_2->addDrawable(shape.get()); 
     69 
     70  shape = new ShapeDrawable(new Cylinder(Vec3(0.0f, 0.0f, 3.0f), radius, height), hints.get()); 
     71  shape->setColor(Vec4(1.0f, 0.3f, 0.3f, 1.0f)); 
     72  geode_2->addDrawable(shape.get()); 
     73 
     74  shape = new ShapeDrawable(new Box(Vec3(0.0f, 3.0f, 0.0f), 2, 0.1f, 2), hints.get()); 
     75  shape->setColor(Vec4(0.8f, 0.8f, 0.4f, 1.0f)); 
     76  geode_3->addDrawable(shape.get()); 
     77 
     78  // material 
     79  ref_ptr<Material> matirial = new Material; 
     80  matirial->setColorMode(Material::DIFFUSE); 
     81  matirial->setAmbient(Material::FRONT_AND_BACK, Vec4(0, 0, 0, 1)); 
     82  matirial->setSpecular(Material::FRONT_AND_BACK, Vec4(1, 1, 1, 1)); 
     83  matirial->setShininess(Material::FRONT_AND_BACK, 64.0f); 
     84  scene->getOrCreateStateSet()->setAttributeAndModes(matirial.get(), StateAttribute::ON); 
     85 
     86  return scene; 
     87} 
     88 
     89osg::RefNodePath createReflector() 
     90{ 
     91  ref_ptr<Group> scene = new Group; 
     92  ref_ptr<Geode> geode_1 = new Geode; 
     93  scene->addChild(geode_1.get()); 
     94 
     95  const float radius = 0.8f; 
     96  ref_ptr<TessellationHints> hints = new TessellationHints; 
     97  hints->setDetailRatio(2.0f); 
     98  ref_ptr<ShapeDrawable> shape = new ShapeDrawable(new Sphere(Vec3(0.0f, 0.0f, 0.0f), radius * 1.5f), hints.get()); 
     99  shape->setColor(Vec4(0.8f, 0.8f, 0.8f, 1.0f)); 
     100  geode_1->addDrawable(shape.get()); 
     101   
     102  osg::RefNodePath refNodeList; 
     103  refNodeList.push_back(scene.get()); 
     104  refNodeList.push_back(geode_1.get()); 
     105   
     106  return refNodeList; 
     107} 
     108 
     109class UpdateCameraAndTexGenCallback : public osg::NodeCallback 
    37110{ 
    38111    public: 
    39112     
    40         PrerenderAppCallback(osg::Node* subgraph): 
    41             _subgraph(subgraph) {} 
    42  
     113        typedef std::vector< osg::ref_ptr<osg::CameraNode> >  CameraList; 
     114 
     115        UpdateCameraAndTexGenCallback(osg::RefNodePath& reflectorNodePath, CameraList& cameraNodes): 
     116            _reflectorNodePath(reflectorNodePath), 
     117            _cameraNodes(cameraNodes) 
     118        { 
     119        } 
     120        
    43121        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 
    44122        { 
    45             // traverse the subgraph to update any nodes. 
    46             if (_subgraph.valid()) _subgraph->accept(*nv); 
    47          
    48             // must traverse the Node's subgraph             
     123            // first update subgraph to make sure objects are all moved into postion 
    49124            traverse(node,nv); 
     125             
     126            // compute the position of the center of the reflector subgraph 
     127            osg::Matrixd matrix = osg::computeLocalToWorld(_reflectorNodePath); 
     128            osg::BoundingSphere bs = _reflectorNodePath.back()->getBound(); 
     129            osg::Vec3 position = bs.center() * matrix; 
     130 
     131            typedef std::pair<osg::Vec3, osg::Vec3> ImageData; 
     132            const ImageData id[] = 
     133            { 
     134                ImageData( osg::Vec3( 1,  0,  0), osg::Vec3( 0, -1,  0) ), // +X 
     135                ImageData( osg::Vec3(-1,  0,  0), osg::Vec3( 0, -1,  0) ), // -X 
     136                ImageData( osg::Vec3( 0,  1,  0), osg::Vec3( 0,  0,  1) ), // +Y 
     137                ImageData( osg::Vec3( 0, -1,  0), osg::Vec3( 0,  0, -1) ), // -Y 
     138                ImageData( osg::Vec3( 0,  0,  1), osg::Vec3( 0, -1,  0) ), // +Z 
     139                ImageData( osg::Vec3( 0,  0, -1), osg::Vec3( 0, -1,  0) )  // -Z 
     140            }; 
     141 
     142            for(unsigned int i=0;  
     143                i<6 && i<_cameraNodes.size(); 
     144                ++i) 
     145            { 
     146                _cameraNodes[i]->setReferenceFrame(osg::CameraNode::ABSOLUTE_RF); 
     147                _cameraNodes[i]->setProjectionMatrixAsFrustum(-1.0,1.0,-1.0,1.0,1.0,10000.0); 
     148                _cameraNodes[i]->setViewMatrixAsLookAt(position,position+id[i].first,id[i].second); 
     149            } 
     150             
    50151        } 
    51152         
    52         osg::ref_ptr<osg::Node>     _subgraph; 
     153    protected: 
     154     
     155        virtual ~UpdateCameraAndTexGenCallback() {} 
     156         
     157        osg::RefNodePath            _reflectorNodePath;         
     158        CameraList                  _cameraNodes; 
    53159}; 
    54160 
    55  
    56 class PrerenderCullCallback : public osg::NodeCallback 
     161class TexMatCullCallback : public osg::NodeCallback 
    57162{ 
    58163    public: 
    59164     
    60         PrerenderCullCallback(osg::Node* subgraph, osg::TextureCubeMap* cubemap, osg::TexMat* texmat): 
    61             _subgraph(subgraph), 
    62             _cubemap(cubemap), 
     165        TexMatCullCallback(osg::TexMat* texmat): 
    63166            _texmat(texmat) 
    64             { 
    65                 _updateCubemapFace = 0; 
    66                 _clearColor = osg::Vec4(1,1,1,1); 
    67                 _localState[0] = new osg::StateSet; 
    68                 _localState[1] = new osg::StateSet; 
    69                 _localState[2] = new osg::StateSet; 
    70                 _localState[3] = new osg::StateSet; 
    71                 _localState[4] = new osg::StateSet; 
    72                 _localState[5] = new osg::StateSet; 
    73             } 
    74  
     167        { 
     168        } 
     169        
    75170        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 
    76171        { 
    77             // Reset this counter to zero, otherwise it wont do the while loop down below. 
    78             // And the cubemap will never update the newer frames. 
    79             if (_updateCubemapFace > 5) 
    80                 _updateCubemapFace = 0; 
    81  
     172            // first update subgraph to make sure objects are all moved into postion 
     173            traverse(node,nv); 
     174             
    82175            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv); 
    83             if (cv && _cubemap.valid() && _subgraph.valid()) 
     176            if (cv) 
    84177            { 
    85                 const osg::Vec4 clearColArray[] = 
    86                 { 
    87                     osg::Vec4(0, 0, 1, 1), // +X 
    88                     osg::Vec4(1, 0.7f, 0, 1), // -X 
    89                     osg::Vec4(0, 1, 1, 1), // +Y 
    90                     osg::Vec4(1, 1, 0, 1), // -Y 
    91                     osg::Vec4(1, 0, 0, 1), // +Z 
    92                     osg::Vec4(0, 1, 0, 1)  // -Z 
    93                 }; 
    94  
    95                 osg::Quat q; 
    96                 cv->getModelViewMatrix().get(q); 
    97                 const osg::Matrix C = osg::Matrix::rotate( q.inverse() ); 
    98                 _texmat->setMatrix(C); 
    99  
    100 #if UPDATE_ONE_IMAGE_PER_FRAME 
    101                 if ((_updateCubemapFace >= 0) && (_updateCubemapFace <= 5)) 
    102                 { 
    103                     _clearColor = clearColArray[_updateCubemapFace]; 
    104                     doPreRender(*node, *cv, _updateCubemapFace++); 
    105                 } 
    106 #else 
    107                 while (_updateCubemapFace<6) 
    108                 { 
    109                     _clearColor = clearColArray[_updateCubemapFace]; 
    110                     doPreRender(*node, *cv, _updateCubemapFace++); 
    111                 }     
    112 #endif 
     178                osg::Quat quat; 
     179                cv->getModelViewMatrix().get(quat); 
     180                _texmat->setMatrix(osg::Matrix::rotate(quat.inverse())); 
    113181            } 
     182        } 
     183         
     184    protected: 
     185     
     186        osg::ref_ptr<TexMat>    _texmat; 
     187}; 
     188 
     189 
     190osg::Group* createShadowedScene(osg::Node* reflectedSubgraph, osg::RefNodePath reflectorNodePath, unsigned int unit, const osg::Vec4& clearColor) 
     191{ 
     192 
     193    osg::Group* group = new osg::Group; 
     194     
     195    unsigned int tex_width = 512; 
     196    unsigned int tex_height = 512; 
     197     
     198    osg::TextureCubeMap* texture = new osg::TextureCubeMap; 
     199    texture->setTextureSize(tex_width, tex_height); 
     200 
     201    texture->setInternalFormat(GL_RGB); 
     202    texture->setFilter(osg::TextureCubeMap::MIN_FILTER,osg::TextureCubeMap::LINEAR); 
     203    texture->setFilter(osg::TextureCubeMap::MAG_FILTER,osg::TextureCubeMap::LINEAR); 
     204     
     205    // set up the render to texture cameras. 
     206    UpdateCameraAndTexGenCallback::CameraList cameraNodes; 
     207    for(unsigned int i=0; i<6; ++i) 
     208    { 
     209 
     210        // create the camera 
     211        osg::CameraNode* camera = new osg::CameraNode; 
     212 
     213        camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     214        camera->setClearColor(clearColor); 
     215 
     216        // set viewport 
     217        camera->setViewport(0,0,tex_width,tex_height); 
     218 
     219        // set the camera to render before the main camera. 
     220        camera->setRenderOrder(osg::CameraNode::PRE_RENDER); 
     221 
     222        // tell the camera to use OpenGL frame buffer object where supported. 
     223        camera->setRenderTargetImplmentation(osg::CameraNode::FRAME_BUFFER_OBJECT); 
     224 
     225        // attach the texture and use it as the color buffer. 
     226        camera->attach(osg::CameraNode::COLOR_BUFFER, texture, 0, i); 
     227 
     228        // add subgraph to render 
     229        camera->addChild(reflectedSubgraph); 
     230         
     231        group->addChild(camera); 
     232         
     233        cameraNodes.push_back(camera); 
     234    } 
     235    
     236    // create the texgen node to project the tex coords onto the subgraph 
     237    osg::TexGenNode* texgenNode = new osg::TexGenNode; 
     238    texgenNode->getTexGen()->setMode(osg::TexGen::REFLECTION_MAP); 
     239    texgenNode->setTextureUnit(unit); 
     240    group->addChild(texgenNode); 
     241 
     242    // set the reflected subgraph so that it uses the texture and tex gen settings.     
     243    { 
     244        osg::Node* reflectorNode = reflectorNodePath.front().get(); 
     245        group->addChild(reflectorNode); 
    114246                 
    115             // must traverse the subgraph             
    116             traverse(node,nv); 
    117         } 
    118             
    119         void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv, const int nFace); 
    120          
    121         struct ImageData 
    122         { 
    123             ImageData(const osg::Vec3& dir, const osg::Vec3& up) : _dir(dir), _up(up) {} 
    124             osg::Vec3 _dir; 
    125             osg::Vec3 _up; 
    126         }; 
    127  
    128         osg::ref_ptr<osg::Node> _subgraph; 
    129         osg::ref_ptr<osg::TextureCubeMap> _cubemap; 
    130         osg::ref_ptr<osg::StateSet> _localState[6]; 
    131         osg::ref_ptr<osg::TexMat> _texmat; 
    132         osg::Vec4 _clearColor; 
    133         int _updateCubemapFace; 
    134 }; 
    135  
    136  
    137 void PrerenderCullCallback::doPreRender(osg::Node& /*node*/, osgUtil::CullVisitor& cv, const int nFace) 
    138 { 
    139     const ImageData id[] = 
    140     { 
    141         ImageData( osg::Vec3( 1,  0,  0), osg::Vec3( 0, -1,  0) ), // +X 
    142         ImageData( osg::Vec3(-1,  0,  0), osg::Vec3( 0, -1,  0) ), // -X 
    143         ImageData( osg::Vec3( 0,  1,  0), osg::Vec3( 0,  0,  1) ), // +Y 
    144         ImageData( osg::Vec3( 0, -1,  0), osg::Vec3( 0,  0, -1) ), // -Y 
    145         ImageData( osg::Vec3( 0,  0,  1), osg::Vec3( 0, -1,  0) ), // +Z 
    146         ImageData( osg::Vec3( 0,  0, -1), osg::Vec3( 0, -1,  0) )  // -Z 
    147     }; 
    148  
    149     osg::Image* image = _cubemap->getImage((osg::TextureCubeMap::Face)nFace); 
    150     osg::Vec3 dir = id[nFace]._dir; 
    151     osg::Vec3 up  = id[nFace]._up; 
    152  
    153     const osg::BoundingSphere& bs = _subgraph->getBound(); 
    154     if (!bs.valid()) 
    155     { 
    156         osg::notify(osg::WARN) << "bb invalid"<<_subgraph.get()<<std::endl; 
    157         return; 
    158     } 
    159  
    160     // create the render to texture stage. 
    161     osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage; 
    162  
    163     // set up lighting. 
    164     // currently ignore lights in the scene graph itself.. 
    165     // will do later. 
    166     osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->getStage(); 
    167  
    168     // set up the background color and clear mask. 
    169     rtts->setClearColor(_clearColor); 
    170  
    171     // ABJ: use default (color+depth) 
    172     rtts->setClearMask(previous_stage->getClearMask()); 
    173  
    174     // set up to charge the same RenderStageLighting is the parent previous stage. 
    175     rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); 
    176  
    177     // record the render bin, to be restored after creation 
    178     // of the render to text 
    179     osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin(); 
    180  
    181     // set the current renderbin to be the newly created stage. 
    182     cv.setCurrentRenderBin(rtts.get()); 
    183  
    184  
    185     float znear = 1.0f*bs.radius(); 
    186     float zfar  = 3.0f*bs.radius(); 
    187          
    188     znear *= 0.9f; 
    189     zfar *= 1.1f; 
    190  
    191     // set up projection. 
    192     const double fovy = 90.0; 
    193     const double aspectRatio = 1.0; 
    194     osg::RefMatrix* projection = new osg::RefMatrix; 
    195     projection->makePerspective(fovy, aspectRatio, znear, zfar); 
    196  
    197     cv.pushProjectionMatrix(projection); 
    198  
    199     osg::RefMatrix* matrix = new osg::RefMatrix; 
    200     osg::Vec3 eye    = bs.center(); eye.z() = 0.0f; 
    201     osg::Vec3 center = eye + dir; 
    202     matrix->makeLookAt(eye, center, up); 
    203  
    204     cv.pushModelViewMatrix(matrix); 
    205  
    206     cv.pushStateSet(_localState[nFace].get()); 
    207  
    208     { 
    209         // traverse the subgraph 
    210         _subgraph->accept(cv); 
    211     } 
    212  
    213     cv.popStateSet(); 
    214  
    215     // restore the previous model view matrix. 
    216     cv.popModelViewMatrix(); 
    217  
    218     // restore the previous model view matrix. 
    219     cv.popProjectionMatrix(); 
    220  
    221     // restore the previous renderbin. 
    222     cv.setCurrentRenderBin(previousRenderBin); 
    223  
    224     if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0) 
    225     { 
    226         // getting to this point means that all the subgraph has been 
    227         // culled by small feature culling or is beyond LOD ranges. 
    228         return; 
    229     } 
    230  
    231     int height = 512; 
    232     int width  = 512; 
    233  
    234     const osg::Viewport& viewport = *cv.getViewport(); 
    235  
    236     // offset the impostor viewport from the center of the main window 
    237     // viewport as often the edges of the viewport might be obscured by 
    238     // other windows, which can cause image/reading writing problems. 
    239     int center_x = viewport.x()+viewport.width()/2; 
    240     int center_y = viewport.y()+viewport.height()/2; 
    241  
    242     osg::Viewport* new_viewport = new osg::Viewport; 
    243     new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height); 
    244     rtts->setViewport(new_viewport); 
    245      
    246     _localState[nFace]->setAttribute(new_viewport); 
    247  
    248     // and the render to texture stage to the current stages 
    249     // dependancy list. 
    250     cv.getCurrentRenderBin()->getStage()->addToDependencyList(rtts.get()); 
    251  
    252     // if one exist attach image to the RenderToTextureStage. 
    253     // if (image.valid()) rtts->setImage(_image.get()); 
    254     if (image) rtts->setImage(image); 
     247        osg::StateSet* stateset = reflectorNode->getOrCreateStateSet(); 
     248        stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON); 
     249        stateset->setTextureMode(unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); 
     250        stateset->setTextureMode(unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); 
     251        stateset->setTextureMode(unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); 
     252        stateset->setTextureMode(unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); 
     253 
     254        osg::TexMat* texmat = new osg::TexMat; 
     255        stateset->setTextureAttributeAndModes(unit,texmat,osg::StateAttribute::ON); 
     256         
     257        reflectorNode->setCullCallback(new TexMatCullCallback(texmat)); 
     258    } 
     259     
     260    // add the reflector scene to draw just as normal 
     261    group->addChild(reflectedSubgraph); 
     262     
     263    // set an update callback to keep moving the camera and tex gen in the right direction. 
     264    group->setUpdateCallback(new UpdateCameraAndTexGenCallback(reflectorNodePath, cameraNodes)); 
     265 
     266    return group; 
    255267} 
    256268 
    257269 
    258 osg::Drawable* makeGeometry() 
    259 { 
    260     const float radius = 20; 
    261     return new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius)); 
    262 } 
    263  
    264 osg::Node* createPreRenderSubGraph(osg::Node* subgraph) 
    265 { 
    266     if (!subgraph) return 0; 
    267   
    268     // create the quad to visualize. 
    269     osg::Drawable* geom = makeGeometry(); 
    270     geom->setSupportsDisplayList(false); 
    271  
    272     // new we need to add the texture to the Drawable, we do so by creating a  
    273     // StateSet to contain the Texture StateAttribute. 
    274     osg::StateSet* stateset = new osg::StateSet; 
    275  
    276     osg::TextureCubeMap* cubemap = new osg::TextureCubeMap; 
    277  
    278     // set up the textures 
    279     osg::Image* imagePosX = new osg::Image; 
    280     osg::Image* imageNegX = new osg::Image; 
    281     osg::Image* imagePosY = new osg::Image; 
    282     osg::Image* imageNegY = new osg::Image; 
    283     osg::Image* imagePosZ = new osg::Image; 
    284     osg::Image* imageNegZ = new osg::Image; 
    285  
    286     imagePosX->setInternalTextureFormat(GL_RGB); 
    287     imageNegX->setInternalTextureFormat(GL_RGB); 
    288     imagePosY->setInternalTextureFormat(GL_RGB); 
    289     imageNegY->setInternalTextureFormat(GL_RGB); 
    290     imagePosZ->setInternalTextureFormat(GL_RGB); 
    291     imageNegZ->setInternalTextureFormat(GL_RGB); 
    292  
    293     cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX); 
    294     cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX); 
    295     cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY); 
    296     cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY); 
    297     cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ); 
    298     cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ); 
    299  
    300     cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 
    301     cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 
    302     cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 
    303     cubemap->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
    304     cubemap->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); 
    305     stateset->setTextureAttributeAndModes(0, cubemap, osg::StateAttribute::ON); 
    306  
    307     osg::TexGen *texgen = new osg::TexGen; 
    308     texgen->setMode(osg::TexGen::REFLECTION_MAP); 
    309     stateset->setTextureAttributeAndModes(0, texgen, osg::StateAttribute::ON); 
    310  
    311     osg::TexMat* texmat = new osg::TexMat; 
    312     stateset->setTextureAttribute(0, texmat); 
    313  
    314     stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); 
    315  
    316     geom->setStateSet(stateset); 
    317  
    318     osg::Geode* geode = new osg::Geode; 
    319     geode->addDrawable(geom); 
    320  
    321     // Geodes can't have cull callback so create extra Group to attach cullcallback. 
    322     osg::Group* parent = new osg::Group; 
    323      
    324     parent->setUpdateCallback(new PrerenderAppCallback(subgraph)); 
    325      
    326     parent->setCullCallback(new PrerenderCullCallback(subgraph, cubemap, texmat)); 
    327   
    328     parent->addChild(geode); 
    329      
    330     return parent; 
    331 } 
    332  
    333  
    334 struct DrawableCullCallback : public osg::Drawable::CullCallback 
    335 { 
    336     DrawableCullCallback(osg::TexMat* texmat) : _texmat(texmat) 
    337     {} 
    338  
    339     virtual bool cull(osg::NodeVisitor* nv, osg::Drawable* /*drawable*/, osg::State* /*state*/) const 
    340     { 
    341         osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv); 
    342         if (cv) 
    343         { 
    344             osg::Quat q; 
    345             cv->getModelViewMatrix().get(q); 
    346             const osg::Matrix C = osg::Matrix::rotate( q.inverse() ); 
    347             _texmat->setMatrix(C); 
    348         } 
    349         return false; 
    350     } 
    351  
    352     mutable osg::ref_ptr<osg::TexMat> _texmat; 
    353 }; 
    354  
    355 osg::Node* createReferenceSphere() 
    356 { 
    357     const float radius = 10; 
    358     osg::Drawable* sphere = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius)); 
    359  
    360     osg::StateSet* stateset = new osg::StateSet; 
    361     sphere->setStateSet(stateset); 
    362  
    363     osg::TextureCubeMap* cubemap = new osg::TextureCubeMap; 
    364     #define CUBEMAP_FILENAME(face) "Cubemap_axis/" #face ".png" 
    365  
    366     osg::Image* imagePosX = osgDB::readImageFile(CUBEMAP_FILENAME(posx)); 
    367     osg::Image* imageNegX = osgDB::readImageFile(CUBEMAP_FILENAME(negx)); 
    368     osg::Image* imagePosY = osgDB::readImageFile(CUBEMAP_FILENAME(posy)); 
    369     osg::Image* imageNegY = osgDB::readImageFile(CUBEMAP_FILENAME(negy)); 
    370     osg::Image* imagePosZ = osgDB::readImageFile(CUBEMAP_FILENAME(posz)); 
    371     osg::Image* imageNegZ = osgDB::readImageFile(CUBEMAP_FILENAME(negz)); 
    372  
    373     if (imagePosX && imageNegX && imagePosY && imageNegY && imagePosZ && imageNegZ) 
    374     { 
    375         cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX); 
    376         cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX); 
    377         cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY); 
    378         cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY); 
    379         cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ); 
    380         cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ); 
    381  
    382         cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 
    383         cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 
    384         cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 
    385         cubemap->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
    386         cubemap->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); 
    387         stateset->setTextureAttributeAndModes(0, cubemap, osg::StateAttribute::ON); 
    388     } 
    389  
    390     osg::TexGen *texgen = new osg::TexGen; 
    391     texgen->setMode(osg::TexGen::REFLECTION_MAP); 
    392     stateset->setTextureAttributeAndModes(0, texgen, osg::StateAttribute::ON); 
    393  
    394     osg::TexMat* texmat = new osg::TexMat; 
    395     stateset->setTextureAttribute(0, texmat); 
    396  
    397     stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); 
    398  
    399  
    400     sphere->setCullCallback(new DrawableCullCallback(texmat)); 
    401  
    402     osg::Geode* geode = new osg::Geode(); 
    403     geode->addDrawable(sphere); 
    404  
    405     return geode; 
    406 } 
    407  
    408 int main( int argc, char **argv ) 
     270int main(int argc, char** argv) 
    409271{ 
    410272    // use an ArgumentParser object to manage the program arguments. 
    411     osg::ArgumentParser arguments(&argc,argv); 
     273    ArgumentParser arguments(&argc, argv); 
    412274 
    413275    // set up the usage document, in case we need to print out how to use this program. 
    414     arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates pre rendering of scene to a texture, and then apply this texture to geometry."); 
    415     arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); 
    416     arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); 
    417     
     276    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class"); 
     277    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()); 
     278    arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information"); 
     279 
    418280    // construct the viewer. 
    419281    osgProducer::Viewer viewer(arguments); 
     
    423285 
    424286    // get details on keyboard and mouse bindings used by the viewer. 
    425     viewer.getUsage(*arguments.getApplicationUsage()); 
     287    viewer.getUsage(*arguments. getApplicationUsage()); 
    426288 
    427289    // if user request help write it out to cout. 
     
    438300    if (arguments.errors()) 
    439301    { 
    440         arguments.writeErrorMessages(std::cout); 
    441         return 1; 
    442     } 
    443 /*     
    444     if (arguments.argc()<=1) 
    445     { 
    446         arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); 
    447         return 1; 
    448     } 
    449 */ 
    450      
    451     osg::Group* rootNode = new osg::Group(); 
    452  
    453 #if 1 
    454     osg::Node* sky = osgDB::readNodeFile("skydome.osg"); 
    455  
    456     // Proof of concept to see if the skydome really rotates and that the cubemap gets updated. 
    457     // create a transform to spin the model. 
    458      
    459     osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform; 
    460     loadedModelTransform->addChild(sky); 
    461  
    462     osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(5.0f)); 
    463     loadedModelTransform->setUpdateCallback(nc); 
    464  
    465     // osg::Group* rootNode = new osg::Group(); 
    466     // rootNode->addChild(loadedModelTransform); 
    467     // rootNode->addChild(createPreRenderSubGraph(loadedModelTransform)); 
    468  
    469  
    470     if (loadedModelTransform) 
    471     {     
    472         rootNode->addChild(createPreRenderSubGraph(loadedModelTransform)); 
    473     } 
    474 #endif 
    475  
    476 #if 1 
    477     osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; 
    478     pat->setPosition(osg::Vec3(0,0,50)); 
    479     pat->addChild(createReferenceSphere()); 
    480     rootNode->addChild(pat); 
    481 #endif 
    482  
    483     // load the nodes from the commandline arguments. 
    484     osg::Node* loadedModel = osgDB::readNodeFiles(arguments); 
    485     if (loadedModel) 
    486         rootNode->addChild(loadedModel); 
    487  
    488     // add model to the viewer. 
    489     viewer.setSceneData( rootNode ); 
     302      arguments.writeErrorMessages(std::cout); 
     303      return 1; 
     304    } 
     305 
     306    ref_ptr<MatrixTransform> scene = new MatrixTransform; 
     307    scene->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(125.0),1.0,0.0,0.0)); 
     308 
     309    ref_ptr<Group> reflectedSubgraph = _create_scene();     
     310    if (!reflectedSubgraph.valid()) return 1; 
     311 
     312    ref_ptr<Group> reflectedScene = createShadowedScene(reflectedSubgraph.get(),createReflector(),0, viewer.getClearColor()); 
     313 
     314    scene->addChild(reflectedScene.get()); 
     315 
     316    viewer.setSceneData(scene.get()); 
    490317 
    491318    // create the windows and run the threads. 
    492319    viewer.realize(); 
    493320 
    494     while( !viewer.done() ) 
    495     { 
    496         // wait for all cull and draw threads to complete. 
    497         viewer.sync(); 
    498  
    499         // update the scene by traversing it with the the update visitor which will 
    500         // call all node update callbacks and animations. 
    501         viewer.update(); 
     321    while (!viewer.done()) 
     322    { 
     323      // wait for all cull and draw threads to complete. 
     324      viewer.sync(); 
     325 
     326      // update the scene by traversing it with the the update visitor which will 
     327      // call all node update callbacks and animations. 
     328      viewer.update(); 
    502329          
    503         // fire off the cull and draw traversals of the scene. 
    504         viewer.frame(); 
    505          
     330      // fire off the cull and draw traversals of the scene. 
     331      viewer.frame(); 
    506332    } 
    507333     
     
    511337    return 0; 
    512338} 
    513