Hi Robert,

i implement a first version of SSAO effect and i have only one issue left in
the implementation. the whole thing works nicely with GLSL shader,
mutlipass-rendering when we don't resize the window, actually 512x512. so
what sould i do, to replace this issue. ?

Another thing is to remove the last pass GLSL shader, is there a way to
solve it under common openGL textureing? Mutlitextureing? Or any other idea.


This version supports:

(Transparant faces: just disable for transparent faces like window, glass
the detph writing, the depth buffer will hold only un-transparent z-values
(alpha > 0.9) )

toggle ssao on/off with key 'a'

have a look and i will be happy to get any ideas to improve the stuff.
FPS is about 30.

/adrian
-- 
********************************************
Adrian Egli
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
*
* This application is open source and may be redistributed and/or modified   
* freely and without restriction, both in commericial and non commericial 
applications,
* as long as this copyright notice is maintained.
* 
* This application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

#include <osg/Switch>
#include <osg/Uniform>

#include <osgText/Text>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/BlendFunc>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>

#include <iostream>

#include <osgFX/Effect>
#include <osgFX/Technique>
#include <osgFX/Registry>

#include <osg/TexGen>
#include <osg/Texture2D>

#include <osg/PolygonOffset>
#include <osgDB/WriteFile>





struct WriteCameraPostDrawCallback : public osg::Camera::DrawCallback
{
        WriteCameraPostDrawCallback(osg::Image* image,std::string filename, 
bool write):
                _image(image),
                _filename(filename),
                _write(write)
        {
                char* write_file = getenv("SSAO_WRITE_FILE");
                if ( write_file ) _write = true;
        }

        virtual void operator () (const osg::Camera& /*camera*/) const
        {
                 
                _image->dirty();
         
                if ( _write ) {
                        std::cout << "write " << _filename << std::endl;
                        osgDB::writeImageFile(*(_image.get()),_filename);
                }

        }

        osg::ref_ptr<osg::Image> _image;
        std::string _filename;
        bool _write;
};
 

namespace osgFX {
        class SSAO : public Effect {
                public:
                        SSAO() {};
                        SSAO(osg::Group*);
                        SSAO(const SSAO& copy, const osg::CopyOp& copyop = 
osg::CopyOp::SHALLOW_COPY);

                        META_Effect(osgFX, SSAO, 

                                "Screen Space Ambient Occlusion", 

                                "SSAO : test implementation", 

                                "Adrian Egli");
                protected:
                        virtual ~SSAO() {}
                        SSAO& operator=(const SSAO&) { return *this; }

                        bool define_techniques();

                        osg::ref_ptr<osg::Group> _root;
        };
        
}



using namespace osgFX;


namespace
{


        osg::Node* createBase(osg::Texture2D* texture ,osg::Texture2D* 
texture2=NULL )
        {

                osg::ref_ptr<osg::Geode> geode = new osg::Geode;

                // set up the texture of the base.
                osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
                
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
            if 
(texture2)stateset->setTextureAttributeAndModes(1,texture2,osg::StateAttribute::ON);
                geode->setStateSet( stateset.get() );


                osg::ref_ptr<osg::HeightField> grid = new osg::HeightField;
                grid->allocate(2,2);
                grid->setOrigin(osg::Vec3(0.0,0.0,0.0));
                grid->setXInterval(1.0);
                grid->setYInterval(1.0);

                grid->setHeight(0,0,-1.0);
                grid->setHeight(0,1,-1.0);
                grid->setHeight(1,1,-1.0);
                grid->setHeight(1,0,-1.0);
 
                geode->addDrawable(new osg::ShapeDrawable(grid.get()));

                osg::Group* group = new osg::Group;
                group->addChild(geode.get());

                return group;

        }

        Registry::Proxy proxy(new SSAO);

        class DefaultTechnique: public Technique {
                public:

                        DefaultTechnique(osg::Group* scene,osg::Group* ssaoFX) 
:    
                            Technique(),
                                _scene(scene)
                        {
 
                                // texture resolution 
                                _RTTInfoDepth._resolution_x = 512;
                                _RTTInfoDepth._resolution_y = 512;

  
                                // texture
                                _RTTInfoDepth._texture = new osg::Texture2D;
                                
_RTTInfoDepth._texture->setTextureSize(_RTTInfoDepth._resolution_x, 
_RTTInfoDepth._resolution_y);
                                
_RTTInfoDepth._texture->setInternalFormat(GL_RGB);
                                
_RTTInfoDepth._texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
                                
_RTTInfoDepth._texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
 
                                // camera 
                                _RTTInfoDepth._camera = new osg::Camera;
                                
_RTTInfoDepth._camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
                                
_RTTInfoDepth._camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                                
_RTTInfoDepth._camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
                                // set viewport
                                
_RTTInfoDepth._camera->setViewport(0,0,_RTTInfoDepth._resolution_x,_RTTInfoDepth._resolution_y);
                                // set the camera to render before the main 
camera.
                                
_RTTInfoDepth._camera->setRenderOrder(osg::Camera::PRE_RENDER);
                                // tell the camera to use OpenGL frame buffer 
object where supported.
                                
_RTTInfoDepth._camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
                                // image (SSAO filter)
                                _RTTInfoDepth._image=new osg::Image;
                                
_RTTInfoDepth._image->allocateImage(_RTTInfoDepth._resolution_x, 
_RTTInfoDepth._resolution_y,  1, GL_RGB, GL_UNSIGNED_BYTE);
                                
_RTTInfoDepth._camera->attach(osg::Camera::COLOR_BUFFER, 
_RTTInfoDepth._image.get(),0,0);
                                _RTTInfoDepth._camera->setPostDrawCallback(new 
WriteCameraPostDrawCallback(_RTTInfoDepth._image.get(),"RTTInfoDepth.png",false));
                                
_RTTInfoDepth._texture->setImage(0,_RTTInfoDepth._image.get());
                                // add subgraph to render
                                _RTTInfoDepth._camera->addChild(_scene.get());

                                
////////////////////////////////////////////////////////////////////////// 
Gaussian Vertical
                                // texture resolution 
                                _RTTInfoGaussianV._resolution_x = 512;
                                _RTTInfoGaussianV._resolution_y = 512;

 
                                // texture
                                _RTTInfoGaussianV._texture = new osg::Texture2D;
                                
_RTTInfoGaussianV._texture->setTextureSize(_RTTInfoGaussianV._resolution_x, 
_RTTInfoGaussianV._resolution_y);
                                
_RTTInfoGaussianV._texture->setInternalFormat(GL_RGB);
                                
_RTTInfoGaussianV._texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
                                
_RTTInfoGaussianV._texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);

                                // camera 
                                _RTTInfoGaussianV._camera = new osg::Camera;
                                
_RTTInfoGaussianV._camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
                                
_RTTInfoGaussianV._camera->setClearMask(GL_COLOR_BUFFER_BIT | 
GL_DEPTH_BUFFER_BIT);
                                
_RTTInfoGaussianV._camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
                                // set viewport
                                
_RTTInfoGaussianV._camera->setViewport(0,0,_RTTInfoGaussianV._resolution_x,_RTTInfoGaussianV._resolution_y);
                                
_RTTInfoGaussianV._camera->setViewMatrixAsLookAt(osg::Vec3(0.5,0.5,1.0),osg::Vec3(0.5,0.5,0.0),osg::Vec3(0,1,0));
                                
_RTTInfoGaussianV._camera->setProjectionMatrixAsOrtho2D(-0.5,0.5,-0.5,0.5);
                                // set the camera to render before the main 
camera.
                                
_RTTInfoGaussianV._camera->setRenderOrder(osg::Camera::PRE_RENDER);
                                // tell the camera to use OpenGL frame buffer 
object where supported.
                                
_RTTInfoGaussianV._camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
                                // image (SSAO filter)
                                _RTTInfoGaussianV._image=new osg::Image;
                                
_RTTInfoGaussianV._image->allocateImage(_RTTInfoGaussianV._resolution_x, 
_RTTInfoGaussianV._resolution_y,  1, GL_RGB, GL_UNSIGNED_BYTE);
                                
_RTTInfoGaussianV._camera->attach(osg::Camera::COLOR_BUFFER, 
_RTTInfoGaussianV._image.get(),0,0);
                                
_RTTInfoGaussianV._camera->setPostDrawCallback(new 
WriteCameraPostDrawCallback(_RTTInfoGaussianV._image.get(),"RTTInfoGaussianV.png",false));
                                
_RTTInfoGaussianV._texture->setImage(0,_RTTInfoGaussianV._image.get());
                                // add subgraph to render
                                
_RTTInfoGaussianV._camera->addChild(createBase(_RTTInfoDepth._texture.get()));

                                
////////////////////////////////////////////////////////////////////////// 
Gaussian Horizontal
                                // texture resolution 
                                _RTTInfoGaussianH._resolution_x = 512;
                                _RTTInfoGaussianH._resolution_y = 512;

 
                                // texture
                                _RTTInfoGaussianH._texture = new osg::Texture2D;
                                
_RTTInfoGaussianH._texture->setTextureSize(_RTTInfoGaussianH._resolution_x, 
_RTTInfoGaussianH._resolution_y);
                                
_RTTInfoGaussianH._texture->setInternalFormat(GL_RGB);
                                
_RTTInfoGaussianH._texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
                                
_RTTInfoGaussianH._texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);

                                // camera 
                                _RTTInfoGaussianH._camera = new osg::Camera;
                                
_RTTInfoGaussianH._camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
                                
_RTTInfoGaussianH._camera->setClearMask(GL_COLOR_BUFFER_BIT | 
GL_DEPTH_BUFFER_BIT);
                                
_RTTInfoGaussianH._camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
                                // set viewport
                                
_RTTInfoGaussianH._camera->setViewport(0,0,_RTTInfoGaussianH._resolution_x,_RTTInfoGaussianH._resolution_y);
                                
_RTTInfoGaussianH._camera->setViewMatrixAsLookAt(osg::Vec3(0.5,0.5,1),osg::Vec3(0.5,0.5,0),osg::Vec3(0,1,0));
                                
_RTTInfoGaussianH._camera->setProjectionMatrixAsOrtho2D(-0.5,0.5,-0.5,0.5);

                                // set the camera to render before the main 
camera.
                                
_RTTInfoGaussianH._camera->setRenderOrder(osg::Camera::PRE_RENDER);
                                // tell the camera to use OpenGL frame buffer 
object where supported.
                                
_RTTInfoGaussianH._camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
                                // image (SSAO filter)
                                _RTTInfoGaussianH._image=new osg::Image;
                                
_RTTInfoGaussianH._image->allocateImage(_RTTInfoGaussianH._resolution_x, 
_RTTInfoGaussianH._resolution_y,  1, GL_RGB, GL_UNSIGNED_BYTE);
                                
_RTTInfoGaussianH._camera->attach(osg::Camera::COLOR_BUFFER, 
_RTTInfoGaussianH._image.get(),0,0);
                                
_RTTInfoGaussianH._camera->setPostDrawCallback(new 
WriteCameraPostDrawCallback(_RTTInfoGaussianH._image.get(),"RTTInfoGaussianH.png",false));
                                
_RTTInfoGaussianH._texture->setImage(0,_RTTInfoGaussianH._image.get());
                                // add subgraph to render
                                
_RTTInfoGaussianH._camera->addChild(createBase(_RTTInfoGaussianV._texture.get()));


                                
////////////////////////////////////////////////////////////////////////// SSAO 
difference
                                // texture resolution 
                                _RTTInfoSSAO._resolution_x = 512;
                                _RTTInfoSSAO._resolution_y = 512;

                                // texture
                                _RTTInfoSSAO._texture = new osg::Texture2D;
                                
_RTTInfoSSAO._texture->setTextureSize(_RTTInfoSSAO._resolution_x, 
_RTTInfoSSAO._resolution_y);
                                
_RTTInfoSSAO._texture->setInternalFormat(GL_RGB);
                                
_RTTInfoSSAO._texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
                                
_RTTInfoSSAO._texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);

                                // camera 
                                _RTTInfoSSAO._camera = new osg::Camera;
                                
_RTTInfoSSAO._camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
                                
_RTTInfoSSAO._camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                                
_RTTInfoSSAO._camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
                                // set viewport
                                
_RTTInfoSSAO._camera->setViewport(0,0,_RTTInfoSSAO._resolution_x,_RTTInfoSSAO._resolution_y);
                                
_RTTInfoSSAO._camera->setViewMatrixAsLookAt(osg::Vec3(0.5,0.5,1),osg::Vec3(0.5,0.5,0),osg::Vec3(0,1,0));
                                
_RTTInfoSSAO._camera->setProjectionMatrixAsOrtho2D(-0.5,0.5,-0.5,0.5);

                                // set the camera to render before the main 
camera.
                                
_RTTInfoSSAO._camera->setRenderOrder(osg::Camera::PRE_RENDER);
                                // tell the camera to use OpenGL frame buffer 
object where supported.
                                
_RTTInfoSSAO._camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
                                // image (SSAO filter)
                                _RTTInfoSSAO._image=new osg::Image;
                                
_RTTInfoSSAO._image->allocateImage(_RTTInfoSSAO._resolution_x, 
_RTTInfoSSAO._resolution_y,  1, GL_RGB, GL_UNSIGNED_BYTE);
                                
_RTTInfoSSAO._camera->attach(osg::Camera::COLOR_BUFFER, 
_RTTInfoSSAO._image.get(),0,0);
                                _RTTInfoSSAO._camera->setPostDrawCallback(new 
WriteCameraPostDrawCallback(_RTTInfoSSAO._image.get(),"RTTInfoSSAO.png",false));
                                
_RTTInfoSSAO._texture->setImage(0,_RTTInfoSSAO._image.get());
                                // add subgraph to render
                                
_RTTInfoSSAO._camera->addChild(createBase(_RTTInfoDepth._texture.get() 
,_RTTInfoGaussianH._texture.get()));




                                
////////////////////////////////////////////////////////////////////////// SSAO 
final pass

                                osg::ref_ptr<osg::StateSet> ss = 
ssaoFX->getOrCreateStateSet();
                                {
                                        unsigned int textLoop(0); 
                                        // fake texture for baseTexture, add a 
fake texture
                                        // we support by default at least one 
texture layer
                                        // without this fake texture we can not 
support
                                        // textured and not textured scene

                                        // TODO: at the moment the PSSM 
supports just one texture layer in the GLSL shader, multitexture are
                                        //       not yet supported !

                                        osg::ref_ptr<osg::Image> image = new 
osg::Image;
                                        // allocate the image data, noPixels x 
1 x 1 with 4 rgba floats - equivalent to a Vec4!
                                        int noPixels = 1;
                                        
image->allocateImage(noPixels,1,1,GL_RGBA,GL_FLOAT);
                                        
image->setInternalTextureFormat(GL_RGBA);
                                        // fill in the image data.
                                        osg::Vec4* dataPtr = 
(osg::Vec4*)image->data();
                                        osg::Vec4f color(1.0f,1.0f,1.0f,0.0f);
                                        *dataPtr = color;
                                        // make fake texture
                                        osg::ref_ptr<osg::Texture2D> texture = 
new osg::Texture2D;
                                        
texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
                                        
texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
                                        
texture->setBorderColor(osg::Vec4(1.0,1.0,1.0,1.0));
                                        
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
                                        
texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
                                        texture->setImage(image.get());
                                        // add fake texture
                                        
ss->setTextureAttribute(textLoop,texture.get(),osg::StateAttribute::ON);
                                        
ss->setTextureMode(textLoop,GL_TEXTURE_1D,osg::StateAttribute::OFF);
                                        
ss->setTextureMode(textLoop,GL_TEXTURE_2D,osg::StateAttribute::ON);
                                        
ss->setTextureMode(textLoop,GL_TEXTURE_3D,osg::StateAttribute::OFF);
                                }
 
 
                                
ss->setTextureAttributeAndModes(1,_RTTInfoSSAO._texture.get(),osg::StateAttribute::ON);

                                osg::ref_ptr<osg::Program> program = new 
osg::Program;
                                ss->setAttribute(program.get());

                                osg::ref_ptr<osg::Uniform> samplerText = new 
osg::Uniform("samplerText",0);
                                ss->addUniform(samplerText.get());

                                osg::ref_ptr<osg::Uniform> samplerRTScene = new 
osg::Uniform("samplerRTScene",1);
                                ss->addUniform(samplerRTScene.get());


                                osg::ref_ptr<osg::Shader> fragment_shader = new 
osg::Shader(osg::Shader::FRAGMENT,
                                        "uniform sampler2D samplerRTScene;"\
                                        "uniform sampler2D samplerText;"\
                                        "void main(void)"\
                                        "{"\
                                        "   vec4 text = 
texture2D(samplerText,gl_TexCoord[0].st);"\
                                        "       vec4 ssao = 
texture2D(samplerRTScene, vec2(1.0/512.0*gl_FragCoord.x, 
1.0/512.0*gl_FragCoord.y));"\
                                        "       float lenRGB = 
length(ssao.rgb);"\
                                        "   lenRGB = 0.25*lenRGB + 
0.75*(1.0f-(1.0f-lenRGB)*(1.0f-lenRGB));"\
                                        "       gl_FragColor = text*gl_Color - 
vec4(lenRGB,lenRGB,lenRGB,1.0);"\
                                        "}"     
                                        );
                                program->addShader(fragment_shader.get());
                        }

                        virtual void 
getRequiredExtensions(std::vector<std::string>& extensions)
                        {
                        }

                        bool validate(osg::State& state) const
                        {
                                if (!Technique::validate(state)) return false;

                                //osg::TextureCubeMap::Extensions *ext = 
osg::TextureCubeMap::getExtensions(state.getContextID(), true);
                                //if (ext) {
                                //      return ext->isCubeMapSupported();
                                //}
                                return true;
                        }


                        /** optional: return a node that overrides the child 
node on a specified pass */
                        inline virtual osg::Node* getOverrideChild(int passNum) 
 { 
                                if ( passNum == 0 ) { //Depth
                                        return _RTTInfoDepth._camera.get();
                                }
                                if ( passNum == 1 ) { // Gaussian V
                                        return _RTTInfoGaussianV._camera.get();
                                }
                                if ( passNum == 2 ) { // Gaussian H
                                        return _RTTInfoGaussianH._camera.get();
                                }
                                if ( passNum == 3 ) { // SSAO
                                        return _RTTInfoSSAO._camera.get();
                                }
                                return 0; 
                        
                        }
                         
                        inline virtual void traverse(osg::NodeVisitor& nv, 
Effect* fx) {

                                // special actions must be taken if the node 
visitor is actually a CullVisitor
                                osgUtil::CullVisitor *cv = 
dynamic_cast<osgUtil::CullVisitor *>(&nv);
                                if ( cv ) {     
                                        osgUtil::RenderStage* orig_rs = 
cv->getRenderStage();
                                        
_RTTInfoDepth._camera->setViewMatrix(cv->getRenderInfo().getView()->getCamera()->getViewMatrix());
                                        
_RTTInfoDepth._camera->setProjectionMatrix(cv->getRenderInfo().getView()->getCamera()->getProjectionMatrix());
                                        osg::ref_ptr<osg::Viewport> vp = 
cv->getRenderInfo().getView()->getCamera()->getViewport();
                                        osg::ref_ptr<osg::Viewport> vpCam = 
_RTTInfoDepth._camera->getViewport();
                                        if ( vpCam->width()!=vp->width() || 
vpCam->height()!=vp->height()  ) {
                                                
_RTTInfoDepth._camera->getViewport()->setViewport(
                                                        0,
                                                        0,
                                                        std::min((unsigned 
int)vp->width(),_RTTInfoDepth._resolution_x),
                                                        std::min((unsigned 
int)vp->height(),_RTTInfoDepth._resolution_y)
                                                        );              
                                        }

                                        double f,a,zn,zf;
                                        
cv->getRenderInfo().getView()->getCamera()->getProjectionMatrix().getPerspective(f,a,zn,zf);
                                        if ( nearUniform.valid() ) 
nearUniform->set((float)zn);
                                        if ( farUniform.valid() )  
farUniform->set((float)zf); 
                                }


                                traverse_implementation(nv, fx);

                        }


                protected:

                        void define_passes()
                        {
 
                                {   // Depth Pass 1
                                        osg::ref_ptr<osg::StateSet> ss = new 
osg::StateSet;

                                        
                                        osg::ref_ptr<osg::Program> program = 
new osg::Program;
                                        ss->setAttribute(program.get());

                                        nearUniform = new 
osg::Uniform("nearUniform",FLT_MIN);
                                        farUniform  = new 
osg::Uniform("farUniform",FLT_MAX);
                                        ss->addUniform(nearUniform.get());
                                        ss->addUniform(farUniform.get());


                                        osg::ref_ptr<osg::Shader> vertex_shader 
= new osg::Shader(osg::Shader::VERTEX,
                                                "varying float intensity;"\
                                                "void main(void)"\
                                                "{"\
                                                "       intensity = 
0.5*(1.0+dot(vec3(0,0,1),gl_Normal));"\
                                                "       gl_Position = 
ftransform();"\
                                                "}"
                                                );
                                        program->addShader(vertex_shader.get());

                                        osg::ref_ptr<osg::Shader> 
fragment_shader = new osg::Shader(osg::Shader::FRAGMENT,
                                                "uniform float nearUniform;"\
                                                "uniform float farUniform;"\
                                                "varying float intensity;"\
                                                "void main() {"\
                                                "   float c = 
0.5+0.5*intensity;"\
                                                "   float z = 
(gl_FragCoord.z/gl_FragCoord.w) / ( farUniform);"\
                                                "       gl_FragColor = 
c*vec4(z,z,z,step(0.9,gl_FrontMaterial.diffuse.a));"\
                                                "} "
                                        );
                                        
program->addShader(fragment_shader.get());
                                        

                                        addPass(ss.get());
                                }

                                {   // Gaussian V  2
                                        osg::ref_ptr<osg::StateSet> ss = new 
osg::StateSet;

                                        osg::ref_ptr<osg::Program> program = 
new osg::Program;
                                        ss->setAttribute(program.get());

                                        osg::ref_ptr<osg::Uniform> 
samplerRTScene = new osg::Uniform("samplerRTScene",0);
                                        ss->addUniform(samplerRTScene.get());

 
                                        osg::ref_ptr<osg::Shader> vertex_shader 
= new osg::Shader(osg::Shader::VERTEX,
                                                        "varying vec2 
vTexCoord;"\
                                                        "void main(void)"\
                                                        "{"\
                                                        "       gl_Position = 
ftransform();"\
                                                        "       vec2 Pos = 
gl_Vertex.xy;"\
                                                        "       vTexCoord = 
Pos;"\
                                                        "}"
                                                );
                                        program->addShader(vertex_shader.get());


                                        osg::ref_ptr<osg::Shader> 
fragment_shader = new osg::Shader(osg::Shader::FRAGMENT,
                                                "uniform sampler2D 
samplerRTScene;"\
                                                "varying vec2 vTexCoord;"\
                                                "const float blurSize = 
1.0/256.0; "\
                                                "void main(void)"\
                                                "{"\
                                                "       vec4 sum = vec4(0.0);"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x - 4.0*blurSize, vTexCoord.y)) *  
1.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x - 3.0*blurSize, vTexCoord.y)) *  
2.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x - 2.0*blurSize, vTexCoord.y)) *  
4.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x - blurSize    , vTexCoord.y)) *  
7.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x               , vTexCoord.y)) * 
22.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x + blurSize    , vTexCoord.y)) *  
7.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x + 2.0*blurSize, vTexCoord.y)) *  
4.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x + 3.0*blurSize, vTexCoord.y)) *  
2.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x + 4.0*blurSize, vTexCoord.y)) *  
1.0/50.0;"\
                                                "       gl_FragColor = sum;"\
                                                "}"     
                                        );
                                        
program->addShader(fragment_shader.get());


                                        addPass(ss.get());
                                }
                                {   // Gaussian H  3
                                        osg::ref_ptr<osg::StateSet> ss = new 
osg::StateSet;
                


                                        osg::ref_ptr<osg::Program> program = 
new osg::Program;
                                        ss->setAttribute(program.get());

                                        osg::ref_ptr<osg::Uniform> 
samplerRTScene = new osg::Uniform("samplerRTScene",0);
                                        ss->addUniform(samplerRTScene.get());

 
                                        osg::ref_ptr<osg::Shader> vertex_shader 
= new osg::Shader(osg::Shader::VERTEX,
                                                "varying vec2 vTexCoord;"\
                                                "void main(void)"\
                                                "{"\
                                                "       gl_Position = 
ftransform();"\
                                                "       vec2 Pos = 
gl_Vertex.xy;"\
                                                "       vTexCoord = Pos;"\
                                                "}"
                                                );
                                        program->addShader(vertex_shader.get());


                                        osg::ref_ptr<osg::Shader> 
fragment_shader = new osg::Shader(osg::Shader::FRAGMENT,
                                                "uniform sampler2D 
samplerRTScene;"\
                                                "varying vec2 vTexCoord;"\
                                                "const float blurSize = 
1.0/256.0; "\
                                                "void main(void)"\
                                                "{"\
                                                "       vec4 sum = vec4(0.0);"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y - 4.0*blurSize)) *  
1.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y - 3.0*blurSize)) *  
2.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y - 2.0*blurSize)) *  
4.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y - blurSize    )) *  
7.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y               )) * 
22.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y + blurSize    )) *  
7.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y + 2.0*blurSize)) *  
4.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y + 3.0*blurSize)) *  
2.0/50.0;"\
                                                "       sum += 
texture2D(samplerRTScene, vec2(vTexCoord.x, vTexCoord.y + 4.0*blurSize)) *  
1.0/50.0;"\
                                                "       gl_FragColor = sum;"\
                                                "}"     
                                                );
                                        
program->addShader(fragment_shader.get());
                                        addPass(ss.get());
                                }

                                {   // SSAO 4
                                        osg::ref_ptr<osg::StateSet> ss = new 
osg::StateSet;


                                        osg::ref_ptr<osg::Program> program = 
new osg::Program;
                                        ss->setAttribute(program.get());

                                        osg::ref_ptr<osg::Uniform> samplerD = 
new osg::Uniform("samplerD",0);
                                        ss->addUniform(samplerD.get());

                                        osg::ref_ptr<osg::Uniform> samplerH = 
new osg::Uniform("samplerH",1);
                                        ss->addUniform(samplerH.get());

 
                                        osg::ref_ptr<osg::Shader> vertex_shader 
= new osg::Shader(osg::Shader::VERTEX,
                                                "varying vec2 vTexCoord;"\
                                                "void main(void)"\
                                                "{"\
                                                "       gl_Position = 
ftransform();"\
                                                "       vec2 Pos = 
gl_Vertex.xy;"\
                                                "       vTexCoord = Pos;"\
                                                "}"
                                                );
                                        program->addShader(vertex_shader.get());

                                        osg::ref_ptr<osg::Shader> 
fragment_shader = new osg::Shader(osg::Shader::FRAGMENT,
                                                "uniform sampler2D samplerD;"\
                                                "uniform sampler2D samplerH;"\
                                                "varying vec2 vTexCoord;"\
                                                "void main(void)"\
                                                "{"\
                                                "       vec4 sum = 
vec4(0.0,0.0,0.0,0.0);"\
                                                "       sum += 
texture2D(samplerD, vec2(vTexCoord.x, vTexCoord.y));"\
                                                "       sum -= 
texture2D(samplerH, vec2(vTexCoord.x, vTexCoord.y));"\
                                                "       gl_FragColor = 
clamp(sum,0.0,1.0);"\
                                                "}"     
                                                );
                                        
program->addShader(fragment_shader.get());
                                        addPass(ss.get());
                                }

                                {   // Final Pass
                                        osg::ref_ptr<osg::StateSet> ss = new 
osg::StateSet;
                                        addPass(ss.get());
                                }
                        }

                private:

                        struct RTTInfo {
                                // RTT
                                osg::ref_ptr<osg::Camera>       _camera;
                                osg::ref_ptr<osg::TexGen>       _texgen;
                                osg::ref_ptr<osg::Texture2D>    _texture;
                                osg::ref_ptr<osg::StateSet>     _stateset;
                                osg::ref_ptr<osg::Image>        _image;
 
                                unsigned int                                    
_resolution_x;
                                unsigned int                                    
_resolution_y;
                        };

                        RTTInfo                                         
_RTTInfoDepth;
                        RTTInfo                                         
_RTTInfoSSAO;

                        RTTInfo                                         
_RTTInfoGaussianH;
                        RTTInfo                                         
_RTTInfoGaussianV;

                        osg::ref_ptr<osg::Group>                _scene;

                        osg::ref_ptr<osg::Uniform> nearUniform;
                        osg::ref_ptr<osg::Uniform> farUniform;

        };

}

SSAO::SSAO(osg::Group* rootGrp)  :    Effect(),_root(rootGrp) {
}

SSAO::SSAO(const SSAO& copy, const osg::CopyOp& copyop)   :    Effect(copy, 
copyop){
}

bool SSAO::define_techniques()
{
        addTechnique(new DefaultTechnique(_root.get(),this));
        return true;
}

 



class SSAOViewerEventHandler : public osgGA::GUIEventHandler
{
public:
        SSAOViewerEventHandler(osg::Switch* s) : 
          _switch(s)
        {
        }
        virtual bool handle(const osgGA::GUIEventAdapter& 
ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor*) 
        { 
                osgViewer::Viewer* viewer = 
dynamic_cast<osgViewer::Viewer*>(&aa);
                if (!viewer) return false;

          

                if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN)
                {
                        switch (ea.getKey())
                        {
                                case 'a': 
                                        if ( _switch->getValue(0) ) {
                                                _switch->setAllChildrenOff();
                                                _switch->setValue(1,true);
                                        } else {
                                                _switch->setAllChildrenOff();
                                                _switch->setValue(0,true);
                                        }
                                        return true;
                        }
                }

                return false;

        }

        osg::ref_ptr<osg::Switch> _switch;
};

int main(int argc, char** argv)
{

        putenv("OSG_WINDOW=128 128 512 512");

        // use an ArgumentParser object to manage the program arguments.
        osg::ArgumentParser arguments(&argc,argv);

        
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
        
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+"
 is the standard OpenSceneGraph example which loads and visualises 3d models.");
        
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+"
 [options] filename ...");
        arguments.getApplicationUsage()->addCommandLineOption("--image 
<filename>","Load an image and render it on a quad");
        arguments.getApplicationUsage()->addCommandLineOption("--dem 
<filename>","Load an image/DEM and render it on a HeightField");
        arguments.getApplicationUsage()->addCommandLineOption("--login <url> 
<username> <password>","Provide authentication information for http file 
access.");

        osgViewer::Viewer viewer(arguments);

        unsigned int helpType = 0;
        if ((helpType = arguments.readHelpType()))
        {
                arguments.getApplicationUsage()->write(std::cout, helpType);
                return 1;
        }

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

        if (arguments.argc()<=1)
        {
                
arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
                return 1;
        }

        std::string url, username, password;
        while(arguments.read("--login",url, username, password))
        {
                if (!osgDB::Registry::instance()->getAuthenticationMap())
                {
                        osgDB::Registry::instance()->setAuthenticationMap(new 
osgDB::AuthenticationMap);
                        
osgDB::Registry::instance()->getAuthenticationMap()->addAuthenticationDetails(
                                url,
                                new osgDB::AuthenticationDetails(username, 
password)
                                );
                }
        }

        // set up the camera manipulators.
        {
                osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> 
keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

                keyswitchManipulator->addMatrixManipulator( '1', "Trackball", 
new osgGA::TrackballManipulator() );
                keyswitchManipulator->addMatrixManipulator( '2', "Flight", new 
osgGA::FlightManipulator() );
                keyswitchManipulator->addMatrixManipulator( '3', "Drive", new 
osgGA::DriveManipulator() );
                keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new 
osgGA::TerrainManipulator() );

                std::string pathfile;
                char keyForAnimationPath = '5';
                while (arguments.read("-p",pathfile))
                {
                        osgGA::AnimationPathManipulator* apm = new 
osgGA::AnimationPathManipulator(pathfile);
                        if (apm || !apm->valid()) 
                        {
                                unsigned int num = 
keyswitchManipulator->getNumMatrixManipulators();
                                keyswitchManipulator->addMatrixManipulator( 
keyForAnimationPath, "Path", apm );
                                
keyswitchManipulator->selectMatrixManipulator(num);
                                ++keyForAnimationPath;
                        }
                }

                viewer.setCameraManipulator( keyswitchManipulator.get() );
        }

        // add the state manipulator
        viewer.addEventHandler( new 
osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

        // add the thread model handler
        viewer.addEventHandler(new osgViewer::ThreadingHandler);

        // add the window size toggle handler
        viewer.addEventHandler(new osgViewer::WindowSizeHandler);

        // add the stats handler
        viewer.addEventHandler(new osgViewer::StatsHandler);

        // add the help handler
        viewer.addEventHandler(new 
osgViewer::HelpHandler(arguments.getApplicationUsage()));

        // add the record camera path handler
        viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

        // add the LOD Scale handler
        viewer.addEventHandler(new osgViewer::LODScaleHandler);

        // add the screen capture handler
        viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);

        osg::ref_ptr<osg::Switch> switchNode = new osg::Switch;
        osg::ref_ptr<SSAOViewerEventHandler> ssaoViewerEventHandler= new 
SSAOViewerEventHandler(switchNode.get());
        viewer.addEventHandler(ssaoViewerEventHandler.get());


        // load the data
        osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
        if (!loadedModel) 
        {
                std::cout << arguments.getApplicationName() <<": No data 
loaded" << std::endl;
                loadedModel = osgDB::readNodeFile("cow.osg");
                if (!loadedModel) return 1;
        }

        // 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;
        }


        // optimize the scene graph, remove redundant nodes and state etc.
        osgUtil::Optimizer optimizer;
        optimizer.optimize(loadedModel.get());

        // SWITCH
        switchNode->addChild(loadedModel.get(),false);

        // SSAO
        osg::ref_ptr<osg::Group> grpSSAOModel = new osg::Group;
        grpSSAOModel->addChild(loadedModel.get());
        osg::ref_ptr<SSAO> ssao = new SSAO(grpSSAOModel.get());
        ssao->addChild(grpSSAOModel.get());
        osg::ref_ptr<osg::Group> grpSSAO = new osg::Group;
        grpSSAO->addChild(ssao.get());
        switchNode->addChild(grpSSAO.get(),true);

        viewer.setSceneData( switchNode.get() );
 

        viewer.realize();

        return viewer.run();

}
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to