opengl - 渲染字体时使用texelFetch是不是更快?

标签 opengl fonts textures opengl-3

我正在 OpenGL 3.3 中编写一些字体绘制着色器。我将把我的字体渲染成纹理图集,然后为我想要绘制的一些文本生成一些显示列表。我希望文本渲染消耗最少的资源(CPU、GPU 内存、GPU 时间)。我怎样才能做到这一点?

查看 Freetype-gl ,我注意到作者为每个字符生成了 6 个索引和 4 个顶点。

由于我使用的是 OpenGL 3.3,因此我有一些额外的自由。我的计划是为每个字符生成 1 个顶点,加上每个字符一个整数“代码”。字符代码可用于 texelFetch 操作来检索纹理坐标和字符大小信息。几何着色器将大小信息和顶点转换为三角形带。

texelFetch 会比发送更多顶点/纹理坐标慢吗?这值得做吗?或者是否有理由在我查看的字体库中没有这样做?


最终代码:

顶点着色器:

#version 330

uniform sampler2D font_atlas;
uniform sampler1D code_to_texture;
uniform mat4 projection;
uniform vec2 vertex_offset;  // in view space.
uniform vec4 color;
uniform float gamma;

in vec2 vertex;  // vertex in view space of each character adjusted for kerning, etc.
in int code;

out vec4 v_uv;

void main()
{
    v_uv = texelFetch(
            code_to_texture,
            code,
            0);
    gl_Position = projection * vec4(vertex_offset + vertex, 0.0, 1.0);
}

几何着色器:

#version 330

layout (points) in;
layout (triangle_strip, max_vertices = 4) out;

uniform sampler2D font_atlas;
uniform mat4 projection;

in vec4 v_uv[];

out vec2 g_uv;

void main()
{
    vec4 pos = gl_in[0].gl_Position;
    vec4 uv = v_uv[0];
    vec2 size = vec2(textureSize(font_atlas, 0)) * (uv.zw - uv.xy);
    vec2 pos_opposite = pos.xy + (mat2(projection) * size);

    gl_Position = vec4(pos.xy, 0, 1);
    g_uv = uv.xy;
    EmitVertex();

    gl_Position = vec4(pos.x, pos_opposite.y, 0, 1);
    g_uv = uv.xw;
    EmitVertex();

    gl_Position = vec4(pos_opposite.x, pos.y, 0, 1);
    g_uv = uv.zy;
    EmitVertex();

    gl_Position = vec4(pos_opposite.xy, 0, 1);
    g_uv = uv.zw;
    EmitVertex();

    EndPrimitive();
}

片段着色器:

#version 330

uniform sampler2D font_atlas;
uniform vec4 color;
uniform float gamma;

in vec2 g_uv;

layout (location = 0) out vec4 fragment_color;

void main()
{
    float a = texture(font_atlas, g_uv).r;
    fragment_color.rgb = color.rgb;
    fragment_color.a = color.a * pow(a, 1.0 / gamma);
}

最佳答案

我不认为您提出的方法与在顶点缓冲区中存储四边形顶点位置和纹理坐标之间存在显着的性能差异。一方面,您的方法需要更小的顶点缓冲区和更少的 CPU 工作。另一方面,texelFetch 调用或多或少会在随机位置进行,并且不会充分利用缓存。最后一点可能不是很重要,因为我猜纹理不会很大。此外,几何着色器的执行模型意味着它们很快就会成为管道的瓶颈。

回答“这值得做吗?” - 我怀疑不是出于性能原因。不幸的是,在实现并测量性能之前您无法判断。我认为这是一个很酷的想法,所以我认为您不会浪费时间去尝试。

关于opengl - 渲染字体时使用texelFetch是不是更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22527385/

相关文章:

html - 网络字体渲染

javascript - 使用 ShaderMaterial 的自定义几何体的纹理加载在 Three.js 中不起作用

javascript - 在 THREE.js 中,如何将一个纹理映射到 3D 矩形

opengl - 我必须在程序结束时使用 glDeleteTextures() 吗?

c++ - 在没有着色器的情况下在 OpenGL 中渲染深度缓冲区

c++ - 在标准路径中找不到 libGL.so、libGLU.so 和 libglut.so

java - 在 Java JTextPane 中写入 UTF-8 字符

java - 界面 : How can I find out if certain Unicode characters are supported?

c - 使用 GLUT 和 C 的闪烁 2D 纹理

java - OpenGL绘制数千个二维圆