使用freetype / GLFW不显示字体/文本 [英] Font/text not being displayed using freetype / GLFW

查看:209
本文介绍了使用freetype / GLFW不显示字体/文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须显示文字。为此,我试图按照这个[1]教程来显示文本。



正如教程中提到的,我已经链接了库,似乎在链接库时没有错误。

所以这是我的应用程序的结构。我的项目的切入点是* radar.cpp *。为了渲染文本,我创建了一个FontRenderer.h,其中包含相应的FontRenderer.cpp文件,如下所述。



1. FontRenderer.h

  #include   <   ft2build.h  >  
#include graphics.h
#include < iostream >
#include < map < span class =code-keyword>>
#include < 字符串 >
#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 字符{
GLuint TextureID; // 字形纹理的ID句柄
glm :: ivec2 Size; // 字形大小
glm :: ivec2 Bearing; // 从基线偏移到字形左侧/顶部
GLuint Advance; // 前进到下一个字形的水平偏移量
};

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>字符;

void FontRenderer :: RenderText(Shader F_shader,std :: string text,GLfloat x,GLfloat y,GLfloat scale,GLuint va_font,GLuint vb_font)
{
// 为字体类绑定顶点数组
F_shader.use();
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(va_font);

// 遍历所有字符
std :: string :: const_iterator c;
for (c = text.begin(); c!= text.end(); c ++)
{
Character ch =字符[* 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;
// 为每个字符更新vb_font
GLfloat顶点[ 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 }
};
// 在四边形上渲染字形纹理
glBindTexture(GL_TEXTURE_2D,ch.TextureID );
// 更新vb_font内存的内容
glBindBuffer(GL_ARRAY_BUFFER,vb_font);
glBufferSubData(GL_ARRAY_BUFFER, 0 sizeof (顶点),顶点); // 一定要使用glBufferSubData而不是glBufferData
// 解除绑定当前绑定的缓冲区
glBindBuffer(GL_ARRAY_BUFFER, 0 );
// 渲染四维
glDrawArrays(GL_TRIANGLES, 0 6 );
// 现在为下一个字形提前游标(请注意,advance是1/64像素的数量)
x + =(ch.Advance>> 6 )* scale; // Bitshift by 6获取像素值(2 ^ 6 = 64(除以1/64像素除以64)获得像素数量))
}
glBindVertexArray( 0 );
glBindTexture(GL_TEXTURE_2D, 0 );
}

Shader FontRenderer :: FontInit()
{
// 编译和设置着色器
着色器着色器( 着色器/文本。 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, 投影), 1 ,GL_FALSE,glm :: value_ptr(投影));

if (FT_Init_FreeType(& ft))
{
std :: cout<< ERROR :: FREETYPE:无法初始化FreeType库<<的std :: ENDL;
}

if (FT_New_Face(ft, Fonts / dataUnifon.ttf 0 ,& face))
{
std :: cout<< ERROR :: FREETYPE:无法加载字体<<的std :: ENDL;
}
FT_Set_Pixel_Sizes(face, 0 48 );
printf( FreeType Initialization successfull \ n);

返回着色器;
}

void FontRenderer :: FontSetup()
{
// 禁用字节对齐限制
glPixelStorei(GL_UNPACK_ALIGNMENT, 1 );

// 加载ASCII集的前128个字符
< span class =code-keyword> for (GLubyte c = 0 ; c< 128 ; c ++)
{
// 加载字符字形
if (FT_Load_Char(face,c,FT_LOAD_RENDER))
{
std :: cout<< ERROR :: FREETYTPE:无法加载字形<<的std :: ENDL;
继续;
}

// 生成纹理
GLuint质地;
glGenTextures( 1 ,& texture);
glBindTexture(GL_TEXTURE_2D,纹理);
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);
// 现在存储字符供以后使用
字符字符= {
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 );

// 完成后销毁FreeType
FT_Done_Face (面对);
FT_Done_FreeType(ft);
}

我有一个爸爸函数来管理在其他一些graphics.cpp文件中定义的名为glRenderLoop()的所有OpenGL渲染(从我调用不同的函数来渲染多个屏幕上的对象)



这是glRenderLoop()的样子

 glRenderLoop()
{
FontRenderer FR;

// 初始化FreeType字体
Shader font_shader = FR .FontInit();
FR.FontSetup();

// 为纹理四边形配置va_font / vb_font
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, 这是示例文本,< span class =code-digit> 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中进行了必要的更改.h喜欢在use()函数中使用小写'u',将'ID'更改为'Program'。



尽管如此,还是没有文字在屏幕上呈现。



我做错了什么? :(



[1]:https://learnopengl.com/In-Practice/Text-Rendering

[2]:https ://learnopengl.com/code_viewer_gh.php?code = includes / learnopengl / shader_s.h



我的尝试:



我现在尝试禁用所有其他渲染以进行调试,因此只有freetype是唯一剩余的活动图形渲染文件。

但是到目前为止仍然没有达到任何结果。屏幕显得绝对空白



然而,当我渲染其他元素时(如渲染方块/圆形/三角形),一切正常。

我也想添加文本。

解决方案

我在代码中看到的一点,就是你在FontRenderer中的投影大于你也建议你应该在FontRenderer中通过变量初始化VAO,VBO。我也使用freetype来渲染文本,它很好。我会发给你链接演示如果哟你仍然无法绘制文字。


谢谢@ Seal2002。对此,我真的非常感激。现在工作正常。 :)

I have to display text. For that, I am trying to follow this[1] tutorial to display the text.

As mentioned in the tutorial, I've linked the libraries and there seem to be no error in linking of the library.
So here is the structure of my application. The entry point of my project is *radar.cpp*. And for rendering the text, I have created a FontRenderer.h with a corresponding FontRenderer.cpp file as described below.

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);
}

I have one daddy function to manage all the OpenGL rendering called glRenderLoop() defined in some other graphics.cpp file (from where I was calling different functions to render multiple objects on the screen)

This is how glRenderLoop() looks like

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);

    }
}


The main() function has just function calls to this glRenderLoop() function which is defined in graphics.cpp

Link to [shader_s.h][2].
I've also made the necessary changes in shader_s.h like using lower case 'u' in use() function, changing 'ID' to 'Program'.

Still, after all this, there is no text rendering on the screen.

What am I doing wrong? :(

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

What I have tried:

I've tried disabling all other rendering at the moment for debugging purpose, so just freetype is the only remaining active graphics rendering file.
But still no result is achieved so far. Screen appears absolutely blank

However, when I render other elements (Like rendering squares/circles/ triangles) everything is working.
I want to add text as well.

解决方案

Just one point I see in your code, that is your projection in the FontRenderer is bigger than your viewport. I also suggest you should init VAO, VBO inside the FontRenderer instead via the variable. I also use the freetype for render the text and it is fine. I will send you the link demo if you still can not draw the text.


Thanks @Seal2002. I really appreciate it. It is working fine now. :)


这篇关于使用freetype / GLFW不显示字体/文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆