Шрифт/текст не отображается с помощью 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 или растровых изображений?