透视投影中的 SDF 文本渲染
SDF text rendering in perspective projection
我正在使用 SDF 技术 http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf 在 WebGL 中呈现文本。我制作了字体的 SDF 纹理,生成 BMFont 文本规格并使用简单的片段着色器显示文本:
precision mediump float;
uniform sampler2D u_texture;
varying vec2 vUv;
float aastep(float value) {
float afwidth = 0.1;
return smoothstep(0.5 - afwidth, 0.5 + afwidth, value);
}
void main(void)
{
vec4 texColor = texture2D(u_texture, vUv);
float alpha = aastep(texColor.a);
gl_FragColor = vec4(0.0, 0.0, 0.0, alpha);
}
我对 aastep
函数中的 afwidth
值有疑问。 afwidth 只是定义字体边界的模糊。如果它很小,那么远处的文字看起来很难看。如果大 - 靠近我的文字看起来很难看。所以问题是如何在片段着色器中计算afwidth?
PS:我有一个计算公式 GL_OES_standard_derivatives:
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
但是我的硬件不支持这个扩展。所以我想我需要根据gl_FragCoord
和变换矩阵来计算它。
人们可能会尝试根据 gl_FragCoord.w = 1.0 / gl_Position.w
:
创建 distance-to-camera 的简单近似值
float aastep(float value)
{
float distanceToCamera = 1.0 / gl_FragCoord.w;
float afwidth = 0.1 * distanceToCamera;
return smoothstep(0.5 - afwidth, 0.5 + afwidth, value);
}
您可能需要根据自己的喜好调整常数 0.1
。
只是检查一下,但您确定您的硬件不支持 OES_standard_derivatives
? http://webglstats.com 看起来不太可能。
在 WebGL 中,您必须启用 OES_standard_derivatives 才能使用它。
ext = gl.getExtention("OES_standard_derivatives");
if (!ext) {
// alert("no OES standard derivatives") or fallback to other technique
}
然后在你的着色器中你必须打开它
// at top of fragment shader
#extension GL_OES_standard_derivatives : enable
Run this test to check if they work on your system。如果您得到关于它们不存在的非常简短的结果,那么您是对的,它们不存在。如果你得到很多结果,那么它们确实存在,只是你没有在你的程序中启用它们
我正在使用 SDF 技术 http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf 在 WebGL 中呈现文本。我制作了字体的 SDF 纹理,生成 BMFont 文本规格并使用简单的片段着色器显示文本:
precision mediump float;
uniform sampler2D u_texture;
varying vec2 vUv;
float aastep(float value) {
float afwidth = 0.1;
return smoothstep(0.5 - afwidth, 0.5 + afwidth, value);
}
void main(void)
{
vec4 texColor = texture2D(u_texture, vUv);
float alpha = aastep(texColor.a);
gl_FragColor = vec4(0.0, 0.0, 0.0, alpha);
}
我对 aastep
函数中的 afwidth
值有疑问。 afwidth 只是定义字体边界的模糊。如果它很小,那么远处的文字看起来很难看。如果大 - 靠近我的文字看起来很难看。所以问题是如何在片段着色器中计算afwidth?
PS:我有一个计算公式 GL_OES_standard_derivatives:
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
但是我的硬件不支持这个扩展。所以我想我需要根据gl_FragCoord
和变换矩阵来计算它。
人们可能会尝试根据 gl_FragCoord.w = 1.0 / gl_Position.w
:
float aastep(float value)
{
float distanceToCamera = 1.0 / gl_FragCoord.w;
float afwidth = 0.1 * distanceToCamera;
return smoothstep(0.5 - afwidth, 0.5 + afwidth, value);
}
您可能需要根据自己的喜好调整常数 0.1
。
只是检查一下,但您确定您的硬件不支持 OES_standard_derivatives
? http://webglstats.com 看起来不太可能。
在 WebGL 中,您必须启用 OES_standard_derivatives 才能使用它。
ext = gl.getExtention("OES_standard_derivatives");
if (!ext) {
// alert("no OES standard derivatives") or fallback to other technique
}
然后在你的着色器中你必须打开它
// at top of fragment shader
#extension GL_OES_standard_derivatives : enable
Run this test to check if they work on your system。如果您得到关于它们不存在的非常简短的结果,那么您是对的,它们不存在。如果你得到很多结果,那么它们确实存在,只是你没有在你的程序中启用它们