[osg-users] Speeding Up osgText?

Kawicki, Ryan H Ryan.H.Kawicki at boeing.com
Fri Sep 5 14:01:18 PDT 2008


This is in reference to a previous question that has been posed.  Sorry
if this has already been addressed.

http://lists.openscenegraph.org/htdig.cgi/osg-users-openscenegraph.org/2
008-April/009652.html

Our application seems to be hitting this same issue.  We are trying to
render quite a bit of text on the screen, and we seem to be getting
burned by both the setText( ... ) and the drawImplementation.

We are currently using an older version of OSG, but we are planning on
moving to 2.6.0 relatively soon.  I have looked at our current version
of osgText and the 2.6.0 version and can conclude that this will still
be an issue.

Our application is building the text shapes with SCREEN_COORDS for the
character size mode and SCREEN for axis alignment.

What I have noticed is that for each text shape update, the function
computeGlyphRepresentation is called to recompute the glyph information.
This function then calls the function computePositions.  Here is what
compute positions looks like.

void Text::computePositions()
{
    unsigned int size =
osg::maximum(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsCon
texts(),_autoTransformCache.size());
    
    // FIXME: OPTIMIZE: This would be one of the ideal locations to
    // call computeAverageGlypthWidthAndHeight(). It is out of the
contextID loop
    // so the value would be computed fewer times. But the code will
need changes
    // to get the value down to the locations it is needed. (Either pass
through parameters
    // or member variables, but we would need a system to know if the
values are stale.)

    for(unsigned int i=0;i<size;++i)
    {
         computePositions(i);
    }
}

As can be seen by the first line, the maximum size is being obtained
from the maximum number of graphics contexts or the size of
_autoTransformCache.  For me this is set to 32, since the default was
never being changed.  The computePositions function is a very expensive
operation, and a minor flaw in our design was causing a huge impact in
performance.  It might be a good idea to either assert on or to check
the traversalNumber from the _autoTransformCache to make sure the
context is a valid one.

Performance is still down for our application.  I think some of the
problem is related to this computePositions function still.  Our
application is frequently setting text, so we incur a CPU hit to
recalculate all the glyph vertices.  When the text is visible, we incur
the same CPU hit to recalculate all the glyph vertices since the
_autoTransformCache model view matrix are always different between the
update of the text and the current state of the draw phase.  Here's the
draw implementation for text.

void Text::drawImplementation(osg::State& state) const
{
    unsigned int contextID = state.getContextID();

    < CODE REMOVED >

    if (_characterSizeMode!=OBJECT_COORDS || _autoRotateToScreen)
    {
        < CODE REMOVED >

        AutoTransformCache& atc = _autoTransformCache[contextID];
        const osg::Matrix& modelview = state.getModelViewMatrix();
        const osg::Matrix& projection = state.getProjectionMatrix();

        < CODE REMOVED >

        bool doUpdate = atc._traversalNumber==-1;
        if (atc._traversalNumber>=0)
        {
            if (atc._modelview!=modelview)
            {
                doUpdate = true;
            }
            else if (width!=atc._width || height!=atc._height)
            {
                doUpdate = true;
            }
            else if (atc._projection!=projection)
            {
                doUpdate = true;
            }
        }
        
        atc._traversalNumber = frameNumber;
        atc._width = width;
        atc._height = height;
        
        if (doUpdate)
        {    
            atc._transformedPosition = newTransformedPosition;
            atc._projection = projection;
            atc._modelview = modelview;

            computePositions(contextID);
        }
        
    }

    < CODE REMOVED >
}

With the draw implementation above and the setText all being called
within a render frame, we are computing the glyph vertices twice.  I
think we can speed things up a bit, but I need some information.

Is there a reason as to why we need to call computePositions from within
computeGlyphRepresentation if the drawImplementation will already take
care of that?  As far as I can see, computeGlyphRepresentation is
already doing the calculations for the bounding box.  Makes sense that
we only have that information.  We can then just allow the
drawImplementation do the nasty work of recalculating the vertices by
calling computePositions.

Does anyone have any suggestions that might help in improving
performance?  I am wondering if some of this work could be moved from
the CPU and pushed to the GPU.

Sorry for the long post and thanks for any suggestions.

Ryan H. Kawicki
The Boeing Company
Training Systems & Services
Software Engineer



More information about the osg-users mailing list