Added osgText/shaders to support greyscale and Signed Distance Field based text

This commit is contained in:
Robert Osfield
2017-09-19 16:35:28 +01:00
parent cc7cf54353
commit 72cf6734a1
5 changed files with 214 additions and 98 deletions

View File

@@ -1345,7 +1345,7 @@ bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
}
}
OSG_NOTICE<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
OSG_INFO<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
return true;
}

View File

@@ -28,84 +28,6 @@
using namespace osg;
using namespace osgText;
#if (!defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE))
#define GLSL_VERSION_STR "330 core"
#define GLYPH_CMP "r"
#else
#define GLSL_VERSION_STR "300 es"
#define GLYPH_CMP "a"
#endif
static const char* gl3_TextVertexShader = {
"#version " GLSL_VERSION_STR "\n"
"// gl3_TextVertexShader\n"
"#ifdef GL_ES\n"
" precision highp float;\n"
"#endif\n"
"in vec4 osg_Vertex;\n"
"in vec4 osg_Color;\n"
"in vec4 osg_MultiTexCoord0;\n"
"uniform mat4 osg_ModelViewProjectionMatrix;\n"
"out vec2 texCoord;\n"
"out vec4 vertexColor;\n"
"void main(void)\n"
"{\n"
" gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex;\n"
" texCoord = osg_MultiTexCoord0.xy;\n"
" vertexColor = osg_Color; \n"
"}\n"
};
static const char* gl3_TextFragmentShader = {
"#version " GLSL_VERSION_STR "\n"
"// gl3_TextFragmentShader\n"
"#ifdef GL_ES\n"
" precision highp float;\n"
"#endif\n"
"uniform sampler2D glyphTexture;\n"
"in vec2 texCoord;\n"
"in vec4 vertexColor;\n"
"out vec4 color;\n"
"void main(void)\n"
"{\n"
" if (texCoord.x>=0.0) color = vertexColor * vec4(1.0, 1.0, 1.0, texture(glyphTexture, texCoord)." GLYPH_CMP ");\n"
" else color = vertexColor;\n"
"}\n"
};
static const char* gl2_TextVertexShader = {
"// gl2_TextVertexShader\n"
"#ifdef GL_ES\n"
" precision highp float;\n"
"#endif\n"
"varying vec2 texCoord;\n"
"varying vec4 vertexColor;\n"
"void main(void)\n"
"{\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" texCoord = gl_MultiTexCoord0.xy;\n"
" vertexColor = gl_Color; \n"
"}\n"
};
static const char* gl2_TextFragmentShader = {
"// gl2_TextFragmentShader\n"
"#ifdef GL_ES\n"
" precision highp float;\n"
"#endif\n"
"uniform sampler2D glyphTexture;\n"
"varying vec2 texCoord;\n"
"varying vec4 vertexColor;\n"
"void main(void)\n"
"{\n"
" if (texCoord.x>=0.0) gl_FragColor = vertexColor * vec4(1.0, 1.0, 1.0, texture2D(glyphTexture, texCoord).a);\n"
" else gl_FragColor = vertexColor;\n"
"}\n"
};
Text::Text():
_enableDepthWrites(true),
_backdropType(NONE),
@@ -237,35 +159,47 @@ osg::StateSet* Text::createStateSet()
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;
OSG_NOTICE<<"Text::createStateSet() activeFont->getGlyphTextureFeatures()="<<activeFont->getGlyphTextureFeatures()<<std::endl;
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
#endif
#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint();
if (shaderHint==osg::DisplaySettings::SHADER_GL3 || shaderHint==osg::DisplaySettings::SHADER_GLES3)
if (activeFont->getGlyphTextureFeatures()==GlyphTexture::GREYSCALE && shaderHint==osg::DisplaySettings::SHADER_NONE)
{
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));
OSG_INFO<<"Font::Font() Fixed function pipeline"<<std::endl;
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
return stateset.release();
}
else if (shaderHint==osg::DisplaySettings::SHADER_GL2 || shaderHint==osg::DisplaySettings::SHADER_GLES2)
#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());
{
OSG_INFO<<"Font::Font() Setting up GL2 compatible shaders"<<std::endl;
OSG_NOTICE<<"Using shaders/text.vert"<<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));
#include "shaders/text_vert.cpp"
program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/text.vert", text_vert));
}
if (activeFont->getGlyphTextureFeatures()==GlyphTexture::GREYSCALE)
{
OSG_NOTICE<<"Using shaders/text_greyscale.frag"<<std::endl;
#include "shaders/text_greyscale_frag.cpp"
program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/text_greyscale.frag", text_greyscale_frag));
}
else
{
OSG_NOTICE<<"Using shaders/text_sdf.frag"<<std::endl;
#include "shaders/text_sdf_frag.cpp"
program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/text_sdf.frag", text_sdf_frag));
}
return stateset.release();

View File

@@ -0,0 +1,33 @@
char text_greyscale_frag[] = "$OSG_GLSL_VERSION\n"
"$OSG_GLSL_PRECISION_FLOAT\n"
"\n"
"#pragma import_defines( BACKDROP_COLOR, OUTLINE, ALPHA )\n"
"\n"
"#if __VERSION__>=130\n"
" #define TEXTURE texture\n"
" out vec4 osg_FragColor;\n"
"#else\n"
" #define TEXTURE texture2D\n"
" #define osg_FragColor gl_FragColor\n"
"#endif\n"
"\n"
"uniform sampler2D glyphTexture;\n"
"\n"
"$OSG_VARYING_IN vec2 texCoord;\n"
"$OSG_VARYING_IN vec4 vertexColor;\n"
"\n"
"#if !defined(GL_ES) && __VERSION__>=130\n"
" #define ALPHA r\n"
"#else\n"
" #define ALPHA a\n"
"#endif\n"
"\n"
"void main(void)\n"
"{\n"
" float alpha = TEXTURE(glyphTexture, texCoord).ALPHA;\n"
"\n"
" if (alpha==0.0) discard;\n"
"\n"
" osg_FragColor = vec4(vertexColor.rgb, alpha);\n"
"}\n"
"\n";

View File

@@ -0,0 +1,136 @@
char text_sdf_frag[] = "$OSG_GLSL_VERSION\n"
"$OSG_GLSL_PRECISION_FLOAT\n"
"\n"
"#pragma import_defines( BACKDROP_COLOR, OUTLINE )\n"
"\n"
"#if __VERSION__>=400\n"
" #define osg_TextureQueryLOD textureQueryLod\n"
" #define USE_SIGNED_DISTNACE_FIELD\n"
"#else\n"
" #extension GL_ARB_texture_query_lod : enable\n"
" #ifdef GL_ARB_texture_query_lod\n"
" #define osg_TextureQueryLOD textureQueryLOD\n"
" #define USE_SIGNED_DISTNACE_FIELD\n"
" #endif\n"
"#endif\n"
"\n"
"#undef USE_SIGNED_DISTNACE_FIELD\n"
"\n"
"#if __VERSION__>=130\n"
" #define TEXTURE texture\n"
" out vec4 osg_FragColor;\n"
"#else\n"
" #define TEXTURE texture2D\n"
" #define osg_FragColor gl_FragColor\n"
"#endif\n"
"\n"
"uniform sampler2D glyphTexture;\n"
"\n"
"$OSG_VARYING_IN vec2 texCoord;\n"
"$OSG_VARYING_IN vec4 vertexColor;\n"
"\n"
"vec4 textureColor()\n"
"{\n"
" #ifdef OUTLINE\n"
" // glyph.rgba = (signed_distance, thin_outline, thick_outline, glyph_alpha)\n"
" vec4 glyph = TEXTURE(glyphTexture, texCoord);\n"
"\n"
" #if 0\n"
" float blend_ratio = OUTLINE*17.0;\n"
"\n"
" float outline_alpha = 0.0;\n"
" if (blend_ratio>2.0) outline_alpha = glyph.b;\n"
" else if (blend_ratio>1.0) outline_alpha = mix(glyph.g, glyph.b, blend_ratio-1.0);\n"
" else outline_alpha = glyph.g*blend_ratio;\n"
" #else\n"
" float outline_alpha = glyph.g;\n"
" //float outline_alpha = glyph.b;\n"
" #endif\n"
"\n"
" float alpha = glyph.a+outline_alpha;\n"
" if (alpha>1.0) alpha = 1.0;\n"
"\n"
" return vec4( vertexColor.rgb*glyph.a + BACKDROP_COLOR.rgb*outline_alpha, alpha);\n"
"\n"
" #else\n"
" float alpha = TEXTURE(glyphTexture, texCoord).a;\n"
" if (alpha==0.0) vec4(0.0, 0.0, 0.0, 0.0);\n"
" return vec4(vertexColor.rgb, alpha);\n"
" #endif\n"
"}\n"
"\n"
"#ifdef USE_SIGNED_DISTNACE_FIELD\n"
"vec4 distanceFieldColor()\n"
"{\n"
" float center_alpha = TEXTURE(glyphTexture, texCoord).r;\n"
"\n"
" float blend_width = 0.2;\n"
" float distance_scale = 5.0;\n"
" float edge_distance = (center_alpha-0.5)*distance_scale;\n"
"\n"
" #ifdef OUTLINE\n"
" float outline_width = OUTLINE*17.0;//0.5;\n"
" if (edge_distance>blend_width*0.5)\n"
" {\n"
" return vertexColor;\n"
" }\n"
" else if (edge_distance>-blend_width*0.5)\n"
" {\n"
" return mix(vertexColor, BACKDROP_COLOR, (blend_width*0.5-edge_distance)/(blend_width));\n"
" }\n"
" else if (edge_distance>(blend_width-outline_width))\n"
" {\n"
" return BACKDROP_COLOR;\n"
" }\n"
" else if (edge_distance>-outline_width)\n"
" {\n"
" return vec4(BACKDROP_COLOR.rgb, (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>0.0)\n"
" {\n"
" return vertexColor;\n"
" }\n"
" else if (edge_distance>-blend_width)\n"
" {\n"
" return vec4(vertexColor.rgb, 1.0+edge_distance/blend_width);\n"
" }\n"
" else\n"
" {\n"
" return vec4(0.0, 0.0, 0.0, 0.0);\n"
" }\n"
" #endif\n"
"}\n"
"#endif\n"
"\n"
"\n"
"void main(void)\n"
"{\n"
"\n"
"#ifdef USE_SIGNED_DISTNACE_FIELD\n"
"\n"
" float mml = osg_TextureQueryLOD(glyphTexture, texCoord).x;\n"
"\n"
" float near_transition = 0.0;\n"
" float far_transition = 1.0;\n"
"\n"
" vec4 color;\n"
" if (mml<near_transition) color = distanceFieldColor();\n"
" else if (mml>far_transition) color = textureColor();\n"
" else color = mix(distanceFieldColor(), textureColor(), (mml-near_transition)/(far_transition-near_transition));\n"
"\n"
"#else\n"
"\n"
" vec4 color = textureColor();\n"
"\n"
"#endif\n"
"\n"
" if (color.a==0.0) discard;\n"
"\n"
" osg_FragColor = color;\n"
"}\n"
"\n";

View 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";