[osg-users] Multipass shading/rendering

hellhound@binary-revolution.org hellhound at binary-revolution.org
Wed Sep 12 09:00:50 PDT 2007


Hi Art,

thanks for your quick response. 

The described multi pass mechanism is a part of our strategy game engine, based on osg and other open source technologies, which will go open source in the next few days (actually you can only find the project description on sourceforge, search for BinRev Engine).

It sounds very good what you have described and perhaps we could create synergies to solve our problems...

Because our source is acutally not reachable at sourceforge, here the fragment of the test i've written for the multipass shader support:

1. Main class where the passes are defined. Here you could see the first pass settings for dot3 shading:

// create RTT 
OSGRenderToTexture* nextRTT = new OSGRenderToTexture(512, 512, false, 0); 

osg::ref_ptr<osg::Group> nextGrp = nextRTT->addRTTScene(objectNode.get()).get();

// set up the passes
OSGRenderPass* pass1 = new OSGRenderPass();
pass1->loadShaders("shader/dot3.vert", "shader/dot3.frag");
addPass(pass1); (add pass to STL-Container)

// at this point define the specific shader variables for the shader
// of the specific pass
   
// 1st bind attributes to access render pipline datas
osg::Program* program1 = pass1->getProgram();
program1->addBindAttribLocation("tangent", osg::Drawable::ATTRIBUTE_6);   program1->addBindAttribLocation("binormal",osg::Drawable::ATTRIBUTE_7);
   
// 2nd create and bind the Uniform variables
osg::Uniform* lightU = new osg::Uniform("LIGHT_POSITION", osg::Vec4(pos.x(), pos.y(), pos.z(), 1.0));
pass1->addUniform(lightU);
   
const double* posV = m_viewer->getPosition();
osg::Uniform* viewerU = new osg::Uniform("CAMERA_POSITION", osg::Vec4(posV[0], posV[1], posV[2], 1.0));
pass1->addUniform(viewerU);

// Update callback for dynamic uniform update of light movement
lightU->setUpdateCallback(new OSGShaderLightCallback(light));
viewerU->setUpdateCallback(new OSGShaderViewCallback(m_viewer));

pass1->addUniform(new osg::Uniform("decalMap", 0));
pass1->addUniform(new osg::Uniform("normalMap",1));
pass1->addUniform(new osg::Uniform("matAmbient", light->getAmbient()));
pass1->addUniform(new osg::Uniform("matDiffuse", light->getDiffuse()));
pass1->addUniform(new osg::Uniform("matSpecular",light->getSpecular()));
pass1->addUniform(new osg::Uniform("shinines", 32.0f));

// bind the material (simulates the complex Material Setting)
bindMaterials(pass1->getStateSet());

// bind the stateSet to the object
objectNode->setStateSet(pass1->getStateSet());
 
This is the central mechanism and should be used for each pass you will have to define. Here is the example of the 2nd pass which should use the
rtt result of the first one:

// create RTT for 2nd pass
OSGRenderToTexture* prevRTT = new OSGRenderToTexture(512, 512, false,1);
prevRTT->addRTTScene(objectNode.get()).get();
   
OSGRenderToTexture* accumRTT = new OSGRenderToTexture(512,512,false,2);
osg::ref_ptr<osg::Group> accumGrp = accumRTT->addRTTScene(objectNode.get()).get();

OSGRenderPass* pass2 = new OSGRenderPass();
pass2->loadShaders("shader/motion.vert", "shader/motion.frag");
addPass(pass2);

pass2->addUniform(new osg::Uniform("fBlur", 0.90500f));

// bind rtt textures
pass2->getStateSet()->setTextureAttributeAndModes(0 ,nextRTT->getRTT().get(), osg::StateAttribute::ON);
pass2->addUniform(new osg::Uniform("Next", 0));   

pass2->getStateSet()->setTextureAttributeAndModes(1 ,prevRTT->getRTT().get() ,osg::StateAttribute::ON);
pass2->addUniform(new osg::Uniform("Next", 1));

// render RTT to object for visibilty check
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform();
pat->addChild(accumGrp.get());
pat->setPosition(osg::Vec3(15.0, 0.0, 0.0));
rootNode->addChild(pat.get());

The OSGRenderPass class does nothing special it's only an adapter class. This class adapts an osg::StateSet object as ref_ptr where all values of a pass are set.

And here the fragments for the RTT class:

// Creates a render to texture object
osg::ref_ptr<osg::TextureRectangle> OSGRenderToTexture::createRTT(unsigned int width, unsigned int height, bool hdr)
{
    osg::ref_ptr<osg::TextureRectangle> rtt = new   osg::TextureRectangle();
    rtt->setTextureSize(width, height);

    // define texture filters
    rtt->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
    rtt->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
    rtt->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
    rtt->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
    
    // crate an empty image object
    osg::ref_ptr<osg::Image> image = new osg::Image();

    // define the format
    if(hdr==false){
    	rtt->setInternalFormat(GL_RGBA);        
        image->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
    }
    else{
	rtt->setInternalFormat(GL_FLOAT_RGBA16_NV);
        image->allocateImage(width, height, 1, GL_RGBA, GL_FLOAT);
    }

    // bind the empty image to rtt
    rtt->setImage(image.get());
    
    return rtt;
}

// Creates a quad as rendertarget with the rtt texture on it
osg::ref_ptr<osg::Geode> OSGRenderToTexture::createRenderTargetQuad() //osg::ref_ptr<osg::TextureRectangle> tex)
{
    unsigned int w = rtt->getImage()->s();
    unsigned int h = rtt->getImage()->t();

    std::cout << w;
    std::cout << h;

    osg::Geometry *geometry = new osg::Geometry;
   
    osg::Vec3Array *vx = new osg::Vec3Array;
/*
    vx->push_back( osg::Vec3( 0, 0,-1) );
    vx->push_back( osg::Vec3(w/2, 0,-1) );
    vx->push_back( osg::Vec3(w/2, h/2,-1) );
    vx->push_back( osg::Vec3( 0,  h/2,-1) );
*/
    vx->push_back(osg::Vec3( 2.0, 0, -2.0));
    vx->push_back(osg::Vec3(-2.0, 0, -2.0));
    vx->push_back(osg::Vec3(-2.0, 0,  2.0));
    vx->push_back(osg::Vec3( 2.0, 0,  2.0));

    geometry->setVertexArray(vx);
  
    osg::Vec3Array *nx = new osg::Vec3Array;
    nx->push_back(osg::Vec3(0, -1, 0));
    geometry->setNormalArray(nx);
    geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
    
    // This textures coordenates isn't normalized due
    // the use of TextureRectangles
    osg::Vec2Array *tx = new osg::Vec2Array;
    tx->push_back(osg::Vec2(0, 0));
    tx->push_back(osg::Vec2(w, 0));
    tx->push_back(osg::Vec2(w, h));
    tx->push_back(osg::Vec2(0, h));

    geometry->setTexCoordArray(0, tx);

    geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));

    osg::ref_ptr<osg::StateSet> osgState = geometry->getOrCreateStateSet();

    // bind rtt-Object as texture
    osgState->setTextureAttributeAndModes(0, rtt.get());
       
    // set render modes
    osgState->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    osgState->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);

    //force render as latest object
    osgState->setRenderBinDetails( 10, "RenderBin");

    //create the geode and add the geometry
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(geometry);
    return geode;
};

And finaly the method, where the scene is added to the camera.
// Adds the scene to shown to the rtt-Camera
osg::ref_ptr<osg::Group> OSGRenderToTexture::addRTTScene(osg::Node* scene)
{
    osg::ref_ptr<osg::Group> root = new osg::Group; 

    // add subgraph to render
    camera->addChild(scene);

    // attach the camera to the main scene graph.    
    root->addChild(camera.get());

    //root->addChild(createRenderTargetQuad().get());

    return root;
}

As you can see, nothing special. Hope this clears your questions, so that you could push me on the right way.

Best regards,
Chris


----- Original Message -----
From: stud_info2 at yahoo.de <Art Tevs>
To: osg-users at lists.openscenegraph.org
Date: 12.09.2007 16:21:09
Subject: Re: [osg-users] Multipass shading/rendering


> Hi Chris,
> 
> I have already implemented the things your are
> speaking about. I am calling it osgPPUG: stands for
> osg post processing unit graph. There I can build up a
> graph of post processing units (rtt quads) which can
> do single/multipass, single or multiple rendering
> targets for inputs and outputs and other cool things.
> The osgPPUG is designed to be extendable, so that new
> ppus could be written as plugins.
> 
> 
> I have presented an overview about them on the osg BOF
> at Siggraph last month. I promised to make a node kit
> of them so that it could be used by everyone. However
> I still do not get enough time to prepare the code to
> put it online.
> 
> The code still use some parts of my application, which
> can be safely removed, but the code has to be
> rewritten. If you like to help me in preparing the
> node kit, so I would be very appreciated ;-) Otherwise
> you have either to wait until I publish this as a node
> kit, or write it on your own.
> 
> Of course for more question about this, just contact
> me.
> 
> To answer your question: More code is required to see
> what happens. It could be that you do not properly
> connected shaders with input and output textures. But
> I have to take a look into the code.
> 
> Cheers, Art
> 
> 
> 
> 
> --- hellhound at binary-revolution.org schrieb:
> 
> > Hi,
> > 
> > I need to implement some post processing shader
> > effect, based on multipass 
> > shading/rendering processes. In thiss multipass
> > process each shader could have one or more RTT
> > targets as input and output of the pass.
> > 
> > To realize this i've implemented a render to texture
> > class based on the 
> > osgprerender and osgtexturerectangle examples. This
> > class creates for each
> > instance a texture rectangle and a FBO POST-Process
> > camera by this way:
> >  
> > void createCamera(osg::ref_ptr<osg::Node> subGraph,
> > unsigned int passPos)
> > { 
> >     m_camera = new osg::Camera;
> >     m_camera->setName("rttCamera");
> >     m_camera->setClearColor(m_clearColor);
> >     
> >    
> >
> m_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
> >    
> > m_camera->setViewMatrix(osg::Matrix::identity());
> >    
> > m_camera->setViewport(0,0,windowWidth,windowHeight);
> >     
> >     // define orthogonal projection
> >     
> >
> m_camera->setProjectionMatrix(osg::Matrix::ortho2D(0,windowWidth,0,windowHeight));
> >     
> >     // bind camera as POST-Process Camera with the
> > position value of the pass
> >    
> > m_camera->setRenderOrder(osg::Camera::POST_RENDER,
> > passPos);
> >     
> >     // add subcene to camera to render
> >     m_camera->addChild(subGraph.get());
> > } 
> > 
> > The initialized camera is a member of type
> > osg::ref_ptr<osg::Camera> and the
> > passPos Parameter defines the pass of the shader. 
> > 
> > Each pass is handled as single
> > osg::ref_ptr<osg::StateSet> in a specialised 
> > pass class. For each pass i define the referenced
> > shader and textures which 
> > depends on. So that i have the following object tree
> > structure:
> > 
> > osg::Geometry
> >       osg::Texture2D  "Decal"    
> >       osg::Texture2D  "Normal"
> > 
> >       RTT next (my RTTclass)
> >           RectangleTexture 
> >           Camera (PRE)
> > 
> >       RTT prev(my RTTclass)
> >           RectangleTexture 
> >           osg::CameraNode (PRE) 
> > 
> >       Pass1 "Dot3" (Main)
> >           StateSet
> >              Program
> >              ShaderV
> >                  Attributes
> >                  Uniform
> >                  Uniform
> >              ShaderF
> >                  Uniform
> >                  Uniform
> >              <-- Decal   (in)
> >              <-- Normal  (in)
> >              --> Next    (out)    
> > 
> >       Pass2 
> >           StateSet
> >              Program
> >              ShaderV
> >                  Attributes
> >                  Uniform
> >                  Uniform
> >              ShaderF
> >                  Uniform
> >                  Uniform
> >              <-- Next     (in)
> >              --> Prev     (out to screen (texturized
> > quad))
> > 
> > This works fine, if i use only a single pass shader.
> > In this case the RTT 
> > Texture is rendered to a texturized quad in front of
> > the view. If i use this
> > RTT as input for the second path, and try to render
> > the output of the second
> > rtt on the textured quad nothing is shown where the
> > textured quad should be...
> > 
> > I have no idea what could be wrong or what i've
> > overseen... Perhaps i made 
> > somthing conceptionally wrong. Has anyone
> > implemented a multipass shadering
> > with osg and could me push to the correct sollution?
> > 
> > If you required more code, i will append if i am
> > back from work...
> > 
> > Thanks in advance,
> > best regards
> > Chris
> > 
> > 
> > 
> > 
> > _______________________________________________
> > osg-users mailing list
> > osg-users at lists.openscenegraph.org
> >
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
> > 
> 
> 
> 
>       Wissenswertes für Bastler und Hobby Handwerker. BE A BETTER HEIMWERKER! www.yahoo.de/clever
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
> 






More information about the osg-users mailing list