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

Adding a gradient to a bitmap font using shaders in OpenGL

我有一个距离场字体,我想用垂直渐变渲染。我遇到的问题是,如果有一种简单的方法让我获得相对于我从字体纹理图集渲染的字形的 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);
}

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

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

因此您需要生成字体,然后在 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);