0
\$\begingroup\$

I've followed this source from learnopengl.com for text rendering. It seems fairly simple, and only required this much code:

struct Font font_load(const char* src, unsigned int size) {
    struct Font font;

    font.src = src;
    font.size = size;

    FT_Library ft;
    if (FT_Init_FreeType(&ft)) {
        ERROR("Could not init FreeType Library");
        exit(EXIT_FAILURE);
    }

    FT_Face face;
    if (FT_New_Face(ft, font.src, 0, &face)) {
        ERROR("Could not load font");
        exit(EXIT_FAILURE);
    }

    FT_Set_Pixel_Sizes(face, 0, font.size);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    for (unsigned char c = 0; c < 128; c++) {
        if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
            ERROR_IMSG("Failed to load glyph", c);
            continue;
        }

        unsigned int glyphTexture;
        glGenTextures(1, &glyphTexture);
        glBindTexture(GL_TEXTURE_2D, glyphTexture);
        glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RED,
            face->glyph->bitmap.width,
            face->glyph->bitmap.rows,
            0,
            GL_RED,
            GL_UNSIGNED_BYTE,
            face->glyph->bitmap.buffer
        );

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

        struct Character character;
        character.textureID = glyphTexture;
        glm_ivec2_copy((ivec2){face->glyph->bitmap.width, face->glyph->bitmap.rows}, character.size);
        glm_ivec2_copy((ivec2){face->glyph->bitmap_left, face->glyph->bitmap_top}, character.bearing);
        character.advance = face->glyph->advance.x;

        font.characters[c] = character;
    }

    glBindTexture(GL_TEXTURE_2D, 0);

    FT_Done_Face(face);
    FT_Done_FreeType(ft);

    glGenVertexArrays(1, &font.VAO);
    glGenBuffers(1, &font.VBO);
    glBindVertexArray(font.VAO);
    glBindBuffer(GL_ARRAY_BUFFER, font.VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    LOG_MSG("Loaded font", font.src);

    return font;
}

void text_render(struct Font* font, shader_t shader, char* text, float x, float y, float scale, vec3 color) {
    shader_use(shader);
    shader_setVec3(shader, "textColor", color[0], color[1], color[2]);
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(font->VAO);

    for (int c = 0; c < strlen(text); c++) {
        struct Character ch = font->characters[*(text + c)];

        float xpos = x + ch.bearing[0] * scale;
        float ypos = y - (ch.size[1] - ch.bearing[1]) * scale;

        float w = ch.size[0] * scale;
        float h = ch.size[1] * scale;

        float vertices[6][4] = {
            { xpos, ypos + h, 0.0f, 0.0f },            
            { xpos, ypos, 0.0f, 1.0f },
            { xpos + w, ypos, 1.0f, 1.0f },

            { xpos, ypos + h, 0.0f, 0.0f },
            { xpos + w, ypos, 1.0f, 1.0f },
            { xpos + w, ypos + h, 1.0f, 0.0f }           
        };

        // render glyph texture over quad
        glBindTexture(GL_TEXTURE_2D, ch.textureID);

        // update content of VBO memory
        glBindBuffer(GL_ARRAY_BUFFER, font->VBO);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); 

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        // render quad
        glDrawArrays(GL_TRIANGLES, 0, 6);
        // now advance cursors for next glyph (note that advance is number of 1/64 pixels)
        x += (ch.advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
    }

    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
}

However, when I attempt to draw the text, nothing shows up. I've tripled checked my code with the code on the website. I'm using the same shaders and everything too, and am calling my function as

    mat4 textProjection;
    glm_ortho(0.0f, window.width, window.height, 0.0f, -1.0f, 1.0f, textProjection);
    shader_use(textShader);
    shader_setMat4(textShader, "projection", textProjection);

     struct Font robotoFont = font_load("res/fonts/roboto.ttf", 48);
     
     // inside draw loop
     text_render(&robotoFont, textShader, "TEST", 25.0f, 25.0f, 1.0f, (vec3){0.5, 0.8f, 0.2f});

However, I've had no luck. I cannot use renderdoc as I'm on a Mac and I'm unsure on what I'm doing wrong. Any idea on my mistake would be great.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

The tutorial used a different culling face direction that I did, so the text wasn't being drawn.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ This answer could be even more useful for future readers if you share some tips for how you determined this was the problem, and the line of code you changed to fix it. \$\endgroup\$
    – DMGregory
    Commented Sep 3 at 16:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .