Merge pull request #372 from openscenegraph/text_improvements
Text improvements, introducing implementation of Signed Distance Function texture generation and new shaders for outlines and shadows replacing old multi-pass approach
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace osg {
|
||||
|
||||
@@ -319,9 +320,15 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced
|
||||
SHADER_GLES3
|
||||
};
|
||||
|
||||
void setShaderHint(ShaderHint hint) { _shaderHint = hint; }
|
||||
/** set the ShaderHint to tells shader generating cdoes version to create.
|
||||
* By default also OSG_GLSL_VERSION and OSG_PRECISION_FLOAT values that can get use directly in shaders using $OSG_GLSL_VERSION and $OSG_PRECISION_FLOAT respectively.*/
|
||||
void setShaderHint(ShaderHint hint, bool setShaderValues=true);
|
||||
ShaderHint getShaderHint() const { return _shaderHint; }
|
||||
|
||||
/** Set the TextShaderTechnique that is used in the Text default constructor to choose which osgText::ShaderTechnique to use.*/
|
||||
void setTextShaderTechnique(const std::string& str) { _textShaderTechnique = str; }
|
||||
const std::string& getTextShaderTechnique() const { return _textShaderTechnique; }
|
||||
|
||||
|
||||
void setKeystoneHint(bool enabled) { _keystoneHint = enabled; }
|
||||
bool getKeystoneHint() const { return _keystoneHint; }
|
||||
@@ -358,6 +365,11 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced
|
||||
/** helper function for computing the right eye view matrix.*/
|
||||
virtual osg::Matrixd computeRightEyeViewImplementation(const osg::Matrixd& view, double eyeSeperationScale=1.0) const;
|
||||
|
||||
|
||||
void setValue(const std::string& name, const std::string& value);
|
||||
|
||||
bool getValue(const std::string& name, std::string& value, bool use_getenv_fallback=true) const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~DisplaySettings();
|
||||
@@ -415,6 +427,7 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced
|
||||
|
||||
VertexBufferHint _vertexBufferHint;
|
||||
ShaderHint _shaderHint;
|
||||
std::string _textShaderTechnique;
|
||||
|
||||
bool _keystoneHint;
|
||||
FileNames _keystoneFileNames;
|
||||
@@ -422,6 +435,11 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced
|
||||
|
||||
OSXMenubarBehavior _OSXMenubarBehavior;
|
||||
|
||||
typedef std::map<std::string, std::string> ValueMap;
|
||||
|
||||
mutable OpenThreads::Mutex _valueMapMutex;
|
||||
mutable ValueMap _valueMap;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -823,9 +823,12 @@ class OSG_EXPORT State : public Referenced
|
||||
* during rendering. */
|
||||
inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
|
||||
|
||||
/** Get the DisplaySettings */
|
||||
/** Get the const DisplaySettings */
|
||||
inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
|
||||
|
||||
/** Get the const DisplaySettings that is current active DisplaySettings to be used by osg::State, - if DisplaySettings is not directly assigned then fallback to DisplaySettings::instance(). */
|
||||
inline const DisplaySettings* getActiveDisplaySettings() const { return _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance().get(); }
|
||||
|
||||
|
||||
|
||||
/** Set flag for early termination of the draw traversal.*/
|
||||
|
||||
@@ -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<Font>& 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<osg::StateSet> > 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.*/
|
||||
@@ -110,19 +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; }
|
||||
|
||||
/** Set the margin around each glyph,
|
||||
* to ensure that texture filtering doesn't bleed adjacent glyph's into each other.
|
||||
* Default margin is 1 texels.*/
|
||||
void setGlyphImageMargin(unsigned int margin);
|
||||
unsigned int getGlyphImageMargin() const;
|
||||
|
||||
/** Set the margin ratio around each glyph, relative to the glyph's size.
|
||||
* to ensure that texture filtering doesn't bleed adjacent glyph's into each other.
|
||||
* Default margin is 0.05.*/
|
||||
void setGlyphImageMarginRatio(float margin);
|
||||
float getGlyphImageMarginRatio() const;
|
||||
|
||||
|
||||
/** 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);
|
||||
@@ -140,6 +124,9 @@ public:
|
||||
void setMagFilterHint(osg::Texture::FilterMode mode);
|
||||
osg::Texture::FilterMode getMagFilterHint() const;
|
||||
|
||||
void setMaxAnisotropy(float anis) { _maxAnisotropy = anis; }
|
||||
float getMaxAnisotropy() const { return _maxAnisotropy; }
|
||||
|
||||
unsigned int getFontDepth() const { return _depth; }
|
||||
|
||||
void setNumberCurveSamples(unsigned int numSamples) { _numCurveSamples = numSamples; }
|
||||
@@ -170,13 +157,14 @@ public:
|
||||
typedef std::vector< osg::ref_ptr<GlyphTexture> > GlyphTextureList;
|
||||
GlyphTextureList& getGlyphTextureList() { return _glyphTextureList; }
|
||||
|
||||
void assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique);
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~Font();
|
||||
|
||||
void addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* glyph);
|
||||
|
||||
typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSetList;
|
||||
typedef std::map< unsigned int, osg::ref_ptr<Glyph> > GlyphMap;
|
||||
typedef std::map< unsigned int, osg::ref_ptr<Glyph3D> > Glyph3DMap;
|
||||
|
||||
@@ -185,8 +173,7 @@ protected:
|
||||
|
||||
mutable OpenThreads::Mutex _glyphMapMutex;
|
||||
|
||||
osg::ref_ptr<osg::TexEnv> _texenv;
|
||||
osg::ref_ptr<osg::StateSet> _stateset;
|
||||
StateSets _statesets;
|
||||
FontSizeGlyphMap _sizeGlyphMap;
|
||||
GlyphTextureList _glyphTextureList;
|
||||
|
||||
@@ -195,13 +182,12 @@ protected:
|
||||
|
||||
// current active size of font
|
||||
FontResolution _fontSize;
|
||||
unsigned int _margin;
|
||||
float _marginRatio;
|
||||
|
||||
unsigned int _textureWidthHint;
|
||||
unsigned int _textureHeightHint;
|
||||
osg::Texture::FilterMode _minFilterHint;
|
||||
osg::Texture::FilterMode _magFilterHint;
|
||||
float _maxAnisotropy;
|
||||
|
||||
unsigned int _depth;
|
||||
unsigned int _numCurveSamples;
|
||||
@@ -247,8 +233,6 @@ public:
|
||||
virtual bool getVerticalSize(float & /*ascender*/, float & /*descender*/) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -30,15 +30,6 @@
|
||||
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
// 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;
|
||||
@@ -47,6 +38,14 @@ class Glyph3D;
|
||||
class GlyphGeometry;
|
||||
class GlyphTexture;
|
||||
|
||||
enum ShaderTechnique
|
||||
{
|
||||
NO_TEXT_SHADER = 0x0,
|
||||
GREYSCALE = 0x1,
|
||||
SIGNED_DISTANCE_FIELD = 0x2,
|
||||
ALL_FEATURES = GREYSCALE | SIGNED_DISTANCE_FIELD
|
||||
};
|
||||
|
||||
class OSGTEXT_EXPORT Glyph : public osg::Image
|
||||
{
|
||||
public:
|
||||
@@ -58,6 +57,9 @@ public:
|
||||
|
||||
unsigned int getGlyphCode() const { return _glyphCode; }
|
||||
|
||||
void setFontResolution(const FontResolution& fontRes) { _fontResolution = fontRes; }
|
||||
const FontResolution& getFontResolution() const { return _fontResolution; }
|
||||
|
||||
void setWidth(float width) { _width = width; }
|
||||
float getWidth() const { return _width; }
|
||||
|
||||
@@ -76,21 +78,33 @@ 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);
|
||||
|
||||
void subload() const;
|
||||
const TextureInfo* getTextureInfo(ShaderTechnique technique) const;
|
||||
|
||||
TextureInfo* getOrCreateTextureInfo(ShaderTechnique technique);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -99,6 +113,8 @@ protected:
|
||||
Font* _font;
|
||||
unsigned int _glyphCode;
|
||||
|
||||
FontResolution _fontResolution;
|
||||
|
||||
float _width;
|
||||
float _height;
|
||||
|
||||
@@ -108,15 +124,8 @@ protected:
|
||||
osg::Vec2 _verticalBearing;
|
||||
float _verticalAdvance;
|
||||
|
||||
GlyphTexture* _texture;
|
||||
int _texturePosX;
|
||||
int _texturePosY;
|
||||
osg::Vec2 _minTexCoord;
|
||||
osg::Vec2 _maxTexCoord;
|
||||
|
||||
typedef osg::buffered_value<GLuint> GLObjectList;
|
||||
mutable GLObjectList _globjList;
|
||||
|
||||
typedef std::vector< osg::ref_ptr<TextureInfo> > TextureInfoList;
|
||||
TextureInfoList _textureInfoList;
|
||||
};
|
||||
|
||||
class OSGTEXT_EXPORT GlyphGeometry : public osg::Referenced
|
||||
@@ -253,12 +262,13 @@ public:
|
||||
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
|
||||
virtual int compare(const osg::StateAttribute& rhs) const;
|
||||
|
||||
/** Set the margin around each glyph, to ensure that texture filtering doesn't bleed adjacent glyph's into each other.*/
|
||||
void setGlyphImageMargin(unsigned int margin) { _margin = margin; }
|
||||
unsigned int getGlyphImageMargin() const { return _margin; }
|
||||
void setShaderTechnique(ShaderTechnique technique) { _shaderTechnique = technique; }
|
||||
|
||||
void setGlyphImageMarginRatio(float margin) { _marginRatio = margin; }
|
||||
float getGlyphImageMarginRatio() const { return _marginRatio; }
|
||||
ShaderTechnique getShaderTechnique() const { return _shaderTechnique; }
|
||||
|
||||
|
||||
int getEffectMargin(const Glyph* glyph);
|
||||
int getTexelMargin(const Glyph* glyph);
|
||||
|
||||
bool getSpaceForGlyph(Glyph* glyph, int& posX, int& posY);
|
||||
|
||||
@@ -277,14 +287,13 @@ protected:
|
||||
|
||||
virtual ~GlyphTexture();
|
||||
|
||||
void copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info);
|
||||
|
||||
// parameter used to compute the size and position of empty space
|
||||
// in the texture which could accommodate new glyphs.
|
||||
int _margin;
|
||||
float _marginRatio;
|
||||
int _usedY;
|
||||
int _partUsedX;
|
||||
int _partUsedY;
|
||||
ShaderTechnique _shaderTechnique;
|
||||
|
||||
int _usedY;
|
||||
int _partUsedX;
|
||||
int _partUsedY;
|
||||
|
||||
typedef std::vector< osg::ref_ptr<Glyph> > GlyphRefList;
|
||||
typedef std::vector< const Glyph* > GlyphPtrList;
|
||||
|
||||
@@ -36,15 +36,12 @@ 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>(font)); };
|
||||
/** Set the ShaderTechnique hint to specify what fatures in the text shaders to enable.*/
|
||||
void setShaderTechnique(ShaderTechnique technique);
|
||||
|
||||
/** Set the Font to use to render the text.*/
|
||||
virtual void setFont(osg::ref_ptr<Font> font);
|
||||
/** Get the ShaderTechnique hint.*/
|
||||
ShaderTechnique getShaderTechnique() { return _shaderTechnique; }
|
||||
|
||||
/** 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
|
||||
@@ -70,31 +67,6 @@ public:
|
||||
NONE
|
||||
};
|
||||
|
||||
enum BackdropImplementation
|
||||
{
|
||||
/* No longer supported, naps to DELAYED_DEPTH_WRITES.*/
|
||||
POLYGON_OFFSET = 0,
|
||||
|
||||
/* No longer supported, naps to DELAYED_DEPTH_WRITES.*/
|
||||
NO_DEPTH_BUFFER,
|
||||
|
||||
/* No longer supported, naps to DELAYED_DEPTH_WRITES.*/
|
||||
DEPTH_RANGE,
|
||||
|
||||
/* No longer supported, naps to DELAYED_DEPTH_WRITES.*/
|
||||
STENCIL_BUFFER,
|
||||
|
||||
/* DELAYED_DEPTH_WRITES
|
||||
* This mode renders all text with depth writes turned off, then
|
||||
* again with depth writes on, but with the color buffer disabled.
|
||||
* This should render text accurately for all graphics cards. The
|
||||
* only downside is the additional pass to render to the depth
|
||||
* 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
|
||||
};
|
||||
|
||||
/**
|
||||
* BackdropType gives you a background shadow text behind your regular
|
||||
* text. This helps give text extra contrast which can be useful when
|
||||
@@ -149,18 +121,6 @@ public:
|
||||
|
||||
const osg::Vec4& getBackdropColor() const { return _backdropColor; }
|
||||
|
||||
/**
|
||||
* This specifies the underlying backdrop rendering implementation.
|
||||
* Unfortunately, at this time, there is no "perfect" rendering solution
|
||||
* so this function is provided to let you 'pick your poison'. Each
|
||||
* implementation has trade-offs. See BackdropImplementation enum
|
||||
* docs for details.*/
|
||||
void setBackdropImplementation(BackdropImplementation implementation);
|
||||
|
||||
BackdropImplementation getBackdropImplementation() const { return _backdropImplementation; }
|
||||
|
||||
|
||||
|
||||
enum ColorGradientMode
|
||||
{
|
||||
SOLID = 0, // a.k.a. ColorGradients off
|
||||
@@ -232,6 +192,20 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
/** deprecated, value ignored.*/
|
||||
enum BackdropImplementation
|
||||
{
|
||||
POLYGON_OFFSET = 0,
|
||||
NO_DEPTH_BUFFER,
|
||||
DEPTH_RANGE,
|
||||
STENCIL_BUFFER,
|
||||
DELAYED_DEPTH_WRITES
|
||||
};
|
||||
|
||||
/** deprecated, value ignored.*/
|
||||
void setBackdropImplementation(BackdropImplementation) {}
|
||||
/** deprecated, value should be ignored.*/
|
||||
BackdropImplementation getBackdropImplementation() const { return DELAYED_DEPTH_WRITES; }
|
||||
|
||||
// internal structures, variable and methods used for rendering of characters.
|
||||
struct OSGTEXT_EXPORT GlyphQuads
|
||||
@@ -239,7 +213,7 @@ public:
|
||||
typedef std::vector<Glyph*> Glyphs;
|
||||
|
||||
Glyphs _glyphs;
|
||||
Primitives _primitives;
|
||||
osg::ref_ptr<osg::DrawElements> _primitives;
|
||||
|
||||
GlyphQuads();
|
||||
GlyphQuads(const GlyphQuads& gq);
|
||||
@@ -284,6 +258,8 @@ protected:
|
||||
|
||||
virtual ~Text();
|
||||
|
||||
virtual osg::StateSet* createStateSet();
|
||||
|
||||
Font* getActiveFont();
|
||||
const Font* getActiveFont() const;
|
||||
|
||||
@@ -302,7 +278,6 @@ protected:
|
||||
|
||||
virtual void computePositionsImplementation();
|
||||
|
||||
void computeBackdropPositions();
|
||||
void computeBackdropBoundingBox();
|
||||
void computeBoundingBoxMargin();
|
||||
|
||||
@@ -314,10 +289,10 @@ protected:
|
||||
|
||||
void drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const;
|
||||
|
||||
ShaderTechnique _shaderTechnique;
|
||||
bool _enableDepthWrites;
|
||||
|
||||
BackdropType _backdropType;
|
||||
BackdropImplementation _backdropImplementation;
|
||||
|
||||
float _backdropHorizontalOffset;
|
||||
float _backdropVerticalOffset;
|
||||
|
||||
@@ -53,6 +53,9 @@ public:
|
||||
virtual void setFont(const std::string& fontfile);
|
||||
|
||||
/** Get the font. Return 0 if default is being used.*/
|
||||
Font* getFont() { return _font.get(); }
|
||||
|
||||
/** Get the const font. Return 0 if default is being used.*/
|
||||
const Font* getFont() const { return _font.get(); }
|
||||
|
||||
|
||||
@@ -284,6 +287,10 @@ protected:
|
||||
|
||||
virtual ~TextBase();
|
||||
|
||||
virtual osg::StateSet* createStateSet();
|
||||
|
||||
virtual void assignStateSet();
|
||||
|
||||
void initArraysAndBuffers();
|
||||
|
||||
osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo) const;
|
||||
|
||||
@@ -97,6 +97,9 @@ class OSGUTIL_EXPORT GLObjectsVisitor : public osg::NodeVisitor
|
||||
void apply(osg::Drawable& drawable);
|
||||
void apply(osg::StateSet& stateset);
|
||||
|
||||
/** Do a compile traversal and then reset any state,*/
|
||||
void compile(osg::Node& node);
|
||||
|
||||
protected:
|
||||
|
||||
typedef std::set<osg::Drawable*> DrawableAppliedSet;
|
||||
|
||||
Reference in New Issue
Block a user