Improvements to the Signed Distance Field implementation.
This commit is contained in:
parent
d2fa7c4317
commit
2f19cd4b87
@ -27,8 +27,13 @@ DefaultFont::DefaultFont()
|
|||||||
_fontSize = FontResolution(8,12);
|
_fontSize = FontResolution(8,12);
|
||||||
|
|
||||||
_minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR;
|
_minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR;
|
||||||
_magFilterHint = osg::Texture::NEAREST;
|
_magFilterHint = osg::Texture::LINEAR;
|
||||||
|
|
||||||
|
char *ptr;
|
||||||
|
if ((ptr = getenv("OSG_SDF_TEXT")) != 0)
|
||||||
|
{
|
||||||
|
_glyphTextureFeatures = osgText::GlyphTexture::ALL_FEATURES;
|
||||||
|
}
|
||||||
|
|
||||||
constructGlyphs();
|
constructGlyphs();
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,9 @@ int GlyphTexture::compare(const osg::StateAttribute& rhs) const
|
|||||||
int GlyphTexture::getEffectMargin(const Glyph* glyph)
|
int GlyphTexture::getEffectMargin(const Glyph* glyph)
|
||||||
{
|
{
|
||||||
if (_glyphTextureFeatures==GREYSCALE) return 0;
|
if (_glyphTextureFeatures==GREYSCALE) return 0;
|
||||||
else return glyph->getFontResolution().second/4;
|
// else return glyph->getFontResolution().second/4;
|
||||||
|
else return osg::maximum(glyph->getFontResolution().second/6, 2u);
|
||||||
|
// else return osg::maximum(glyph->getFontResolution().second/8,1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GlyphTexture::getTexelMargin(const Glyph* glyph)
|
int GlyphTexture::getTexelMargin(const Glyph* glyph)
|
||||||
|
@ -47,6 +47,17 @@ Text::Text():
|
|||||||
{
|
{
|
||||||
_supportsVertexBufferObjects = true;
|
_supportsVertexBufferObjects = true;
|
||||||
|
|
||||||
|
char *ptr;
|
||||||
|
if ((ptr = getenv("OSG_SDF_TEXT")) != 0)
|
||||||
|
{
|
||||||
|
_backdropImplementation = USE_SHADERS;
|
||||||
|
}
|
||||||
|
else if ((ptr = getenv("OSG_GREYSCALE_TEXT")) != 0)
|
||||||
|
{
|
||||||
|
_backdropImplementation = DELAYED_DEPTH_WRITES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
assignStateSet();
|
assignStateSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,11 +91,10 @@ osg::StateSet* Text::createStateSet()
|
|||||||
|
|
||||||
Font::StateSets& statesets = activeFont->getCachedStateSets();
|
Font::StateSets& statesets = activeFont->getCachedStateSets();
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
osg::StateSet::DefineList defineList;
|
osg::StateSet::DefineList defineList;
|
||||||
if (_backdropType!=NONE && _backdropImplementation==USE_SHADERS)
|
if (_backdropType!=NONE && _backdropImplementation==USE_SHADERS)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
|
||||||
|
|
||||||
ss.str("");
|
ss.str("");
|
||||||
ss << "vec4("<<_backdropColor.r()<<", "<<_backdropColor.g()<<", "<<_backdropColor.b()<<", "<<_backdropColor.a()<<")";
|
ss << "vec4("<<_backdropColor.r()<<", "<<_backdropColor.g()<<", "<<_backdropColor.b()<<", "<<_backdropColor.a()<<")";
|
||||||
|
|
||||||
@ -122,15 +132,19 @@ osg::StateSet* Text::createStateSet()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_fontSize.second>16/* && _backdropImplementation==USE_SHADERS*/)
|
if (activeFont->getGlyphTextureFeatures()!=GlyphTexture::GREYSCALE)
|
||||||
{
|
{
|
||||||
OSG_NOTICE<<"Requesting SDF support _fontSize.second="<<_fontSize.second<<std::endl;
|
ss.str("");
|
||||||
|
ss << _fontSize.second;
|
||||||
|
|
||||||
|
defineList["GLYPH_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||||
|
|
||||||
|
ss.str("");
|
||||||
|
ss << activeFont->getTextureWidthHint();
|
||||||
|
defineList["TEXTURE_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||||
|
|
||||||
defineList["SIGNED_DISTNACE_FIELD"] = osg::StateSet::DefinePair("1", osg::StateAttribute::ON);
|
defineList["SIGNED_DISTNACE_FIELD"] = osg::StateSet::DefinePair("1", osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
OSG_NOTICE<<"Disabling SDF support _fontSize.second="<<_fontSize.second<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
OSG_NOTICE<<"Text::createStateSet() _backdropType="<<_backdropType<<", _backdropImplementation="<<_backdropImplementation<<std::endl;
|
OSG_NOTICE<<"Text::createStateSet() _backdropType="<<_backdropType<<", _backdropImplementation="<<_backdropImplementation<<std::endl;
|
||||||
@ -151,7 +165,7 @@ osg::StateSet* Text::createStateSet()
|
|||||||
{
|
{
|
||||||
if ((*itr)->getDefineList()==defineList)
|
if ((*itr)->getDefineList()==defineList)
|
||||||
{
|
{
|
||||||
OSG_NOTICE<<"Text::createStateSet() : Matched DefineList, return StateSet "<<itr->get()<<std::endl;
|
// OSG_NOTICE<<"Text::createStateSet() : Matched DefineList, return StateSet "<<itr->get()<<std::endl;
|
||||||
return itr->get();
|
return itr->get();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -180,7 +194,7 @@ osg::StateSet* Text::createStateSet()
|
|||||||
osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint();
|
osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint();
|
||||||
if (activeFont->getGlyphTextureFeatures()==GlyphTexture::GREYSCALE && shaderHint==osg::DisplaySettings::SHADER_NONE)
|
if (activeFont->getGlyphTextureFeatures()==GlyphTexture::GREYSCALE && shaderHint==osg::DisplaySettings::SHADER_NONE)
|
||||||
{
|
{
|
||||||
OSG_INFO<<"Font::Font() Fixed function pipeline"<<std::endl;
|
OSG_NOTICE<<"Font::Font() Fixed function pipeline"<<std::endl;
|
||||||
|
|
||||||
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||||
return stateset.release();
|
return stateset.release();
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
char text_sdf_frag[] = "$OSG_GLSL_VERSION\n"
|
char text_sdf_frag[] = "$OSG_GLSL_VERSION\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#pragma import_defines( BACKDROP_COLOR, OUTLINE, SIGNED_DISTNACE_FIELD )\n"
|
"#pragma import_defines( BACKDROP_COLOR, OUTLINE, SIGNED_DISTNACE_FIELD, TEXTURE_DIMENSION, GLYPH_DIMENSION)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#if !defined(GL_ES)\n"
|
"#ifdef GL_ES\n"
|
||||||
" #if __VERSION__>=400\n"
|
" #extension GL_OES_standard_derivatives : enable\n"
|
||||||
" #define osg_TextureQueryLOD textureQueryLod\n"
|
" #ifndef GL_OES_standard_derivatives\n"
|
||||||
" #else\n"
|
" #undef SIGNED_DISTNACE_FIELD\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"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"\n"
|
"\n"
|
||||||
"$OSG_PRECISION_FLOAT\n"
|
"$OSG_PRECISION_FLOAT\n"
|
||||||
"\n"
|
"\n"
|
||||||
"//#undef USE_SIGNED_DISTNACE_FIELD\n"
|
"#undef SIGNED_DISTNACE_FIELD\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#if __VERSION__>=130\n"
|
"#if __VERSION__>=130\n"
|
||||||
" #define TEXTURE texture\n"
|
" #define TEXTURE texture\n"
|
||||||
@ -32,13 +28,138 @@ char text_sdf_frag[] = "$OSG_GLSL_VERSION\n"
|
|||||||
"$OSG_VARYING_IN vec2 texCoord;\n"
|
"$OSG_VARYING_IN vec2 texCoord;\n"
|
||||||
"$OSG_VARYING_IN vec4 vertexColor;\n"
|
"$OSG_VARYING_IN vec4 vertexColor;\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"#ifdef SIGNED_DISTNACE_FIELD\n"
|
||||||
|
"\n"
|
||||||
|
"float distanceFromEdge(vec2 tc)\n"
|
||||||
|
"{\n"
|
||||||
|
" float center_alpha = TEXTURELOD(glyphTexture, tc, 0.0).r;\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, BACKDROP_COLOR, 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 BACKDROP_COLOR;\n"
|
||||||
|
" }\n"
|
||||||
|
" else if (edge_distance>-(outline_width+blend_half_width))\n"
|
||||||
|
" {\n"
|
||||||
|
" return vec4(BACKDROP_COLOR.rgb, ((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, 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 distanceFieldColor()\n"
|
||||||
|
"{\n"
|
||||||
|
" float sample_distance_scale = 0.75;\n"
|
||||||
|
" vec2 dx = dFdx(texCoord)*sample_distance_scale;\n"
|
||||||
|
" vec2 dy = dFdy(texCoord)*sample_distance_scale;\n"
|
||||||
|
"\n"
|
||||||
|
" #ifndef TEXTURE_DIMENSION\n"
|
||||||
|
" float TEXTURE_DIMENSION = 1024.0;\n"
|
||||||
|
" #endif\n"
|
||||||
|
"\n"
|
||||||
|
" #ifndef GLYPH_DIMENSION\n"
|
||||||
|
" float GLYPH_DIMENSION = 32.0;\n"
|
||||||
|
" #endif\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(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 = 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"
|
||||||
|
"#else\n"
|
||||||
|
"\n"
|
||||||
"vec4 textureColor()\n"
|
"vec4 textureColor()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" #ifdef OUTLINE\n"
|
" #ifdef OUTLINE\n"
|
||||||
" // glyph.rgba = (signed_distance, thin_outline, thick_outline, glyph_alpha)\n"
|
" // glyph.rgba = (signed_distance, thin_outline, thick_outline, glyph_alpha)\n"
|
||||||
" vec4 glyph = TEXTURE(glyphTexture, texCoord);\n"
|
" vec4 glyph = TEXTURE(glyphTexture, texCoord);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" float outline_alpha = (OUTLINE<=0.1) ? glyph.g : glyph.b;\n"
|
" float outline_alpha = (OUTLINE<=0.05) ? glyph.g : glyph.b;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" float alpha = glyph.a+outline_alpha;\n"
|
" float alpha = glyph.a+outline_alpha;\n"
|
||||||
" if (alpha>1.0) alpha = 1.0;\n"
|
" if (alpha>1.0) alpha = 1.0;\n"
|
||||||
@ -52,53 +173,6 @@ char text_sdf_frag[] = "$OSG_GLSL_VERSION\n"
|
|||||||
" #endif\n"
|
" #endif\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#ifdef SIGNED_DISTNACE_FIELD\n"
|
|
||||||
"vec4 distanceFieldColor()\n"
|
|
||||||
"{\n"
|
|
||||||
" float center_alpha = TEXTURELOD(glyphTexture, texCoord, 0.0).r;\n"
|
|
||||||
" //float center_alpha = TEXTURE(glyphTexture, texCoord).r;\n"
|
|
||||||
"\n"
|
|
||||||
" float blend_width = 0.005;\n"
|
|
||||||
" float distance_scale = 0.25;\n"
|
|
||||||
" float edge_distance = (center_alpha-0.5)*distance_scale;\n"
|
|
||||||
"\n"
|
|
||||||
" #ifdef OUTLINE\n"
|
|
||||||
" float outline_width = OUTLINE*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"
|
"#endif\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -110,36 +184,12 @@ char text_sdf_frag[] = "$OSG_GLSL_VERSION\n"
|
|||||||
" return;\n"
|
" return;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
|
||||||
" float near_fade_away = 2.0;\n"
|
|
||||||
" float far_fade_away = near_fade_away+5.0;\n"
|
|
||||||
"\n"
|
|
||||||
"#ifdef osg_TextureQueryLOD\n"
|
|
||||||
" float mml = osg_TextureQueryLOD(glyphTexture, texCoord).x;\n"
|
|
||||||
" if (mml>far_fade_away) discard;\n"
|
|
||||||
"#else\n"
|
|
||||||
" float mml = 0.0;\n"
|
|
||||||
"#endif\n"
|
|
||||||
"\n"
|
|
||||||
"\n"
|
|
||||||
"#ifdef SIGNED_DISTNACE_FIELD\n"
|
"#ifdef SIGNED_DISTNACE_FIELD\n"
|
||||||
"\n"
|
" vec4 color = distanceFieldColor();\n"
|
||||||
" float near_transition = 0.0;\n"
|
|
||||||
" float far_transition = near_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"
|
"#else\n"
|
||||||
"\n"
|
|
||||||
" vec4 color = textureColor();\n"
|
" vec4 color = textureColor();\n"
|
||||||
"\n"
|
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"\n"
|
"\n"
|
||||||
" if (mml>near_fade_away) color.a *= (far_fade_away-mml)/(far_fade_away-near_fade_away);\n"
|
|
||||||
"\n"
|
|
||||||
" if (color.a==0.0) discard;\n"
|
" if (color.a==0.0) discard;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" osg_FragColor = color;\n"
|
" osg_FragColor = color;\n"
|
||||||
|
Loading…
Reference in New Issue
Block a user