Adding a Gradient to a Bitmap Font Using Shaders in OpenGL

I have a distance field font that I would like to display with a vertical gradient. The problem I am having is this I cannot solve if there is an easy way to get the y coordinate relative to the glyph that I get from the font texture atlas.

I am using LibGDX. I can use v_texCoord.y to get the position relative to the texture. Is there an easy way to get the y position relative to the area of ​​the texture that I am scanning for the current character? Once I'm good, I can just use mix (...) to create a gradient in the fragment shader.

Vertex shader

attribute vec4 a_position;
attribute vec2 a_texCoord0;
attribute vec4 a_color;

uniform mat4 u_projTrans;

varying vec4 v_color;
varying vec2 v_texCoord;

void main()
{
    gl_Position = u_projTrans * a_position;
    v_texCoord = a_texCoord0;
    v_color = a_color;
}

      

Fragment shader

#ifdef GL_ES
  precision mediump float;
#endif

uniform sampler2D u_texture;
uniform float u_boldness;
uniform float u_smoothing;

varying vec4 v_color;
varying vec2 v_texCoord;

void main()
{
    float distance = texture2D(u_texture, v_texCoord).a;
    float alpha = smoothstep(0.5 - u_boldness - u_smoothing, 0.5 - u_boldness + u_smoothing, distance);
    gl_FragColor = vec4(v_color.rgb * alpha, alpha * v_color.a);
}

      

+3


source to share


1 answer


There is no easy way without creating a specialized font texture. The BitmapFont in libgdx is created with SpriteBatch, which does not support vertex attributes outside UV, position and color. You can try to encode the vertical position relative to the TextureRegion in the color attribute, but this will require some rework on the BitmapFont class. I'm not sure if you can just subclass it, or if you have to clone and modify it.

The easiest solution I can think of is to create a specialized font texture. For each letter in your bitmap font, you can use a vertical gradient from red to green, where red and green will be replaced with different colors in the shader.

So, you need to generate a font and then open it in Gimp or Photoshop and add a gradient. For the standard font, create a new layered layer and paint red-green gradients over all the letters. With a distance field font, you just want to draw gradients in the color channels and leave the distance field in the alpha channel.

Then in your shader, you can set the shape for the top color and the bottom color, which will be multiplied by red and green. You can look in other questions on how to use additional uniforms with SpriteBatch. Something like this in the snippet shader for the standard font:



uniform vec3 u_topColor;
uniform vec3 u_botttomColor;

vec4 textureColor = texture2D(u_texture, v_texCoord);
gl_FragColor = vec4(v_color.rgb * (u_topColor*textureColor.r + u_bottomColor*textureColor.g), textureColor.a * v_color.a);

      

And for the font of the distance field:

uniform vec3 u_topColor;
uniform vec3 u_botttomColor;

vec4 textureColor = texture2D(u_texture, v_texCoord);
float alpha = smoothstep(0.5 - u_boldness - u_smoothing, 0.5 - u_boldness + u_smoothing, textureColor.a);
gl_FragColor = vec4(v_color.rgb * (u_topColor*textureColor.r + u_bottomColor*textureColor.g), alpha * v_color.a);

      

+4


source







All Articles