NeHe 系列教程之十四:2D纹理字体

英文教程地址:lesson17

本课展示2D纹理生成字体。

首先是字体库的建立及相关字符输出函数:

namespace {GLuint  texture[2];                             // Storage For Our Font TextureGLuint  loop;                                   // Generic Loop VariableGLfloat cnt1;                                   // 1st Counter Used To Move Text & For ColoringGLfloat cnt2;                                   // 2nd Counter Used To Move Text & For Coloringstruct FyjBitmapChar{QVector<QVector2D> texCoords;int right; //字符宽度int height;//字符高度int ascillValue;};struct FyjBitmapFont{char *name;int quality;FyjBitmapChar *characters;};static FyjBitmapChar chars1[128];static FyjBitmapChar chars2[128];const FyjBitmapFont font1 = {"standard", 128, chars1};const FyjBitmapFont font2 = {"Itatic", 128, chars2};void buildFont(){float   cx;                      // Holds Our X Character Coordfloat   cy;                     // Holds Our Y Character CoordglBindTexture(GL_TEXTURE_2D, texture[0]);for (loop = 0; loop < 256; loop++) {cx = float(loop%16)/16.0f; //当前字符的x纹理坐标cy = float(loop/16)/16.0f; //当前字符的y纹理坐标if (loop < 128) {chars1[loop].texCoords<<QVector2D(cx, cy + 0.0625f)<<QVector2D(cx+0.0625f, cy+0.0625f)<<QVector2D(cx+0.0625f, cy)<<QVector2D(cx, cy);chars1[loop].height = 16;chars1[loop].right = 10;chars1[loop].ascillValue = loop+32;} else {chars2[loop-128].texCoords<<QVector2D(cx, cy + 0.0625f)<<QVector2D(cx+0.0625f, cy+0.0625f)<<QVector2D(cx+0.0625f, cy)<<QVector2D(cx, cy);chars2[loop-128].height = 12;chars2[loop-128].right = 10;chars2[loop-128].ascillValue = loop-128+32;}}}void renderBitmapCharacter(FyjBitmapChar c, int fontSize){Q_ASSERT_X(c.ascillValue >= 32 && c.ascillValue <= 127,"renderBitmapCharacter", "unspported char");glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState(GL_TEXTURE_COORD_ARRAY);QVector<QVector2D> vertices;vertices<<QVector2D(0, 0)<<QVector2D(fontSize, 0)<<QVector2D(fontSize, fontSize)<<QVector2D(0, fontSize);glVertexPointer(2, GL_FLOAT, 0, vertices.constData());glTexCoordPointer(2, GL_FLOAT, 0, c.texCoords.constData());glDrawArrays(GL_QUADS, 0, 4);glDisableClientState(GL_VERTEX_ARRAY);glDisableClientState(GL_TEXTURE_COORD_ARRAY);}void renderBitmapString(GLint x, GLint y, QString string, int set, int fontSize){int numOfReturnChar = 0;if (string.isNull() || string.isEmpty())return;if (set > 1)set = 1;FyjBitmapFont currentFont;if (set == 0)currentFont = font1;elsecurrentFont = font2;glBindTexture(GL_TEXTURE_2D, texture[0]);glDisable(GL_DEPTH_TEST);glMatrixMode(GL_PROJECTION);glPushMatrix();glLoadIdentity();glOrtho(0,640,0,480,-1,1);glMatrixMode(GL_MODELVIEW);glPushMatrix();glLoadIdentity();glTranslated(x, y, 0);for(int i = 0; i < string.length(); i++) {char c = string.at(i).toAscii();if (c == '\n') {numOfReturnChar++;glLoadIdentity();glTranslated(x, y - numOfReturnChar * currentFont.characters[0].height, 0);continue;}renderBitmapCharacter(currentFont.characters[c-32], fontSize);glTranslated(currentFont.characters[c-32].right * fontSize/16, 0, 0);}glMatrixMode(GL_PROJECTION);glPopMatrix();glMatrixMode(GL_MODELVIEW);glPopMatrix();glEnable(GL_DEPTH_TEST);}void glPrint(GLint x, GLint y, int set, int fontSize, const char *fmt, ...){char   text[256];              // Holds Our Stringva_list     ap;                 // Pointer To List Of Argumentsif (fmt == NULL)                    // If There's No Textreturn;                     // Do Nothingva_start(ap, fmt);                  // Parses The String For Variablesvsprintf(text, fmt, ap);                // And Converts Symbols To Actual Numbersva_end(ap);                     // Results Are Stored In TextrenderBitmapString(x, y, QString(text), set, fontSize);}void drawTextureMappedQuad(){QVector<QVector2D> vertices;QVector<QVector2D> texCoords;glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState(GL_TEXTURE_COORD_ARRAY);vertices<<QVector2D(-1.0f, 1.0f)<<QVector2D(1.0f, 1.0f)<<QVector2D(1.0f,-1.0f)<<QVector2D(-1.0f,-1.0f);texCoords<<QVector2D(0.0f,0.0f)<<QVector2D(1.0f,0.0f)<<QVector2D(1.0f,1.0f)<<QVector2D(0.0f,1.0f);glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData());glVertexPointer(2, GL_FLOAT, 0, vertices.constData());glDrawArrays(GL_QUADS, 0, 4);glDisableClientState(GL_VERTEX_ARRAY);glDisableClientState(GL_TEXTURE_COORD_ARRAY);}}

接着是字体纹理加载:

void MyGLWidget::loadTextures()
{texture[0] = bindTexture(QString(":/Font.bmp"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption);// Create Nearest Filtered TextureglBindTexture(GL_TEXTURE_2D, texture[0]);texture[1] = bindTexture(QString(":/Bumps.bmp"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption);// Create Linear Filtered TextureglBindTexture(GL_TEXTURE_2D, texture[1]);
}

初始化:

void MyGLWidget::initializeGL()
{loadTextures();glEnable(GL_TEXTURE_2D);buildFont();glBlendFunc(GL_SRC_ALPHA,GL_ONE);glShadeModel(GL_SMOOTH);   // Enables Smooth ShadingglClearColor(0.0f, 0.0f, 0.0f, 0.0f);  // Black BackgroundglClearDepth(1.0f);             // Depth Buffer SetupglEnable(GL_DEPTH_TEST);        // Enables Depth TestingglDepthFunc(GL_LEQUAL);        // The Type Of Depth Test To DoglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
}

绘制:

void MyGLWidget::paintGL()
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear The Screen And The Depth BufferglLoadIdentity();       // Reset The Current Modelview MatrixglBindTexture(GL_TEXTURE_2D, texture[1]);glTranslatef(0.0f,0.0f,-5.0f);glRotatef(45.0f,0.0f,0.0f,1.0f);glRotatef(cnt1*30.0f,1.0f,1.0f,0.0f);glDisable(GL_BLEND);glColor3f(1.0f,1.0f,1.0f);drawTextureMappedQuad();glRotatef(90.0f,1.0f,1.0f,0.0f);drawTextureMappedQuad();glEnable(GL_BLEND);glLoadIdentity();glColor3f(1.0f*float(cos(cnt1)),1.0f*float(sin(cnt2)),1.0f-0.5f*float(cos(cnt1+cnt2)));glPrint(int((280+250*cos(cnt1))),int(235+200*sin(cnt2)),0, 16, "NeHe");glColor3f(1.0f*float(sin(cnt2)),1.0f-0.5f*float(cos(cnt1+cnt2)),1.0f*float(cos(cnt1)));glPrint(int((280+230*cos(cnt2))),int(235+200*sin(cnt1)), 1, 24, "OpenGL");glColor3f(0.0f,0.0f,1.0f);glPrint(int(240+200*cos((cnt2+cnt1)/5)),2, 0, 16, "Giuseppe D'Agata");glColor3f(1.0f,1.0f,1.0f);glPrint(int(242+200*cos((cnt2+cnt1)/5)),2, 0, 16, "Giuseppe D'Agata");cnt1+=0.01f;cnt2+=0.0081f;
}

运行效果图:

转载于:https://my.oschina.net/fuyajun1983cn/blog/263936

NeHe教程Qt实现——lesson17相关推荐

  1. NeHe教程Qt实现——lesson01

    NeHe 系列教程之一: 创建一个OpenGL 窗口 英文教程地址: lesson01 在Qt的实现中, 我们主要依赖QGLWidget类, 我们主要重载三个重要方法 :     void initi ...

  2. NeHe教程Qt实现——lesson10

    NeHe 系列教程之十:在3D空间中漫游 英文教程地址:lesson10 本课演示了从外部文件中加载数据构建3D模型的实例,代码基于第一课. 首先是3D模型的数据结构定义: namespace {bo ...

  3. NeHe教程Qt实现——lesson07

    NeHe 系列教程之七: 光照及纹理过滤 英文教程地址:lesson07 本课将以第一课的代码为基础, 实现光照效果. 首先是对象定义与纹理加载的代码: namespace { bool light; ...

  4. NeHe教程Qt实现——lesson08

    NeHe 系列教程之八: 混合 英文教程地址:lesson08 本课将在第七课的基础上添加颜色混合的代码: namespace { ... bool blend; // Blending OFF/ON ...

  5. NeHe教程Qt实现——lesson09

    NeHe 系列教程之九: 在3D空间中移动位图 英文教程地址:lesson09 本课基于第一课的代码, 利用颜色混合的方法,将一个黑白纹理与随机颜色进行混合,产生绚丽的效果. 首先是定义相关变量和数据 ...

  6. NeHe教程Qt实现——lesson16

    NeHe 系列教程之十四:雾 英文教程地址:lesson16 本课展示产生雾. 相关变量和函数定义: namespace { bool gp; GLuint fogMode[] = { GL_EXP, ...

  7. NeHe教程Qt实现——lesson06

    NeHe 系列教程之六: 纹理映射 英文教程地址:lesson06 本课以第一课的代码为基础,演示了加载纹理的过程. 首先给出的是绘制几何对象和加载纹理坐标的代码 namespace {GLfloat ...

  8. NeHe教程Qt实现——lesson15

    NeHe 系列教程之十四:纹理 轮廓字体 英文教程地址:lesson15 本课展示如何创建和显示纹理轮廓字体, 代码基于第一课. 首先是字体库的创建: namespace {#define USE_D ...

  9. NeHe教程Qt实现——lesson13

    NeHe 系列教程之十三: 位图字体 英文教程地址:lesson13 本课将展示位图字体的创建和显示, 代码基于第一课. 首先是字休库的创建,如下所示: namespace {#define USE_ ...

最新文章

  1. 德鲁克管理31条金句
  2. 152斤了,离健康又近了一步
  3. 分拆之后又有大动作,惠普的下一步怎么走?
  4. VS.net中快捷键收缩和展开代码段
  5. 分解质因数(优中再优化)
  6. HRBP执行工具——PDCA
  7. c语言 判断一个图是否全连通_【连载】(判断执行语句)乐创DIY C语言讲义——3.8节(2)...
  8. Laravel配置DingoAPI和JWT
  9. C++(21)——反向输出一个三位数
  10. 地级市交通基础设施数据,省份交通基础设施数据,处理好的面板数据(excel或stata版本)
  11. html5 打气球小游戏,javascript开发打气球小游戏
  12. 软件测试肖sir__python之模块
  13. Docker环境下的前后端分离部署与运维 脚本
  14. 嵌入式薪资真实情况,这届毕业生都拿多少钱?!
  15. 《机器学习实战》-04 朴素贝叶斯
  16. access h3c交换机光口_H3C交换机常用配置命令转载
  17. Mac如何开启关闭隐藏文件
  18. Android 运行报错:Cause: java.lang.IllegalArgumentException
  19. AD转换中通道的概念
  20. Ubuntu20.04下NVIDIA驱动+anaconda3+cuda+cudnn+pytorch安装

热门文章

  1. sql中的text字段如何导入oracle
  2. 百个JavaScript函数以及基础写法汇总
  3. oracle表分区详解
  4. 笔记react router 4(三)
  5. 文档型数据库列一般都是弱项
  6. 生产者,消费者,CDN
  7. 1055. 集体照 (25)
  8. VUE -- 自定义控件(标签)
  9. 记今日访问网页总是报nginx 403的解决
  10. 从一个实际的例子来了解线程套间模型(.NET and COM interop)