簡體   English   中英

在OpenGL中垂直翻轉FreeType文本

[英]Flip FreeType text vertically in OpenGL

我正在做一個科學項目,我們必須將照相機倒過來,然后翻轉其他所有東西。 但是我似乎找不到垂直翻轉Freetype文本的方法。 這是現在的樣子:

在此處輸入圖片說明

這就是我創建文本的方式:

// Text.cpp
#include "Text.h"

using namespace OpenGL::Rendering::Models;

Text::Text(const std::string& text, OpenGL::Container::Position position,
           int font_size, OpenGL::Container::Color color) {
    m_font_size = font_size;
    m_scale = 1.0;
    m_text = text;

    this->color.r = color.r;
    this->color.g = color.g;
    this->color.b = color.b;
    this->color.a = color.a;

    this->position.x = position.x;
    this->position.y = position.y;
    this->position.z = position.z;

    if (FT_Init_FreeType(&font)) {
        Log()->critical("Could not initalize Freetype library for fonts.");
    }

    if (FT_New_Face(font, "/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf", 0,
                    &face)) {
        Log()->critical("Could not load font. File is missing maybe?");
    }

    FT_Set_Char_Size(face, 0, m_font_size * 64, 300, 300);
    FT_Set_Pixel_Sizes(face, 0, m_font_size);
    if (FT_Load_Char(face, 'X', FT_LOAD_RENDER)) {
        Log()->critical(
            "Could not load a test glyph. The font is corrupted maybe?");
    }

    float angle = 0;
    matrix.xx = (FT_Fixed)(cos(angle) * 0x10000L);
    matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L);
    matrix.yx = (FT_Fixed)(sin(angle) * 0x10000L);
    matrix.yy = (FT_Fixed)(cos(angle) * 0x10000L);
    FT_Set_Transform(face, &matrix, 0);

    for (GLubyte c = 0; c < 128; ++c) {
        if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
            Log()->critical("Could not load glyph \"{}\"", c);
            continue;
        }

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

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

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

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

    FT_Done_Face(face);
    FT_Done_FreeType(font);
}

void Text::create() {
    GLuint vao;
    GLuint vbo;

    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);

    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Container::Vertex) * 6, NULL,
                 GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Container::Vertex),
                          (void*)0);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(
        1, 2, GL_FLOAT, GL_FALSE, sizeof(Container::Vertex),
        (void*)(offsetof(Container::Vertex, Container::Vertex::m_texcoord)));

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    this->vao = vao;
    this->vbos.push_back(vbo);
    this->set_program(OpenGL::Managers::ShaderManager::get_program("text"));
    this->set_position(position.x, position.y, position.z);
    //this->set_rotation(180, 0, 0, 1);
}

void Text::draw() {
    glUseProgram(this->program);
    glUniformMatrix4fv(glGetUniformLocation(this->program, "model_matrix"), 1,
                       false, &model_matrix[0][0]);
    glUniform4f(glGetUniformLocation(this->program, "text_color"), color.r,
                color.g, color.b, color.a);
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(this->vao);

    GLfloat temp_x = 0;
    GLfloat temp_y = 0;

    std::string::const_iterator c;
    for (c = m_text.begin(); c != m_text.end(); c++) {
        Character ch = characters[*c];

        GLfloat xpos = temp_x + ch.bearing.x * m_scale;
        GLfloat ypos = temp_y - (ch.size.y - ch.bearing.y) * m_scale;
        GLfloat zpos = position.z;

        GLfloat w = ch.size.x * m_scale;
        GLfloat h = ch.size.y * m_scale;

        std::vector<Container::Vertex> vertices;
        vertices.push_back(Container::Vertex(glm::vec3(xpos, ypos + h, zpos),
                                             glm::vec2(0.0, 0.0)));
        vertices.push_back(Container::Vertex(glm::vec3(xpos, ypos, zpos),
                                             glm::vec2(0.0, 1.0)));
        vertices.push_back(Container::Vertex(glm::vec3(xpos + w, ypos, zpos),
                                             glm::vec2(1.0, 1.0)));

        vertices.push_back(Container::Vertex(glm::vec3(xpos, ypos + h, zpos),
                                             glm::vec2(0.0, 0.0)));
        vertices.push_back(Container::Vertex(glm::vec3(xpos + w, ypos, zpos),
                                             glm::vec2(1.0, 1.0)));
        vertices.push_back(Container::Vertex(
            glm::vec3(xpos + w, ypos + h, zpos), glm::vec2(1.0, 0.0)));

        glBindTexture(GL_TEXTURE_2D, ch.texture_id);
        glBindBuffer(GL_ARRAY_BUFFER, this->vbos[0]);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Container::Vertex) * vertices.size(), &vertices[0]);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glDrawArrays(GL_TRIANGLES, 0, 6);
        temp_x += (ch.advance >> 6) * m_scale;
    }

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

void Text::set_text(const std::string& a_text) {
    if (!a_text.empty()) {
        m_text = a_text;
    } else {
        Log()->info("Cannot set the text. Input seems to be empty.");
    }
}

std::string Text::get_text() { return m_text; }

void Text::set_color(const Container::Color a_color) {
    color.r = a_color.r;
    color.g = a_color.g;
    color.b = a_color.b;
    color.a = a_color.a;
}

理想的解決方案是在保留方位和填充物的同時翻轉每個字形,但是我不知道該怎么做。 我的坐標全部以像素為單位,並且我使用的是OpenGL 3.3核心配置文件。

通過查看代碼,您可以將每個字符渲染為兩個紋理三角形,因此翻轉文本非常容易。 所需要做的就是更改紋理的UV坐標:

//Flip UV's second value
vertices.push_back(Container::Vertex(glm::vec3(xpos, ypos + h, zpos),
                                         glm::vec2(0.0, 1.0)));
vertices.push_back(Container::Vertex(glm::vec3(xpos, ypos, zpos),
                                         glm::vec2(0.0, 0.0)));
vertices.push_back(Container::Vertex(glm::vec3(xpos + w, ypos, zpos),
                                         glm::vec2(1.0, 0.0)));

vertices.push_back(Container::Vertex(glm::vec3(xpos, ypos + h, zpos),
                                         glm::vec2(0.0, 1.0)));
vertices.push_back(Container::Vertex(glm::vec3(xpos + w, ypos, zpos),
                                         glm::vec2(1.0, 0.0)));
vertices.push_back(Container::Vertex(glm::vec3(xpos + w, ypos + h, zpos), 
                                         glm::vec2(1.0, 1.0)));

除此之外,這不是渲染很多文本的有效方法。 通常,它是通過將所有字符打包到一個緩沖區中並將字形收集到一個紋理集來完成的。 因此,只有一個繪制調用和一個紋理綁定,然后使用UV將特定字形映射到三角形。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM