Fair enough.. I do understand the frustration of supporting unfamiliar devs in 
an FOSS project.

I already understand and agree with your post, but I think you took me wrong 
I'm not making a big deal out of anything and value OSG highly. 


Based on your post I'll move on to something more concrete: Attached is a 
example OSG program in OSG 3.4.1 demonstrating vertex attribute aliasing 
causing issues.

There are 8 option permutations to try viewing cow.osg and a osgParticle system 
with vertex attribute aliasing, uniforms, and shader based particles either on 
or off. A number provided as a command line arg decides the case.

The results are:

Code:
                // 8 pemutations of 3 options, 0-7
                // Case 4 : Black cow (vertex attrib aliasing)
                // Case 5 : Black cow, purple particle smoke (vertex attrib 
aliasing, shaders)
                // Case 6 : Black cow (vertex attrib aliasing, 
modelviewandprojectionuniforms)
                // Other cases: Shiny cow, white particles




And I can't seem to turn it on only for the required programs and off otherwise.


Since I can't use legacy gl_* uniforms/attribs in modern shaders you need OSG 
to set them or to set them yourself. And if you can't enable vertex attrib 
aliasing or modelviewandprojectionuniforms because they break other things as 
above you can end up trying unusual things and causing grief on the support 
mailing list.

------------------------
http://www.hrwallingford.com/facilities/ship-simulation-centre 
(http://www.hrwallingford.com/facilities/ship-simulation-centre)

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71568#71568



/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commercial and non commercial 
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/Types>
#include <osgText/Text>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

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

#include <osgGA/Device>

#include <iostream>

#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osg/Point>
#include <osg/PointSprite>


#include <osgParticle/ParticleSystem>
#include <osgParticle/ParticleSystemUpdater>
#include <osgParticle/ModularEmitter>
#include <osgParticle/ModularProgram>

#include <osgParticle/AccelOperator>
#include <osgParticle/DampingOperator>
#include <osgParticle/BounceOperator>
#include <osgParticle/SinkOperator>

void createFountainEffect(osgParticle::ModularEmitter* emitter, 
osgParticle::ModularProgram* program)
{
        // Emit specific number of particles every frame
        osg::ref_ptr<osgParticle::RandomRateCounter> rrc = new 
osgParticle::RandomRateCounter;
        rrc->setRateRange(500, 2000);

        // Accelerate particles in the given gravity direction.
        osg::ref_ptr<osgParticle::AccelOperator> accel = new 
osgParticle::AccelOperator;
        accel->setToGravity();

        // Multiply each particle's velocity by a damping constant.
        osg::ref_ptr<osgParticle::DampingOperator> damping = new 
osgParticle::DampingOperator;
        damping->setDamping(0.9f);

        // Bounce particles off objects defined by one or more domains.
        // Supported domains include triangle, rectangle, plane, disk and 
sphere.
        // Since a bounce always happens instantaneously, it will not work 
correctly with unstable delta-time.
        // At present, even the floating error of dt (which are applied to 
ParticleSystem and Operator separately)
        // causes wrong bounce results. Some one else may have better solutions 
for this.
        osg::ref_ptr<osgParticle::BounceOperator> bounce = new 
osgParticle::BounceOperator;
        bounce->setFriction(-0.05);
        bounce->setResilience(0.35);
        bounce->addDiskDomain(osg::Vec3(0.0f, 0.0f, -2.0f), osg::Z_AXIS, 8.0f);
        bounce->addPlaneDomain(osg::Plane(osg::Z_AXIS, 5.0f));

        // Kill particles going inside/outside of specified domains.
        osg::ref_ptr<osgParticle::SinkOperator> sink = new 
osgParticle::SinkOperator;
        sink->setSinkStrategy(osgParticle::SinkOperator::SINK_OUTSIDE);
        sink->addSphereDomain(osg::Vec3(), 20.0f);

        emitter->setCounter(rrc.get());
        program->addOperator(accel.get());
        program->addOperator(damping.get());
        program->addOperator(bounce.get());
        program->addOperator(sink.get());
}

const std::string 
OSG_DATA_FOLDER("C:/Users/User/Desktop/OpenSceneGraph/OpenSceneGraph-Data/");

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

        auto useVertexAttributeAliasing = false;
        auto useModelViewAndProjectionUniforms = true;
        bool useShaders = false;
        if (argc > 1) {
                auto caseNo = atoi(argv[1]);
                // 8 pemutations of 3 options, 0-7
                // Case 4 : Black cow
                // Case 5 : Black cow, purple particle smoke
                // Case 6 : Black cow
                useVertexAttributeAliasing = (0x4 & caseNo)!=0;
                useModelViewAndProjectionUniforms = (0x2 & caseNo) != 0;
                useShaders = (0x1 & caseNo) != 0;
        }

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

        osgViewer::Viewer viewer(arguments);

        std::string textureFile(OSG_DATA_FOLDER + "Images/smoke.rgb");
        while (arguments.read("--texture", textureFile)) {}

        float pointSize = 20.0f;
        while (arguments.read("--point", pointSize)) {}

        double visibilityDistance = -1.0f;
        while (arguments.read("--visibility", visibilityDistance)) {}

        bool customShape = false;
        while (arguments.read("--enable-custom")) { customShape = true; }

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

        // 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());
                keyswitchManipulator->addMatrixManipulator('5', "Orbit", new 
osgGA::OrbitManipulator());
                keyswitchManipulator->addMatrixManipulator('6', "FirstPerson", 
new osgGA::FirstPersonManipulator());
                keyswitchManipulator->addMatrixManipulator('7', "Spherical", 
new osgGA::SphericalManipulator());

                std::string pathfile;
                double animationSpeed = 1.0;
                while (arguments.read("--speed", animationSpeed)) {}
                char keyForAnimationPath = '8';
                while (arguments.read("-p", pathfile))
                {
                        osgGA::AnimationPathManipulator* apm = new 
osgGA::AnimationPathManipulator(pathfile);
                        if (apm || !apm->valid())
                        {
                                apm->setTimeScale(animationSpeed);

                                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);

        // load the data
        osg::ref_ptr<osg::Node> loadedModel = 
osgDB::readRefNodeFiles(arguments);

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

        /***
        Customize particle template and system attributes
        ***/
        osg::ref_ptr<osgParticle::ParticleSystem> ps = new 
osgParticle::ParticleSystem;

        ps->getDefaultParticleTemplate().setLifeTime(5.0f);

        if (customShape)
        {
                // osgParticle now supports making use of customized drawables. 
The draw() method will be executed
                // and display lists will be called for each particle. It is 
always a huge consumption of memory, and
                // hardly to use shaders to render them, so please be careful 
using this feature.
                
ps->getDefaultParticleTemplate().setShape(osgParticle::Particle::USER);
                ps->getDefaultParticleTemplate().setDrawable(new 
osg::ShapeDrawable(new osg::Box(osg::Vec3(), 1.0f)));
                useShaders = false;
        }
        else
        {
                // The shader only supports rendering points at present.
                
ps->getDefaultParticleTemplate().setShape(osgParticle::Particle::POINT);
        }

        // Set the visibility distance of particles, due to their Z-value in 
the eye coordinates.
        // Particles that are out of the distance (or behind the eye) will not 
be rendered.
        ps->setVisibilityDistance(visibilityDistance);

        if (useShaders)
        {
                // Set using local GLSL shaders to render particles.
                // At present, this is slightly efficient than ordinary 
methods. The bottlenack here seems to be the cull
                // traversal time. Operators go through the particle list again 
and again...
                ps->setDefaultAttributesUsingShaders(textureFile, true, 0);
        }
        else
        {
                // The default methods uses glBegin()/glEnd() pairs. 
Fortunately the GLBeginEndAdapter does improve the
                // process, which mimics the immediate mode with glDrawArrays().
                ps->setDefaultAttributes(textureFile, true, false, 0);

                // Without the help of shaders, we have to sort particles to 
make the visibility distance work. Sorting is
                // also useful in rendering transparent particles in 
back-to-front order.
                if (visibilityDistance>0.0)
                        
ps->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
        }

        // At last, to make the point sprite work, we have to set the points 
size and the sprite attribute.
        osg::StateSet* stateset = ps->getOrCreateStateSet();
        stateset->setAttribute(new osg::Point(pointSize));
        stateset->setTextureAttributeAndModes(0, new osg::PointSprite, 
osg::StateAttribute::ON);

        /***
        Construct other particle system elements, including the emitter and 
program
        ***/
        osg::ref_ptr<osgParticle::ModularEmitter> emitter = new 
osgParticle::ModularEmitter;
        emitter->setParticleSystem(ps.get());

        osg::ref_ptr<osgParticle::ModularProgram> program = new 
osgParticle::ModularProgram;
        program->setParticleSystem(ps.get());

        createFountainEffect(emitter.get(), program.get());

        /***
        Add the entire particle system to the scene graph
        ***/
        osg::ref_ptr<osg::MatrixTransform> parent = new osg::MatrixTransform;
        parent->addChild(emitter.get());
        parent->addChild(program.get());

        // The updater can receive particle systems as child drawables now. The 
addParticleSystem() method
        // is still usable, with which we should define another geode to 
contain a particle system.
        osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater = new 
osgParticle::ParticleSystemUpdater;
        //updater->addDrawable( ps.get() );

        osg::ref_ptr<osg::Group> root = new osg::Group;
        root->addChild(parent.get());
        root->addChild(updater.get());

        // FIXME 2010.9.19: the updater can't be a drawable; otehrwise the 
ParticleEffect will not work properly. why?
        updater->addParticleSystem(ps.get());

        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
        geode->addDrawable(ps.get());
        root->addChild(geode.get());

        std::string cowFile(OSG_DATA_FOLDER + "cow.osg");
        auto cow = osgDB::readNodeFile(cowFile);
        root->addChild(cow);
        
        viewer.setSceneData(root);

        viewer.realize();

        auto cams = std::vector<osg::Camera*>();


        viewer.getCameras(cams, false);
        for (int i = 0; i < cams.size(); i++) {
                if(cams.at(i)->getGraphicsContext() ) 
cams.at(i)->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(useVertexAttributeAliasing);
                if (cams.at(i)->getGraphicsContext()) 
cams.at(i)->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(useModelViewAndProjectionUniforms);
        }

        viewer.run();


}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to