simarmannsingh Ответов: 2

Шрифт/текст не отображается с помощью freetype / GLFW


Мне нужно вывести текст на экран. Для этого я пытаюсь следовать этому учебнику[1], чтобы отобразить текст.

Как уже упоминалось в учебнике, я связал библиотеки, и, похоже, нет никакой ошибки в связывании библиотеки.
Итак, вот структура моего приложения. Точка входа в мой проект-это *radar.cpp*. А для рендеринга текста я создал FontRenderer.h с соответствующим FontRenderer.cpp файл, как описано ниже.

1. FontRenderer.h
#include <ft2build.h>
#include "graphics.h"
#include <iostream>
#include <map>
#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "shader_s.h"

#include FT_FREETYPE_H

struct Character {
    GLuint TextureID;       // ID handle of the glyph texture
    glm::ivec2 Size;        // Size of glyph
    glm::ivec2 Bearing;     // Offset from baseline to left/top of glyph
    GLuint Advance;         // Horizontal offset to advance to next glyph
};

class FontRenderer
{
private:
    FT_Library ft;
    FT_Face face;
public:
    void RenderText(Shader fshader, std::string text, GLfloat x, GLfloat y, GLfloat scale, GLuint va_font, GLuint vb_font);
    Shader FontInit();
    void FontSetup();
};
2. FontRenderer.cpp
#include"FontRenderer.h"
#include<glad/glad.h>
#include <GLFW/glfw3.h>

std::map<GLchar, Character> Characters;

void FontRenderer::RenderText( Shader F_shader, std::string text, GLfloat x, GLfloat y, GLfloat scale, GLuint va_font, GLuint vb_font)
{
    // Binding vertex array for font class
    F_shader.use();
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(va_font);

    // Iterate through all characters
    std::string::const_iterator c;
    for (c = text.begin(); c != text.end(); c++)
        {
        Character ch = Characters[*c];

        GLfloat xpos = x + ch.Bearing.x * scale;
        GLfloat ypos = y - (ch.Size.y - ch.Bearing.y) * scale;

        GLfloat w = ch.Size.x * scale;
        GLfloat h = ch.Size.y * scale;
        // Update vb_font for each character
        GLfloat vertices[6][4] = {
            { xpos,     ypos + h,   0.0, 0.0 },
            { xpos,     ypos,       0.0, 1.0 },
            { xpos + w, ypos,       1.0, 1.0 },

            { xpos,     ypos + h,   0.0, 0.0 },
            { xpos + w, ypos,       1.0, 1.0 },
            { xpos + w, ypos + h,   1.0, 0.0 }
        };
        // Render glyph texture over quad
        glBindTexture(GL_TEXTURE_2D, ch.TextureID);
        // Update content of vb_font memory
        glBindBuffer(GL_ARRAY_BUFFER, vb_font);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
        //Unbinding the currently bound buffer
        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 (divide amount of 1/64th pixels by 64 to get amount of pixels))
    }
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
}

Shader FontRenderer::FontInit()
{
    // Compile and setup the shader
    Shader shader("shaders/text.vs", "shaders/text.frag");
    glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(800), 0.0f, static_cast<GLfloat>(600));
    shader.use();
    glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

    if (FT_Init_FreeType(&ft))
    {
        std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
    }

    if (FT_New_Face(ft, "Fonts/dataUnifon.ttf", 0, &face))
    {
        std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
    }
    FT_Set_Pixel_Sizes(face, 0, 48);
    printf("FreeType Initialization successfull\n");

    return shader;
}

void FontRenderer::FontSetup()
{
    // Disable byte-alignment restriction
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // Load first 128 characters of ASCII set
    for (GLubyte c = 0; c < 128; c++)
    {
        // Load character glyph
        if (FT_Load_Char(face, c, FT_LOAD_RENDER))
        {
            std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
            continue;
        }

        // Generate texture
        GLuint texture;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        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
        );

        // Set texture options
        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);
        // Now store character for later use
        Character character = {
            texture,
            glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
            glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
            face->glyph->advance.x
        };
        Characters.insert(std::pair<GLchar, Character>(c, character));
    }
    glBindTexture(GL_TEXTURE_2D, 0);

    // Destroy FreeType once we're finished
    FT_Done_Face(face);
    FT_Done_FreeType(ft);
}
У меня есть одна папина функция для управления всем рендерингом OpenGL под названием glRenderLoop (), определенная в некоторых других graphics.cpp файл (откуда я вызывал различные функции для визуализации нескольких объектов на экране)

Вот как выглядит glRenderLoop()
glRenderLoop()
{
        FontRenderer FR;

    // Initialize the FreeType fonts
    Shader font_shader = FR.FontInit();
    FR.FontSetup();

    // Configure va_font/vb_font for texture quads
    GLuint va_font, vb_font;
    glGenVertexArrays(1, &va_font);
    glGenBuffers(1, &vb_font);
    glBindVertexArray(va_font);
    glBindBuffer(GL_ARRAY_BUFFER, vb_font);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    while (!glfwWindowShouldClose(window))
    {
        glViewport(0, 0, 200, 60);
        glUniform4f(location, 0.9f, 0.9f, 0.0f, 1.0f);

        FR.RenderText(font_shader, "This is sample text", 25.0f, 25.0f, 1.0f, va_font, vb_font);
        FR.RenderText(font_shader, "(C) LearnOpenGL.com", 540.0f, 570.0f, 0.5f, va_font, vb_font);
    glFlush();
    glSwapBuffer(windows);

    }
}

Функция main() имеет только вызовы функций для этой функции glRenderLoop (), которая определена в graphics.cpp

Ссылка на [shader_s.h][2].
Я также внес необходимые изменения в shader_s.ч как, используя нижний регистр 'U' при использовании() функция, изменение 'ИД' в 'программы'.

Тем не менее, после всего этого, на экране нет текстового рендеринга.

Что я делаю не так? :(

[1]: https://learnopengl.com/In-Practice/Text-Rendering
[2]: https://learnopengl.com/code_viewer_gh.php?code=includes/learnopengl/shader_s.h

Что я уже пробовал:

Я попытался отключить все остальные рендеринги в данный момент для целей отладки, так что просто freetype-это единственный оставшийся активным файл рендеринга графики.
Но до сих пор никакого результата не достигнуто. Экран выглядит абсолютно пустым

Однако, когда я визуализирую другие элементы (например, рендеринг квадратов/кругов/ треугольников), все работает.
Я тоже хочу добавить текст.

Rick York

У меня нет для тебя хорошего ответа. То, что я обычно делаю, когда мой код рендеринга не работает, - это добавляю некоторые операторы трассировки, чтобы увидеть, какие данные он пытается нарисовать. Либо это, либо использовать отладчик, чтобы посмотреть на вещи, но у меня обычно так много рисуется, что отладчик довольно громоздок для этого, поэтому я выводю данные с помощью операторов трассировки или чего-то подобного.

simarmannsingh

Спасибо Рику за Ваш быстрый ответ. Я новичок в OpenGL. Поэтому я также попытался добавить операторы печати в конце каждой вызываемой мной функции, просто чтобы отслеживать, где что-то не работает или возникает какое-то исключение. Проблема в том, что все выглядит нормально, все операторы печати выполняются. Я пробовал использовать отладчик для проверки значений каждой переменной. После всего этого код все еще не производит никакого текста, который я пытаюсь напечатать. Есть ли какой-либо другой способ отображения текста, кроме использования Freetype или растровых изображений?

2 Ответов

Рейтинг:
13

Seal2002

Только один момент я вижу в вашем коде, то есть ваша проекция в FontRenderer больше, чем ваш видовой экран. Я также предлагаю вам инициализировать VAO, VBO внутри FontRenderer вместо этого через переменную. Я также использую freetype для рендеринга текста, и это нормально. Я вышлю вам ссылку демо, если вы все еще не можете нарисовать текст.


Dickens A S

Привет @Seal2002, можно мне ссылку на фиксированный код

Seal2002

Привет, вот ты где
https://github.com/seal2002/AdvancedOpenGL

Рейтинг:
1

simarmannsingh

Спасибо @Seal2002. Я действительно ценю это. Сейчас он работает нормально. :)


CHill60

Seal2002 не будет знать, что вы ответили .... Если вы хотите прокомментировать сообщение, используйте кнопку "есть вопрос или комментарий?" ссылка рядом с ним

Seal2002

Да, я не заметил ответа, пока не вернулся к этому посту.