使用OpenGL中的着色器向位图字体添加渐变

时间:2015-04-21 08:38:44

标签: opengl-es libgdx shader fragment-shader vertex-shader

我有一个距离字段字体,我想用垂直渐变渲染。我遇到的问题是,如果有一个简单的方法让我获得相对于我从字体纹理图集渲染的字形的y坐标,我就无法解决。

我正在使用LibGDX。我可以使用v_texCoord.y来获取相对于纹理的位置。有没有一种简单的方法可以获得相对于我为当前角色渲染的纹理区域的y位置?一旦我有了,我就可以使用mix(...)在片段着色器中创建渐变。

顶点着色器

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;
}

片段着色器

#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);
}

1 个答案:

答案 0 :(得分:4)

没有创建专门的字体纹理就没有简单的方法。 libgdx中的BitmapFont是使用SpriteBatch绘制的,它不支持UV,位置和颜色之外的任何顶点属性。您可以尝试将相对于TextureRegion的垂直位置编码到color属性中,但这需要对BitmapFont类进行一些重新处理。我不确定你是否可以将其子类化,或者你是否必须克隆和修改它。

我能想到的最简单的解决方案是制作专门的字体纹理。对于位图字体中的每个字母,您可以使用垂直的红色到绿色渐变,其中红色和绿色将替换为着色器中的其他颜色。

所以你需要生成你的字体,然后在Gimp或Photoshop中打开它并添加渐变。对于标准字体,创建一个新的乘法图层并在所有字母上绘制红绿渐变。使用距离场字体,您只想在颜色通道中绘制渐变,并将距离字段保留在Alpha通道中。

然后在着色器中,您可以设置顶部颜色和底部颜色的制服,这些颜色将乘以红色和绿色。你可以在其他问题上查询如何使用SpriteBatch使用额外的制服。在标准字体的片段着色器中有类似的东西:

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);

对于距离场字体:

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);