SPIN Framework

include/ssaoppu.h

00001 #include <osgPPU/Processor.h>
00002 #include <osgPPU/Unit.h>
00003 #include <osgPPU/UnitInOut.h>
00004 #include <osgPPU/UnitText.h>
00005 #include <osgPPU/UnitInResampleOut.h>
00006 #include <osgPPU/UnitInMipmapOut.h>
00007 #include <osgPPU/UnitOut.h>
00008 #include <osgPPU/UnitOutCapture.h>
00009 #include <osgPPU/UnitBypass.h>
00010 #include <osgPPU/UnitTexture.h>
00011 #include <osgPPU/UnitDepthbufferBypass.h>
00012 #include <osgDB/ReaderWriter>
00013 #include <osgDB/ReadFile>
00014 #include <osgPPU/ShaderAttribute.h>
00015 
00016 /**********************************************/
00017 // PPU setup for SSAO (ambient occlusion) rendering
00018 /**********************************************/
00019 class SSAORendering : virtual public osg::Referenced
00020 {
00021     private:
00022         float dofGaussSigma;
00023         float dofGaussRadius;
00024 
00025         osgPPU::ShaderAttribute* ssaoShaderAttr;
00026         osgPPU::ShaderAttribute* gaussx;
00027         osgPPU::ShaderAttribute* gaussy;
00028         osgPPU::ShaderAttribute* compositeAttr;
00029     
00030 
00031     public:
00032         /********************/
00033         SSAORendering()
00034         {
00035             dofGaussSigma = 1.5f;
00036             dofGaussRadius = 3.0f;
00037         }
00038 
00039         /*******************/
00040         void setPower(float pPower)
00041         {
00042             ssaoShaderAttr->set("vPower", pPower);
00043         }
00044 
00045         /*******************/
00046         void createSSAOPipeline(osgPPU::Processor* pParent, osgPPU::Unit*& pLastUnit,
00047                                 osg::Texture* pColor1, osg::Texture* pColor2, osg::Texture* pColor3,
00048                                 osg::Matrixf pProjMat)
00049         {
00050             double fovy, aspect, lNear, lFar;
00051             pProjMat.getPerspective(fovy, aspect, lNear, lFar);
00052         
00053             osg::ref_ptr<osgDB::ReaderWriter::Options> fragmentOptions = new osgDB::ReaderWriter::Options("fragment");
00054             osg::ref_ptr<osgDB::ReaderWriter::Options> vertexOptions = new osgDB::ReaderWriter::Options("vertex");
00055 
00056             // We need to get the ptr to the texture attached to the camera
00057             //osg::Camera::BufferAttachmentMap lBufferMap = pCamera->getBufferAttachmentMap();
00058             //osg::Texture* lColorTexture1 = lBufferMap[osg::Camera::COLOR_BUFFER0]._texture;
00059             //osg::Texture* lColorTexture2 = lBufferMap[osg::Camera::COLOR_BUFFER1]._texture;
00060 
00061             // Now we are ready for the PPU
00062             // The first unit gets the first color buffer
00063             osgPPU::UnitTexture* lColor1 = new osgPPU::UnitTexture();
00064             lColor1->setName("Color1");
00065             lColor1->setTexture(pColor1);
00066             pParent->addChild(lColor1);
00067 
00068             // The second unit gets the second color buffer
00069             osgPPU::UnitTexture* lColor2 = new osgPPU::UnitTexture();
00070             lColor2->setName("Color2");
00071             lColor2->setTexture(pColor2);
00072             pParent->addChild(lColor2);
00073 
00074             // The third unit gets the third color buffer
00075             osgPPU::UnitTexture* lColor3 = new osgPPU::UnitTexture();
00076             lColor3->setName("Color3");
00077             lColor3->setTexture(pColor3);
00078             pParent->addChild(lColor3);
00079 
00080             // The fourth unit gets the noise texture
00081             // It is read from an image file
00082             osg::ref_ptr<osg::Image> lNoiseImage = osgDB::readImageFile("ssao_noise.png");
00083             osg::Texture* lNoiseTex = new osg::Texture2D;
00084             lNoiseTex->setWrap(osg::Texture::WRAP_S, osg::Texture::MIRROR);
00085             lNoiseTex->setWrap(osg::Texture::WRAP_T, osg::Texture::MIRROR);
00086             lNoiseTex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
00087             lNoiseTex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
00088             lNoiseTex->setImage(0, lNoiseImage.get());
00089 
00090             osgPPU::UnitTexture* lNoise = new osgPPU::UnitTexture();
00091             lNoise->setName("Noise");
00092             lNoise->setTexture(lNoiseTex);
00093             pParent->addChild(lNoise);
00094 
00095             // The 5th unit gets the depth buffer
00096             osgPPU::UnitDepthbufferBypass* lDepth = new osgPPU::UnitDepthbufferBypass();
00097             lDepth->setName("Depth");
00098             pParent->addChild(lDepth);
00099 
00100             // And the unit to apply our shader
00101             osgPPU::UnitInOut* ssao = new osgPPU::UnitInOut();
00102             ssao->setName("ssao");
00103             
00104             // Setup the ssao shader
00105             ssaoShaderAttr = new osgPPU::ShaderAttribute();
00106             {
00107                 ssaoShaderAttr->addShader(osgDB::readShaderFile("screenSpaceAmbientOcc_vp.glsl", vertexOptions.get()));
00108                 ssaoShaderAttr->addShader(osgDB::readShaderFile("screenSpaceAmbientOcc_fp.glsl", fragmentOptions.get())); 
00109                 ssaoShaderAttr->setName("ssaoShader");
00110 
00111                 ssaoShaderAttr->add("vPower", osg::Uniform::FLOAT);
00112                 ssaoShaderAttr->add("vPixelSize", osg::Uniform::FLOAT);
00113                 ssaoShaderAttr->add("vNear", osg::Uniform::FLOAT);
00114                 ssaoShaderAttr->add("vFar", osg::Uniform::FLOAT);
00115                 ssaoShaderAttr->add("vProjectionMatrix", osg::Uniform::FLOAT_MAT4);
00116                 ssaoShaderAttr->add("vInvProjectionMatrix", osg::Uniform::FLOAT_MAT4);
00117 
00118                 ssaoShaderAttr->set("vPixelSize", 1.f);
00119                 ssaoShaderAttr->set("vNear", (float)lNear);
00120                 ssaoShaderAttr->set("vFar", (float)lFar);
00121                 ssaoShaderAttr->set("vProjectionMatrix", pProjMat);
00122                 ssaoShaderAttr->set("vInvProjectionMatrix", osg::Matrixf::inverse(pProjMat));
00123 
00124                 ssao->getOrCreateStateSet()->setAttributeAndModes(ssaoShaderAttr);
00125                 ssao->setInputTextureIndexForViewportReference(0);
00126 
00127                 //ssao->setInputToUniform(lColor1, "vColor1", true);
00128                 ssao->setInputToUniform(lColor2, "vColor2", true);
00129                 ssao->setInputToUniform(lColor3, "vColor3", true);
00130                 ssao->setInputToUniform(lNoise, "vNoiseMap", true);
00131                 ssao->setInputToUniform(lDepth, "vDepth", true);
00132             }
00133 
00134             // Now we will filter the ssao as it's quite noisy
00135             gaussx = new osgPPU::ShaderAttribute();
00136             gaussy = new osgPPU::ShaderAttribute();
00137             {
00138                 // read shaders from file
00139                 osg::Shader* vshader = osgDB::readShaderFile("gauss_convolution_vp.glsl", vertexOptions.get());
00140                 osg::Shader* fhshader = osgDB::readShaderFile("gauss_convolution_1Dx_fp.glsl", fragmentOptions.get());
00141                 osg::Shader* fvshader = osgDB::readShaderFile("gauss_convolution_1Dy_fp.glsl", fragmentOptions.get());
00142 
00143                 // setup horizontal blur shaders
00144                 gaussx->addShader(vshader);
00145                 gaussx->addShader(fhshader);
00146                 gaussx->setName("BlurHorizontalShader");
00147 
00148                 gaussx->add("sigma", osg::Uniform::FLOAT);
00149                 gaussx->add("radius", osg::Uniform::FLOAT);
00150                 gaussx->add("texUnit0", osg::Uniform::SAMPLER_2D);
00151 
00152                 gaussx->set("sigma", dofGaussSigma);
00153                 gaussx->set("radius", dofGaussRadius);
00154                 gaussx->set("texUnit0", 0);
00155 
00156                 // setup vertical blur shaders
00157                 gaussy->addShader(vshader);
00158                 gaussy->addShader(fvshader);
00159                 gaussy->setName("BlurVerticalShader");
00160 
00161                 gaussy->add("sigma", osg::Uniform::FLOAT);
00162                 gaussy->add("radius", osg::Uniform::FLOAT);
00163                 gaussy->add("texUnit0", osg::Uniform::SAMPLER_2D);
00164 
00165                 gaussy->set("sigma", dofGaussSigma);
00166                 gaussy->set("radius", dofGaussRadius);
00167                 gaussy->set("texUnit0", 0);
00168             }
00169 
00170             osgPPU::UnitInOut* blurxlight = new osgPPU::UnitInOut();
00171             osgPPU::UnitInOut* blurylight = new osgPPU::UnitInOut();
00172             {
00173                 // set name and indicies
00174                 blurxlight->setName("BlurHorizontalLight");
00175                 blurylight->setName("BlurVerticalLight");
00176 
00177                 //blurxlight->setShader(gaussx);
00178                 //blurylight->setShader(gaussy);
00179                 blurxlight->getOrCreateStateSet()->setAttributeAndModes(gaussx);
00180                 blurylight->getOrCreateStateSet()->setAttributeAndModes(gaussy);
00181             }
00182             ssao->addChild(blurxlight);
00183             blurxlight->addChild(blurylight);
00184 
00185             // Last step: multiplication of the SSAO and the previous rendering
00186             osgPPU::Unit* composite = new osgPPU::UnitInOut();
00187             compositeAttr = new osgPPU::ShaderAttribute();
00188             {
00189                 compositeAttr->addShader(osgDB::readShaderFile("screenSpaceAO_composite_vp.glsl", vertexOptions.get()));
00190                 compositeAttr->addShader(osgDB::readShaderFile("screenSpaceAO_composite_fp.glsl", fragmentOptions.get()));
00191                 compositeAttr->setName("compositeSSAO");
00192 
00193                 compositeAttr->add("vSSAO", osg::Uniform::SAMPLER_2D);
00194                 compositeAttr->add("vColor", osg::Uniform::SAMPLER_2D);
00195 
00196                 //compositeAttr->set("vSSAO", 0);
00197                 
00198                 composite->getOrCreateStateSet()->setAttributeAndModes(compositeAttr);
00199 
00200                 composite->setInputToUniform(blurylight, "vSSAO", true);
00201                 composite->setInputToUniform(lColor1, "vColor", true);
00202             }
00203             blurylight->addChild(composite);
00204 
00205             pLastUnit = composite;
00206         }
00207 };