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:
commit
1126812f8f
@ -473,7 +473,6 @@ void ComputeNode::addDataMonitor(osg::Vec3 placement, osg::Vec3 relativePlacemen
|
|||||||
pat->setName(labelCaption);
|
pat->setName(labelCaption);
|
||||||
text->setText(pat->getName());
|
text->setText(pat->getName());
|
||||||
text->setBackdropType(osgText::Text::OUTLINE);
|
text->setBackdropType(osgText::Text::OUTLINE);
|
||||||
text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET);
|
|
||||||
text->setBackdropOffset(0.05f);
|
text->setBackdropOffset(0.05f);
|
||||||
text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
@ -121,10 +121,70 @@ osg::Node* createFadeText(osg::EllipsoidModel* ellipsoid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int, char**)
|
class TextSettings : public osg::NodeVisitor
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
TextSettings(osg::ArgumentParser& arguments):
|
||||||
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||||
|
_backdropTypeSet(false),
|
||||||
|
_backdropType(osgText::Text::NONE),
|
||||||
|
_shaderTechniqueSet(false),
|
||||||
|
_shaderTechnique(osgText::GREYSCALE)
|
||||||
|
{
|
||||||
|
if (arguments.read("--outline"))
|
||||||
|
{
|
||||||
|
_backdropTypeSet = true;
|
||||||
|
_backdropType = osgText::Text::OUTLINE;
|
||||||
|
}
|
||||||
|
if (arguments.read("--sdf"))
|
||||||
|
{
|
||||||
|
_shaderTechniqueSet = true;
|
||||||
|
_shaderTechnique = osgText::SIGNED_DISTANCE_FIELD;
|
||||||
|
}
|
||||||
|
if (arguments.read("--all"))
|
||||||
|
{
|
||||||
|
_shaderTechniqueSet = true;
|
||||||
|
_shaderTechnique = osgText::ALL_FEATURES;
|
||||||
|
}
|
||||||
|
if (arguments.read("--greyscale"))
|
||||||
|
{
|
||||||
|
_shaderTechniqueSet = true;
|
||||||
|
_shaderTechnique = osgText::GREYSCALE;
|
||||||
|
}
|
||||||
|
if (arguments.read("--no-shader"))
|
||||||
|
{
|
||||||
|
_shaderTechniqueSet = true;
|
||||||
|
_shaderTechnique = osgText::NO_TEXT_SHADER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(osg::Drawable& drawable)
|
||||||
|
{
|
||||||
|
osgText::Text* text = dynamic_cast<osgText::Text*>(&drawable);
|
||||||
|
if (text)
|
||||||
|
{
|
||||||
|
if (_backdropTypeSet)
|
||||||
|
{
|
||||||
|
text->setBackdropType(_backdropType);
|
||||||
|
text->setBackdropOffset(0.1f);
|
||||||
|
text->setBackdropColor(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
}
|
||||||
|
if (_shaderTechniqueSet) text->setShaderTechnique(_shaderTechnique);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _backdropTypeSet;
|
||||||
|
osgText::Text::BackdropType _backdropType;
|
||||||
|
bool _shaderTechniqueSet;
|
||||||
|
osgText::ShaderTechnique _shaderTechnique;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
osg::ArgumentParser arguments(&argc, argv);
|
||||||
|
|
||||||
// construct the viewer.
|
// construct the viewer.
|
||||||
osgViewer::Viewer viewer;
|
osgViewer::Viewer viewer(arguments);
|
||||||
|
|
||||||
viewer.getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
|
viewer.getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
|
||||||
viewer.getCamera()->setNearFarRatio(0.00001f);
|
viewer.getCamera()->setNearFarRatio(0.00001f);
|
||||||
@ -144,6 +204,12 @@ int main(int, char**)
|
|||||||
csn->addChild(createFadeText(csn->getEllipsoidModel()));
|
csn->addChild(createFadeText(csn->getEllipsoidModel()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arguments.argc()>1)
|
||||||
|
{
|
||||||
|
TextSettings textSettings(arguments);
|
||||||
|
root->accept(textSettings);
|
||||||
|
}
|
||||||
|
|
||||||
viewer.setCameraManipulator(new osgGA::TerrainManipulator);
|
viewer.setCameraManipulator(new osgGA::TerrainManipulator);
|
||||||
|
|
||||||
return viewer.run();
|
return viewer.run();
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include <osg/io_utils>
|
#include <osg/io_utils>
|
||||||
#include <osg/ArgumentParser>
|
#include <osg/ArgumentParser>
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
|
#include <osg/MatrixTransform>
|
||||||
|
#include <osgDB/ReadFile>
|
||||||
|
#include <osgDB/WriteFile>
|
||||||
#include <osgViewer/Viewer>
|
#include <osgViewer/Viewer>
|
||||||
#include <osgViewer/ViewerEventHandlers>
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
#include <osgGA/StateSetManipulator>
|
#include <osgGA/StateSetManipulator>
|
||||||
@ -56,80 +59,367 @@ osg::Camera* createOrthoCamera(double width, double height)
|
|||||||
return camera;
|
return camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
osgText::Text* createLabel(const std::string& l, const char* f, unsigned int size)
|
typedef std::list<unsigned int> Sizes;
|
||||||
|
|
||||||
|
struct TextSettings
|
||||||
{
|
{
|
||||||
static osg::Vec3 pos(10.0f, 10.0f, 0.0f);
|
TextSettings():
|
||||||
|
fontFilename("fonts/arial.ttf"),
|
||||||
|
minFilter(osg::Texture::LINEAR_MIPMAP_LINEAR),
|
||||||
|
magFilter(osg::Texture::LINEAR),
|
||||||
|
maxAnisotropy(16.0f),
|
||||||
|
shaderTechnique(osgText::GREYSCALE),
|
||||||
|
textColor(1.0f, 1.0f, 1.0f, 1.0f),
|
||||||
|
backdropType(osgText::Text::NONE),
|
||||||
|
backdropOffset(0.07f, 0.07f),
|
||||||
|
backdropColor(0.0f, 0.0f, 0.0f, 1.0f),
|
||||||
|
scaleFontSizeToFontResolution(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void readFilterMode(const std::string& value, osg::Texture::FilterMode& filterMode)
|
||||||
|
{
|
||||||
|
if (value=="LINEAR") filterMode = osg::Texture::LINEAR;
|
||||||
|
else if (value=="NEAREST") filterMode = osg::Texture::NEAREST;
|
||||||
|
else if (value=="LINEAR_MIPMAP_LINEAR") filterMode = osg::Texture::LINEAR_MIPMAP_LINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(osg::ArgumentParser& arguments)
|
||||||
|
{
|
||||||
|
if (arguments.read("--test"))
|
||||||
|
{
|
||||||
|
backgroundColor = osg::Vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
fontFilename = "fonts/arialbd.ttf";
|
||||||
|
backdropType = osgText::Text::OUTLINE;
|
||||||
|
|
||||||
|
sizes.clear();
|
||||||
|
sizes.push_back(8);
|
||||||
|
sizes.push_back(16);
|
||||||
|
sizes.push_back(32);
|
||||||
|
sizes.push_back(64);
|
||||||
|
sizes.push_back(128);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.read("--GREYSCALE")) { shaderTechnique = osgText::GREYSCALE; }
|
||||||
|
if (arguments.read("--SIGNED_DISTANCE_FIELD")) { shaderTechnique = osgText::SIGNED_DISTANCE_FIELD; }
|
||||||
|
if (arguments.read("--ALL_FEATURES")) { shaderTechnique = osgText::ALL_FEATURES; }
|
||||||
|
|
||||||
|
if (arguments.read("--font",fontFilename)) {}
|
||||||
|
|
||||||
|
std::string value;
|
||||||
|
if (arguments.read("--min", value)) { readFilterMode(value, minFilter); }
|
||||||
|
if (arguments.read("--mag", value)) { readFilterMode(value, magFilter); }
|
||||||
|
|
||||||
|
if (arguments.read("--anisotropy",maxAnisotropy)) {}
|
||||||
|
|
||||||
|
|
||||||
|
if (arguments.read("--outline")) backdropType = osgText::Text::OUTLINE;
|
||||||
|
if (arguments.read("--shadow")) backdropType = osgText::Text::DROP_SHADOW_BOTTOM_RIGHT;
|
||||||
|
if (arguments.read("--shadow-br")) backdropType = osgText::Text::DROP_SHADOW_BOTTOM_RIGHT;
|
||||||
|
if (arguments.read("--shadow-cr")) backdropType = osgText::Text::DROP_SHADOW_CENTER_RIGHT;
|
||||||
|
if (arguments.read("--shadow-tr")) backdropType = osgText::Text::DROP_SHADOW_TOP_RIGHT;
|
||||||
|
if (arguments.read("--shadow-bc")) backdropType = osgText::Text::DROP_SHADOW_BOTTOM_CENTER;
|
||||||
|
if (arguments.read("--shadow-tc")) backdropType = osgText::Text::DROP_SHADOW_TOP_CENTER;
|
||||||
|
if (arguments.read("--shadow-bl")) backdropType = osgText::Text::DROP_SHADOW_BOTTOM_LEFT;
|
||||||
|
if (arguments.read("--shadow-cl")) backdropType = osgText::Text::DROP_SHADOW_CENTER_LEFT;
|
||||||
|
if (arguments.read("--shadow-tl")) backdropType = osgText::Text::DROP_SHADOW_TOP_LEFT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float offset;
|
||||||
|
if (arguments.read("--offset", offset)) backdropOffset.set(offset, offset);
|
||||||
|
|
||||||
|
if (arguments.read("--text-color", textColor.r(), textColor.g(), textColor.b(), textColor.a())) {}
|
||||||
|
if (arguments.read("--bd-color", backdropColor.r(), backdropColor.g(), backdropColor.b(), backdropColor.a())) {}
|
||||||
|
if (arguments.read("--bg-color", backgroundColor.r(), backgroundColor.g(), backgroundColor.b(), backgroundColor.a())) {}
|
||||||
|
|
||||||
|
if (arguments.read("--constant-size")) scaleFontSizeToFontResolution = false;
|
||||||
|
if (arguments.read("--scale-size")) scaleFontSizeToFontResolution = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void setText(osgText::Text& text)
|
||||||
|
{
|
||||||
|
OSG_NOTICE<<"Settings::setText()"<<std::endl;
|
||||||
|
|
||||||
|
osg::ref_ptr<osgText::Font> font;
|
||||||
|
|
||||||
|
if (fontFilename!="default") font = osgText::readRefFontFile(fontFilename);
|
||||||
|
|
||||||
|
if (!font) font = osgText::Font::getDefaultFont();
|
||||||
|
|
||||||
|
font->setMinFilterHint(minFilter);
|
||||||
|
font->setMagFilterHint(magFilter);
|
||||||
|
font->setMaxAnisotropy(maxAnisotropy);
|
||||||
|
|
||||||
|
text.setColor(textColor);
|
||||||
|
text.setBackdropType(backdropType);
|
||||||
|
text.setBackdropOffset(backdropOffset.x(), backdropOffset.y());
|
||||||
|
text.setBackdropColor(backdropColor);
|
||||||
|
text.setShaderTechnique(shaderTechnique);
|
||||||
|
|
||||||
|
text.setFont(font.get());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fontFilename;
|
||||||
|
osg::Texture::FilterMode minFilter;
|
||||||
|
osg::Texture::FilterMode magFilter;
|
||||||
|
float maxAnisotropy;
|
||||||
|
osgText::ShaderTechnique shaderTechnique;
|
||||||
|
|
||||||
|
osg::Vec4 textColor;
|
||||||
|
osgText::Text::BackdropType backdropType;
|
||||||
|
osg::Vec2 backdropOffset;
|
||||||
|
osg::Vec4 backdropColor;
|
||||||
|
osg::Vec4 backgroundColor;
|
||||||
|
Sizes sizes;
|
||||||
|
bool scaleFontSizeToFontResolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
osgText::Text* createLabel(const std::string& l, TextSettings& settings, unsigned int size, osg::Vec3& pos)
|
||||||
|
{
|
||||||
osgText::Text* label = new osgText::Text();
|
osgText::Text* label = new osgText::Text();
|
||||||
osg::ref_ptr<osgText::Font> font = osgText::readRefFontFile(f);
|
|
||||||
|
|
||||||
label->setFont(font);
|
settings.setText(*label);
|
||||||
label->setCharacterSize(size);
|
|
||||||
|
if (settings.scaleFontSizeToFontResolution)
|
||||||
|
{
|
||||||
|
label->setCharacterSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
label->setFontResolution(size, size);
|
label->setFontResolution(size, size);
|
||||||
label->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
|
||||||
label->setPosition(pos);
|
label->setPosition(pos);
|
||||||
label->setAlignment(osgText::Text::LEFT_BOTTOM);
|
label->setAlignment(osgText::Text::LEFT_BOTTOM);
|
||||||
|
|
||||||
// It seems to be important we do this last to get best results?
|
// It seems to be important we do this last to get best results?
|
||||||
label->setText(l);
|
label->setText(l);
|
||||||
|
|
||||||
textInfo(label);
|
// textInfo(label);
|
||||||
|
|
||||||
pos.y() += size + 10.0f;
|
pos.y() += label->getCharacterHeight()*2.0;
|
||||||
|
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::list<unsigned int> Sizes;
|
class KeyHandler : public osgGA::GUIEventHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
KeyHandler() {}
|
||||||
|
|
||||||
|
~KeyHandler() {}
|
||||||
|
|
||||||
|
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
|
||||||
|
{
|
||||||
|
osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
|
||||||
|
if (!view) return false;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
osg::StateSet* stateset = view->getSceneData()->getOrCreateStateSet();
|
||||||
|
#else
|
||||||
|
osg::StateSet* stateset = view->getCamera()->getOrCreateStateSet();
|
||||||
|
#endif
|
||||||
|
switch(ea.getEventType())
|
||||||
|
{
|
||||||
|
case(osgGA::GUIEventAdapter::KEYUP):
|
||||||
|
{
|
||||||
|
if (ea.getKey()=='d')
|
||||||
|
{
|
||||||
|
toggleDefine(stateset, "SIGNED_DISTANCE_FIELD");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (ea.getKey()=='o')
|
||||||
|
{
|
||||||
|
toggleDefine(stateset, "OUTLINE");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleDefine(osg::StateSet* stateset, const std::string& define)
|
||||||
|
{
|
||||||
|
osg::StateSet::DefinePair* dp = stateset->getDefinePair(define);
|
||||||
|
if (dp)
|
||||||
|
{
|
||||||
|
OSG_NOTICE<<"Disabling "<<define<<std::endl;
|
||||||
|
stateset->removeDefine(define);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OSG_NOTICE<<"Enabling "<<define<<std::endl;
|
||||||
|
stateset->setDefine(define);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
osgViewer::Viewer viewer;
|
|
||||||
osg::ArgumentParser args(&argc, argv);
|
osg::ArgumentParser args(&argc, argv);
|
||||||
|
osgViewer::Viewer viewer(args);
|
||||||
// Make sure we have the minimum args...
|
|
||||||
if(argc <= 2)
|
|
||||||
{
|
|
||||||
osg::notify(osg::FATAL) << "usage: " << args[0] << " fontfile size1 [size2 ...]" << std::endl;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
|
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
|
||||||
viewer.addEventHandler(new osgViewer::StatsHandler());
|
viewer.addEventHandler(new osgViewer::StatsHandler());
|
||||||
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
|
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
|
||||||
|
viewer.addEventHandler(new KeyHandler());
|
||||||
|
|
||||||
osg::Group* group = new osg::Group();
|
TextSettings settings;
|
||||||
osg::Camera* camera = createOrthoCamera(1280.0f, 1024.0f);
|
settings.backgroundColor = viewer.getCamera()->getClearColor();
|
||||||
|
|
||||||
// Create the list of desired sizes.
|
settings.read(args);
|
||||||
Sizes sizes;
|
|
||||||
|
|
||||||
for(int i = 2; i < argc; i++)
|
viewer.getCamera()->setClearColor(settings.backgroundColor);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Group> root = new osg::Group;
|
||||||
|
|
||||||
|
bool split_screen = args.read("--split");
|
||||||
|
|
||||||
|
if (split_screen)
|
||||||
{
|
{
|
||||||
if(!args.isNumber(i)) continue;
|
viewer.realize();
|
||||||
|
|
||||||
sizes.push_back(std::atoi(args[i]));
|
// quite an dirty divusion of the master Camera's window if one is assigned.
|
||||||
|
if (viewer.getCamera()->getGraphicsContext())
|
||||||
|
{
|
||||||
|
viewer.stopThreading();
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::GraphicsContext> gc = viewer.getCamera()->getGraphicsContext();
|
||||||
|
osg::ref_ptr<const osg::GraphicsContext::Traits> traits = gc->getTraits();
|
||||||
|
|
||||||
|
// left half
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
|
||||||
|
camera->setCullMask(0x1);
|
||||||
|
camera->setGraphicsContext(gc.get());
|
||||||
|
camera->setViewport(new osg::Viewport(0,0, traits->width/2, traits->height));
|
||||||
|
viewer.addSlave(camera.get(), osg::Matrixd::translate(1.0,0.0,0.0), osg::Matrixd::scale(2.0, 1.0, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
|
||||||
|
camera->setCullMask(0x2);
|
||||||
|
camera->setGraphicsContext(gc.get());
|
||||||
|
camera->setViewport(new osg::Viewport(traits->width/2+2,0, traits->width/2, traits->height));
|
||||||
|
viewer.addSlave(camera.get(), osg::Matrixd::translate(-1.0,0.0,0.0), osg::Matrixd::scale(2.0, 1.0, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
viewer.getCamera()->setGraphicsContext(0);
|
||||||
|
|
||||||
|
viewer.startThreading();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
split_screen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Geode* geode = new osg::Geode();
|
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
|
||||||
|
transform->setMatrix(osg::Matrixd::rotate(osg::DegreesToRadians(90.0), 1.0, 0.0, 0.0));
|
||||||
|
root->addChild(transform.get());
|
||||||
|
root = transform;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Program> program = new osg::Program;
|
||||||
|
std::string shaderFilename;
|
||||||
|
while(args.read("--shader", shaderFilename))
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Shader> shader = osgDB::readRefShaderFile(shaderFilename);
|
||||||
|
if (shader.get())
|
||||||
|
{
|
||||||
|
OSG_NOTICE<<"Loading shader "<<shaderFilename<<std::endl;
|
||||||
|
program->addShader(shader.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program->getNumShaders()>0)
|
||||||
|
{
|
||||||
|
OSG_NOTICE<<"Using shaders"<<std::endl;
|
||||||
|
root->getOrCreateStateSet()->setAttribute(program.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
|
||||||
|
root->getOrCreateStateSet()->addUniform(new osg::Uniform("glyphTexture", 0));
|
||||||
|
|
||||||
|
settings.shaderTechnique = osgText::ALL_FEATURES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string outputFilename;
|
||||||
|
if (args.read("-o", outputFilename)) {}
|
||||||
|
|
||||||
|
if (args.argc() > 1)
|
||||||
|
{
|
||||||
|
settings.fontFilename = argv[1];
|
||||||
|
|
||||||
|
// Create the list of desired sizes.
|
||||||
|
for(int i = 2; i < args.argc(); i++)
|
||||||
|
{
|
||||||
|
if(!args.isNumber(i)) continue;
|
||||||
|
|
||||||
|
settings.sizes.push_back(std::atoi(args[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.sizes.empty())
|
||||||
|
{
|
||||||
|
settings.sizes.push_back(8);
|
||||||
|
settings.sizes.push_back(16);
|
||||||
|
settings.sizes.push_back(32);
|
||||||
|
settings.sizes.push_back(64);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
|
||||||
|
|
||||||
|
osg::Vec3 pos(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
// Add all of our osgText drawables.
|
// Add all of our osgText drawables.
|
||||||
for(Sizes::const_iterator i = sizes.begin(); i != sizes.end(); i++)
|
for(Sizes::const_iterator i = settings.sizes.begin(); i != settings.sizes.end(); i++)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << *i << " 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
ss << *i << " 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
||||||
geode->addDrawable(createLabel(ss.str(), args[1], *i));
|
geode->addDrawable(createLabel(ss.str(), settings, *i, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
camera->addChild(geode);
|
root->addChild(geode.get());
|
||||||
|
|
||||||
group->addChild(camera);
|
if (split_screen)
|
||||||
|
{
|
||||||
|
geode->setNodeMask(0x1);
|
||||||
|
|
||||||
viewer.setSceneData(group);
|
osg::ref_ptr<osg::Geode> right_geode = new osg::Geode;
|
||||||
|
right_geode->setNodeMask(0x2);
|
||||||
|
|
||||||
|
settings.shaderTechnique = osgText::GREYSCALE;
|
||||||
|
|
||||||
|
pos.set(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
for(Sizes::const_iterator i = settings.sizes.begin(); i != settings.sizes.end(); i++)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
ss << *i << " 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
||||||
|
right_geode->addDrawable(createLabel(ss.str(), settings, *i, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
root->addChild(right_geode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!outputFilename.empty())
|
||||||
|
{
|
||||||
|
osgDB::writeNodeFile(*root, outputFilename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
viewer.setSceneData(root.get());
|
||||||
|
|
||||||
return viewer.run();
|
return viewer.run();
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include <osgGA/TrackballManipulator>
|
#include <osgGA/TrackballManipulator>
|
||||||
|
|
||||||
#include <osgViewer/Viewer>
|
#include <osgViewer/Viewer>
|
||||||
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
#include <osgDB/ReadFile>
|
#include <osgDB/ReadFile>
|
||||||
#include <osgDB/FileUtils>
|
#include <osgDB/FileUtils>
|
||||||
@ -424,6 +425,9 @@ int main( int argc, char **argv )
|
|||||||
// add the handler for doing the picking
|
// add the handler for doing the picking
|
||||||
viewer.addEventHandler(new PickHandler(&viewer,updateText.get()));
|
viewer.addEventHandler(new PickHandler(&viewer,updateText.get()));
|
||||||
|
|
||||||
|
// add the stats handler
|
||||||
|
viewer.addEventHandler(new osgViewer::StatsHandler);
|
||||||
|
|
||||||
osg::Group* root = new osg::Group();
|
osg::Group* root = new osg::Group();
|
||||||
|
|
||||||
root->addChild( setupGraph() );
|
root->addChild( setupGraph() );
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
static bool s_useSDF = false;
|
||||||
|
|
||||||
class MyBillboardTransform : public osg::PositionAttitudeTransform
|
class MyBillboardTransform : public osg::PositionAttitudeTransform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -147,6 +150,12 @@ osg:: Node* createTextBelow(const osg::BoundingBox& bb, const std::string& label
|
|||||||
|
|
||||||
text->setFont(font);
|
text->setFont(font);
|
||||||
text->setFontResolution(64,64);
|
text->setFontResolution(64,64);
|
||||||
|
|
||||||
|
if (s_useSDF)
|
||||||
|
{
|
||||||
|
text->setShaderTechnique(osgText::ALL_FEATURES);
|
||||||
|
}
|
||||||
|
|
||||||
text->setAlignment(osgText::Text::CENTER_CENTER);
|
text->setAlignment(osgText::Text::CENTER_CENTER);
|
||||||
text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
||||||
text->setPosition(bb.center()-osg::Vec3(0.0f,0.0f,(bb.zMax()-bb.zMin())));
|
text->setPosition(bb.center()-osg::Vec3(0.0f,0.0f,(bb.zMax()-bb.zMin())));
|
||||||
@ -174,48 +183,35 @@ osg:: Node* createTextLeft(const osg::BoundingBox& bb, const std::string& label,
|
|||||||
|
|
||||||
text->setFont(font);
|
text->setFont(font);
|
||||||
text->setFontResolution(110,120);
|
text->setFontResolution(110,120);
|
||||||
|
|
||||||
|
if (s_useSDF)
|
||||||
|
{
|
||||||
|
text->setShaderTechnique(osgText::ALL_FEATURES);
|
||||||
|
}
|
||||||
|
|
||||||
text->setAlignment(osgText::Text::RIGHT_CENTER);
|
text->setAlignment(osgText::Text::RIGHT_CENTER);
|
||||||
text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
||||||
text->setCharacterSize((bb.zMax()-bb.zMin())*1.0f);
|
text->setCharacterSize((bb.zMax()-bb.zMin())*1.0f);
|
||||||
|
|
||||||
text->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin()),-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.1f));
|
text->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin()),-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.1f));
|
||||||
//text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f)); // Neil's original OSG colour
|
|
||||||
text->setColor(osg::Vec4(0.20f,0.45f,0.60f,1.0f)); // OGL logo colour
|
text->setColor(osg::Vec4(0.20f,0.45f,0.60f,1.0f)); // OGL logo colour
|
||||||
text->setText(label);
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
text->setBackdropType(osgText::Text::OUTLINE);
|
text->setBackdropType(osgText::Text::OUTLINE);
|
||||||
// text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
|
text->setBackdropOffset(0.03f);
|
||||||
|
|
||||||
text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET);
|
|
||||||
// text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER);
|
|
||||||
// text->setBackdropImplementation(osgText::Text::DEPTH_RANGE);
|
|
||||||
// text->setBackdropImplementation(osgText::Text::STENCIL_BUFFER);
|
|
||||||
|
|
||||||
text->setBackdropOffset(0.05f);
|
|
||||||
text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.5f, 1.0f));
|
text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.5f, 1.0f));
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
text->setColorGradientMode(osgText::Text::OVERALL);
|
text->setColorGradientMode(osgText::Text::OVERALL);
|
||||||
osg::Vec4 lightblue(0.30f,0.6f,0.90f,1.0f);
|
osg::Vec4 lightblue(0.30f,0.6f,0.90f,1.0f);
|
||||||
osg::Vec4 blue(0.10f,0.30f,0.40f,1.0f);
|
osg::Vec4 blue(0.10f,0.30f,0.40f,1.0f);
|
||||||
text->setColorGradientCorners(lightblue, blue, blue, lightblue);
|
text->setColorGradientCorners(lightblue, blue, blue, lightblue);
|
||||||
#else
|
|
||||||
text->setColorGradientMode(osgText::Text::OVERALL);
|
text->setText(label);
|
||||||
osg::Vec4 light = osg::Vec4(0.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
osg::Vec4 dark = osg::Vec4(0.0f, 0.0f, 0.5f, 1.0f);
|
|
||||||
text->setColorGradientCorners(light, dark, dark, light);
|
|
||||||
// text->setColorGradientCorners(dark, light, light, dark);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
geode->addDrawable( text );
|
geode->addDrawable( text );
|
||||||
|
|
||||||
|
|
||||||
if (!subscript.empty())
|
if (!subscript.empty())
|
||||||
{
|
{
|
||||||
//osgText::Text* subscript = new osgText::Text(new osgText::TextureFont(font,45));
|
|
||||||
|
|
||||||
osgText::Text* subscriptText = new osgText::Text;
|
osgText::Text* subscriptText = new osgText::Text;
|
||||||
subscriptText->setFont(font);
|
subscriptText->setFont(font);
|
||||||
subscriptText->setText(subscript);
|
subscriptText->setText(subscript);
|
||||||
@ -353,9 +349,6 @@ osg:: Node* createBoxNo5No2(const osg::BoundingBox& bb,float chordRatio)
|
|||||||
|
|
||||||
osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right)
|
osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
osg::Geometry* geom = new osg::Geometry;
|
osg::Geometry* geom = new osg::Geometry;
|
||||||
|
|
||||||
osg::Vec3 normal = (corner-top)^(right-corner);
|
osg::Vec3 normal = (corner-top)^(right-corner);
|
||||||
@ -475,6 +468,9 @@ int main( int argc, char **argv )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while(arguments.read("--sdf")) { s_useSDF = true; }
|
||||||
|
|
||||||
std::string label = "OpenSceneGraph";
|
std::string label = "OpenSceneGraph";
|
||||||
std::string subscript = "";
|
std::string subscript = "";
|
||||||
|
|
||||||
|
@ -621,8 +621,8 @@ struct TextCounterCallback : public osg::NodeCallback
|
|||||||
if (text)
|
if (text)
|
||||||
{
|
{
|
||||||
std::stringstream str;
|
std::stringstream str;
|
||||||
str <<"Text Counter "<<_textCounter<<std::endl;
|
str <<"Text Counter "<<_textCounter;
|
||||||
OSG_NOTICE<<"Udating text"<<str.str()<<std::endl;
|
OSG_NOTICE<<"Updating text : "<<str.str()<<std::endl;
|
||||||
|
|
||||||
text->setText(str.str());
|
text->setText(str.str());
|
||||||
|
|
||||||
@ -670,7 +670,7 @@ int main(int argc, char** argv)
|
|||||||
text->setUpdateCallback(new TextCounterCallback());
|
text->setUpdateCallback(new TextCounterCallback());
|
||||||
text->setFont("fonts/times.ttf");
|
text->setFont("fonts/times.ttf");
|
||||||
text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
||||||
text->setText("This is a counter test");
|
text->setText("Text Counter :");
|
||||||
|
|
||||||
viewer.setSceneData(text.get());
|
viewer.setSceneData(text.get());
|
||||||
}
|
}
|
||||||
|
@ -432,7 +432,6 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va
|
|||||||
|
|
||||||
default_text->setAlignment(osgText::Text::CENTER_CENTER);
|
default_text->setAlignment(osgText::Text::CENTER_CENTER);
|
||||||
default_text->setBackdropType(osgText::Text::OUTLINE);
|
default_text->setBackdropType(osgText::Text::OUTLINE);
|
||||||
// default_text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET);
|
|
||||||
default_text->setColor(osg::Vec4(1.0, 1.0, 0.0, 1.0));
|
default_text->setColor(osg::Vec4(1.0, 1.0, 0.0, 1.0));
|
||||||
default_text->setBackdropColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
|
default_text->setBackdropColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
|
||||||
default_text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
default_text->setAxisAlignment(osgText::Text::XZ_PLANE);
|
||||||
|
@ -30,12 +30,6 @@ osgWidget::Label* createLabel(const std::string& l, unsigned int size=13) {
|
|||||||
label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
|
label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
label->setLabel(l);
|
label->setLabel(l);
|
||||||
|
|
||||||
/*
|
|
||||||
text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
|
|
||||||
text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER);
|
|
||||||
text->setBackdropOffset(0.2f);
|
|
||||||
*/
|
|
||||||
|
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace osg {
|
namespace osg {
|
||||||
|
|
||||||
@ -319,9 +320,15 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced
|
|||||||
SHADER_GLES3
|
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; }
|
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; }
|
void setKeystoneHint(bool enabled) { _keystoneHint = enabled; }
|
||||||
bool getKeystoneHint() const { return _keystoneHint; }
|
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.*/
|
/** helper function for computing the right eye view matrix.*/
|
||||||
virtual osg::Matrixd computeRightEyeViewImplementation(const osg::Matrixd& view, double eyeSeperationScale=1.0) const;
|
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:
|
protected:
|
||||||
|
|
||||||
virtual ~DisplaySettings();
|
virtual ~DisplaySettings();
|
||||||
@ -415,6 +427,7 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced
|
|||||||
|
|
||||||
VertexBufferHint _vertexBufferHint;
|
VertexBufferHint _vertexBufferHint;
|
||||||
ShaderHint _shaderHint;
|
ShaderHint _shaderHint;
|
||||||
|
std::string _textShaderTechnique;
|
||||||
|
|
||||||
bool _keystoneHint;
|
bool _keystoneHint;
|
||||||
FileNames _keystoneFileNames;
|
FileNames _keystoneFileNames;
|
||||||
@ -422,6 +435,11 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced
|
|||||||
|
|
||||||
OSXMenubarBehavior _OSXMenubarBehavior;
|
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. */
|
* during rendering. */
|
||||||
inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
|
inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
|
||||||
|
|
||||||
/** Get the DisplaySettings */
|
/** Get the const DisplaySettings */
|
||||||
inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
|
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.*/
|
/** Set flag for early termination of the draw traversal.*/
|
||||||
|
@ -27,6 +27,7 @@ namespace osgText {
|
|||||||
|
|
||||||
// forward declare Font
|
// forward declare Font
|
||||||
class Font;
|
class Font;
|
||||||
|
class TextBase;
|
||||||
|
|
||||||
#ifdef OSG_PROVIDE_READFILE
|
#ifdef OSG_PROVIDE_READFILE
|
||||||
/** Read a font from specified file. The filename may contain a path.
|
/** Read a font from specified file. The filename may contain a path.
|
||||||
@ -84,13 +85,9 @@ public:
|
|||||||
|
|
||||||
static osg::ref_ptr<Font>& getDefaultFont();
|
static osg::ref_ptr<Font>& getDefaultFont();
|
||||||
|
|
||||||
void setTexEnv(osg::TexEnv* texenv) { if (texenv) _texenv = texenv; }
|
typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSets;
|
||||||
inline osg::TexEnv* getTexEnv() { return _texenv.get(); }
|
StateSets& getCachedStateSets() { return _statesets; }
|
||||||
inline const osg::TexEnv* getTexEnv() const { return _texenv.get(); }
|
const StateSets& getCachedStateSets() const { return _statesets; }
|
||||||
|
|
||||||
void setStateSet(osg::StateSet* stateset) { _stateset = stateset; }
|
|
||||||
osg::StateSet* getStateSet() { return _stateset.get(); }
|
|
||||||
const osg::StateSet* getStateSet() const { return _stateset.get(); }
|
|
||||||
|
|
||||||
|
|
||||||
/** Get a kerning (adjustment of spacing of two adjacent character) for specified charcodes and a font resolution.*/
|
/** 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.*/
|
* return true on success, return false when not supported.*/
|
||||||
virtual bool getVerticalSize(float& ascender, float& descender) const { return _implementation ? _implementation->getVerticalSize(ascender, descender) : false; }
|
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.
|
/** Set the size of texture to create to store the glyph images when rendering.
|
||||||
* Note, this doesn't affect already created Texture Glhph's.*/
|
* Note, this doesn't affect already created Texture Glhph's.*/
|
||||||
void setTextureSizeHint(unsigned int width,unsigned int height);
|
void setTextureSizeHint(unsigned int width,unsigned int height);
|
||||||
@ -140,6 +124,9 @@ public:
|
|||||||
void setMagFilterHint(osg::Texture::FilterMode mode);
|
void setMagFilterHint(osg::Texture::FilterMode mode);
|
||||||
osg::Texture::FilterMode getMagFilterHint() const;
|
osg::Texture::FilterMode getMagFilterHint() const;
|
||||||
|
|
||||||
|
void setMaxAnisotropy(float anis) { _maxAnisotropy = anis; }
|
||||||
|
float getMaxAnisotropy() const { return _maxAnisotropy; }
|
||||||
|
|
||||||
unsigned int getFontDepth() const { return _depth; }
|
unsigned int getFontDepth() const { return _depth; }
|
||||||
|
|
||||||
void setNumberCurveSamples(unsigned int numSamples) { _numCurveSamples = numSamples; }
|
void setNumberCurveSamples(unsigned int numSamples) { _numCurveSamples = numSamples; }
|
||||||
@ -170,13 +157,14 @@ public:
|
|||||||
typedef std::vector< osg::ref_ptr<GlyphTexture> > GlyphTextureList;
|
typedef std::vector< osg::ref_ptr<GlyphTexture> > GlyphTextureList;
|
||||||
GlyphTextureList& getGlyphTextureList() { return _glyphTextureList; }
|
GlyphTextureList& getGlyphTextureList() { return _glyphTextureList; }
|
||||||
|
|
||||||
|
void assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual ~Font();
|
virtual ~Font();
|
||||||
|
|
||||||
void addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* glyph);
|
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<Glyph> > GlyphMap;
|
||||||
typedef std::map< unsigned int, osg::ref_ptr<Glyph3D> > Glyph3DMap;
|
typedef std::map< unsigned int, osg::ref_ptr<Glyph3D> > Glyph3DMap;
|
||||||
|
|
||||||
@ -185,8 +173,7 @@ protected:
|
|||||||
|
|
||||||
mutable OpenThreads::Mutex _glyphMapMutex;
|
mutable OpenThreads::Mutex _glyphMapMutex;
|
||||||
|
|
||||||
osg::ref_ptr<osg::TexEnv> _texenv;
|
StateSets _statesets;
|
||||||
osg::ref_ptr<osg::StateSet> _stateset;
|
|
||||||
FontSizeGlyphMap _sizeGlyphMap;
|
FontSizeGlyphMap _sizeGlyphMap;
|
||||||
GlyphTextureList _glyphTextureList;
|
GlyphTextureList _glyphTextureList;
|
||||||
|
|
||||||
@ -195,13 +182,12 @@ protected:
|
|||||||
|
|
||||||
// current active size of font
|
// current active size of font
|
||||||
FontResolution _fontSize;
|
FontResolution _fontSize;
|
||||||
unsigned int _margin;
|
|
||||||
float _marginRatio;
|
|
||||||
|
|
||||||
unsigned int _textureWidthHint;
|
unsigned int _textureWidthHint;
|
||||||
unsigned int _textureHeightHint;
|
unsigned int _textureHeightHint;
|
||||||
osg::Texture::FilterMode _minFilterHint;
|
osg::Texture::FilterMode _minFilterHint;
|
||||||
osg::Texture::FilterMode _magFilterHint;
|
osg::Texture::FilterMode _magFilterHint;
|
||||||
|
float _maxAnisotropy;
|
||||||
|
|
||||||
unsigned int _depth;
|
unsigned int _depth;
|
||||||
unsigned int _numCurveSamples;
|
unsigned int _numCurveSamples;
|
||||||
@ -247,8 +233,6 @@ public:
|
|||||||
virtual bool getVerticalSize(float & /*ascender*/, float & /*descender*/) const { return false; }
|
virtual bool getVerticalSize(float & /*ascender*/, float & /*descender*/) const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,15 +30,6 @@
|
|||||||
|
|
||||||
#include <OpenThreads/Mutex>
|
#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 {
|
namespace osgText {
|
||||||
|
|
||||||
class Font;
|
class Font;
|
||||||
@ -47,6 +38,14 @@ class Glyph3D;
|
|||||||
class GlyphGeometry;
|
class GlyphGeometry;
|
||||||
class GlyphTexture;
|
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
|
class OSGTEXT_EXPORT Glyph : public osg::Image
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -58,6 +57,9 @@ public:
|
|||||||
|
|
||||||
unsigned int getGlyphCode() const { return _glyphCode; }
|
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; }
|
void setWidth(float width) { _width = width; }
|
||||||
float getWidth() const { return _width; }
|
float getWidth() const { return _width; }
|
||||||
|
|
||||||
@ -76,21 +78,33 @@ public:
|
|||||||
void setVerticalAdvance(float advance);
|
void setVerticalAdvance(float advance);
|
||||||
float getVerticalAdvance() const;
|
float getVerticalAdvance() const;
|
||||||
|
|
||||||
void setTexture(GlyphTexture* texture);
|
struct TextureInfo : public osg::Referenced
|
||||||
GlyphTexture* getTexture();
|
{
|
||||||
const GlyphTexture* getTexture() const;
|
TextureInfo():
|
||||||
|
texture(0),
|
||||||
|
texelMargin(0.0f) {}
|
||||||
|
|
||||||
void setTexturePosition(int posX,int posY);
|
TextureInfo(GlyphTexture* tex, int x, int y, const osg::Vec2& mintc, const osg::Vec2& maxtc, float margin):
|
||||||
int getTexturePositionX() const;
|
texture(tex),
|
||||||
int getTexturePositionY() const;
|
texturePositionX(x),
|
||||||
|
texturePositionY(y),
|
||||||
|
minTexCoord(mintc),
|
||||||
|
maxTexCoord(maxtc),
|
||||||
|
texelMargin(margin) {}
|
||||||
|
|
||||||
void setMinTexCoord(const osg::Vec2& coord);
|
GlyphTexture* texture;
|
||||||
const osg::Vec2& getMinTexCoord() const;
|
int texturePositionX;
|
||||||
|
int texturePositionY;
|
||||||
|
osg::Vec2 minTexCoord;
|
||||||
|
osg::Vec2 maxTexCoord;
|
||||||
|
float texelMargin;
|
||||||
|
};
|
||||||
|
|
||||||
void setMaxTexCoord(const osg::Vec2& coord);
|
void setTextureInfo(ShaderTechnique technique, TextureInfo* info);
|
||||||
const osg::Vec2& getMaxTexCoord() const;
|
|
||||||
|
|
||||||
void subload() const;
|
const TextureInfo* getTextureInfo(ShaderTechnique technique) const;
|
||||||
|
|
||||||
|
TextureInfo* getOrCreateTextureInfo(ShaderTechnique technique);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -99,6 +113,8 @@ protected:
|
|||||||
Font* _font;
|
Font* _font;
|
||||||
unsigned int _glyphCode;
|
unsigned int _glyphCode;
|
||||||
|
|
||||||
|
FontResolution _fontResolution;
|
||||||
|
|
||||||
float _width;
|
float _width;
|
||||||
float _height;
|
float _height;
|
||||||
|
|
||||||
@ -108,15 +124,8 @@ protected:
|
|||||||
osg::Vec2 _verticalBearing;
|
osg::Vec2 _verticalBearing;
|
||||||
float _verticalAdvance;
|
float _verticalAdvance;
|
||||||
|
|
||||||
GlyphTexture* _texture;
|
typedef std::vector< osg::ref_ptr<TextureInfo> > TextureInfoList;
|
||||||
int _texturePosX;
|
TextureInfoList _textureInfoList;
|
||||||
int _texturePosY;
|
|
||||||
osg::Vec2 _minTexCoord;
|
|
||||||
osg::Vec2 _maxTexCoord;
|
|
||||||
|
|
||||||
typedef osg::buffered_value<GLuint> GLObjectList;
|
|
||||||
mutable GLObjectList _globjList;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class OSGTEXT_EXPORT GlyphGeometry : public osg::Referenced
|
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.*/
|
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
|
||||||
virtual int compare(const osg::StateAttribute& rhs) const;
|
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 setShaderTechnique(ShaderTechnique technique) { _shaderTechnique = technique; }
|
||||||
void setGlyphImageMargin(unsigned int margin) { _margin = margin; }
|
|
||||||
unsigned int getGlyphImageMargin() const { return _margin; }
|
|
||||||
|
|
||||||
void setGlyphImageMarginRatio(float margin) { _marginRatio = margin; }
|
ShaderTechnique getShaderTechnique() const { return _shaderTechnique; }
|
||||||
float getGlyphImageMarginRatio() const { return _marginRatio; }
|
|
||||||
|
|
||||||
|
int getEffectMargin(const Glyph* glyph);
|
||||||
|
int getTexelMargin(const Glyph* glyph);
|
||||||
|
|
||||||
bool getSpaceForGlyph(Glyph* glyph, int& posX, int& posY);
|
bool getSpaceForGlyph(Glyph* glyph, int& posX, int& posY);
|
||||||
|
|
||||||
@ -277,14 +287,13 @@ protected:
|
|||||||
|
|
||||||
virtual ~GlyphTexture();
|
virtual ~GlyphTexture();
|
||||||
|
|
||||||
|
void copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info);
|
||||||
|
|
||||||
// parameter used to compute the size and position of empty space
|
ShaderTechnique _shaderTechnique;
|
||||||
// in the texture which could accommodate new glyphs.
|
|
||||||
int _margin;
|
int _usedY;
|
||||||
float _marginRatio;
|
int _partUsedX;
|
||||||
int _usedY;
|
int _partUsedY;
|
||||||
int _partUsedX;
|
|
||||||
int _partUsedY;
|
|
||||||
|
|
||||||
typedef std::vector< osg::ref_ptr<Glyph> > GlyphRefList;
|
typedef std::vector< osg::ref_ptr<Glyph> > GlyphRefList;
|
||||||
typedef std::vector< const Glyph* > GlyphPtrList;
|
typedef std::vector< const Glyph* > GlyphPtrList;
|
||||||
|
@ -36,15 +36,12 @@ public:
|
|||||||
virtual const char* className() const { return "Text"; }
|
virtual const char* className() const { return "Text"; }
|
||||||
virtual const char* libraryName() const { return "osgText"; }
|
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.*/
|
/** Get the ShaderTechnique hint.*/
|
||||||
virtual void setFont(osg::ref_ptr<Font> font);
|
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
|
* Turns off writing to the depth buffer when rendering text. This only affects text
|
||||||
@ -70,31 +67,6 @@ public:
|
|||||||
NONE
|
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
|
* BackdropType gives you a background shadow text behind your regular
|
||||||
* text. This helps give text extra contrast which can be useful when
|
* text. This helps give text extra contrast which can be useful when
|
||||||
@ -149,18 +121,6 @@ public:
|
|||||||
|
|
||||||
const osg::Vec4& getBackdropColor() const { return _backdropColor; }
|
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
|
enum ColorGradientMode
|
||||||
{
|
{
|
||||||
SOLID = 0, // a.k.a. ColorGradients off
|
SOLID = 0, // a.k.a. ColorGradients off
|
||||||
@ -232,6 +192,20 @@ public:
|
|||||||
|
|
||||||
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.
|
// internal structures, variable and methods used for rendering of characters.
|
||||||
struct OSGTEXT_EXPORT GlyphQuads
|
struct OSGTEXT_EXPORT GlyphQuads
|
||||||
@ -239,7 +213,7 @@ public:
|
|||||||
typedef std::vector<Glyph*> Glyphs;
|
typedef std::vector<Glyph*> Glyphs;
|
||||||
|
|
||||||
Glyphs _glyphs;
|
Glyphs _glyphs;
|
||||||
Primitives _primitives;
|
osg::ref_ptr<osg::DrawElements> _primitives;
|
||||||
|
|
||||||
GlyphQuads();
|
GlyphQuads();
|
||||||
GlyphQuads(const GlyphQuads& gq);
|
GlyphQuads(const GlyphQuads& gq);
|
||||||
@ -284,6 +258,8 @@ protected:
|
|||||||
|
|
||||||
virtual ~Text();
|
virtual ~Text();
|
||||||
|
|
||||||
|
virtual osg::StateSet* createStateSet();
|
||||||
|
|
||||||
Font* getActiveFont();
|
Font* getActiveFont();
|
||||||
const Font* getActiveFont() const;
|
const Font* getActiveFont() const;
|
||||||
|
|
||||||
@ -302,7 +278,6 @@ protected:
|
|||||||
|
|
||||||
virtual void computePositionsImplementation();
|
virtual void computePositionsImplementation();
|
||||||
|
|
||||||
void computeBackdropPositions();
|
|
||||||
void computeBackdropBoundingBox();
|
void computeBackdropBoundingBox();
|
||||||
void computeBoundingBoxMargin();
|
void computeBoundingBoxMargin();
|
||||||
|
|
||||||
@ -314,10 +289,10 @@ protected:
|
|||||||
|
|
||||||
void drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const;
|
void drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const;
|
||||||
|
|
||||||
|
ShaderTechnique _shaderTechnique;
|
||||||
bool _enableDepthWrites;
|
bool _enableDepthWrites;
|
||||||
|
|
||||||
BackdropType _backdropType;
|
BackdropType _backdropType;
|
||||||
BackdropImplementation _backdropImplementation;
|
|
||||||
|
|
||||||
float _backdropHorizontalOffset;
|
float _backdropHorizontalOffset;
|
||||||
float _backdropVerticalOffset;
|
float _backdropVerticalOffset;
|
||||||
|
@ -53,6 +53,9 @@ public:
|
|||||||
virtual void setFont(const std::string& fontfile);
|
virtual void setFont(const std::string& fontfile);
|
||||||
|
|
||||||
/** Get the font. Return 0 if default is being used.*/
|
/** 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(); }
|
const Font* getFont() const { return _font.get(); }
|
||||||
|
|
||||||
|
|
||||||
@ -284,6 +287,10 @@ protected:
|
|||||||
|
|
||||||
virtual ~TextBase();
|
virtual ~TextBase();
|
||||||
|
|
||||||
|
virtual osg::StateSet* createStateSet();
|
||||||
|
|
||||||
|
virtual void assignStateSet();
|
||||||
|
|
||||||
void initArraysAndBuffers();
|
void initArraysAndBuffers();
|
||||||
|
|
||||||
osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo) const;
|
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::Drawable& drawable);
|
||||||
void apply(osg::StateSet& stateset);
|
void apply(osg::StateSet& stateset);
|
||||||
|
|
||||||
|
/** Do a compile traversal and then reset any state,*/
|
||||||
|
void compile(osg::Node& node);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::set<osg::Drawable*> DrawableAppliedSet;
|
typedef std::set<osg::Drawable*> DrawableAppliedSet;
|
||||||
|
@ -118,7 +118,8 @@ void DisplaySettings::setDisplaySettings(const DisplaySettings& vs)
|
|||||||
_swapMethod = vs._swapMethod;
|
_swapMethod = vs._swapMethod;
|
||||||
|
|
||||||
_vertexBufferHint = vs._vertexBufferHint;
|
_vertexBufferHint = vs._vertexBufferHint;
|
||||||
_shaderHint = vs._shaderHint;
|
|
||||||
|
setShaderHint(_shaderHint);
|
||||||
|
|
||||||
_keystoneHint = vs._keystoneHint;
|
_keystoneHint = vs._keystoneHint;
|
||||||
_keystoneFileNames = vs._keystoneFileNames;
|
_keystoneFileNames = vs._keystoneFileNames;
|
||||||
@ -250,23 +251,17 @@ void DisplaySettings::setDefaults()
|
|||||||
// _vertexBufferHint = VERTEX_ARRAY_OBJECT;
|
// _vertexBufferHint = VERTEX_ARRAY_OBJECT;
|
||||||
|
|
||||||
#if defined(OSG_GLES3_AVAILABLE)
|
#if defined(OSG_GLES3_AVAILABLE)
|
||||||
_shaderHint = SHADER_GLES3;
|
setShaderHint(SHADER_GLES3);
|
||||||
OSG_INFO<<"DisplaySettings::SHADER_GLES3"<<std::endl;
|
|
||||||
#elif defined(OSG_GLES2_AVAILABLE)
|
#elif defined(OSG_GLES2_AVAILABLE)
|
||||||
_shaderHint = SHADER_GLES2;
|
setShaderHint(SHADER_GLES2);
|
||||||
OSG_INFO<<"DisplaySettings::SHADER_GLES2"<<std::endl;
|
|
||||||
#elif defined(OSG_GL3_AVAILABLE)
|
#elif defined(OSG_GL3_AVAILABLE)
|
||||||
_shaderHint = SHADER_GL3;
|
setShaderHint(SHADER_GL3);
|
||||||
OSG_INFO<<"DisplaySettings::SHADER_GL3"<<std::endl;
|
|
||||||
#elif defined(OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE)
|
#elif defined(OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE)
|
||||||
OSG_INFO<<"DisplaySettings::SHADER_NONE"<<std::endl;
|
setShaderHint(SHADER_NONE);
|
||||||
_shaderHint = SHADER_NONE;
|
|
||||||
#else
|
#else
|
||||||
OSG_INFO<<"DisplaySettings::SHADER_GL2"<<std::endl;
|
setShaderHint(SHADER_GL2);
|
||||||
_shaderHint = SHADER_GL2;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
_keystoneHint = false;
|
_keystoneHint = false;
|
||||||
|
|
||||||
_OSXMenubarBehavior = MENUBAR_AUTO_HIDE;
|
_OSXMenubarBehavior = MENUBAR_AUTO_HIDE;
|
||||||
@ -390,6 +385,9 @@ static ApplicationUsageProxy DisplaySetting_e31(ApplicationUsage::ENVIRONMENTAL_
|
|||||||
static ApplicationUsageProxy DisplaySetting_e32(ApplicationUsage::ENVIRONMENTAL_VARIABLE,
|
static ApplicationUsageProxy DisplaySetting_e32(ApplicationUsage::ENVIRONMENTAL_VARIABLE,
|
||||||
"OSG_VERTEX_BUFFER_HINT <value>",
|
"OSG_VERTEX_BUFFER_HINT <value>",
|
||||||
"Set the hint to what backend osg::Geometry implementation to use. NO_PREFERENCE | VERTEX_BUFFER_OBJECT | VERTEX_ARRAY_OBJECT");
|
"Set the hint to what backend osg::Geometry implementation to use. NO_PREFERENCE | VERTEX_BUFFER_OBJECT | VERTEX_ARRAY_OBJECT");
|
||||||
|
static ApplicationUsageProxy DisplaySetting_e33(ApplicationUsage::ENVIRONMENTAL_VARIABLE,
|
||||||
|
"OSG_TEXT_SHADER_TECHNIQUE <value>",
|
||||||
|
"Set the defafult osgText::ShaderTechnique. ALL_FEATURES | ALL | GREYSCALE | SIGNED_DISTANCE_FIELD | SDF | NO_TEXT_SHADER | NONE");
|
||||||
|
|
||||||
void DisplaySettings::readEnvironmentalVariables()
|
void DisplaySettings::readEnvironmentalVariables()
|
||||||
{
|
{
|
||||||
@ -725,26 +723,30 @@ void DisplaySettings::readEnvironmentalVariables()
|
|||||||
{
|
{
|
||||||
if (strcmp(ptr,"GL2")==0)
|
if (strcmp(ptr,"GL2")==0)
|
||||||
{
|
{
|
||||||
_shaderHint = SHADER_GL2;
|
setShaderHint(SHADER_GL2);
|
||||||
}
|
}
|
||||||
else if (strcmp(ptr,"GL3")==0)
|
else if (strcmp(ptr,"GL3")==0)
|
||||||
{
|
{
|
||||||
_shaderHint = SHADER_GL3;
|
setShaderHint(SHADER_GL3);
|
||||||
}
|
}
|
||||||
else if (strcmp(ptr,"GLES2")==0)
|
else if (strcmp(ptr,"GLES2")==0)
|
||||||
{
|
{
|
||||||
_shaderHint = SHADER_GLES2;
|
setShaderHint(SHADER_GLES2);
|
||||||
}
|
}
|
||||||
else if (strcmp(ptr,"GLES3")==0)
|
else if (strcmp(ptr,"GLES3")==0)
|
||||||
{
|
{
|
||||||
_shaderHint = SHADER_GLES3;
|
setShaderHint(SHADER_GLES3);
|
||||||
}
|
}
|
||||||
else if (strcmp(ptr,"NONE")==0)
|
else if (strcmp(ptr,"NONE")==0)
|
||||||
{
|
{
|
||||||
_shaderHint = SHADER_NONE;
|
setShaderHint(SHADER_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ptr = getenv("OSG_TEXT_SHADER_TECHNIQUE")) != 0)
|
||||||
|
{
|
||||||
|
setTextShaderTechnique(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
if( (ptr = getenv("OSG_KEYSTONE")) != 0)
|
if( (ptr = getenv("OSG_KEYSTONE")) != 0)
|
||||||
{
|
{
|
||||||
@ -1098,3 +1100,84 @@ osg::Matrixd DisplaySettings::computeRightEyeViewImplementation(const osg::Matri
|
|||||||
0.0,0.0,1.0,0.0,
|
0.0,0.0,1.0,0.0,
|
||||||
-es,0.0,0.0,1.0);
|
-es,0.0,0.0,1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplaySettings::setShaderHint(ShaderHint hint, bool setShaderValues)
|
||||||
|
{
|
||||||
|
_shaderHint = hint;
|
||||||
|
if (setShaderValues)
|
||||||
|
{
|
||||||
|
switch(_shaderHint)
|
||||||
|
{
|
||||||
|
case(SHADER_GLES3) :
|
||||||
|
setValue("OSG_GLSL_VERSION", "#version 300 es");
|
||||||
|
setValue("OSG_PRECISION_FLOAT", "precision highp float;");
|
||||||
|
setValue("OSG_VARYING_IN", "in");
|
||||||
|
setValue("OSG_VARYING_OUT", "out");
|
||||||
|
OSG_NOTICE<<"DisplaySettings::SHADER_GLES3"<<std::endl;
|
||||||
|
break;
|
||||||
|
case(SHADER_GLES2) :
|
||||||
|
setValue("OSG_GLSL_VERSION", "");
|
||||||
|
setValue("OSG_PRECISION_FLOAT", "precision highp float;");
|
||||||
|
setValue("OSG_VARYING_IN", "varying");
|
||||||
|
setValue("OSG_VARYING_OUT", "varying");
|
||||||
|
OSG_NOTICE<<"DisplaySettings::SHADER_GLES2"<<std::endl;
|
||||||
|
break;
|
||||||
|
case(SHADER_GL3) :
|
||||||
|
setValue("OSG_GLSL_VERSION", "#version 330");
|
||||||
|
setValue("OSG_PRECISION_FLOAT", "");
|
||||||
|
setValue("OSG_VARYING_IN", "in");
|
||||||
|
setValue("OSG_VARYING_OUT", "out");
|
||||||
|
OSG_NOTICE<<"DisplaySettings::SHADER_GL3"<<std::endl;
|
||||||
|
break;
|
||||||
|
case(SHADER_GL2) :
|
||||||
|
setValue("OSG_GLSL_VERSION", "");
|
||||||
|
setValue("OSG_PRECISION_FLOAT", "");
|
||||||
|
setValue("OSG_VARYING_IN", "varying");
|
||||||
|
setValue("OSG_VARYING_OUT", "varying");
|
||||||
|
OSG_NOTICE<<"DisplaySettings::SHADER_GL2"<<std::endl;
|
||||||
|
break;
|
||||||
|
case(SHADER_NONE) :
|
||||||
|
setValue("OSG_GLSL_VERSION", "");
|
||||||
|
setValue("OSG_PRECISION_FLOAT", "");
|
||||||
|
setValue("OSG_VARYING_IN", "varying");
|
||||||
|
setValue("OSG_VARYING_OUT", "varying");
|
||||||
|
OSG_NOTICE<<"DisplaySettings::NONE"<<std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplaySettings::setValue(const std::string& name, const std::string& value)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_valueMapMutex);
|
||||||
|
|
||||||
|
_valueMap[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DisplaySettings::getValue(const std::string& name, std::string& value, bool use_getenv_fallback) const
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_valueMapMutex);
|
||||||
|
|
||||||
|
ValueMap::iterator itr = _valueMap.find(name);
|
||||||
|
if (itr!=_valueMap.end())
|
||||||
|
{
|
||||||
|
value = itr->second;
|
||||||
|
OSG_INFO<<"DisplaySettings::getValue("<<name<<") found existing value = ["<<value<<"]"<<std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!use_getenv_fallback) return false;
|
||||||
|
|
||||||
|
const char* str = getenv(name.c_str());
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
OSG_INFO<<"DisplaySettings::getValue("<<name<<") found getenv value = ["<<value<<"]"<<std::endl;
|
||||||
|
_valueMap[name] = value = str;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -631,27 +631,27 @@ void Shader::PerContextShader::compileShader(osg::State& state)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string source = _shader->getShaderSource();
|
std::string source = _shader->getShaderSource();
|
||||||
if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms()))
|
// if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms()))
|
||||||
{
|
{
|
||||||
state.convertVertexShaderSourceToOsgBuiltIns(source);
|
state.convertVertexShaderSourceToOsgBuiltIns(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (osg::getNotifyLevel()>=osg::INFO)
|
|
||||||
{
|
|
||||||
std::string sourceWithLineNumbers = insertLineNumbers(source);
|
|
||||||
OSG_INFO << "\nCompiling " << _shader->getTypename()
|
|
||||||
<< " source:\n" << sourceWithLineNumbers << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLint compiled = GL_FALSE;
|
GLint compiled = GL_FALSE;
|
||||||
|
|
||||||
// OSG_NOTICE<<"Compiling PerContextShader "<<this<<" ShaderDefine="<<getDefineString()<<std::endl;
|
// OSG_NOTICE<<"Compiling PerContextShader "<<this<<" DefineString="<<getDefineString()<<std::endl;
|
||||||
|
|
||||||
if (_defineStr.empty())
|
if (_defineStr.empty())
|
||||||
{
|
{
|
||||||
const GLchar* sourceText = reinterpret_cast<const GLchar*>(source.c_str());
|
const GLchar* sourceText = reinterpret_cast<const GLchar*>(source.c_str());
|
||||||
_extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL );
|
_extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL );
|
||||||
|
|
||||||
|
if (osg::getNotifyLevel()>=osg::INFO)
|
||||||
|
{
|
||||||
|
std::string sourceWithLineNumbers = insertLineNumbers(source);
|
||||||
|
OSG_INFO << "\nCompiling A :" << _shader->getTypename()
|
||||||
|
<< " source:\n" << sourceWithLineNumbers << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -690,21 +690,40 @@ void Shader::PerContextShader::compileShader(osg::State& state)
|
|||||||
|
|
||||||
if (!versionLine.empty())
|
if (!versionLine.empty())
|
||||||
{
|
{
|
||||||
// OSG_NOTICE<<"Shader::PerContextShader::compileShader() : Found #version, lineNum = "<<lineNum<<" ["<<versionLine<<"] new source = ["<<source<<"]"<<std::endl;
|
|
||||||
const GLchar* sourceText[3];
|
const GLchar* sourceText[3];
|
||||||
//OSG_NOTICE<<"glShaderSource() ["<<versionLine<<"] "<<std::endl<<"["<<_defineStr<<"], ["<<sourceText<<"]"<<std::endl;
|
|
||||||
sourceText[0] = reinterpret_cast<const GLchar*>(versionLine.c_str());
|
sourceText[0] = reinterpret_cast<const GLchar*>(versionLine.c_str());
|
||||||
sourceText[1] = reinterpret_cast<const GLchar*>(_defineStr.c_str());
|
sourceText[1] = reinterpret_cast<const GLchar*>(_defineStr.c_str());
|
||||||
sourceText[2] = reinterpret_cast<const GLchar*>(source.c_str());
|
sourceText[2] = reinterpret_cast<const GLchar*>(source.c_str());
|
||||||
_extensions->glShaderSource( _glShaderHandle, 3, sourceText, NULL );
|
_extensions->glShaderSource( _glShaderHandle, 3, sourceText, NULL );
|
||||||
|
|
||||||
|
if (osg::getNotifyLevel()>=osg::INFO)
|
||||||
|
{
|
||||||
|
std::string sourceWithLineNumbers = insertLineNumbers(versionLine+_defineStr+source);
|
||||||
|
OSG_INFO << "\nCompiling B: " << _shader->getTypename()
|
||||||
|
<< " source:\n" << sourceWithLineNumbers << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSG_NOTICE<<" Version Line : ["<<std::endl<<versionLine<<"]"<<std::endl;
|
||||||
|
// OSG_NOTICE<<" DefineStr : ["<<std::endl<<_defineStr<<"]"<<std::endl;
|
||||||
|
// OSG_NOTICE<<" Source : ["<<std::endl<<source<<"]"<<std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const GLchar* sourceText[2];
|
const GLchar* sourceText[2];
|
||||||
//OSG_NOTICE<<"glShaderSource() ["<<_defineStr<<"], ["<<sourceText<<"]"<<std::endl;
|
|
||||||
sourceText[0] = reinterpret_cast<const GLchar*>(_defineStr.c_str());
|
sourceText[0] = reinterpret_cast<const GLchar*>(_defineStr.c_str());
|
||||||
sourceText[1] = reinterpret_cast<const GLchar*>(source.c_str());
|
sourceText[1] = reinterpret_cast<const GLchar*>(source.c_str());
|
||||||
_extensions->glShaderSource( _glShaderHandle, 2, sourceText, NULL );
|
_extensions->glShaderSource( _glShaderHandle, 2, sourceText, NULL );
|
||||||
|
|
||||||
|
|
||||||
|
if (osg::getNotifyLevel()>=osg::INFO)
|
||||||
|
{
|
||||||
|
std::string sourceWithLineNumbers = insertLineNumbers(_defineStr+source);
|
||||||
|
OSG_INFO << "\nCompiling C: " << _shader->getTypename()
|
||||||
|
<< " source:\n" << sourceWithLineNumbers << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSG_NOTICE<<" DefineStr : ["<<std::endl<<_defineStr<<"]"<<std::endl;
|
||||||
|
// OSG_NOTICE<<" Source : ["<<std::endl<<source<<"]"<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_extensions->glCompileShader( _glShaderHandle );
|
_extensions->glCompileShader( _glShaderHandle );
|
||||||
|
@ -1216,13 +1216,69 @@ namespace State_Utils
|
|||||||
source.insert(declPos, qualifier + declarationPrefix + newStr + std::string(";\n"));
|
source.insert(declPos, qualifier + declarationPrefix + newStr + std::string(";\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void replaceVar(const osg::State& state, std::string& str, std::string::size_type start_pos, std::string::size_type num_chars)
|
||||||
|
{
|
||||||
|
std::string var_str(str.substr(start_pos+1, num_chars-1));
|
||||||
|
std::string value;
|
||||||
|
if (state.getActiveDisplaySettings()->getValue(var_str, value))
|
||||||
|
{
|
||||||
|
str.replace(start_pos, num_chars, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str.erase(start_pos, num_chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void substitudeEnvVars(const osg::State& state, std::string& str)
|
||||||
|
{
|
||||||
|
std::string::size_type pos = 0;
|
||||||
|
while (pos<str.size() && ((pos=str.find_first_of("$'\"", pos)) != std::string::npos))
|
||||||
|
{
|
||||||
|
if (pos==str.size())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str[pos]=='"' || str[pos]=='\'')
|
||||||
|
{
|
||||||
|
std::string::size_type start_quote = pos;
|
||||||
|
++pos;
|
||||||
|
pos = str.find(str[start_quote], pos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string::size_type start_var = pos;
|
||||||
|
++pos;
|
||||||
|
pos = str.find_first_not_of("ABCDEFGHIJKLMNOPQRTSUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", pos);
|
||||||
|
std::string var_str;
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
|
||||||
|
replaceVar(state, str, start_var, pos-start_var);
|
||||||
|
pos = start_var;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
replaceVar(state, str, start_var, str.size()-start_var);
|
||||||
|
pos = start_var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
|
bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
|
||||||
{
|
{
|
||||||
OSG_INFO<<"State::convertShaderSourceToOsgBuiltIns()"<<std::endl;
|
OSG_DEBUG<<"State::convertShaderSourceToOsgBuiltIns()"<<std::endl;
|
||||||
|
|
||||||
|
OSG_DEBUG<<"++Before Converted source "<<std::endl<<source<<std::endl<<"++++++++"<<std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
State_Utils::substitudeEnvVars(*this, source);
|
||||||
|
|
||||||
OSG_INFO<<"++Before Converted source "<<std::endl<<source<<std::endl<<"++++++++"<<std::endl;
|
|
||||||
|
|
||||||
std::string attributeQualifier("attribute ");
|
std::string attributeQualifier("attribute ");
|
||||||
|
|
||||||
@ -1279,7 +1335,7 @@ bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OSG_INFO<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
|
OSG_DEBUG<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -278,19 +278,6 @@ void FreeTypeFont::setFontResolution(const osgText::FontResolution& fontSize)
|
|||||||
|
|
||||||
int width = fontSize.first;
|
int width = fontSize.first;
|
||||||
int height = fontSize.second;
|
int height = fontSize.second;
|
||||||
int maxAxis = std::max(width, height);
|
|
||||||
int margin = _facade->getGlyphImageMargin() + (int)((float)maxAxis * _facade->getGlyphImageMarginRatio());
|
|
||||||
|
|
||||||
if ((unsigned int)(width+2*margin) > _facade->getTextureWidthHint() ||
|
|
||||||
(unsigned int)(width+2*margin) > _facade->getTextureHeightHint())
|
|
||||||
{
|
|
||||||
OSG_WARN<<"Warning: FreeTypeFont::setSize("<<width<<","<<height<<") sizes too large,"<<std::endl;
|
|
||||||
|
|
||||||
width = _facade->getTextureWidthHint()-2*margin;
|
|
||||||
height = _facade->getTextureHeightHint()-2*margin;
|
|
||||||
|
|
||||||
OSG_WARN<<" sizes capped ("<<width<<","<<height<<") to fit int current glyph texture size."<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Error error = FT_Set_Pixel_Sizes( _face, /* handle to face object */
|
FT_Error error = FT_Set_Pixel_Sizes( _face, /* handle to face object */
|
||||||
width, /* pixel_width */
|
width, /* pixel_width */
|
||||||
@ -351,6 +338,8 @@ osgText::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, u
|
|||||||
|
|
||||||
osg::ref_ptr<osgText::Glyph> glyph = new osgText::Glyph(_facade, charcode);
|
osg::ref_ptr<osgText::Glyph> glyph = new osgText::Glyph(_facade, charcode);
|
||||||
|
|
||||||
|
glyph->setFontResolution(fontRes);
|
||||||
|
|
||||||
unsigned int dataSize = width*height;
|
unsigned int dataSize = width*height;
|
||||||
unsigned char* data = new unsigned char[dataSize];
|
unsigned char* data = new unsigned char[dataSize];
|
||||||
|
|
||||||
@ -359,14 +348,12 @@ osgText::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, u
|
|||||||
for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; }
|
for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; }
|
||||||
|
|
||||||
glyph->setImage(width,height,1,
|
glyph->setImage(width,height,1,
|
||||||
OSGTEXT_GLYPH_INTERNALFORMAT,
|
GL_ALPHA,
|
||||||
OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE,
|
GL_ALPHA, GL_UNSIGNED_BYTE,
|
||||||
data,
|
data,
|
||||||
osg::Image::USE_NEW_DELETE,
|
osg::Image::USE_NEW_DELETE,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT);
|
|
||||||
|
|
||||||
// copy image across to osgText::Glyph image.
|
// copy image across to osgText::Glyph image.
|
||||||
switch(glyphslot->bitmap.pixel_mode)
|
switch(glyphslot->bitmap.pixel_mode)
|
||||||
{
|
{
|
||||||
|
@ -90,7 +90,7 @@ void Text::write(DataOutputStream* out){
|
|||||||
out->writeFloat(getBackdropVerticalOffset());
|
out->writeFloat(getBackdropVerticalOffset());
|
||||||
|
|
||||||
out->writeVec4(getBackdropColor());
|
out->writeVec4(getBackdropColor());
|
||||||
out->writeUInt(getBackdropImplementation());
|
out->writeUInt(4); // old DELAYED_DEPTH_WRITES
|
||||||
|
|
||||||
out->writeUInt(getColorGradientMode());
|
out->writeUInt(getColorGradientMode());
|
||||||
out->writeVec4(getColorGradientTopLeft());
|
out->writeVec4(getColorGradientTopLeft());
|
||||||
@ -213,7 +213,7 @@ void Text::read(DataInputStream* in){
|
|||||||
setBackdropOffset(horizontalOffset,verticalOffset);
|
setBackdropOffset(horizontalOffset,verticalOffset);
|
||||||
|
|
||||||
setBackdropColor(in->readVec4());
|
setBackdropColor(in->readVec4());
|
||||||
setBackdropImplementation((osgText::Text::BackdropImplementation) in->readUInt());
|
in->readUInt(); // read old BackdropImplementation value, no longer used
|
||||||
setColorGradientMode((osgText::Text::ColorGradientMode) in->readUInt());
|
setColorGradientMode((osgText::Text::ColorGradientMode) in->readUInt());
|
||||||
|
|
||||||
osg::Vec4 colorGradientTopLeft,colorGradientBottomLeft,colorGradientBottomRight,colorGradientTopRight;
|
osg::Vec4 colorGradientTopLeft,colorGradientBottomLeft,colorGradientBottomRight,colorGradientTopRight;
|
||||||
|
@ -24,8 +24,11 @@ using namespace osgText;
|
|||||||
|
|
||||||
DefaultFont::DefaultFont()
|
DefaultFont::DefaultFont()
|
||||||
{
|
{
|
||||||
|
_fontSize = FontResolution(8,12);
|
||||||
|
|
||||||
_minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR;
|
_minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR;
|
||||||
_magFilterHint = osg::Texture::NEAREST;
|
_magFilterHint = osg::Texture::LINEAR;
|
||||||
|
|
||||||
constructGlyphs();
|
constructGlyphs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,14 +201,12 @@ void DefaultFont::constructGlyphs()
|
|||||||
for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; }
|
for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; }
|
||||||
|
|
||||||
glyph->setImage(sourceWidth,sourceHeight,1,
|
glyph->setImage(sourceWidth,sourceHeight,1,
|
||||||
OSGTEXT_GLYPH_INTERNALFORMAT,
|
GL_ALPHA,
|
||||||
OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE,
|
GL_ALPHA, GL_UNSIGNED_BYTE,
|
||||||
data,
|
data,
|
||||||
osg::Image::USE_NEW_DELETE,
|
osg::Image::USE_NEW_DELETE,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT);
|
|
||||||
|
|
||||||
// now populate data array by converting bitmap into a luminance_alpha map.
|
// now populate data array by converting bitmap into a luminance_alpha map.
|
||||||
unsigned char* ptr = rasters[i-32];
|
unsigned char* ptr = rasters[i-32];
|
||||||
unsigned char value_on = 255;
|
unsigned char value_on = 255;
|
||||||
@ -233,6 +234,8 @@ void DefaultFont::constructGlyphs()
|
|||||||
glyph->setVerticalBearing(osg::Vec2(0.5f,1.0f)); // top middle.
|
glyph->setVerticalBearing(osg::Vec2(0.5f,1.0f)); // top middle.
|
||||||
glyph->setVerticalAdvance(sourceHeight*coord_scale);
|
glyph->setVerticalAdvance(sourceHeight*coord_scale);
|
||||||
|
|
||||||
|
glyph->setFontResolution(fontRes);
|
||||||
|
|
||||||
addGlyph(fontRes,i,glyph.get());
|
addGlyph(fontRes,i,glyph.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,81 +32,6 @@
|
|||||||
using namespace osgText;
|
using namespace osgText;
|
||||||
using namespace std;
|
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>& Font::getDefaultFont()
|
osg::ref_ptr<Font>& Font::getDefaultFont()
|
||||||
{
|
{
|
||||||
static OpenThreads::Mutex s_DefaultFontMutex;
|
static OpenThreads::Mutex s_DefaultFontMutex;
|
||||||
@ -299,67 +224,24 @@ osg::ref_ptr<Font> osgText::readRefFontStream(std::istream& stream, const osgDB:
|
|||||||
|
|
||||||
Font::Font(FontImplementation* implementation):
|
Font::Font(FontImplementation* implementation):
|
||||||
osg::Object(true),
|
osg::Object(true),
|
||||||
_margin(1),
|
|
||||||
_marginRatio(0.02),
|
|
||||||
_textureWidthHint(1024),
|
_textureWidthHint(1024),
|
||||||
_textureHeightHint(1024),
|
_textureHeightHint(1024),
|
||||||
_minFilterHint(osg::Texture::LINEAR_MIPMAP_LINEAR),
|
_minFilterHint(osg::Texture::LINEAR_MIPMAP_LINEAR),
|
||||||
_magFilterHint(osg::Texture::LINEAR),
|
_magFilterHint(osg::Texture::LINEAR),
|
||||||
|
_maxAnisotropy(16),
|
||||||
_depth(1),
|
_depth(1),
|
||||||
_numCurveSamples(10)
|
_numCurveSamples(10)
|
||||||
{
|
{
|
||||||
setImplementation(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"<<std::endl;
|
|
||||||
|
|
||||||
_stateset->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"<<std::endl;
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Program> 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"<<std::endl;
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Program> 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;
|
char *ptr;
|
||||||
if( (ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0)
|
if ((ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0)
|
||||||
{
|
{
|
||||||
unsigned int osg_max_size = atoi(ptr);
|
unsigned int osg_max_size = atoi(ptr);
|
||||||
|
|
||||||
if (osg_max_size<_textureWidthHint) _textureWidthHint = osg_max_size;
|
if (osg_max_size<_textureWidthHint) _textureWidthHint = osg_max_size;
|
||||||
if (osg_max_size<_textureHeightHint) _textureHeightHint = osg_max_size;
|
if (osg_max_size<_textureHeightHint) _textureHeightHint = osg_max_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::~Font()
|
Font::~Font()
|
||||||
@ -390,26 +272,6 @@ std::string Font::getFileName() const
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::setGlyphImageMargin(unsigned int margin)
|
|
||||||
{
|
|
||||||
_margin = margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Font::getGlyphImageMargin() const
|
|
||||||
{
|
|
||||||
return _margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Font::setGlyphImageMarginRatio(float ratio)
|
|
||||||
{
|
|
||||||
_marginRatio = ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Font::getGlyphImageMarginRatio() const
|
|
||||||
{
|
|
||||||
return _marginRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Font::setTextureSizeHint(unsigned int width,unsigned int height)
|
void Font::setTextureSizeHint(unsigned int width,unsigned int height)
|
||||||
{
|
{
|
||||||
_textureWidthHint = width;
|
_textureWidthHint = width;
|
||||||
@ -518,9 +380,6 @@ void Font::setThreadSafeRefUnref(bool threadSafe)
|
|||||||
{
|
{
|
||||||
osg::Object::setThreadSafeRefUnref(threadSafe);
|
osg::Object::setThreadSafeRefUnref(threadSafe);
|
||||||
|
|
||||||
if (_texenv.valid()) _texenv->setThreadSafeRefUnref(threadSafe);
|
|
||||||
if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe);
|
|
||||||
|
|
||||||
for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin();
|
for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin();
|
||||||
itr!=_glyphTextureList.end();
|
itr!=_glyphTextureList.end();
|
||||||
++itr)
|
++itr)
|
||||||
@ -531,7 +390,12 @@ void Font::setThreadSafeRefUnref(bool threadSafe)
|
|||||||
|
|
||||||
void Font::resizeGLObjectBuffers(unsigned int maxSize)
|
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();
|
for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin();
|
||||||
itr!=_glyphTextureList.end();
|
itr!=_glyphTextureList.end();
|
||||||
@ -543,7 +407,12 @@ void Font::resizeGLObjectBuffers(unsigned int maxSize)
|
|||||||
|
|
||||||
void Font::releaseGLObjects(osg::State* state) const
|
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();
|
for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin();
|
||||||
itr!=_glyphTextureList.end();
|
itr!=_glyphTextureList.end();
|
||||||
@ -576,6 +445,10 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph*
|
|||||||
|
|
||||||
_sizeGlyphMap[fontRes][charcode]=glyph;
|
_sizeGlyphMap[fontRes][charcode]=glyph;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique)
|
||||||
|
{
|
||||||
int posX=0,posY=0;
|
int posX=0,posY=0;
|
||||||
|
|
||||||
GlyphTexture* glyphTexture = 0;
|
GlyphTexture* glyphTexture = 0;
|
||||||
@ -583,12 +456,12 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph*
|
|||||||
itr!=_glyphTextureList.end() && !glyphTexture;
|
itr!=_glyphTextureList.end() && !glyphTexture;
|
||||||
++itr)
|
++itr)
|
||||||
{
|
{
|
||||||
if ((*itr)->getSpaceForGlyph(glyph,posX,posY)) glyphTexture = itr->get();
|
if ((*itr)->getShaderTechnique()==shaderTechnique && (*itr)->getSpaceForGlyph(glyph,posX,posY)) glyphTexture = itr->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glyphTexture)
|
if (glyphTexture)
|
||||||
{
|
{
|
||||||
//cout << " found space for texture "<<glyphTexture<<" posX="<<posX<<" posY="<<posY<<endl;
|
//cout << " Font::assignGlyphToGlyphTexture() found space for texture "<<glyphTexture<<" posX="<<posX<<" posY="<<posY<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!glyphTexture)
|
if (!glyphTexture)
|
||||||
@ -602,12 +475,11 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph*
|
|||||||
OSG_INFO<< " Font " << this<< ", numberOfTexturesAllocated "<<numberOfTexturesAllocated<<std::endl;
|
OSG_INFO<< " Font " << this<< ", numberOfTexturesAllocated "<<numberOfTexturesAllocated<<std::endl;
|
||||||
|
|
||||||
// reserve enough space for the glyphs.
|
// reserve enough space for the glyphs.
|
||||||
glyphTexture->setGlyphImageMargin(_margin);
|
glyphTexture->setShaderTechnique(shaderTechnique);
|
||||||
glyphTexture->setGlyphImageMarginRatio(_marginRatio);
|
|
||||||
glyphTexture->setTextureSize(_textureWidthHint,_textureHeightHint);
|
glyphTexture->setTextureSize(_textureWidthHint,_textureHeightHint);
|
||||||
glyphTexture->setFilter(osg::Texture::MIN_FILTER,_minFilterHint);
|
glyphTexture->setFilter(osg::Texture::MIN_FILTER,_minFilterHint);
|
||||||
glyphTexture->setFilter(osg::Texture::MAG_FILTER,_magFilterHint);
|
glyphTexture->setFilter(osg::Texture::MAG_FILTER,_magFilterHint);
|
||||||
glyphTexture->setMaxAnisotropy(8);
|
glyphTexture->setMaxAnisotropy(_maxAnisotropy);
|
||||||
|
|
||||||
_glyphTextureList.push_back(glyphTexture);
|
_glyphTextureList.push_back(glyphTexture);
|
||||||
|
|
||||||
@ -621,5 +493,4 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph*
|
|||||||
|
|
||||||
// add the glyph into the texture.
|
// add the glyph into the texture.
|
||||||
glyphTexture->addGlyph(glyph,posX,posY);
|
glyphTexture->addGlyph(glyph,posX,posY);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,34 @@
|
|||||||
using namespace osgText;
|
using namespace osgText;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
// GL_ALPHA and GL_LUMINANCE_ALPHA are deprecated in GL3/GL4 core profile, use GL_RED & GL_RB in this case.
|
||||||
|
#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE)
|
||||||
|
#define OSGTEXT_GLYPH_ALPHA_FORMAT GL_RED
|
||||||
|
#define OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT GL_R8
|
||||||
|
#define OSGTEXT_GLYPH_SDF_FORMAT GL_RG
|
||||||
|
#define OSGTEXT_GLYPH_SDF_INTERNALFORMAT GL_RG8
|
||||||
|
#else
|
||||||
|
#define OSGTEXT_GLYPH_ALPHA_FORMAT GL_ALPHA
|
||||||
|
#define OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT GL_ALPHA
|
||||||
|
#define OSGTEXT_GLYPH_SDF_FORMAT GL_LUMINANCE_ALPHA
|
||||||
|
#define OSGTEXT_GLYPH_SDF_INTERNALFORMAT GL_LUMINANCE_ALPHA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define TEXTURE_IMAGE_NUM_CHANNELS 1
|
||||||
|
#define TEXTURE_IMAGE_FORMAT OSGTEXT_GLYPH_FORMAT
|
||||||
|
#else
|
||||||
|
#define TEXTURE_IMAGE_NUM_CHANNELS 2
|
||||||
|
#define TEXTURE_IMAGE_FORMAT GL_RGBA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// GlyphTexture
|
||||||
|
//
|
||||||
GlyphTexture::GlyphTexture():
|
GlyphTexture::GlyphTexture():
|
||||||
_margin(1),
|
|
||||||
_marginRatio(0.02f),
|
|
||||||
_usedY(0),
|
_usedY(0),
|
||||||
_partUsedX(0),
|
_partUsedX(0),
|
||||||
_partUsedY(0)
|
_partUsedY(0)
|
||||||
@ -51,27 +76,52 @@ int GlyphTexture::compare(const osg::StateAttribute& rhs) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GlyphTexture::getEffectMargin(const Glyph* glyph)
|
||||||
|
{
|
||||||
|
if (_shaderTechnique==GREYSCALE) return 0;
|
||||||
|
else return osg::maximum(glyph->getFontResolution().second/6, 2u);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GlyphTexture::getTexelMargin(const Glyph* glyph)
|
||||||
|
{
|
||||||
|
int width = glyph->s();
|
||||||
|
int height = glyph->t();
|
||||||
|
int effect_margin = getEffectMargin(glyph);
|
||||||
|
|
||||||
|
int max_dimension = std::max(width, height) + 2 * effect_margin;
|
||||||
|
int margin = osg::maximum(max_dimension/4, 2) + effect_margin;
|
||||||
|
|
||||||
|
return margin;
|
||||||
|
}
|
||||||
|
|
||||||
bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY)
|
bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY)
|
||||||
{
|
{
|
||||||
int maxAxis = osg::maximum(glyph->s(), glyph->t());
|
int width = glyph->s();
|
||||||
int margin = _margin + (int)((float)maxAxis * _marginRatio);
|
int height = glyph->t();
|
||||||
|
|
||||||
int width = glyph->s()+2*margin;
|
int margin = getTexelMargin(glyph);
|
||||||
int height = glyph->t()+2*margin;
|
|
||||||
|
|
||||||
// first check box (_partUsedX,_usedY) to (width,height)
|
width += 2*margin;
|
||||||
if (width <= (getTextureWidth()-_partUsedX) &&
|
height += 2*margin;
|
||||||
height <= (getTextureHeight()-_usedY))
|
|
||||||
|
int interval = 4;
|
||||||
|
|
||||||
|
int partUsedX = ((_partUsedX % interval) == 0) ? _partUsedX : (((_partUsedX/interval)+1)*interval);
|
||||||
|
int partUsedY = ((_partUsedY % interval) == 0) ? _partUsedY : (((_partUsedY/interval)+1)*interval);
|
||||||
|
int usedY = ((_usedY % interval) == 0) ? _usedY : (((_usedY/interval)+1)*interval);
|
||||||
|
|
||||||
|
// first check box (partUsedX, usedY) to (width,height)
|
||||||
|
if (width <= (getTextureWidth()-partUsedX) &&
|
||||||
|
height <= (getTextureHeight()-usedY))
|
||||||
{
|
{
|
||||||
// can fit in existing row.
|
// can fit in existing row.
|
||||||
|
|
||||||
// record the position in which the texture will be stored.
|
// record the position in which the texture will be stored.
|
||||||
posX = _partUsedX+margin;
|
posX = partUsedX+margin;
|
||||||
posY = _usedY+margin;
|
posY = usedY+margin;
|
||||||
|
|
||||||
// move used markers on.
|
// move used markers on.
|
||||||
_partUsedX += width;
|
_partUsedX = posX+width;
|
||||||
if (_usedY+height>_partUsedY) _partUsedY = _usedY+height;
|
if (_usedY+height>_partUsedY) _partUsedY = _usedY+height;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -83,14 +133,14 @@ bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY)
|
|||||||
{
|
{
|
||||||
// can fit next row.
|
// can fit next row.
|
||||||
_partUsedX = 0;
|
_partUsedX = 0;
|
||||||
_usedY = _partUsedY;
|
_usedY = partUsedY;
|
||||||
|
|
||||||
posX = _partUsedX+margin;
|
posX = _partUsedX+margin;
|
||||||
posY = _usedY+margin;
|
posY = _usedY+margin;
|
||||||
|
|
||||||
// move used markers on.
|
// move used markers on.
|
||||||
_partUsedX += width;
|
_partUsedX = posX+width;
|
||||||
if (_usedY+height>_partUsedY) _partUsedY = _usedY+height;
|
_partUsedY = _usedY+height;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -101,23 +151,237 @@ bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY)
|
|||||||
|
|
||||||
void GlyphTexture::addGlyph(Glyph* glyph, int posX, int posY)
|
void GlyphTexture::addGlyph(Glyph* glyph, int posX, int posY)
|
||||||
{
|
{
|
||||||
|
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||||
|
|
||||||
if (!_image.valid()) createImage();
|
if (!_image.valid()) createImage();
|
||||||
|
|
||||||
_glyphs.push_back(glyph);
|
_glyphs.push_back(glyph);
|
||||||
|
|
||||||
// set up the details of where to place glyph's image in the texture.
|
osg::ref_ptr<Glyph::TextureInfo> info = new Glyph::TextureInfo(
|
||||||
glyph->setTexture(this);
|
this,
|
||||||
glyph->setTexturePosition(posX,posY);
|
posX, posY,
|
||||||
|
osg::Vec2( static_cast<float>(posX)/static_cast<float>(getTextureWidth()), static_cast<float>(posY)/static_cast<float>(getTextureHeight()) ), // minTexCoord
|
||||||
|
osg::Vec2( static_cast<float>(posX+glyph->s())/static_cast<float>(getTextureWidth()), static_cast<float>(posY+glyph->t())/static_cast<float>(getTextureHeight()) ), // maxTexCoord
|
||||||
|
float(getTexelMargin(glyph))); // margin
|
||||||
|
|
||||||
glyph->setMinTexCoord( osg::Vec2( static_cast<float>(posX)/static_cast<float>(getTextureWidth()),
|
glyph->setTextureInfo(_shaderTechnique, info.get());
|
||||||
static_cast<float>(posY)/static_cast<float>(getTextureHeight()) ) );
|
|
||||||
glyph->setMaxTexCoord( osg::Vec2( static_cast<float>(posX+glyph->s())/static_cast<float>(getTextureWidth()),
|
|
||||||
static_cast<float>(posY+glyph->t())/static_cast<float>(getTextureHeight()) ) );
|
|
||||||
|
|
||||||
_image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph);
|
copyGlyphImage(glyph, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlyphTexture::copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info)
|
||||||
|
{
|
||||||
_image->dirty();
|
_image->dirty();
|
||||||
|
|
||||||
|
if (_shaderTechnique<=GREYSCALE)
|
||||||
|
{
|
||||||
|
// OSG_NOTICE<<"GlyphTexture::copyGlyphImage() greyscale copying. glyphTexture="<<this<<", glyph="<<glyph->getGlyphCode()<<std::endl;
|
||||||
|
// make sure the glyph image settings and the target image are consisent before copying.
|
||||||
|
glyph->setPixelFormat(_image->getPixelFormat());
|
||||||
|
glyph->setInternalTextureFormat(_image->getPixelFormat());
|
||||||
|
_image->copySubImage(info->texturePositionX, info->texturePositionY, 0, glyph);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSG_NOTICE<<"GlyphTexture::copyGlyphImage() generating signed distance field. glyphTexture="<<this<<", glyph="<<glyph->getGlyphCode()<<std::endl;
|
||||||
|
|
||||||
|
int src_columns = glyph->s();
|
||||||
|
int src_rows = glyph->t();
|
||||||
|
unsigned char* src_data = glyph->data();
|
||||||
|
|
||||||
|
int dest_columns = _image->s();
|
||||||
|
int dest_rows = _image->t();
|
||||||
|
unsigned char* dest_data = _image->data(info->texturePositionX, info->texturePositionY);
|
||||||
|
|
||||||
|
int search_distance = getEffectMargin(glyph);
|
||||||
|
|
||||||
|
int left = -search_distance;
|
||||||
|
int right = glyph->s()+search_distance;
|
||||||
|
int lower = -search_distance;
|
||||||
|
int upper = glyph->t()+search_distance;
|
||||||
|
|
||||||
|
float multiplier = 1.0/255.0f;
|
||||||
|
|
||||||
|
float max_distance = sqrtf(float(search_distance)*float(search_distance)*2.0);
|
||||||
|
|
||||||
|
if ((left+info->texturePositionX)<0) left = -info->texturePositionX;
|
||||||
|
if ((right+info->texturePositionX)>=dest_columns) right = dest_columns-info->texturePositionX-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());
|
||||||
|
int bytes_per_pixel = osg::Image::computePixelSizeInBits(_image->getPixelFormat(),_image->getDataType())/8;
|
||||||
|
int alpha_offset = (_image->getPixelFormat()==GL_LUMINANCE_ALPHA) ? 1 : 0;
|
||||||
|
int sdf_offset = (_image->getPixelFormat()==GL_LUMINANCE_ALPHA) ? 0 : 1;
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char full_on = 255;
|
||||||
|
unsigned char mid_point = full_on/2;
|
||||||
|
float mid_point_f = float(mid_point)*multiplier;
|
||||||
|
|
||||||
|
for(int dr=lower; dr<=upper; ++dr)
|
||||||
|
{
|
||||||
|
for(int dc=left; dc<=right; ++dc)
|
||||||
|
{
|
||||||
|
unsigned char value = 0;
|
||||||
|
|
||||||
|
unsigned char center_value = 0;
|
||||||
|
if (dr>=0 && dr<src_rows && dc>=0 && dc<src_columns) center_value = *(src_data + dr*src_columns + dc);
|
||||||
|
|
||||||
|
float center_value_f = center_value*multiplier;
|
||||||
|
float min_distance = max_distance;
|
||||||
|
|
||||||
|
if (center_value>0 && center_value<full_on)
|
||||||
|
{
|
||||||
|
if (center_value_f>=mid_point_f)
|
||||||
|
{
|
||||||
|
min_distance = center_value_f-mid_point_f;
|
||||||
|
value = 128+(min_distance/max_distance)*127;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
min_distance = mid_point_f-center_value_f;
|
||||||
|
value = 127-(min_distance/max_distance)*127;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int radius=1; radius<search_distance; ++radius)
|
||||||
|
{
|
||||||
|
for(int span=-radius; span<=radius; ++span)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// left
|
||||||
|
int dx = -radius;
|
||||||
|
int dy = span;
|
||||||
|
|
||||||
|
int c = dc+dx;
|
||||||
|
int r = dr+dy;
|
||||||
|
|
||||||
|
unsigned char local_value = 0;
|
||||||
|
if (r>=0 && r<src_rows && c>=0 && c<src_columns) local_value = *(src_data + r*src_columns + c);
|
||||||
|
if (local_value!=center_value)
|
||||||
|
{
|
||||||
|
float local_value_f = float(local_value)*multiplier;
|
||||||
|
|
||||||
|
float D = sqrtf(float(dx*dx) + float(dy*dy));
|
||||||
|
float local_multiplier = (abs(dx)>abs(dy)) ? D/float(abs(dx)) : D/float(abs(dy));
|
||||||
|
|
||||||
|
float local_distance = sqrtf(float(radius*radius)+float(span*span));
|
||||||
|
if (center_value==0) local_distance += (mid_point_f-local_value_f)*local_multiplier;
|
||||||
|
else local_distance += (local_value_f - mid_point_f)*local_multiplier;
|
||||||
|
|
||||||
|
if (local_distance<min_distance) min_distance = local_distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// top
|
||||||
|
int dx = span;
|
||||||
|
int dy = radius;
|
||||||
|
|
||||||
|
int c = dc+dx;
|
||||||
|
int r = dr+dy;
|
||||||
|
|
||||||
|
unsigned char local_value = 0;
|
||||||
|
if (r>=0 && r<src_rows && c>=0 && c<src_columns) local_value = *(src_data + r*src_columns + c);
|
||||||
|
if (local_value!=center_value)
|
||||||
|
{
|
||||||
|
float local_value_f = float(local_value)*multiplier;
|
||||||
|
|
||||||
|
float D = sqrtf(float(dx*dx) + float(dy*dy));
|
||||||
|
float local_multiplier = (abs(dx)>abs(dy)) ? D/float(abs(dx)) : D/float(abs(dy));
|
||||||
|
|
||||||
|
float local_distance = sqrtf(float(radius*radius)+float(span*span));
|
||||||
|
if (center_value==0) local_distance += (mid_point_f-local_value_f)*local_multiplier;
|
||||||
|
else local_distance += (local_value_f - mid_point_f)*local_multiplier;
|
||||||
|
|
||||||
|
if (local_distance<min_distance) min_distance = local_distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// right
|
||||||
|
int dx = radius;
|
||||||
|
int dy = span;
|
||||||
|
|
||||||
|
int c = dc+dx;
|
||||||
|
int r = dr+dy;
|
||||||
|
|
||||||
|
unsigned char local_value = 0;
|
||||||
|
if (r>=0 && r<src_rows && c>=0 && c<src_columns) local_value = *(src_data + r*src_columns + c);
|
||||||
|
if (local_value!=center_value)
|
||||||
|
{
|
||||||
|
float local_value_f = float(local_value)*multiplier;
|
||||||
|
|
||||||
|
float D = sqrtf(float(dx*dx) + float(dy*dy));
|
||||||
|
float local_multiplier = (abs(dx)>abs(dy)) ? D/float(abs(dx)) : D/float(abs(dy));
|
||||||
|
|
||||||
|
float local_distance = sqrtf(float(radius*radius)+float(span*span));
|
||||||
|
|
||||||
|
if (center_value==0) local_distance += (mid_point_f-local_value_f)*local_multiplier;
|
||||||
|
else local_distance += (local_value_f - mid_point_f)*local_multiplier;
|
||||||
|
|
||||||
|
if (local_distance<min_distance) min_distance = local_distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// bottom
|
||||||
|
int dx = span;
|
||||||
|
int dy = -radius;
|
||||||
|
|
||||||
|
int c = dc+dx;
|
||||||
|
int r = dr+dy;
|
||||||
|
|
||||||
|
unsigned char local_value = 0;
|
||||||
|
if (r>=0 && r<src_rows && c>=0 && c<src_columns) local_value = *(src_data + r*src_columns + c);
|
||||||
|
if (local_value!=center_value)
|
||||||
|
{
|
||||||
|
float local_value_f = float(local_value)*multiplier;
|
||||||
|
|
||||||
|
float D = sqrtf(float(dx*dx) + float(dy*dy));
|
||||||
|
float local_multiplier = (abs(dx)>abs(dy)) ? D/float(abs(dx)) : D/float(abs(dy));
|
||||||
|
|
||||||
|
float local_distance = sqrtf(float(radius*radius)+float(span*span));
|
||||||
|
if (center_value==0) local_distance += (mid_point_f-local_value_f)*local_multiplier;
|
||||||
|
else local_distance += (local_value_f - mid_point_f)*local_multiplier;
|
||||||
|
|
||||||
|
if (local_distance<min_distance) min_distance = local_distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (center_value_f>=0.5)
|
||||||
|
{
|
||||||
|
value = 128+(min_distance/max_distance)*127;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = 127-(min_distance/max_distance)*127;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char* dest_ptr = dest_data + (dr*dest_columns + dc)*bytes_per_pixel;
|
||||||
|
if (num_components==2)
|
||||||
|
{
|
||||||
|
// signed distance field value
|
||||||
|
*(dest_ptr+sdf_offset) = value;
|
||||||
|
|
||||||
|
// original alpha value from glyph image
|
||||||
|
*(dest_ptr+alpha_offset) = center_value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(dest_ptr) = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlyphTexture::setThreadSafeRefUnref(bool threadSafe)
|
void GlyphTexture::setThreadSafeRefUnref(bool threadSafe)
|
||||||
@ -147,22 +411,26 @@ osg::Image* GlyphTexture::createImage()
|
|||||||
{
|
{
|
||||||
if (!_image)
|
if (!_image)
|
||||||
{
|
{
|
||||||
_image = new osg::Image;
|
OSG_INFO<<"GlyphTexture::createImage() : Creating image 0x"<<std::hex<<TEXTURE_IMAGE_FORMAT<<std::dec<<std::endl;
|
||||||
_image->allocateImage(getTextureWidth(), getTextureHeight(), 1, OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE);
|
|
||||||
memset(_image->data(), 0, _image->getTotalSizeInBytes());
|
|
||||||
|
|
||||||
for(GlyphRefList::iterator itr = _glyphs.begin();
|
_image = new osg::Image;
|
||||||
itr != _glyphs.end();
|
|
||||||
++itr)
|
GLenum imageFormat = (_shaderTechnique<=GREYSCALE) ? OSGTEXT_GLYPH_ALPHA_FORMAT : OSGTEXT_GLYPH_SDF_FORMAT;
|
||||||
{
|
GLenum internalFormat = (_shaderTechnique<=GREYSCALE) ? OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT : OSGTEXT_GLYPH_SDF_INTERNALFORMAT;
|
||||||
Glyph* glyph = itr->get();
|
|
||||||
_image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph);
|
_image->allocateImage(getTextureWidth(), getTextureHeight(), 1, imageFormat, GL_UNSIGNED_BYTE);
|
||||||
}
|
_image->setInternalTextureFormat(internalFormat);
|
||||||
|
|
||||||
|
memset(_image->data(), 0, _image->getTotalSizeInBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
return _image.get();
|
return _image.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Glyph
|
||||||
|
//
|
||||||
// all the methods in Font::Glyph have been made non inline because VisualStudio6.0 is STUPID, STUPID, STUPID PILE OF JUNK.
|
// all the methods in Font::Glyph have been made non inline because VisualStudio6.0 is STUPID, STUPID, STUPID PILE OF JUNK.
|
||||||
Glyph::Glyph(Font* font, unsigned int glyphCode):
|
Glyph::Glyph(Font* font, unsigned int glyphCode):
|
||||||
_font(font),
|
_font(font),
|
||||||
@ -172,12 +440,7 @@ Glyph::Glyph(Font* font, unsigned int glyphCode):
|
|||||||
_horizontalBearing(0.0f,0.f),
|
_horizontalBearing(0.0f,0.f),
|
||||||
_horizontalAdvance(0.f),
|
_horizontalAdvance(0.f),
|
||||||
_verticalBearing(0.0f,0.f),
|
_verticalBearing(0.0f,0.f),
|
||||||
_verticalAdvance(0.f),
|
_verticalAdvance(0.f)
|
||||||
_texture(0),
|
|
||||||
_texturePosX(0),
|
|
||||||
_texturePosY(0),
|
|
||||||
_minTexCoord(0.0f,0.0f),
|
|
||||||
_maxTexCoord(0.0f,0.0f)
|
|
||||||
{
|
{
|
||||||
setThreadSafeRefUnref(true);
|
setThreadSafeRefUnref(true);
|
||||||
}
|
}
|
||||||
@ -198,67 +461,37 @@ const osg::Vec2& Glyph::getVerticalBearing() const { return _verticalBearing; }
|
|||||||
void Glyph::setVerticalAdvance(float advance) { _verticalAdvance=advance; }
|
void Glyph::setVerticalAdvance(float advance) { _verticalAdvance=advance; }
|
||||||
float Glyph::getVerticalAdvance() const { return _verticalAdvance; }
|
float Glyph::getVerticalAdvance() const { return _verticalAdvance; }
|
||||||
|
|
||||||
void Glyph::setTexture(GlyphTexture* texture) { _texture = texture; }
|
void Glyph::setTextureInfo(ShaderTechnique technique, TextureInfo* info)
|
||||||
GlyphTexture* Glyph::getTexture() { return _texture; }
|
|
||||||
const GlyphTexture* Glyph::getTexture() const { return _texture; }
|
|
||||||
|
|
||||||
void Glyph::setTexturePosition(int posX,int posY) { _texturePosX = posX; _texturePosY = posY; }
|
|
||||||
int Glyph::getTexturePositionX() const { return _texturePosX; }
|
|
||||||
int Glyph::getTexturePositionY() const { return _texturePosY; }
|
|
||||||
|
|
||||||
void Glyph::setMinTexCoord(const osg::Vec2& coord) { _minTexCoord=coord; }
|
|
||||||
const osg::Vec2& Glyph::getMinTexCoord() const { return _minTexCoord; }
|
|
||||||
|
|
||||||
void Glyph::setMaxTexCoord(const osg::Vec2& coord) { _maxTexCoord=coord; }
|
|
||||||
const osg::Vec2& Glyph::getMaxTexCoord() const { return _maxTexCoord; }
|
|
||||||
|
|
||||||
void Glyph::subload() const
|
|
||||||
{
|
{
|
||||||
GLenum errorNo = glGetError();
|
if (technique>=_textureInfoList.size())
|
||||||
if (errorNo!=GL_NO_ERROR)
|
|
||||||
{
|
{
|
||||||
const GLubyte* msg = osg::gluErrorString(errorNo);
|
_textureInfoList.resize(technique+1);
|
||||||
if (msg) { OSG_WARN<<"before Glyph::subload(): detected OpenGL error: "<<msg<<std::endl; }
|
|
||||||
else { OSG_WARN<<"before Glyph::subload(): detected OpenGL error number: "<<errorNo<<std::endl; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s() <= 0 || t() <= 0)
|
|
||||||
{
|
|
||||||
OSG_INFO<<"Glyph::subload(): texture sub-image width and/or height of 0, ignoring operation."<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT,getPacking());
|
|
||||||
|
|
||||||
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,getRowLength());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D,0,
|
|
||||||
_texturePosX,_texturePosY,
|
|
||||||
s(),t(),
|
|
||||||
(GLenum)getPixelFormat(),
|
|
||||||
(GLenum)getDataType(),
|
|
||||||
data());
|
|
||||||
|
|
||||||
errorNo = glGetError();
|
|
||||||
if (errorNo!=GL_NO_ERROR)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
const GLubyte* msg = osg::gluErrorString(errorNo);
|
|
||||||
if (msg) { OSG_WARN<<"after Glyph::subload() : detected OpenGL error: "<<msg<<std::endl; }
|
|
||||||
else { OSG_WARN<<"after Glyph::subload() : detected OpenGL error number: "<<errorNo<<std::endl; }
|
|
||||||
|
|
||||||
OSG_WARN<< "\tglTexSubImage2D(0x"<<hex<<GL_TEXTURE_2D<<dec<<" ,"<<0<<"\t"<<std::endl<<
|
|
||||||
"\t "<<_texturePosX<<" ,"<<_texturePosY<<std::endl<<
|
|
||||||
"\t "<<s()<<" ,"<<t()<<std::endl<<hex<<
|
|
||||||
"\t 0x"<<(GLenum)getPixelFormat()<<std::endl<<
|
|
||||||
"\t 0x"<<(GLenum)getDataType()<<std::endl<<
|
|
||||||
"\t "<<static_cast<const void*>(data())<<");"<<dec<<std::endl;
|
|
||||||
}
|
}
|
||||||
|
_textureInfoList[technique] = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Glyph::TextureInfo* Glyph::getTextureInfo(ShaderTechnique technique) const
|
||||||
|
{
|
||||||
|
return (technique<_textureInfoList.size()) ? _textureInfoList[technique].get() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Glyph::TextureInfo* Glyph::getOrCreateTextureInfo(ShaderTechnique technique)
|
||||||
|
{
|
||||||
|
if (technique>=_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):
|
Glyph3D::Glyph3D(Font* font, unsigned int glyphCode):
|
||||||
osg::Referenced(true),
|
osg::Referenced(true),
|
||||||
_font(font),
|
_font(font),
|
||||||
|
@ -25,13 +25,19 @@
|
|||||||
|
|
||||||
#include <osgDB/ReadFile>
|
#include <osgDB/ReadFile>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#define DEBUG_MESSAGE_LEVEL osg::INFO
|
||||||
|
#define DEBUG_MESSAGE osg::notify(DEBUG_MESSAGE_LEVEL)
|
||||||
|
|
||||||
using namespace osg;
|
using namespace osg;
|
||||||
using namespace osgText;
|
using namespace osgText;
|
||||||
|
|
||||||
Text::Text():
|
Text::Text():
|
||||||
|
_shaderTechnique(GREYSCALE),
|
||||||
_enableDepthWrites(true),
|
_enableDepthWrites(true),
|
||||||
_backdropType(NONE),
|
_backdropType(NONE),
|
||||||
_backdropImplementation(DELAYED_DEPTH_WRITES),
|
|
||||||
_backdropHorizontalOffset(0.07f),
|
_backdropHorizontalOffset(0.07f),
|
||||||
_backdropVerticalOffset(0.07f),
|
_backdropVerticalOffset(0.07f),
|
||||||
_backdropColor(0.0f, 0.0f, 0.0f, 1.0f),
|
_backdropColor(0.0f, 0.0f, 0.0f, 1.0f),
|
||||||
@ -42,13 +48,24 @@ Text::Text():
|
|||||||
_colorGradientTopRight(1.0f, 1.0f, 1.0f, 1.0f)
|
_colorGradientTopRight(1.0f, 1.0f, 1.0f, 1.0f)
|
||||||
{
|
{
|
||||||
_supportsVertexBufferObjects = true;
|
_supportsVertexBufferObjects = true;
|
||||||
|
|
||||||
|
const std::string& str = osg::DisplaySettings::instance()->getTextShaderTechnique();
|
||||||
|
if (!str.empty())
|
||||||
|
{
|
||||||
|
if (str=="ALL_FEATURES" || str=="ALL") _shaderTechnique = ALL_FEATURES;
|
||||||
|
else if (str=="GREYSCALE") _shaderTechnique = GREYSCALE;
|
||||||
|
else if (str=="SIGNED_DISTANCE_FIELD" || str=="SDF") _shaderTechnique = SIGNED_DISTANCE_FIELD;
|
||||||
|
else if (str=="NO_TEXT_SHADER" || str=="NONE") _shaderTechnique = NO_TEXT_SHADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
assignStateSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
Text::Text(const Text& text,const osg::CopyOp& copyop):
|
Text::Text(const Text& text,const osg::CopyOp& copyop):
|
||||||
osgText::TextBase(text,copyop),
|
osgText::TextBase(text,copyop),
|
||||||
|
_shaderTechnique(text._shaderTechnique),
|
||||||
_enableDepthWrites(text._enableDepthWrites),
|
_enableDepthWrites(text._enableDepthWrites),
|
||||||
_backdropType(text._backdropType),
|
_backdropType(text._backdropType),
|
||||||
_backdropImplementation(text._backdropImplementation),
|
|
||||||
_backdropHorizontalOffset(text._backdropHorizontalOffset),
|
_backdropHorizontalOffset(text._backdropHorizontalOffset),
|
||||||
_backdropVerticalOffset(text._backdropVerticalOffset),
|
_backdropVerticalOffset(text._backdropVerticalOffset),
|
||||||
_backdropColor(text._backdropColor),
|
_backdropColor(text._backdropColor),
|
||||||
@ -65,21 +82,170 @@ Text::~Text()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::setFont(osg::ref_ptr<Font> font)
|
|
||||||
|
void Text::setShaderTechnique(ShaderTechnique technique)
|
||||||
{
|
{
|
||||||
if (_font==font) return;
|
if (_shaderTechnique==technique) return;
|
||||||
|
|
||||||
osg::StateSet* previousFontStateSet = _font.valid() ? _font->getStateSet() : Font::getDefaultFont()->getStateSet();
|
_shaderTechnique = technique;
|
||||||
osg::StateSet* newFontStateSet = font.valid() ? font->getStateSet() : Font::getDefaultFont()->getStateSet();
|
|
||||||
|
|
||||||
if (getStateSet() == previousFontStateSet)
|
assignStateSet();
|
||||||
{
|
|
||||||
setStateSet( newFontStateSet );
|
|
||||||
}
|
|
||||||
|
|
||||||
TextBase::setFont(font);
|
computeGlyphRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::StateSet* Text::createStateSet()
|
||||||
|
{
|
||||||
|
Font* activeFont = getActiveFont();
|
||||||
|
if (!activeFont) return 0;
|
||||||
|
|
||||||
|
Font::StateSets& statesets = activeFont->getCachedStateSets();
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss<<std::fixed<<std::setprecision(3);
|
||||||
|
|
||||||
|
osg::StateSet::DefineList defineList;
|
||||||
|
if (_backdropType!=NONE)
|
||||||
|
{
|
||||||
|
ss.str("");
|
||||||
|
ss << "vec4("<<_backdropColor.r()<<", "<<_backdropColor.g()<<", "<<_backdropColor.b()<<", "<<_backdropColor.a()<<")";
|
||||||
|
|
||||||
|
defineList["BACKDROP_COLOR"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||||
|
|
||||||
|
|
||||||
|
if (_backdropType==OUTLINE)
|
||||||
|
{
|
||||||
|
ss.str("");
|
||||||
|
ss <<_backdropHorizontalOffset;
|
||||||
|
defineList["OUTLINE"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osg::Vec2 offset(_backdropHorizontalOffset, _backdropVerticalOffset);
|
||||||
|
switch(_backdropType)
|
||||||
|
{
|
||||||
|
case(DROP_SHADOW_BOTTOM_RIGHT) : offset.set(_backdropHorizontalOffset, -_backdropVerticalOffset); break;
|
||||||
|
case(DROP_SHADOW_CENTER_RIGHT) : offset.set(_backdropHorizontalOffset, 0.0f); break;
|
||||||
|
case(DROP_SHADOW_TOP_RIGHT) : offset.set(_backdropHorizontalOffset, _backdropVerticalOffset); break;
|
||||||
|
case(DROP_SHADOW_BOTTOM_CENTER) : offset.set(0.0f, -_backdropVerticalOffset); break;
|
||||||
|
case(DROP_SHADOW_TOP_CENTER) : offset.set(0.0f, _backdropVerticalOffset); break;
|
||||||
|
case(DROP_SHADOW_BOTTOM_LEFT) : offset.set(-_backdropHorizontalOffset, -_backdropVerticalOffset); break;
|
||||||
|
case(DROP_SHADOW_CENTER_LEFT) : offset.set(-_backdropHorizontalOffset, 0.0f); break;
|
||||||
|
case(DROP_SHADOW_TOP_LEFT) : offset.set(-_backdropHorizontalOffset, _backdropVerticalOffset); break;
|
||||||
|
default : break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss.str("");
|
||||||
|
ss << "vec2("<<offset.x()<<", "<<offset.y()<<")";
|
||||||
|
|
||||||
|
defineList["SHADOW"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ss<<std::fixed<<std::setprecision(1);
|
||||||
|
|
||||||
|
ss.str("");
|
||||||
|
ss << float(_fontSize.second);
|
||||||
|
|
||||||
|
defineList["GLYPH_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||||
|
|
||||||
|
ss.str("");
|
||||||
|
ss << float(activeFont->getTextureWidthHint());
|
||||||
|
defineList["TEXTURE_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_shaderTechnique>GREYSCALE)
|
||||||
|
{
|
||||||
|
defineList["SIGNED_DISTNACE_FIELD"] = osg::StateSet::DefinePair("1", osg::StateAttribute::ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
OSG_NOTICE<<"Text::createStateSet() defines:"<<defineList.size()<<std::endl;
|
||||||
|
for(osg::StateSet::DefineList::iterator itr = defineList.begin();
|
||||||
|
itr != defineList.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
OSG_NOTICE<<" define["<<itr->first<<"] = "<<itr->second.first<<std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!statesets.empty())
|
||||||
|
{
|
||||||
|
for(Font::StateSets::iterator itr = statesets.begin();
|
||||||
|
itr != statesets.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->getDefineList()==defineList)
|
||||||
|
{
|
||||||
|
// OSG_NOTICE<<"Text::createStateSet() : Matched DefineList, return StateSet "<<itr->get()<<std::endl;
|
||||||
|
return itr->get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (osg::isNotifyEnabled(DEBUG_MESSAGE_LEVEL))
|
||||||
|
{
|
||||||
|
DEBUG_MESSAGE<<"Text::createStateSet() ShaderTechnique ";
|
||||||
|
switch(_shaderTechnique)
|
||||||
|
{
|
||||||
|
case(NO_TEXT_SHADER) : DEBUG_MESSAGE<<"NO_TEXT_SHADER"<<std::endl; break;
|
||||||
|
case(GREYSCALE) : DEBUG_MESSAGE<<"GREYSCALE"<<std::endl; break;
|
||||||
|
case(SIGNED_DISTANCE_FIELD) : DEBUG_MESSAGE<<"SIGNED_DISTANCE_FIELD"<<std::endl; break;
|
||||||
|
case(ALL_FEATURES) : DEBUG_MESSAGE<<"ALL_FEATURES"<<std::endl; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_MESSAGE<<"Text::createStateSet() : Not Matched DefineList, creating new StateSet"<<std::endl;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
|
||||||
|
|
||||||
|
stateset->setDefineList(defineList);
|
||||||
|
|
||||||
|
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::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint();
|
||||||
|
if (_shaderTechnique==NO_TEXT_SHADER && shaderHint==osg::DisplaySettings::SHADER_NONE)
|
||||||
|
{
|
||||||
|
DEBUG_MESSAGE<<"Font::Font() Fixed function pipeline"<<std::endl;
|
||||||
|
|
||||||
|
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||||
|
return stateset.release();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// set up the StateSet to use shaders
|
||||||
|
stateset->addUniform(new osg::Uniform("glyphTexture", 0));
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Program> program = new osg::Program;
|
||||||
|
stateset->setAttributeAndModes(program.get());
|
||||||
|
|
||||||
|
{
|
||||||
|
DEBUG_MESSAGE<<"Using shaders/text.vert"<<std::endl;
|
||||||
|
|
||||||
|
#include "shaders/text_vert.cpp"
|
||||||
|
program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/text.vert", text_vert));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
DEBUG_MESSAGE<<"Using shaders/text.frag"<<std::endl;
|
||||||
|
|
||||||
|
#include "shaders/text_frag.cpp"
|
||||||
|
program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/text.frag", text_frag));
|
||||||
|
}
|
||||||
|
|
||||||
|
return stateset.release();
|
||||||
|
}
|
||||||
|
|
||||||
Font* Text::getActiveFont()
|
Font* Text::getActiveFont()
|
||||||
{
|
{
|
||||||
@ -225,22 +391,20 @@ String::iterator Text::computeLastCharacterOnLine(osg::Vec2& cursor, String::ite
|
|||||||
void Text::addGlyphQuad(Glyph* glyph, const osg::Vec2& minc, const osg::Vec2& maxc, const osg::Vec2& mintc, const osg::Vec2& maxtc)
|
void Text::addGlyphQuad(Glyph* glyph, const osg::Vec2& minc, const osg::Vec2& maxc, const osg::Vec2& mintc, const osg::Vec2& maxtc)
|
||||||
{
|
{
|
||||||
// set up the coords of the quad
|
// set up the coords of the quad
|
||||||
GlyphQuads& glyphquad = _textureGlyphQuadMap[glyph->getTexture()];
|
const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique);
|
||||||
|
GlyphTexture* glyphTexture = info ? info->texture : 0;
|
||||||
|
GlyphQuads& glyphquad = _textureGlyphQuadMap[glyphTexture];
|
||||||
|
|
||||||
glyphquad._glyphs.push_back(glyph);
|
glyphquad._glyphs.push_back(glyph);
|
||||||
|
|
||||||
osg::DrawElements* primitives = 0;
|
osg::DrawElements* primitives = glyphquad._primitives.get();
|
||||||
if (glyphquad._primitives.empty())
|
if (!primitives)
|
||||||
{
|
{
|
||||||
unsigned int maxIndices = _text.size()*4;
|
unsigned int maxIndices = _text.size()*4;
|
||||||
if (maxIndices>=16384) primitives = new osg::DrawElementsUInt(GL_TRIANGLES);
|
if (maxIndices>=16384) primitives = new osg::DrawElementsUInt(GL_TRIANGLES);
|
||||||
else primitives = new osg::DrawElementsUShort(GL_TRIANGLES);
|
else primitives = new osg::DrawElementsUShort(GL_TRIANGLES);
|
||||||
primitives->setBufferObject(_ebo.get());
|
primitives->setBufferObject(_ebo.get());
|
||||||
glyphquad._primitives.push_back(primitives);
|
glyphquad._primitives = primitives;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
primitives = glyphquad._primitives[0].get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -280,25 +444,18 @@ void Text::computeGlyphRepresentation()
|
|||||||
if (!_texcoords) { _texcoords = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); _texcoords->setBufferObject(_vbo.get()); }
|
if (!_texcoords) { _texcoords = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); _texcoords->setBufferObject(_vbo.get()); }
|
||||||
else _texcoords->clear();
|
else _texcoords->clear();
|
||||||
|
|
||||||
#if 0
|
|
||||||
_textureGlyphQuadMap.clear();
|
|
||||||
#else
|
|
||||||
for(TextureGlyphQuadMap::iterator itr = _textureGlyphQuadMap.begin();
|
for(TextureGlyphQuadMap::iterator itr = _textureGlyphQuadMap.begin();
|
||||||
itr != _textureGlyphQuadMap.end();
|
itr != _textureGlyphQuadMap.end();
|
||||||
++itr)
|
++itr)
|
||||||
{
|
{
|
||||||
GlyphQuads& glyphquads = itr->second;
|
GlyphQuads& glyphquads = itr->second;
|
||||||
glyphquads._glyphs.clear();
|
glyphquads._glyphs.clear();
|
||||||
for(Primitives::iterator pitr = glyphquads._primitives.begin();
|
if (glyphquads._primitives.valid())
|
||||||
pitr != glyphquads._primitives.end();
|
|
||||||
++pitr)
|
|
||||||
{
|
{
|
||||||
(*pitr)->resizeElements(0);
|
glyphquads._primitives->resizeElements(0);
|
||||||
(*pitr)->dirty();
|
glyphquads._primitives->dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_lineCount = 0;
|
_lineCount = 0;
|
||||||
@ -487,45 +644,53 @@ void Text::computeGlyphRepresentation()
|
|||||||
local.x() += bearing.x() * wr;
|
local.x() += bearing.x() * wr;
|
||||||
local.y() += bearing.y() * hr;
|
local.y() += bearing.y() * hr;
|
||||||
|
|
||||||
|
const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique);
|
||||||
// Adjust coordinates and texture coordinates to avoid
|
if (info)
|
||||||
// clipping the edges of antialiased characters.
|
|
||||||
osg::Vec2 mintc = glyph->getMinTexCoord();
|
|
||||||
osg::Vec2 maxtc = glyph->getMaxTexCoord();
|
|
||||||
osg::Vec2 vDiff = maxtc - mintc;
|
|
||||||
|
|
||||||
float fHorizTCMargin = 1.0f / glyph->getTexture()->getTextureWidth();
|
|
||||||
float fVertTCMargin = 1.0f / 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)
|
|
||||||
{
|
{
|
||||||
case LEFT_TO_RIGHT:
|
// Adjust coordinates and texture coordinates to avoid
|
||||||
cursor.x() += glyph->getHorizontalAdvance() * wr;
|
// clipping the edges of antialiased characters.
|
||||||
_textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner
|
osg::Vec2 mintc = info->minTexCoord;
|
||||||
_textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner
|
osg::Vec2 maxtc = info->maxTexCoord;
|
||||||
break;
|
osg::Vec2 vDiff = maxtc - mintc;
|
||||||
case VERTICAL:
|
float texelMargin = info->texelMargin;
|
||||||
cursor.y() -= glyph->getVerticalAdvance() * hr;
|
|
||||||
_textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner
|
float fHorizTCMargin = texelMargin / info->texture->getTextureWidth();
|
||||||
_textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner
|
float fVertTCMargin = texelMargin / info->texture->getTextureHeight();
|
||||||
break;
|
float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x();
|
||||||
case RIGHT_TO_LEFT:
|
float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y();
|
||||||
_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
|
mintc.x() -= fHorizTCMargin;
|
||||||
break;
|
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 "<<charcode<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
previous_charcode = charcode;
|
previous_charcode = charcode;
|
||||||
@ -622,153 +787,10 @@ void Text::computePositionsImplementation()
|
|||||||
{
|
{
|
||||||
TextBase::computePositionsImplementation();
|
TextBase::computePositionsImplementation();
|
||||||
|
|
||||||
computeBackdropPositions();
|
|
||||||
computeBackdropBoundingBox();
|
computeBackdropBoundingBox();
|
||||||
computeBoundingBoxMargin();
|
computeBoundingBoxMargin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Presumes the atc matrix is already up-to-date
|
|
||||||
void Text::computeBackdropPositions()
|
|
||||||
{
|
|
||||||
if(_backdropType == NONE)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float avg_width = 0.0f;
|
|
||||||
float avg_height = 0.0f;
|
|
||||||
|
|
||||||
// FIXME: OPTIMIZE: This function produces the same value regardless of contextID.
|
|
||||||
// Since we tend to loop over contextID, we should cache this value some how
|
|
||||||
// instead of recomputing it each time.
|
|
||||||
bool is_valid_size = computeAverageGlyphWidthAndHeight(avg_width, avg_height);
|
|
||||||
if (!is_valid_size) return;
|
|
||||||
|
|
||||||
unsigned int backdrop_index;
|
|
||||||
unsigned int max_backdrop_index;
|
|
||||||
if(_backdropType == OUTLINE)
|
|
||||||
{
|
|
||||||
// For outline, we want to draw the in every direction
|
|
||||||
backdrop_index = 1;
|
|
||||||
max_backdrop_index = backdrop_index+8;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Yes, this may seem a little strange,
|
|
||||||
// but since the code is using references,
|
|
||||||
// I would have to duplicate the following code twice
|
|
||||||
// for each part of the if/else because I can't
|
|
||||||
// declare a reference without setting it immediately
|
|
||||||
// and it wouldn't survive the scope.
|
|
||||||
// So it happens that the _backdropType value matches
|
|
||||||
// the index in the array I want to store the coordinates
|
|
||||||
// in. So I'll just setup the for-loop so it only does
|
|
||||||
// the one direction I'm interested in.
|
|
||||||
backdrop_index = _backdropType+1;
|
|
||||||
max_backdrop_index = backdrop_index+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( ; backdrop_index < max_backdrop_index; backdrop_index++)
|
|
||||||
{
|
|
||||||
float horizontal_shift_direction;
|
|
||||||
float vertical_shift_direction;
|
|
||||||
switch(backdrop_index)
|
|
||||||
{
|
|
||||||
case DROP_SHADOW_BOTTOM_RIGHT:
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = 1.0f;
|
|
||||||
vertical_shift_direction = -1.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DROP_SHADOW_CENTER_RIGHT:
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = 1.0f;
|
|
||||||
vertical_shift_direction = 0.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DROP_SHADOW_TOP_RIGHT:
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = 1.0f;
|
|
||||||
vertical_shift_direction = 1.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DROP_SHADOW_BOTTOM_CENTER:
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = 0.0f;
|
|
||||||
vertical_shift_direction = -1.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DROP_SHADOW_TOP_CENTER:
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = 0.0f;
|
|
||||||
vertical_shift_direction = 1.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DROP_SHADOW_BOTTOM_LEFT:
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = -1.0f;
|
|
||||||
vertical_shift_direction = -1.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DROP_SHADOW_CENTER_LEFT:
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = -1.0f;
|
|
||||||
vertical_shift_direction = 0.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DROP_SHADOW_TOP_LEFT:
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = -1.0f;
|
|
||||||
vertical_shift_direction = 1.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: // error
|
|
||||||
{
|
|
||||||
horizontal_shift_direction = 1.0f;
|
|
||||||
vertical_shift_direction = -1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now apply matrix to the glyphs.
|
|
||||||
for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin();
|
|
||||||
titr!=_textureGlyphQuadMap.end();
|
|
||||||
++titr)
|
|
||||||
{
|
|
||||||
GlyphQuads& glyphquad = titr->second;
|
|
||||||
|
|
||||||
osg::DrawElements* src_primitives = glyphquad._primitives[0].get();
|
|
||||||
|
|
||||||
for(unsigned int i=glyphquad._primitives.size(); i<=backdrop_index; ++i)
|
|
||||||
{
|
|
||||||
osg::DrawElementsUShort* dst_primitives = new osg::DrawElementsUShort(GL_TRIANGLES);
|
|
||||||
dst_primitives->setBufferObject(src_primitives->getBufferObject());
|
|
||||||
glyphquad._primitives.push_back(dst_primitives);
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::DrawElements* dst_primitives = glyphquad._primitives[backdrop_index].get();
|
|
||||||
dst_primitives->resizeElements(0);
|
|
||||||
|
|
||||||
unsigned int numCoords = src_primitives->getNumIndices();
|
|
||||||
|
|
||||||
Coords& src_coords = _coords;
|
|
||||||
TexCoords& src_texcoords = _texcoords;
|
|
||||||
|
|
||||||
Coords& dst_coords = _coords;
|
|
||||||
TexCoords& dst_texcoords = _texcoords;
|
|
||||||
|
|
||||||
for(unsigned int i=0;i<numCoords;++i)
|
|
||||||
{
|
|
||||||
unsigned int si = (*src_primitives).getElement(i);
|
|
||||||
osg::Vec3 v(horizontal_shift_direction * _backdropHorizontalOffset * avg_width + (*src_coords)[si].x(), vertical_shift_direction * _backdropVerticalOffset * avg_height + (*src_coords)[si].y(), 0.0f);
|
|
||||||
unsigned int di = dst_coords->size();
|
|
||||||
(*dst_primitives).addElement(di);
|
|
||||||
(*dst_coords).push_back(v);
|
|
||||||
(*dst_texcoords).push_back((*src_texcoords)[si]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method adjusts the bounding box to account for the expanded area caused by the backdrop.
|
// This method adjusts the bounding box to account for the expanded area caused by the backdrop.
|
||||||
// This assumes that the bounding box has already been computed for the text without the backdrop.
|
// This assumes that the bounding box has already been computed for the text without the backdrop.
|
||||||
void Text::computeBackdropBoundingBox()
|
void Text::computeBackdropBoundingBox()
|
||||||
@ -1095,6 +1117,8 @@ void Text::drawImplementation(osg::RenderInfo& renderInfo) const
|
|||||||
|
|
||||||
void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const
|
void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const
|
||||||
{
|
{
|
||||||
|
if (colorMultiplier.a()==0.0f || _color.a()==0.0f) return;
|
||||||
|
|
||||||
osg::VertexArrayState* vas = state.getCurrentVertexArrayState();
|
osg::VertexArrayState* vas = state.getCurrentVertexArrayState();
|
||||||
bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects);
|
bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects);
|
||||||
bool usingVertexArrayObjects = usingVertexBufferObjects && state.useVertexArrayObject(_useVertexArrayObject);
|
bool usingVertexArrayObjects = usingVertexBufferObjects && state.useVertexArrayObject(_useVertexArrayObject);
|
||||||
@ -1117,7 +1141,6 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_drawMode & TEXT)
|
if (_drawMode & TEXT)
|
||||||
// if (false)
|
|
||||||
{
|
{
|
||||||
for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin();
|
for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin();
|
||||||
titr!=_textureGlyphQuadMap.end();
|
titr!=_textureGlyphQuadMap.end();
|
||||||
@ -1128,33 +1151,6 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo
|
|||||||
|
|
||||||
const GlyphQuads& glyphquad = titr->second;
|
const GlyphQuads& glyphquad = titr->second;
|
||||||
|
|
||||||
#if 1
|
|
||||||
if(_backdropType != NONE)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(_colorGradientMode == SOLID)
|
if(_colorGradientMode == SOLID)
|
||||||
{
|
{
|
||||||
vas->disableColorArray(state);
|
vas->disableColorArray(state);
|
||||||
@ -1168,7 +1164,7 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glyphquad._primitives[0]->draw(state, usingVertexBufferObjects);
|
glyphquad._primitives->draw(state, usingVertexBufferObjects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1216,9 +1212,6 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie
|
|||||||
vas->applyDisablingOfVertexAttributes(state);
|
vas->applyDisablingOfVertexAttributes(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
drawImplementationSinglePass(state, colorMultiplier);
|
|
||||||
#else
|
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
|
|
||||||
drawImplementationSinglePass(state, colorMultiplier);
|
drawImplementationSinglePass(state, colorMultiplier);
|
||||||
@ -1235,7 +1228,6 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie
|
|||||||
}
|
}
|
||||||
|
|
||||||
state.haveAppliedAttribute(osg::StateAttribute::DEPTH);
|
state.haveAppliedAttribute(osg::StateAttribute::DEPTH);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (usingVertexBufferObjects && !usingVertexArrayObjects)
|
if (usingVertexBufferObjects && !usingVertexArrayObjects)
|
||||||
{
|
{
|
||||||
@ -1273,16 +1265,16 @@ void Text::accept(osg::PrimitiveFunctor& pf) const
|
|||||||
++titr)
|
++titr)
|
||||||
{
|
{
|
||||||
const GlyphQuads& glyphquad = titr->second;
|
const GlyphQuads& glyphquad = titr->second;
|
||||||
if (!glyphquad._primitives.empty())
|
if (glyphquad._primitives.valid())
|
||||||
{
|
{
|
||||||
const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast<const osg::DrawElementsUShort*>(glyphquad._primitives[0].get());
|
const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast<const osg::DrawElementsUShort*>(glyphquad._primitives.get());
|
||||||
if (drawElementsUShort)
|
if (drawElementsUShort)
|
||||||
{
|
{
|
||||||
pf.drawElements(GL_TRIANGLES, drawElementsUShort->size(), &(drawElementsUShort->front()));
|
pf.drawElements(GL_TRIANGLES, drawElementsUShort->size(), &(drawElementsUShort->front()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast<const osg::DrawElementsUInt*>(glyphquad._primitives[0].get());
|
const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast<const osg::DrawElementsUInt*>(glyphquad._primitives.get());
|
||||||
if (drawElementsUInt)
|
if (drawElementsUInt)
|
||||||
{
|
{
|
||||||
pf.drawElements(GL_TRIANGLES, drawElementsUInt->size(), &(drawElementsUInt->front()));
|
pf.drawElements(GL_TRIANGLES, drawElementsUInt->size(), &(drawElementsUInt->front()));
|
||||||
@ -1322,22 +1314,19 @@ void Text::setBackdropType(BackdropType type)
|
|||||||
if (_backdropType==type) return;
|
if (_backdropType==type) return;
|
||||||
|
|
||||||
_backdropType = type;
|
_backdropType = type;
|
||||||
|
|
||||||
|
assignStateSet();
|
||||||
|
|
||||||
computeGlyphRepresentation();
|
computeGlyphRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::setBackdropImplementation(BackdropImplementation implementation)
|
|
||||||
{
|
|
||||||
if (_backdropImplementation==implementation) return;
|
|
||||||
|
|
||||||
_backdropImplementation = implementation;
|
|
||||||
computeGlyphRepresentation();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Text::setBackdropOffset(float offset)
|
void Text::setBackdropOffset(float offset)
|
||||||
{
|
{
|
||||||
_backdropHorizontalOffset = offset;
|
_backdropHorizontalOffset = offset;
|
||||||
_backdropVerticalOffset = offset;
|
_backdropVerticalOffset = offset;
|
||||||
|
|
||||||
|
assignStateSet();
|
||||||
|
|
||||||
computeGlyphRepresentation();
|
computeGlyphRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1345,12 +1334,17 @@ void Text::setBackdropOffset(float horizontal, float vertical)
|
|||||||
{
|
{
|
||||||
_backdropHorizontalOffset = horizontal;
|
_backdropHorizontalOffset = horizontal;
|
||||||
_backdropVerticalOffset = vertical;
|
_backdropVerticalOffset = vertical;
|
||||||
|
|
||||||
|
assignStateSet();
|
||||||
|
|
||||||
computeGlyphRepresentation();
|
computeGlyphRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::setBackdropColor(const osg::Vec4& color)
|
void Text::setBackdropColor(const osg::Vec4& color)
|
||||||
{
|
{
|
||||||
_backdropColor = color;
|
_backdropColor = color;
|
||||||
|
|
||||||
|
assignStateSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::setColorGradientMode(ColorGradientMode mode)
|
void Text::setColorGradientMode(ColorGradientMode mode)
|
||||||
@ -1391,20 +1385,10 @@ Text::GlyphQuads::GlyphQuads(const GlyphQuads&)
|
|||||||
|
|
||||||
void Text::GlyphQuads::resizeGLObjectBuffers(unsigned int maxSize)
|
void Text::GlyphQuads::resizeGLObjectBuffers(unsigned int maxSize)
|
||||||
{
|
{
|
||||||
for(Primitives::iterator itr = _primitives.begin();
|
if (_primitives.valid()) _primitives->resizeGLObjectBuffers(maxSize);
|
||||||
itr != _primitives.end();
|
|
||||||
++itr)
|
|
||||||
{
|
|
||||||
(*itr)->resizeGLObjectBuffers(maxSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::GlyphQuads::releaseGLObjects(osg::State* state) const
|
void Text::GlyphQuads::releaseGLObjects(osg::State* state) const
|
||||||
{
|
{
|
||||||
for(Primitives::const_iterator itr = _primitives.begin();
|
if (_primitives.valid()) _primitives->releaseGLObjects(state);
|
||||||
itr != _primitives.end();
|
|
||||||
++itr)
|
|
||||||
{
|
|
||||||
(*itr)->releaseGLObjects(state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,6 @@ TextBase::TextBase():
|
|||||||
_lineCount(0),
|
_lineCount(0),
|
||||||
_glyphNormalized(false)
|
_glyphNormalized(false)
|
||||||
{
|
{
|
||||||
setStateSet(Font::getDefaultFont()->getStateSet());
|
|
||||||
setUseDisplayList(false);
|
setUseDisplayList(false);
|
||||||
setSupportsDisplayList(false);
|
setSupportsDisplayList(false);
|
||||||
|
|
||||||
@ -89,6 +88,11 @@ TextBase::~TextBase()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::StateSet* TextBase::createStateSet()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void TextBase::initArraysAndBuffers()
|
void TextBase::initArraysAndBuffers()
|
||||||
{
|
{
|
||||||
_vbo = new osg::VertexBufferObject;
|
_vbo = new osg::VertexBufferObject;
|
||||||
@ -182,6 +186,10 @@ void TextBase::setColor(const osg::Vec4& color)
|
|||||||
_color = color;
|
_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextBase::assignStateSet()
|
||||||
|
{
|
||||||
|
setStateSet(createStateSet());
|
||||||
|
}
|
||||||
|
|
||||||
void TextBase::setFont(osg::ref_ptr<Font> font)
|
void TextBase::setFont(osg::ref_ptr<Font> font)
|
||||||
{
|
{
|
||||||
@ -189,6 +197,8 @@ void TextBase::setFont(osg::ref_ptr<Font> font)
|
|||||||
|
|
||||||
_font = font;
|
_font = font;
|
||||||
|
|
||||||
|
assignStateSet();
|
||||||
|
|
||||||
computeGlyphRepresentation();
|
computeGlyphRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +213,9 @@ void TextBase::setFontResolution(unsigned int width, unsigned int height)
|
|||||||
if (_fontSize==size) return;
|
if (_fontSize==size) return;
|
||||||
|
|
||||||
_fontSize = size;
|
_fontSize = size;
|
||||||
|
|
||||||
|
assignStateSet();
|
||||||
|
|
||||||
computeGlyphRepresentation();
|
computeGlyphRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
257
src/osgText/shaders/text_frag.cpp
Normal file
257
src/osgText/shaders/text_frag.cpp
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
char text_frag[] = "$OSG_GLSL_VERSION\n"
|
||||||
|
"\n"
|
||||||
|
"#pragma import_defines( BACKDROP_COLOR, SHADOW, OUTLINE, SIGNED_DISTNACE_FIELD, TEXTURE_DIMENSION, GLYPH_DIMENSION)\n"
|
||||||
|
"\n"
|
||||||
|
"#ifdef GL_ES\n"
|
||||||
|
" #extension GL_OES_standard_derivatives : enable\n"
|
||||||
|
" #ifndef GL_OES_standard_derivatives\n"
|
||||||
|
" #undef SIGNED_DISTNACE_FIELD\n"
|
||||||
|
" #endif\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
"#if !defined(GL_ES)\n"
|
||||||
|
" #if __VERSION__>=400\n"
|
||||||
|
" #define osg_TextureQueryLOD textureQueryLod\n"
|
||||||
|
" #else\n"
|
||||||
|
" #extension GL_ARB_texture_query_lod : enable\n"
|
||||||
|
" #ifdef GL_ARB_texture_query_lod\n"
|
||||||
|
" #define osg_TextureQueryLOD textureQueryLOD\n"
|
||||||
|
" #endif\n"
|
||||||
|
" #endif\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
"$OSG_PRECISION_FLOAT\n"
|
||||||
|
"\n"
|
||||||
|
"#if __VERSION__>=130\n"
|
||||||
|
" #define TEXTURE texture\n"
|
||||||
|
" #define TEXTURELOD textureLod\n"
|
||||||
|
" out vec4 osg_FragColor;\n"
|
||||||
|
"#else\n"
|
||||||
|
" #define TEXTURE texture2D\n"
|
||||||
|
" #define TEXTURELOD texture2DLod\n"
|
||||||
|
" #define osg_FragColor gl_FragColor\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"#if !defined(GL_ES) && __VERSION__>=130\n"
|
||||||
|
" #define ALPHA r\n"
|
||||||
|
" #define SDF g\n"
|
||||||
|
"#else\n"
|
||||||
|
" #define ALPHA a\n"
|
||||||
|
" #define SDF r\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"uniform sampler2D glyphTexture;\n"
|
||||||
|
"\n"
|
||||||
|
"$OSG_VARYING_IN vec2 texCoord;\n"
|
||||||
|
"$OSG_VARYING_IN vec4 vertexColor;\n"
|
||||||
|
"\n"
|
||||||
|
"#ifndef TEXTURE_DIMENSION\n"
|
||||||
|
"const float TEXTURE_DIMENSION = 1024.0;\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
"#ifndef GLYPH_DIMENSION\n"
|
||||||
|
"const float GLYPH_DIMENSION = 32.0;\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
"#ifdef SIGNED_DISTNACE_FIELD\n"
|
||||||
|
"\n"
|
||||||
|
"float distanceFromEdge(vec2 tc)\n"
|
||||||
|
"{\n"
|
||||||
|
" float center_alpha = TEXTURELOD(glyphTexture, tc, 0.0).SDF;\n"
|
||||||
|
" if (center_alpha==0.0) return -1.0;\n"
|
||||||
|
"\n"
|
||||||
|
" //float distance_scale = (1.0/4.0)*1.41;\n"
|
||||||
|
" float distance_scale = (1.0/6.0)*1.41;\n"
|
||||||
|
" //float distance_scale = (1.0/8.0)*1.41;\n"
|
||||||
|
"\n"
|
||||||
|
" return (center_alpha-0.5)*distance_scale;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"vec4 distanceFieldColorSample(float edge_distance, float blend_width, float blend_half_width)\n"
|
||||||
|
"{\n"
|
||||||
|
"#ifdef OUTLINE\n"
|
||||||
|
" float outline_width = OUTLINE*0.5;\n"
|
||||||
|
" if (edge_distance>blend_half_width)\n"
|
||||||
|
" {\n"
|
||||||
|
" return vertexColor;\n"
|
||||||
|
" }\n"
|
||||||
|
" else if (edge_distance>-blend_half_width)\n"
|
||||||
|
" {\n"
|
||||||
|
" return mix(vertexColor, vec4(BACKDROP_COLOR.rgb, BACKDROP_COLOR.a*vertexColor.a), smoothstep(0.0, 1.0, (blend_half_width-edge_distance)/(blend_width)));\n"
|
||||||
|
" }\n"
|
||||||
|
" else if (edge_distance>(blend_half_width-outline_width))\n"
|
||||||
|
" {\n"
|
||||||
|
" return vec4(BACKDROP_COLOR.rgb, BACKDROP_COLOR.a*vertexColor.a);\n"
|
||||||
|
" }\n"
|
||||||
|
" else if (edge_distance>-(outline_width+blend_half_width))\n"
|
||||||
|
" {\n"
|
||||||
|
" return vec4(BACKDROP_COLOR.rgb, vertexColor.a * ((blend_half_width+outline_width+edge_distance)/blend_width));\n"
|
||||||
|
" }\n"
|
||||||
|
" else\n"
|
||||||
|
" {\n"
|
||||||
|
" return vec4(0.0, 0.0, 0.0, 0.0);\n"
|
||||||
|
" }\n"
|
||||||
|
"#else\n"
|
||||||
|
" if (edge_distance>blend_half_width)\n"
|
||||||
|
" {\n"
|
||||||
|
" return vertexColor;\n"
|
||||||
|
" }\n"
|
||||||
|
" else if (edge_distance>-blend_half_width)\n"
|
||||||
|
" {\n"
|
||||||
|
" return vec4(vertexColor.rgb, vertexColor.a * smoothstep(1.0, 0.0, (blend_half_width-edge_distance)/(blend_width)));\n"
|
||||||
|
" }\n"
|
||||||
|
" else\n"
|
||||||
|
" {\n"
|
||||||
|
" return vec4(0.0, 0.0, 0.0, 0.0);\n"
|
||||||
|
" }\n"
|
||||||
|
"#endif\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"vec4 textColor(vec2 src_texCoord)\n"
|
||||||
|
"{\n"
|
||||||
|
" float sample_distance_scale = 0.75;\n"
|
||||||
|
" vec2 dx = dFdx(src_texCoord)*sample_distance_scale;\n"
|
||||||
|
" vec2 dy = dFdy(src_texCoord)*sample_distance_scale;\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
" float distance_across_pixel = length(dx+dy)*(TEXTURE_DIMENSION/GLYPH_DIMENSION);\n"
|
||||||
|
"\n"
|
||||||
|
" // compute the appropriate number of samples required to avoid aliasing.\n"
|
||||||
|
" int maxNumSamplesAcrossSide = 4;\n"
|
||||||
|
"\n"
|
||||||
|
" int numSamplesX = int(TEXTURE_DIMENSION * length(dx));\n"
|
||||||
|
" int numSamplesY = int(TEXTURE_DIMENSION * length(dy));\n"
|
||||||
|
" if (numSamplesX<2) numSamplesX = 2;\n"
|
||||||
|
" if (numSamplesY<2) numSamplesY = 2;\n"
|
||||||
|
" if (numSamplesX>maxNumSamplesAcrossSide) numSamplesX = maxNumSamplesAcrossSide;\n"
|
||||||
|
" if (numSamplesY>maxNumSamplesAcrossSide) numSamplesY = maxNumSamplesAcrossSide;\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
" vec2 delta_tx = dx/float(numSamplesX-1);\n"
|
||||||
|
" vec2 delta_ty = dy/float(numSamplesY-1);\n"
|
||||||
|
"\n"
|
||||||
|
" float numSamples = float(numSamplesX)*float(numSamplesY);\n"
|
||||||
|
" float scale = 1.0/numSamples;\n"
|
||||||
|
" vec4 total_color = vec4(0.0,0.0,0.0,0.0);\n"
|
||||||
|
"\n"
|
||||||
|
" float blend_width = 1.5*distance_across_pixel/numSamples;\n"
|
||||||
|
" float blend_half_width = blend_width*0.5;\n"
|
||||||
|
"\n"
|
||||||
|
" // check whether fragment is wholly within or outwith glyph body+outline\n"
|
||||||
|
" float cd = distanceFromEdge(src_texCoord); // central distance (distance from center to edge)\n"
|
||||||
|
" if (cd-blend_half_width>distance_across_pixel) return vertexColor; // pixel fully within glyph body\n"
|
||||||
|
"\n"
|
||||||
|
" #ifdef OUTLINE\n"
|
||||||
|
" float outline_width = OUTLINE*0.5;\n"
|
||||||
|
" if ((-cd-outline_width-blend_half_width)>distance_across_pixel) return vec4(0.0, 0.0, 0.0, 0.0); // pixel fully outside outline+glyph body\n"
|
||||||
|
" #else\n"
|
||||||
|
" if (-cd-blend_half_width>distance_across_pixel) return vec4(0.0, 0.0, 0.0, 0.0); // pixel fully outside glyph body\n"
|
||||||
|
" #endif\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
" // use multi-sampling to provide high quality antialised fragments\n"
|
||||||
|
" vec2 origin = src_texCoord - dx*0.5 - dy*0.5;\n"
|
||||||
|
" for(;numSamplesY>0; --numSamplesY)\n"
|
||||||
|
" {\n"
|
||||||
|
" vec2 pos = origin;\n"
|
||||||
|
" int numX = numSamplesX;\n"
|
||||||
|
" for(;numX>0; --numX)\n"
|
||||||
|
" {\n"
|
||||||
|
" vec4 c = distanceFieldColorSample(distanceFromEdge(pos), blend_width, blend_half_width);\n"
|
||||||
|
" total_color = total_color + c * c.a;\n"
|
||||||
|
" pos += delta_tx;\n"
|
||||||
|
" }\n"
|
||||||
|
" origin += delta_ty;\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" total_color.rgb /= total_color.a;\n"
|
||||||
|
" total_color.a *= scale;\n"
|
||||||
|
"\n"
|
||||||
|
" return total_color;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"#else\n"
|
||||||
|
"\n"
|
||||||
|
"vec4 textColor(vec2 src_texCoord)\n"
|
||||||
|
"{\n"
|
||||||
|
"\n"
|
||||||
|
"#ifdef OUTLINE\n"
|
||||||
|
"\n"
|
||||||
|
" float alpha = TEXTURE(glyphTexture, src_texCoord).ALPHA;\n"
|
||||||
|
" float delta_tc = 1.6*OUTLINE*GLYPH_DIMENSION/TEXTURE_DIMENSION;\n"
|
||||||
|
"\n"
|
||||||
|
" float outline_alpha = alpha;\n"
|
||||||
|
" vec2 origin = src_texCoord-vec2(delta_tc*0.5, delta_tc*0.5);\n"
|
||||||
|
"\n"
|
||||||
|
" float numSamples = 3.0;\n"
|
||||||
|
" delta_tc = delta_tc/(numSamples-1.0);\n"
|
||||||
|
"\n"
|
||||||
|
" float background_alpha = 1.0;\n"
|
||||||
|
"\n"
|
||||||
|
" for(float i=0.0; i<numSamples; ++i)\n"
|
||||||
|
" {\n"
|
||||||
|
" for(float j=0.0; j<numSamples; ++j)\n"
|
||||||
|
" {\n"
|
||||||
|
" float local_alpha = TEXTURE(glyphTexture, origin + vec2(i*delta_tc, j*delta_tc)).ALPHA;\n"
|
||||||
|
" outline_alpha = max(outline_alpha, local_alpha);\n"
|
||||||
|
" background_alpha = background_alpha * (1.0-local_alpha);\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" #ifdef osg_TextureQueryLOD\n"
|
||||||
|
" float mipmapLevel = osg_TextureQueryLOD(glyphTexture, src_texCoord).x;\n"
|
||||||
|
" if (mipmapLevel<1.0)\n"
|
||||||
|
" {\n"
|
||||||
|
" outline_alpha = mix(1.0-background_alpha, outline_alpha, mipmapLevel/1.0);\n"
|
||||||
|
" }\n"
|
||||||
|
" #endif\n"
|
||||||
|
"\n"
|
||||||
|
" if (outline_alpha<alpha) outline_alpha = alpha;\n"
|
||||||
|
" if (outline_alpha>1.0) outline_alpha = 1.0;\n"
|
||||||
|
"\n"
|
||||||
|
" if (outline_alpha==0.0) return vec4(0.0, 0.0, 0.0, 0.0); // outside glyph and outline\n"
|
||||||
|
"\n"
|
||||||
|
" vec4 color = mix(BACKDROP_COLOR, vertexColor, smoothstep(0.0, 1.0, alpha));\n"
|
||||||
|
" color.a = vertexColor.a * smoothstep(0.0, 1.0, outline_alpha);\n"
|
||||||
|
"\n"
|
||||||
|
" return color;\n"
|
||||||
|
"\n"
|
||||||
|
"#else\n"
|
||||||
|
"\n"
|
||||||
|
" float alpha = TEXTURE(glyphTexture, src_texCoord).ALPHA;\n"
|
||||||
|
" if (alpha==0.0) vec4(0.0, 0.0, 0.0, 0.0);\n"
|
||||||
|
" return vec4(vertexColor.rgb, vertexColor.a * alpha);\n"
|
||||||
|
"\n"
|
||||||
|
"#endif\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"void main(void)\n"
|
||||||
|
"{\n"
|
||||||
|
" if (texCoord.x<0.0 && texCoord.y<0.0)\n"
|
||||||
|
" {\n"
|
||||||
|
" osg_FragColor = vertexColor;\n"
|
||||||
|
" return;\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
"#ifdef SHADOW\n"
|
||||||
|
" float scale = -1.0*GLYPH_DIMENSION/TEXTURE_DIMENSION;\n"
|
||||||
|
" vec2 delta_tc = SHADOW*scale;\n"
|
||||||
|
" vec4 shadow_color = textColor(texCoord+delta_tc);\n"
|
||||||
|
" shadow_color.rgb = BACKDROP_COLOR.rgb;\n"
|
||||||
|
"\n"
|
||||||
|
" vec4 glyph_color = textColor(texCoord);\n"
|
||||||
|
" vec4 color = mix(shadow_color, glyph_color, glyph_color.a);\n"
|
||||||
|
"#else\n"
|
||||||
|
" vec4 color = textColor(texCoord);\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\n"
|
||||||
|
" if (color.a==0.0) discard;\n"
|
||||||
|
"\n"
|
||||||
|
" osg_FragColor = color;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n";
|
13
src/osgText/shaders/text_vert.cpp
Normal file
13
src/osgText/shaders/text_vert.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
char text_vert[] = "$OSG_GLSL_VERSION\n"
|
||||||
|
"$OSG_PRECISION_FLOAT\n"
|
||||||
|
"\n"
|
||||||
|
"$OSG_VARYING_OUT vec2 texCoord;\n"
|
||||||
|
"$OSG_VARYING_OUT vec4 vertexColor;\n"
|
||||||
|
"\n"
|
||||||
|
"void main(void)\n"
|
||||||
|
"{\n"
|
||||||
|
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||||
|
" texCoord = gl_MultiTexCoord0.xy;\n"
|
||||||
|
" vertexColor = gl_Color;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n";
|
@ -153,6 +153,23 @@ void GLObjectsVisitor::apply(osg::StateSet& stateset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLObjectsVisitor::compile(osg::Node& node)
|
||||||
|
{
|
||||||
|
if (_renderInfo.getState())
|
||||||
|
{
|
||||||
|
node.accept(*this);
|
||||||
|
|
||||||
|
if (_lastCompiledProgram.valid())
|
||||||
|
{
|
||||||
|
osg::State* state = _renderInfo.getState();
|
||||||
|
osg::GLExtensions* extensions = state->get<osg::GLExtensions>();
|
||||||
|
extensions->glUseProgram(0);
|
||||||
|
_renderInfo.getState()->setLastAppliedProgramObject(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// GLObjectsOperation
|
// GLObjectsOperation
|
||||||
|
@ -571,7 +571,6 @@ void Renderer::compile()
|
|||||||
{
|
{
|
||||||
DEBUG_MESSAGE<<"Renderer::compile()"<<std::endl;
|
DEBUG_MESSAGE<<"Renderer::compile()"<<std::endl;
|
||||||
|
|
||||||
|
|
||||||
_compileOnNextDraw = false;
|
_compileOnNextDraw = false;
|
||||||
|
|
||||||
osgUtil::SceneView* sceneView = _sceneView[0].get();
|
osgUtil::SceneView* sceneView = _sceneView[0].get();
|
||||||
@ -583,7 +582,7 @@ void Renderer::compile()
|
|||||||
{
|
{
|
||||||
osgUtil::GLObjectsVisitor glov;
|
osgUtil::GLObjectsVisitor glov;
|
||||||
glov.setState(sceneView->getState());
|
glov.setState(sceneView->getState());
|
||||||
sceneView->getSceneData()->accept(glov);
|
glov.compile(*(sceneView->getSceneData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
sceneView->getState()->checkGLErrors("After Renderer::compile");
|
sceneView->getState()->checkGLErrors("After Renderer::compile");
|
||||||
|
@ -134,7 +134,6 @@ void Label::setFontColor(const Color& c) {
|
|||||||
|
|
||||||
void Label::setShadow(point_type offset) {
|
void Label::setShadow(point_type offset) {
|
||||||
_text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
|
_text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
|
||||||
_text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER);
|
|
||||||
_text->setBackdropOffset(offset);
|
_text->setBackdropOffset(offset);
|
||||||
|
|
||||||
_calculateSize(getTextSize());
|
_calculateSize(getTextSize());
|
||||||
|
@ -57,27 +57,6 @@ std::string convertBackdropTypeEnumToString(osgText::Text::BackdropType backdrop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
osgText::Text::BackdropImplementation convertBackdropImplementationStringToEnum(std::string & str)
|
|
||||||
{
|
|
||||||
if (str=="POLYGON_OFFSET") return osgText::Text::POLYGON_OFFSET;
|
|
||||||
else if (str=="NO_DEPTH_BUFFER") return osgText::Text::NO_DEPTH_BUFFER;
|
|
||||||
else if (str=="DEPTH_RANGE") return osgText::Text::DEPTH_RANGE;
|
|
||||||
else if (str=="STENCIL_BUFFER") return osgText::Text::STENCIL_BUFFER;
|
|
||||||
else return static_cast<osgText::Text::BackdropImplementation>(-1);
|
|
||||||
}
|
|
||||||
std::string convertBackdropImplementationEnumToString(osgText::Text::BackdropImplementation backdropImplementation)
|
|
||||||
{
|
|
||||||
switch (backdropImplementation)
|
|
||||||
{
|
|
||||||
case osgText::Text::POLYGON_OFFSET: return "POLYGON_OFFSET";
|
|
||||||
case osgText::Text::NO_DEPTH_BUFFER: return "NO_DEPTH_BUFFER";
|
|
||||||
case osgText::Text::DEPTH_RANGE: return "DEPTH_RANGE";
|
|
||||||
case osgText::Text::STENCIL_BUFFER: return "STENCIL_BUFFER";
|
|
||||||
default : return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
osgText::Text::ColorGradientMode convertColorGradientModeStringToEnum(std::string & str)
|
osgText::Text::ColorGradientMode convertColorGradientModeStringToEnum(std::string & str)
|
||||||
{
|
{
|
||||||
if (str=="SOLID") return osgText::Text::SOLID;
|
if (str=="SOLID") return osgText::Text::SOLID;
|
||||||
@ -155,12 +134,6 @@ bool Text_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
|||||||
// backdropImplementation
|
// backdropImplementation
|
||||||
if (fr[0].matchWord("backdropImplementation"))
|
if (fr[0].matchWord("backdropImplementation"))
|
||||||
{
|
{
|
||||||
std::string str = fr[1].getStr();
|
|
||||||
osgText::Text::BackdropImplementation backdropImplementation = convertBackdropImplementationStringToEnum(str);
|
|
||||||
|
|
||||||
if (backdropImplementation != static_cast<osgText::Text::BackdropImplementation>(-1))
|
|
||||||
text.setBackdropImplementation(backdropImplementation);
|
|
||||||
|
|
||||||
fr += 2;
|
fr += 2;
|
||||||
itAdvanced = true;
|
itAdvanced = true;
|
||||||
}
|
}
|
||||||
@ -254,9 +227,6 @@ bool Text_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
|||||||
osg::Vec4 c = text.getBackdropColor();
|
osg::Vec4 c = text.getBackdropColor();
|
||||||
fw.indent() << "backdropColor " << c.x() << " " << c.y() << " " << c.z() << " " << c.w() << std::endl;
|
fw.indent() << "backdropColor " << c.x() << " " << c.y() << " " << c.z() << " " << c.w() << std::endl;
|
||||||
|
|
||||||
// backdropImplementation
|
|
||||||
fw.indent() << "backdropImplementation " << convertBackdropImplementationEnumToString(text.getBackdropImplementation()) << std::endl;
|
|
||||||
|
|
||||||
// colorGradientMode
|
// colorGradientMode
|
||||||
fw.indent() << "colorGradientMode " << convertColorGradientModeEnumToString(text.getColorGradientMode()) << std::endl;
|
fw.indent() << "colorGradientMode " << convertColorGradientModeEnumToString(text.getColorGradientMode()) << std::endl;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user