From 722ed6fc5ecc89620cc90a03317bf25e22d38a5e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 12 Sep 2017 11:50:47 +0100 Subject: [PATCH] Shifted set up of osgText related StateSet from osgText::Font into into osg::TextBase/Text to enable grater control over state required for specific Text implementations --- include/osgText/Font | 15 ++-- include/osgText/Text | 16 ++-- include/osgText/TextBase | 4 + src/osgText/Font.cpp | 133 +++------------------------- src/osgText/Text.cpp | 184 +++++++++++++++++++++++++++++++++------ src/osgText/TextBase.cpp | 12 ++- 6 files changed, 193 insertions(+), 171 deletions(-) diff --git a/include/osgText/Font b/include/osgText/Font index e77a0e035..7b7fd0186 100644 --- a/include/osgText/Font +++ b/include/osgText/Font @@ -27,6 +27,7 @@ namespace osgText { // forward declare Font class Font; +class TextBase; #ifdef OSG_PROVIDE_READFILE /** Read a font from specified file. The filename may contain a path. @@ -84,13 +85,9 @@ public: static osg::ref_ptr& getDefaultFont(); - void setTexEnv(osg::TexEnv* texenv) { if (texenv) _texenv = texenv; } - inline osg::TexEnv* getTexEnv() { return _texenv.get(); } - inline const osg::TexEnv* getTexEnv() const { return _texenv.get(); } - - void setStateSet(osg::StateSet* stateset) { _stateset = stateset; } - osg::StateSet* getStateSet() { return _stateset.get(); } - const osg::StateSet* getStateSet() const { return _stateset.get(); } + typedef std::vector< osg::ref_ptr > StateSets; + StateSets& getCachedStateSets() { return _statesets; } + const StateSets& getCachedStateSets() const { return _statesets; } /** Get a kerning (adjustment of spacing of two adjacent character) for specified charcodes and a font resolution.*/ @@ -188,7 +185,6 @@ protected: void addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* glyph); - typedef std::vector< osg::ref_ptr > StateSetList; typedef std::map< unsigned int, osg::ref_ptr > GlyphMap; typedef std::map< unsigned int, osg::ref_ptr > Glyph3DMap; @@ -197,8 +193,7 @@ protected: mutable OpenThreads::Mutex _glyphMapMutex; - osg::ref_ptr _texenv; - osg::ref_ptr _stateset; + StateSets _statesets; FontSizeGlyphMap _sizeGlyphMap; GlyphTextureList _glyphTextureList; diff --git a/include/osgText/Text b/include/osgText/Text index db497792f..fc6fbfc0f 100644 --- a/include/osgText/Text +++ b/include/osgText/Text @@ -36,16 +36,6 @@ public: virtual const char* className() const { return "Text"; } virtual const char* libraryName() const { return "osgText"; } - virtual void setFont(Font* font=0) { setFont(osg::ref_ptr(font)); }; - - /** Set the Font to use to render the text.*/ - virtual void setFont(osg::ref_ptr font); - - /** Set the font, loaded from the specified front file, to use to render the text, - * setFont("") sets the use of the default font. - * See the osgText::readFontFile function for how the font file will be located. */ - virtual void setFont(const std::string& fontfile) { TextBase::setFont(fontfile); } - /** * Turns off writing to the depth buffer when rendering text. This only affects text * with no backdrop or text using the DELAYED_DEPTH_WRITES implementation, since @@ -92,7 +82,9 @@ public: * buffer. But if you don't need the depth buffer updated for * your, this extra pass can be disabled by calling * enableDepthWrites(false).*/ - DELAYED_DEPTH_WRITES + DELAYED_DEPTH_WRITES, + + USE_SHADERS }; /** @@ -284,6 +276,8 @@ protected: virtual ~Text(); + virtual osg::StateSet* createStateSet(); + Font* getActiveFont(); const Font* getActiveFont() const; diff --git a/include/osgText/TextBase b/include/osgText/TextBase index 64fe785f1..dceac86b7 100644 --- a/include/osgText/TextBase +++ b/include/osgText/TextBase @@ -284,6 +284,10 @@ protected: virtual ~TextBase(); + virtual osg::StateSet* createStateSet(); + + virtual void assignStateSet(); + void initArraysAndBuffers(); osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo) const; diff --git a/src/osgText/Font.cpp b/src/osgText/Font.cpp index c09285046..c1aa0e077 100644 --- a/src/osgText/Font.cpp +++ b/src/osgText/Font.cpp @@ -32,81 +32,6 @@ using namespace osgText; using namespace std; -#if (!defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)) - #define GLSL_VERSION_STR "330 core" - #define GLYPH_CMP "r" -#else - #define GLSL_VERSION_STR "300 es" - #define GLYPH_CMP "a" -#endif - -static const char* gl3_TextVertexShader = { - "#version " GLSL_VERSION_STR "\n" - "// gl3_TextVertexShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\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* gl3_TextFragmentShader = { - "#version " GLSL_VERSION_STR "\n" - "// gl3_TextFragmentShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "uniform sampler2D glyphTexture;\n" - "in vec2 texCoord;\n" - "in vec4 vertexColor;\n" - "out vec4 color;\n" - "void main(void)\n" - "{\n" - " if (texCoord.x>=0.0) color = vertexColor * vec4(1.0, 1.0, 1.0, texture(glyphTexture, texCoord)." GLYPH_CMP ");\n" - " else color = vertexColor;\n" - "}\n" -}; - -static const char* gl2_TextVertexShader = { - "// gl2_TextVertexShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "varying vec2 texCoord;\n" - "varying vec4 vertexColor;\n" - "void main(void)\n" - "{\n" - " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" - " texCoord = gl_MultiTexCoord0.xy;\n" - " vertexColor = gl_Color; \n" - "}\n" -}; - -static const char* gl2_TextFragmentShader = { - "// gl2_TextFragmentShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "uniform sampler2D glyphTexture;\n" - "varying vec2 texCoord;\n" - "varying vec4 vertexColor;\n" - "void main(void)\n" - "{\n" - " if (texCoord.x>=0.0) gl_FragColor = vertexColor * vec4(1.0, 1.0, 1.0, texture2D(glyphTexture, texCoord).a);\n" - " else gl_FragColor = vertexColor;\n" - "}\n" -}; - osg::ref_ptr& Font::getDefaultFont() { static OpenThreads::Mutex s_DefaultFontMutex; @@ -317,47 +242,6 @@ Font::Font(FontImplementation* implementation): { setImplementation(implementation); - _texenv = new osg::TexEnv; - _stateset = new osg::StateSet; - - _stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - _stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - _stateset->setMode(GL_BLEND, osg::StateAttribute::ON); - -#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE) - - OSG_INFO<<"Font::Font() Fixed function pipeline"<setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); -#endif - - osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint(); - if (shaderHint==osg::DisplaySettings::SHADER_GL3 || shaderHint==osg::DisplaySettings::SHADER_GLES3) - { - - OSG_INFO<<"Font::Font() Setting up GL3 compatible shaders"< program = new osg::Program; - program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3_TextVertexShader)); - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl3_TextFragmentShader)); - _stateset->setAttributeAndModes(program.get()); - _stateset->addUniform(new osg::Uniform("glyphTexture", 0)); - - } - else if (shaderHint==osg::DisplaySettings::SHADER_GL2 || shaderHint==osg::DisplaySettings::SHADER_GLES2) - { - - - OSG_INFO<<"Font::Font() Setting up GL2 compatible shaders"< program = new osg::Program; - program->addShader(new osg::Shader(osg::Shader::VERTEX, gl2_TextVertexShader)); - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl2_TextFragmentShader)); - _stateset->setAttributeAndModes(program.get()); - _stateset->addUniform(new osg::Uniform("glyphTexture", 0)); - - } - char *ptr; if( (ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0) { @@ -531,9 +415,6 @@ void Font::setThreadSafeRefUnref(bool threadSafe) { osg::Object::setThreadSafeRefUnref(threadSafe); - if (_texenv.valid()) _texenv->setThreadSafeRefUnref(threadSafe); - if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe); - for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); ++itr) @@ -544,7 +425,12 @@ void Font::setThreadSafeRefUnref(bool threadSafe) void Font::resizeGLObjectBuffers(unsigned int maxSize) { - if (_stateset.valid()) _stateset->resizeGLObjectBuffers(maxSize); + for(StateSets::iterator itr = _statesets.begin(); + itr != _statesets.end(); + ++itr) + { + (*itr)->resizeGLObjectBuffers(maxSize); + } for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); @@ -556,7 +442,12 @@ void Font::resizeGLObjectBuffers(unsigned int maxSize) void Font::releaseGLObjects(osg::State* state) const { - if (_stateset.valid()) _stateset->releaseGLObjects(state); + for(StateSets::const_iterator itr = _statesets.begin(); + itr != _statesets.end(); + ++itr) + { + (*itr)->releaseGLObjects(state); + } for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); diff --git a/src/osgText/Text.cpp b/src/osgText/Text.cpp index 7cac3d0a9..f4cb94bd7 100644 --- a/src/osgText/Text.cpp +++ b/src/osgText/Text.cpp @@ -28,10 +28,92 @@ using namespace osg; using namespace osgText; +#if (!defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)) + #define GLSL_VERSION_STR "330 core" + #define GLYPH_CMP "r" +#else + #define GLSL_VERSION_STR "300 es" + #define GLYPH_CMP "a" +#endif + +static const char* gl3_TextVertexShader = { + "#version " GLSL_VERSION_STR "\n" + "// gl3_TextVertexShader\n" + "#ifdef GL_ES\n" + " precision highp float;\n" + "#endif\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* gl3_TextFragmentShader = { + "#version " GLSL_VERSION_STR "\n" + "// gl3_TextFragmentShader\n" + "#ifdef GL_ES\n" + " precision highp float;\n" + "#endif\n" + "uniform sampler2D glyphTexture;\n" + "in vec2 texCoord;\n" + "in vec4 vertexColor;\n" + "out vec4 color;\n" + "void main(void)\n" + "{\n" + " if (texCoord.x>=0.0) color = vertexColor * vec4(1.0, 1.0, 1.0, texture(glyphTexture, texCoord)." GLYPH_CMP ");\n" + " else color = vertexColor;\n" + "}\n" +}; + +static const char* gl2_TextVertexShader = { + "// gl2_TextVertexShader\n" + "#ifdef GL_ES\n" + " precision highp float;\n" + "#endif\n" + "varying vec2 texCoord;\n" + "varying vec4 vertexColor;\n" + "void main(void)\n" + "{\n" + " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + " texCoord = gl_MultiTexCoord0.xy;\n" + " vertexColor = gl_Color; \n" + "}\n" +}; + +static const char* gl2_TextFragmentShader = { + "// gl2_TextFragmentShader\n" + "#ifdef GL_ES\n" + " precision highp float;\n" + "#endif\n" + "uniform sampler2D glyphTexture;\n" + "varying vec2 texCoord;\n" + "varying vec4 vertexColor;\n" + "void main(void)\n" + "{\n" + " if (texCoord.x>=0.0) gl_FragColor = vertexColor * vec4(1.0, 1.0, 1.0, texture2D(glyphTexture, texCoord).a);\n" + " else gl_FragColor = vertexColor;\n" + "}\n" +}; + + + + Text::Text(): _enableDepthWrites(true), _backdropType(NONE), +#if 1 _backdropImplementation(DELAYED_DEPTH_WRITES), +#else + _backdropImplementation(USE_SHADERS), +#endif _backdropHorizontalOffset(0.07f), _backdropVerticalOffset(0.07f), _backdropColor(0.0f, 0.0f, 0.0f, 1.0f), @@ -42,6 +124,8 @@ Text::Text(): _colorGradientTopRight(1.0f, 1.0f, 1.0f, 1.0f) { _supportsVertexBufferObjects = true; + + assignStateSet(); } Text::Text(const Text& text,const osg::CopyOp& copyop): @@ -65,21 +149,59 @@ Text::~Text() { } -void Text::setFont(osg::ref_ptr font) +osg::StateSet* Text::createStateSet() { - if (_font==font) return; + Font* activeFont = getActiveFont(); + if (!activeFont) return 0; - osg::StateSet* previousFontStateSet = _font.valid() ? _font->getStateSet() : Font::getDefaultFont()->getStateSet(); - osg::StateSet* newFontStateSet = font.valid() ? font->getStateSet() : Font::getDefaultFont()->getStateSet(); + Font::StateSets& statesets = activeFont->getCachedStateSets(); - if (getStateSet() == previousFontStateSet) + if (!statesets.empty()) { - setStateSet( newFontStateSet ); + return statesets.front().get(); } - TextBase::setFont(font); -} + osg::ref_ptr stateset = new osg::StateSet; + statesets.push_back(stateset.get()); + + stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + stateset->setMode(GL_BLEND, osg::StateAttribute::ON); + +#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE) + + OSG_INFO<<"Font::Font() Fixed function pipeline"<setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); +#endif + + osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint(); + if (shaderHint==osg::DisplaySettings::SHADER_GL3 || shaderHint==osg::DisplaySettings::SHADER_GLES3) + { + OSG_INFO<<"Font::Font() Setting up GL3 compatible shaders"< program = new osg::Program; + program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3_TextVertexShader)); + program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl3_TextFragmentShader)); + stateset->setAttributeAndModes(program.get()); + stateset->addUniform(new osg::Uniform("glyphTexture", 0)); + + } + else if (shaderHint==osg::DisplaySettings::SHADER_GL2 || shaderHint==osg::DisplaySettings::SHADER_GLES2) + { + OSG_INFO<<"Font::Font() Setting up GL2 compatible shaders"< program = new osg::Program; + program->addShader(new osg::Shader(osg::Shader::VERTEX, gl2_TextVertexShader)); + program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl2_TextFragmentShader)); + stateset->setAttributeAndModes(program.get()); + stateset->addUniform(new osg::Uniform("glyphTexture", 0)); + + } + + return stateset.release(); +} Font* Text::getActiveFont() { @@ -632,7 +754,7 @@ void Text::computePositionsImplementation() // Presumes the atc matrix is already up-to-date void Text::computeBackdropPositions() { - if(_backdropType == NONE) + if(_backdropType == NONE || _backdropImplementation == USE_SHADERS) { return; } @@ -1130,33 +1252,39 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo const GlyphQuads& glyphquad = titr->second; -#if 1 if(_backdropType != NONE) { - unsigned int backdrop_index; - unsigned int max_backdrop_index; - if(_backdropType == OUTLINE) + if (_backdropImplementation != USE_SHADERS) { - backdrop_index = 1; - max_backdrop_index = 8; + unsigned int backdrop_index; + unsigned int max_backdrop_index; + if(_backdropType == OUTLINE) + { + backdrop_index = 1; + max_backdrop_index = 8; + } + else + { + backdrop_index = _backdropType+1; + max_backdrop_index = backdrop_index+1; + } + + if (max_backdrop_index>glyphquad._primitives.size()) max_backdrop_index=glyphquad._primitives.size(); + + state.disableColorPointer(); + state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); + + for( ; backdrop_index < max_backdrop_index; backdrop_index++) + { + glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); + } } else { - backdrop_index = _backdropType+1; - max_backdrop_index = backdrop_index+1; - } - - if (max_backdrop_index>glyphquad._primitives.size()) max_backdrop_index=glyphquad._primitives.size(); - - state.disableColorPointer(); - state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a()); - - for( ; backdrop_index < max_backdrop_index; backdrop_index++) - { - glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); + OSG_NOTICE<<"Using shaders for backdrop"<disableColorArray(state); diff --git a/src/osgText/TextBase.cpp b/src/osgText/TextBase.cpp index 5c5e5460e..c0da7b679 100644 --- a/src/osgText/TextBase.cpp +++ b/src/osgText/TextBase.cpp @@ -50,7 +50,6 @@ TextBase::TextBase(): _lineCount(0), _glyphNormalized(false) { - setStateSet(Font::getDefaultFont()->getStateSet()); setUseDisplayList(false); setSupportsDisplayList(false); @@ -89,6 +88,11 @@ TextBase::~TextBase() { } +osg::StateSet* TextBase::createStateSet() +{ + return 0; +} + void TextBase::initArraysAndBuffers() { _vbo = new osg::VertexBufferObject; @@ -182,6 +186,10 @@ void TextBase::setColor(const osg::Vec4& color) _color = color; } +void TextBase::assignStateSet() +{ + setStateSet(createStateSet()); +} void TextBase::setFont(osg::ref_ptr font) { @@ -189,6 +197,8 @@ void TextBase::setFont(osg::ref_ptr font) _font = font; + assignStateSet(); + computeGlyphRepresentation(); }