From 4b295c46d16ef837b8fb8a93417df5bd2ca95596 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 23 Oct 2017 14:50:35 +0100 Subject: [PATCH] Restructed the way that GlyphTexture is set up to better support control of osgText::ShaderTechnique from osgText::Text --- examples/osgfont/osgfont.cpp | 2 +- examples/osglogo/osglogo.cpp | 4 +- include/osgText/Font | 9 +-- include/osgText/Glyph | 56 ++++++++++-------- src/osgText/DefaultFont.cpp | 6 -- src/osgText/Font.cpp | 21 ++----- src/osgText/Glyph.cpp | 80 +++++++++++++------------- src/osgText/Text.cpp | 108 +++++++++++++++++++++-------------- 8 files changed, 147 insertions(+), 139 deletions(-) diff --git a/examples/osgfont/osgfont.cpp b/examples/osgfont/osgfont.cpp index e16ab4079..bad750798 100644 --- a/examples/osgfont/osgfont.cpp +++ b/examples/osgfont/osgfont.cpp @@ -153,12 +153,12 @@ struct TextSettings font->setMinFilterHint(minFilter); font->setMagFilterHint(magFilter); font->setMaxAnisotropy(maxAnisotropy); - font->setShaderTechnique(shaderTechnique); text.setColor(textColor); text.setBackdropType(backdropType); text.setBackdropOffset(backdropOffset.x(), backdropOffset.y()); text.setBackdropColor(backdropColor); + text.setShaderTechnique(shaderTechnique); text.setFont(font.get()); diff --git a/examples/osglogo/osglogo.cpp b/examples/osglogo/osglogo.cpp index c419103cb..f5161c041 100644 --- a/examples/osglogo/osglogo.cpp +++ b/examples/osglogo/osglogo.cpp @@ -153,7 +153,7 @@ osg:: Node* createTextBelow(const osg::BoundingBox& bb, const std::string& label if (s_useSDF) { - text->getFont()->setShaderTechnique(osgText::ALL_FEATURES); + text->setShaderTechnique(osgText::ALL_FEATURES); } text->setAlignment(osgText::Text::CENTER_CENTER); @@ -186,7 +186,7 @@ osg:: Node* createTextLeft(const osg::BoundingBox& bb, const std::string& label, if (s_useSDF) { - text->getFont()->setShaderTechnique(osgText::ALL_FEATURES); + text->setShaderTechnique(osgText::ALL_FEATURES); } text->setAlignment(osgText::Text::RIGHT_CENTER); diff --git a/include/osgText/Font b/include/osgText/Font index f8fcc89b0..ab4641c93 100644 --- a/include/osgText/Font +++ b/include/osgText/Font @@ -107,11 +107,6 @@ public: * return true on success, return false when not supported.*/ virtual bool getVerticalSize(float& ascender, float& descender) const { return _implementation ? _implementation->getVerticalSize(ascender, descender) : false; } - - void setShaderTechnique(ShaderTechnique features) { _shaderTechnique = features; } - ShaderTechnique getShaderTechnique() const { return _shaderTechnique; } - - /** Set the size of texture to create to store the glyph images when rendering. * Note, this doesn't affect already created Texture Glhph's.*/ void setTextureSizeHint(unsigned int width,unsigned int height); @@ -162,6 +157,8 @@ public: typedef std::vector< osg::ref_ptr > GlyphTextureList; GlyphTextureList& getGlyphTextureList() { return _glyphTextureList; } + void assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique); + protected: virtual ~Font(); @@ -186,8 +183,6 @@ protected: // current active size of font FontResolution _fontSize; - ShaderTechnique _shaderTechnique; - unsigned int _textureWidthHint; unsigned int _textureHeightHint; osg::Texture::FilterMode _minFilterHint; diff --git a/include/osgText/Glyph b/include/osgText/Glyph index c7d717f25..782b402dd 100644 --- a/include/osgText/Glyph +++ b/include/osgText/Glyph @@ -77,22 +77,40 @@ public: void setVerticalAdvance(float advance); float getVerticalAdvance() const; - void setTexture(GlyphTexture* texture); - GlyphTexture* getTexture(); - const GlyphTexture* getTexture() const; + struct TextureInfo : public osg::Referenced + { + TextureInfo(): + texture(0), + texelMargin(0.0f) {} - void setTexturePosition(int posX,int posY); - int getTexturePositionX() const; - int getTexturePositionY() const; + TextureInfo(GlyphTexture* tex, int x, int y, const osg::Vec2& mintc, const osg::Vec2& maxtc, float margin): + texture(tex), + texturePositionX(x), + texturePositionY(y), + minTexCoord(mintc), + maxTexCoord(maxtc), + texelMargin(margin) {} - void setMinTexCoord(const osg::Vec2& coord); - const osg::Vec2& getMinTexCoord() const; + GlyphTexture* texture; + int texturePositionX; + int texturePositionY; + osg::Vec2 minTexCoord; + osg::Vec2 maxTexCoord; + float texelMargin; + }; - void setMaxTexCoord(const osg::Vec2& coord); - const osg::Vec2& getMaxTexCoord() const; + void setTextureInfo(ShaderTechnique technique, TextureInfo* info) + { + if (technique>=_textureInfoList.size()) _textureInfoList.resize(technique+1); + _textureInfoList[technique] = info; + } - void setTexelMargin(float margin) { _texelMargin = margin; } - float getTexelMargin() const { return _texelMargin; } + const TextureInfo* getTextureInfo(ShaderTechnique technique) const + { + return (technique<_textureInfoList.size()) ? _textureInfoList[technique].get() : 0; + } + + TextureInfo* getOrCreateTextureInfo(ShaderTechnique technique); protected: @@ -112,16 +130,8 @@ protected: osg::Vec2 _verticalBearing; float _verticalAdvance; - GlyphTexture* _texture; - int _texturePosX; - int _texturePosY; - osg::Vec2 _minTexCoord; - osg::Vec2 _maxTexCoord; - float _texelMargin; - - typedef osg::buffered_value GLObjectList; - mutable GLObjectList _globjList; - + typedef std::vector< osg::ref_ptr > TextureInfoList; + TextureInfoList _textureInfoList; }; class OSGTEXT_EXPORT GlyphGeometry : public osg::Referenced @@ -283,7 +293,7 @@ protected: virtual ~GlyphTexture(); - void copyGlyphImage(Glyph* glyph); + void copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info); ShaderTechnique _shaderTechnique; diff --git a/src/osgText/DefaultFont.cpp b/src/osgText/DefaultFont.cpp index ac1a5d8ba..dfc9b5945 100644 --- a/src/osgText/DefaultFont.cpp +++ b/src/osgText/DefaultFont.cpp @@ -29,12 +29,6 @@ DefaultFont::DefaultFont() _minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR; _magFilterHint = osg::Texture::LINEAR; - char *ptr; - if ((ptr = getenv("OSG_SDF_TEXT")) != 0) - { - _shaderTechnique = osgText::ALL_FEATURES; - } - constructGlyphs(); } diff --git a/src/osgText/Font.cpp b/src/osgText/Font.cpp index bfe67cd74..7d6c61c1f 100644 --- a/src/osgText/Font.cpp +++ b/src/osgText/Font.cpp @@ -224,11 +224,6 @@ osg::ref_ptr osgText::readRefFontStream(std::istream& stream, const osgDB: Font::Font(FontImplementation* implementation): osg::Object(true), -#if 0 - _shaderTechnique(ALL_FEATURES), -#else - _shaderTechnique(GREYSCALE), -#endif _textureWidthHint(1024), _textureHeightHint(1024), _minFilterHint(osg::Texture::LINEAR_MIPMAP_LINEAR), @@ -247,15 +242,6 @@ Font::Font(FontImplementation* implementation): if (osg_max_size<_textureWidthHint) _textureWidthHint = osg_max_size; if (osg_max_size<_textureHeightHint) _textureHeightHint = osg_max_size; } - - if ((ptr = getenv("OSG_SDF_TEXT")) != 0) - { - _shaderTechnique = ALL_FEATURES; - } - else if ((ptr = getenv("OSG_GREYSCALE_TEXT")) != 0) - { - _shaderTechnique = GREYSCALE; - } } Font::~Font() @@ -459,6 +445,10 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* _sizeGlyphMap[fontRes][charcode]=glyph; +} + +void Font::assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique) +{ int posX=0,posY=0; GlyphTexture* glyphTexture = 0; @@ -485,7 +475,7 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* OSG_INFO<< " Font " << this<< ", numberOfTexturesAllocated "<setShaderTechnique(_shaderTechnique); + glyphTexture->setShaderTechnique(shaderTechnique); glyphTexture->setTextureSize(_textureWidthHint,_textureHeightHint); glyphTexture->setFilter(osg::Texture::MIN_FILTER,_minFilterHint); glyphTexture->setFilter(osg::Texture::MAG_FILTER,_magFilterHint); @@ -503,5 +493,4 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* // add the glyph into the texture. glyphTexture->addGlyph(glyph,posX,posY); - } diff --git a/src/osgText/Glyph.cpp b/src/osgText/Glyph.cpp index d7f2395fb..fbd793cfa 100644 --- a/src/osgText/Glyph.cpp +++ b/src/osgText/Glyph.cpp @@ -42,8 +42,6 @@ using namespace std; #endif - - #if 0 #define TEXTURE_IMAGE_NUM_CHANNELS 1 #define TEXTURE_IMAGE_FORMAT OSGTEXT_GLYPH_FORMAT @@ -52,6 +50,11 @@ using namespace std; #define TEXTURE_IMAGE_FORMAT GL_RGBA #endif + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GlyphTexture +// GlyphTexture::GlyphTexture(): _usedY(0), _partUsedX(0), @@ -154,22 +157,19 @@ void GlyphTexture::addGlyph(Glyph* glyph, int posX, int posY) _glyphs.push_back(glyph); - // set up the details of where to place glyph's image in the texture. - glyph->setTexture(this); - glyph->setTexturePosition(posX,posY); + osg::ref_ptr info = new Glyph::TextureInfo( + this, + posX, posY, + osg::Vec2( static_cast(posX)/static_cast(getTextureWidth()), static_cast(posY)/static_cast(getTextureHeight()) ), // minTexCoord + osg::Vec2( static_cast(posX+glyph->s())/static_cast(getTextureWidth()), static_cast(posY+glyph->t())/static_cast(getTextureHeight()) ), // maxTexCoord + float(getTexelMargin(glyph))); // margin - glyph->setMinTexCoord( osg::Vec2( static_cast(posX)/static_cast(getTextureWidth()), - static_cast(posY)/static_cast(getTextureHeight()) ) ); - glyph->setMaxTexCoord( osg::Vec2( static_cast(posX+glyph->s())/static_cast(getTextureWidth()), - static_cast(posY+glyph->t())/static_cast(getTextureHeight()) ) ); + glyph->setTextureInfo(_shaderTechnique, info.get()); - - glyph->setTexelMargin(float(getTexelMargin(glyph))); - - copyGlyphImage(glyph); + copyGlyphImage(glyph, info); } -void GlyphTexture::copyGlyphImage(Glyph* glyph) +void GlyphTexture::copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info) { _image->dirty(); @@ -179,7 +179,7 @@ void GlyphTexture::copyGlyphImage(Glyph* glyph) // make sure the glyph image settings and the target image are consisent before copying. glyph->setPixelFormat(_image->getPixelFormat()); glyph->setInternalTextureFormat(_image->getPixelFormat()); - _image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph); + _image->copySubImage(info->texturePositionX, info->texturePositionY, 0, glyph); return; } @@ -191,7 +191,7 @@ void GlyphTexture::copyGlyphImage(Glyph* glyph) int dest_columns = _image->s(); int dest_rows = _image->t(); - unsigned char* dest_data = _image->data(glyph->getTexturePositionX(),glyph->getTexturePositionY()); + unsigned char* dest_data = _image->data(info->texturePositionX, info->texturePositionY); int search_distance = getEffectMargin(glyph); @@ -204,11 +204,11 @@ void GlyphTexture::copyGlyphImage(Glyph* glyph) float max_distance = sqrtf(float(search_distance)*float(search_distance)*2.0); - if ((left+glyph->getTexturePositionX())<0) left = -glyph->getTexturePositionX(); - if ((right+glyph->getTexturePositionX())>=dest_columns) right = dest_columns-glyph->getTexturePositionX()-1; + if ((left+info->texturePositionX)<0) left = -info->texturePositionX; + if ((right+info->texturePositionX)>=dest_columns) right = dest_columns-info->texturePositionX-1; - if ((lower+glyph->getTexturePositionY())<0) lower = -glyph->getTexturePositionY(); - if ((upper+glyph->getTexturePositionY())>=dest_rows) upper = dest_rows-glyph->getTexturePositionY()-1; + if ((lower+info->texturePositionY)<0) lower = -info->texturePositionY; + if ((upper+info->texturePositionY)>=dest_rows) upper = dest_rows-info->texturePositionY-1; int num_components = osg::Image::computeNumComponents(_image->getPixelFormat()); @@ -427,13 +427,18 @@ osg::Image* GlyphTexture::createImage() ++itr) { Glyph* glyph = itr->get(); - copyGlyphImage(glyph); + // copyGlyphImage(glyph); // TODO!!!!! + OSG_NOTICE<<"GlyphTexture::createImage() need to implement copy"<=_textureInfoList.size()) _textureInfoList.resize(technique+1); + if (!_textureInfoList[technique]) + { + _font->assignGlyphToGlyphTexture(this, technique); + } + return _textureInfoList[technique].get(); +} +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Glyph3D +// Glyph3D::Glyph3D(Font* font, unsigned int glyphCode): osg::Referenced(true), _font(font), diff --git a/src/osgText/Text.cpp b/src/osgText/Text.cpp index f2ef6ecbb..4651edb5d 100644 --- a/src/osgText/Text.cpp +++ b/src/osgText/Text.cpp @@ -47,6 +47,16 @@ Text::Text(): { _supportsVertexBufferObjects = true; + char* ptr = 0; + if ((ptr = getenv("OSG_SDF_TEXT")) != 0) + { + _shaderTechnique = ALL_FEATURES; + } + else if ((ptr = getenv("OSG_GREYSCALE_TEXT")) != 0) + { + _shaderTechnique = GREYSCALE; + } + assignStateSet(); } @@ -129,7 +139,7 @@ osg::StateSet* Text::createStateSet() } } - if (activeFont->getShaderTechnique()!=GREYSCALE) + if (_shaderTechnique!=GREYSCALE) { ss<setMode(GL_BLEND, osg::StateAttribute::ON); - OSG_NOTICE<<"Text::createStateSet() activeFont->getShaderTechnique()="<getShaderTechnique()<addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/text.vert", text_vert)); } - if (activeFont->getShaderTechnique()==GREYSCALE) + if (_shaderTechnique==GREYSCALE) { OSG_NOTICE<<"Using shaders/text_greyscale.frag"<getTexture()]; + const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique); + GlyphTexture* glyphTexture = info ? info->texture : 0; + GlyphQuads& glyphquad = _textureGlyphQuadMap[glyphTexture]; glyphquad._glyphs.push_back(glyph); @@ -625,46 +637,54 @@ void Text::computeGlyphRepresentation() local.x() += bearing.x() * wr; local.y() += bearing.y() * hr; - - // Adjust coordinates and texture coordinates to avoid - // clipping the edges of antialiased characters. - osg::Vec2 mintc = glyph->getMinTexCoord(); - osg::Vec2 maxtc = glyph->getMaxTexCoord(); - osg::Vec2 vDiff = maxtc - mintc; - float texelMargin = glyph->getTexelMargin(); - - float fHorizTCMargin = texelMargin / glyph->getTexture()->getTextureWidth(); - float fVertTCMargin = texelMargin / glyph->getTexture()->getTextureHeight(); - float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x(); - float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y(); - - mintc.x() -= fHorizTCMargin; - mintc.y() -= fVertTCMargin; - maxtc.x() += fHorizTCMargin; - maxtc.y() += fVertTCMargin; - osg::Vec2 minc = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin); - osg::Vec2 maxc = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin); - - addGlyphQuad(glyph, minc, maxc, mintc, maxtc); - - // move the cursor onto the next character. - // also expand bounding box - switch(_layout) + const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique); + if (info) { - case LEFT_TO_RIGHT: - cursor.x() += glyph->getHorizontalAdvance() * wr; - _textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner - _textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner - break; - case VERTICAL: - cursor.y() -= glyph->getVerticalAdvance() * hr; - _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner - _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner - break; - case RIGHT_TO_LEFT: - _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner - _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner - break; + + // Adjust coordinates and texture coordinates to avoid + // clipping the edges of antialiased characters. + osg::Vec2 mintc = info->minTexCoord; + osg::Vec2 maxtc = info->maxTexCoord; + osg::Vec2 vDiff = maxtc - mintc; + float texelMargin = info->texelMargin; + + float fHorizTCMargin = texelMargin / info->texture->getTextureWidth(); + float fVertTCMargin = texelMargin / info->texture->getTextureHeight(); + float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x(); + float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y(); + + mintc.x() -= fHorizTCMargin; + mintc.y() -= fVertTCMargin; + maxtc.x() += fHorizTCMargin; + maxtc.y() += fVertTCMargin; + osg::Vec2 minc = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin); + osg::Vec2 maxc = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin); + + addGlyphQuad(glyph, minc, maxc, mintc, maxtc); + + // move the cursor onto the next character. + // also expand bounding box + switch(_layout) + { + case LEFT_TO_RIGHT: + cursor.x() += glyph->getHorizontalAdvance() * wr; + _textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner + _textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner + break; + case VERTICAL: + cursor.y() -= glyph->getVerticalAdvance() * hr; + _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner + _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner + break; + case RIGHT_TO_LEFT: + _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner + _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner + break; + } + } + else + { + OSG_NOTICE<<"No TextureInfo for "<