如何使用 FreeType 和 OpenGL 渲染文本

问题描述 投票:0回答:1

目前,如果我不乘以采样,我设法渲染看起来像对应字符的四边形,但每当我这样做时,四边形就会完全透明并消失

FreeType 和 FontConfig 的设置

c.glEnable(c.GL_BLEND);
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);

var ft: c.FT_Library = undefined;
_ = c.FT_Init_FreeType(&ft);
var face: c.FT_Face = undefined;

const font_path = getFontPath(alloc, font.family) catch unreachable; // Returned path matches font
_ = c.FT_New_Face(ft, font_path.ptr, 0, &face);
_ = c.FT_Set_Pixel_Sizes(face, 0, 16);
c.glPixelStorei(c.GL_UNPACK_ALIGNMENT, 1);

for (keys_s.search) |key| {
    keys_s.char_info.put(key, Character.new(face, key)) catch unreachable;
}

保存有关角色信息的结构

pub const Character = struct {
texture_id: u32,
size: [2]i32,
bearing: [2]i32,
advance: [2]u32,

fn new(face: c.FT_Face, key: u8) Character {
    var texture: u32 = undefined;
    c.glGenTextures(1, &texture);
    c.glBindTexture(c.GL_TEXTURE_2D, texture);
    c.glTexImage2D(
        c.GL_TEXTURE_2D,
        0,
        c.GL_RED,
        @intCast(face.*.glyph.*.bitmap.width),
        @intCast(face.*.glyph.*.bitmap.rows),
        0,
        c.GL_RED,
        c.GL_UNSIGNED_BYTE,
        face.*.glyph.*.bitmap.buffer,
    );

    c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_WRAP_S, c.GL_CLAMP_TO_EDGE);
    c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_WRAP_T, c.GL_CLAMP_TO_EDGE);
    c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, c.GL_LINEAR);
    c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, c.GL_LINEAR);

    return .{
        .texture_id = texture,
        .size = .{
            @intCast(face.*.glyph.*.bitmap.width),
            @intCast(face.*.glyph.*.bitmap.rows),
        },
        .bearing = .{
            @intCast(face.*.glyph.*.bitmap_left),
            @intCast(face.*.glyph.*.bitmap_top),
        },
        .advance = .{
            @intCast(face.*.glyph.*.advance.x >> 6),
            @intCast(face.*.glyph.*.advance.y >> 6),
        },
    };
}
};

渲染文本的实际函数(setColor 只是将制服设置为所选颜色)


pub fn renderText(self: *const Self, text: []const u8, x: i32, y: i32) void {
    setColor(self.config.font.color, self.egl.text_shader_program.*);
    c.glActiveTexture(c.GL_TEXTURE0);

    for (text, 0..) |char, i| {
        const ch = self.config.keys.char_info.get(char).?;
        const move: i32 = @intCast(ch.advance[0] * i);

        const x_pos = x + ch.size[0] + move;
        const y_pos = y - ch.bearing[1];

        const vertices = [_]i32{
            x_pos,              y_pos,              0, 1,
            x_pos + ch.size[0], y_pos,              1, 1,
            x_pos,              y_pos + ch.size[1], 0, 0,
            x_pos + ch.size[0], y_pos + ch.size[1], 1, 0,
        };


        c.glBindTexture(c.GL_TEXTURE_2D, ch.texture_id);
        c.glBindBuffer(c.GL_ARRAY_BUFFER, self.egl.VBO);
        c.glBufferSubData(c.GL_ARRAY_BUFFER, 0, @sizeOf(i32) * vertices.len, &vertices);
        c.glVertexAttribPointer(0, 4, c.GL_INT, c.GL_FALSE, 0, null);
        c.glDrawElements(c.GL_TRIANGLES, 6, c.GL_UNSIGNED_INT, null);
    }
}

我也使用这个 EBO 来渲染四边形

const indices = [_]i32{
    0, 1, 3,
    0, 2, 3,
};

c.glBindBuffer(c.GL_ELEMENT_ARRAY_BUFFER, EBO[0]);
c.glBufferData(c.GL_ELEMENT_ARRAY_BUFFER, @sizeOf(i32) * indices.len, &indices, c.GL_STATIC_DRAW);

片段着色器

#version 460 core

layout(location = 0) out vec4 FragColor;

uniform vec4 u_color;
uniform sampler2D text;

in vec2 v_texcoords;

void main() {
  vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, v_texcoords).r);
  FragColor = u_color * sampled;
}

顶点着色器

#version 460 core

layout(location = 0) in vec4 vertex;

uniform mat4 projection;

out vec2 v_pos;
out vec2 v_texcoords;

void main() {
  gl_Position = projection * vec4(in_pos.xy, 0.0, 1.0);
  v_texcoords = vertex.zw;
}
opengl freetype zig fontconfig
1个回答
0
投票

看起来您没有告诉 FreeType 库加载/渲染任何字形。尝试在循环中的此行之前调用

FT_Load_Char
函数:

keys_s.char_info.put(key, Character.new(face, key)) catch unreachable;

另外,避免使用

catch unreachable
;它仅适用于您可以保证代码永远不会失败的情况。只需使用
try

© www.soinside.com 2019 - 2024. All rights reserved.