天天看點

NeHe-OpenGL-Qt5-Lesson13-注釋與學習-BitmapFonts

字型是一個好重要的内容,在三維中一樣。

記得方正靠字型掙了不少的錢,當然我們使用者是不是特别清楚的。

開源的字型解釋庫中freetype是比較出名的,OpenCV中也有用到這個庫來作為字型解釋用。如果我們要打中文等unicode字型,用

freetype解釋再渲染就行了。

在.pro中添加freetype庫:

NeHe-OpenGL-Qt5-Lesson13-注釋與學習-BitmapFonts

轉換代碼:

fontwindow.h

#ifndef FONTWINDOW_H
#define FONTWINDOW_H

#include <QOpenGLShaderProgram>
#include <QApplication>
#include <freetype2/ft2build.h>
#include <freetype/freetype.h>
#include <freetype/config/ftheader.h>
#include <QtMath>
#include "openglwindow.h"

class FontWindow : public OpenGLWindow
{
    Q_OBJECT
public:
    explicit FontWindow(QWindow *parent = 0);
    ~FontWindow();
protected:
    void initialize();
private:
    void initFreeType();

    void render();
private:
    void loadShader();

    void renderText(const char *text, float x, float y, float sx, float sy);
private:
    QOpenGLShaderProgram *m_program;

    FT_Face m_ftFace;
    GLfloat	m_cnt1;
    GLfloat m_cnt2;
};

#endif // FONTWINDOW_H
           

fontwindow.cpp

#include "fontwindow.h"

FontWindow::FontWindow(QWindow *parent) :
    OpenGLWindow(parent), m_program(NULL),
    m_cnt1(0.0f), m_cnt2(0.0f)
{
    initFreeType();
}

FontWindow::~FontWindow()
{
}

void FontWindow::initialize()
{
    loadShader();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepthf(1.0f);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void FontWindow::initFreeType()
{
    FT_Library ft;
    if(FT_Init_FreeType(&ft))
    {
        qDebug() << "could not init free type library.";
        return;
    }
    //QString fontPath = QApplication::applicationDirPath() + "/Test.ttf";
    QString fontPath = "C:/Users/PC1073/Downloads/NeHe_OpenGL_Qt5-master/Lesson13_BitmapFonts/font/Test.ttf";
    if(FT_New_Face(ft, fontPath.toLatin1().data(), 0, &m_ftFace))
    {
        qDebug() << "Could not open font.";
        return;
    }
}

void FontWindow::render()
{
    m_program->bind();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    m_modelView.setToIdentity();
    m_modelView.translate(0.0f, 0.0f, -3.0f);
    QVector4D color(1.0f*float(qCos(m_cnt1)),
                    1.0f*float(qSin(m_cnt2)),
                    1.0f-0.5f*float(qCos(m_cnt1+m_cnt2)),
                    1.0f);
    m_program->setUniformValue("color", color);
    m_program->setUniformValue("mvpMatrix", m_projection * m_modelView);

    const qreal retinaScale = devicePixelRatio();
    resizeGL(width()*retinaScale, height()*retinaScale);

    float sx = 2.0 / width()*retinaScale;
    float sy = 2.0 / height()*retinaScale;
    FT_Set_Pixel_Sizes(m_ftFace, 0, 68);

    float mx = float(cos(m_cnt1));
    float my = float(sin(m_cnt2));
    QString text = "Bill & Mei @" + QString::number(m_cnt1, 'f', 2);
    renderText(text.toLatin1().data(),
                mx - 0.5, my, sx, sy);
    m_program->release();

    m_cnt1+=0.051f;
    m_cnt2+=0.005f;
}

void FontWindow::loadShader()
{
    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader/vertshader.glsl");
    m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shader/fragshader.glsl");
    m_program->link();
}

void FontWindow::renderText(const char *text, float x, float y, float sx, float sy)
{
    const char *p;
    FT_GlyphSlot ftGlyph = m_ftFace->glyph;
    GLuint coordAttr = m_program->attributeLocation("coord");
    m_program->enableAttributeArray(coordAttr);

    GLuint ftTex;
    glGenTextures(1, &ftTex);
    glBindTexture(GL_TEXTURE_2D, ftTex);

    for(p = text; *p; p++)
    {
        if(FT_Load_Char(m_ftFace, *p, FT_LOAD_RENDER))
        {
            qDebug() << "Could not load character " << *p;
            continue;
        }
        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);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ftGlyph->bitmap.width,
                     ftGlyph->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
                     ftGlyph->bitmap.buffer);

        float x2 = x + ftGlyph->bitmap_left * sx;
        float y2 = -y - ftGlyph->bitmap_top * sy;
        float w = ftGlyph->bitmap.width * sx;
        float h = ftGlyph->bitmap.rows * sy;

        GLfloat box[4][4] =
        {
            {x2,     -y2    , 0, 0},
            {x2 + w, -y2    , 1, 0},
            {x2,     -y2 - h, 0, 1},
            {x2 + w, -y2 - h, 1, 1},
        };

        m_program->setAttributeArray(coordAttr, GL_FLOAT, box, 4);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        x += (ftGlyph->advance.x >> 6) * sx;
        y += (ftGlyph->advance.y >> 6) * sy;
    }

    glDeleteTextures(1, &ftTex);
}
           

運作結果:

NeHe-OpenGL-Qt5-Lesson13-注釋與學習-BitmapFonts

這是NeHe-OpenGL-Qt5中的最後一節了,多謝。

多謝,親愛的美美。

繼續閱讀