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