Qt 中使用freeType2实现简单的文本渲染

来源:互联网 发布:三体结局知乎 编辑:程序博客网 时间:2024/05/16 18:41

      就按转载说吧,其实自己就是把win32平台,改到了Qt平台,然后去掉了一些原作者自己封装的类,基本都是OpenGL的原生函数,没啥技术,就是交流学习吧。

     下面就贴代码吧。

   这是头文件

#pragma once#include <freetype2/ft2build.h>#include FT_FREETYPE_H#include FT_GLYPH_H#include <QOpenGLFunctions_3_3_Core>#include <QOpenGLShaderProgram>#include <glm/glm.hpp>#include <glm/ext.hpp>#include <vector>#include <QOpenGLContext>#include <QSurface>#define FOR(q,n) for(int q=0;q<n;q++)using std::string;class freeTypeFont :protected QOpenGLFunctions_3_3_Core{public:freeTypeFont(QOpenGLContext * context,QSurface * surface);bool loadFont(std::string sFile, int iPXSize);int getTextWidth(string sText, int iPXSize);void print(string sText, int x, int y, int iPXSize = -1);void releaseFont();void setShaderProgram(QOpenGLShaderProgram * a_shShaderProgram);~freeTypeFont(void);private:void createChar(int iIndex);int iAdvX[256], iAdvY[256];int iBearingX[256], iBearingY[256];int iCharWidth[256], iCharHeight[256];int iLoadedPixelSize, iNewLine;bool bLoaded;GLuint texID[256];GLuint uiVAO;GLuint uiVBOPosintions;GLuint uiVBOTexCoods;FT_Library ftLib;FT_Face ftFace;std::vector<glm::vec2> positions;std::vector<glm::vec2> texcoods;QOpenGLShaderProgram * shShaderProgram;QOpenGLContext* ftContext;QSurface * ftSurface;};
这是源文件

#include "freeTypeFont .h"#include <freetype2/freetype.h>#include <QDebug>#define max(a,b) (((a) > (b)) ? (a) : (b))#pragma comment (lib,"freeType.lib")freeTypeFont::freeTypeFont(QOpenGLContext *context, QSurface * surface){ftContext = context;ftSurface = surface;ftContext->makeCurrent(ftSurface);initializeOpenGLFunctions();}inline int next_p2(int n){ int res = 1; while (res < n)res <<= 1; return res; }void freeTypeFont::createChar(int iIndex){qDebug() << " Index " << iIndex;ftContext->makeCurrent(ftSurface);FT_Load_Glyph(ftFace, FT_Get_Char_Index(ftFace, iIndex), FT_LOAD_DEFAULT);FT_Render_Glyph(ftFace->glyph, FT_RENDER_MODE_NORMAL);FT_Bitmap * pBitmap = &ftFace->glyph->bitmap;int iW = pBitmap->width;int iH = pBitmap->rows;int iTW = next_p2(iW);int iTH = next_p2(iH);GLubyte* bData = new GLubyte[iTW*iTH];FOR(ch, iTH)FOR(cw,iTW)bData[ch*iTW + cw] = (ch >= iH || cw >= iW) ? 0 : pBitmap->buffer[(iH - ch - 1)*iW + cw];/* *生成纹理 */glGenTextures(1, &texID[iIndex]);glBindTexture(GL_TEXTURE_2D, texID[iIndex]);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, iTW, iTH, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, bData);iAdvX[iIndex] = ftFace->glyph->advance.x >> 6;iBearingX[iIndex] = ftFace->glyph->metrics.horiBearingX >> 6;iCharWidth[iIndex] = ftFace->glyph->metrics.width >> 6;iAdvY[iIndex] = (ftFace->glyph->metrics.height - ftFace->glyph->metrics.horiBearingY) >> 6;iBearingY[iIndex] = ftFace->glyph->metrics.horiBearingY >> 6;iCharHeight[iIndex] = ftFace->glyph->metrics.height >> 6;iNewLine = 0;iNewLine = max(iNewLine, int(ftFace->glyph->metrics.height >> 6));glm::vec2 vQuad[] ={glm::vec2(0.0f, float(-iAdvY[iIndex] + iTH)),glm::vec2(0.0f, float(-iAdvY[iIndex])),glm::vec2(float(iTW), float(-iAdvY[iIndex] + iTH)),glm::vec2(float(iTW), float(-iAdvY[iIndex]))};glm::vec2 vTexQuad[] = { glm::vec2(0.0f, 1.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(1.0f, 0.0f) };FOR(i, 4){positions.push_back(vQuad[i]);texcoods.push_back(vTexQuad[i]);}delete[] bData;}bool freeTypeFont::loadFont(std::string sFile, int iPXSize){ftContext->makeCurrent(ftSurface);bool  bError = FT_Init_FreeType(&ftLib);bError = FT_New_Face(ftLib, sFile.c_str(), 0, &ftFace);if (bError)return false;FT_Set_Pixel_Sizes(ftFace, iPXSize, iPXSize);iLoadedPixelSize = iPXSize;glGenVertexArrays(1, &uiVAO);glBindVertexArray(uiVAO);FOR(i, 128) createChar(i);bLoaded = true;glGenBuffers(1, &uiVBOPosintions);glBindBuffer(GL_ARRAY_BUFFER, uiVBOPosintions);glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2)*positions.size(), (GLvoid*)&positions[0][0], GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);glGenBuffers(1, &uiVBOTexCoods);glBindBuffer(GL_ARRAY_BUFFER, uiVBOTexCoods);glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2)*texcoods.size(), (GLvoid*)&texcoods[0][0], GL_STATIC_DRAW);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);FT_Done_Face(ftFace);FT_Done_FreeType(ftLib);glBindVertexArray(0);return true;}void freeTypeFont::print(string sText, int x, int y, int iPXSize /* = -1 */){ftContext->makeCurrent(ftSurface);if (!bLoaded) return;glBindVertexArray(uiVAO);glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);int iCurX = x, iCurY = y;if (iPXSize == -1)iPXSize = iLoadedPixelSize;float fScale = float(iPXSize) / float(iLoadedPixelSize);FOR(i, (int)sText.size()){if (sText[i] == '\n'){iCurX = x;iCurY -= iNewLine*iPXSize / iLoadedPixelSize;continue;}int iIndex = int(sText[i]);iCurX += iBearingX[iIndex] * iPXSize / iLoadedPixelSize;if (sText[i] != ' '){glBindTexture(GL_TEXTURE_2D,texID[iIndex]);glm::mat4 mModelView = glm::translate(glm::mat4(1.0f), glm::vec3(float(iCurX), float(iCurY), 0.0f));mModelView = glm::scale(mModelView, glm::vec3(fScale));GLint locMV =glGetUniformLocation(shShaderProgram->programId(), "modelViewMatrix");glUniformMatrix4fv(locMV, 1, GL_FALSE, &mModelView[0][0]);// Draw characterglDrawArrays(GL_TRIANGLE_STRIP, iIndex*4, 4);}iCurX += (iAdvX[iIndex] - iBearingX[iIndex])*iPXSize / iLoadedPixelSize;}glDisable(GL_BLEND);}void freeTypeFont::setShaderProgram(QOpenGLShaderProgram* a_shShaderProgram){shShaderProgram = a_shShaderProgram;}void freeTypeFont::releaseFont(){glDeleteBuffers(1, &uiVBOPosintions);glDeleteBuffers(1, &uiVBOTexCoods);glDeleteVertexArrays(1, &uiVAO);}freeTypeFont::~freeTypeFont(void){}

使用的时候就是

在类中声明个该类的指针font


然后ftFont = new freeTypeFont(m_context,this);//Qt需要上下文环境


    在初始时,传入字体处理的着色器程序,载入字体

      ftFont->setShaderProgram(ftProgram);
ftFont->loadFont("comic.ttf", 64);

glDisable(GL_DEPTH_TEST);glDepthFunc(GL_ALWAYS);/* *字体渲染 */ ftProgram->bind(); GLfloat color[] = { 1.0f, 0.0f, 0.0f, 1.0f };glm::mat4 orthoMatrix = glm::ortho(0.0f, float(width()), 0.0f, float(height())); GLuint locOrtho = glGetUniformLocation(ftProgram->programId(), "projectionMatrix"); GLuint locColor = glGetUniformLocation(ftProgram->programId(), "vColor"); GLuint locftSampler = glGetUniformLocation(ftProgram->programId(), "gSampler"); glUniformMatrix4fv(locOrtho, 1, GL_FALSE, &orthoMatrix[0][0]); glUniform4fv(locColor, 1, color); glUniform1i(locftSampler, 0);ftFont->print("GLuint locOrtho = glGetUniformLocation(ftProgram->programId(), projectionMatrix);", 20, height() - 10 - 16, 16);ftFont->print("GLuint locOrtho = glGetUniformLocation(ftProgram->programId(), projectionMatrix);", 20, height() - 40 - 16, 16);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);


     着色器代码 顶点着色器

#version 330uniform mat4 projectionMatrix;uniform mat4 modelViewMatrix;layout (location = 0) in vec2 inPosition;layout (location = 1) in vec2 inCoord;out vec2 texCoord;void main(){gl_Position = projectionMatrix  * modelViewMatrix*vec4(inPosition,0.0f, 1.0f);texCoord = inCoord;}

片段着色器

#version 330in vec2 texCoord;out vec4 outputColor;uniform sampler2D gSampler;uniform vec4 vColor;void main(){vec4 vTexColor = texture2D(gSampler, texCoord);outputColor = vec4(vTexColor.r, vTexColor.r,vTexColor.r, vTexColor.r) * vColor;}



参考

http://www.mbsoftworks.sk/index.php?page=tutorials&series=1&tutorial=12

0 0
原创粉丝点击