一、函数介绍

void glTexSubImage2D(GLenum target,

​ GLint level,

​ GLint xoffset,

​ GLint yoffset,

​ GLsizei width,

​ GLsizei height,

​ GLenum format,

​ GLenum type,

​ const GLvoid * data);

参数

target

指定活动纹理单元的目标纹理。 必须是GL_TEXTURE_2DGL_TEXTURE_CUBE_MAP_POSITIVE_XGL_TEXTURE_CUBE_MAP_NEGATIVE_XGL_TEXTURE_CUBE_MAP_POSITIVE_YGL_TEXTURE_CUBE_MAP_NEGATIVE_YGL_TEXTURE_CUBE_MAP_POSITIVE_ZGL_TEXTURE_CUBE_MAP_NEGATIVE_Z

level

指定详细级别编号。 0级是基本图像级别。 级别n是第n个mipmap缩小图像。

xoffset

指定纹理数组中x方向的像素偏移量,x方向是指纹理坐标,即左下角为(0,0)。

yoffset

指定纹理数组中y方向的纹素偏移,y方向是指纹理坐标,即左下角为(0,0)。

width

指定纹理子图像的像素宽度。

height

指定纹理子图像的像素高度。

format

指定像素数据的格式。 接受以下符号值:GL_ALPHAGL_RGBGL_RGBAGL_LUMINANCEGL_LUMINANCE_ALPHA

type

指定像素数据的数据类型。 接受以下符号值:GL_UNSIGNED_BYTEGL_UNSIGNED_SHORT_5_6_5GL_UNSIGNED_SHORT_4_4_4_4GL_UNSIGNED_SHORT_5_5_5_1

data

指定指向内存中图像数据的指针

注意!!!

因为纹理坐标的(0,0)点是左下角,所以我们修改纹理数据的时候是从左下角开始绘制的。

顺序先沿着X轴从左至右,再沿着Y轴从下至上,即一行一行像素的绘制。

示例代码如下:

        virtual unsigned    loadTexture(const char* fileName){unsigned    textureId   =   0;//1 获取图片格式FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);//2 加载图片FIBITMAP    *dib = FreeImage_Load(fifmt, fileName,0);//3 转化为rgb 24色dib     =   FreeImage_ConvertTo24Bits(dib);//4 获取数据指针BYTE    *pixels =   (BYTE*)FreeImage_GetBits(dib);int     width   =   FreeImage_GetWidth(dib);int     height  =   FreeImage_GetHeight(dib);//windows是BGR模式for (int i =0;i<width*height*3;){float temp = pixels[i+2];pixels[i + 2] = pixels[i];pixels[i] = temp;i += 3;}/***   产生一个纹理Id,可以认为是纹理句柄,后面的操作将书用这个纹理id*/glGenTextures( 1, &textureId );/***   使用这个纹理id,或者叫绑定(关联)*/glBindTexture( GL_TEXTURE_2D, textureId );/***   指定纹理的放大,缩小滤波,使用线性方式,即当图片放大的时候插值方式 */glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);/***   将图片的rgb数据上传给opengl.*/glTexImage2D( GL_TEXTURE_2D,      //! 指定是二维图片0,                  //! 指定为第一级别,纹理可以做mipmap,即lod,离近的就采用级别大的,远则使用较小的纹理GL_RGB,             //! 纹理的使用的存储格式width,              //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。height,             //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。0,                  //! 是否的边GL_RGB,             //! 数据的格式,bmp中,windows,操作系统中存储的数据是bgr格式GL_UNSIGNED_BYTE,   //! 数据是8bit数据pixels);char    subData[100 * 100 * 3];memset(subData, 255, sizeof(subData));for (int i = 0; i<150;){subData[i] = 0;subData[++i] = 0;subData[++i] = 255;}glTexSubImage2D(GL_TEXTURE_2D, 0, 100, 50, 100, 100, GL_RGB, GL_UNSIGNED_BYTE, subData);/***   释放内存*/FreeImage_Unload(dib);return  textureId;}

图片修改结果如下:

二、在freetype中应用的时候要注意了!!!

代码如下

int _yStart = 0;
int _xStart = 0;char* readFile(const char* fileName, unsigned& length){FILE* pFile = fopen(fileName, "rb");if (pFile){fseek(pFile, 0, SEEK_END);length = ftell(pFile);fseek(pFile, 0, SEEK_SET);char*buffer = new char[length + 1];fread(buffer, 1, length, pFile);buffer[length] = 0;fclose(pFile);return buffer;}else{char buffer[1024];sprintf_s(buffer, "read %s failed", fileName);assert(pFile != 0 && buffer);}return 0;}void buildSystemFont(const char* font,int fontSize){_uiProgram.initialize();unsigned length = 0;_fontBuffer = readFile(font, length);/***   保存字体的大小*/_fontSize = fontSize;/***   已经创建了字体则销毁*   支持多次调用*/if (_face){FT_Done_Face(FT_Face(_face));_xStart = 0;_yStart = 0;memset(_character, 0, sizeof(_character));}/***   销毁字体*/if (_sysFontTexture != -1){glDeleteTextures(1, &_sysFontTexture);}glGenTextures(1, &_sysFontTexture);/***   使用这个纹理id,或者叫绑定(关联)*/glBindTexture(GL_TEXTURE_2D, _sysFontTexture);/***   指定纹理的放大,缩小滤波,使用线性方式,即当图片放大的时候插值方式*/glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, _textureWidth,_textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);FT_Error error = FT_New_Memory_Face((FT_Library)_library,(const FT_Byte*)_fontBuffer,length,0,&(FT_Face)_face);if (error != 0){return;}FT_Face ftFace = (FT_Face)_face;FT_Select_Charmap(ftFace, FT_ENCODING_UNICODE);FT_F26Dot6 ftSize = (FT_F26Dot6)(fontSize * (1 << 6));FT_Set_Char_Size((FT_Face)_face, ftSize, 0, 72, 72);assert(_face != 0);}Character getCharacter(wchar_t ch){if (_character[ch].x0 == 0 &&_character[ch].x0 == 0 &&_character[ch].x1 == 0 &&_character[ch].y1 == 0){glPixelStorei(GL_UNPACK_ALIGNMENT, 1);if (_xStart + max(_fontPixelX, _fontSize) > _textureWidth){/***   写满一行,从新开始*/_xStart = 0;/***   y开始位置要增加*/_yStart += max(_fontPixelY, _fontSize);}FT_Load_Glyph(_face, FT_Get_Char_Index(_face, ch), FT_LOAD_DEFAULT);FT_Glyph glyph;FT_Get_Glyph(FT_Face(_face)->glyph, &glyph);/***   根据字体的大小决定是否使用反锯齿绘制模式*   当字体比较小的是说建议使用ft_render_mode_mono*   当字体比较大的情况下12以上,建议使用ft_render_mode_normal模式*/if (!(ch >= L'0' && ch <= L'9')){FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1);}else{FT_Glyph_To_Bitmap(&glyph, ft_render_mode_mono, 0, 1);}FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;FT_Bitmap& bitmap = bitmap_glyph->bitmap;FT_Bitmap ftBitmap;FT_Bitmap_New(&ftBitmap);if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO){if (FT_Bitmap_Convert((FT_Library)_library, &bitmap, &ftBitmap, 1) == 0){/***   Go through the bitmap and convert all of the nonzero values to 0xFF (white).*/for (unsigned char* p = ftBitmap.buffer, *endP = p + ftBitmap.width * ftBitmap.rows; p != endP; ++p)*p ^= -*p ^ *p;bitmap = ftBitmap;}}/***   如果没有数据,则不写,直接过去*/if (bitmap.width == 0 || bitmap.rows == 0){char    mem[1024 * 32];memset(mem, 0, sizeof(mem));_character[ch].x0 = _xStart;_character[ch].y0 = _yStart;_character[ch].x1 = _xStart + _fontSize / 2;_character[ch].y1 = _yStart + _fontSize - 1;_character[ch].offsetY = _fontSize - 1;_character[ch].offsetX = 0;glBindTexture(GL_TEXTURE_2D, _sysFontTexture);glTexSubImage2D(GL_TEXTURE_2D,0,_xStart,_yStart,_fontSize / 2,_fontSize,GL_ALPHA,GL_UNSIGNED_BYTE,mem);_xStart += _fontSize / 2;}else{glBindTexture(GL_TEXTURE_2D, _sysFontTexture);_character[ch].x0 = _xStart;_character[ch].y0 = _yStart;_character[ch].x1 = _xStart + bitmap.width;_character[ch].y1 = _yStart + bitmap.rows;_character[ch].offsetY = bitmap_glyph->top;_character[ch].offsetX = bitmap_glyph->left;glPixelStorei(GL_UNPACK_ALIGNMENT, 1);glTexSubImage2D(GL_TEXTURE_2D,0,_xStart,_yStart,max(1, bitmap.width),max(1, bitmap.rows),GL_ALPHA,GL_UNSIGNED_BYTE,bitmap.buffer);_xStart += (bitmap.width + 1);_fontPixelY = max(_fontPixelY, bitmap.rows);_fontPixelX = max(_fontPixelX, bitmap.width);}FT_Bitmap_Done((FT_Library)_library, &ftBitmap);}return  _character[ch];}

主要的内容在getCharacter函数,将字库里的数据,通过glTexSubImage2D贴到我们自己的纹理上。

但由于glTexSubImage2D绘制的特性(从下往上),所以我们的字是倒过来的。

我们再使用该纹理写字的时候务必注意倒过来

glTexSubImage2D的使用详解相关推荐

  1. glTexImage2D 函数详解

    glTexImage2D 函数详解 参考 https://blog.csdn.net/jeffasd/article/details/78135588 版权 jeffasd glTexImage2D ...

  2. 从命令行到IDE,版本管理工具Git详解(远程仓库创建+命令行讲解+IDEA集成使用)

    首先,Git已经并不只是GitHub,而是所有基于Git的平台,只要在你的电脑上面下载了Git,你就可以通过Git去管理"基于Git的平台"上的代码,常用的平台有GitHub.Gi ...

  3. JVM年轻代,老年代,永久代详解​​​​​​​

    秉承不重复造轮子的原则,查看印象笔记分享连接↓↓↓↓ 传送门:JVM年轻代,老年代,永久代详解 速读摘要 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.在 ...

  4. docker常用命令详解

    docker常用命令详解 本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备忘记录下来. 根据自己的理解,总的来说分为以下几种: Doc ...

  5. 通俗易懂word2vec详解词嵌入-深度学习

    https://blog.csdn.net/just_so_so_fnc/article/details/103304995 skip-gram 原理没看完 https://blog.csdn.net ...

  6. 深度学习优化函数详解(5)-- Nesterov accelerated gradient (NAG) 优化算法

    深度学习优化函数详解系列目录 深度学习优化函数详解(0)– 线性回归问题 深度学习优化函数详解(1)– Gradient Descent 梯度下降法 深度学习优化函数详解(2)– SGD 随机梯度下降 ...

  7. CUDA之nvidia-smi命令详解---gpu

    nvidia-smi是用来查看GPU使用情况的.我常用这个命令判断哪几块GPU空闲,但是最近的GPU使用状态让我很困惑,于是把nvidia-smi命令显示的GPU使用表中各个内容的具体含义解释一下. ...

  8. Bert代码详解(一)重点详细

    这是bert的pytorch版本(与tensorflow一样的,这个更简单些,这个看懂了,tf也能看懂),地址:https://github.com/huggingface/pytorch-pretr ...

  9. CRF(条件随机场)与Viterbi(维特比)算法原理详解

    摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...

  10. pytorch nn.LSTM()参数详解

    输入数据格式: input(seq_len, batch, input_size) h0(num_layers * num_directions, batch, hidden_size) c0(num ...

最新文章

  1. Android 多语言
  2. 希望增加的BLOG功能(序)
  3. 怎么判断间隙过渡过盈配合_尺寸公差配合与装配方法
  4. netcore redis 存储集合_.net core redis的全套操作
  5. Error:-81024 LR_VUG:The 'QTWeb' type is not supported on win32 platforms
  6. drupal7 node.tpl.php,使用Drupal 7在custom - node.tpl.php中顯示CCK字段(無格式化)
  7. windowbuilder怎么加图片_一键制作音乐图片,这效果太惊艳了!微信这个功能简直是“宝藏”...
  8. 华硕笔记本r414u怎么安装键盘_华硕笔记本键盘灯怎么开
  9. ConcurrentHashMap(JDK1.8)的源码解析
  10. 考研数学 - 初数基础整理09
  11. PS第一集 证件照换底色
  12. win7 升级IE11
  13. 人工智能实验二——prolog语言求解渡河问题(传教士和野人渡河,农夫渡河问题)实现详解
  14. 操作系统概论【引入操作系统中的基本概念和操作】
  15. 基于5G森林防火无线监控解决方案
  16. 数据治理服务解决方案
  17. 支付宝小程序状态栏显示图片
  18. Excel数据透视表经典教程四《多字段布局》
  19. 基于java的城市公交查询管理系统
  20. 可以“看得见”的声音---声学成像仪

热门文章

  1. 计算机课件制作,多媒体课件制作photoshop和powerpoint教案
  2. 国家开放大学2021春1135液压气动技术题目
  3. Linux嵌入式系统的电子相册代码,基于嵌入式Linux和Qt编程实现数码相框的设计
  4. 室内定位之蓝牙定位精度(蓝牙RSSI定位)
  5. 线性代数笔记26——傅立叶级数
  6. 电磁场理论笔记03:自由空间中微分形式电磁场定律和边界条件
  7. 北京大学历届学生名单 计算机,北京大学历史系历届学生名单
  8. python平行四边形代码_python 已知平行四边形三个点,求第四个点的案例
  9. 使用java编写中国象棋(内含源代码)
  10. 几种不同格式的json数据及解析