Hi Robert,

I just started seeing something similar at the end of the day yesterday.  I am 
using osg::PointSprite, not using GL_POINT_SPRITE directly.  I have some more 
background too and I think I see the cause, but not the solution.

PointSprite::checkValidityOfAssociatedModes() is great, and it works great and 
is right when called.  But I found an edge case where it's not being called 
although PointSprite is in the scene.

I have a scene that is generated dynamically on user input.  When the Viewer 
starts, there are no points, and there is no PointSprite.  This is when the 
GLObjectsVisitor is called, who is responsible for (among other things) calling 
checkValidityOfAssociatedModes(), due to the Renderer::_compileOnNextDraw flag 
being set.

Later on in some GUIEventHandler, a GL_POINTS drawable is added with 
PointSprite in its stateset.  checkValidityOfAssociatedModes() is never called 
because the Renderer already did its compile pass.  Because it's never called, 
we never get to state.setModeValidity(GL_POINT_SPRITE_ARB, modeValid [false]).

Because of this, the associated mode of PointSprite ends up applying, causing a 
GL error.  Basically, checkValidityOfAssociatedModes() never gets called if 
that mode is not present under the scene, when the scene is first compiled.


Things I tried:

* Adding PointSprite to the osg::View::getCamera() on start-up.  Did not work 
because GLObjectVisitor only visits scene data.  
checkValidityOfAssociatedModes() never called.

* Adding PointSprite to osgViewer::View's root node near setSceneData() call.  
This did work.


I can work around this because I do control my View/Viewer and I can add this 
PointSprite.  But this bug might have other side effects.   Though I'm seeing 
this in GL3/GLCORE, it is not a bug exclusive to GL core nor to Point Sprite. 
(I think)

Attached is a small example that demonstrates the bad behavior.  I know you're 
not currently working on OSG, for me at least this issue can sit for a while.  
But I wanted to provide you with all the info I had while it was fresh in my 
mind.

 - Dan


> -----Original Message-----
> From: osg-users [mailto:[email protected]] On
> Behalf Of Robert Osfield
> Sent: Sunday, July 29, 2018 10:28 AM
> To: OpenSceneGraph Users
> Subject: Re: [osg-users] Core Profile: glEnable/glDisable GL_POINT_SPRITE
> 
> Hi Damian,
> 
> The glEnable/glDisable will be done directed by your scene graph via
> the StateSet::setMode(GLenum,..), so simply remove the
> setMode(GL_POINT_SPRITE).
> 
> Robert.

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/PointSprite>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

osg::Node* createCircle(const osg::Vec4f& color, float radius)
{
    osg::Geode* geode = new osg::Geode;
    osg::Geometry* geom = new osg::Geometry;

    // Draw a simple circle, every 3 degrees
    osg::Vec3Array* vertices = new osg::Vec3Array();
    for (int k = 0; k < 120; ++k)
    {
      double asRadians = osg::DegreesToRadians(3.0 * k);
      vertices->push_back(osg::Vec3(radius * sin(asRadians), 0.0, radius * 
cos(asRadians)));
    }

    osg::Vec4Array* colors = new osg::Vec4Array(osg::Array::BIND_OVERALL);
    colors->push_back(color);

    geom->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, 120));
    geom->setVertexArray(vertices);
    geom->setColorArray(colors);
    geode->addDrawable(geom);

    return geode;
}

osg::Node* createScene()
{
    osg::Group* group = new osg::Group;
    group->addChild(createCircle(osg::Vec4f(0.5, 1, 0.5, 1), 85.f));

    osgText::Text* text = new osgText::Text;
    text->setText("Press any key to turn on PointSprite.");
    text->setCharacterSize(10.f);
    text->setFont("fonts/times.ttf");
    text->setAxisAlignment(osgText::Text::XZ_PLANE);
    text->setAlignment(osgText::Text::CENTER_CENTER);
    group->addChild(text);

    return group;
}

struct PointSpriteAdder : public osgGA::GUIEventHandler
{
  explicit PointSpriteAdder(osg::StateSet* stateSet)
    : stateSet_(stateSet)
  {
  }

  virtual bool handle(const osgGA::GUIEventAdapter& ea, 
osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor* nv)
  {
    if (ea.getEventType() == ea.KEYDOWN)
    {
      //////////////////////////////////////////////////////////////
      // PointSprite::checkValidityOfModes() never gets called here
      OSG_NOTICE << "Turning on Point Sprite.\n";
      stateSet_->setTextureAttributeAndModes(0, new osg::PointSprite);
    }
    return GUIEventHandler::handle(ea, aa, obj, nv);
  }

  osg::ref_ptr<osg::StateSet> stateSet_;
};

int main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc, argv);

    // construct the viewer.
    osgViewer::Viewer viewer(arguments);
    osg::Node* scene = createScene();
    viewer.setSceneData(scene);
    viewer.setUpViewInWindow(100, 100, 800, 600);
    viewer.addEventHandler(new osgViewer::StatsHandler());

    OSG_NOTICE << "Point Sprite Mode Validity Tester\n";
    OSG_NOTICE << "Arguments:\n";
    OSG_NOTICE << "  --camera    Apply osg::PointSprite to Camera's state set 
only\n";
    OSG_NOTICE << "  --scene     Apply osg::PointSprite to Scene's state set 
only\n";
    OSG_NOTICE << "\n";

    if (arguments.read("--camera"))
    {
      OSG_NOTICE << "--camera was detected; this will not call 
PointSprite::checkValidityOfModes().\n";
      OSG_NOTICE << "Try calling with --scene to see 'correct' behavior.\n";

      //////////////////////////////////////////////////////////////
      // PointSprite::checkValidityOfModes() never gets called here
      viewer.getCamera()->getOrCreateStateSet()->setTextureAttributeAndModes(0, 
new osg::PointSprite);
    }
    else if (arguments.read("--scene"))
    {
      OSG_NOTICE << "--scene was detected; this WILL correctly call 
PointSprite::checkValidityOfModes().\n";

      //////////////////////////////////////////////////////////////
      // PointSprite::checkValidityOfModes() will get called here, because the 
scene
      // is traversed by GLObjectsVisitor during first render after 
setSceneData() call.
      // Therefore, this correctly sets up the mode validity on GL_POINT_SPRITE.
      scene->getOrCreateStateSet()->setTextureAttributeAndModes(0, new 
osg::PointSprite);
    }
    else
    {
      OSG_NOTICE << "No arguments detected; this will not correctly call 
PointSprite::checkValidityOfModes().\n";
      OSG_NOTICE << "Try calling with --scene to see 'correct' behavior.\n";
    }

    viewer.addEventHandler(new PointSpriteAdder(scene->getOrCreateStateSet()));

    return viewer.run();
}
cmake_minimum_required(VERSION 2.6)

SET(PROJECT_NAME checkvalidity_bug)

PROJECT(${PROJECT_NAME})

FIND_PACKAGE(OpenThreads)
FIND_PACKAGE(osg)
FIND_PACKAGE(osgDB)
FIND_PACKAGE(osgUtil)
FIND_PACKAGE(osgGA)
FIND_PACKAGE(osgViewer)
FIND_PACKAGE(osgText)

SET(SOURCES
    main.cpp
)

INCLUDE_DIRECTORIES(${OPENTHREADS_INCLUDE_DIR} ${OSG_INCLUDE_DIR})

LINK_DIRECTORIES(${OSG_LIB_DIR})

ADD_EXECUTABLE(${PROJECT_NAME} ${SOURCES})

TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OSG_LIBRARIES} ${OSGVIEWER_LIBRARIES} 
${OSGUTIL_LIBRARIES} ${OSGDB_LIBRARIES} ${OSGGA_LIBRARIES} ${OSGTEXT_LIBRARIES} 
${OPENTHREADS_LIBRARIES})
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to