From 47db2da8b4f7cce1bcb092196a3fc6ebbcdc9e84 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 25 Feb 2015 18:56:29 +0000 Subject: [PATCH] From Andreas Henne, Support for GL3 core profile in osgText git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14717 16af8721-9629-0410-8352-f15c8da7e697 --- examples/osgfont/osgfont.cpp | 15 +- examples/osgtext/osgtext.cpp | 74 +++++++ include/osgText/Glyph | 9 + include/osgText/Text | 15 +- src/osgPlugins/freetype/FreeTypeFont.cpp | 6 +- src/osgQt/QFontImplementation.cpp | 6 +- src/osgText/DefaultFont.cpp | 6 +- src/osgText/Glyph.cpp | 10 +- src/osgText/Text.cpp | 257 +++++++++++++++-------- src/osgWidget/Input.cpp | 2 +- 10 files changed, 282 insertions(+), 118 deletions(-) diff --git a/examples/osgfont/osgfont.cpp b/examples/osgfont/osgfont.cpp index 728708edb..976c1e28d 100644 --- a/examples/osgfont/osgfont.cpp +++ b/examples/osgfont/osgfont.cpp @@ -19,17 +19,10 @@ void textInfo(osgText::Text* text) for(unsigned int i = 0; i < s.size(); i++) { - osg::Vec2 ul = gq.getCoords()[0 + (i * 4)]; // upperLeft - osg::Vec2 ll = gq.getCoords()[1 + (i * 4)]; // lowerLeft - osg::Vec2 lr = gq.getCoords()[2 + (i * 4)]; // lowerRight - osg::Vec2 ur = gq.getCoords()[3 + (i * 4)]; // upperRight - - /* - osg::Vec3 ul = gq.getTransformedCoords(0)[0 + (i * 4)]; - osg::Vec3 ll = gq.getTransformedCoords(0)[1 + (i * 4)]; - osg::Vec3 lr = gq.getTransformedCoords(0)[2 + (i * 4)]; - osg::Vec3 ur = gq.getTransformedCoords(0)[3 + (i * 4)]; - */ + osg::Vec2 ul = (*gq.getCoords())[0 + (i * 4)]; // upperLeft + osg::Vec2 ll = (*gq.getCoords())[1 + (i * 4)]; // lowerLeft + osg::Vec2 lr = (*gq.getCoords())[2 + (i * 4)]; // lowerRight + osg::Vec2 ur = (*gq.getCoords())[3 + (i * 4)]; // upperRight osg::notify(osg::NOTICE) << "'" << static_cast(s[i]) << "':" diff --git a/examples/osgtext/osgtext.cpp b/examples/osgtext/osgtext.cpp index 71a02065c..b7f45104e 100644 --- a/examples/osgtext/osgtext.cpp +++ b/examples/osgtext/osgtext.cpp @@ -36,6 +36,39 @@ #include #include +// These shaders are only required for GL3/GL4 core profile. +// The fragment shader uses the red component of the font texture and not the alpha channel (GL_ALPHA is deprecated in the core profile),. +// osgText will write to GL_RED instead of GL_ALPHA if it is compiled with OSG_GL3_AVAILABLE but not with OSG_GL2_AVAILABLE or OSG_GL1_AVAILABLE. +#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE) +static const char *gl3TextVertexShader = { + "#version 330 core\n" + "in vec4 osg_Vertex;\n" + "in vec4 osg_Color;\n" + "in vec4 osg_MultiTexCoord0;\n" + "uniform mat4 osg_ModelViewProjectionMatrix;\n" + "out vec2 texCoord;\n" + "out vec4 vertexColor;\n" + "void main(void)\n" + "{\n" + " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex;\n" + " texCoord = osg_MultiTexCoord0.xy;\n" + " vertexColor = osg_Color; \n" + "}\n" +}; + +static const char *gl3TextFragmentShader = { + "#version 330 core\n" + "uniform sampler2D glyphTexture;\n" + "in vec2 texCoord;\n" + "in vec4 vertexColor;\n" + "out vec4 color;\n" + "void main(void)\n" + "{\n" + " color = vertexColor * texture(glyphTexture, texCoord).rrrr;\n" + "}\n" +}; +#endif + osg::Group* createHUDText() { @@ -44,9 +77,20 @@ osg::Group* createHUDText() osgText::Font* font = osgText::readFontFile("fonts/arial.ttf"); + osg::setNotifyLevel(osg::INFO); + osg::Geode* geode = new osg::Geode; rootNode->addChild(geode); + bool useVBOs = false; +#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE) + useVBOs = true; + osg::Program* program = new osg::Program; + program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3TextVertexShader)); + program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl3TextFragmentShader)); + geode->getOrCreateStateSet()->setAttributeAndModes(program, osg::StateAttribute::ON); +#endif + float windowHeight = 1024.0f; float windowWidth = 1280.0f; float margin = 50.0f; @@ -62,6 +106,7 @@ osg::Group* createHUDText() { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(layoutColor); text->setCharacterSize(layoutCharacterSize); @@ -77,6 +122,7 @@ osg::Group* createHUDText() { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(layoutColor); text->setCharacterSize(layoutCharacterSize); @@ -92,6 +138,7 @@ osg::Group* createHUDText() { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(layoutColor); text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f)); @@ -117,6 +164,7 @@ osg::Group* createHUDText() { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(fontSizeColor); text->setCharacterSize(fontSizeCharacterSize); @@ -132,6 +180,7 @@ osg::Group* createHUDText() cursor.y() -= fontSizeCharacterSize; { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(fontSizeColor); text->setCharacterSize(fontSizeCharacterSize); @@ -147,6 +196,7 @@ osg::Group* createHUDText() cursor.y() -= fontSizeCharacterSize; { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(fontSizeColor); text->setCharacterSize(fontSizeCharacterSize); @@ -171,6 +221,7 @@ osg::Group* createHUDText() { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(characterSizeColor); text->setFontResolution(20,20); @@ -186,6 +237,7 @@ osg::Group* createHUDText() cursor.y() -= 30.0f; { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(characterSizeColor); text->setFontResolution(30,30); @@ -201,6 +253,7 @@ osg::Group* createHUDText() cursor.y() -= 50.0f; { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setFont(font); text->setColor(characterSizeColor); text->setFontResolution(40,40); @@ -292,6 +345,7 @@ osg::Group* createHUDText() { osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setColor(fontColor); text->setPosition(cursor); text->setCharacterSize(fontCharacterSize); @@ -307,6 +361,7 @@ osg::Group* createHUDText() osgText::Font* arial = osgText::readFontFile("fonts/arial.ttf"); osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setColor(fontColor); text->setPosition(cursor); text->setCharacterSize(fontCharacterSize); @@ -324,6 +379,7 @@ osg::Group* createHUDText() osgText::Font* times = osgText::readFontFile("fonts/times.ttf"); osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setColor(fontColor); text->setPosition(cursor); text->setCharacterSize(fontCharacterSize); @@ -344,6 +400,7 @@ osg::Group* createHUDText() osgText::Font* dirtydoz = osgText::readFontFile("fonts/dirtydoz.ttf"); osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setColor(fontColor); text->setPosition(cursor); text->setCharacterSize(fontCharacterSize); @@ -361,6 +418,7 @@ osg::Group* createHUDText() osgText::Font* fudd = osgText::readFontFile("fonts/fudd.ttf"); osgText::Text* text = new osgText::Text; + text->setUseVertexBufferObjects(useVBOs); text->setColor(fontColor); text->setPosition(cursor); text->setCharacterSize(fontCharacterSize); @@ -386,6 +444,15 @@ osg::Group* create3DText(const osg::Vec3& center,float radius) osg::Geode* geode = new osg::Geode; + bool useVBOs = false; +#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE) + useVBOs = true; + osg::Program* program = new osg::Program; + program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3TextVertexShader)); + program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl3TextFragmentShader)); + geode->getOrCreateStateSet()->setAttributeAndModes(program, osg::StateAttribute::ON); +#endif + //////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -398,6 +465,7 @@ osg::Group* create3DText(const osg::Vec3& center,float radius) osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f); osgText::Text* text1 = new osgText::Text; + text1->setUseVertexBufferObjects(useVBOs); text1->setFont("fonts/times.ttf"); text1->setCharacterSize(characterSize); text1->setPosition(pos); @@ -406,6 +474,7 @@ osg::Group* create3DText(const osg::Vec3& center,float radius) geode->addDrawable(text1); osgText::Text* text2 = new osgText::Text; + text2->setUseVertexBufferObjects(useVBOs); text2->setFont("fonts/times.ttf"); text2->setCharacterSize(characterSize); text2->setPosition(pos); @@ -414,6 +483,7 @@ osg::Group* create3DText(const osg::Vec3& center,float radius) geode->addDrawable(text2); osgText::Text* text3 = new osgText::Text; + text3->setUseVertexBufferObjects(useVBOs); text3->setFont("fonts/times.ttf"); text3->setCharacterSize(characterSize); text3->setPosition(pos); @@ -424,6 +494,7 @@ osg::Group* create3DText(const osg::Vec3& center,float radius) osg::Vec4 characterSizeModeColor(1.0f,0.0f,0.5f,1.0f); osgText::Text* text4 = new osgText::Text; + text4->setUseVertexBufferObjects(useVBOs); text4->setFont("fonts/times.ttf"); text4->setCharacterSize(characterSize); text4->setPosition(center); @@ -437,6 +508,7 @@ osg::Group* create3DText(const osg::Vec3& center,float radius) geode->addDrawable(text4); osgText::Text* text5 = new osgText::Text; + text5->setUseVertexBufferObjects(useVBOs); text5->setColor(characterSizeModeColor); text5->setFont("fonts/times.ttf"); //text5->setCharacterSize(characterSize); @@ -449,6 +521,7 @@ osg::Group* create3DText(const osg::Vec3& center,float radius) geode->addDrawable(text5); osgText::Text* text6 = new osgText::Text; + text6->setUseVertexBufferObjects(useVBOs); text6->setColor(characterSizeModeColor); text6->setFont("fonts/times.ttf"); text6->setCharacterSize(characterSize); @@ -459,6 +532,7 @@ osg::Group* create3DText(const osg::Vec3& center,float radius) geode->addDrawable(text6); osgText::Text* text7 = new osgText::Text; + text7->setUseVertexBufferObjects(useVBOs); text7->setColor(characterSizeModeColor); text7->setFont("fonts/times.ttf"); text7->setCharacterSize(characterSize); diff --git a/include/osgText/Glyph b/include/osgText/Glyph index b84f4a499..41bed4d8d 100644 --- a/include/osgText/Glyph +++ b/include/osgText/Glyph @@ -30,6 +30,15 @@ #include +// GL_ALPHA is deprecated in GL3/GL4 core profile, use GL_RED and a shader in this case. See osgText example. +#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE) +#define OSGTEXT_GLYPH_FORMAT GL_RED +#define OSGTEXT_GLYPH_INTERNALFORMAT GL_R8 +#else +#define OSGTEXT_GLYPH_FORMAT GL_ALPHA +#define OSGTEXT_GLYPH_INTERNALFORMAT GL_ALPHA +#endif + namespace osgText { class Font; diff --git a/include/osgText/Text b/include/osgText/Text index 89a67ff75..df0414552 100644 --- a/include/osgText/Text +++ b/include/osgText/Text @@ -299,10 +299,10 @@ public: { typedef std::vector Glyphs; typedef std::vector LineNumbers; - typedef std::vector Coords2; - typedef std::vector Coords3; - typedef std::vector TexCoords; - typedef std::vector ColorCoords; + typedef osg::ref_ptr Coords2; + typedef osg::ref_ptr Coords3; + typedef osg::ref_ptr TexCoords; + typedef osg::ref_ptr ColorCoords; Glyphs _glyphs; Coords2 _coords; @@ -313,6 +313,13 @@ public: osg::buffered_object _transformedBackdropCoords[8]; ColorCoords _colorCoords; + osg::ref_ptr _quadIndices; + void updateQuadIndices(); + + GlyphQuads(); + + void initGPUBufferObjects(); + Glyphs getGlyphs() { return _glyphs; } const Glyphs getGlyphs() const { return _glyphs; } diff --git a/src/osgPlugins/freetype/FreeTypeFont.cpp b/src/osgPlugins/freetype/FreeTypeFont.cpp index 8af1470d8..eded9a976 100644 --- a/src/osgPlugins/freetype/FreeTypeFont.cpp +++ b/src/osgPlugins/freetype/FreeTypeFont.cpp @@ -347,13 +347,13 @@ osgText::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, u for(unsigned char* p=data;psetImage(width,height,1, - GL_ALPHA, - GL_ALPHA,GL_UNSIGNED_BYTE, + OSGTEXT_GLYPH_INTERNALFORMAT, + OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); - glyph->setInternalTextureFormat(GL_ALPHA); + glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT); // copy image across to osgText::Glyph image. switch(glyphslot->bitmap.pixel_mode) diff --git a/src/osgQt/QFontImplementation.cpp b/src/osgQt/QFontImplementation.cpp index 8b5e28d09..bc54204b9 100644 --- a/src/osgQt/QFontImplementation.cpp +++ b/src/osgQt/QFontImplementation.cpp @@ -90,12 +90,12 @@ QFontImplementation::getGlyph(const osgText::FontResolution& fontRes, unsigned i // the glyph texture in osg glyph->setImage(imageWidth, imageHeight, 1, - GL_ALPHA, - GL_ALPHA, GL_UNSIGNED_BYTE, + OSGTEXT_GLYPH_INTERNALFORMAT, + OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); - glyph->setInternalTextureFormat(GL_ALPHA); + glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT); glyph->setWidth((float)imageWidth * coord_scale); glyph->setHeight((float)imageHeight * coord_scale); diff --git a/src/osgText/DefaultFont.cpp b/src/osgText/DefaultFont.cpp index 87ca39322..390705485 100644 --- a/src/osgText/DefaultFont.cpp +++ b/src/osgText/DefaultFont.cpp @@ -198,13 +198,13 @@ void DefaultFont::constructGlyphs() for(unsigned char* p=data;psetImage(sourceWidth,sourceHeight,1, - GL_ALPHA, - GL_ALPHA,GL_UNSIGNED_BYTE, + OSGTEXT_GLYPH_INTERNALFORMAT, + OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); - glyph->setInternalTextureFormat(GL_ALPHA); + glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT); // now populate data array by converting bitmap into a luminance_alpha map. unsigned char* ptr = rasters[i-32]; diff --git a/src/osgText/Glyph.cpp b/src/osgText/Glyph.cpp index 8bd2d8abf..3f98eb23a 100644 --- a/src/osgText/Glyph.cpp +++ b/src/osgText/Glyph.cpp @@ -187,7 +187,7 @@ void GlyphTexture::apply(osg::State& state) const // being bound for the first time, need to allocate the texture _textureObjectBuffer[contextID] = textureObject = osg::Texture::generateTextureObject( - this, contextID,GL_TEXTURE_2D,1,GL_ALPHA,getTextureWidth(), getTextureHeight(),1,0); + this, contextID, GL_TEXTURE_2D, 1, OSGTEXT_GLYPH_INTERNALFORMAT, getTextureWidth(), getTextureHeight(), 1, 0); textureObject->bind(); @@ -228,9 +228,9 @@ void GlyphTexture::apply(osg::State& state) const #endif // allocate the texture memory. - glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, + glTexImage2D(GL_TEXTURE_2D, 0, OSGTEXT_GLYPH_INTERNALFORMAT, getTextureWidth(), getTextureHeight(), 0, - GL_ALPHA, + OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, imageData ); @@ -382,7 +382,7 @@ void GlyphTexture::apply(osg::State& state) const glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, getTextureWidth(), getTextureHeight(), - GL_ALPHA, GL_UNSIGNED_BYTE, local_data ); + OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, local_data); #if defined(OSG_GLES2_AVAILABLE) if (requiresGenerateMipmapCall) glGenerateMipmap(GL_TEXTURE_2D); @@ -433,7 +433,7 @@ void GlyphTexture::resizeGLObjectBuffers(unsigned int maxSize) osg::Image* GlyphTexture::createImage() { osg::ref_ptr image = new osg::Image; - image->allocateImage(getTextureWidth(), getTextureHeight(), 1, GL_ALPHA, GL_UNSIGNED_BYTE); + image->allocateImage(getTextureWidth(), getTextureHeight(), 1, OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE); memset(image->data(), 0, image->getTotalSizeInBytes()); for(GlyphRefList::iterator itr = _glyphs.begin(); diff --git a/src/osgText/Text.cpp b/src/osgText/Text.cpp index 0b70b7d51..930ecc634 100644 --- a/src/osgText/Text.cpp +++ b/src/osgText/Text.cpp @@ -41,7 +41,9 @@ Text::Text(): _colorGradientBottomLeft(0.0f, 1.0f, 0.0f, 1.0f), _colorGradientBottomRight(0.0f, 0.0f, 1.0f, 1.0f), _colorGradientTopRight(1.0f, 1.0f, 1.0f, 1.0f) -{} +{ + _supportsVertexBufferObjects = true; +} Text::Text(const Text& text,const osg::CopyOp& copyop): osgText::TextBase(text,copyop), @@ -442,16 +444,16 @@ void Text::computeGlyphRepresentation() osg::Vec2 lowLeft = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin); osg::Vec2 lowRight = local+osg::Vec2(width+fHorizQuadMargin,0.0f-fVertQuadMargin); osg::Vec2 upRight = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin); - glyphquad._coords.push_back(upLeft); - glyphquad._coords.push_back(lowLeft); - glyphquad._coords.push_back(lowRight); - glyphquad._coords.push_back(upRight); + glyphquad._coords->push_back(upLeft); + glyphquad._coords->push_back(lowLeft); + glyphquad._coords->push_back(lowRight); + glyphquad._coords->push_back(upRight); // set up the tex coords of the quad - glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),maxtc.y())); - glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),mintc.y())); - glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),mintc.y())); - glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),maxtc.y())); + glyphquad._texcoords->push_back(osg::Vec2(mintc.x(), maxtc.y())); + glyphquad._texcoords->push_back(osg::Vec2(mintc.x(), mintc.y())); + glyphquad._texcoords->push_back(osg::Vec2(maxtc.x(), mintc.y())); + glyphquad._texcoords->push_back(osg::Vec2(maxtc.x(), maxtc.y())); // move the cursor onto the next character. // also expand bounding box @@ -521,6 +523,17 @@ void Text::computeGlyphRepresentation() } + for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin(); + titr!=_textureGlyphQuadMap.end(); + ++titr) + { + titr->second.updateQuadIndices(); + if (_useVertexBufferObjects) + { + titr->second.initGPUBufferObjects(); + } + } + TextBase::computePositions(); computeBackdropBoundingBox(); computeBoundingBoxMargin(); @@ -557,10 +570,10 @@ bool Text::computeAverageGlyphWidthAndHeight(float& avg_width, float& avg_height { const GlyphQuads& glyphquad = const_titr->second; const GlyphQuads::Coords2& coords2 = glyphquad._coords; - for(i = 0; i < coords2.size(); i+=4) + for (i = 0; i < coords2->size(); i += 4) { - width = coords2[i+2].x() - coords2[i].x(); - height = coords2[i].y() - coords2[i+1].y(); + width = (*coords2)[i + 2].x() - (*coords2)[i].x(); + height = (*coords2)[i].y() - (*coords2)[i + 1].y(); running_width += width; running_height += height; @@ -713,16 +726,17 @@ void Text::computePositions(unsigned int contextID) const GlyphQuads::Coords2& coords2 = glyphquad._coords; GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; - unsigned int numCoords = coords2.size(); - if (numCoords!=transformedCoords.size()) + unsigned int numCoords = coords2->size(); + if (numCoords != transformedCoords->size()) { - transformedCoords.resize(numCoords); + transformedCoords->resize(numCoords); } for(unsigned int i=0;idirty(); } computeBackdropPositions(contextID); @@ -790,10 +804,10 @@ void Text::computeBackdropPositions(unsigned int contextID) const for( ; backdrop_index < max_backdrop_index; backdrop_index++) { GlyphQuads::Coords3& transformedCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; - unsigned int numCoords = coords2.size(); - if (numCoords!=transformedCoords.size()) + unsigned int numCoords = coords2->size(); + if (numCoords!=transformedCoords->size()) { - transformedCoords.resize(numCoords); + transformedCoords->resize(numCoords); } for(i=0;idirty(); } } } @@ -1056,24 +1071,24 @@ void Text::computeColorGradientsOverall() const const GlyphQuads& glyphquad = const_titr->second; const GlyphQuads::Coords2& coords2 = glyphquad._coords; - for(i=0;isize();++i) { // Min and Max are needed for color gradients - if(coords2[i].x() > max_x) + if((*coords2)[i].x() > max_x) { - max_x = coords2[i].x(); + max_x = (*coords2)[i].x(); } - if(coords2[i].x() < min_x) + if ((*coords2)[i].x() < min_x) { - min_x = coords2[i].x(); + min_x = (*coords2)[i].x(); } - if(coords2[i].y() > max_y) + if ((*coords2)[i].y() > max_y) { - max_y = coords2[i].y(); + max_y = (*coords2)[i].y(); } - if(coords2[i].y() < min_y) + if ((*coords2)[i].y() < min_y) { - min_y = coords2[i].y(); + min_y = (*coords2)[i].y(); } } @@ -1087,10 +1102,10 @@ void Text::computeColorGradientsOverall() const GlyphQuads::Coords2& coords2 = glyphquad._coords; GlyphQuads::ColorCoords& colorCoords = glyphquad._colorCoords; - unsigned int numCoords = coords2.size(); - if (numCoords!=colorCoords.size()) + unsigned int numCoords = coords2->size(); + if (numCoords!=colorCoords->size()) { - colorCoords.resize(numCoords); + colorCoords->resize(numCoords); } for(i=0;isize(); + if (numCoords!=colorCoords->size()) { - colorCoords.resize(numCoords); + colorCoords->resize(numCoords); } for(unsigned int i=0;isecond; - if ( glyphquad._transformedCoords[contextID].empty() ) + if ( glyphquad._transformedCoords[contextID]->empty() ) { computePositions(contextID); } @@ -1385,6 +1400,10 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie { renderWithDelayedDepthWrites(state,colorMultiplier); } + + // unbind buffers if necessary + state.unbindVertexBufferObject(); + state.unbindElementBufferObject(); } if (_drawMode & BOUNDINGBOX) @@ -1444,8 +1463,8 @@ void Text::accept(osg::Drawable::ConstAttributeFunctor& af) const ++titr) { const GlyphQuads& glyphquad = titr->second; - af.apply(osg::Drawable::VERTICES,glyphquad._transformedCoords[0].size(),&(glyphquad._transformedCoords[0].front())); - af.apply(osg::Drawable::TEXTURE_COORDS_0,glyphquad._texcoords.size(),&(glyphquad._texcoords.front())); + af.apply(osg::Drawable::VERTICES, glyphquad._transformedCoords[0]->size(), &(glyphquad._transformedCoords[0]->front())); + af.apply(osg::Drawable::TEXTURE_COORDS_0, glyphquad._texcoords->size(), &(glyphquad._texcoords->front())); } } @@ -1457,8 +1476,8 @@ void Text::accept(osg::PrimitiveFunctor& pf) const { const GlyphQuads& glyphquad = titr->second; - pf.setVertexArray(glyphquad._transformedCoords[0].size(),&(glyphquad._transformedCoords[0].front())); - pf.drawArrays(GL_QUADS,0,glyphquad._transformedCoords[0].size()); + pf.setVertexArray(glyphquad._transformedCoords[0]->size(), &(glyphquad._transformedCoords[0]->front())); + pf.drawArrays(GL_QUADS, 0, glyphquad._transformedCoords[0]->size()); } @@ -1556,10 +1575,10 @@ void Text::drawForegroundText(osg::State& state, const GlyphQuads& glyphquad, co unsigned int contextID = state.getContextID(); const GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; - if (!transformedCoords.empty()) + if (!transformedCoords->empty()) { - state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedCoords.front())); - state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); + state.setVertexPointer(transformedCoords); + state.setTexCoordPointer(0, glyphquad._texcoords); if(_colorGradientMode == SOLID) { @@ -1568,11 +1587,10 @@ void Text::drawForegroundText(osg::State& state, const GlyphQuads& glyphquad, co } else { - state.setColorPointer( 4, GL_FLOAT, 0, &(glyphquad._colorCoords.front())); + state.setColorPointer(glyphquad._colorCoords); } - state.drawQuads(0,transformedCoords.size()); - + glyphquad._quadIndices->draw(state, _useVertexBufferObjects); } } @@ -1647,17 +1665,17 @@ void Text::drawTextWithBackdrop(osg::State& state, const osg::Vec4& colorMultipl max_backdrop_index = _backdropType+1; } - state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); + state.setTexCoordPointer(0, glyphquad._texcoords); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; - if (!transformedBackdropCoords.empty()) + if (!transformedBackdropCoords->empty()) { - state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); - state.drawQuads(0,transformedBackdropCoords.size()); + state.setVertexPointer(transformedBackdropCoords); + glyphquad._quadIndices->draw(state, _useVertexBufferObjects); } } } @@ -1703,19 +1721,19 @@ void Text::renderWithPolygonOffset(osg::State& state, const osg::Vec4& colorMult max_backdrop_index = _backdropType+1; } - state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); + state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords->front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; - if (!transformedBackdropCoords.empty()) + if (!transformedBackdropCoords->empty()) { - state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); + state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords->front())); glPolygonOffset(0.1f * osg::PolygonOffset::getFactorMultiplier(), osg::PolygonOffset::getUnitsMultiplier() * (max_backdrop_index-backdrop_index) ); - state.drawQuads(0,transformedBackdropCoords.size()); + state.drawQuads(0,transformedBackdropCoords->size()); } } @@ -1762,17 +1780,17 @@ void Text::renderWithNoDepthBuffer(osg::State& state, const osg::Vec4& colorMult max_backdrop_index = _backdropType+1; } - state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); + state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords->front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; - if (!transformedBackdropCoords.empty()) + if (!transformedBackdropCoords->empty()) { - state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); - state.drawQuads(0,transformedBackdropCoords.size()); + state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords->front())); + state.drawQuads(0,transformedBackdropCoords->size()); } } @@ -1818,20 +1836,20 @@ void Text::renderWithDepthRange(osg::State& state, const osg::Vec4& colorMultipl max_backdrop_index = _backdropType+1; } - state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); + state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords->front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; - if (!transformedBackdropCoords.empty()) + if (!transformedBackdropCoords->empty()) { - state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); + state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords->front())); double offset = double(max_backdrop_index-backdrop_index)*0.0001; glDepthRange( offset, 1.0+offset); - state.drawQuads(0,transformedBackdropCoords.size()); + state.drawQuads(0,transformedBackdropCoords->size()); } } @@ -1917,26 +1935,26 @@ void Text::renderWithStencilBuffer(osg::State& state, const osg::Vec4& colorMult max_backdrop_index = _backdropType+1; } - state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); + state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords->front())); state.disableColorPointer(); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; - if (!transformedBackdropCoords.empty()) + if (!transformedBackdropCoords->empty()) { - state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); - state.drawQuads(0,transformedBackdropCoords.size()); + state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords->front())); + state.drawQuads(0,transformedBackdropCoords->size()); } } // Draw the foreground text const GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; - if (!transformedCoords.empty()) + if (!transformedCoords->empty()) { - state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedCoords.front())); - state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); - state.drawQuads(0,transformedCoords.size()); + state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedCoords->front())); + state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords->front())); + state.drawQuads(0, transformedCoords->size()); } } @@ -1984,17 +2002,17 @@ void Text::renderWithStencilBuffer(osg::State& state, const osg::Vec4& colorMult max_backdrop_index = _backdropType+1; } - state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords.front())); + state.setTexCoordPointer( 0, 2, GL_FLOAT, 0, &(glyphquad._texcoords->front())); state.disableColorPointer(); state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); for( ; backdrop_index < max_backdrop_index; backdrop_index++) { const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; - if (!transformedBackdropCoords.empty()) + if (!transformedBackdropCoords->empty()) { - state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); - state.drawQuads(0,transformedBackdropCoords.size()); + state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords->front())); + state.drawQuads(0,transformedBackdropCoords->size()); } } @@ -2006,3 +2024,66 @@ void Text::renderWithStencilBuffer(osg::State& state, const osg::Vec4& colorMult OSG_NOTICE<<"Warning: Text::renderWithStencilBuffer(..) not implemented."<clear(); + if (_coords->size() % 4 != 0) + OSG_WARN << "size of _coords is not divisible by 4."; + for (unsigned int i = 0; i < (unsigned int)_coords->size(); i += 4) + { + _quadIndices->push_back(i); + _quadIndices->push_back(i + 1); + _quadIndices->push_back(i + 3); + + _quadIndices->push_back(i + 1); + _quadIndices->push_back(i + 2); + _quadIndices->push_back(i + 3); + } +} + +void Text::GlyphQuads::initGPUBufferObjects() +{ + osg::VertexBufferObject* vbo = new osg::VertexBufferObject(); + _coords->setBinding(osg::Array::BIND_PER_VERTEX); + _coords->setVertexBufferObject(vbo); + _texcoords->setBinding(osg::Array::BIND_PER_VERTEX); + _texcoords->setVertexBufferObject(vbo); + _colorCoords->setBinding(osg::Array::BIND_PER_VERTEX); + _colorCoords->setVertexBufferObject(vbo); + for (size_t i = 0; i < _transformedCoords.size(); i++) + { + _transformedCoords[i]->setBinding(osg::Array::BIND_PER_VERTEX); + _transformedCoords[i]->setVertexBufferObject(vbo); + } + for (int j = 0; j < 8; j++) + { + for (size_t i = 0; i < _transformedBackdropCoords[j].size(); i++) + { + _transformedBackdropCoords[j][i]->setBinding(osg::Array::BIND_PER_VERTEX); + _transformedBackdropCoords[j][i]->setVertexBufferObject(vbo); + } + } + + _quadIndices->setElementBufferObject(new osg::ElementBufferObject()); +} diff --git a/src/osgWidget/Input.cpp b/src/osgWidget/Input.cpp index 7b5658830..420177a06 100644 --- a/src/osgWidget/Input.cpp +++ b/src/osgWidget/Input.cpp @@ -122,7 +122,7 @@ void Input::_calculateCursorOffsets() { const osgText::Text::GlyphQuads& gq = tgqmi->second; //coords.insert(coords.end(),gq.getTransformedCoords(0).begin(),gq.getTransformedCoords(0).end()); - coords.insert(coords.end(),gq.getCoords().begin(),gq.getCoords().end()); + coords.insert(coords.end(),gq.getCoords()->begin(),gq.getCoords()->end()); for (unsigned int i=0; i