Hi Robert,

attached is slighly modified and corrected example with multitexturing with
prerendered cubemaps. There was an issue with the uniforms that are cube
samplers. also, it has the correct OpenGL coordinate system now. I think it
should replace the existing example. I spent one day to figure things for
real application out of this example and believe some one else could benefit
from it

Nick

http://www.linkedin.com/in/tnick
/* OpenSceneGraph example, osgprerendercubemap.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

#include <osgViewer/Viewer>

#include <osg/Projection>
#include <osg/Geometry>
#include <osg/Texture>
#include <osg/TexGen>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/PolygonOffset>
#include <osg/CullFace>
#include <osg/TextureCubeMap>
#include <osg/TexMat>
#include <osg/MatrixTransform>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/PolygonOffset>
#include <osg/CullFace>
#include <osg/Material>
#include <osg/PositionAttitudeTransform>
#include <osg/ArgumentParser>

#include <osgDB/ReadFile>

#include <osgUtil/SmoothingVisitor>

#include <osg/Camera>
#include <osg/TexGenNode>
#include <osg/Texture2D>

#include <iostream>

using namespace osg;

unsigned int numTextures = 6;

ref_ptr<Group> _create_scene()
{
  ref_ptr<Group> scene = new Group;
  ref_ptr<Geode> geode_1 = new Geode;
  scene->addChild(geode_1.get());

  ref_ptr<Geode> geode_2 = new Geode;
  ref_ptr<MatrixTransform> transform_2 = new MatrixTransform;
  transform_2->addChild(geode_2.get());
  transform_2->setUpdateCallback(new osg::AnimationPathCallback(Vec3(0, 0, 0), 
Z_AXIS, inDegrees(45.0f)));
  scene->addChild(transform_2.get());

  ref_ptr<Geode> geode_3 = new Geode;
  ref_ptr<MatrixTransform> transform_3 = new MatrixTransform;
  transform_3->addChild(geode_3.get());
  transform_3->setUpdateCallback(new osg::AnimationPathCallback(Vec3(0, 0, 0), 
Z_AXIS, inDegrees(-22.5f)));
  scene->addChild(transform_3.get());

  const float radius = 0.8f;
  const float height = 1.0f;
  ref_ptr<TessellationHints> hints = new TessellationHints;
  hints->setDetailRatio(2.0f);
  ref_ptr<ShapeDrawable> shape;

  shape = new ShapeDrawable(new Box(Vec3(0.0f, 0.0f, -2.0f), 10, 10.f, 0.1), 
hints.get());
  shape->setColor(Vec4(0.5f, 0.5f, 0.7f, 1.0f));
  geode_1->addDrawable(shape.get());


  shape = new ShapeDrawable(new Sphere(Vec3(-3.0f, 0.0f, 0.0f), radius), 
hints.get());
  shape->setColor(Vec4(0.6f, 0.8f, 0.8f, 1.0f));
  geode_2->addDrawable(shape.get());

  shape = new ShapeDrawable(new Box(Vec3(3.0f, 0.0f, 0.0f), 2 * radius), 
hints.get());
  shape->setColor(Vec4(0.4f, 0.9f, 0.3f, 1.0f));
  geode_2->addDrawable(shape.get());

#if 0
  shape = new ShapeDrawable(new Cone(Vec3(0.0f, 0.0f, -3.0f), radius, height), 
hints.get());
  shape->setColor(Vec4(0.2f, 0.5f, 0.7f, 1.0f));
  geode_2->addDrawable(shape.get());
#endif

  shape = new ShapeDrawable(new Cylinder(Vec3(0.0f, 0.0f, 3.0f), radius, 
height), hints.get());
  shape->setColor(Vec4(1.0f, 0.3f, 0.3f, 1.0f));
  geode_2->addDrawable(shape.get());

  shape = new ShapeDrawable(new Box(Vec3(0.0f, 3.0f, 0.0f), 2, 0.1f, 2), 
hints.get());
  shape->setColor(Vec4(0.8f, 0.8f, 0.4f, 1.0f));
  geode_3->addDrawable(shape.get());

  // material
  ref_ptr<Material> matirial = new Material;
  matirial->setColorMode(Material::DIFFUSE);
  matirial->setAmbient(Material::FRONT_AND_BACK, Vec4(0, 0, 0, 1));
  matirial->setSpecular(Material::FRONT_AND_BACK, Vec4(1, 1, 1, 1));
  matirial->setShininess(Material::FRONT_AND_BACK, 64.0f);
  scene->getOrCreateStateSet()->setAttributeAndModes(matirial.get(), 
StateAttribute::ON);

  return scene;
}

osg::NodePath createReflector()
{
  osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform;
  pat->setPosition(osg::Vec3(0.0f,0.0f,0.0f));
  pat->setAttitude(osg::Quat(osg::inDegrees(0.0f),osg::Vec3(0.0f,0.0f,1.0f)));
  
#if 1
  Geode* node = new Geode;
  const float radius = 0.8f;
  ref_ptr<TessellationHints> hints = new TessellationHints;
  hints->setDetailRatio(2.0f);
  ShapeDrawable* shape = new ShapeDrawable(new Sphere(Vec3(0.0f, 0.0f, 0.0f), 
radius * 1.5f), hints.get());
  shape->setColor(Vec4(0.8f, 0.8f, 0.8f, 1.0f));
  node->addDrawable(shape);
#else
  osg::Node* file = osgDB::readNodeFile("D:\\dev\\POTSIM3D\\DATA\\B700.ive");
  osgUtil::SmoothingVisitor sv;
  file->accept(sv);

  osg::MatrixTransform* node = new osg::MatrixTransform;
  node->addChild(file);
  node->setMatrix(osg::Matrix::scale(osg::Vec3(0.25,0.25,0.25)));
#endif
  
  pat->addChild(node);

  osg::NodePath nodeList;
  nodeList.push_back(pat);
  nodeList.push_back(node);
  //nodeList.push_back(file);

  
  return nodeList;
}

class UpdateCameraAndTexGenCallback : public osg::NodeCallback
{
    public:
    
        typedef std::vector< osg::ref_ptr<osg::Camera> >  CameraList;

        UpdateCameraAndTexGenCallback(osg::NodePath& reflectorNodePath, 
CameraList& Cameras):
            _reflectorNodePath(reflectorNodePath),
            _Cameras(Cameras)
        {
        }
       
        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
        {
            // first update subgraph to make sure objects are all moved into 
position
            traverse(node,nv);

            // compute the position of the center of the reflector subgraph
            osg::Matrixd worldToLocal = 
osg::computeWorldToLocal(_reflectorNodePath);
            osg::BoundingSphere bs = _reflectorNodePath.back()->getBound();
            osg::Vec3 position = bs.center();

            typedef std::pair<osg::Vec3, osg::Vec3> ImageData;
            const ImageData id[] =
            {
                ImageData( osg::Vec3( 1,  0,  0), osg::Vec3( 0, -1,  0) ), // +X
                ImageData( osg::Vec3(-1,  0,  0), osg::Vec3( 0, -1,  0) ), // -X
                ImageData( osg::Vec3( 0,  1,  0), osg::Vec3( 0,  0,  1) ), // +Y
                ImageData( osg::Vec3( 0, -1,  0), osg::Vec3( 0,  0, -1) ), // -Y
                ImageData( osg::Vec3( 0,  0,  1), osg::Vec3( 0, -1,  0) ), // +Z
                ImageData( osg::Vec3( 0,  0, -1), osg::Vec3( 0, -1,  0) )  // -Z
            };

            for(unsigned int i=0; 
                i<numTextures && i<_Cameras.size();
                ++i)
            {
                osg::Matrix localOffset;
                
localOffset.makeLookAt(position,position+id[i].first,id[i].second);
                
                osg::Matrix viewMatrix = worldToLocal*localOffset;
            
                _Cameras[i]->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
                
_Cameras[i]->setProjectionMatrixAsFrustum(-1.0,1.0,-1.0,1.0,1.0,10000.0);
                _Cameras[i]->setViewMatrix(viewMatrix);
            }
        }
        
    protected:
    
        virtual ~UpdateCameraAndTexGenCallback() {}
        
        osg::NodePath               _reflectorNodePath;        
        CameraList                  _Cameras;
};

class TexMatCullCallback : public osg::NodeCallback
{
    public:
    
        TexMatCullCallback(osg::TexMat* texmat):
            _texmat(texmat)
        {
        }
       
        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
        {
            // first update subgraph to make sure objects are all moved into 
position
            traverse(node,nv);
            
            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cv)
            {
                                osg::Quat q = 
osg::Matrix::inverse(*cv->getModelViewMatrix()).getRotate();


                                float yaw2 = asin(-2.0f*(q.x()*q.z() - 
q.w()*q.y()));
                                osg::Matrixd mxY;
                                mxY.makeRotate(yaw2,osg::Vec3(0,0,1));

                                osg::Matrixd mx = mxY;
                _texmat->setMatrix(mx);
            }
        }
        
    protected:
    
        osg::ref_ptr<TexMat>    _texmat;
};

class UpdateCameraPosUniformCallback : public osg::Uniform::Callback
{
public:
        UpdateCameraPosUniformCallback(osg::Camera* camera)
                : mCamera(camera)
        {
        }

        virtual void operator () (osg::Uniform* u, osg::NodeVisitor*)
        {
                osg::Vec3 eye;
                osg::Vec3 center;
                osg::Vec3 up;
                mCamera->getViewMatrixAsLookAt(eye,center,up);

                u->set(eye);
        }
protected:
        osg::Camera* mCamera;
};


osg::Group* createShadowedScene(osg::Node* reflectedSubgraph, osg::NodePath 
reflectorNodePath, unsigned int unit, const osg::Vec4& clearColor, unsigned 
tex_width, unsigned tex_height, osg::Camera::RenderTargetImplementation 
renderImplementation, osg::Camera* camera = 0)
{

    osg::Group* group = new osg::Group;
    
    osg::TextureCubeMap* texture = new osg::TextureCubeMap;
    texture->setTextureSize(tex_width, tex_height);

    texture->setInternalFormat(GL_RGB);
    texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
    texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
    texture->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
    
texture->setFilter(osg::TextureCubeMap::MIN_FILTER,osg::TextureCubeMap::LINEAR);
    
texture->setFilter(osg::TextureCubeMap::MAG_FILTER,osg::TextureCubeMap::LINEAR);
    
    // set up the render to texture cameras.
    UpdateCameraAndTexGenCallback::CameraList Cameras;
    for(unsigned int i=0; i<numTextures; ++i)
    {
        // create the camera
        osg::Camera* camera = new osg::Camera;

        camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        camera->setClearColor(clearColor);

        // set viewport
        camera->setViewport(0,0,tex_width,tex_height);

        // set the camera to render before the main camera.
        camera->setRenderOrder(osg::Camera::PRE_RENDER);

        // tell the camera to use OpenGL frame buffer object where supported.
        camera->setRenderTargetImplementation(renderImplementation);

        // attach the texture and use it as the color buffer.
        camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, i);

        // add subgraph to render
        camera->addChild(reflectedSubgraph);
        
        group->addChild(camera);
        
        Cameras.push_back(camera);
    }
   
#if 1
    // create the texgen node to project the tex coords onto the subgraph
    osg::TexGenNode* texgenNode = new osg::TexGenNode;
    texgenNode->getTexGen()->setMode(osg::TexGen::REFLECTION_MAP);
    texgenNode->setTextureUnit(unit);
    group->addChild(texgenNode);

    // set the reflected subgraph so that it uses the texture and tex gen 
settings. 
        osg::Node* reflectorNode = reflectorNodePath.front();
    {
        
        group->addChild(reflectorNode);

                osg::StateSet* stateset = reflectorNode->getOrCreateStateSet();
#if 0
                
        
                
stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
        
stateset->setTextureMode(unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
        
stateset->setTextureMode(unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
        
stateset->setTextureMode(unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
        
stateset->setTextureMode(unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);

        osg::TexMat* texmat = new osg::TexMat;
        
stateset->setTextureAttributeAndModes(unit,texmat,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
        
        reflectorNode->setCullCallback(new TexMatCullCallback(texmat));
#else
                
stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
#endif
    }

        osg::StateSet* ss = reflectorNode->getOrCreateStateSet();
        
ss->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);

                const char* microshaderVertSource = 
                                "uniform mat4 osg_ViewMatrixInverse;    \n"
                                "uniform vec3 CameraPos;                        
        \n" //
                                "mat3 GetLinearPart( mat4 m )                   
\n" //
                                "{                                              
                                \n" //
                                "       mat3 result;                            
                \n" //
                                "                                               
                                \n" //
                                "       result[0][0] = m[0][0];                 
        \n" //  
                                "       result[0][1] = m[0][1];                 
        \n" //
                                "       result[0][2] = m[0][2];                 
        \n" //
                                "                                               
                                \n" //
                                "       result[1][0] = m[1][0];                 
        \n" //
                                "       result[1][1] = m[1][1];                 
        \n" //
                                "       result[1][2] = m[1][2];                 
        \n" //
                                "                                               
                                \n" //
                                "       result[2][0] = m[2][0];                 
        \n" //
                                "       result[2][1] = m[2][1];                 
        \n" //
                                "       result[2][2] = m[2][2];                 
        \n" //
                                "                                               
                                \n" //
                                "       return result;                          
                \n" //
                                "}                                              
                                \n" //  
                                "                                               
                                \n" //
                                "void main()                                    
                \n" //  
                                "{                                              
                                \n" //
                                "       gl_Position = ftransform();             
        \n" //
                                "                                               
                                                                \n" //
                                "       gl_TexCoord[0] = gl_MultiTexCoord0;     
                                \n" //  
                                "   mat4 ModelWorld4x4 = osg_ViewMatrixInverse 
* gl_ModelViewMatrix;    \n" //
                                "                                               
                                                                \n" //
                                "       mat3 ModelWorld3x3 = GetLinearPart( 
ModelWorld4x4 );    \n" //
                                "                                               
                                                                \n" //
                                "       vec4 WorldPos = ModelWorld4x4 *  
gl_Vertex;                     \n" //
                                "                                               
                                                                \n" //
                                "       vec3 N = normalize( ModelWorld3x3 * 
gl_Normal );        \n" //
                                "                                               
                                                                \n" //
                                "       vec3 E = normalize( WorldPos.xyz - 
CameraPos.xyz );     \n" //  
                                "                                               
                                                                \n" //
                                "       gl_TexCoord[1].xyz = reflect( E, N );   
                        \n" //
                                "}                                              
                                                                \n" //
                                ;
                        const char* microshaderFragSource = 
                                "uniform samplerCube cubeMap;                   
                                                                        \n"
                                "uniform sampler2D colorMap;                    
                                                                        \n"
                                "                                               
                                                                                
                        \n"
                                "const float reflect_factor = 0.5;              
                                                                        \n"
                                "                                               
                                                                                
                        \n"
                                "void main (void)                               
                                                                                
        \n"
                                "{                                              
                                                                                
                        \n"
                                "       vec3 base_color = texture2D(colorMap, 
gl_TexCoord[0].xy).rgb;                   \n"
                                "                                               
                                                                                
                        \n"
                                "       vec3 cube_color = textureCube(cubeMap, 
gl_TexCoord[1].xyz).rgb;                 \n"
                                "                                               
                                                                                
                        \n"
                                "       gl_FragColor = vec4( mix(cube_color, 
base_color, reflect_factor).rgb, 1.0);     \n"
                                "       //gl_FragColor = vec4( 1,1,1, 1.0);     
\n"
                                "}                                              
                                                                                
                        \n"             
                                ;


        osg::Program* program = new osg::Program;
    program->setName( "microshader" );
    program->addShader( new osg::Shader( osg::Shader::VERTEX, 
microshaderVertSource ) );
    program->addShader( new osg::Shader( osg::Shader::FRAGMENT, 
microshaderFragSource ) );
    ss->setAttributeAndModes( program, osg::StateAttribute::ON );
        ss->addUniform( new osg::Uniform("colorMap",0) );

        {
                osg::Uniform* u = new osg::Uniform("CameraPos",osg::Vec3());
                u->setUpdateCallback( new UpdateCameraPosUniformCallback( 
camera ) );
                ss->addUniform( u );
        }
        {
                osg::Uniform* u = new osg::Uniform(osg::Uniform::SAMPLER_CUBE, 
"cubeMap");
                u->set(1);
                ss->addUniform( u );
        }
#endif

        osg::Texture2D * texture0 =  new 
osg::Texture2D(osgDB::readImageFile("Images/skymap.jpg") );
    ss->setTextureAttributeAndModes( 0, texture0, osg::StateAttribute::ON );

    // add the reflector scene to draw just as normal
    group->addChild(reflectedSubgraph);
    
    // set an update callback to keep moving the camera and tex gen in the 
right direction.
    group->setUpdateCallback(new 
UpdateCameraAndTexGenCallback(reflectorNodePath, Cameras));

    return group;
}


int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    ArgumentParser arguments(&argc, argv);

    // set up the usage document, in case we need to print out how to use this 
program.
    
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() 
+ " is the example which demonstrates using of GL_ARB_shadow extension 
implemented in osg::Texture class");
    
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help", 
"Display this information");
    arguments.getApplicationUsage()->addCommandLineOption("--fbo","Use Frame 
Buffer Object for render to texture, where supported.");
    arguments.getApplicationUsage()->addCommandLineOption("--fb","Use 
FrameBuffer for render to texture.");
    arguments.getApplicationUsage()->addCommandLineOption("--pbuffer","Use 
Pixel Buffer for render to texture, where supported.");
    arguments.getApplicationUsage()->addCommandLineOption("--window","Use a 
separate Window for render to texture.");
    arguments.getApplicationUsage()->addCommandLineOption("--width","Set the 
width of the render to texture");
    arguments.getApplicationUsage()->addCommandLineOption("--height","Set the 
height of the render to texture");

    // construct the viewer.
    osgViewer::Viewer viewer;

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }
    
    unsigned tex_width = 256;
    unsigned tex_height = 256;
    while (arguments.read("--width", tex_width)) {}
    while (arguments.read("--height", tex_height)) {}

    osg::Camera::RenderTargetImplementation renderImplementation = 
osg::Camera::FRAME_BUFFER_OBJECT;
    
    while (arguments.read("--fbo")) { renderImplementation = 
osg::Camera::FRAME_BUFFER_OBJECT; }
    while (arguments.read("--pbuffer")) { renderImplementation = 
osg::Camera::PIXEL_BUFFER; }
    while (arguments.read("--fb")) { renderImplementation = 
osg::Camera::FRAME_BUFFER; }
    while (arguments.read("--window")) { renderImplementation = 
osg::Camera::SEPERATE_WINDOW; }
    

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occurred when parsing the program 
arguments.
    if (arguments.errors())
    {
      arguments.writeErrorMessages(std::cout);
      return 1;
    }

    ref_ptr<MatrixTransform> scene = new MatrixTransform;
    
scene->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(0.f),1.0,0.0,0.0));

    ref_ptr<Group> reflectedSubgraph = _create_scene();    
    if (!reflectedSubgraph.valid()) return 1;

    ref_ptr<Group> reflectedScene = createShadowedScene(
                        reflectedSubgraph.get(), 
                        createReflector(), 
                        1, 
                        viewer.getCamera()->getClearColor(),
            tex_width, 
                        tex_height, 
                        renderImplementation,
                        viewer.getCamera());

    scene->addChild(reflectedScene.get());

    viewer.setSceneData(scene.get());

    return viewer.run();
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to