diff --git a/examples/osgSSBO/osgSSBO.cpp b/examples/osgSSBO/osgSSBO.cpp index c058664be..e357acac8 100644 --- a/examples/osgSSBO/osgSSBO.cpp +++ b/examples/osgSSBO/osgSSBO.cpp @@ -473,7 +473,6 @@ void ComputeNode::addDataMonitor(osg::Vec3 placement, osg::Vec3 relativePlacemen pat->setName(labelCaption); text->setText(pat->getName()); text->setBackdropType(osgText::Text::OUTLINE); - text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET); text->setBackdropOffset(0.05f); text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); diff --git a/examples/osgfadetext/osgfadetext.cpp b/examples/osgfadetext/osgfadetext.cpp index 37b0eafe2..308b482b6 100644 --- a/examples/osgfadetext/osgfadetext.cpp +++ b/examples/osgfadetext/osgfadetext.cpp @@ -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(&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. - osgViewer::Viewer viewer; + osgViewer::Viewer viewer(arguments); viewer.getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES); viewer.getCamera()->setNearFarRatio(0.00001f); @@ -144,6 +204,12 @@ int main(int, char**) csn->addChild(createFadeText(csn->getEllipsoidModel())); } + if (arguments.argc()>1) + { + TextSettings textSettings(arguments); + root->accept(textSettings); + } + viewer.setCameraManipulator(new osgGA::TerrainManipulator); return viewer.run(); diff --git a/examples/osgfont/osgfont.cpp b/examples/osgfont/osgfont.cpp index 9255bea0c..bad750798 100644 --- a/examples/osgfont/osgfont.cpp +++ b/examples/osgfont/osgfont.cpp @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -56,80 +59,367 @@ osg::Camera* createOrthoCamera(double width, double height) return camera; } -osgText::Text* createLabel(const std::string& l, const char* f, unsigned int size) +typedef std::list 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()"< 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(); - osg::ref_ptr font = osgText::readRefFontFile(f); - label->setFont(font); - label->setCharacterSize(size); + settings.setText(*label); + + if (settings.scaleFontSizeToFontResolution) + { + label->setCharacterSize(size); + } + label->setFontResolution(size, size); - label->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); label->setPosition(pos); label->setAlignment(osgText::Text::LEFT_BOTTOM); // It seems to be important we do this last to get best results? label->setText(l); - textInfo(label); + // textInfo(label); - pos.y() += size + 10.0f; + pos.y() += label->getCharacterHeight()*2.0; return label; } -typedef std::list Sizes; +class KeyHandler : public osgGA::GUIEventHandler +{ +public: + + KeyHandler() {} + + ~KeyHandler() {} + + bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) + { + osgViewer::View* view = dynamic_cast(&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 "<removeDefine(define); + } + else + { + OSG_NOTICE<<"Enabling "<setDefine(define); + } + } +}; + int main(int argc, char** argv) { - osgViewer::Viewer viewer; osg::ArgumentParser args(&argc, argv); - - // Make sure we have the minimum args... - if(argc <= 2) - { - osg::notify(osg::FATAL) << "usage: " << args[0] << " fontfile size1 [size2 ...]" << std::endl; - - return 1; - } + osgViewer::Viewer viewer(args); - 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::WindowSizeHandler()); + viewer.addEventHandler(new KeyHandler()); - osg::Group* group = new osg::Group(); - osg::Camera* camera = createOrthoCamera(1280.0f, 1024.0f); + TextSettings settings; + settings.backgroundColor = viewer.getCamera()->getClearColor(); - // Create the list of desired sizes. - Sizes sizes; + settings.read(args); - for(int i = 2; i < argc; i++) + viewer.getCamera()->setClearColor(settings.backgroundColor); + + osg::ref_ptr 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 gc = viewer.getCamera()->getGraphicsContext(); + osg::ref_ptr traits = gc->getTraits(); + + // left half + { + osg::ref_ptr 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 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 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 program = new osg::Program; + std::string shaderFilename; + while(args.read("--shader", shaderFilename)) + { + osg::ref_ptr shader = osgDB::readRefShaderFile(shaderFilename); + if (shader.get()) + { + OSG_NOTICE<<"Loading shader "<addShader(shader.get()); + } + } + + if (program->getNumShaders()>0) + { + OSG_NOTICE<<"Using shaders"<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 geode = new osg::Geode(); + + osg::Vec3 pos(0.0f, 0.0f, 0.0f); // 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; 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 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(); } diff --git a/examples/osglauncher/osglauncher.cpp b/examples/osglauncher/osglauncher.cpp index 00c98b42c..ce7e4c553 100644 --- a/examples/osglauncher/osglauncher.cpp +++ b/examples/osglauncher/osglauncher.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -424,6 +425,9 @@ int main( int argc, char **argv ) // add the handler for doing the picking viewer.addEventHandler(new PickHandler(&viewer,updateText.get())); + // add the stats handler + viewer.addEventHandler(new osgViewer::StatsHandler); + osg::Group* root = new osg::Group(); root->addChild( setupGraph() ); diff --git a/examples/osglogo/osglogo.cpp b/examples/osglogo/osglogo.cpp index 18699462d..f5161c041 100644 --- a/examples/osglogo/osglogo.cpp +++ b/examples/osglogo/osglogo.cpp @@ -41,6 +41,9 @@ #include + +static bool s_useSDF = false; + class MyBillboardTransform : public osg::PositionAttitudeTransform { public: @@ -147,6 +150,12 @@ osg:: Node* createTextBelow(const osg::BoundingBox& bb, const std::string& label text->setFont(font); text->setFontResolution(64,64); + + if (s_useSDF) + { + text->setShaderTechnique(osgText::ALL_FEATURES); + } + text->setAlignment(osgText::Text::CENTER_CENTER); text->setAxisAlignment(osgText::Text::XZ_PLANE); 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->setFontResolution(110,120); + + if (s_useSDF) + { + text->setShaderTechnique(osgText::ALL_FEATURES); + } + text->setAlignment(osgText::Text::RIGHT_CENTER); text->setAxisAlignment(osgText::Text::XZ_PLANE); 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->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->setText(label); -#if 1 text->setBackdropType(osgText::Text::OUTLINE); -// text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); - - 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->setBackdropOffset(0.03f); text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.5f, 1.0f)); -#endif - -#if 1 text->setColorGradientMode(osgText::Text::OVERALL); osg::Vec4 lightblue(0.30f,0.6f,0.90f,1.0f); osg::Vec4 blue(0.10f,0.30f,0.40f,1.0f); text->setColorGradientCorners(lightblue, blue, blue, lightblue); -#else - text->setColorGradientMode(osgText::Text::OVERALL); - 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 + + text->setText(label); geode->addDrawable( text ); if (!subscript.empty()) { - //osgText::Text* subscript = new osgText::Text(new osgText::TextureFont(font,45)); - osgText::Text* subscriptText = new osgText::Text; subscriptText->setFont(font); 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::Geometry* geom = new osg::Geometry; osg::Vec3 normal = (corner-top)^(right-corner); @@ -475,6 +468,9 @@ int main( int argc, char **argv ) return 1; } + + while(arguments.read("--sdf")) { s_useSDF = true; } + std::string label = "OpenSceneGraph"; std::string subscript = ""; diff --git a/examples/osgtext/osgtext.cpp b/examples/osgtext/osgtext.cpp index b576dc76b..4f7972fe3 100644 --- a/examples/osgtext/osgtext.cpp +++ b/examples/osgtext/osgtext.cpp @@ -621,8 +621,8 @@ struct TextCounterCallback : public osg::NodeCallback if (text) { std::stringstream str; - str <<"Text Counter "<<_textCounter<setText(str.str()); @@ -670,7 +670,7 @@ int main(int argc, char** argv) text->setUpdateCallback(new TextCounterCallback()); text->setFont("fonts/times.ttf"); text->setAxisAlignment(osgText::Text::XZ_PLANE); - text->setText("This is a counter test"); + text->setText("Text Counter :"); viewer.setSceneData(text.get()); } diff --git a/examples/osgviewerCocoa/ViewerCocoa.mm b/examples/osgviewerCocoa/ViewerCocoa.mm index aded53820..84333c449 100644 --- a/examples/osgviewerCocoa/ViewerCocoa.mm +++ b/examples/osgviewerCocoa/ViewerCocoa.mm @@ -432,7 +432,6 @@ static void Internal_SetAlpha(NSBitmapImageRep *imageRep, unsigned char alpha_va default_text->setAlignment(osgText::Text::CENTER_CENTER); 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->setBackdropColor(osg::Vec4(0.0, 0.0, 0.0, 1.0)); default_text->setAxisAlignment(osgText::Text::XZ_PLANE); diff --git a/examples/osgwidgetlabel/osgwidgetlabel.cpp b/examples/osgwidgetlabel/osgwidgetlabel.cpp index 39d86fefe..a29320cdf 100644 --- a/examples/osgwidgetlabel/osgwidgetlabel.cpp +++ b/examples/osgwidgetlabel/osgwidgetlabel.cpp @@ -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->setLabel(l); - /* - text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); - text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER); - text->setBackdropOffset(0.2f); - */ - return label; } diff --git a/include/osg/DisplaySettings b/include/osg/DisplaySettings index 6821d14e9..0609cf0c6 100644 --- a/include/osg/DisplaySettings +++ b/include/osg/DisplaySettings @@ -20,6 +20,7 @@ #include #include +#include namespace osg { @@ -319,9 +320,15 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced SHADER_GLES3 }; - void setShaderHint(ShaderHint hint) { _shaderHint = hint; } + /** set the ShaderHint to tells shader generating cdoes version to create. + * By default also OSG_GLSL_VERSION and OSG_PRECISION_FLOAT values that can get use directly in shaders using $OSG_GLSL_VERSION and $OSG_PRECISION_FLOAT respectively.*/ + void setShaderHint(ShaderHint hint, bool setShaderValues=true); ShaderHint getShaderHint() const { return _shaderHint; } + /** Set the TextShaderTechnique that is used in the Text default constructor to choose which osgText::ShaderTechnique to use.*/ + void setTextShaderTechnique(const std::string& str) { _textShaderTechnique = str; } + const std::string& getTextShaderTechnique() const { return _textShaderTechnique; } + void setKeystoneHint(bool enabled) { _keystoneHint = enabled; } bool getKeystoneHint() const { return _keystoneHint; } @@ -358,6 +365,11 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced /** helper function for computing the right eye view matrix.*/ virtual osg::Matrixd computeRightEyeViewImplementation(const osg::Matrixd& view, double eyeSeperationScale=1.0) const; + + void setValue(const std::string& name, const std::string& value); + + bool getValue(const std::string& name, std::string& value, bool use_getenv_fallback=true) const; + protected: virtual ~DisplaySettings(); @@ -415,6 +427,7 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced VertexBufferHint _vertexBufferHint; ShaderHint _shaderHint; + std::string _textShaderTechnique; bool _keystoneHint; FileNames _keystoneFileNames; @@ -422,6 +435,11 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced OSXMenubarBehavior _OSXMenubarBehavior; + typedef std::map ValueMap; + + mutable OpenThreads::Mutex _valueMapMutex; + mutable ValueMap _valueMap; + }; } diff --git a/include/osg/State b/include/osg/State index ee5415660..97b6fec2a 100644 --- a/include/osg/State +++ b/include/osg/State @@ -823,9 +823,12 @@ class OSG_EXPORT State : public Referenced * during rendering. */ inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; } - /** Get the DisplaySettings */ + /** Get the const DisplaySettings */ inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); } + /** Get the const DisplaySettings that is current active DisplaySettings to be used by osg::State, - if DisplaySettings is not directly assigned then fallback to DisplaySettings::instance(). */ + inline const DisplaySettings* getActiveDisplaySettings() const { return _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance().get(); } + /** Set flag for early termination of the draw traversal.*/ diff --git a/include/osgText/Font b/include/osgText/Font index 952a6fda4..ab4641c93 100644 --- a/include/osgText/Font +++ b/include/osgText/Font @@ -27,6 +27,7 @@ namespace osgText { // forward declare Font class Font; +class TextBase; #ifdef OSG_PROVIDE_READFILE /** Read a font from specified file. The filename may contain a path. @@ -84,13 +85,9 @@ public: static osg::ref_ptr& getDefaultFont(); - void setTexEnv(osg::TexEnv* texenv) { if (texenv) _texenv = texenv; } - inline osg::TexEnv* getTexEnv() { return _texenv.get(); } - inline const osg::TexEnv* getTexEnv() const { return _texenv.get(); } - - void setStateSet(osg::StateSet* stateset) { _stateset = stateset; } - osg::StateSet* getStateSet() { return _stateset.get(); } - const osg::StateSet* getStateSet() const { return _stateset.get(); } + typedef std::vector< osg::ref_ptr > StateSets; + StateSets& getCachedStateSets() { return _statesets; } + const StateSets& getCachedStateSets() const { return _statesets; } /** Get a kerning (adjustment of spacing of two adjacent character) for specified charcodes and a font resolution.*/ @@ -110,19 +107,6 @@ public: * return true on success, return false when not supported.*/ virtual bool getVerticalSize(float& ascender, float& descender) const { return _implementation ? _implementation->getVerticalSize(ascender, descender) : false; } - /** Set the margin around each glyph, - * to ensure that texture filtering doesn't bleed adjacent glyph's into each other. - * Default margin is 1 texels.*/ - void setGlyphImageMargin(unsigned int margin); - unsigned int getGlyphImageMargin() const; - - /** Set the margin ratio around each glyph, relative to the glyph's size. - * to ensure that texture filtering doesn't bleed adjacent glyph's into each other. - * Default margin is 0.05.*/ - void setGlyphImageMarginRatio(float margin); - float getGlyphImageMarginRatio() const; - - /** Set the size of texture to create to store the glyph images when rendering. * Note, this doesn't affect already created Texture Glhph's.*/ void setTextureSizeHint(unsigned int width,unsigned int height); @@ -140,6 +124,9 @@ public: void setMagFilterHint(osg::Texture::FilterMode mode); osg::Texture::FilterMode getMagFilterHint() const; + void setMaxAnisotropy(float anis) { _maxAnisotropy = anis; } + float getMaxAnisotropy() const { return _maxAnisotropy; } + unsigned int getFontDepth() const { return _depth; } void setNumberCurveSamples(unsigned int numSamples) { _numCurveSamples = numSamples; } @@ -170,13 +157,14 @@ public: typedef std::vector< osg::ref_ptr > GlyphTextureList; GlyphTextureList& getGlyphTextureList() { return _glyphTextureList; } + void assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique); + protected: virtual ~Font(); void addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* glyph); - typedef std::vector< osg::ref_ptr > StateSetList; typedef std::map< unsigned int, osg::ref_ptr > GlyphMap; typedef std::map< unsigned int, osg::ref_ptr > Glyph3DMap; @@ -185,8 +173,7 @@ protected: mutable OpenThreads::Mutex _glyphMapMutex; - osg::ref_ptr _texenv; - osg::ref_ptr _stateset; + StateSets _statesets; FontSizeGlyphMap _sizeGlyphMap; GlyphTextureList _glyphTextureList; @@ -195,13 +182,12 @@ protected: // current active size of font FontResolution _fontSize; - unsigned int _margin; - float _marginRatio; unsigned int _textureWidthHint; unsigned int _textureHeightHint; osg::Texture::FilterMode _minFilterHint; osg::Texture::FilterMode _magFilterHint; + float _maxAnisotropy; unsigned int _depth; unsigned int _numCurveSamples; @@ -247,8 +233,6 @@ public: virtual bool getVerticalSize(float & /*ascender*/, float & /*descender*/) const { return false; } }; - - }; } diff --git a/include/osgText/Glyph b/include/osgText/Glyph index f08686841..2d1eafa05 100644 --- a/include/osgText/Glyph +++ b/include/osgText/Glyph @@ -30,15 +30,6 @@ #include -// GL_ALPHA is deprecated in GL3/GL4 core profile, use GL_RED and a shader in this case. See osgText example. -#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE) -#define OSGTEXT_GLYPH_FORMAT GL_RED -#define OSGTEXT_GLYPH_INTERNALFORMAT GL_R8 -#else -#define OSGTEXT_GLYPH_FORMAT GL_ALPHA -#define OSGTEXT_GLYPH_INTERNALFORMAT GL_ALPHA -#endif - namespace osgText { class Font; @@ -47,6 +38,14 @@ class Glyph3D; class GlyphGeometry; class GlyphTexture; +enum ShaderTechnique +{ + NO_TEXT_SHADER = 0x0, + GREYSCALE = 0x1, + SIGNED_DISTANCE_FIELD = 0x2, + ALL_FEATURES = GREYSCALE | SIGNED_DISTANCE_FIELD +}; + class OSGTEXT_EXPORT Glyph : public osg::Image { public: @@ -58,6 +57,9 @@ public: unsigned int getGlyphCode() const { return _glyphCode; } + void setFontResolution(const FontResolution& fontRes) { _fontResolution = fontRes; } + const FontResolution& getFontResolution() const { return _fontResolution; } + void setWidth(float width) { _width = width; } float getWidth() const { return _width; } @@ -76,21 +78,33 @@ public: void setVerticalAdvance(float advance); float getVerticalAdvance() const; - void setTexture(GlyphTexture* texture); - GlyphTexture* getTexture(); - const GlyphTexture* getTexture() const; + struct TextureInfo : public osg::Referenced + { + TextureInfo(): + texture(0), + texelMargin(0.0f) {} - void setTexturePosition(int posX,int posY); - int getTexturePositionX() const; - int getTexturePositionY() const; + TextureInfo(GlyphTexture* tex, int x, int y, const osg::Vec2& mintc, const osg::Vec2& maxtc, float margin): + texture(tex), + texturePositionX(x), + texturePositionY(y), + minTexCoord(mintc), + maxTexCoord(maxtc), + texelMargin(margin) {} - void setMinTexCoord(const osg::Vec2& coord); - const osg::Vec2& getMinTexCoord() const; + GlyphTexture* texture; + int texturePositionX; + int texturePositionY; + osg::Vec2 minTexCoord; + osg::Vec2 maxTexCoord; + float texelMargin; + }; - void setMaxTexCoord(const osg::Vec2& coord); - const osg::Vec2& getMaxTexCoord() const; + void setTextureInfo(ShaderTechnique technique, TextureInfo* info); - void subload() const; + const TextureInfo* getTextureInfo(ShaderTechnique technique) const; + + TextureInfo* getOrCreateTextureInfo(ShaderTechnique technique); protected: @@ -99,6 +113,8 @@ protected: Font* _font; unsigned int _glyphCode; + FontResolution _fontResolution; + float _width; float _height; @@ -108,15 +124,8 @@ protected: osg::Vec2 _verticalBearing; float _verticalAdvance; - GlyphTexture* _texture; - int _texturePosX; - int _texturePosY; - osg::Vec2 _minTexCoord; - osg::Vec2 _maxTexCoord; - - typedef osg::buffered_value GLObjectList; - mutable GLObjectList _globjList; - + typedef std::vector< osg::ref_ptr > TextureInfoList; + TextureInfoList _textureInfoList; }; class OSGTEXT_EXPORT GlyphGeometry : public osg::Referenced @@ -253,12 +262,13 @@ public: /** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/ virtual int compare(const osg::StateAttribute& rhs) const; - /** Set the margin around each glyph, to ensure that texture filtering doesn't bleed adjacent glyph's into each other.*/ - void setGlyphImageMargin(unsigned int margin) { _margin = margin; } - unsigned int getGlyphImageMargin() const { return _margin; } + void setShaderTechnique(ShaderTechnique technique) { _shaderTechnique = technique; } - void setGlyphImageMarginRatio(float margin) { _marginRatio = margin; } - float getGlyphImageMarginRatio() const { return _marginRatio; } + ShaderTechnique getShaderTechnique() const { return _shaderTechnique; } + + + int getEffectMargin(const Glyph* glyph); + int getTexelMargin(const Glyph* glyph); bool getSpaceForGlyph(Glyph* glyph, int& posX, int& posY); @@ -277,14 +287,13 @@ protected: virtual ~GlyphTexture(); + void copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info); - // parameter used to compute the size and position of empty space - // in the texture which could accommodate new glyphs. - int _margin; - float _marginRatio; - int _usedY; - int _partUsedX; - int _partUsedY; + ShaderTechnique _shaderTechnique; + + int _usedY; + int _partUsedX; + int _partUsedY; typedef std::vector< osg::ref_ptr > GlyphRefList; typedef std::vector< const Glyph* > GlyphPtrList; diff --git a/include/osgText/Text b/include/osgText/Text index db497792f..ab5e547a0 100644 --- a/include/osgText/Text +++ b/include/osgText/Text @@ -36,15 +36,12 @@ public: virtual const char* className() const { return "Text"; } virtual const char* libraryName() const { return "osgText"; } - virtual void setFont(Font* font=0) { setFont(osg::ref_ptr(font)); }; + /** Set the ShaderTechnique hint to specify what fatures in the text shaders to enable.*/ + void setShaderTechnique(ShaderTechnique technique); - /** Set the Font to use to render the text.*/ - virtual void setFont(osg::ref_ptr font); + /** Get the ShaderTechnique hint.*/ + ShaderTechnique getShaderTechnique() { return _shaderTechnique; } - /** Set the font, loaded from the specified front file, to use to render the text, - * setFont("") sets the use of the default font. - * See the osgText::readFontFile function for how the font file will be located. */ - virtual void setFont(const std::string& fontfile) { TextBase::setFont(fontfile); } /** * Turns off writing to the depth buffer when rendering text. This only affects text @@ -70,31 +67,6 @@ public: NONE }; - enum BackdropImplementation - { - /* No longer supported, naps to DELAYED_DEPTH_WRITES.*/ - POLYGON_OFFSET = 0, - - /* No longer supported, naps to DELAYED_DEPTH_WRITES.*/ - NO_DEPTH_BUFFER, - - /* No longer supported, naps to DELAYED_DEPTH_WRITES.*/ - DEPTH_RANGE, - - /* No longer supported, naps to DELAYED_DEPTH_WRITES.*/ - STENCIL_BUFFER, - - /* DELAYED_DEPTH_WRITES - * This mode renders all text with depth writes turned off, then - * again with depth writes on, but with the color buffer disabled. - * This should render text accurately for all graphics cards. The - * only downside is the additional pass to render to the depth - * buffer. But if you don't need the depth buffer updated for - * your, this extra pass can be disabled by calling - * enableDepthWrites(false).*/ - DELAYED_DEPTH_WRITES - }; - /** * BackdropType gives you a background shadow text behind your regular * text. This helps give text extra contrast which can be useful when @@ -149,18 +121,6 @@ public: const osg::Vec4& getBackdropColor() const { return _backdropColor; } - /** - * This specifies the underlying backdrop rendering implementation. - * Unfortunately, at this time, there is no "perfect" rendering solution - * so this function is provided to let you 'pick your poison'. Each - * implementation has trade-offs. See BackdropImplementation enum - * docs for details.*/ - void setBackdropImplementation(BackdropImplementation implementation); - - BackdropImplementation getBackdropImplementation() const { return _backdropImplementation; } - - - enum ColorGradientMode { SOLID = 0, // a.k.a. ColorGradients off @@ -232,6 +192,20 @@ public: public: + /** deprecated, value ignored.*/ + enum BackdropImplementation + { + POLYGON_OFFSET = 0, + NO_DEPTH_BUFFER, + DEPTH_RANGE, + STENCIL_BUFFER, + DELAYED_DEPTH_WRITES + }; + + /** deprecated, value ignored.*/ + void setBackdropImplementation(BackdropImplementation) {} + /** deprecated, value should be ignored.*/ + BackdropImplementation getBackdropImplementation() const { return DELAYED_DEPTH_WRITES; } // internal structures, variable and methods used for rendering of characters. struct OSGTEXT_EXPORT GlyphQuads @@ -239,7 +213,7 @@ public: typedef std::vector Glyphs; Glyphs _glyphs; - Primitives _primitives; + osg::ref_ptr _primitives; GlyphQuads(); GlyphQuads(const GlyphQuads& gq); @@ -284,6 +258,8 @@ protected: virtual ~Text(); + virtual osg::StateSet* createStateSet(); + Font* getActiveFont(); const Font* getActiveFont() const; @@ -302,7 +278,6 @@ protected: virtual void computePositionsImplementation(); - void computeBackdropPositions(); void computeBackdropBoundingBox(); void computeBoundingBoxMargin(); @@ -314,10 +289,10 @@ protected: void drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const; + ShaderTechnique _shaderTechnique; bool _enableDepthWrites; BackdropType _backdropType; - BackdropImplementation _backdropImplementation; float _backdropHorizontalOffset; float _backdropVerticalOffset; diff --git a/include/osgText/TextBase b/include/osgText/TextBase index 64fe785f1..d75e41ff2 100644 --- a/include/osgText/TextBase +++ b/include/osgText/TextBase @@ -53,6 +53,9 @@ public: virtual void setFont(const std::string& fontfile); /** Get the font. Return 0 if default is being used.*/ + Font* getFont() { return _font.get(); } + + /** Get the const font. Return 0 if default is being used.*/ const Font* getFont() const { return _font.get(); } @@ -284,6 +287,10 @@ protected: virtual ~TextBase(); + virtual osg::StateSet* createStateSet(); + + virtual void assignStateSet(); + void initArraysAndBuffers(); osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo) const; diff --git a/include/osgUtil/GLObjectsVisitor b/include/osgUtil/GLObjectsVisitor index b9a130f3e..c52d6cce6 100644 --- a/include/osgUtil/GLObjectsVisitor +++ b/include/osgUtil/GLObjectsVisitor @@ -97,6 +97,9 @@ class OSGUTIL_EXPORT GLObjectsVisitor : public osg::NodeVisitor void apply(osg::Drawable& drawable); void apply(osg::StateSet& stateset); + /** Do a compile traversal and then reset any state,*/ + void compile(osg::Node& node); + protected: typedef std::set DrawableAppliedSet; diff --git a/src/osg/DisplaySettings.cpp b/src/osg/DisplaySettings.cpp index 1df3e7e89..5e7259956 100644 --- a/src/osg/DisplaySettings.cpp +++ b/src/osg/DisplaySettings.cpp @@ -118,7 +118,8 @@ void DisplaySettings::setDisplaySettings(const DisplaySettings& vs) _swapMethod = vs._swapMethod; _vertexBufferHint = vs._vertexBufferHint; - _shaderHint = vs._shaderHint; + + setShaderHint(_shaderHint); _keystoneHint = vs._keystoneHint; _keystoneFileNames = vs._keystoneFileNames; @@ -250,23 +251,17 @@ void DisplaySettings::setDefaults() // _vertexBufferHint = VERTEX_ARRAY_OBJECT; #if defined(OSG_GLES3_AVAILABLE) - _shaderHint = SHADER_GLES3; - OSG_INFO<<"DisplaySettings::SHADER_GLES3"<", "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 ", + "Set the defafult osgText::ShaderTechnique. ALL_FEATURES | ALL | GREYSCALE | SIGNED_DISTANCE_FIELD | SDF | NO_TEXT_SHADER | NONE"); void DisplaySettings::readEnvironmentalVariables() { @@ -725,26 +723,30 @@ void DisplaySettings::readEnvironmentalVariables() { if (strcmp(ptr,"GL2")==0) { - _shaderHint = SHADER_GL2; + setShaderHint(SHADER_GL2); } else if (strcmp(ptr,"GL3")==0) { - _shaderHint = SHADER_GL3; + setShaderHint(SHADER_GL3); } else if (strcmp(ptr,"GLES2")==0) { - _shaderHint = SHADER_GLES2; + setShaderHint(SHADER_GLES2); } else if (strcmp(ptr,"GLES3")==0) { - _shaderHint = SHADER_GLES3; + setShaderHint(SHADER_GLES3); } 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) { @@ -1098,3 +1100,84 @@ osg::Matrixd DisplaySettings::computeRightEyeViewImplementation(const osg::Matri 0.0,0.0,1.0,0.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"< lock(_valueMapMutex); + + _valueMap[name] = value; +} + +bool DisplaySettings::getValue(const std::string& name, std::string& value, bool use_getenv_fallback) const +{ + OpenThreads::ScopedLock lock(_valueMapMutex); + + ValueMap::iterator itr = _valueMap.find(name); + if (itr!=_valueMap.end()) + { + value = itr->second; + OSG_INFO<<"DisplaySettings::getValue("<getShaderSource(); - if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms())) + // if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms())) { 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; - // OSG_NOTICE<<"Compiling PerContextShader "<getTypename() + << " source:\n" << sourceWithLineNumbers << std::endl; + } } else { @@ -690,21 +690,40 @@ void Shader::PerContextShader::compileShader(osg::State& state) if (!versionLine.empty()) { - // OSG_NOTICE<<"Shader::PerContextShader::compileShader() : Found #version, lineNum = "<(versionLine.c_str()); sourceText[1] = reinterpret_cast(_defineStr.c_str()); sourceText[2] = reinterpret_cast(source.c_str()); _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 : ["<(_defineStr.c_str()); sourceText[1] = reinterpret_cast(source.c_str()); _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 : ["<glCompileShader( _glShaderHandle ); diff --git a/src/osg/State.cpp b/src/osg/State.cpp index c652d4cc6..05933aa30 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -1216,13 +1216,69 @@ namespace State_Utils 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 (posgetGlyphImageMargin() + (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("<getTextureWidthHint()-2*margin; - height = _facade->getTextureHeightHint()-2*margin; - - OSG_WARN<<" sizes capped ("< glyph = new osgText::Glyph(_facade, charcode); + glyph->setFontResolution(fontRes); + unsigned int dataSize = width*height; 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;psetImage(width,height,1, - OSGTEXT_GLYPH_INTERNALFORMAT, - OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, + GL_ALPHA, + GL_ALPHA, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); - glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT); - // copy image across to osgText::Glyph image. switch(glyphslot->bitmap.pixel_mode) { diff --git a/src/osgPlugins/ive/Text.cpp b/src/osgPlugins/ive/Text.cpp index ae9da298f..0139695c5 100644 --- a/src/osgPlugins/ive/Text.cpp +++ b/src/osgPlugins/ive/Text.cpp @@ -90,7 +90,7 @@ void Text::write(DataOutputStream* out){ out->writeFloat(getBackdropVerticalOffset()); out->writeVec4(getBackdropColor()); - out->writeUInt(getBackdropImplementation()); + out->writeUInt(4); // old DELAYED_DEPTH_WRITES out->writeUInt(getColorGradientMode()); out->writeVec4(getColorGradientTopLeft()); @@ -213,7 +213,7 @@ void Text::read(DataInputStream* in){ setBackdropOffset(horizontalOffset,verticalOffset); setBackdropColor(in->readVec4()); - setBackdropImplementation((osgText::Text::BackdropImplementation) in->readUInt()); + in->readUInt(); // read old BackdropImplementation value, no longer used setColorGradientMode((osgText::Text::ColorGradientMode) in->readUInt()); osg::Vec4 colorGradientTopLeft,colorGradientBottomLeft,colorGradientBottomRight,colorGradientTopRight; diff --git a/src/osgText/DefaultFont.cpp b/src/osgText/DefaultFont.cpp index cf0b55cc4..dfc9b5945 100644 --- a/src/osgText/DefaultFont.cpp +++ b/src/osgText/DefaultFont.cpp @@ -24,8 +24,11 @@ using namespace osgText; DefaultFont::DefaultFont() { + _fontSize = FontResolution(8,12); + _minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR; - _magFilterHint = osg::Texture::NEAREST; + _magFilterHint = osg::Texture::LINEAR; + constructGlyphs(); } @@ -198,14 +201,12 @@ void DefaultFont::constructGlyphs() for(unsigned char* p=data;psetImage(sourceWidth,sourceHeight,1, - OSGTEXT_GLYPH_INTERNALFORMAT, - OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, + GL_ALPHA, + GL_ALPHA, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); - glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT); - // now populate data array by converting bitmap into a luminance_alpha map. unsigned char* ptr = rasters[i-32]; unsigned char value_on = 255; @@ -233,6 +234,8 @@ void DefaultFont::constructGlyphs() glyph->setVerticalBearing(osg::Vec2(0.5f,1.0f)); // top middle. glyph->setVerticalAdvance(sourceHeight*coord_scale); + glyph->setFontResolution(fontRes); + addGlyph(fontRes,i,glyph.get()); } } diff --git a/src/osgText/Font.cpp b/src/osgText/Font.cpp index c06392640..599dd6f6e 100644 --- a/src/osgText/Font.cpp +++ b/src/osgText/Font.cpp @@ -32,81 +32,6 @@ using namespace osgText; using namespace std; -#if (!defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)) - #define GLSL_VERSION_STR "330 core" - #define GLYPH_CMP "r" -#else - #define GLSL_VERSION_STR "300 es" - #define GLYPH_CMP "a" -#endif - -static const char* gl3_TextVertexShader = { - "#version " GLSL_VERSION_STR "\n" - "// gl3_TextVertexShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "in vec4 osg_Vertex;\n" - "in vec4 osg_Color;\n" - "in vec4 osg_MultiTexCoord0;\n" - "uniform mat4 osg_ModelViewProjectionMatrix;\n" - "out vec2 texCoord;\n" - "out vec4 vertexColor;\n" - "void main(void)\n" - "{\n" - " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex;\n" - " texCoord = osg_MultiTexCoord0.xy;\n" - " vertexColor = osg_Color; \n" - "}\n" -}; - -static const char* gl3_TextFragmentShader = { - "#version " GLSL_VERSION_STR "\n" - "// gl3_TextFragmentShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "uniform sampler2D glyphTexture;\n" - "in vec2 texCoord;\n" - "in vec4 vertexColor;\n" - "out vec4 color;\n" - "void main(void)\n" - "{\n" - " if (texCoord.x>=0.0) color = vertexColor * vec4(1.0, 1.0, 1.0, texture(glyphTexture, texCoord)." GLYPH_CMP ");\n" - " else color = vertexColor;\n" - "}\n" -}; - -static const char* gl2_TextVertexShader = { - "// gl2_TextVertexShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "varying vec2 texCoord;\n" - "varying vec4 vertexColor;\n" - "void main(void)\n" - "{\n" - " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" - " texCoord = gl_MultiTexCoord0.xy;\n" - " vertexColor = gl_Color; \n" - "}\n" -}; - -static const char* gl2_TextFragmentShader = { - "// gl2_TextFragmentShader\n" - "#ifdef GL_ES\n" - " precision highp float;\n" - "#endif\n" - "uniform sampler2D glyphTexture;\n" - "varying vec2 texCoord;\n" - "varying vec4 vertexColor;\n" - "void main(void)\n" - "{\n" - " if (texCoord.x>=0.0) gl_FragColor = vertexColor * vec4(1.0, 1.0, 1.0, texture2D(glyphTexture, texCoord).a);\n" - " else gl_FragColor = vertexColor;\n" - "}\n" -}; - osg::ref_ptr& Font::getDefaultFont() { static OpenThreads::Mutex s_DefaultFontMutex; @@ -299,67 +224,24 @@ osg::ref_ptr osgText::readRefFontStream(std::istream& stream, const osgDB: Font::Font(FontImplementation* implementation): osg::Object(true), - _margin(1), - _marginRatio(0.02), _textureWidthHint(1024), _textureHeightHint(1024), _minFilterHint(osg::Texture::LINEAR_MIPMAP_LINEAR), _magFilterHint(osg::Texture::LINEAR), + _maxAnisotropy(16), _depth(1), _numCurveSamples(10) { setImplementation(implementation); - _texenv = new osg::TexEnv; - _stateset = new osg::StateSet; - - _stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - _stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - _stateset->setMode(GL_BLEND, osg::StateAttribute::ON); - -#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE) - - OSG_INFO<<"Font::Font() Fixed function pipeline"<setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); -#endif - - osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint(); - if (shaderHint==osg::DisplaySettings::SHADER_GL3 || shaderHint==osg::DisplaySettings::SHADER_GLES3) - { - - OSG_INFO<<"Font::Font() Setting up GL3 compatible shaders"< program = new osg::Program; - program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3_TextVertexShader)); - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl3_TextFragmentShader)); - _stateset->setAttributeAndModes(program.get()); - _stateset->addUniform(new osg::Uniform("glyphTexture", 0)); - - } - else if (shaderHint==osg::DisplaySettings::SHADER_GL2 || shaderHint==osg::DisplaySettings::SHADER_GLES2) - { - - - OSG_INFO<<"Font::Font() Setting up GL2 compatible shaders"< program = new osg::Program; - program->addShader(new osg::Shader(osg::Shader::VERTEX, gl2_TextVertexShader)); - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl2_TextFragmentShader)); - _stateset->setAttributeAndModes(program.get()); - _stateset->addUniform(new osg::Uniform("glyphTexture", 0)); - - } - char *ptr; - if( (ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0) + if ((ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0) { unsigned int osg_max_size = atoi(ptr); if (osg_max_size<_textureWidthHint) _textureWidthHint = osg_max_size; if (osg_max_size<_textureHeightHint) _textureHeightHint = osg_max_size; } - } Font::~Font() @@ -390,26 +272,6 @@ std::string Font::getFileName() const 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) { _textureWidthHint = width; @@ -518,9 +380,6 @@ void Font::setThreadSafeRefUnref(bool threadSafe) { osg::Object::setThreadSafeRefUnref(threadSafe); - if (_texenv.valid()) _texenv->setThreadSafeRefUnref(threadSafe); - if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe); - for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); ++itr) @@ -531,7 +390,12 @@ void Font::setThreadSafeRefUnref(bool threadSafe) void Font::resizeGLObjectBuffers(unsigned int maxSize) { - if (_stateset.valid()) _stateset->resizeGLObjectBuffers(maxSize); + for(StateSets::iterator itr = _statesets.begin(); + itr != _statesets.end(); + ++itr) + { + (*itr)->resizeGLObjectBuffers(maxSize); + } for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); @@ -543,7 +407,12 @@ void Font::resizeGLObjectBuffers(unsigned int maxSize) void Font::releaseGLObjects(osg::State* state) const { - if (_stateset.valid()) _stateset->releaseGLObjects(state); + for(StateSets::const_iterator itr = _statesets.begin(); + itr != _statesets.end(); + ++itr) + { + (*itr)->releaseGLObjects(state); + } for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin(); itr!=_glyphTextureList.end(); @@ -576,6 +445,10 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* _sizeGlyphMap[fontRes][charcode]=glyph; +} + +void Font::assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique) +{ int posX=0,posY=0; GlyphTexture* glyphTexture = 0; @@ -583,12 +456,12 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* itr!=_glyphTextureList.end() && !glyphTexture; ++itr) { - if ((*itr)->getSpaceForGlyph(glyph,posX,posY)) glyphTexture = itr->get(); + if ((*itr)->getShaderTechnique()==shaderTechnique && (*itr)->getSpaceForGlyph(glyph,posX,posY)) glyphTexture = itr->get(); } if (glyphTexture) { - //cout << " found space for texture "<setGlyphImageMargin(_margin); - glyphTexture->setGlyphImageMarginRatio(_marginRatio); + glyphTexture->setShaderTechnique(shaderTechnique); glyphTexture->setTextureSize(_textureWidthHint,_textureHeightHint); glyphTexture->setFilter(osg::Texture::MIN_FILTER,_minFilterHint); glyphTexture->setFilter(osg::Texture::MAG_FILTER,_magFilterHint); - glyphTexture->setMaxAnisotropy(8); + glyphTexture->setMaxAnisotropy(_maxAnisotropy); _glyphTextureList.push_back(glyphTexture); @@ -621,5 +493,4 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* // add the glyph into the texture. glyphTexture->addGlyph(glyph,posX,posY); - } diff --git a/src/osgText/Glyph.cpp b/src/osgText/Glyph.cpp index 3bc346c8f..09c166cf6 100644 --- a/src/osgText/Glyph.cpp +++ b/src/osgText/Glyph.cpp @@ -28,9 +28,34 @@ using namespace osgText; 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(): - _margin(1), - _marginRatio(0.02f), _usedY(0), _partUsedX(0), _partUsedY(0) @@ -51,27 +76,52 @@ int GlyphTexture::compare(const osg::StateAttribute& rhs) const 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) { - int maxAxis = osg::maximum(glyph->s(), glyph->t()); - int margin = _margin + (int)((float)maxAxis * _marginRatio); + int width = glyph->s(); + int height = glyph->t(); - int width = glyph->s()+2*margin; - int height = glyph->t()+2*margin; + int margin = getTexelMargin(glyph); - // first check box (_partUsedX,_usedY) to (width,height) - if (width <= (getTextureWidth()-_partUsedX) && - height <= (getTextureHeight()-_usedY)) + width += 2*margin; + height += 2*margin; + + 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. // record the position in which the texture will be stored. - posX = _partUsedX+margin; - posY = _usedY+margin; + posX = partUsedX+margin; + posY = usedY+margin; // move used markers on. - _partUsedX += width; + _partUsedX = posX+width; if (_usedY+height>_partUsedY) _partUsedY = _usedY+height; return true; @@ -83,14 +133,14 @@ bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY) { // can fit next row. _partUsedX = 0; - _usedY = _partUsedY; + _usedY = partUsedY; posX = _partUsedX+margin; posY = _usedY+margin; // move used markers on. - _partUsedX += width; - if (_usedY+height>_partUsedY) _partUsedY = _usedY+height; + _partUsedX = posX+width; + _partUsedY = _usedY+height; return true; } @@ -101,23 +151,237 @@ bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY) void GlyphTexture::addGlyph(Glyph* glyph, int posX, int posY) { + OpenThreads::ScopedLock lock(_mutex); if (!_image.valid()) createImage(); _glyphs.push_back(glyph); - // set up the details of where to place glyph's image in the texture. - glyph->setTexture(this); - glyph->setTexturePosition(posX,posY); + osg::ref_ptr info = new Glyph::TextureInfo( + this, + posX, posY, + osg::Vec2( static_cast(posX)/static_cast(getTextureWidth()), static_cast(posY)/static_cast(getTextureHeight()) ), // minTexCoord + osg::Vec2( static_cast(posX+glyph->s())/static_cast(getTextureWidth()), static_cast(posY+glyph->t())/static_cast(getTextureHeight()) ), // maxTexCoord + float(getTexelMargin(glyph))); // margin - glyph->setMinTexCoord( osg::Vec2( static_cast(posX)/static_cast(getTextureWidth()), - static_cast(posY)/static_cast(getTextureHeight()) ) ); - glyph->setMaxTexCoord( osg::Vec2( static_cast(posX+glyph->s())/static_cast(getTextureWidth()), - static_cast(posY+glyph->t())/static_cast(getTextureHeight()) ) ); + glyph->setTextureInfo(_shaderTechnique, info.get()); - _image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph); + copyGlyphImage(glyph, info); +} + +void GlyphTexture::copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info) +{ _image->dirty(); + + if (_shaderTechnique<=GREYSCALE) + { + // OSG_NOTICE<<"GlyphTexture::copyGlyphImage() greyscale copying. glyphTexture="<get(); - _image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph); - } + _image = new osg::Image; + + GLenum imageFormat = (_shaderTechnique<=GREYSCALE) ? OSGTEXT_GLYPH_ALPHA_FORMAT : OSGTEXT_GLYPH_SDF_FORMAT; + GLenum internalFormat = (_shaderTechnique<=GREYSCALE) ? OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT : OSGTEXT_GLYPH_SDF_INTERNALFORMAT; + + _image->allocateImage(getTextureWidth(), getTextureHeight(), 1, imageFormat, GL_UNSIGNED_BYTE); + _image->setInternalTextureFormat(internalFormat); + + memset(_image->data(), 0, _image->getTotalSizeInBytes()); } 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. Glyph::Glyph(Font* font, unsigned int glyphCode): _font(font), @@ -172,12 +440,7 @@ Glyph::Glyph(Font* font, unsigned int glyphCode): _horizontalBearing(0.0f,0.f), _horizontalAdvance(0.f), _verticalBearing(0.0f,0.f), - _verticalAdvance(0.f), - _texture(0), - _texturePosX(0), - _texturePosY(0), - _minTexCoord(0.0f,0.0f), - _maxTexCoord(0.0f,0.0f) + _verticalAdvance(0.f) { setThreadSafeRefUnref(true); } @@ -198,67 +461,37 @@ const osg::Vec2& Glyph::getVerticalBearing() const { return _verticalBearing; } void Glyph::setVerticalAdvance(float advance) { _verticalAdvance=advance; } float Glyph::getVerticalAdvance() const { return _verticalAdvance; } -void Glyph::setTexture(GlyphTexture* texture) { _texture = texture; } -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 +void Glyph::setTextureInfo(ShaderTechnique technique, TextureInfo* info) { - GLenum errorNo = glGetError(); - if (errorNo!=GL_NO_ERROR) + if (technique>=_textureInfoList.size()) { - const GLubyte* msg = osg::gluErrorString(errorNo); - if (msg) { OSG_WARN<<"before Glyph::subload(): detected OpenGL error: "<(data())<<");"<=_textureInfoList.size()) + { + _textureInfoList.resize(technique+1); + } + if (!_textureInfoList[technique]) + { + _font->assignGlyphToGlyphTexture(this, technique); + } + return _textureInfoList[technique].get(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Glyph3D +// Glyph3D::Glyph3D(Font* font, unsigned int glyphCode): osg::Referenced(true), _font(font), diff --git a/src/osgText/Text.cpp b/src/osgText/Text.cpp index 53a5d3b1a..46c857639 100644 --- a/src/osgText/Text.cpp +++ b/src/osgText/Text.cpp @@ -25,13 +25,19 @@ #include +#include +#include + +#define DEBUG_MESSAGE_LEVEL osg::INFO +#define DEBUG_MESSAGE osg::notify(DEBUG_MESSAGE_LEVEL) + using namespace osg; using namespace osgText; Text::Text(): + _shaderTechnique(GREYSCALE), _enableDepthWrites(true), _backdropType(NONE), - _backdropImplementation(DELAYED_DEPTH_WRITES), _backdropHorizontalOffset(0.07f), _backdropVerticalOffset(0.07f), _backdropColor(0.0f, 0.0f, 0.0f, 1.0f), @@ -42,13 +48,24 @@ Text::Text(): _colorGradientTopRight(1.0f, 1.0f, 1.0f, 1.0f) { _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): osgText::TextBase(text,copyop), + _shaderTechnique(text._shaderTechnique), _enableDepthWrites(text._enableDepthWrites), _backdropType(text._backdropType), - _backdropImplementation(text._backdropImplementation), _backdropHorizontalOffset(text._backdropHorizontalOffset), _backdropVerticalOffset(text._backdropVerticalOffset), _backdropColor(text._backdropColor), @@ -65,21 +82,170 @@ Text::~Text() { } -void Text::setFont(osg::ref_ptr font) + +void Text::setShaderTechnique(ShaderTechnique technique) { - if (_font==font) return; + if (_shaderTechnique==technique) return; - osg::StateSet* previousFontStateSet = _font.valid() ? _font->getStateSet() : Font::getDefaultFont()->getStateSet(); - osg::StateSet* newFontStateSet = font.valid() ? font->getStateSet() : Font::getDefaultFont()->getStateSet(); + _shaderTechnique = technique; - if (getStateSet() == previousFontStateSet) - { - setStateSet( newFontStateSet ); - } + assignStateSet(); - TextBase::setFont(font); + computeGlyphRepresentation(); } +osg::StateSet* Text::createStateSet() +{ + Font* activeFont = getActiveFont(); + if (!activeFont) return 0; + + Font::StateSets& statesets = activeFont->getCachedStateSets(); + + std::stringstream ss; + ss<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:"<first<<"] = "<second.first<getDefineList()==defineList) + { + // OSG_NOTICE<<"Text::createStateSet() : Matched DefineList, return StateSet "<get()<get(); + } + else + { + } + } + } + + + if (osg::isNotifyEnabled(DEBUG_MESSAGE_LEVEL)) + { + DEBUG_MESSAGE<<"Text::createStateSet() ShaderTechnique "; + switch(_shaderTechnique) + { + case(NO_TEXT_SHADER) : DEBUG_MESSAGE<<"NO_TEXT_SHADER"< 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"<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 program = new osg::Program; + stateset->setAttributeAndModes(program.get()); + + { + DEBUG_MESSAGE<<"Using shaders/text.vert"<addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/text.vert", text_vert)); + } + + { + DEBUG_MESSAGE<<"Using shaders/text.frag"<addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/text.frag", text_frag)); + } + + return stateset.release(); +} 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) { // 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); - osg::DrawElements* primitives = 0; - if (glyphquad._primitives.empty()) + osg::DrawElements* primitives = glyphquad._primitives.get(); + if (!primitives) { unsigned int maxIndices = _text.size()*4; if (maxIndices>=16384) primitives = new osg::DrawElementsUInt(GL_TRIANGLES); else primitives = new osg::DrawElementsUShort(GL_TRIANGLES); primitives->setBufferObject(_ebo.get()); - glyphquad._primitives.push_back(primitives); - } - else - { - primitives = glyphquad._primitives[0].get(); + glyphquad._primitives = primitives; } @@ -280,25 +444,18 @@ void Text::computeGlyphRepresentation() if (!_texcoords) { _texcoords = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); _texcoords->setBufferObject(_vbo.get()); } else _texcoords->clear(); -#if 0 - _textureGlyphQuadMap.clear(); -#else for(TextureGlyphQuadMap::iterator itr = _textureGlyphQuadMap.begin(); itr != _textureGlyphQuadMap.end(); ++itr) { GlyphQuads& glyphquads = itr->second; glyphquads._glyphs.clear(); - for(Primitives::iterator pitr = glyphquads._primitives.begin(); - pitr != glyphquads._primitives.end(); - ++pitr) + if (glyphquads._primitives.valid()) { - (*pitr)->resizeElements(0); - (*pitr)->dirty(); + glyphquads._primitives->resizeElements(0); + glyphquads._primitives->dirty(); } } -#endif - _lineCount = 0; @@ -487,45 +644,53 @@ void Text::computeGlyphRepresentation() local.x() += bearing.x() * wr; local.y() += bearing.y() * hr; - - // Adjust coordinates and texture coordinates to avoid - // clipping the edges of antialiased characters. - osg::Vec2 mintc = glyph->getMinTexCoord(); - osg::Vec2 maxtc = glyph->getMaxTexCoord(); - osg::Vec2 vDiff = maxtc - mintc; - - float 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) + const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique); + if (info) { - case LEFT_TO_RIGHT: - cursor.x() += glyph->getHorizontalAdvance() * wr; - _textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner - _textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner - break; - case VERTICAL: - cursor.y() -= glyph->getVerticalAdvance() * hr; - _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner - _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner - break; - case RIGHT_TO_LEFT: - _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner - _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner - break; + // Adjust coordinates and texture coordinates to avoid + // clipping the edges of antialiased characters. + osg::Vec2 mintc = info->minTexCoord; + osg::Vec2 maxtc = info->maxTexCoord; + osg::Vec2 vDiff = maxtc - mintc; + float texelMargin = info->texelMargin; + + float fHorizTCMargin = texelMargin / info->texture->getTextureWidth(); + float fVertTCMargin = texelMargin / info->texture->getTextureHeight(); + float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x(); + float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y(); + + mintc.x() -= fHorizTCMargin; + mintc.y() -= fVertTCMargin; + maxtc.x() += fHorizTCMargin; + maxtc.y() += fVertTCMargin; + osg::Vec2 minc = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin); + osg::Vec2 maxc = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin); + + addGlyphQuad(glyph, minc, maxc, mintc, maxtc); + + // move the cursor onto the next character. + // also expand bounding box + switch(_layout) + { + case LEFT_TO_RIGHT: + cursor.x() += glyph->getHorizontalAdvance() * wr; + _textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner + _textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner + break; + case VERTICAL: + cursor.y() -= glyph->getVerticalAdvance() * hr; + _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner + _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner + break; + case RIGHT_TO_LEFT: + _textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner + _textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner + break; + } + } + else + { + OSG_NOTICE<<"No TextureInfo for "<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;isize(); - (*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 assumes that the bounding box has already been computed for the text without the backdrop. 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 { + if (colorMultiplier.a()==0.0f || _color.a()==0.0f) return; + osg::VertexArrayState* vas = state.getCurrentVertexArrayState(); bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); bool usingVertexArrayObjects = usingVertexBufferObjects && state.useVertexArrayObject(_useVertexArrayObject); @@ -1117,7 +1141,6 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo } if (_drawMode & TEXT) -// if (false) { for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); @@ -1128,33 +1151,6 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo const GlyphQuads& glyphquad = titr->second; -#if 1 - if(_backdropType != NONE) - { - unsigned int backdrop_index; - unsigned int max_backdrop_index; - if(_backdropType == OUTLINE) - { - 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) { 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); } -#if 0 - drawImplementationSinglePass(state, colorMultiplier); -#else glDepthMask(GL_FALSE); drawImplementationSinglePass(state, colorMultiplier); @@ -1235,7 +1228,6 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie } state.haveAppliedAttribute(osg::StateAttribute::DEPTH); -#endif if (usingVertexBufferObjects && !usingVertexArrayObjects) { @@ -1273,16 +1265,16 @@ void Text::accept(osg::PrimitiveFunctor& pf) const ++titr) { const GlyphQuads& glyphquad = titr->second; - if (!glyphquad._primitives.empty()) + if (glyphquad._primitives.valid()) { - const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast(glyphquad._primitives[0].get()); + const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast(glyphquad._primitives.get()); if (drawElementsUShort) { pf.drawElements(GL_TRIANGLES, drawElementsUShort->size(), &(drawElementsUShort->front())); } else { - const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast(glyphquad._primitives[0].get()); + const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast(glyphquad._primitives.get()); if (drawElementsUInt) { pf.drawElements(GL_TRIANGLES, drawElementsUInt->size(), &(drawElementsUInt->front())); @@ -1322,22 +1314,19 @@ void Text::setBackdropType(BackdropType type) if (_backdropType==type) return; _backdropType = type; + + assignStateSet(); + computeGlyphRepresentation(); } -void Text::setBackdropImplementation(BackdropImplementation implementation) -{ - if (_backdropImplementation==implementation) return; - - _backdropImplementation = implementation; - computeGlyphRepresentation(); -} - - void Text::setBackdropOffset(float offset) { _backdropHorizontalOffset = offset; _backdropVerticalOffset = offset; + + assignStateSet(); + computeGlyphRepresentation(); } @@ -1345,12 +1334,17 @@ void Text::setBackdropOffset(float horizontal, float vertical) { _backdropHorizontalOffset = horizontal; _backdropVerticalOffset = vertical; + + assignStateSet(); + computeGlyphRepresentation(); } void Text::setBackdropColor(const osg::Vec4& color) { _backdropColor = color; + + assignStateSet(); } void Text::setColorGradientMode(ColorGradientMode mode) @@ -1391,20 +1385,10 @@ Text::GlyphQuads::GlyphQuads(const GlyphQuads&) void Text::GlyphQuads::resizeGLObjectBuffers(unsigned int maxSize) { - for(Primitives::iterator itr = _primitives.begin(); - itr != _primitives.end(); - ++itr) - { - (*itr)->resizeGLObjectBuffers(maxSize); - } + if (_primitives.valid()) _primitives->resizeGLObjectBuffers(maxSize); } void Text::GlyphQuads::releaseGLObjects(osg::State* state) const { - for(Primitives::const_iterator itr = _primitives.begin(); - itr != _primitives.end(); - ++itr) - { - (*itr)->releaseGLObjects(state); - } + if (_primitives.valid()) _primitives->releaseGLObjects(state); } diff --git a/src/osgText/TextBase.cpp b/src/osgText/TextBase.cpp index 5c5e5460e..6fbf2e5ba 100644 --- a/src/osgText/TextBase.cpp +++ b/src/osgText/TextBase.cpp @@ -50,7 +50,6 @@ TextBase::TextBase(): _lineCount(0), _glyphNormalized(false) { - setStateSet(Font::getDefaultFont()->getStateSet()); setUseDisplayList(false); setSupportsDisplayList(false); @@ -89,6 +88,11 @@ TextBase::~TextBase() { } +osg::StateSet* TextBase::createStateSet() +{ + return 0; +} + void TextBase::initArraysAndBuffers() { _vbo = new osg::VertexBufferObject; @@ -182,6 +186,10 @@ void TextBase::setColor(const osg::Vec4& color) _color = color; } +void TextBase::assignStateSet() +{ + setStateSet(createStateSet()); +} void TextBase::setFont(osg::ref_ptr font) { @@ -189,6 +197,8 @@ void TextBase::setFont(osg::ref_ptr font) _font = font; + assignStateSet(); + computeGlyphRepresentation(); } @@ -203,6 +213,9 @@ void TextBase::setFontResolution(unsigned int width, unsigned int height) if (_fontSize==size) return; _fontSize = size; + + assignStateSet(); + computeGlyphRepresentation(); } diff --git a/src/osgText/shaders/text_frag.cpp b/src/osgText/shaders/text_frag.cpp new file mode 100644 index 000000000..02c253100 --- /dev/null +++ b/src/osgText/shaders/text_frag.cpp @@ -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; i1.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"; diff --git a/src/osgText/shaders/text_vert.cpp b/src/osgText/shaders/text_vert.cpp new file mode 100644 index 000000000..72506284f --- /dev/null +++ b/src/osgText/shaders/text_vert.cpp @@ -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"; diff --git a/src/osgUtil/GLObjectsVisitor.cpp b/src/osgUtil/GLObjectsVisitor.cpp index b194b7990..25aa8c896 100644 --- a/src/osgUtil/GLObjectsVisitor.cpp +++ b/src/osgUtil/GLObjectsVisitor.cpp @@ -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(); + extensions->glUseProgram(0); + _renderInfo.getState()->setLastAppliedProgramObject(0); + } + } +} + + ///////////////////////////////////////////////////////////////// // // GLObjectsOperation diff --git a/src/osgViewer/Renderer.cpp b/src/osgViewer/Renderer.cpp index 71f93ccc5..06620af32 100644 --- a/src/osgViewer/Renderer.cpp +++ b/src/osgViewer/Renderer.cpp @@ -571,7 +571,6 @@ void Renderer::compile() { DEBUG_MESSAGE<<"Renderer::compile()"<getState()); - sceneView->getSceneData()->accept(glov); + glov.compile(*(sceneView->getSceneData())); } sceneView->getState()->checkGLErrors("After Renderer::compile"); diff --git a/src/osgWidget/Label.cpp b/src/osgWidget/Label.cpp index 3731bca8c..6c7e9ebc4 100644 --- a/src/osgWidget/Label.cpp +++ b/src/osgWidget/Label.cpp @@ -134,7 +134,6 @@ void Label::setFontColor(const Color& c) { void Label::setShadow(point_type offset) { _text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); - _text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER); _text->setBackdropOffset(offset); _calculateSize(getTextSize()); diff --git a/src/osgWrappers/deprecated-dotosg/osgText/IO_Text.cpp b/src/osgWrappers/deprecated-dotosg/osgText/IO_Text.cpp index e34c1d46e..c2bb99e6a 100644 --- a/src/osgWrappers/deprecated-dotosg/osgText/IO_Text.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgText/IO_Text.cpp @@ -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(-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) { if (str=="SOLID") return osgText::Text::SOLID; @@ -155,12 +134,6 @@ bool Text_readLocalData(osg::Object &obj, osgDB::Input &fr) // backdropImplementation if (fr[0].matchWord("backdropImplementation")) { - std::string str = fr[1].getStr(); - osgText::Text::BackdropImplementation backdropImplementation = convertBackdropImplementationStringToEnum(str); - - if (backdropImplementation != static_cast(-1)) - text.setBackdropImplementation(backdropImplementation); - fr += 2; itAdvanced = true; } @@ -254,9 +227,6 @@ bool Text_writeLocalData(const osg::Object &obj, osgDB::Output &fw) osg::Vec4 c = text.getBackdropColor(); fw.indent() << "backdropColor " << c.x() << " " << c.y() << " " << c.z() << " " << c.w() << std::endl; - // backdropImplementation - fw.indent() << "backdropImplementation " << convertBackdropImplementationEnumToString(text.getBackdropImplementation()) << std::endl; - // colorGradientMode fw.indent() << "colorGradientMode " << convertColorGradientModeEnumToString(text.getColorGradientMode()) << std::endl;